summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-02-01 19:23:48 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-02-01 19:23:48 -0800
commit664d80e8457141343edb578a4923a74eba91370b (patch)
treeb0a92058413a55035c6adb409d748ce4003ce08f /drivers
parent48f5a37e3b382776a2e6e85c86b8aec8e1723e42 (diff)
parent3a798eea0bbfad711c9ba14c8ad5439af3c0206a (diff)
Merge "msm: kgsl: refcount irq to avoid racing against idle check"
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/msm/adreno.c22
-rw-r--r--drivers/gpu/msm/adreno.h4
2 files changed, 23 insertions, 3 deletions
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 11226472d801..0f582cf35e6b 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -592,6 +592,9 @@ static irqreturn_t adreno_irq_handler(struct kgsl_device *device)
unsigned int status = 0, tmp, int_bit;
int i;
+ atomic_inc(&adreno_dev->pending_irq_refcnt);
+ smp_mb__after_atomic();
+
adreno_readreg(adreno_dev, ADRENO_REG_RBBM_INT_0_STATUS, &status);
/*
@@ -630,6 +633,10 @@ static irqreturn_t adreno_irq_handler(struct kgsl_device *device)
adreno_writereg(adreno_dev, ADRENO_REG_RBBM_INT_CLEAR_CMD,
int_bit);
+ smp_mb__before_atomic();
+ atomic_dec(&adreno_dev->pending_irq_refcnt);
+ smp_mb__after_atomic();
+
return ret;
}
@@ -2030,7 +2037,18 @@ inline unsigned int adreno_irq_pending(struct adreno_device *adreno_dev)
adreno_readreg(adreno_dev, ADRENO_REG_RBBM_INT_0_STATUS, &status);
- return (status & gpudev->irq->mask) ? 1 : 0;
+ /*
+ * IRQ handler clears the RBBM INT0 status register immediately
+ * entering the ISR before actually serving the interrupt because
+ * of this we can't rely only on RBBM INT0 status only.
+ * Use pending_irq_refcnt along with RBBM INT0 to correctly
+ * determine whether any IRQ is pending or not.
+ */
+ if ((status & gpudev->irq->mask) ||
+ atomic_read(&adreno_dev->pending_irq_refcnt))
+ return 1;
+ else
+ return 0;
}
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 2c8345aadc07..f8c9b00d3f39 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -351,6 +351,7 @@ struct adreno_gpu_core {
* @ram_cycles_lo: Number of DDR clock cycles for the monitor session
* @perfctr_pwr_lo: Number of cycles VBIF is stalled by DDR
* @halt: Atomic variable to check whether the GPU is currently halted
+ * @pending_irq_refcnt: Atomic variable to keep track of running IRQ handlers
* @ctx_d_debugfs: Context debugfs node
* @pwrctrl_flag: Flag to hold adreno specific power attributes
* @profile_buffer: Memdesc holding the drawobj profiling buffer
@@ -408,6 +409,7 @@ struct adreno_device {
unsigned int starved_ram_lo;
unsigned int perfctr_pwr_lo;
atomic_t halt;
+ atomic_t pending_irq_refcnt;
struct dentry *ctx_d_debugfs;
unsigned long pwrctrl_flag;