diff mbox series

[v2,3/3] drm/panfrost: Stay in the threaded MMU IRQ handler until we've handled all IRQs

Message ID 20210205111757.585248-4-boris.brezillon@collabora.com (mailing list archive)
State New, archived
Headers show
Series drm/panfrost: MMU fixes | expand

Commit Message

Boris Brezillon Feb. 5, 2021, 11:17 a.m. UTC
Doing a hw-irq -> threaded-irq round-trip is counter-productive, stay
in the threaded irq handler as long as we can.

v2:
* Rework the loop to avoid a goto

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_mmu.c | 26 +++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

Comments

Steven Price Feb. 5, 2021, 11:57 a.m. UTC | #1
On 05/02/2021 11:17, Boris Brezillon wrote:
> Doing a hw-irq -> threaded-irq round-trip is counter-productive, stay
> in the threaded irq handler as long as we can.
> 
> v2:
> * Rework the loop to avoid a goto
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>

Reviewed-by: Steven Price <steven.price@arm.com>

> ---
>   drivers/gpu/drm/panfrost/panfrost_mmu.c | 26 +++++++++++++------------
>   1 file changed, 14 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> index 21e552d1ac71..0581186ebfb3 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> @@ -578,22 +578,20 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
>   {
>   	struct panfrost_device *pfdev = data;
>   	u32 status = mmu_read(pfdev, MMU_INT_RAWSTAT);
> -	int i, ret;
> +	int ret;
>   
> -	for (i = 0; status; i++) {
> -		u32 mask = BIT(i) | BIT(i + 16);
> +	while (status) {
> +		u32 as = ffs(status | (status >> 16)) - 1;
> +		u32 mask = BIT(as) | BIT(as + 16);
>   		u64 addr;
>   		u32 fault_status;
>   		u32 exception_type;
>   		u32 access_type;
>   		u32 source_id;
>   
> -		if (!(status & mask))
> -			continue;
> -
> -		fault_status = mmu_read(pfdev, AS_FAULTSTATUS(i));
> -		addr = mmu_read(pfdev, AS_FAULTADDRESS_LO(i));
> -		addr |= (u64)mmu_read(pfdev, AS_FAULTADDRESS_HI(i)) << 32;
> +		fault_status = mmu_read(pfdev, AS_FAULTSTATUS(as));
> +		addr = mmu_read(pfdev, AS_FAULTADDRESS_LO(as));
> +		addr |= (u64)mmu_read(pfdev, AS_FAULTADDRESS_HI(as)) << 32;
>   
>   		/* decode the fault status */
>   		exception_type = fault_status & 0xFF;
> @@ -604,8 +602,8 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
>   
>   		/* Page fault only */
>   		ret = -1;
> -		if ((status & mask) == BIT(i) && (exception_type & 0xF8) == 0xC0)
> -			ret = panfrost_mmu_map_fault_addr(pfdev, i, addr);
> +		if ((status & mask) == BIT(as) && (exception_type & 0xF8) == 0xC0)
> +			ret = panfrost_mmu_map_fault_addr(pfdev, as, addr);
>   
>   		if (ret)
>   			/* terminal fault, print info about the fault */
> @@ -617,7 +615,7 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
>   				"exception type 0x%X: %s\n"
>   				"access type 0x%X: %s\n"
>   				"source id 0x%X\n",
> -				i, addr,
> +				as, addr,
>   				"TODO",
>   				fault_status,
>   				(fault_status & (1 << 10) ? "DECODER FAULT" : "SLAVE FAULT"),
> @@ -626,6 +624,10 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
>   				source_id);
>   
>   		status &= ~mask;
> +
> +		/* If we received new MMU interrupts, process them before returning. */
> +		if (!status)
> +			status = mmu_read(pfdev, MMU_INT_RAWSTAT);
>   	}
>   
>   	mmu_write(pfdev, MMU_INT_MASK, ~0);
>
Rob Herring Feb. 9, 2021, 3:05 p.m. UTC | #2
On Fri, Feb 5, 2021 at 5:18 AM Boris Brezillon
<boris.brezillon@collabora.com> wrote:
>
> Doing a hw-irq -> threaded-irq round-trip is counter-productive, stay
> in the threaded irq handler as long as we can.
>
> v2:
> * Rework the loop to avoid a goto
>
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> ---
>  drivers/gpu/drm/panfrost/panfrost_mmu.c | 26 +++++++++++++------------
>  1 file changed, 14 insertions(+), 12 deletions(-)

Reviewed-by: Rob Herring <robh@kernel.org>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 21e552d1ac71..0581186ebfb3 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -578,22 +578,20 @@  static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
 {
 	struct panfrost_device *pfdev = data;
 	u32 status = mmu_read(pfdev, MMU_INT_RAWSTAT);
-	int i, ret;
+	int ret;
 
-	for (i = 0; status; i++) {
-		u32 mask = BIT(i) | BIT(i + 16);
+	while (status) {
+		u32 as = ffs(status | (status >> 16)) - 1;
+		u32 mask = BIT(as) | BIT(as + 16);
 		u64 addr;
 		u32 fault_status;
 		u32 exception_type;
 		u32 access_type;
 		u32 source_id;
 
-		if (!(status & mask))
-			continue;
-
-		fault_status = mmu_read(pfdev, AS_FAULTSTATUS(i));
-		addr = mmu_read(pfdev, AS_FAULTADDRESS_LO(i));
-		addr |= (u64)mmu_read(pfdev, AS_FAULTADDRESS_HI(i)) << 32;
+		fault_status = mmu_read(pfdev, AS_FAULTSTATUS(as));
+		addr = mmu_read(pfdev, AS_FAULTADDRESS_LO(as));
+		addr |= (u64)mmu_read(pfdev, AS_FAULTADDRESS_HI(as)) << 32;
 
 		/* decode the fault status */
 		exception_type = fault_status & 0xFF;
@@ -604,8 +602,8 @@  static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
 
 		/* Page fault only */
 		ret = -1;
-		if ((status & mask) == BIT(i) && (exception_type & 0xF8) == 0xC0)
-			ret = panfrost_mmu_map_fault_addr(pfdev, i, addr);
+		if ((status & mask) == BIT(as) && (exception_type & 0xF8) == 0xC0)
+			ret = panfrost_mmu_map_fault_addr(pfdev, as, addr);
 
 		if (ret)
 			/* terminal fault, print info about the fault */
@@ -617,7 +615,7 @@  static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
 				"exception type 0x%X: %s\n"
 				"access type 0x%X: %s\n"
 				"source id 0x%X\n",
-				i, addr,
+				as, addr,
 				"TODO",
 				fault_status,
 				(fault_status & (1 << 10) ? "DECODER FAULT" : "SLAVE FAULT"),
@@ -626,6 +624,10 @@  static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
 				source_id);
 
 		status &= ~mask;
+
+		/* If we received new MMU interrupts, process them before returning. */
+		if (!status)
+			status = mmu_read(pfdev, MMU_INT_RAWSTAT);
 	}
 
 	mmu_write(pfdev, MMU_INT_MASK, ~0);