Loading drivers/gpu/msm/adreno.c +78 −25 Original line number Diff line number Diff line Loading @@ -1339,7 +1339,7 @@ static int adreno_iommu_setstate(struct kgsl_device *device, if (result) kgsl_mmu_disable_clk(&device->mmu, KGSL_IOMMU_MAX_UNITS); else kgsl_mmu_disable_clk_on_ts(&device->mmu, rb->global_ts, adreno_ringbuffer_mmu_disable_clk_on_ts(device, rb, KGSL_IOMMU_MAX_UNITS); done: Loading Loading @@ -1811,7 +1811,7 @@ static int adreno_remove(struct platform_device *pdev) static int adreno_init(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_gpudev *gpudev; struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); int i; int ret; Loading @@ -1823,8 +1823,6 @@ static int adreno_init(struct kgsl_device *device) if (test_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv)) return 0; gpudev = ADRENO_GPU_DEVICE(adreno_dev); /* Power up the device */ ret = kgsl_pwrctrl_enable(device); if (ret) Loading Loading @@ -2083,6 +2081,8 @@ static int adreno_stop(struct kgsl_device *device) adreno_dispatcher_stop(adreno_dev); adreno_ringbuffer_stop(adreno_dev); kgsl_mmu_stop(&device->mmu); adreno_irqctrl(adreno_dev, 0); Loading Loading @@ -3203,6 +3203,74 @@ static int adreno_waittimestamp(struct kgsl_device *device, return ret; } /** * __adreno_readtimestamp() - Reads the timestamp from memstore memory * @device: Pointer to device whose memstore is read * @index: Index into the memstore memory * @type: Type of timestamp to read * @timestamp: The out parameter where the timestamp is read */ int __adreno_readtimestamp(struct kgsl_device *device, int index, int type, unsigned int *timestamp) { int status = 0; switch (type) { case KGSL_TIMESTAMP_CONSUMED: kgsl_sharedmem_readl(&device->memstore, timestamp, KGSL_MEMSTORE_OFFSET(index, soptimestamp)); break; case KGSL_TIMESTAMP_RETIRED: kgsl_sharedmem_readl(&device->memstore, timestamp, KGSL_MEMSTORE_OFFSET(index, eoptimestamp)); break; default: status = -EINVAL; *timestamp = 0; break; } return status; } /** * adreno_rb_readtimestamp(): Return the value of given type of timestamp * for a RB * @device: GPU device whose timestamp values are being queried * @priv: The object being queried for a timestamp (expected to be a rb pointer) * @type: The type of timestamp (one of 3) to be read * @timestamp: Pointer to where the read timestamp is to be written to * * CONSUMED and RETIRED type timestamps are sorted by id and are constantly * updated by the GPU through shared memstore memory. QUEUED type timestamps * are read directly from context struct. * The function returns 0 on success and timestamp value at the *timestamp * address and returns -EINVAL on any read error/invalid type and timestamp = 0. */ int adreno_rb_readtimestamp(struct kgsl_device *device, void *priv, enum kgsl_timestamp_type type, unsigned int *timestamp) { int status = 0; struct adreno_ringbuffer *rb = priv; /* * If user passed in a NULL pointer for timestamp, return without * doing anything. */ if (!timestamp) return status; if (KGSL_TIMESTAMP_QUEUED == type) *timestamp = rb->timestamp; else status = __adreno_readtimestamp(device, rb->id + KGSL_MEMSTORE_MAX, type, timestamp); return status; } /** * adreno_readtimestamp(): Return the value of given type of timestamp * @device: GPU device whose timestamp values are being queried Loading @@ -3225,6 +3293,7 @@ static int adreno_readtimestamp(struct kgsl_device *device, struct kgsl_context *context = priv; unsigned int id = KGSL_CONTEXT_ID(context); BUG_ON(NULL == context || id >= KGSL_MEMSTORE_MAX); /* * If user passed in a NULL pointer for timestamp, return without * doing anything. Loading @@ -3232,27 +3301,11 @@ static int adreno_readtimestamp(struct kgsl_device *device, if (!timestamp) return status; switch (type) { case KGSL_TIMESTAMP_QUEUED: { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); *timestamp = adreno_context_timestamp(context, ADRENO_CURRENT_RINGBUFFER(adreno_dev)); break; } case KGSL_TIMESTAMP_CONSUMED: kgsl_sharedmem_readl(&device->memstore, timestamp, KGSL_MEMSTORE_OFFSET(id, soptimestamp)); break; case KGSL_TIMESTAMP_RETIRED: kgsl_sharedmem_readl(&device->memstore, timestamp, KGSL_MEMSTORE_OFFSET(id, eoptimestamp)); break; default: status = -EINVAL; *timestamp = 0; break; } if (KGSL_TIMESTAMP_QUEUED == type) *timestamp = adreno_context_timestamp(context); else status = __adreno_readtimestamp(device, context->id, type, timestamp); return status; } Loading drivers/gpu/msm/adreno.h +37 −8 Original line number Diff line number Diff line Loading @@ -605,6 +605,7 @@ struct adreno_gpudev { struct adreno_coresight *coresight; struct adreno_irq *irq; int num_prio_levels; /* GPU specific function hooks */ irqreturn_t (*irq_handler)(struct adreno_device *); void (*irq_control)(struct adreno_device *, int); Loading Loading @@ -778,6 +779,10 @@ void adreno_coresight_remove(struct kgsl_device *device); bool adreno_hw_isidle(struct kgsl_device *device); int adreno_rb_readtimestamp(struct kgsl_device *device, void *priv, enum kgsl_timestamp_type type, unsigned int *timestamp); static inline int adreno_is_a3xx(struct adreno_device *adreno_dev) { return ((ADRENO_GPUREV(adreno_dev) >= 300) && Loading Loading @@ -860,19 +865,14 @@ static inline int adreno_rb_ctxtswitch(unsigned int *cmd) /** * adreno_context_timestamp() - Return the last queued timestamp for the context * @k_ctxt: Pointer to the KGSL context to query * @rb: Pointer to the ringbuffer structure for the GPU * * Return the last queued context for the given context. This is used to verify * that incoming requests are not using an invalid (unsubmitted) timestamp */ static inline int adreno_context_timestamp(struct kgsl_context *k_ctxt, struct adreno_ringbuffer *rb) static inline int adreno_context_timestamp(struct kgsl_context *k_ctxt) { if (k_ctxt) { struct adreno_context *a_ctxt = ADRENO_CONTEXT(k_ctxt); return a_ctxt->timestamp; } return rb->global_ts; struct adreno_context *drawctxt = ADRENO_CONTEXT(k_ctxt); return drawctxt->timestamp; } static inline int __adreno_add_idle_indirect_cmds(unsigned int *cmds, Loading Loading @@ -1292,4 +1292,33 @@ adreno_get_rptr(struct adreno_ringbuffer *rb) return rb->rptr; } /** * adreno_ctx_get_rb() - Return the ringbuffer that a context should * use based on priority * @adreno_dev: The adreno device that context is using * @drawctxt: The context pointer */ static inline struct adreno_ringbuffer *adreno_ctx_get_rb( struct adreno_device *adreno_dev, struct adreno_context *drawctxt) { struct kgsl_context *context; int level; if (!drawctxt) return NULL; context = &(drawctxt->base); /* * Math to convert the priority field in context structure to an RB ID. * Divide up the context priority based on number of ringbuffer levels. */ level = context->priority / adreno_dev->num_ringbuffers; if (level < adreno_dev->num_ringbuffers) return &(adreno_dev->ringbuffers[level]); else return &(adreno_dev->ringbuffers[ adreno_dev->num_ringbuffers - 1]); } #endif /*__ADRENO_H */ drivers/gpu/msm/adreno_a3xx.c +1 −0 Original line number Diff line number Diff line Loading @@ -2482,6 +2482,7 @@ struct adreno_gpudev adreno_a3xx_gpudev = { .perfcounters = &a3xx_perfcounters, .irq = &a3xx_irq, .snapshot_data = &a3xx_snapshot_data, .num_prio_levels = 1, .rb_init = a3xx_rb_init, .perfcounter_init = a3xx_perfcounter_init, Loading drivers/gpu/msm/adreno_a4xx.c +1 −0 Original line number Diff line number Diff line Loading @@ -1394,6 +1394,7 @@ struct adreno_gpudev adreno_a4xx_gpudev = { .perfcounters = &a4xx_perfcounters, .irq = &a4xx_irq, .snapshot_data = &a4xx_snapshot_data, .num_prio_levels = 1, .perfcounter_init = a3xx_perfcounter_init, .perfcounter_close = a3xx_perfcounter_close, Loading drivers/gpu/msm/adreno_dispatch.c +28 −17 Original line number Diff line number Diff line Loading @@ -57,23 +57,25 @@ static unsigned int _fault_timer_interval = 200; /* Local array for the current set of fault detect registers */ static unsigned int fault_detect_regs[FT_DETECT_REGS_COUNT]; /* The last retired global timestamp read during fault detect */ static unsigned int fault_detect_ts; /** * fault_detect_read() - Read the set of fault detect registers * @device: Pointer to the KGSL device struct * * Read the set of fault detect registers and store them in the local array. * This is for the initial values that are compared later with * fault_detect_read_compare * fault_detect_read_compare. Also store the initial timestamp of each rb * to compare the timestamps with. */ static void fault_detect_read(struct kgsl_device *device) { int i; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED, &fault_detect_ts); for (i = 0; i < adreno_dev->num_ringbuffers; i++) { struct adreno_ringbuffer *rb = &(adreno_dev->ringbuffers[i]); adreno_rb_readtimestamp(device, rb, KGSL_TIMESTAMP_RETIRED, &(rb->fault_detect_ts)); } for (i = 0; i < FT_DETECT_REGS_COUNT; i++) { if (ft_detect_regs[i] == 0) Loading @@ -99,12 +101,16 @@ static inline bool _isidle(struct kgsl_device *device) if (!adreno_hw_isidle(device)) return false; for (i = 0; i < adreno_dev->num_ringbuffers; i++) { kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED, &ts); if (ts != adreno_dev->ringbuffers[i].global_ts) /* * only compare the current RB timestamp because the device has gone * idle and therefore only the current RB ts can be equal, the other * RB's may not be scheduled by dispatcher yet */ if (adreno_rb_readtimestamp(device, adreno_dev->cur_rb, KGSL_TIMESTAMP_RETIRED, &ts)) return false; if (ts != adreno_dev->cur_rb->timestamp) return false; } ret: for (i = 0; i < FT_DETECT_REGS_COUNT; i++) fault_detect_regs[i] = 0; Loading @@ -117,10 +123,13 @@ ret: * @device: Pointer to the KGSL device struct * * Read the set of fault detect registers and compare them to the current set * of registers. Return 1 if any of the register values changed * of registers. Return 1 if any of the register values changed. Also, compare * if the current RB's timstamp has changed or not. */ static int fault_detect_read_compare(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_ringbuffer *rb = ADRENO_CURRENT_RINGBUFFER(adreno_dev); int i, ret = 0; unsigned int ts; Loading @@ -139,11 +148,13 @@ static int fault_detect_read_compare(struct kgsl_device *device) fault_detect_regs[i] = val; } kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED, &ts); if (ts != fault_detect_ts) if (!adreno_rb_readtimestamp(device, adreno_dev->cur_rb, KGSL_TIMESTAMP_RETIRED, &ts)) { if (ts != rb->fault_detect_ts) ret = 1; fault_detect_ts = ts; rb->fault_detect_ts = ts; } return ret; } Loading Loading
drivers/gpu/msm/adreno.c +78 −25 Original line number Diff line number Diff line Loading @@ -1339,7 +1339,7 @@ static int adreno_iommu_setstate(struct kgsl_device *device, if (result) kgsl_mmu_disable_clk(&device->mmu, KGSL_IOMMU_MAX_UNITS); else kgsl_mmu_disable_clk_on_ts(&device->mmu, rb->global_ts, adreno_ringbuffer_mmu_disable_clk_on_ts(device, rb, KGSL_IOMMU_MAX_UNITS); done: Loading Loading @@ -1811,7 +1811,7 @@ static int adreno_remove(struct platform_device *pdev) static int adreno_init(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_gpudev *gpudev; struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); int i; int ret; Loading @@ -1823,8 +1823,6 @@ static int adreno_init(struct kgsl_device *device) if (test_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv)) return 0; gpudev = ADRENO_GPU_DEVICE(adreno_dev); /* Power up the device */ ret = kgsl_pwrctrl_enable(device); if (ret) Loading Loading @@ -2083,6 +2081,8 @@ static int adreno_stop(struct kgsl_device *device) adreno_dispatcher_stop(adreno_dev); adreno_ringbuffer_stop(adreno_dev); kgsl_mmu_stop(&device->mmu); adreno_irqctrl(adreno_dev, 0); Loading Loading @@ -3203,6 +3203,74 @@ static int adreno_waittimestamp(struct kgsl_device *device, return ret; } /** * __adreno_readtimestamp() - Reads the timestamp from memstore memory * @device: Pointer to device whose memstore is read * @index: Index into the memstore memory * @type: Type of timestamp to read * @timestamp: The out parameter where the timestamp is read */ int __adreno_readtimestamp(struct kgsl_device *device, int index, int type, unsigned int *timestamp) { int status = 0; switch (type) { case KGSL_TIMESTAMP_CONSUMED: kgsl_sharedmem_readl(&device->memstore, timestamp, KGSL_MEMSTORE_OFFSET(index, soptimestamp)); break; case KGSL_TIMESTAMP_RETIRED: kgsl_sharedmem_readl(&device->memstore, timestamp, KGSL_MEMSTORE_OFFSET(index, eoptimestamp)); break; default: status = -EINVAL; *timestamp = 0; break; } return status; } /** * adreno_rb_readtimestamp(): Return the value of given type of timestamp * for a RB * @device: GPU device whose timestamp values are being queried * @priv: The object being queried for a timestamp (expected to be a rb pointer) * @type: The type of timestamp (one of 3) to be read * @timestamp: Pointer to where the read timestamp is to be written to * * CONSUMED and RETIRED type timestamps are sorted by id and are constantly * updated by the GPU through shared memstore memory. QUEUED type timestamps * are read directly from context struct. * The function returns 0 on success and timestamp value at the *timestamp * address and returns -EINVAL on any read error/invalid type and timestamp = 0. */ int adreno_rb_readtimestamp(struct kgsl_device *device, void *priv, enum kgsl_timestamp_type type, unsigned int *timestamp) { int status = 0; struct adreno_ringbuffer *rb = priv; /* * If user passed in a NULL pointer for timestamp, return without * doing anything. */ if (!timestamp) return status; if (KGSL_TIMESTAMP_QUEUED == type) *timestamp = rb->timestamp; else status = __adreno_readtimestamp(device, rb->id + KGSL_MEMSTORE_MAX, type, timestamp); return status; } /** * adreno_readtimestamp(): Return the value of given type of timestamp * @device: GPU device whose timestamp values are being queried Loading @@ -3225,6 +3293,7 @@ static int adreno_readtimestamp(struct kgsl_device *device, struct kgsl_context *context = priv; unsigned int id = KGSL_CONTEXT_ID(context); BUG_ON(NULL == context || id >= KGSL_MEMSTORE_MAX); /* * If user passed in a NULL pointer for timestamp, return without * doing anything. Loading @@ -3232,27 +3301,11 @@ static int adreno_readtimestamp(struct kgsl_device *device, if (!timestamp) return status; switch (type) { case KGSL_TIMESTAMP_QUEUED: { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); *timestamp = adreno_context_timestamp(context, ADRENO_CURRENT_RINGBUFFER(adreno_dev)); break; } case KGSL_TIMESTAMP_CONSUMED: kgsl_sharedmem_readl(&device->memstore, timestamp, KGSL_MEMSTORE_OFFSET(id, soptimestamp)); break; case KGSL_TIMESTAMP_RETIRED: kgsl_sharedmem_readl(&device->memstore, timestamp, KGSL_MEMSTORE_OFFSET(id, eoptimestamp)); break; default: status = -EINVAL; *timestamp = 0; break; } if (KGSL_TIMESTAMP_QUEUED == type) *timestamp = adreno_context_timestamp(context); else status = __adreno_readtimestamp(device, context->id, type, timestamp); return status; } Loading
drivers/gpu/msm/adreno.h +37 −8 Original line number Diff line number Diff line Loading @@ -605,6 +605,7 @@ struct adreno_gpudev { struct adreno_coresight *coresight; struct adreno_irq *irq; int num_prio_levels; /* GPU specific function hooks */ irqreturn_t (*irq_handler)(struct adreno_device *); void (*irq_control)(struct adreno_device *, int); Loading Loading @@ -778,6 +779,10 @@ void adreno_coresight_remove(struct kgsl_device *device); bool adreno_hw_isidle(struct kgsl_device *device); int adreno_rb_readtimestamp(struct kgsl_device *device, void *priv, enum kgsl_timestamp_type type, unsigned int *timestamp); static inline int adreno_is_a3xx(struct adreno_device *adreno_dev) { return ((ADRENO_GPUREV(adreno_dev) >= 300) && Loading Loading @@ -860,19 +865,14 @@ static inline int adreno_rb_ctxtswitch(unsigned int *cmd) /** * adreno_context_timestamp() - Return the last queued timestamp for the context * @k_ctxt: Pointer to the KGSL context to query * @rb: Pointer to the ringbuffer structure for the GPU * * Return the last queued context for the given context. This is used to verify * that incoming requests are not using an invalid (unsubmitted) timestamp */ static inline int adreno_context_timestamp(struct kgsl_context *k_ctxt, struct adreno_ringbuffer *rb) static inline int adreno_context_timestamp(struct kgsl_context *k_ctxt) { if (k_ctxt) { struct adreno_context *a_ctxt = ADRENO_CONTEXT(k_ctxt); return a_ctxt->timestamp; } return rb->global_ts; struct adreno_context *drawctxt = ADRENO_CONTEXT(k_ctxt); return drawctxt->timestamp; } static inline int __adreno_add_idle_indirect_cmds(unsigned int *cmds, Loading Loading @@ -1292,4 +1292,33 @@ adreno_get_rptr(struct adreno_ringbuffer *rb) return rb->rptr; } /** * adreno_ctx_get_rb() - Return the ringbuffer that a context should * use based on priority * @adreno_dev: The adreno device that context is using * @drawctxt: The context pointer */ static inline struct adreno_ringbuffer *adreno_ctx_get_rb( struct adreno_device *adreno_dev, struct adreno_context *drawctxt) { struct kgsl_context *context; int level; if (!drawctxt) return NULL; context = &(drawctxt->base); /* * Math to convert the priority field in context structure to an RB ID. * Divide up the context priority based on number of ringbuffer levels. */ level = context->priority / adreno_dev->num_ringbuffers; if (level < adreno_dev->num_ringbuffers) return &(adreno_dev->ringbuffers[level]); else return &(adreno_dev->ringbuffers[ adreno_dev->num_ringbuffers - 1]); } #endif /*__ADRENO_H */
drivers/gpu/msm/adreno_a3xx.c +1 −0 Original line number Diff line number Diff line Loading @@ -2482,6 +2482,7 @@ struct adreno_gpudev adreno_a3xx_gpudev = { .perfcounters = &a3xx_perfcounters, .irq = &a3xx_irq, .snapshot_data = &a3xx_snapshot_data, .num_prio_levels = 1, .rb_init = a3xx_rb_init, .perfcounter_init = a3xx_perfcounter_init, Loading
drivers/gpu/msm/adreno_a4xx.c +1 −0 Original line number Diff line number Diff line Loading @@ -1394,6 +1394,7 @@ struct adreno_gpudev adreno_a4xx_gpudev = { .perfcounters = &a4xx_perfcounters, .irq = &a4xx_irq, .snapshot_data = &a4xx_snapshot_data, .num_prio_levels = 1, .perfcounter_init = a3xx_perfcounter_init, .perfcounter_close = a3xx_perfcounter_close, Loading
drivers/gpu/msm/adreno_dispatch.c +28 −17 Original line number Diff line number Diff line Loading @@ -57,23 +57,25 @@ static unsigned int _fault_timer_interval = 200; /* Local array for the current set of fault detect registers */ static unsigned int fault_detect_regs[FT_DETECT_REGS_COUNT]; /* The last retired global timestamp read during fault detect */ static unsigned int fault_detect_ts; /** * fault_detect_read() - Read the set of fault detect registers * @device: Pointer to the KGSL device struct * * Read the set of fault detect registers and store them in the local array. * This is for the initial values that are compared later with * fault_detect_read_compare * fault_detect_read_compare. Also store the initial timestamp of each rb * to compare the timestamps with. */ static void fault_detect_read(struct kgsl_device *device) { int i; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED, &fault_detect_ts); for (i = 0; i < adreno_dev->num_ringbuffers; i++) { struct adreno_ringbuffer *rb = &(adreno_dev->ringbuffers[i]); adreno_rb_readtimestamp(device, rb, KGSL_TIMESTAMP_RETIRED, &(rb->fault_detect_ts)); } for (i = 0; i < FT_DETECT_REGS_COUNT; i++) { if (ft_detect_regs[i] == 0) Loading @@ -99,12 +101,16 @@ static inline bool _isidle(struct kgsl_device *device) if (!adreno_hw_isidle(device)) return false; for (i = 0; i < adreno_dev->num_ringbuffers; i++) { kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED, &ts); if (ts != adreno_dev->ringbuffers[i].global_ts) /* * only compare the current RB timestamp because the device has gone * idle and therefore only the current RB ts can be equal, the other * RB's may not be scheduled by dispatcher yet */ if (adreno_rb_readtimestamp(device, adreno_dev->cur_rb, KGSL_TIMESTAMP_RETIRED, &ts)) return false; if (ts != adreno_dev->cur_rb->timestamp) return false; } ret: for (i = 0; i < FT_DETECT_REGS_COUNT; i++) fault_detect_regs[i] = 0; Loading @@ -117,10 +123,13 @@ ret: * @device: Pointer to the KGSL device struct * * Read the set of fault detect registers and compare them to the current set * of registers. Return 1 if any of the register values changed * of registers. Return 1 if any of the register values changed. Also, compare * if the current RB's timstamp has changed or not. */ static int fault_detect_read_compare(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_ringbuffer *rb = ADRENO_CURRENT_RINGBUFFER(adreno_dev); int i, ret = 0; unsigned int ts; Loading @@ -139,11 +148,13 @@ static int fault_detect_read_compare(struct kgsl_device *device) fault_detect_regs[i] = val; } kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED, &ts); if (ts != fault_detect_ts) if (!adreno_rb_readtimestamp(device, adreno_dev->cur_rb, KGSL_TIMESTAMP_RETIRED, &ts)) { if (ts != rb->fault_detect_ts) ret = 1; fault_detect_ts = ts; rb->fault_detect_ts = ts; } return ret; } Loading