Skip to contentSkip to conversation

pci-dra7xx: Fix legacy IRQ handling

PATCH Applied Vignesh R 3 participants 13 messages Dec 29, 2017 – Jan 12, 2018

Subsystems (2)

v2 of 5 Applied Latest is v5 →

lore
Share & tools
lore

Vignesh R

author
#0 lore raw

v2 cover pci-dra7xx: Fix legacy IRQ handling

This series fixes couple of issues wrt PCIe legacy IRQ handling on dra7xx platforms.

Tested on DRA74 EVM.

Changes in v2:
* Drop patches related to errata i870 handling. That will be posted separately later.
* Split INTD IRQ handling into separate patch.

v1: https://lkml.org/lkml/2017/12/1/59

Vignesh R (2):
PCI: dra7xx: Fix legacy INTD IRQ handling
PCI: dra7xx: Iterate over INTx status bits

 drivers/pci/dwc/pci-dra7xx.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
Signature · 1 line
2.15.1
author
#1 lore raw

PATCH v2 1/2 PCI: dra7xx: Fix legacy INTD IRQ handling

Legacy INTD IRQ handling is broken on dra7xx due to fact that driver uses hwirq in range of 1-4 for INTA, INTD whereas IRQ domain is of size 4 which is numbered 0-3. Therefore when INTD IRQ line is used with pci-dra7xx driver following warning is seen:

       WARNING: CPU: 0 PID: 1 at kernel/irq/irqdomain.c:342 irq_domain_associate+0x12c/0x1c4
       error: hwirq 0x4 is too large for dummy

Fix this by using pci_irqd_intx_xlate() helper to translate the INTx 1-4 range into the 0-3 as done in other PCIe drivers.

---
 drivers/pci/dwc/pci-dra7xx.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/pci/dwc/pci-dra7xx.c +2 -1
index 58aed0896468..892f93910012 100644
@@ -226,6 +226,7 @@ static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
 
 static const struct irq_domain_ops intx_domain_ops = {
 	.map = dra7xx_pcie_intx_map,
+	.xlate = pci_irqd_intx_xlate,
 };
 
 static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp)
@@ -269,7 +270,7 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
 	case INTC:
 	case INTD:
 		generic_handle_irq(irq_find_mapping(dra7xx->irq_domain,
-						    ffs(reg)));
+						    ffs(reg) - 1));
 		break;
 	}
 
Signature · 1 line
2.15.1
Acked-by on v2 1/2
#2 lore raw

Re: [PATCH v2 1/2] PCI: dra7xx: Fix legacy INTD IRQ handling

Quoted 8 lines · Vignesh R

Legacy INTD IRQ handling is broken on dra7xx due to fact that driver uses hwirq in range of 1-4 for INTA, INTD whereas IRQ domain is of size 4 which is numbered 0-3. Therefore when INTD IRQ line is used with pci-dra7xx driver following warning is seen:

       WARNING: CPU: 0 PID: 1 at kernel/irq/irqdomain.c:342 irq_domain_associate+0x12c/0x1c4
       error: hwirq 0x4 is too large for dummy
Quoted 6 lines

Fix this by using pci_irqd_intx_xlate() helper to translate the INTx 1-4 range into the 0-3 as done in other PCIe drivers.

Quoted 26 lines
---
 drivers/pci/dwc/pci-dra7xx.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/pci/dwc/pci-dra7xx.c +2 -1
index 58aed0896468..892f93910012 100644
@@ -226,6 +226,7 @@ static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
 
 static const struct irq_domain_ops intx_domain_ops = {
 	.map = dra7xx_pcie_intx_map,
+	.xlate = pci_irqd_intx_xlate,
 };
 
 static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp)
@@ -269,7 +270,7 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
 	case INTC:
 	case INTD:
 		generic_handle_irq(irq_find_mapping(dra7xx->irq_domain,
-						    ffs(reg)));
+						    ffs(reg) - 1));
 		break;
 	}
 
#3 lore raw

