msm: kgsl: Fault tolernace for context with pagefault
If pagefault happened in same global timestamp
as the hang do not attempt replay for fault tolerance.
This is an improvement from previous policy of not
attempting fault tolerance for the context
with pagefault.
CRs-Fixed: 469807
Change-Id: Idc9512b9fab3c9a2bf0b33a7e06f3070075427ba
Signed-off-by: Tarun Karra <tkarra@codeaurora.org>
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 1886e04..16a10ac 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1798,6 +1798,7 @@
* that do not want to be fault tolerant (ex: OPENCL)
*/
if (adreno_context->flags & CTXT_FLAGS_NO_FAULT_TOLERANCE) {
+ ft_data->status = 1;
KGSL_FT_ERR(device,
"No FT set for this context play good cmds\n");
goto play_good_cmds;
@@ -1824,15 +1825,20 @@
}
}
- /* Do not try the bad commands if hang is due to a fault */
- if (device->mmu.fault) {
- KGSL_FT_ERR(device, "MMU fault skipping bad cmds\n");
- device->mmu.fault = 0;
- goto play_good_cmds;
+ /* Do not try the reply if hang is due to a pagefault */
+ if (adreno_context->pagefault) {
+ if ((ft_data->context_id == adreno_context->id) &&
+ (ft_data->global_eop == adreno_context->pagefault_ts)) {
+ ft_data->ft_policy &= ~KGSL_FT_REPLAY;
+ KGSL_FT_ERR(device, "MMU fault skipping replay\n");
+ }
+
+ adreno_context->pagefault = 0;
}
if (ft_data->ft_policy & KGSL_FT_DISABLE) {
KGSL_FT_ERR(device, "NO FT policy play only good cmds\n");
+ ft_data->status = 1;
goto play_good_cmds;
}
diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h
index fd60688..c91bfc0 100644
--- a/drivers/gpu/msm/adreno_drawctxt.h
+++ b/drivers/gpu/msm/adreno_drawctxt.h
@@ -93,6 +93,8 @@
unsigned int id;
unsigned int ib_gpu_time_used;
uint32_t flags;
+ uint32_t pagefault;
+ unsigned long pagefault_ts;
struct kgsl_pagetable *pagetable;
struct kgsl_memdesc gpustate;
unsigned int reg_restore[3];
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index f2393e4..57ccb8f 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -112,6 +112,10 @@
struct kgsl_device *device;
struct adreno_device *adreno_dev;
unsigned int no_page_fault_log = 0;
+ unsigned int curr_context_id = 0;
+ unsigned int curr_global_ts = 0;
+ static struct adreno_context *curr_context;
+ static struct kgsl_context *context;
ret = get_iommu_unit(dev, &mmu, &iommu_unit);
if (ret)
@@ -146,6 +150,22 @@
mmu->fault = 1;
iommu_dev->fault = 1;
+ kgsl_sharedmem_readl(&device->memstore, &curr_context_id,
+ KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context));
+ context = idr_find(&device->context_idr, curr_context_id);
+ if (context != NULL)
+ curr_context = context->devctxt;
+
+ kgsl_sharedmem_readl(&device->memstore, &curr_global_ts,
+ KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, eoptimestamp));
+
+ /*
+ * Store pagefault's timestamp and ib1 addr in context,
+ * this information is used in GFT
+ */
+ curr_context->pagefault = 1;
+ curr_context->pagefault_ts = curr_global_ts;
+
trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr,
kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase), 0);
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index d1f58c4..f11511f 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -359,11 +359,11 @@
spin_lock(&kgsl_driver.ptlock);
list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) {
if (mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base)) {
- if ((addr & (PAGE_SIZE-1)) == pt->fault_addr) {
+ if ((addr & ~(PAGE_SIZE-1)) == pt->fault_addr) {
ret = 1;
break;
} else {
- pt->fault_addr = (addr & (PAGE_SIZE-1));
+ pt->fault_addr = (addr & ~(PAGE_SIZE-1));
ret = 0;
break;
}