msm: kgsl: Add a new property to IOCTL_KGSL_DEVICE_GETPROPERTY
Return the reset status of the GPU unit when
IOCTL_KGSL_DEVICE_GETPROPERTY is called with
type KGSL_PROP_GPU_RESET_STAT
Change-Id: I4bb17be959eadba3ba491d94c6fd4f5824442e92
Signed-off-by: Shubhraprakash Das<sadas@codeaurora.org>
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 73d00b3..39a6248 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -604,6 +604,8 @@
unsigned int soptimestamp;
unsigned int eoptimestamp;
struct adreno_context *drawctxt;
+ struct kgsl_context *context;
+ int next = 0;
KGSL_DRV_ERR(device, "Starting recovery from 3D GPU hang....\n");
rb_buffer = vmalloc(rb->buffer_desc.size);
@@ -672,6 +674,24 @@
drawctxt->flags |= CTXT_FLAGS_GPU_HANG;
+ /*
+ * Set the reset status of all contexts to
+ * INNOCENT_CONTEXT_RESET_EXT except for the bad context
+ * since thats the guilty party
+ */
+ while ((context = idr_get_next(&device->context_idr, &next))) {
+ if (KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT !=
+ context->reset_status) {
+ if (context->devctxt != drawctxt)
+ context->reset_status =
+ KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT;
+ else
+ context->reset_status =
+ KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT;
+ }
+ next = next + 1;
+ }
+
/* Restore valid commands in ringbuffer */
adreno_ringbuffer_restore(rb, rb_buffer, num_rb_contents);
rb->timestamp = timestamp;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 9333dca..45007da 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -789,6 +789,40 @@
break;
}
+ case KGSL_PROP_GPU_RESET_STAT:
+ {
+ /* Return reset status of given context and clear it */
+ uint32_t id;
+ struct kgsl_context *context;
+
+ if (param->sizebytes != sizeof(unsigned int)) {
+ result = -EINVAL;
+ break;
+ }
+ /* We expect the value passed in to contain the context id */
+ if (copy_from_user(&id, param->value,
+ sizeof(unsigned int))) {
+ result = -EFAULT;
+ break;
+ }
+ context = kgsl_find_context(dev_priv, id);
+ if (!context) {
+ result = -EINVAL;
+ break;
+ }
+ /*
+ * Copy the reset status to value which also serves as
+ * the out parameter
+ */
+ if (copy_to_user(param->value, &(context->reset_status),
+ sizeof(unsigned int))) {
+ result = -EFAULT;
+ break;
+ }
+ /* Clear reset status once its been queried */
+ context->reset_status = KGSL_CTX_STAT_NO_ERROR;
+ break;
+ }
default:
result = dev_priv->device->ftbl->getproperty(
dev_priv->device, param->type,
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 2fb1e43..06432f9 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -197,6 +197,11 @@
/* Pointer to the device specific context information */
void *devctxt;
+ /*
+ * Status indicating whether a gpu reset occurred and whether this
+ * context was responsible for causing it
+ */
+ unsigned int reset_status;
};
struct kgsl_process_private {