From dc333aeae5c93482c33c8acff0a98724731f3db5 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 24 Oct 2019 09:55:14 -0600 Subject: [PATCH 1/4] msm: kgsl: Use DMA APIs for memory pool cache maintenance After allocating and zeroing pages from system memory or the pool we need to ensure that the cache is synchronized so that it doesn't cause problems down the road. Use dma_sync_sg_for_device to make sure the allocated pages are clean. This isn't the best way to handle this but we haven't yet come up with a better way and this does the job. Change-Id: Ic0dedbade48b700015bec172cf9b64e436364b4a Signed-off-by: Jordan Crouse --- drivers/gpu/msm/kgsl_pool.c | 41 +++++++++++++++++++++----------- drivers/gpu/msm/kgsl_pool.h | 7 +++++- drivers/gpu/msm/kgsl_sharedmem.c | 4 ++-- 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/msm/kgsl_pool.c b/drivers/gpu/msm/kgsl_pool.c index 7fca6d8b8b4a..199f3cd03efc 100644 --- a/drivers/gpu/msm/kgsl_pool.c +++ b/drivers/gpu/msm/kgsl_pool.c @@ -57,20 +57,36 @@ _kgsl_get_pool_from_order(int order) return index >= 0 ? &kgsl_pools[index] : NULL; } +static void kgsl_pool_sync_for_device(struct device *dev, struct page *page, + size_t size) +{ + struct scatterlist sg; + + /* The caller may choose not to specify a device on purpose */ + if (!dev) + return; + + sg_init_table(&sg, 1); + sg_set_page(&sg, page, size, 0); + sg_dma_address(&sg) = page_to_phys(page); + + dma_sync_sg_for_device(dev, &sg, 1, DMA_BIDIRECTIONAL); +} + /* Map the page into kernel and zero it out */ static void -_kgsl_pool_zero_page(struct page *p, unsigned int pool_order) +_kgsl_pool_zero_page(struct page *p, unsigned int pool_order, + struct device *dev) { int i; for (i = 0; i < (1 << pool_order); i++) { struct page *page = nth_page(p, i); - void *addr = kmap_atomic(page); - memset(addr, 0, PAGE_SIZE); - dmac_flush_range(addr, addr + PAGE_SIZE); - kunmap_atomic(addr); + clear_highpage(page); } + + kgsl_pool_sync_for_device(dev, p, PAGE_SIZE << pool_order); } /* Add a page to specified pool */ @@ -80,8 +96,6 @@ _kgsl_pool_add_page(struct kgsl_page_pool *pool, struct page *p) if (!p) return; - _kgsl_pool_zero_page(p, pool->pool_order); - spin_lock(&pool->list_lock); list_add_tail(&p->lru, &pool->page_list); pool->page_count++; @@ -327,7 +341,8 @@ static int kgsl_get_page_size(size_t size, unsigned int align) * Return total page count on success and negative value on failure */ static int kgsl_pool_alloc_page(int *page_size, struct page **pages, - unsigned int pages_len, unsigned int *align) + unsigned int pages_len, unsigned int *align, + struct device *dev) { int j; int pcount = 0; @@ -355,7 +370,6 @@ static int kgsl_pool_alloc_page(int *page_size, struct page **pages, } else return -ENOMEM; } - _kgsl_pool_zero_page(page, order); goto done; } @@ -375,7 +389,6 @@ static int kgsl_pool_alloc_page(int *page_size, struct page **pages, page = alloc_pages(gfp_mask, order); if (page == NULL) return -ENOMEM; - _kgsl_pool_zero_page(page, order); goto done; } } @@ -405,11 +418,11 @@ static int kgsl_pool_alloc_page(int *page_size, struct page **pages, } else return -ENOMEM; } - - _kgsl_pool_zero_page(page, order); } done: + _kgsl_pool_zero_page(page, order, dev); + for (j = 0; j < (*page_size >> PAGE_SHIFT); j++) { p = nth_page(page, j); pages[pcount] = p; @@ -426,7 +439,7 @@ eagain: return -EAGAIN; } -int kgsl_pool_alloc_pages(u64 size, struct page ***pages) +int kgsl_pool_alloc_pages(u64 size, struct page ***pages, struct device *dev) { int count = 0; int npages = size >> PAGE_SHIFT; @@ -444,7 +457,7 @@ int kgsl_pool_alloc_pages(u64 size, struct page ***pages) while (len) { int ret = kgsl_pool_alloc_page(&page_size, &local[count], - npages, &align); + npages, &align, dev); if (ret == -EAGAIN) continue; diff --git a/drivers/gpu/msm/kgsl_pool.h b/drivers/gpu/msm/kgsl_pool.h index dbddced7f277..946af0a4eff9 100644 --- a/drivers/gpu/msm/kgsl_pool.h +++ b/drivers/gpu/msm/kgsl_pool.h @@ -11,12 +11,17 @@ void kgsl_pool_free_sgt(struct sg_table *sgt); * kgsl_pool_alloc_pages - Allocate an array of pages from the pool * @size: Size of the allocation * @pages: Pointer to an array of pages + * @dev: A &struct device pointer * * Allocate a list of pages and store it in the pointer pointed to by @pages. + * @dev specifies a &struct device that is used to call dma_sync_sg_for_device + * to synchronize the caches. If @dev isn't specified, no cache maintenance + * will be performed. + * * Return: The number of entries in the array pointed to by @page or negative * on error. */ -int kgsl_pool_alloc_pages(u64 size, struct page ***pages); +int kgsl_pool_alloc_pages(u64 size, struct page ***pages, struct device *dev); /** * kgsl_pool_free_pages - Free pages in an pages array diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index 37d4399d4f3e..0c997ad96d00 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -1074,7 +1074,7 @@ static int kgsl_alloc_secure_pages(struct kgsl_device *device, memdesc->priv |= priv; memdesc->ops = &kgsl_secure_pool_ops; - count = kgsl_pool_alloc_pages(size, &pages); + count = kgsl_pool_alloc_pages(size, &pages, device->dev); if (count < 0) return count; @@ -1129,7 +1129,7 @@ static int kgsl_alloc_pages(struct kgsl_device *device, memdesc->priv |= priv; memdesc->ops = &kgsl_pool_ops; - count = kgsl_pool_alloc_pages(size, &pages); + count = kgsl_pool_alloc_pages(size, &pages, device->dev); if (count < 0) return count; From 0735007430dcd9aa21a2bf2098391be6db22a2a1 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 24 Oct 2019 10:23:50 -0600 Subject: [PATCH 2/4] msm: kgsl: Move memory pool initialization to the KGSL core In the code the memory pools are generic. They are stored in global memory and none of the APIs take a device handle, yet the device tree description has traditionally been device specific and as such the pools were set up at device initialization time. This is not needed as we can safely look up the memory pools node from the compatible string at any point. Make the memory pools completely generic and initialize them with the rest of the KGSL core. This clears the way to move the memory definitions out of the device and into the top level soc in the device tree, but since we are using the compatible string that isn't strictly necessary. Change-Id: Ic0dedbad687b9581f0e40142644ed19ee069d54d Signed-off-by: Jordan Crouse --- drivers/gpu/msm/kgsl.c | 10 +++++----- drivers/gpu/msm/kgsl_pool.c | 10 ++-------- drivers/gpu/msm/kgsl_pool.h | 10 +++++++++- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index b20597d7555d..2fb0d233e3ad 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -4972,9 +4972,6 @@ int kgsl_device_platform_probe(struct kgsl_device *device) if (status) goto error_close_mmu; - /* Initialize the memory pools */ - kgsl_init_page_pools(device->pdev); - device->events_wq = alloc_workqueue("kgsl-events", WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0); @@ -5000,8 +4997,6 @@ void kgsl_device_platform_remove(struct kgsl_device *device) kgsl_device_snapshot_close(device); - kgsl_exit_page_pools(); - kobject_put(device->gpu_sysfs_kobj); idr_destroy(&device->context_idr); @@ -5022,6 +5017,8 @@ void kgsl_device_platform_remove(struct kgsl_device *device) void kgsl_core_exit(void) { + kgsl_exit_page_pools(); + kgsl_events_exit(); kgsl_core_debugfs_close(); @@ -5111,6 +5108,9 @@ int __init kgsl_core_init(void) kgsl_sharedmem_init_sysfs(); + /* Initialize the memory pools */ + kgsl_probe_page_pools(); + INIT_LIST_HEAD(&kgsl_driver.process_list); INIT_LIST_HEAD(&kgsl_driver.pagetable_list); diff --git a/drivers/gpu/msm/kgsl_pool.c b/drivers/gpu/msm/kgsl_pool.c index 199f3cd03efc..00a6466704c5 100644 --- a/drivers/gpu/msm/kgsl_pool.c +++ b/drivers/gpu/msm/kgsl_pool.c @@ -599,12 +599,12 @@ static int kgsl_of_parse_mempool(struct kgsl_page_pool *pool, return 0; } -static void kgsl_of_get_mempools(struct device_node *parent) +void kgsl_probe_page_pools(void) { struct device_node *node, *child; int index = 0; - node = of_find_compatible_node(parent, NULL, "qcom,gpu-mempools"); + node = of_find_compatible_node(NULL, NULL, "qcom,gpu-mempools"); if (!node) return; @@ -624,12 +624,6 @@ static void kgsl_of_get_mempools(struct device_node *parent) kgsl_num_pools = index; of_node_put(node); -} - -void kgsl_init_page_pools(struct platform_device *pdev) -{ - /* Get GPU mempools data and configure pools */ - kgsl_of_get_mempools(pdev->dev.of_node); /* Initialize shrinker */ register_shrinker(&kgsl_pool_shrinker); diff --git a/drivers/gpu/msm/kgsl_pool.h b/drivers/gpu/msm/kgsl_pool.h index 946af0a4eff9..e8a0e9f3806e 100644 --- a/drivers/gpu/msm/kgsl_pool.h +++ b/drivers/gpu/msm/kgsl_pool.h @@ -33,7 +33,15 @@ int kgsl_pool_alloc_pages(u64 size, struct page ***pages, struct device *dev); * otherwise they are given back to system. */ void kgsl_pool_free_pages(struct page **pages, unsigned int page_count); -void kgsl_init_page_pools(struct platform_device *pdev); + +/** + * kgsl_probe_page_pools - Initialize the memory pools pools + */ +void kgsl_probe_page_pools(void); + +/** + * kgsl_exit_page_pools - Free outstanding pooled memory + */ void kgsl_exit_page_pools(void); #endif /* __KGSL_POOL_H */ From ef5440e7b807356dbbd328acea2e763b12d0970e Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 14 Oct 2019 10:41:12 -0600 Subject: [PATCH 3/4] msm: kgsl: Remove nonsense around the a5xx and a6xx SMMU table update All a5xx and a6xx targets use the CP_SMMU_TABLE_UPDATE opcode to switch the pagetable which handles all the needed locking but we've seen fit to add a bunch more around it, including keeping a dummy NOP IB used for synchronization on a3xx targets. Stop the madness and remove all the extraneous locking and other baloney and just do a straight up SMMU_TABLE_UPDATE without fanfare. And now that the setstate is only valid for a3xx, only create it for a3xx thereby removing another global buffer from the mix. Change-Id: Ic0dedbad7694cad6d40fcee66b7864a454df1653 Signed-off-by: Jordan Crouse --- drivers/gpu/msm/adreno.h | 1 - drivers/gpu/msm/adreno_a3xx.c | 1 - drivers/gpu/msm/adreno_a5xx.c | 1 - drivers/gpu/msm/adreno_a6xx.c | 1 - drivers/gpu/msm/adreno_iommu.c | 142 +++++++++--------------------- drivers/gpu/msm/adreno_pm4types.h | 24 ----- drivers/gpu/msm/adreno_snapshot.c | 20 ++--- drivers/gpu/msm/kgsl_iommu.c | 9 +- drivers/gpu/msm/kgsl_sharedmem.c | 6 +- 9 files changed, 54 insertions(+), 151 deletions(-) diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 67a5b57d1490..89ddfbea4a0d 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -605,7 +605,6 @@ enum adreno_regs { ADRENO_REG_CP_RB_RPTR_ADDR_HI, ADRENO_REG_CP_RB_RPTR, ADRENO_REG_CP_RB_WPTR, - ADRENO_REG_CP_CNTL, ADRENO_REG_CP_ME_CNTL, ADRENO_REG_CP_RB_CNTL, ADRENO_REG_CP_IB1_BASE, diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c index 858520271d42..a1574f4c7082 100644 --- a/drivers/gpu/msm/adreno_a3xx.c +++ b/drivers/gpu/msm/adreno_a3xx.c @@ -1198,7 +1198,6 @@ static unsigned int a3xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_BASE_HI, ADRENO_REG_SKIP), ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR, A3XX_CP_RB_RPTR), ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_WPTR, A3XX_CP_RB_WPTR), - ADRENO_REG_DEFINE(ADRENO_REG_CP_CNTL, A3XX_CP_CNTL), ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_CNTL, A3XX_CP_ME_CNTL), ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_CNTL, A3XX_CP_RB_CNTL), ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BASE, A3XX_CP_IB1_BASE), diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 30febffd8859..88819e06d886 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -2393,7 +2393,6 @@ static unsigned int a5xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { A5XX_CP_RB_RPTR_ADDR_HI), ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR, A5XX_CP_RB_RPTR), ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_WPTR, A5XX_CP_RB_WPTR), - ADRENO_REG_DEFINE(ADRENO_REG_CP_CNTL, A5XX_CP_CNTL), ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_CNTL, A5XX_CP_ME_CNTL), ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_CNTL, A5XX_CP_RB_CNTL), ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BASE, A5XX_CP_IB1_BASE), diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index 58f383c345af..03eaf8d59416 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -2264,7 +2264,6 @@ static unsigned int a6xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_WPTR, A6XX_CP_RB_WPTR), ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_CNTL, A6XX_CP_RB_CNTL), ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_CNTL, A6XX_CP_SQE_CNTL), - ADRENO_REG_DEFINE(ADRENO_REG_CP_CNTL, A6XX_CP_MISC_CNTL), ADRENO_REG_DEFINE(ADRENO_REG_CP_HW_FAULT, A6XX_CP_HW_FAULT), ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BASE, A6XX_CP_IB1_BASE), ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BASE_HI, A6XX_CP_IB1_BASE_HI), diff --git a/drivers/gpu/msm/adreno_iommu.c b/drivers/gpu/msm/adreno_iommu.c index 9f5a50a16a66..f92f6b65e17f 100644 --- a/drivers/gpu/msm/adreno_iommu.c +++ b/drivers/gpu/msm/adreno_iommu.c @@ -116,66 +116,36 @@ static unsigned int a3xx_tlbiall(struct adreno_device *adreno_dev, return cmds - start; } - -/** - * _adreno_iommu_add_idle_cmds - Add pm4 packets for GPU idle - * @adreno_dev - Pointer to device structure - * @cmds - Pointer to memory where idle commands need to be added - */ -static inline int _adreno_iommu_add_idle_cmds(struct adreno_device *adreno_dev, - unsigned int *cmds) -{ - unsigned int *start = cmds; - - cmds += cp_wait_for_idle(adreno_dev, cmds); - - if (adreno_is_a3xx(adreno_dev)) - cmds += cp_wait_for_me(adreno_dev, cmds); - - return cmds - start; -} - -/** - * adreno_iommu_set_apriv() - Generate commands to set/reset the APRIV - * @adreno_dev: Device on which the commands will execute - * @cmds: The memory pointer where commands are generated - * @set: If set then APRIV is set else reset - * - * Returns the number of commands generated - */ -static unsigned int adreno_iommu_set_apriv(struct adreno_device *adreno_dev, - unsigned int *cmds, int set) -{ - unsigned int *cmds_orig = cmds; - - /* adreno 3xx doesn't have the CP_CNTL.APRIV field */ - if (adreno_is_a3xx(adreno_dev)) - return 0; - - /* Targets with apriv control do not need to explicitly set the bit */ - if (ADRENO_FEATURE(adreno_dev, ADRENO_APRIV)) - return 0; - - cmds += cp_wait_for_idle(adreno_dev, cmds); - cmds += cp_wait_for_me(adreno_dev, cmds); - *cmds++ = cp_register(adreno_dev, adreno_getreg(adreno_dev, - ADRENO_REG_CP_CNTL), 1); - if (set) - *cmds++ = 1; - else - *cmds++ = 0; - - return cmds - cmds_orig; -} +/* offset at which a nop command is placed in setstate */ +#define KGSL_IOMMU_SETSTATE_NOP_OFFSET 1024 static unsigned int _adreno_iommu_set_pt_v2_a3xx(struct kgsl_device *device, unsigned int *cmds_orig, u64 ttbr0, u32 contextidr) { + struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device); struct adreno_device *adreno_dev = ADRENO_DEVICE(device); unsigned int *cmds = cmds_orig; - cmds += _adreno_iommu_add_idle_cmds(adreno_dev, cmds); + /* + * Adding an indirect buffer ensures that the prefetch stalls until + * the commands in indirect buffer have completed. We need to stall + * prefetch with a nop indirect buffer when updating pagetables + * because it provides stabler synchronization. + */ + cmds += cp_wait_for_me(adreno_dev, cmds); + + if (!IS_ERR_OR_NULL(iommu->setstate)) { + *cmds++ = cp_mem_packet(adreno_dev, + CP_INDIRECT_BUFFER_PFE, 2, 1); + cmds += cp_gpuaddr(adreno_dev, cmds, iommu->setstate->gpuaddr + + KGSL_IOMMU_SETSTATE_NOP_OFFSET); + *cmds++ = 2; + } + + cmds += cp_wait_for_idle(adreno_dev, cmds); + + cmds += cp_wait_for_me(adreno_dev, cmds); cmds += a3xx_vbif_lock(adreno_dev, cmds); @@ -192,8 +162,11 @@ static unsigned int _adreno_iommu_set_pt_v2_a3xx(struct kgsl_device *device, /* wait for me to finish the TLBI */ cmds += cp_wait_for_me(adreno_dev, cmds); + cmds += cp_wait_for_idle(adreno_dev, cmds); - cmds += _adreno_iommu_add_idle_cmds(adreno_dev, cmds); + /* Invalidate the state */ + *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1); + *cmds++ = 0x7ffff; return cmds - cmds_orig; } @@ -206,9 +179,6 @@ static unsigned int _adreno_iommu_set_pt_v2_a5xx(struct kgsl_device *device, struct adreno_device *adreno_dev = ADRENO_DEVICE(device); unsigned int *cmds = cmds_orig; - cmds += _adreno_iommu_add_idle_cmds(adreno_dev, cmds); - cmds += cp_wait_for_me(adreno_dev, cmds); - /* CP switches the pagetable and flushes the Caches */ *cmds++ = cp_packet(adreno_dev, CP_SMMU_TABLE_UPDATE, 3); *cmds++ = lower_32_bits(ttbr0); @@ -222,11 +192,6 @@ static unsigned int _adreno_iommu_set_pt_v2_a5xx(struct kgsl_device *device, *cmds++ = upper_32_bits(ttbr0); *cmds++ = contextidr; - /* release all commands with wait_for_me */ - cmds += cp_wait_for_me(adreno_dev, cmds); - - cmds += _adreno_iommu_add_idle_cmds(adreno_dev, cmds); - return cmds - cmds_orig; } @@ -239,9 +204,6 @@ static unsigned int _adreno_iommu_set_pt_v2_a6xx(struct kgsl_device *device, struct adreno_device *adreno_dev = ADRENO_DEVICE(device); unsigned int *cmds = cmds_orig; - cmds += _adreno_iommu_add_idle_cmds(adreno_dev, cmds); - cmds += cp_wait_for_me(adreno_dev, cmds); - /* CP switches the pagetable and flushes the Caches */ *cmds++ = cp_packet(adreno_dev, CP_SMMU_TABLE_UPDATE, 4); *cmds++ = lower_32_bits(ttbr0); @@ -256,11 +218,6 @@ static unsigned int _adreno_iommu_set_pt_v2_a6xx(struct kgsl_device *device, *cmds++ = upper_32_bits(ttbr0); *cmds++ = contextidr; - /* release all commands with wait_for_me */ - cmds += cp_wait_for_me(adreno_dev, cmds); - - cmds += _adreno_iommu_add_idle_cmds(adreno_dev, cmds); - return cmds - cmds_orig; } @@ -281,42 +238,22 @@ unsigned int adreno_iommu_set_pt_generate_cmds( struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER]; u64 ttbr0; u32 contextidr; - unsigned int *cmds_orig = cmds; ttbr0 = kgsl_mmu_pagetable_get_ttbr0(pt); contextidr = kgsl_mmu_pagetable_get_contextidr(pt); - cmds += adreno_iommu_set_apriv(adreno_dev, cmds, 1); - /* - * Adding an indirect buffer ensures that the prefetch stalls until - * the commands in indirect buffer have completed. We need to stall - * prefetch with a nop indirect buffer when updating pagetables - * because it provides stabler synchronization. - */ - cmds += cp_wait_for_me(adreno_dev, cmds); - *cmds++ = cp_mem_packet(adreno_dev, CP_INDIRECT_BUFFER_PFE, 2, 1); - cmds += cp_gpuaddr(adreno_dev, cmds, - iommu->setstate->gpuaddr + KGSL_IOMMU_SETSTATE_NOP_OFFSET); - *cmds++ = 2; - cmds += cp_wait_for_idle(adreno_dev, cmds); - if (adreno_is_a6xx(adreno_dev)) - cmds += _adreno_iommu_set_pt_v2_a6xx(device, cmds, + return _adreno_iommu_set_pt_v2_a6xx(device, cmds, ttbr0, contextidr, rb, ctx->cb_num); else if (adreno_is_a5xx(adreno_dev)) - cmds += _adreno_iommu_set_pt_v2_a5xx(device, cmds, + return _adreno_iommu_set_pt_v2_a5xx(device, cmds, ttbr0, contextidr, rb); else if (adreno_is_a3xx(adreno_dev)) - cmds += _adreno_iommu_set_pt_v2_a3xx(device, cmds, + return _adreno_iommu_set_pt_v2_a3xx(device, cmds, ttbr0, contextidr); - /* invalidate all base pointers */ - cmds += cp_invalidate_state(adreno_dev, cmds); - - cmds += adreno_iommu_set_apriv(adreno_dev, cmds, 0); - - return cmds - cmds_orig; + return 0; } /** @@ -440,18 +377,23 @@ void adreno_iommu_init(struct adreno_device *adreno_dev) if (kgsl_mmu_get_mmutype(device) == KGSL_MMU_TYPE_NONE) return; + if (!adreno_is_a3xx(adreno_dev)) + return; + /* - * A nop is required in an indirect buffer when switching + * 3xx requres a nop in an indirect buffer when switching * pagetables in-stream */ + if (IS_ERR_OR_NULL(iommu->setstate)) { + iommu->setstate = kgsl_allocate_global(device, PAGE_SIZE, + KGSL_MEMFLAGS_GPUREADONLY, 0, "setstate"); - kgsl_sharedmem_writel(device, iommu->setstate, - KGSL_IOMMU_SETSTATE_NOP_OFFSET, - cp_packet(adreno_dev, CP_NOP, 1)); + kgsl_sharedmem_writel(device, iommu->setstate, + KGSL_IOMMU_SETSTATE_NOP_OFFSET, + cp_type3_packet(CP_NOP, 1)); + } - /* Enable guard page MMU feature for A3xx and A4xx targets only */ - if (adreno_is_a3xx(adreno_dev)) - device->mmu.features |= KGSL_MMU_NEED_GUARD_PAGE; + device->mmu.features |= KGSL_MMU_NEED_GUARD_PAGE; } /** diff --git a/drivers/gpu/msm/adreno_pm4types.h b/drivers/gpu/msm/adreno_pm4types.h index 03d22029b18b..55c586860f8e 100644 --- a/drivers/gpu/msm/adreno_pm4types.h +++ b/drivers/gpu/msm/adreno_pm4types.h @@ -360,30 +360,6 @@ static inline uint cp_wait_for_idle(struct adreno_device *adreno_dev, return cmds - start; } -/** - * cp_invalidate_state - common function for invalidating cp - * state - * @adreno_dev: The adreno device - * @cmds: command pointer to add gpuaddr - */ -static inline uint cp_invalidate_state(struct adreno_device *adreno_dev, - uint *cmds) -{ - uint *start = cmds; - - if (ADRENO_GPUREV(adreno_dev) < 500) { - *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1); - *cmds++ = 0x7fff; - } else { - *cmds++ = cp_type7_packet(CP_SET_DRAW_STATE, 3); - *cmds++ = 0x40000; - *cmds++ = 0; - *cmds++ = 0; - } - - return cmds - start; -} - static inline u32 cp_protected_mode(struct adreno_device *adreno_dev, u32 *cmds, int on) { diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c index d0f1c06bbd67..67165ec93764 100644 --- a/drivers/gpu/msm/adreno_snapshot.c +++ b/drivers/gpu/msm/adreno_snapshot.c @@ -208,18 +208,6 @@ static inline void parse_ib(struct kgsl_device *device, } -static inline bool iommu_is_setstate_addr(struct kgsl_device *device, - uint64_t gpuaddr, uint64_t size) -{ - struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device); - - if (kgsl_mmu_get_mmutype(device) != KGSL_MMU_TYPE_IOMMU) - return false; - - return kgsl_gpuaddr_in_memdesc(iommu->setstate, gpuaddr, - size); -} - static void dump_all_ibs(struct kgsl_device *device, struct adreno_ringbuffer *rb, struct kgsl_snapshot *snapshot) @@ -227,6 +215,7 @@ static void dump_all_ibs(struct kgsl_device *device, int index = 0; unsigned int *rbptr; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device); rbptr = rb->buffer_desc->hostptr; @@ -248,7 +237,8 @@ static void dump_all_ibs(struct kgsl_device *device, } /* Don't parse known global IBs */ - if (iommu_is_setstate_addr(device, ibaddr, ibsize)) + if (kgsl_gpuaddr_in_memdesc(iommu->setstate, + ibaddr, ibsize)) continue; if (kgsl_gpuaddr_in_memdesc(adreno_dev->pwron_fixup, @@ -384,6 +374,7 @@ static void snapshot_rb_ibs(struct kgsl_device *device, parse_ibs = 0; if (parse_ibs && adreno_cmd_is_ib(adreno_dev, rbptr[index])) { + struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device); uint64_t ibaddr; uint64_t ibsize; @@ -399,7 +390,8 @@ static void snapshot_rb_ibs(struct kgsl_device *device, index = (index + 1) % KGSL_RB_DWORDS; /* Don't parse known global IBs */ - if (iommu_is_setstate_addr(device, ibaddr, ibsize)) + if (kgsl_gpuaddr_in_memdesc(iommu->setstate, + ibaddr, ibsize)) continue; if (kgsl_gpuaddr_in_memdesc(adreno_dev->pwron_fixup, diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 62b8e7cbaad4..d615ebcae95d 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -1209,7 +1209,7 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu) struct kgsl_device *device = KGSL_MMU_DEVICE(mmu); struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu); struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER]; - int status; + int status = 0; mmu->features |= KGSL_MMU_PAGED; @@ -1236,13 +1236,6 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu) } } - iommu->setstate = kgsl_allocate_global(device, PAGE_SIZE, - KGSL_MEMFLAGS_GPUREADONLY, 0, "setstate"); - - status = PTR_ERR_OR_ZERO(iommu->setstate); - if (status) - goto done; - device->qdss_desc = kgsl_allocate_global_fixed(device, "qcom,gpu-qdss-stm", "gpu-qdss"); diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index 0c997ad96d00..35b635260c10 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -812,7 +812,11 @@ kgsl_sharedmem_writel(struct kgsl_device *device, { uint32_t *dst; - if (WARN_ON(memdesc == NULL || memdesc->hostptr == NULL)) + /* Quietly return if the memdesc isn't valid */ + if (IS_ERR_OR_NULL(memdesc)) + return -EINVAL; + + if (WARN_ON(memdesc->hostptr == NULL)) return -EINVAL; WARN_ON(offsetbytes % sizeof(uint32_t) != 0); From 9bcf308dfc37b33e96fa00aaa0da4b9fd590d9d2 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 14 Oct 2019 10:41:10 -0600 Subject: [PATCH 4/4] msm: kgsl: Add dedicated boolean functions for adreno sysfs Instead of gloaming the boolean adreno sysfs functions onto the u32 functions give them their own dedicated functions that deal with native booleans from top to bottom. This allows for a bit of code cleanup but more importantly fixes the logical disconnect of switching back and forth between u32 and bool. Change-Id: Ic0dedbadc5b669b5131ff232d80d25ef5486b85e Signed-off-by: Jordan Crouse --- drivers/gpu/msm/adreno_sysfs.c | 175 ++++++++++++++++----------------- 1 file changed, 83 insertions(+), 92 deletions(-) diff --git a/drivers/gpu/msm/adreno_sysfs.c b/drivers/gpu/msm/adreno_sysfs.c index 9ff3d3cebcf0..53ee73c31a67 100644 --- a/drivers/gpu/msm/adreno_sysfs.c +++ b/drivers/gpu/msm/adreno_sysfs.c @@ -7,28 +7,17 @@ #include "adreno.h" -struct adreno_sysfs_attribute { +struct adreno_sysfs_attribute_u32 { struct device_attribute attr; - unsigned int (*show)(struct adreno_device *adreno_dev); - int (*store)(struct adreno_device *adreno_dev, unsigned int val); + u32 (*show)(struct adreno_device *adreno_dev); + int (*store)(struct adreno_device *adreno_dev, u32 val); }; -#define _ADRENO_SYSFS_ATTR(_name, __show, __store) \ -struct adreno_sysfs_attribute adreno_attr_##_name = { \ - .attr = __ATTR(_name, 0644, __show, __store), \ - .show = _ ## _name ## _show, \ - .store = _ ## _name ## _store, \ -} - -#define _ADRENO_SYSFS_ATTR_RO(_name, __show) \ -struct adreno_sysfs_attribute adreno_attr_##_name = { \ - .attr = __ATTR(_name, 0444, __show, NULL), \ - .show = _ ## _name ## _show, \ - .store = NULL, \ -} - -#define ADRENO_SYSFS_ATTR(_a) \ - container_of((_a), struct adreno_sysfs_attribute, attr) +struct adreno_sysfs_attribute_bool { + struct device_attribute attr; + bool (*show)(struct adreno_device *adreno_dev); + int (*store)(struct adreno_device *adreno_dev, bool val); +}; static int _ft_policy_store(struct adreno_device *adreno_dev, unsigned int val) @@ -54,13 +43,10 @@ static int _preempt_level_store(struct adreno_device *adreno_dev, static unsigned int _preempt_level_show(struct adreno_device *adreno_dev) { - struct adreno_preemption *preempt = &adreno_dev->preempt; - - return preempt->preempt_level; + return adreno_dev->preempt.preempt_level; } -static int _usesgmem_store(struct adreno_device *adreno_dev, - unsigned int val) +static int _usesgmem_store(struct adreno_device *adreno_dev, bool val) { struct adreno_preemption *preempt = &adreno_dev->preempt; @@ -68,15 +54,12 @@ static int _usesgmem_store(struct adreno_device *adreno_dev, return 0; } -static unsigned int _usesgmem_show(struct adreno_device *adreno_dev) +static bool _usesgmem_show(struct adreno_device *adreno_dev) { - struct adreno_preemption *preempt = &adreno_dev->preempt; - - return preempt->usesgmem; + return adreno_dev->preempt.usesgmem; } -static int _skipsaverestore_store(struct adreno_device *adreno_dev, - unsigned int val) +static int _skipsaverestore_store(struct adreno_device *adreno_dev, bool val) { struct adreno_preemption *preempt = &adreno_dev->preempt; @@ -84,11 +67,9 @@ static int _skipsaverestore_store(struct adreno_device *adreno_dev, return 0; } -static unsigned int _skipsaverestore_show(struct adreno_device *adreno_dev) +static bool _skipsaverestore_show(struct adreno_device *adreno_dev) { - struct adreno_preemption *preempt = &adreno_dev->preempt; - - return preempt->skipsaverestore; + return adreno_dev->preempt.skipsaverestore; } static int _ft_pagefault_policy_store(struct adreno_device *adreno_dev, @@ -118,46 +99,44 @@ static unsigned int _ft_pagefault_policy_show(struct adreno_device *adreno_dev) } static int _gpu_llc_slice_enable_store(struct adreno_device *adreno_dev, - unsigned int val) + bool val) { - adreno_dev->gpu_llc_slice_enable = val ? true : false; + adreno_dev->gpu_llc_slice_enable = val; return 0; } -static unsigned int _gpu_llc_slice_enable_show(struct adreno_device *adreno_dev) +static bool _gpu_llc_slice_enable_show(struct adreno_device *adreno_dev) { return adreno_dev->gpu_llc_slice_enable; } static int _gpuhtw_llc_slice_enable_store(struct adreno_device *adreno_dev, - unsigned int val) + bool val) { - adreno_dev->gpuhtw_llc_slice_enable = val ? true : false; + adreno_dev->gpuhtw_llc_slice_enable = val; return 0; } -static unsigned int -_gpuhtw_llc_slice_enable_show(struct adreno_device *adreno_dev) +static bool _gpuhtw_llc_slice_enable_show(struct adreno_device *adreno_dev) { return adreno_dev->gpuhtw_llc_slice_enable; } -static int _ft_long_ib_detect_store(struct adreno_device *adreno_dev, - unsigned int val) +static int _ft_long_ib_detect_store(struct adreno_device *adreno_dev, bool val) { adreno_dev->long_ib_detect = val; return 0; } -static unsigned int _ft_long_ib_detect_show(struct adreno_device *adreno_dev) +static bool _ft_long_ib_detect_show(struct adreno_device *adreno_dev) { return adreno_dev->long_ib_detect; } -static unsigned int _ft_hang_intr_status_show(struct adreno_device *adreno_dev) +static bool _ft_hang_intr_status_show(struct adreno_device *adreno_dev) { /* Hang interrupt is always on on all targets */ - return 1; + return true; } static int _pwrctrl_store(struct adreno_device *adreno_dev, @@ -180,8 +159,7 @@ static int _pwrctrl_store(struct adreno_device *adreno_dev, return 0; } -static int _preemption_store(struct adreno_device *adreno_dev, - unsigned int val) +static int _preemption_store(struct adreno_device *adreno_dev, bool val) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct kgsl_context *context; @@ -216,60 +194,57 @@ static int _preemption_store(struct adreno_device *adreno_dev, return 0; } -static unsigned int _preemption_show(struct adreno_device *adreno_dev) +static bool _preemption_show(struct adreno_device *adreno_dev) { return adreno_is_preemption_enabled(adreno_dev); } -static int _hwcg_store(struct adreno_device *adreno_dev, - unsigned int val) +static int _hwcg_store(struct adreno_device *adreno_dev, bool val) { return _pwrctrl_store(adreno_dev, val, ADRENO_HWCG_CTRL); } -static unsigned int _hwcg_show(struct adreno_device *adreno_dev) +static bool _hwcg_show(struct adreno_device *adreno_dev) { return test_bit(ADRENO_HWCG_CTRL, &adreno_dev->pwrctrl_flag); } -static int _throttling_store(struct adreno_device *adreno_dev, - unsigned int val) +static int _throttling_store(struct adreno_device *adreno_dev, bool val) { return _pwrctrl_store(adreno_dev, val, ADRENO_THROTTLING_CTRL); } -static unsigned int _throttling_show(struct adreno_device *adreno_dev) +static bool _throttling_show(struct adreno_device *adreno_dev) { return test_bit(ADRENO_THROTTLING_CTRL, &adreno_dev->pwrctrl_flag); } -static int _sptp_pc_store(struct adreno_device *adreno_dev, - unsigned int val) +static int _sptp_pc_store(struct adreno_device *adreno_dev, bool val) { return _pwrctrl_store(adreno_dev, val, ADRENO_SPTP_PC_CTRL); } -static unsigned int _sptp_pc_show(struct adreno_device *adreno_dev) +static bool _sptp_pc_show(struct adreno_device *adreno_dev) { return test_bit(ADRENO_SPTP_PC_CTRL, &adreno_dev->pwrctrl_flag); } -static int _lm_store(struct adreno_device *adreno_dev, unsigned int val) +static int _lm_store(struct adreno_device *adreno_dev, bool val) { return _pwrctrl_store(adreno_dev, val, ADRENO_LM_CTRL); } -static unsigned int _lm_show(struct adreno_device *adreno_dev) +static bool _lm_show(struct adreno_device *adreno_dev) { return test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag); } -static int _ifpc_store(struct adreno_device *adreno_dev, unsigned int val) +static int _ifpc_store(struct adreno_device *adreno_dev, bool val) { return gmu_core_dev_ifpc_store(KGSL_DEVICE(adreno_dev), val); } -static unsigned int _ifpc_show(struct adreno_device *adreno_dev) +static bool _ifpc_show(struct adreno_device *adreno_dev) { return gmu_core_dev_ifpc_show(KGSL_DEVICE(adreno_dev)); } @@ -286,12 +261,12 @@ static unsigned int _preempt_count_show(struct adreno_device *adreno_dev) return preempt->count; } -static unsigned int _acd_show(struct adreno_device *adreno_dev) +static bool _acd_show(struct adreno_device *adreno_dev) { return test_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag); } -static int _acd_store(struct adreno_device *adreno_dev, unsigned int val) +static int _acd_store(struct adreno_device *adreno_dev, bool val) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); @@ -306,16 +281,20 @@ static ssize_t _sysfs_store_u32(struct device *dev, const char *buf, size_t count) { struct adreno_device *adreno_dev = ADRENO_DEVICE(dev_get_drvdata(dev)); - struct adreno_sysfs_attribute *_attr = ADRENO_SYSFS_ATTR(attr); - unsigned int val = 0; + struct adreno_sysfs_attribute_u32 *_attr = + container_of(attr, struct adreno_sysfs_attribute_u32, attr); + u32 val; int ret; - ret = kgsl_sysfs_store(buf, &val); + ret = kstrtou32(buf, 0, &val); + if (ret) + return ret; - if (!ret && _attr->store) - ret = _attr->store(adreno_dev, val); + ret = _attr->store(adreno_dev, val); + if (ret) + return ret; - return (ssize_t) ret < 0 ? ret : count; + return count; } static ssize_t _sysfs_show_u32(struct device *dev, @@ -323,13 +302,10 @@ static ssize_t _sysfs_show_u32(struct device *dev, char *buf) { struct adreno_device *adreno_dev = ADRENO_DEVICE(dev_get_drvdata(dev)); - struct adreno_sysfs_attribute *_attr = ADRENO_SYSFS_ATTR(attr); - unsigned int val = 0; + struct adreno_sysfs_attribute_u32 *_attr = + container_of(attr, struct adreno_sysfs_attribute_u32, attr); - if (_attr->show) - val = _attr->show(adreno_dev); - - return scnprintf(buf, PAGE_SIZE, "0x%X\n", val); + return scnprintf(buf, PAGE_SIZE, "0x%X\n", _attr->show(adreno_dev)); } static ssize_t _sysfs_store_bool(struct device *dev, @@ -337,16 +313,20 @@ static ssize_t _sysfs_store_bool(struct device *dev, const char *buf, size_t count) { struct adreno_device *adreno_dev = ADRENO_DEVICE(dev_get_drvdata(dev)); - struct adreno_sysfs_attribute *_attr = ADRENO_SYSFS_ATTR(attr); - unsigned int val = 0; + struct adreno_sysfs_attribute_bool *_attr = + container_of(attr, struct adreno_sysfs_attribute_bool, attr); + bool val; int ret; - ret = kgsl_sysfs_store(buf, &val); + ret = kstrtobool(buf, &val); + if (ret) + return ret; - if (!ret && _attr->store) - ret = _attr->store(adreno_dev, val ? 1 : 0); + ret = _attr->store(adreno_dev, val); + if (ret) + return ret; - return (ssize_t) ret < 0 ? ret : count; + return count; } static ssize_t _sysfs_show_bool(struct device *dev, @@ -354,26 +334,37 @@ static ssize_t _sysfs_show_bool(struct device *dev, char *buf) { struct adreno_device *adreno_dev = ADRENO_DEVICE(dev_get_drvdata(dev)); - struct adreno_sysfs_attribute *_attr = ADRENO_SYSFS_ATTR(attr); - unsigned int val = 0; + struct adreno_sysfs_attribute_bool *_attr = + container_of(attr, struct adreno_sysfs_attribute_bool, attr); - if (_attr->show) - val = _attr->show(adreno_dev); - - return scnprintf(buf, PAGE_SIZE, "%d\n", val); + return scnprintf(buf, PAGE_SIZE, "%d\n", _attr->show(adreno_dev)); } #define ADRENO_SYSFS_BOOL(_name) \ - _ADRENO_SYSFS_ATTR(_name, _sysfs_show_bool, _sysfs_store_bool) +struct adreno_sysfs_attribute_bool adreno_attr_##_name = { \ + .attr = __ATTR(_name, 0644, _sysfs_show_bool, _sysfs_store_bool), \ + .show = _ ## _name ## _show, \ + .store = _ ## _name ## _store, \ +} #define ADRENO_SYSFS_RO_BOOL(_name) \ - _ADRENO_SYSFS_ATTR_RO(_name, _sysfs_show_bool) +struct adreno_sysfs_attribute_bool adreno_attr_##_name = { \ + .attr = __ATTR(_name, 0444, _sysfs_show_bool, NULL), \ + .show = _ ## _name ## _show, \ +} #define ADRENO_SYSFS_U32(_name) \ - _ADRENO_SYSFS_ATTR(_name, _sysfs_show_u32, _sysfs_store_u32) +struct adreno_sysfs_attribute_u32 adreno_attr_##_name = { \ + .attr = __ATTR(_name, 0644, _sysfs_show_u32, _sysfs_store_u32), \ + .show = _ ## _name ## _show, \ + .store = _ ## _name ## _store, \ +} #define ADRENO_SYSFS_RO_U32(_name) \ - _ADRENO_SYSFS_ATTR_RO(_name, _sysfs_show_u32) +struct adreno_sysfs_attribute_u32 adreno_attr_##_name = { \ + .attr = __ATTR(_name, 0444, _sysfs_show_u32, NULL), \ + .show = _ ## _name ## _show, \ +} static ADRENO_SYSFS_U32(ft_policy); static ADRENO_SYSFS_U32(ft_pagefault_policy);