Re: [PATCH v2 1/2] PCI: dra7xx: Fix legacy INTD IRQ handling

Hi,

Quoted 29 lines · Kishon Vijay Abraham I
Quoted 8 lines · Vignesh R

Legacy INTD IRQ handling is broken on dra7xx due to fact that driver uses hwirq in range of 1-4 for INTA, INTD whereas IRQ domain is of size 4 which is numbered 0-3. Therefore when INTD IRQ line is used with pci-dra7xx driver following warning is seen:

       WARNING: CPU: 0 PID: 1 at kernel/irq/irqdomain.c:342 irq_domain_associate+0x12c/0x1c4
       error: hwirq 0x4 is too large for dummy
Quoted 6 lines

Fix this by using pci_irqd_intx_xlate() helper to translate the INTx 1-4 range into the 0-3 as done in other PCIe drivers.

Quoted 10 lines
---
 drivers/pci/dwc/pci-dra7xx.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/pci/dwc/pci-dra7xx.c +0 -0
index 58aed0896468..892f93910012 100644
@@ -226,6 +226,7 @@ static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
 
Quoted 3 lines

drivers/pci/dwc/pci-dra7xx.c static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq, · line 229

Quoted 3 lines
drivers/pci/dwc/pci-dra7xx.c +1 -0
 static const struct irq_domain_ops intx_domain_ops = {
 	.map = dra7xx_pcie_intx_map,
+	.xlate = pci_irqd_intx_xlate,

Looking at this again, I think the mapping should be done in device tree using the interrupt-map property.

Lorenzo, can you hold merging this patch till we verify using the dt approach?

Thanks
Kishon

#4 lore raw

Re: [PATCH v2 1/2] PCI: dra7xx: Fix legacy INTD IRQ handling

Quoted 32 lines · Kishon Vijay Abraham I

Hi,

Quoted 29 lines · Kishon Vijay Abraham I
Quoted 8 lines · Vignesh R

Legacy INTD IRQ handling is broken on dra7xx due to fact that driver uses hwirq in range of 1-4 for INTA, INTD whereas IRQ domain is of size 4 which is numbered 0-3. Therefore when INTD IRQ line is used with pci-dra7xx driver following warning is seen:

       WARNING: CPU: 0 PID: 1 at kernel/irq/irqdomain.c:342 irq_domain_associate+0x12c/0x1c4
       error: hwirq 0x4 is too large for dummy
Quoted 6 lines

Fix this by using pci_irqd_intx_xlate() helper to translate the INTx 1-4 range into the 0-3 as done in other PCIe drivers.

Quoted 10 lines
---
 drivers/pci/dwc/pci-dra7xx.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/pci/dwc/pci-dra7xx.c +0 -0
index 58aed0896468..892f93910012 100644
@@ -226,6 +226,7 @@ static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
 
Quoted 8 lines
Quoted 3 lines

drivers/pci/dwc/pci-dra7xx.c static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq, · line 229

Quoted 3 lines
drivers/pci/dwc/pci-dra7xx.c +1 -0
 static const struct irq_domain_ops intx_domain_ops = {
 	.map = dra7xx_pcie_intx_map,
+	.xlate = pci_irqd_intx_xlate,

Looking at this again, I think the mapping should be done in device tree using the interrupt-map property.

Lorenzo, can you hold merging this patch till we verify using the dt approach?

Yes and I agree that's a DT mapping bug.

Lorenzo

author
#5 lore raw

Re: [PATCH v2 1/2] PCI: dra7xx: Fix legacy INTD IRQ handling

Quoted 40 lines · Lorenzo Pieralisi
Quoted 39 lines · Kishon Vijay Abraham I

Hi,

Quoted 29 lines · Kishon Vijay Abraham I
Quoted 8 lines · Vignesh R

Legacy INTD IRQ handling is broken on dra7xx due to fact that driver uses hwirq in range of 1-4 for INTA, INTD whereas IRQ domain is of size 4 which is numbered 0-3. Therefore when INTD IRQ line is used with pci-dra7xx driver following warning is seen:

       WARNING: CPU: 0 PID: 1 at kernel/irq/irqdomain.c:342 irq_domain_associate+0x12c/0x1c4
       error: hwirq 0x4 is too large for dummy
Quoted 6 lines

Fix this by using pci_irqd_intx_xlate() helper to translate the INTx 1-4 range into the 0-3 as done in other PCIe drivers.

Quoted 10 lines
---
 drivers/pci/dwc/pci-dra7xx.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/pci/dwc/pci-dra7xx.c +0 -0
index 58aed0896468..892f93910012 100644
@@ -226,6 +226,7 @@ static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
 
Quoted 3 lines

drivers/pci/dwc/pci-dra7xx.c static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq, · line 229

Quoted 3 lines
drivers/pci/dwc/pci-dra7xx.c +1 -0
 static const struct irq_domain_ops intx_domain_ops = {
 	.map = dra7xx_pcie_intx_map,
+	.xlate = pci_irqd_intx_xlate,

Looking at this again, I think the mapping should be done in device tree using the interrupt-map property.

Quoted 3 lines
Quoted 1 line

Lorenzo, can you hold merging this patch till we verify using the dt approach?

Yes and I agree that's a DT mapping bug.

I did some testing by changing interrupt-map property of PCIe node as as below:

arch/arm/boot/dts/dra7.dtsi +4 -4
index 261b5deb2456..2b1a2c5303bb 100644
@@ -332,10 +332,10 @@
                                phys = <&pcie1_phy>;
                                phy-names = "pcie-phy0";
                                interrupt-map-mask = <0 0 0 7>;
-                               interrupt-map = <0 0 0 1 &pcie1_intc 1>,
-                                               <0 0 0 2 &pcie1_intc 2>,
-                                               <0 0 0 3 &pcie1_intc 3>,
-                                               <0 0 0 4 &pcie1_intc 4>;
+                               interrupt-map = <0 0 0 1 &pcie1_intc 0>,
+                                               <0 0 0 2 &pcie1_intc 1>,
+                                               <0 0 0 3 &pcie1_intc 2>,
+                                               <0 0 0 4 &pcie1_intc 3>;
 
 

Although this eliminates need for xlate, we still need driver change to call the correct handler with above change:

static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp) @@ -269,7 +270,7 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
case INTC:
case INTD:
generic_handle_irq(irq_find_mapping(dra7xx->irq_domain,
- ffs(reg)));
+ ffs(reg) - 1));
break;
}

