Loading drivers/gpu/msm/Makefile +2 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ msm_adreno-y += \ adreno_a3xx_snapshot.o \ adreno_a4xx_snapshot.o \ adreno_a5xx_snapshot.o \ adreno_a4xx_preempt.o \ adreno_a5xx_preempt.o \ adreno_sysfs.o \ adreno.o \ adreno_cp_parser.o \ Loading drivers/gpu/msm/a5xx_reg.h +2 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,8 @@ #define A5XX_CP_RB_BASE 0x800 #define A5XX_CP_RB_BASE_HI 0x801 #define A5XX_CP_RB_CNTL 0x802 #define A5XX_CP_RB_RPTR_ADDR_LO 0x804 #define A5XX_CP_RB_RPTR_ADDR_HI 0x805 #define A5XX_CP_RB_RPTR 0x806 #define A5XX_CP_RB_WPTR 0x807 #define A5XX_CP_PFP_STAT_ADDR 0x808 Loading drivers/gpu/msm/adreno.c +72 −32 Original line number Diff line number Diff line Loading @@ -170,6 +170,30 @@ void adreno_writereg64(struct adreno_device *adreno_dev, gpudev->reg_offsets->offsets[hi], upper_32_bits(val)); } /** * adreno_get_rptr() - Get the current ringbuffer read pointer * @rb: Pointer the ringbuffer to query * * Get the latest rptr */ unsigned int adreno_get_rptr(struct adreno_ringbuffer *rb) { struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb); unsigned int rptr = 0; if (adreno_is_a3xx(adreno_dev)) adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_RPTR, &rptr); else { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); kgsl_sharedmem_readl(&device->scratch, &rptr, SCRATCH_RPTR_OFFSET(rb->id)); } return rptr; } /** * adreno_of_read_property() - Adreno read property * @node: Device node Loading Loading @@ -1288,6 +1312,28 @@ static void _update_threshold_count(struct adreno_device *adreno_dev, adreno_dev->lm_threshold_cross = adj; } static void _set_secvid(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); /* Program GPU contect protection init values */ if (device->mmu.secured) { if (adreno_is_a4xx(adreno_dev)) adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TRUST_CONFIG, 0x2); adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_CONTROL, 0x0); adreno_writereg64(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE_HI, KGSL_IOMMU_SECURE_BASE); adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_SIZE, KGSL_IOMMU_SECURE_SIZE); } } /** * _adreno_start - Power up the GPU and prepare to accept commands * @adreno_dev: Pointer to an adreno_device structure Loading Loading @@ -1334,22 +1380,7 @@ static int _adreno_start(struct adreno_device *adreno_dev) if (status) goto error_pwr_off; /* Program GPU contect protection init values */ if (device->mmu.secured) { if (adreno_is_a4xx(adreno_dev)) adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TRUST_CONFIG, 0x2); adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_CONTROL, 0x0); adreno_writereg64(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE_HI, KGSL_IOMMU_SECURE_BASE); adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_SIZE, KGSL_IOMMU_SECURE_SIZE); } _set_secvid(device); status = adreno_ocmem_malloc(adreno_dev); if (status) { Loading Loading @@ -1531,6 +1562,22 @@ static int adreno_vbif_clear_pending_transactions(struct kgsl_device *device) return ret; } static void adreno_set_active_ctxs_null(struct adreno_device *adreno_dev) { int i; struct adreno_ringbuffer *rb; FOR_EACH_RINGBUFFER(adreno_dev, rb, i) { if (rb->drawctxt_active) kgsl_context_put(&(rb->drawctxt_active->base)); rb->drawctxt_active = NULL; kgsl_sharedmem_writel(KGSL_DEVICE(adreno_dev), &rb->pagetable_desc, PT_INFO_OFFSET(current_rb_ptname), 0); } } static int adreno_stop(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); Loading Loading @@ -1647,10 +1694,7 @@ int adreno_reset(struct kgsl_device *device, int fault) /* Set the page table back to the default page table */ kgsl_mmu_set_pt(&device->mmu, device->mmu.defaultpagetable); kgsl_sharedmem_writel(device, &adreno_dev->ringbuffers[0].pagetable_desc, offsetof(struct adreno_ringbuffer_pagetable_info, current_global_ptname), 0); adreno_ringbuffer_set_global(adreno_dev, 0); return ret; } Loading Loading @@ -2097,6 +2141,8 @@ static int adreno_soft_reset(struct kgsl_device *device) /* start of new CFF after reset */ kgsl_cffdump_open(device); _set_secvid(device); /* Enable 64 bit gpu addr if feature is set */ if (gpudev->enable_64bit && adreno_support_64bit(adreno_dev)) Loading Loading @@ -2149,8 +2195,6 @@ bool adreno_isidle(struct kgsl_device *device) if (!kgsl_state_is_awake(device)) return true; adreno_get_rptr(ADRENO_CURRENT_RINGBUFFER(adreno_dev)); /* * wptr is updated when we add commands to ringbuffer, add a barrier * to make sure updated wptr is compared to rptr Loading @@ -2161,15 +2205,13 @@ bool adreno_isidle(struct kgsl_device *device) * ringbuffer is truly idle when all ringbuffers read and write * pointers are equal */ FOR_EACH_RINGBUFFER(adreno_dev, rb, i) { if (rb->rptr != rb->wptr) break; if (!adreno_rb_empty(rb)) return false; } if (i == adreno_dev->num_ringbuffers) return adreno_hw_isidle(adreno_dev); return false; } /** Loading Loading @@ -2278,10 +2320,8 @@ static int adreno_suspend_context(struct kgsl_device *device) return status; /* set the device to default pagetable */ kgsl_mmu_set_pt(&device->mmu, device->mmu.defaultpagetable); kgsl_sharedmem_writel(device, &adreno_dev->ringbuffers[0].pagetable_desc, offsetof(struct adreno_ringbuffer_pagetable_info, current_global_ptname), 0); adreno_ringbuffer_set_global(adreno_dev, 0); /* set ringbuffers to NULL ctxt */ adreno_set_active_ctxs_null(adreno_dev); Loading drivers/gpu/msm/adreno.h +105 −50 Original line number Diff line number Diff line Loading @@ -191,6 +191,47 @@ enum adreno_gpurev { struct adreno_gpudev; /* Time to allow preemption to complete (in ms) */ #define ADRENO_PREEMPT_TIMEOUT 10000 /** * enum adreno_preempt_states * ADRENO_PREEMPT_NONE: No preemption is scheduled * ADRENO_PREEMPT_START: The S/W has started * ADRENO_PREEMPT_TRIGGERED: A preeempt has been triggered in the HW * ADRENO_PREEMPT_FAULTED: The preempt timer has fired * ADRENO_PREEMPT_PENDING: The H/W has signaled preemption complete * ADRENO_PREEMPT_COMPLETE: Preemption could not be finished in the IRQ handler, * worker has been scheduled */ enum adreno_preempt_states { ADRENO_PREEMPT_NONE = 0, ADRENO_PREEMPT_START, ADRENO_PREEMPT_TRIGGERED, ADRENO_PREEMPT_FAULTED, ADRENO_PREEMPT_PENDING, ADRENO_PREEMPT_COMPLETE, }; /** * struct adreno_preemption * @state: The current state of preemption * @counters: Memory descriptor for the memory where the GPU writes the * preemption counters on switch * @timer: A timer to make sure preemption doesn't stall * @work: A work struct for the preemption worker (for 5XX) * @token_submit: Indicates if a preempt token has been submitted in * current ringbuffer (for 4XX) */ struct adreno_preemption { atomic_t state; struct kgsl_memdesc counters; struct timer_list timer; struct work_struct work; bool token_submit; }; struct adreno_busy_data { unsigned int gpu_busy; unsigned int vbif_ram_cycles; Loading Loading @@ -366,7 +407,7 @@ struct adreno_device { const struct firmware *lm_fw; uint32_t *lm_sequence; uint32_t lm_size; struct kgsl_memdesc preemption_counters; struct adreno_preemption preempt; struct work_struct gpmu_work; uint32_t lm_leakage; uint32_t lm_limit; Loading Loading @@ -456,6 +497,8 @@ enum adreno_regs { ADRENO_REG_CP_WFI_PEND_CTR, ADRENO_REG_CP_RB_BASE, ADRENO_REG_CP_RB_BASE_HI, ADRENO_REG_CP_RB_RPTR_ADDR_LO, ADRENO_REG_CP_RB_RPTR_ADDR_HI, ADRENO_REG_CP_RB_RPTR, ADRENO_REG_CP_RB_WPTR, ADRENO_REG_CP_CNTL, Loading Loading @@ -707,17 +750,12 @@ struct adreno_gpudev { void (*pwrlevel_change_settings)(struct adreno_device *, unsigned int prelevel, unsigned int postlevel, bool post); int (*preemption_pre_ibsubmit)(struct adreno_device *, struct adreno_ringbuffer *, unsigned int *, struct kgsl_context *, uint64_t cond_addr, struct kgsl_memobj_node *); unsigned int (*preemption_pre_ibsubmit)(struct adreno_device *, struct adreno_ringbuffer *rb, unsigned int *, struct kgsl_context *); int (*preemption_yield_enable)(unsigned int *); int (*preemption_post_ibsubmit)(struct adreno_device *, struct adreno_ringbuffer *, unsigned int *, struct kgsl_context *); int (*preemption_token)(struct adreno_device *, struct adreno_ringbuffer *, unsigned int *, uint64_t gpuaddr); unsigned int (*preemption_post_ibsubmit)(struct adreno_device *, unsigned int *); int (*preemption_init)(struct adreno_device *); void (*preemption_schedule)(struct adreno_device *); void (*enable_64bit)(struct adreno_device *); Loading Loading @@ -1258,34 +1296,32 @@ static inline int adreno_bootstrap_ucode(struct adreno_device *adreno_dev) } /** * adreno_preempt_state() - Check if preemption state is equal to given state * adreno_in_preempt_state() - Check if preemption state is equal to given state * @adreno_dev: Device whose preemption state is checked * @state: State to compare against */ static inline unsigned int adreno_preempt_state( struct adreno_device *adreno_dev, enum adreno_dispatcher_preempt_states state) static inline bool adreno_in_preempt_state(struct adreno_device *adreno_dev, enum adreno_preempt_states state) { return atomic_read(&adreno_dev->dispatcher.preemption_state) == state; return atomic_read(&adreno_dev->preempt.state) == state; } /** * adreno_get_rptr() - Get the current ringbuffer read pointer * @rb: Pointer the ringbuffer to query * * Get the current read pointer from the GPU register. * adreno_set_preempt_state() - Set the specified preemption state * @adreno_dev: Device to change preemption state * @state: State to set */ static inline unsigned int adreno_get_rptr(struct adreno_ringbuffer *rb) static inline void adreno_set_preempt_state(struct adreno_device *adreno_dev, enum adreno_preempt_states state) { struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb); if (adreno_dev->cur_rb == rb && adreno_preempt_state(adreno_dev, ADRENO_DISPATCHER_PREEMPT_CLEAR)) adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_RPTR, &(rb->rptr)); /* * atomic_set doesn't use barriers, so we need to do it ourselves. One * before... */ smp_wmb(); atomic_set(&adreno_dev->preempt.state, state); return rb->rptr; /* ... and one after */ smp_wmb(); } static inline bool adreno_is_preemption_enabled( Loading @@ -1293,7 +1329,6 @@ static inline bool adreno_is_preemption_enabled( { return test_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv); } /** * adreno_ctx_get_rb() - Return the ringbuffer that a context should * use based on priority Loading Loading @@ -1330,25 +1365,6 @@ static inline struct adreno_ringbuffer *adreno_ctx_get_rb( return &(adreno_dev->ringbuffers[ adreno_dev->num_ringbuffers - 1]); } /* * adreno_set_active_ctxs_null() - Put back reference to any active context * and set the active context to NULL * @adreno_dev: The adreno device */ static inline void adreno_set_active_ctxs_null(struct adreno_device *adreno_dev) { int i; struct adreno_ringbuffer *rb; FOR_EACH_RINGBUFFER(adreno_dev, rb, i) { if (rb->drawctxt_active) kgsl_context_put(&(rb->drawctxt_active->base)); rb->drawctxt_active = NULL; kgsl_sharedmem_writel(KGSL_DEVICE(adreno_dev), &rb->pagetable_desc, offsetof(struct adreno_ringbuffer_pagetable_info, current_rb_ptname), 0); } } /* * adreno_compare_prio_level() - Compares 2 priority levels based on enum values Loading @@ -1369,6 +1385,13 @@ void adreno_readreg64(struct adreno_device *adreno_dev, void adreno_writereg64(struct adreno_device *adreno_dev, enum adreno_regs lo, enum adreno_regs hi, uint64_t val); unsigned int adreno_get_rptr(struct adreno_ringbuffer *rb); static inline bool adreno_rb_empty(struct adreno_ringbuffer *rb) { return (adreno_get_rptr(rb) == rb->wptr); } static inline bool adreno_soft_fault_detect(struct adreno_device *adreno_dev) { return adreno_dev->fast_hang_detect && Loading Loading @@ -1398,4 +1421,36 @@ static inline bool adreno_support_64bit(struct adreno_device *adreno_dev) } #endif /*BITS_PER_LONG*/ static inline void adreno_ringbuffer_set_global( struct adreno_device *adreno_dev, int name) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); kgsl_sharedmem_writel(device, &adreno_dev->ringbuffers[0].pagetable_desc, PT_INFO_OFFSET(current_global_ptname), name); } static inline void adreno_ringbuffer_set_pagetable(struct adreno_ringbuffer *rb, struct kgsl_pagetable *pt) { struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb); struct kgsl_device *device = KGSL_DEVICE(adreno_dev); unsigned long flags; spin_lock_irqsave(&rb->preempt_lock, flags); kgsl_sharedmem_writel(device, &rb->pagetable_desc, PT_INFO_OFFSET(current_rb_ptname), pt->name); kgsl_sharedmem_writeq(device, &rb->pagetable_desc, PT_INFO_OFFSET(ttbr0), kgsl_mmu_pagetable_get_ttbr0(pt)); kgsl_sharedmem_writel(device, &rb->pagetable_desc, PT_INFO_OFFSET(contextidr), kgsl_mmu_pagetable_get_contextidr(pt)); spin_unlock_irqrestore(&rb->preempt_lock, flags); } #endif /*__ADRENO_H */ drivers/gpu/msm/adreno_a3xx.c +2 −2 Original line number Diff line number Diff line Loading @@ -1756,9 +1756,9 @@ static int _ringbuffer_bootstrap_ucode(struct adreno_device *adreno_dev, *cmds++ = cp_type3_packet(CP_INTERRUPT, 1); *cmds++ = 0; rb->wptr = rb->wptr - 2; rb->_wptr = rb->_wptr - 2; adreno_ringbuffer_submit(rb, NULL); rb->wptr = rb->wptr + 2; rb->_wptr = rb->_wptr + 2; } else { for (i = pfp_idx; i < adreno_dev->pfp_fw_size; i++) *cmds++ = adreno_dev->pfp_fw[i]; Loading Loading
drivers/gpu/msm/Makefile +2 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ msm_adreno-y += \ adreno_a3xx_snapshot.o \ adreno_a4xx_snapshot.o \ adreno_a5xx_snapshot.o \ adreno_a4xx_preempt.o \ adreno_a5xx_preempt.o \ adreno_sysfs.o \ adreno.o \ adreno_cp_parser.o \ Loading
drivers/gpu/msm/a5xx_reg.h +2 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,8 @@ #define A5XX_CP_RB_BASE 0x800 #define A5XX_CP_RB_BASE_HI 0x801 #define A5XX_CP_RB_CNTL 0x802 #define A5XX_CP_RB_RPTR_ADDR_LO 0x804 #define A5XX_CP_RB_RPTR_ADDR_HI 0x805 #define A5XX_CP_RB_RPTR 0x806 #define A5XX_CP_RB_WPTR 0x807 #define A5XX_CP_PFP_STAT_ADDR 0x808 Loading
drivers/gpu/msm/adreno.c +72 −32 Original line number Diff line number Diff line Loading @@ -170,6 +170,30 @@ void adreno_writereg64(struct adreno_device *adreno_dev, gpudev->reg_offsets->offsets[hi], upper_32_bits(val)); } /** * adreno_get_rptr() - Get the current ringbuffer read pointer * @rb: Pointer the ringbuffer to query * * Get the latest rptr */ unsigned int adreno_get_rptr(struct adreno_ringbuffer *rb) { struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb); unsigned int rptr = 0; if (adreno_is_a3xx(adreno_dev)) adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_RPTR, &rptr); else { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); kgsl_sharedmem_readl(&device->scratch, &rptr, SCRATCH_RPTR_OFFSET(rb->id)); } return rptr; } /** * adreno_of_read_property() - Adreno read property * @node: Device node Loading Loading @@ -1288,6 +1312,28 @@ static void _update_threshold_count(struct adreno_device *adreno_dev, adreno_dev->lm_threshold_cross = adj; } static void _set_secvid(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); /* Program GPU contect protection init values */ if (device->mmu.secured) { if (adreno_is_a4xx(adreno_dev)) adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TRUST_CONFIG, 0x2); adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_CONTROL, 0x0); adreno_writereg64(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE_HI, KGSL_IOMMU_SECURE_BASE); adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_SIZE, KGSL_IOMMU_SECURE_SIZE); } } /** * _adreno_start - Power up the GPU and prepare to accept commands * @adreno_dev: Pointer to an adreno_device structure Loading Loading @@ -1334,22 +1380,7 @@ static int _adreno_start(struct adreno_device *adreno_dev) if (status) goto error_pwr_off; /* Program GPU contect protection init values */ if (device->mmu.secured) { if (adreno_is_a4xx(adreno_dev)) adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TRUST_CONFIG, 0x2); adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_CONTROL, 0x0); adreno_writereg64(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE_HI, KGSL_IOMMU_SECURE_BASE); adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_SIZE, KGSL_IOMMU_SECURE_SIZE); } _set_secvid(device); status = adreno_ocmem_malloc(adreno_dev); if (status) { Loading Loading @@ -1531,6 +1562,22 @@ static int adreno_vbif_clear_pending_transactions(struct kgsl_device *device) return ret; } static void adreno_set_active_ctxs_null(struct adreno_device *adreno_dev) { int i; struct adreno_ringbuffer *rb; FOR_EACH_RINGBUFFER(adreno_dev, rb, i) { if (rb->drawctxt_active) kgsl_context_put(&(rb->drawctxt_active->base)); rb->drawctxt_active = NULL; kgsl_sharedmem_writel(KGSL_DEVICE(adreno_dev), &rb->pagetable_desc, PT_INFO_OFFSET(current_rb_ptname), 0); } } static int adreno_stop(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); Loading Loading @@ -1647,10 +1694,7 @@ int adreno_reset(struct kgsl_device *device, int fault) /* Set the page table back to the default page table */ kgsl_mmu_set_pt(&device->mmu, device->mmu.defaultpagetable); kgsl_sharedmem_writel(device, &adreno_dev->ringbuffers[0].pagetable_desc, offsetof(struct adreno_ringbuffer_pagetable_info, current_global_ptname), 0); adreno_ringbuffer_set_global(adreno_dev, 0); return ret; } Loading Loading @@ -2097,6 +2141,8 @@ static int adreno_soft_reset(struct kgsl_device *device) /* start of new CFF after reset */ kgsl_cffdump_open(device); _set_secvid(device); /* Enable 64 bit gpu addr if feature is set */ if (gpudev->enable_64bit && adreno_support_64bit(adreno_dev)) Loading Loading @@ -2149,8 +2195,6 @@ bool adreno_isidle(struct kgsl_device *device) if (!kgsl_state_is_awake(device)) return true; adreno_get_rptr(ADRENO_CURRENT_RINGBUFFER(adreno_dev)); /* * wptr is updated when we add commands to ringbuffer, add a barrier * to make sure updated wptr is compared to rptr Loading @@ -2161,15 +2205,13 @@ bool adreno_isidle(struct kgsl_device *device) * ringbuffer is truly idle when all ringbuffers read and write * pointers are equal */ FOR_EACH_RINGBUFFER(adreno_dev, rb, i) { if (rb->rptr != rb->wptr) break; if (!adreno_rb_empty(rb)) return false; } if (i == adreno_dev->num_ringbuffers) return adreno_hw_isidle(adreno_dev); return false; } /** Loading Loading @@ -2278,10 +2320,8 @@ static int adreno_suspend_context(struct kgsl_device *device) return status; /* set the device to default pagetable */ kgsl_mmu_set_pt(&device->mmu, device->mmu.defaultpagetable); kgsl_sharedmem_writel(device, &adreno_dev->ringbuffers[0].pagetable_desc, offsetof(struct adreno_ringbuffer_pagetable_info, current_global_ptname), 0); adreno_ringbuffer_set_global(adreno_dev, 0); /* set ringbuffers to NULL ctxt */ adreno_set_active_ctxs_null(adreno_dev); Loading
drivers/gpu/msm/adreno.h +105 −50 Original line number Diff line number Diff line Loading @@ -191,6 +191,47 @@ enum adreno_gpurev { struct adreno_gpudev; /* Time to allow preemption to complete (in ms) */ #define ADRENO_PREEMPT_TIMEOUT 10000 /** * enum adreno_preempt_states * ADRENO_PREEMPT_NONE: No preemption is scheduled * ADRENO_PREEMPT_START: The S/W has started * ADRENO_PREEMPT_TRIGGERED: A preeempt has been triggered in the HW * ADRENO_PREEMPT_FAULTED: The preempt timer has fired * ADRENO_PREEMPT_PENDING: The H/W has signaled preemption complete * ADRENO_PREEMPT_COMPLETE: Preemption could not be finished in the IRQ handler, * worker has been scheduled */ enum adreno_preempt_states { ADRENO_PREEMPT_NONE = 0, ADRENO_PREEMPT_START, ADRENO_PREEMPT_TRIGGERED, ADRENO_PREEMPT_FAULTED, ADRENO_PREEMPT_PENDING, ADRENO_PREEMPT_COMPLETE, }; /** * struct adreno_preemption * @state: The current state of preemption * @counters: Memory descriptor for the memory where the GPU writes the * preemption counters on switch * @timer: A timer to make sure preemption doesn't stall * @work: A work struct for the preemption worker (for 5XX) * @token_submit: Indicates if a preempt token has been submitted in * current ringbuffer (for 4XX) */ struct adreno_preemption { atomic_t state; struct kgsl_memdesc counters; struct timer_list timer; struct work_struct work; bool token_submit; }; struct adreno_busy_data { unsigned int gpu_busy; unsigned int vbif_ram_cycles; Loading Loading @@ -366,7 +407,7 @@ struct adreno_device { const struct firmware *lm_fw; uint32_t *lm_sequence; uint32_t lm_size; struct kgsl_memdesc preemption_counters; struct adreno_preemption preempt; struct work_struct gpmu_work; uint32_t lm_leakage; uint32_t lm_limit; Loading Loading @@ -456,6 +497,8 @@ enum adreno_regs { ADRENO_REG_CP_WFI_PEND_CTR, ADRENO_REG_CP_RB_BASE, ADRENO_REG_CP_RB_BASE_HI, ADRENO_REG_CP_RB_RPTR_ADDR_LO, ADRENO_REG_CP_RB_RPTR_ADDR_HI, ADRENO_REG_CP_RB_RPTR, ADRENO_REG_CP_RB_WPTR, ADRENO_REG_CP_CNTL, Loading Loading @@ -707,17 +750,12 @@ struct adreno_gpudev { void (*pwrlevel_change_settings)(struct adreno_device *, unsigned int prelevel, unsigned int postlevel, bool post); int (*preemption_pre_ibsubmit)(struct adreno_device *, struct adreno_ringbuffer *, unsigned int *, struct kgsl_context *, uint64_t cond_addr, struct kgsl_memobj_node *); unsigned int (*preemption_pre_ibsubmit)(struct adreno_device *, struct adreno_ringbuffer *rb, unsigned int *, struct kgsl_context *); int (*preemption_yield_enable)(unsigned int *); int (*preemption_post_ibsubmit)(struct adreno_device *, struct adreno_ringbuffer *, unsigned int *, struct kgsl_context *); int (*preemption_token)(struct adreno_device *, struct adreno_ringbuffer *, unsigned int *, uint64_t gpuaddr); unsigned int (*preemption_post_ibsubmit)(struct adreno_device *, unsigned int *); int (*preemption_init)(struct adreno_device *); void (*preemption_schedule)(struct adreno_device *); void (*enable_64bit)(struct adreno_device *); Loading Loading @@ -1258,34 +1296,32 @@ static inline int adreno_bootstrap_ucode(struct adreno_device *adreno_dev) } /** * adreno_preempt_state() - Check if preemption state is equal to given state * adreno_in_preempt_state() - Check if preemption state is equal to given state * @adreno_dev: Device whose preemption state is checked * @state: State to compare against */ static inline unsigned int adreno_preempt_state( struct adreno_device *adreno_dev, enum adreno_dispatcher_preempt_states state) static inline bool adreno_in_preempt_state(struct adreno_device *adreno_dev, enum adreno_preempt_states state) { return atomic_read(&adreno_dev->dispatcher.preemption_state) == state; return atomic_read(&adreno_dev->preempt.state) == state; } /** * adreno_get_rptr() - Get the current ringbuffer read pointer * @rb: Pointer the ringbuffer to query * * Get the current read pointer from the GPU register. * adreno_set_preempt_state() - Set the specified preemption state * @adreno_dev: Device to change preemption state * @state: State to set */ static inline unsigned int adreno_get_rptr(struct adreno_ringbuffer *rb) static inline void adreno_set_preempt_state(struct adreno_device *adreno_dev, enum adreno_preempt_states state) { struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb); if (adreno_dev->cur_rb == rb && adreno_preempt_state(adreno_dev, ADRENO_DISPATCHER_PREEMPT_CLEAR)) adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_RPTR, &(rb->rptr)); /* * atomic_set doesn't use barriers, so we need to do it ourselves. One * before... */ smp_wmb(); atomic_set(&adreno_dev->preempt.state, state); return rb->rptr; /* ... and one after */ smp_wmb(); } static inline bool adreno_is_preemption_enabled( Loading @@ -1293,7 +1329,6 @@ static inline bool adreno_is_preemption_enabled( { return test_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv); } /** * adreno_ctx_get_rb() - Return the ringbuffer that a context should * use based on priority Loading Loading @@ -1330,25 +1365,6 @@ static inline struct adreno_ringbuffer *adreno_ctx_get_rb( return &(adreno_dev->ringbuffers[ adreno_dev->num_ringbuffers - 1]); } /* * adreno_set_active_ctxs_null() - Put back reference to any active context * and set the active context to NULL * @adreno_dev: The adreno device */ static inline void adreno_set_active_ctxs_null(struct adreno_device *adreno_dev) { int i; struct adreno_ringbuffer *rb; FOR_EACH_RINGBUFFER(adreno_dev, rb, i) { if (rb->drawctxt_active) kgsl_context_put(&(rb->drawctxt_active->base)); rb->drawctxt_active = NULL; kgsl_sharedmem_writel(KGSL_DEVICE(adreno_dev), &rb->pagetable_desc, offsetof(struct adreno_ringbuffer_pagetable_info, current_rb_ptname), 0); } } /* * adreno_compare_prio_level() - Compares 2 priority levels based on enum values Loading @@ -1369,6 +1385,13 @@ void adreno_readreg64(struct adreno_device *adreno_dev, void adreno_writereg64(struct adreno_device *adreno_dev, enum adreno_regs lo, enum adreno_regs hi, uint64_t val); unsigned int adreno_get_rptr(struct adreno_ringbuffer *rb); static inline bool adreno_rb_empty(struct adreno_ringbuffer *rb) { return (adreno_get_rptr(rb) == rb->wptr); } static inline bool adreno_soft_fault_detect(struct adreno_device *adreno_dev) { return adreno_dev->fast_hang_detect && Loading Loading @@ -1398,4 +1421,36 @@ static inline bool adreno_support_64bit(struct adreno_device *adreno_dev) } #endif /*BITS_PER_LONG*/ static inline void adreno_ringbuffer_set_global( struct adreno_device *adreno_dev, int name) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); kgsl_sharedmem_writel(device, &adreno_dev->ringbuffers[0].pagetable_desc, PT_INFO_OFFSET(current_global_ptname), name); } static inline void adreno_ringbuffer_set_pagetable(struct adreno_ringbuffer *rb, struct kgsl_pagetable *pt) { struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb); struct kgsl_device *device = KGSL_DEVICE(adreno_dev); unsigned long flags; spin_lock_irqsave(&rb->preempt_lock, flags); kgsl_sharedmem_writel(device, &rb->pagetable_desc, PT_INFO_OFFSET(current_rb_ptname), pt->name); kgsl_sharedmem_writeq(device, &rb->pagetable_desc, PT_INFO_OFFSET(ttbr0), kgsl_mmu_pagetable_get_ttbr0(pt)); kgsl_sharedmem_writel(device, &rb->pagetable_desc, PT_INFO_OFFSET(contextidr), kgsl_mmu_pagetable_get_contextidr(pt)); spin_unlock_irqrestore(&rb->preempt_lock, flags); } #endif /*__ADRENO_H */
drivers/gpu/msm/adreno_a3xx.c +2 −2 Original line number Diff line number Diff line Loading @@ -1756,9 +1756,9 @@ static int _ringbuffer_bootstrap_ucode(struct adreno_device *adreno_dev, *cmds++ = cp_type3_packet(CP_INTERRUPT, 1); *cmds++ = 0; rb->wptr = rb->wptr - 2; rb->_wptr = rb->_wptr - 2; adreno_ringbuffer_submit(rb, NULL); rb->wptr = rb->wptr + 2; rb->_wptr = rb->_wptr + 2; } else { for (i = pfp_idx; i < adreno_dev->pfp_fw_size; i++) *cmds++ = adreno_dev->pfp_fw[i]; Loading