summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Crouse <jcrouse@codeaurora.org>2016-05-11 09:37:52 -0600
committerCarter Cooper <ccooper@codeaurora.org>2016-07-20 15:19:35 -0600
commita5c4e52c5e4fc90f1de40a6379a4c7639674fc23 (patch)
treed6d7bbd0dd83ee70d1859294f743c3578830fde1
parentd8fa23c2446b287aed0390ac04bbc0de8502dfa5 (diff)
msm: kgsl: Keep the active draw context until it is switched out
Instead of trying to make a decision to switch out the active draw context for NULL at detach time leave the reference count for it until the next context switch or until the next slumber whichever comes first. This avoids races with the preemption code and ensures a smooth transition. A side effect is that we were depending heavily on the context detach to reset the ringbuffer to the default at power down and we didn't touch it on power up (though we did on soft reset and wake from slumber. Curious). Obviously if we are no longer switching we will need to force the default pagetable during start but it seems to me like this would be the right thing to do even if we were still switching out. CRs-Fixed: 1009124 Change-Id: Ic0dedbadff8df192096292b221130c8ef5b31e12 Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
-rw-r--r--drivers/gpu/msm/adreno.c28
-rw-r--r--drivers/gpu/msm/adreno_drawctxt.c49
-rw-r--r--drivers/gpu/msm/kgsl_iommu.c38
3 files changed, 37 insertions, 78 deletions
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 7b87424703cd..918231b73215 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1378,6 +1378,8 @@ static int _adreno_start(struct adreno_device *adreno_dev)
if (regulator_left_on)
_soft_reset(adreno_dev);
+ adreno_ringbuffer_set_global(adreno_dev, 0);
+
status = kgsl_mmu_start(device);
if (status)
goto error_pwr_off;
@@ -1692,10 +1694,6 @@ int adreno_reset(struct kgsl_device *device, int fault)
else
kgsl_pwrctrl_change_state(device, KGSL_STATE_NAP);
- /* Set the page table back to the default page table */
- kgsl_mmu_set_pt(&device->mmu, device->mmu.defaultpagetable);
- adreno_ringbuffer_set_global(adreno_dev, 0);
-
return ret;
}
@@ -2138,6 +2136,10 @@ static int adreno_soft_reset(struct kgsl_device *device)
/* Reset the GPU */
_soft_reset(adreno_dev);
+ /* Set the page table back to the default page table */
+ adreno_ringbuffer_set_global(adreno_dev, 0);
+ kgsl_mmu_set_pt(&device->mmu, device->mmu.defaultpagetable);
+
/* start of new CFF after reset */
kgsl_cffdump_open(device);
@@ -2309,23 +2311,11 @@ static int adreno_drain(struct kgsl_device *device)
/* Caller must hold the device mutex. */
static int adreno_suspend_context(struct kgsl_device *device)
{
- int status = 0;
- struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-
/* process any profiling results that are available */
- adreno_profile_process_results(adreno_dev);
-
- status = adreno_idle(device);
- if (status)
- return status;
- /* set the device to default pagetable */
- kgsl_mmu_set_pt(&device->mmu, device->mmu.defaultpagetable);
- adreno_ringbuffer_set_global(adreno_dev, 0);
+ adreno_profile_process_results(ADRENO_DEVICE(device));
- /* set ringbuffers to NULL ctxt */
- adreno_set_active_ctxs_null(adreno_dev);
-
- return status;
+ /* Wait for the device to go idle */
+ return adreno_idle(device);
}
/**
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index e0a7afd7bd8e..fb95f6108fb8 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -452,7 +452,7 @@ void adreno_drawctxt_detach(struct kgsl_context *context)
struct adreno_device *adreno_dev;
struct adreno_context *drawctxt;
struct adreno_ringbuffer *rb;
- int ret = 0, count, i;
+ int ret, count, i;
struct kgsl_cmdbatch *list[ADRENO_CONTEXT_CMDQUEUE_SIZE];
if (context == NULL)
@@ -467,33 +467,6 @@ void adreno_drawctxt_detach(struct kgsl_context *context)
list_del_init(&drawctxt->active_node);
spin_unlock(&adreno_dev->active_list_lock);
- /* deactivate context */
- mutex_lock(&device->mutex);
- if (rb->drawctxt_active == drawctxt) {
- if (adreno_dev->cur_rb == rb) {
- if (!kgsl_active_count_get(device)) {
- ret = adreno_drawctxt_switch(adreno_dev, rb,
- NULL, 0);
- kgsl_active_count_put(device);
- } else
- BUG();
- } else
- ret = adreno_drawctxt_switch(adreno_dev, rb, NULL, 0);
-
- if (ret != 0) {
- KGSL_DRV_ERR(device,
- "Unable to switch the context to NULL: %d\n",
- ret);
- }
-
- /*
- * Keep going ahead if we can't switch the context - failure
- * isn't always fatal, but sometimes it is. I like those
- * chances!
- */
- }
- mutex_unlock(&device->mutex);
-
spin_lock(&drawctxt->lock);
count = drawctxt_detach_cmdbatches(drawctxt, list);
spin_unlock(&drawctxt->lock);
@@ -562,6 +535,15 @@ void adreno_drawctxt_destroy(struct kgsl_context *context)
kfree(drawctxt);
}
+static void _drawctxt_switch_wait_callback(struct kgsl_device *device,
+ struct kgsl_event_group *group,
+ void *priv, int result)
+{
+ struct adreno_context *drawctxt = (struct adreno_context *) priv;
+
+ kgsl_context_put(&drawctxt->base);
+}
+
/**
* adreno_drawctxt_switch - switch the current draw context in a given RB
* @adreno_dev - The 3D device that owns the context
@@ -613,9 +595,14 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev,
if (ret)
return ret;
- /* Put the old instance of the active drawctxt */
- if (rb->drawctxt_active)
- kgsl_context_put(&rb->drawctxt_active->base);
+ if (rb->drawctxt_active) {
+ /* Wait for the timestamp to expire */
+ if (kgsl_add_event(device, &rb->events, rb->timestamp,
+ _drawctxt_switch_wait_callback,
+ rb->drawctxt_active)) {
+ kgsl_context_put(&rb->drawctxt_active->base);
+ }
+ }
rb->drawctxt_active = drawctxt;
return 0;
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 793c4f8b05e5..103d290eb681 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -1449,25 +1449,25 @@ done:
return ret;
}
+static int kgsl_iommu_set_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt);
+
static int kgsl_iommu_start(struct kgsl_mmu *mmu)
{
int status;
struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
- struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];
status = _setup_user_context(mmu);
if (status)
return status;
status = _setup_secure_context(mmu);
- if (status)
+ if (status) {
_detach_context(&iommu->ctx[KGSL_IOMMU_CONTEXT_USER]);
- else {
- kgsl_iommu_enable_clk(mmu);
- KGSL_IOMMU_SET_CTX_REG(ctx, TLBIALL, 1);
- kgsl_iommu_disable_clk(mmu);
+ return status;
}
- return status;
+
+ /* Make sure the hardware is programmed to the default pagetable */
+ return kgsl_iommu_set_pt(mmu, mmu->defaultpagetable);
}
static int
@@ -1704,23 +1704,15 @@ kgsl_iommu_get_current_ttbr0(struct kgsl_mmu *mmu)
*
* Return - void
*/
-static int kgsl_iommu_set_pt(struct kgsl_mmu *mmu,
- struct kgsl_pagetable *pt)
+static int kgsl_iommu_set_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
{
- 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 ret = 0;
uint64_t ttbr0, temp;
unsigned int contextidr;
unsigned long wait_for_flush;
- /*
- * If using a global pagetable, we can skip all this
- * because the pagetable will be set up by the iommu
- * driver and never changed at runtime.
- */
- if (!kgsl_mmu_is_perprocess(mmu))
+ if ((pt != mmu->defaultpagetable) && !kgsl_mmu_is_perprocess(mmu))
return 0;
kgsl_iommu_enable_clk(mmu);
@@ -1728,14 +1720,6 @@ static int kgsl_iommu_set_pt(struct kgsl_mmu *mmu,
ttbr0 = kgsl_mmu_pagetable_get_ttbr0(pt);
contextidr = kgsl_mmu_pagetable_get_contextidr(pt);
- /*
- * Taking the liberty to spin idle since this codepath
- * is invoked when we can spin safely for it to be idle
- */
- ret = adreno_spin_idle(ADRENO_DEVICE(device), ADRENO_IDLE_TIMEOUT);
- if (ret)
- return ret;
-
KGSL_IOMMU_SET_CTX_REG_Q(ctx, TTBR0, ttbr0);
KGSL_IOMMU_SET_CTX_REG(ctx, CONTEXTIDR, contextidr);
@@ -1764,10 +1748,8 @@ static int kgsl_iommu_set_pt(struct kgsl_mmu *mmu,
cpu_relax();
}
- /* Disable smmu clock */
kgsl_iommu_disable_clk(mmu);
-
- return ret;
+ return 0;
}
/*