From: Cho KyongHo Date: Wed, 21 Feb 2018 12:42:47 +0000 (+0900) Subject: android: ion: add fixups to ion exynos extension X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=0659178393f0b8979608e6c65d2ee2be41ee6c0a;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git android: ion: add fixups to ion exynos extension The purpose of the exynos extension is to attach addtional improvements to ION. The first improvment is the elimination of dma-mapping overhead. dma_map_sg() and dma_unmap_sg() maps the given memory to the address space of the given device. The mapping can be translation table update if the device has iommu. It may allocate swiotlb buffer if the device does not have iommu and the address space of the device is smaller than the physical address space. dma_map_sg() and dma_unmap_sg() also maintain CPU caches to ensure memory coherency. The purpose of calls to dma_map_sg() and dma_unmap_sg() in ion_map_dma_buf() and ion_unmap_dma_buf(), respectively is just ensuring cache coherency in Exynos SoCs. We have another approach to map the physical memory to the device address space, ion_iovmm_map(). But replacing dma_map_sg() with dma_sync_sg_for_device() does not work because dma_sync_sg_for_device() needs dma_address fields to be initialized by dma_map_sg(). This is the first step to replacing dma_map_sg() with dma_sync_sg_for_device() in ion_map_dma_buf(). Buffer allocation now involves dma_map_sg() to assign dma_address fields of ion_buffer.sg_table. dma_unmap_sg() is called by ion_buffer_destroy(). Then we can finally use dma_sync_sg_for_device() in ion_map_dma_buf(). Change-Id: I8b439eddc0b3722a297ea395aa7e6f3ebc00b294 Signed-off-by: Cho KyongHo --- diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 89cf91901641..2ff694890d37 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -39,6 +39,7 @@ #include #include "ion.h" +#include "ion_exynos.h" static struct ion_device *internal_dev; static int heap_id; @@ -111,6 +112,10 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, buffer->dev = dev; buffer->size = len; + ret = exynos_ion_alloc_fixup(dev, buffer); + if (ret < 0) + goto err1; + INIT_LIST_HEAD(&buffer->iovas); mutex_init(&buffer->lock); mutex_lock(&dev->buffer_lock); @@ -127,6 +132,7 @@ err2: void ion_buffer_destroy(struct ion_buffer *buffer) { + exynos_ion_free_fixup(buffer); if (WARN_ON(buffer->kmap_cnt > 0)) buffer->heap->ops->unmap_kernel(buffer->heap, buffer); buffer->heap->ops->free(buffer); @@ -659,6 +665,7 @@ static int ion_device_create(void) } debugfs_done: + exynos_ion_fixup(idev); idev->buffers = RB_ROOT; mutex_init(&idev->buffer_lock); init_rwsem(&idev->lock); diff --git a/drivers/staging/android/ion/ion_exynos.c b/drivers/staging/android/ion/ion_exynos.c index 11f18675fade..0542e04b6fdb 100644 --- a/drivers/staging/android/ion/ion_exynos.c +++ b/drivers/staging/android/ion/ion_exynos.c @@ -160,3 +160,50 @@ void ion_iovmm_unmap(struct dma_buf_attachment *attachment, dma_addr_t iova) WARN(1, "iova %pad found for %s\n", &iova, dev_name(attachment->dev)); } + +/* + * exynos_ion_fixup - do something to ion_device for the Exynos extensions + */ +void exynos_ion_fixup(struct ion_device *idev) +{ + struct device *dev = idev->dev.this_device; + + /* + * dma-mapping API only works on dma supported device. dma_map_sg() and + * the similarities allocates swiotlb buffers if the dma mask of the + * given device is not capable of full access to physical address space. + * This forces dma-mapping of ARM64 works as if the given device is full + * memory access devices. + * See ion_buffer_create() and ion_buffer_destroy(). + */ + arch_setup_dma_ops(dev, 0x0ULL, 1ULL << 36, NULL, false); + dev->dma_mask = &dev->coherent_dma_mask; + dma_set_mask(dev, DMA_BIT_MASK(36)); +} + +int exynos_ion_alloc_fixup(struct ion_device *idev, struct ion_buffer *buffer) +{ + struct sg_table *table = buffer->sg_table; + int nents; + + /* assign dma_addresses to scatter-gather list */ + nents = dma_map_sg_attrs(idev->dev.this_device, table->sgl, + table->orig_nents, DMA_TO_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + if (nents < table->orig_nents) { + pr_err("%s: failed dma_map_sg(nents %d)=nents %d\n", + __func__, table->orig_nents, nents); + return -ENOMEM; + } + + return 0; +} + +void exynos_ion_free_fixup(struct ion_buffer *buffer) +{ + struct sg_table *table = buffer->sg_table; + + dma_unmap_sg_attrs(buffer->dev->dev.this_device, table->sgl, + table->orig_nents, DMA_TO_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); +} diff --git a/drivers/staging/android/ion/ion_exynos.h b/drivers/staging/android/ion/ion_exynos.h index ba4d0bb18b6f..f1abf8924109 100644 --- a/drivers/staging/android/ion/ion_exynos.h +++ b/drivers/staging/android/ion/ion_exynos.h @@ -21,6 +21,8 @@ struct cma; struct dma_buf; struct ion_heap; struct ion_platform_heap; +struct ion_device; +struct ion_buffer; /** * struct ion_buffer_prot_info - buffer protection information @@ -68,6 +70,10 @@ static inline int ion_secure_iova_pool_create(void) void *ion_buffer_protect_single(unsigned int protection_id, unsigned int size, unsigned long phys, unsigned int protalign); void ion_buffer_unprotect(void *priv); +void exynos_ion_fixup(struct ion_device *idev); +int exynos_ion_alloc_fixup(struct ion_device *idev, struct ion_buffer *buffer); +void exynos_ion_free_fixup(struct ion_buffer *buffer); + #else static inline void *ion_buffer_protect_single(unsigned int protection_id, unsigned int size, @@ -77,6 +83,14 @@ static inline void *ion_buffer_protect_single(unsigned int protection_id, return NULL; } #define ion_buffer_unprotect(priv) do { } while (0) +#define exynos_ion_fixup(idev) do { } while (0) +static inline int exynos_ion_alloc_fixup(struct ion_device *idev, + struct ion_buffer *buffer) +{ + return 0; +} + +#define exynos_ion_free_fixup(buffer) do { } while (0) #endif extern const struct dma_buf_ops ion_dma_buf_ops; @@ -84,4 +98,5 @@ extern const struct dma_buf_ops ion_dma_buf_ops; struct ion_heap *ion_get_heap_by_name(const char *heap_name); struct dma_buf *__ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags); + #endif /* _ION_EXYNOS_H_ */