If we merge the driver change then the DT backward compatibility is broken. Right now INTA/B/C keep working even with buggy interrupt-map settings. But, if we fix interrupt-map and merge above driver change, then we will be *breaking* DT backward compatibility and INTA/B/C will no longer work with older DTs.
Therefore, IMO, this patch should be merged in order to keep DT backward compatibility and live with wrong DT representation.

Signature · 2 lines
Regards
Vignesh
#6 lore raw

Re: [PATCH v2 1/2] PCI: dra7xx: Fix legacy INTD IRQ handling

Quoted 82 lines · Vignesh R
Quoted 40 lines · Lorenzo Pieralisi
Quoted 39 lines · Kishon Vijay Abraham I

Hi,

Quoted 29 lines · Kishon Vijay Abraham I
Quoted 8 lines · Vignesh R

Legacy INTD IRQ handling is broken on dra7xx due to fact that driver uses hwirq in range of 1-4 for INTA, INTD whereas IRQ domain is of size 4 which is numbered 0-3. Therefore when INTD IRQ line is used with pci-dra7xx driver following warning is seen:

       WARNING: CPU: 0 PID: 1 at kernel/irq/irqdomain.c:342 irq_domain_associate+0x12c/0x1c4
       error: hwirq 0x4 is too large for dummy
Quoted 6 lines

Fix this by using pci_irqd_intx_xlate() helper to translate the INTx 1-4 range into the 0-3 as done in other PCIe drivers.

Quoted 10 lines
---
 drivers/pci/dwc/pci-dra7xx.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/pci/dwc/pci-dra7xx.c +0 -0
