msm: kgsl: fix 2d IB processing
The 2d hardware handles ringbuffer and IB commands as
a series of gotos. At the end of each IB, there must
be a goto command back to the ringbuffer, which must
be "monkey patched" into the IB by the driver.
Fix this code to use a proper kernel mapping.
Change-Id: Ic35e6fbf6baeef51dbc2497f1702c7ccd6997579
Signed-off-by: Jeremy Gebben <jgebben@codeaurora.org>
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 6c43a75..41f4435 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -409,7 +409,7 @@
unsigned int index = 0;
unsigned int nextindex;
unsigned int nextcnt = Z180_STREAM_END_CMD | 5;
- struct kgsl_memdesc tmp = {0};
+ struct kgsl_mem_entry *entry = NULL;
unsigned int cmd;
struct kgsl_device *device = dev_priv->device;
struct kgsl_pagetable *pagetable = dev_priv->process_priv->pagetable;
@@ -427,8 +427,30 @@
}
cmd = ibdesc[0].gpuaddr;
sizedwords = ibdesc[0].sizedwords;
-
- tmp.hostptr = (void *)*timestamp;
+ /*
+ * Get a kernel mapping to the IB for monkey patching.
+ * See the end of this function.
+ */
+ entry = kgsl_sharedmem_find_region(dev_priv->process_priv, cmd,
+ sizedwords);
+ if (entry == NULL) {
+ KGSL_DRV_ERR(device, "Bad ibdesc: gpuaddr 0x%x size %d\n",
+ cmd, sizedwords);
+ result = -EINVAL;
+ goto error;
+ }
+ /*
+ * This will only map memory if it exists, otherwise it will reuse the
+ * mapping. And the 2d userspace reuses IBs so we likely won't create
+ * too many mappings.
+ */
+ if (kgsl_gpuaddr_to_vaddr(&entry->memdesc, cmd) == NULL) {
+ KGSL_DRV_ERR(device,
+ "Cannot make kernel mapping for gpuaddr 0x%x\n",
+ cmd);
+ result = -EINVAL;
+ goto error;
+ }
KGSL_CMD_INFO(device, "ctxt %d ibaddr 0x%08x sizedwords %d\n",
context->id, cmd, sizedwords);
@@ -470,12 +492,13 @@
nextaddr = z180_dev->ringbuffer.cmdbufdesc.gpuaddr
+ rb_offset(nextindex);
- tmp.hostptr = (void *)(tmp.hostptr +
- (sizedwords * sizeof(unsigned int)));
- tmp.size = 12;
-
- kgsl_sharedmem_writel(&tmp, 4, nextaddr);
- kgsl_sharedmem_writel(&tmp, 8, nextcnt);
+ /* monkey patch the IB so that it jumps back to the ringbuffer */
+ kgsl_sharedmem_writel(&entry->memdesc,
+ ((sizedwords + 1) * sizeof(unsigned int)),
+ nextaddr);
+ kgsl_sharedmem_writel(&entry->memdesc,
+ ((sizedwords + 2) * sizeof(unsigned int)),
+ nextcnt);
/* sync memory before activating the hardware for the new command*/
mb();