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/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); 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_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_pool.c b/drivers/gpu/msm/kgsl_pool.c index 7fca6d8b8b4a..00a6466704c5 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; @@ -586,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; @@ -611,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 dbddced7f277..e8a0e9f3806e 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 @@ -28,7 +33,15 @@ int kgsl_pool_alloc_pages(u64 size, struct page ***pages); * 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 */ diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index 37d4399d4f3e..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); @@ -1074,7 +1078,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 +1133,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;