index 58aed0896468..892f93910012 100644
@@ -226,6 +226,7 @@ static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
 
Quoted 3 lines

drivers/pci/dwc/pci-dra7xx.c static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq, · line 229

Quoted 3 lines
drivers/pci/dwc/pci-dra7xx.c +1 -0
 static const struct irq_domain_ops intx_domain_ops = {
 	.map = dra7xx_pcie_intx_map,
+	.xlate = pci_irqd_intx_xlate,

Looking at this again, I think the mapping should be done in device tree using the interrupt-map property.

Quoted 3 lines
Quoted 1 line

Lorenzo, can you hold merging this patch till we verify using the dt approach?

Yes and I agree that's a DT mapping bug.

I did some testing by changing interrupt-map property of PCIe node as as below:

arch/arm/boot/dts/dra7.dtsi +4 -4
index 261b5deb2456..2b1a2c5303bb 100644
@@ -332,10 +332,10 @@
                                phys = <&pcie1_phy>;
                                phy-names = "pcie-phy0";
                                interrupt-map-mask = <0 0 0 7>;
-                               interrupt-map = <0 0 0 1 &pcie1_intc 1>,
-                                               <0 0 0 2 &pcie1_intc 2>,
-                                               <0 0 0 3 &pcie1_intc 3>,
-                                               <0 0 0 4 &pcie1_intc 4>;
+                               interrupt-map = <0 0 0 1 &pcie1_intc 0>,
+                                               <0 0 0 2 &pcie1_intc 1>,
+                                               <0 0 0 3 &pcie1_intc 2>,
+                                               <0 0 0 4 &pcie1_intc 3>;
 
 

Although this eliminates need for xlate, we still need driver change to call the correct handler with above change:

static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp)

arch/arm/boot/dts/dra7.dtsi +1 -1
@@ -269,7 +270,7 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int
 irq, void *arg)
 	case INTC:
 	case INTD:
 		generic_handle_irq(irq_find_mapping(dra7xx->irq_domain,
-						    ffs(reg)));
+						    ffs(reg) - 1));
 		break;
 	}
Quoted 7 lines

If we merge the driver change then the DT backward compatibility is broken. Right now INTA/B/C keep working even with buggy interrupt-map settings. But, if we fix interrupt-map and merge above driver change, then we will be *breaking* DT backward compatibility and INTA/B/C will no longer work with older DTs.
Therefore, IMO, this patch should be merged in order to keep DT backward compatibility and live with wrong DT representation.

Yes, this is a mess. I am not fond at all of this fix but I will end up merging it for the same reasons you provided - I can't break backward DT compatibility.

Lorenzo

#7 lore raw

Re: [PATCH v2 1/2] PCI: dra7xx: Fix legacy INTD IRQ handling

In reply to Vignesh R
Quoted 11 lines · Vignesh R

Legacy INTD IRQ handling is broken on dra7xx due to fact that driver uses hwirq in range of 1-4 for INTA, INTD whereas IRQ domain is of size 4 which is numbered 0-3. Therefore when INTD IRQ line is used with pci-dra7xx driver following warning is seen:

       WARNING: CPU: 0 PID: 1 at kernel/irq/irqdomain.c:342 irq_domain_associate+0x12c/0x1c4
       error: hwirq 0x4 is too large for dummy

Fix this by using pci_irqd_intx_xlate() helper to translate the INTx 1-4 range into the 0-3 as done in other PCIe drivers.

Quoted 6 lines
---
 drivers/pci/dwc/pci-dra7xx.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

Applied to pci/dwc for v4.16, thanks.

Lorenzo

Quoted 24 lines
drivers/pci/dwc/pci-dra7xx.c +2 -1
index 58aed0896468..892f93910012 100644
@@ -226,6 +226,7 @@ static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
 
 static const struct irq_domain_ops intx_domain_ops = {
 	.map = dra7xx_pcie_intx_map,
+	.xlate = pci_irqd_intx_xlate,
 };
 
 static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp)
