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;