@@ -269,7 +270,7 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
 	case INTC:
 	case INTD:
 		generic_handle_irq(irq_find_mapping(dra7xx->irq_domain,
-						    ffs(reg)));
+						    ffs(reg) - 1));
 		break;
 	}
 
Signature · 1 line
2.15.1
author
#8 lore raw

PATCH v2 2/2 PCI: dra7xx: Iterate over INTx status bits

In reply to Vignesh R

It is possible that more than one legacy IRQ may be set at the same time, therefore iterate and handle all the pending INTx interrupts before clearing the status and exiting the IRQ handler. Otherwise, some interrupts would be lost.

---
 drivers/pci/dwc/pci-dra7xx.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/pci/dwc/pci-dra7xx.c +7 -3
index 892f93910012..48c6ae535847 100644
@@ -257,7 +257,8 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
 	struct dra7xx_pcie *dra7xx = arg;
 	struct dw_pcie *pci = dra7xx->pci;
 	struct pcie_port *pp = &pci->pp;
-	u32 reg;
+	unsigned long reg;
+	u32 virq, bit;
 
 	reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI);
 
@@ -269,8 +270,11 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
 	case INTB:
 	case INTC:
 	case INTD:
-		generic_handle_irq(irq_find_mapping(dra7xx->irq_domain,
-						    ffs(reg) - 1));
+		for_each_set_bit(bit, &reg, PCI_NUM_INTX) {
+			virq = irq_find_mapping(dra7xx->irq_domain, bit);
+			if (virq)
+				generic_handle_irq(virq);
+		}
 		break;
 	}
 
Signature · 1 line
2.15.1
#9 lore raw

Re: [PATCH v2 2/2] PCI: dra7xx: Iterate over INTx status bits

Quoted 27 lines · Vignesh R

It is possible that more than one legacy IRQ may be set at the same time, therefore iterate and handle all the pending INTx interrupts before clearing the status and exiting the IRQ handler. Otherwise, some interrupts would be lost.

---
 drivers/pci/dwc/pci-dra7xx.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/pci/dwc/pci-dra7xx.c +2 -1
index 892f93910012..48c6ae535847 100644
@@ -257,7 +257,8 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
 	struct dra7xx_pcie *dra7xx = arg;
 	struct dw_pcie *pci = dra7xx->pci;
 	struct pcie_port *pp = &pci->pp;
-	u32 reg;
+	unsigned long reg;
+	u32 virq, bit;
 
 	reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI);
 
@@ -269,8 +270,11 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
 	case INTB:
 	case INTC:

drivers/pci/dwc/pci-dra7xx.c static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg) · line 279

Quoted 10 lines
drivers/pci/dwc/pci-dra7xx.c +5 -2
 	case INTD:
-		generic_handle_irq(irq_find_mapping(dra7xx->irq_domain,
-						    ffs(reg) - 1));
+		for_each_set_bit(bit, &reg, PCI_NUM_INTX) {
+			virq = irq_find_mapping(dra7xx->irq_domain, bit);
+			if (virq)
+				generic_handle_irq(virq);
+		}
 		break;
 	}

It is not strictly related to this patch but why MSI and INTX are handled as mutually exclusive in dra7xx_pcie_msi_irq_handler() ?

Lorenzo

author
#10 lore raw

Re: [PATCH v2 2/2] PCI: dra7xx: Iterate over INTx status bits

Quoted 33 lines · Lorenzo Pieralisi
Quoted 32 lines · Vignesh R

It is possible that more than one legacy IRQ may be set at the same time, therefore iterate and handle all the pending INTx interrupts before clearing the status and exiting the IRQ handler. Otherwise, some interrupts would be lost.

---
  drivers/pci/dwc/pci-dra7xx.c | 10 +++++++---

  1 file changed, 7 insertions(+), 3 deletions(-)
drivers/pci/dwc/pci-dra7xx.c +2 -1
index 892f93910012..48c6ae535847 100644
@@ -257,7 +257,8 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
         struct dra7xx_pcie *dra7xx = arg;
         struct dw_pcie *pci = dra7xx->pci;
         struct pcie_port *pp = &pci->pp;
-     u32 reg;
+     unsigned long reg;
+     u32 virq, bit;


        reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI);

drivers/pci/dwc/pci-dra7xx.c +0 -0
@@ -269,8 +270,11 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)

        case INTB:
        case INTC:
        case INTD:
-             generic_handle_irq(irq_find_mapping(dra7xx->irq_domain, -                                                 ffs(reg) - 1)); +             for_each_set_bit(bit, &reg, PCI_NUM_INTX) {
+                     virq = irq_find_mapping(dra7xx->irq_domain, bit);

Quoted 8 lines
Quoted 5 lines

+                     if (virq)
+                             generic_handle_irq(virq); +             }
                break;
        }

It is not strictly related to this patch but why MSI and INTX are handled as mutually exclusive in dra7xx_pcie_msi_irq_handler() ?

I think the driver previously assumed MSI and legacy IRQs are exclusive of each other, which is not true. Will try to fix this along with couple of other fixes that I have for MSI IRQ handling.

Signature · 2 lines
Regards
Vignesh
Acked-by on v2 2/2
#11 lore raw

Re: [PATCH v2 2/2] PCI: dra7xx: Iterate over INTx status bits

In reply to Vignesh R
Quoted 6 lines · Vignesh R

It is possible that more than one legacy IRQ may be set at the same time, therefore iterate and handle all the pending INTx interrupts before clearing the status and exiting the IRQ handler. Otherwise, some interrupts would be lost.

Quoted 33 lines
---
 drivers/pci/dwc/pci-dra7xx.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/pci/dwc/pci-dra7xx.c +7 -3
index 892f93910012..48c6ae535847 100644
@@ -257,7 +257,8 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
 	struct dra7xx_pcie *dra7xx = arg;
 	struct dw_pcie *pci = dra7xx->pci;
 	struct pcie_port *pp = &pci->pp;
-	u32 reg;
+	unsigned long reg;
+	u32 virq, bit;
 
 	reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI);
 
@@ -269,8 +270,11 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
 	case INTB:
 	case INTC:
 	case INTD:
-		generic_handle_irq(irq_find_mapping(dra7xx->irq_domain,
-						    ffs(reg) - 1));
+		for_each_set_bit(bit, &reg, PCI_NUM_INTX) {
+			virq = irq_find_mapping(dra7xx->irq_domain, bit);
+			if (virq)
+				generic_handle_irq(virq);
+		}
 		break;
 	}
 
#12 lore raw

Re: [PATCH v2 2/2] PCI: dra7xx: Iterate over INTx status bits

In reply to Vignesh R
Quoted 9 lines · Vignesh R

It is possible that more than one legacy IRQ may be set at the same time, therefore iterate and handle all the pending INTx interrupts before clearing the status and exiting the IRQ handler. Otherwise, some interrupts would be lost.

---
 drivers/pci/dwc/pci-dra7xx.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

Applied to pci/dwc for v4.16, thanks.

Lorenzo

Quoted 31 lines
drivers/pci/dwc/pci-dra7xx.c +7 -3
index 892f93910012..48c6ae535847 100644
@@ -257,7 +257,8 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
 	struct dra7xx_pcie *dra7xx = arg;
 	struct dw_pcie *pci = dra7xx->pci;
 	struct pcie_port *pp = &pci->pp;
-	u32 reg;
+	unsigned long reg;
+	u32 virq, bit;
 
 	reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI);
 
@@ -269,8 +270,11 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
 	case INTB:
 	case INTC:
 	case INTD:
-		generic_handle_irq(irq_find_mapping(dra7xx->irq_domain,
-						    ffs(reg) - 1));
+		for_each_set_bit(bit, &reg, PCI_NUM_INTX) {
+			virq = irq_find_mapping(dra7xx->irq_domain, bit);
+			if (virq)
+				generic_handle_irq(virq);
+		}
 		break;
 	}
 
Signature · 1 line
2.15.1