All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] PCI: mvebu: subsystem ids, AER and INTx
@ 2022-01-05 15:02 ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

This patch series extends pci-bridge-emul.c driver to emulate PCI Subsystem
Vendor ID capability and PCIe extended capabilities. And then implement
in pci-mvebu.c driver support for PCI Subsystem Vendor IDs, PCIe AER
registers, support for legacy INTx interrupts, configuration for X1/X4
mode and usage of new PCI child_ops API.

This patch series depends on other pci-mvebu and pci-bridge-emul patches from:
https://lore.kernel.org/linux-pci/20220104153529.31647-1-pali@kernel.org/

Pali Rohár (9):
  PCI: pci-bridge-emul: Add support for PCI Bridge Subsystem Vendor ID
    capability
  dt-bindings: PCI: mvebu: Add num-lanes property
  PCI: mvebu: Correctly configure x1/x4 mode
  PCI: mvebu: Add support for PCI Bridge Subsystem Vendor ID on emulated
    bridge
  PCI: mvebu: Add support for Advanced Error Reporting registers on
    emulated bridge
  PCI: mvebu: Use child_ops API
  dt-bindings: PCI: mvebu: Update information about intx interrupts
  PCI: mvebu: Implement support for legacy INTx interrupts
  ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx
    interrupts

Russell King (2):
  PCI: pci-bridge-emul: Re-arrange register tests
  PCI: pci-bridge-emul: Add support for PCIe extended capabilities

 .../devicetree/bindings/pci/mvebu-pci.txt     |  16 +
 arch/arm/boot/dts/armada-385.dtsi             |  52 ++-
 drivers/pci/controller/pci-mvebu.c            | 352 +++++++++++++++---
 drivers/pci/pci-bridge-emul.c                 | 167 ++++++---
 drivers/pci/pci-bridge-emul.h                 |  17 +
 5 files changed, 494 insertions(+), 110 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH 00/11] PCI: mvebu: subsystem ids, AER and INTx
@ 2022-01-05 15:02 ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

This patch series extends pci-bridge-emul.c driver to emulate PCI Subsystem
Vendor ID capability and PCIe extended capabilities. And then implement
in pci-mvebu.c driver support for PCI Subsystem Vendor IDs, PCIe AER
registers, support for legacy INTx interrupts, configuration for X1/X4
mode and usage of new PCI child_ops API.

This patch series depends on other pci-mvebu and pci-bridge-emul patches from:
https://lore.kernel.org/linux-pci/20220104153529.31647-1-pali@kernel.org/

Pali Rohár (9):
  PCI: pci-bridge-emul: Add support for PCI Bridge Subsystem Vendor ID
    capability
  dt-bindings: PCI: mvebu: Add num-lanes property
  PCI: mvebu: Correctly configure x1/x4 mode
  PCI: mvebu: Add support for PCI Bridge Subsystem Vendor ID on emulated
    bridge
  PCI: mvebu: Add support for Advanced Error Reporting registers on
    emulated bridge
  PCI: mvebu: Use child_ops API
  dt-bindings: PCI: mvebu: Update information about intx interrupts
  PCI: mvebu: Implement support for legacy INTx interrupts
  ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx
    interrupts

Russell King (2):
  PCI: pci-bridge-emul: Re-arrange register tests
  PCI: pci-bridge-emul: Add support for PCIe extended capabilities

 .../devicetree/bindings/pci/mvebu-pci.txt     |  16 +
 arch/arm/boot/dts/armada-385.dtsi             |  52 ++-
 drivers/pci/controller/pci-mvebu.c            | 352 +++++++++++++++---
 drivers/pci/pci-bridge-emul.c                 | 167 ++++++---
 drivers/pci/pci-bridge-emul.h                 |  17 +
 5 files changed, 494 insertions(+), 110 deletions(-)

-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH 01/11] PCI: pci-bridge-emul: Re-arrange register tests
  2022-01-05 15:02 ` Pali Rohár
@ 2022-01-05 15:02   ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

From: Russell King <rmk+kernel@armlinux.org.uk>

Re-arrange the tests for which sets of registers are being accessed so that
it is easier to add further regions later. No functional change.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
[pali: Fix reading old value in pci_bridge_emul_conf_write]
Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/pci-bridge-emul.c | 61 ++++++++++++++++++-----------------
 1 file changed, 31 insertions(+), 30 deletions(-)

diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c
index 033bbeb99176..56b2cb741498 100644
--- a/drivers/pci/pci-bridge-emul.c
+++ b/drivers/pci/pci-bridge-emul.c
@@ -418,25 +418,25 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
 	__le32 *cfgspace;
 	const struct pci_bridge_reg_behavior *behavior;
 
-	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_END) {
-		*value = 0;
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	if (!bridge->has_pcie && reg >= PCI_BRIDGE_CONF_END) {
+	if (reg < PCI_BRIDGE_CONF_END) {
+		/* Emulated PCI space */
+		read_op = bridge->ops->read_base;
+		cfgspace = (__le32 *) &bridge->conf;
+		behavior = bridge->pci_regs_behavior;
+	} else if (!bridge->has_pcie) {
+		/* PCIe space is not implemented, and no PCI capabilities */
 		*value = 0;
 		return PCIBIOS_SUCCESSFUL;
-	}
-
-	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_START) {
+	} else if (reg < PCI_CAP_PCIE_END) {
+		/* Our emulated PCIe capability */
 		reg -= PCI_CAP_PCIE_START;
 		read_op = bridge->ops->read_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
 	} else {
-		read_op = bridge->ops->read_base;
-		cfgspace = (__le32 *) &bridge->conf;
-		behavior = bridge->pci_regs_behavior;
+		/* Beyond our PCIe space */
+		*value = 0;
+		return PCIBIOS_SUCCESSFUL;
 	}
 
 	if (read_op)
@@ -480,11 +480,27 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 	__le32 *cfgspace;
 	const struct pci_bridge_reg_behavior *behavior;
 
-	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_END)
-		return PCIBIOS_SUCCESSFUL;
+	ret = pci_bridge_emul_conf_read(bridge, reg, 4, &old);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		return ret;
 
-	if (!bridge->has_pcie && reg >= PCI_BRIDGE_CONF_END)
+	if (reg < PCI_BRIDGE_CONF_END) {
+		/* Emulated PCI space */
+		write_op = bridge->ops->write_base;
+		cfgspace = (__le32 *) &bridge->conf;
+		behavior = bridge->pci_regs_behavior;
+	} else if (!bridge->has_pcie) {
+		/* PCIe space is not implemented, and no PCI capabilities */
 		return PCIBIOS_SUCCESSFUL;
+	} else if (reg < PCI_CAP_PCIE_END) {
+		/* Our emulated PCIe capability */
+		reg -= PCI_CAP_PCIE_START;
+		write_op = bridge->ops->write_pcie;
+		cfgspace = (__le32 *) &bridge->pcie_conf;
+		behavior = bridge->pcie_cap_regs_behavior;
+	} else {
+		return PCIBIOS_SUCCESSFUL;
+	}
 
 	shift = (where & 0x3) * 8;
 
@@ -497,21 +513,6 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 	else
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
-	ret = pci_bridge_emul_conf_read(bridge, reg, 4, &old);
-	if (ret != PCIBIOS_SUCCESSFUL)
-		return ret;
-
-	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_START) {
-		reg -= PCI_CAP_PCIE_START;
-		write_op = bridge->ops->write_pcie;
-		cfgspace = (__le32 *) &bridge->pcie_conf;
-		behavior = bridge->pcie_cap_regs_behavior;
-	} else {
-		write_op = bridge->ops->write_base;
-		cfgspace = (__le32 *) &bridge->conf;
-		behavior = bridge->pci_regs_behavior;
-	}
-
 	/* Keep all bits, except the RW bits */
 	new = old & (~mask | ~behavior[reg / 4].rw);
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 01/11] PCI: pci-bridge-emul: Re-arrange register tests
@ 2022-01-05 15:02   ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

From: Russell King <rmk+kernel@armlinux.org.uk>

Re-arrange the tests for which sets of registers are being accessed so that
it is easier to add further regions later. No functional change.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
[pali: Fix reading old value in pci_bridge_emul_conf_write]
Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/pci-bridge-emul.c | 61 ++++++++++++++++++-----------------
 1 file changed, 31 insertions(+), 30 deletions(-)

diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c
index 033bbeb99176..56b2cb741498 100644
--- a/drivers/pci/pci-bridge-emul.c
+++ b/drivers/pci/pci-bridge-emul.c
@@ -418,25 +418,25 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
 	__le32 *cfgspace;
 	const struct pci_bridge_reg_behavior *behavior;
 
-	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_END) {
-		*value = 0;
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	if (!bridge->has_pcie && reg >= PCI_BRIDGE_CONF_END) {
+	if (reg < PCI_BRIDGE_CONF_END) {
+		/* Emulated PCI space */
+		read_op = bridge->ops->read_base;
+		cfgspace = (__le32 *) &bridge->conf;
+		behavior = bridge->pci_regs_behavior;
+	} else if (!bridge->has_pcie) {
+		/* PCIe space is not implemented, and no PCI capabilities */
 		*value = 0;
 		return PCIBIOS_SUCCESSFUL;
-	}
-
-	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_START) {
+	} else if (reg < PCI_CAP_PCIE_END) {
+		/* Our emulated PCIe capability */
 		reg -= PCI_CAP_PCIE_START;
 		read_op = bridge->ops->read_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
 	} else {
-		read_op = bridge->ops->read_base;
-		cfgspace = (__le32 *) &bridge->conf;
-		behavior = bridge->pci_regs_behavior;
+		/* Beyond our PCIe space */
+		*value = 0;
+		return PCIBIOS_SUCCESSFUL;
 	}
 
 	if (read_op)
@@ -480,11 +480,27 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 	__le32 *cfgspace;
 	const struct pci_bridge_reg_behavior *behavior;
 
-	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_END)
-		return PCIBIOS_SUCCESSFUL;
+	ret = pci_bridge_emul_conf_read(bridge, reg, 4, &old);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		return ret;
 
-	if (!bridge->has_pcie && reg >= PCI_BRIDGE_CONF_END)
+	if (reg < PCI_BRIDGE_CONF_END) {
+		/* Emulated PCI space */
+		write_op = bridge->ops->write_base;
+		cfgspace = (__le32 *) &bridge->conf;
+		behavior = bridge->pci_regs_behavior;
+	} else if (!bridge->has_pcie) {
+		/* PCIe space is not implemented, and no PCI capabilities */
 		return PCIBIOS_SUCCESSFUL;
+	} else if (reg < PCI_CAP_PCIE_END) {
+		/* Our emulated PCIe capability */
+		reg -= PCI_CAP_PCIE_START;
+		write_op = bridge->ops->write_pcie;
+		cfgspace = (__le32 *) &bridge->pcie_conf;
+		behavior = bridge->pcie_cap_regs_behavior;
+	} else {
+		return PCIBIOS_SUCCESSFUL;
+	}
 
 	shift = (where & 0x3) * 8;
 
@@ -497,21 +513,6 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 	else
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
-	ret = pci_bridge_emul_conf_read(bridge, reg, 4, &old);
-	if (ret != PCIBIOS_SUCCESSFUL)
-		return ret;
-
-	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_START) {
-		reg -= PCI_CAP_PCIE_START;
-		write_op = bridge->ops->write_pcie;
-		cfgspace = (__le32 *) &bridge->pcie_conf;
-		behavior = bridge->pcie_cap_regs_behavior;
-	} else {
-		write_op = bridge->ops->write_base;
-		cfgspace = (__le32 *) &bridge->conf;
-		behavior = bridge->pci_regs_behavior;
-	}
-
 	/* Keep all bits, except the RW bits */
 	new = old & (~mask | ~behavior[reg / 4].rw);
 
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 02/11] PCI: pci-bridge-emul: Add support for PCIe extended capabilities
  2022-01-05 15:02 ` Pali Rohár
@ 2022-01-05 15:02   ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

From: Russell King <rmk+kernel@armlinux.org.uk>

Add support for PCIe extended capabilities, which we just redirect to the
emulating driver.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
[pali: Fix writing new value with W1C bits]
Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/pci-bridge-emul.c | 77 +++++++++++++++++++++++------------
 drivers/pci/pci-bridge-emul.h | 15 +++++++
 2 files changed, 67 insertions(+), 25 deletions(-)

diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c
index 56b2cb741498..9f4f173f0650 100644
--- a/drivers/pci/pci-bridge-emul.c
+++ b/drivers/pci/pci-bridge-emul.c
@@ -433,10 +433,16 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
 		read_op = bridge->ops->read_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
-	} else {
-		/* Beyond our PCIe space */
+	} else if (reg < PCI_CFG_SPACE_SIZE) {
+		/* Rest of PCI space not implemented */
 		*value = 0;
 		return PCIBIOS_SUCCESSFUL;
+	} else {
+		/* PCIe extended capability space */
+		reg -= PCI_CFG_SPACE_SIZE;
+		read_op = bridge->ops->read_ext;
+		cfgspace = NULL;
+		behavior = NULL;
 	}
 
 	if (read_op)
@@ -444,15 +450,20 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
 	else
 		ret = PCI_BRIDGE_EMUL_NOT_HANDLED;
 
-	if (ret == PCI_BRIDGE_EMUL_NOT_HANDLED)
-		*value = le32_to_cpu(cfgspace[reg / 4]);
+	if (ret == PCI_BRIDGE_EMUL_NOT_HANDLED) {
+		if (cfgspace)
+			*value = le32_to_cpu(cfgspace[reg / 4]);
+		else
+			*value = 0;
+	}
 
 	/*
 	 * Make sure we never return any reserved bit with a value
 	 * different from 0.
 	 */
-	*value &= behavior[reg / 4].ro | behavior[reg / 4].rw |
-		  behavior[reg / 4].w1c;
+	if (behavior)
+		*value &= behavior[reg / 4].ro | behavior[reg / 4].rw |
+			  behavior[reg / 4].w1c;
 
 	if (size == 1)
 		*value = (*value >> (8 * (where & 3))) & 0xff;
@@ -498,8 +509,15 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 		write_op = bridge->ops->write_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
-	} else {
+	} else if (reg < PCI_CFG_SPACE_SIZE) {
+		/* Rest of PCI space not implemented */
 		return PCIBIOS_SUCCESSFUL;
+	} else {
+		/* PCIe extended capability space */
+		reg -= PCI_CFG_SPACE_SIZE;
+		write_op = bridge->ops->write_ext;
+		cfgspace = NULL;
+		behavior = NULL;
 	}
 
 	shift = (where & 0x3) * 8;
@@ -513,29 +531,38 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 	else
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
-	/* Keep all bits, except the RW bits */
-	new = old & (~mask | ~behavior[reg / 4].rw);
+	if (behavior) {
+		/* Keep all bits, except the RW bits */
+		new = old & (~mask | ~behavior[reg / 4].rw);
 
-	/* Update the value of the RW bits */
-	new |= (value << shift) & (behavior[reg / 4].rw & mask);
+		/* Update the value of the RW bits */
+		new |= (value << shift) & (behavior[reg / 4].rw & mask);
 
-	/* Clear the W1C bits */
-	new &= ~((value << shift) & (behavior[reg / 4].w1c & mask));
+		/* Clear the W1C bits */
+		new &= ~((value << shift) & (behavior[reg / 4].w1c & mask));
+	} else {
+		new = old & ~mask;
+		new |= (value << shift) & mask;
+	}
 
-	/* Save the new value with the cleared W1C bits into the cfgspace */
-	cfgspace[reg / 4] = cpu_to_le32(new);
+	if (cfgspace) {
+		/* Save the new value with the cleared W1C bits into the cfgspace */
+		cfgspace[reg / 4] = cpu_to_le32(new);
+	}
 
-	/*
-	 * Clear the W1C bits not specified by the write mask, so that the
-	 * write_op() does not clear them.
-	 */
-	new &= ~(behavior[reg / 4].w1c & ~mask);
+	if (behavior) {
+		/*
+		 * Clear the W1C bits not specified by the write mask, so that the
+		 * write_op() does not clear them.
+		 */
+		new &= ~(behavior[reg / 4].w1c & ~mask);
 
-	/*
-	 * Set the W1C bits specified by the write mask, so that write_op()
-	 * knows about that they are to be cleared.
-	 */
-	new |= (value << shift) & (behavior[reg / 4].w1c & mask);
+		/*
+		 * Set the W1C bits specified by the write mask, so that write_op()
+		 * knows about that they are to be cleared.
+		 */
+		new |= (value << shift) & (behavior[reg / 4].w1c & mask);
+	}
 
 	if (write_op)
 		write_op(bridge, reg, old, new, mask);
diff --git a/drivers/pci/pci-bridge-emul.h b/drivers/pci/pci-bridge-emul.h
index 4953274cac18..6b5f75b2ad02 100644
--- a/drivers/pci/pci-bridge-emul.h
+++ b/drivers/pci/pci-bridge-emul.h
@@ -90,6 +90,14 @@ struct pci_bridge_emul_ops {
 	 */
 	pci_bridge_emul_read_status_t (*read_pcie)(struct pci_bridge_emul *bridge,
 						   int reg, u32 *value);
+
+	/*
+	 * Same as ->read_base(), except it is for reading from the
+	 * PCIe extended capability configuration space.
+	 */
+	pci_bridge_emul_read_status_t (*read_ext)(struct pci_bridge_emul *bridge,
+						  int reg, u32 *value);
+
 	/*
 	 * Called when writing to the regular PCI bridge configuration
 	 * space. old is the current value, new is the new value being
@@ -105,6 +113,13 @@ struct pci_bridge_emul_ops {
 	 */
 	void (*write_pcie)(struct pci_bridge_emul *bridge, int reg,
 			   u32 old, u32 new, u32 mask);
+
+	/*
+	 * Same as ->write_base(), except it is for writing from the
+	 * PCIe extended capability configuration space.
+	 */
+	void (*write_ext)(struct pci_bridge_emul *bridge, int reg,
+			  u32 old, u32 new, u32 mask);
 };
 
 struct pci_bridge_reg_behavior;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 02/11] PCI: pci-bridge-emul: Add support for PCIe extended capabilities
@ 2022-01-05 15:02   ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

From: Russell King <rmk+kernel@armlinux.org.uk>

Add support for PCIe extended capabilities, which we just redirect to the
emulating driver.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
[pali: Fix writing new value with W1C bits]
Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/pci-bridge-emul.c | 77 +++++++++++++++++++++++------------
 drivers/pci/pci-bridge-emul.h | 15 +++++++
 2 files changed, 67 insertions(+), 25 deletions(-)

diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c
index 56b2cb741498..9f4f173f0650 100644
--- a/drivers/pci/pci-bridge-emul.c
+++ b/drivers/pci/pci-bridge-emul.c
@@ -433,10 +433,16 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
 		read_op = bridge->ops->read_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
-	} else {
-		/* Beyond our PCIe space */
+	} else if (reg < PCI_CFG_SPACE_SIZE) {
+		/* Rest of PCI space not implemented */
 		*value = 0;
 		return PCIBIOS_SUCCESSFUL;
+	} else {
+		/* PCIe extended capability space */
+		reg -= PCI_CFG_SPACE_SIZE;
+		read_op = bridge->ops->read_ext;
+		cfgspace = NULL;
+		behavior = NULL;
 	}
 
 	if (read_op)
@@ -444,15 +450,20 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
 	else
 		ret = PCI_BRIDGE_EMUL_NOT_HANDLED;
 
-	if (ret == PCI_BRIDGE_EMUL_NOT_HANDLED)
-		*value = le32_to_cpu(cfgspace[reg / 4]);
+	if (ret == PCI_BRIDGE_EMUL_NOT_HANDLED) {
+		if (cfgspace)
+			*value = le32_to_cpu(cfgspace[reg / 4]);
+		else
+			*value = 0;
+	}
 
 	/*
 	 * Make sure we never return any reserved bit with a value
 	 * different from 0.
 	 */
-	*value &= behavior[reg / 4].ro | behavior[reg / 4].rw |
-		  behavior[reg / 4].w1c;
+	if (behavior)
+		*value &= behavior[reg / 4].ro | behavior[reg / 4].rw |
+			  behavior[reg / 4].w1c;
 
 	if (size == 1)
 		*value = (*value >> (8 * (where & 3))) & 0xff;
@@ -498,8 +509,15 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 		write_op = bridge->ops->write_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
-	} else {
+	} else if (reg < PCI_CFG_SPACE_SIZE) {
+		/* Rest of PCI space not implemented */
 		return PCIBIOS_SUCCESSFUL;
+	} else {
+		/* PCIe extended capability space */
+		reg -= PCI_CFG_SPACE_SIZE;
+		write_op = bridge->ops->write_ext;
+		cfgspace = NULL;
+		behavior = NULL;
 	}
 
 	shift = (where & 0x3) * 8;
@@ -513,29 +531,38 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 	else
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
-	/* Keep all bits, except the RW bits */
-	new = old & (~mask | ~behavior[reg / 4].rw);
+	if (behavior) {
+		/* Keep all bits, except the RW bits */
+		new = old & (~mask | ~behavior[reg / 4].rw);
 
-	/* Update the value of the RW bits */
-	new |= (value << shift) & (behavior[reg / 4].rw & mask);
+		/* Update the value of the RW bits */
+		new |= (value << shift) & (behavior[reg / 4].rw & mask);
 
-	/* Clear the W1C bits */
-	new &= ~((value << shift) & (behavior[reg / 4].w1c & mask));
+		/* Clear the W1C bits */
+		new &= ~((value << shift) & (behavior[reg / 4].w1c & mask));
+	} else {
+		new = old & ~mask;
+		new |= (value << shift) & mask;
+	}
 
-	/* Save the new value with the cleared W1C bits into the cfgspace */
-	cfgspace[reg / 4] = cpu_to_le32(new);
+	if (cfgspace) {
+		/* Save the new value with the cleared W1C bits into the cfgspace */
+		cfgspace[reg / 4] = cpu_to_le32(new);
+	}
 
-	/*
-	 * Clear the W1C bits not specified by the write mask, so that the
-	 * write_op() does not clear them.
-	 */
-	new &= ~(behavior[reg / 4].w1c & ~mask);
+	if (behavior) {
+		/*
+		 * Clear the W1C bits not specified by the write mask, so that the
+		 * write_op() does not clear them.
+		 */
+		new &= ~(behavior[reg / 4].w1c & ~mask);
 
-	/*
-	 * Set the W1C bits specified by the write mask, so that write_op()
-	 * knows about that they are to be cleared.
-	 */
-	new |= (value << shift) & (behavior[reg / 4].w1c & mask);
+		/*
+		 * Set the W1C bits specified by the write mask, so that write_op()
+		 * knows about that they are to be cleared.
+		 */
+		new |= (value << shift) & (behavior[reg / 4].w1c & mask);
+	}
 
 	if (write_op)
 		write_op(bridge, reg, old, new, mask);
diff --git a/drivers/pci/pci-bridge-emul.h b/drivers/pci/pci-bridge-emul.h
index 4953274cac18..6b5f75b2ad02 100644
--- a/drivers/pci/pci-bridge-emul.h
+++ b/drivers/pci/pci-bridge-emul.h
@@ -90,6 +90,14 @@ struct pci_bridge_emul_ops {
 	 */
 	pci_bridge_emul_read_status_t (*read_pcie)(struct pci_bridge_emul *bridge,
 						   int reg, u32 *value);
+
+	/*
+	 * Same as ->read_base(), except it is for reading from the
+	 * PCIe extended capability configuration space.
+	 */
+	pci_bridge_emul_read_status_t (*read_ext)(struct pci_bridge_emul *bridge,
+						  int reg, u32 *value);
+
 	/*
 	 * Called when writing to the regular PCI bridge configuration
 	 * space. old is the current value, new is the new value being
@@ -105,6 +113,13 @@ struct pci_bridge_emul_ops {
 	 */
 	void (*write_pcie)(struct pci_bridge_emul *bridge, int reg,
 			   u32 old, u32 new, u32 mask);
+
+	/*
+	 * Same as ->write_base(), except it is for writing from the
+	 * PCIe extended capability configuration space.
+	 */
+	void (*write_ext)(struct pci_bridge_emul *bridge, int reg,
+			  u32 old, u32 new, u32 mask);
 };
 
 struct pci_bridge_reg_behavior;
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 03/11] PCI: pci-bridge-emul: Add support for PCI Bridge Subsystem Vendor ID capability
  2022-01-05 15:02 ` Pali Rohár
@ 2022-01-05 15:02   ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

This is read-only capability in PCI config space. Put it between base PCI
capability and base PCI Express capability.

Driver just have to specify subsystem_vendor_id and subsystem_id fields in
emulated bridge structure and pci-bridge-emul takes care of correctly
compose PCI Bridge Subsystem Vendor ID capability.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/pci-bridge-emul.c | 69 +++++++++++++++++++++++++----------
 drivers/pci/pci-bridge-emul.h |  2 +
 2 files changed, 51 insertions(+), 20 deletions(-)

diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c
index 9f4f173f0650..c84f423a5893 100644
--- a/drivers/pci/pci-bridge-emul.c
+++ b/drivers/pci/pci-bridge-emul.c
@@ -21,8 +21,11 @@
 #include "pci-bridge-emul.h"
 
 #define PCI_BRIDGE_CONF_END	PCI_STD_HEADER_SIZEOF
+#define PCI_CAP_SSID_SIZEOF	(PCI_SSVID_DEVICE_ID + 2)
+#define PCI_CAP_SSID_START	PCI_BRIDGE_CONF_END
+#define PCI_CAP_SSID_END	(PCI_CAP_SSID_START + PCI_CAP_SSID_SIZEOF)
 #define PCI_CAP_PCIE_SIZEOF	(PCI_EXP_SLTSTA2 + 2)
-#define PCI_CAP_PCIE_START	PCI_BRIDGE_CONF_END
+#define PCI_CAP_PCIE_START	PCI_CAP_SSID_END
 #define PCI_CAP_PCIE_END	(PCI_CAP_PCIE_START + PCI_CAP_PCIE_SIZEOF)
 
 /**
@@ -315,6 +318,25 @@ struct pci_bridge_reg_behavior pcie_cap_regs_behavior[PCI_CAP_PCIE_SIZEOF / 4] =
 	},
 };
 
+static pci_bridge_emul_read_status_t
+pci_bridge_emul_read_ssid(struct pci_bridge_emul *bridge, int reg, u32 *value)
+{
+	switch (reg) {
+	case PCI_CAP_LIST_ID:
+		*value = PCI_CAP_ID_SSVID |
+			(bridge->has_pcie ? (PCI_CAP_PCIE_START << 8) : 0);
+		return PCI_BRIDGE_EMUL_HANDLED;
+
+	case PCI_SSVID_VENDOR_ID:
+		*value = bridge->subsystem_vendor_id |
+			(bridge->subsystem_id << 16);
+		return PCI_BRIDGE_EMUL_HANDLED;
+
+	default:
+		return PCI_BRIDGE_EMUL_NOT_HANDLED;
+	}
+}
+
 /*
  * Initialize a pci_bridge_emul structure to represent a fake PCI
  * bridge configuration space. The caller needs to have initialized
@@ -337,9 +359,17 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
 	if (!bridge->pci_regs_behavior)
 		return -ENOMEM;
 
-	if (bridge->has_pcie) {
+	if (bridge->subsystem_vendor_id)
+		bridge->conf.capabilities_pointer = PCI_CAP_SSID_START;
+	else if (bridge->has_pcie)
 		bridge->conf.capabilities_pointer = PCI_CAP_PCIE_START;
+	else
+		bridge->conf.capabilities_pointer = 0;
+
+	if (bridge->conf.capabilities_pointer)
 		bridge->conf.status |= cpu_to_le16(PCI_STATUS_CAP_LIST);
+
+	if (bridge->has_pcie) {
 		bridge->pcie_conf.cap_id = PCI_CAP_ID_EXP;
 		bridge->pcie_conf.cap |= cpu_to_le16(PCI_EXP_TYPE_ROOT_PORT << 4);
 		bridge->pcie_cap_regs_behavior =
@@ -423,26 +453,28 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
 		read_op = bridge->ops->read_base;
 		cfgspace = (__le32 *) &bridge->conf;
 		behavior = bridge->pci_regs_behavior;
-	} else if (!bridge->has_pcie) {
-		/* PCIe space is not implemented, and no PCI capabilities */
-		*value = 0;
-		return PCIBIOS_SUCCESSFUL;
-	} else if (reg < PCI_CAP_PCIE_END) {
+	} else if (reg >= PCI_CAP_SSID_START && reg < PCI_CAP_SSID_END && bridge->subsystem_vendor_id) {
+		/* Emulated PCI Bridge Subsystem Vendor ID capability */
+		reg -= PCI_CAP_SSID_START;
+		read_op = pci_bridge_emul_read_ssid;
+		cfgspace = NULL;
+		behavior = NULL;
+	} else if (reg >= PCI_CAP_PCIE_START && reg < PCI_CAP_PCIE_END && bridge->has_pcie) {
 		/* Our emulated PCIe capability */
 		reg -= PCI_CAP_PCIE_START;
 		read_op = bridge->ops->read_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
-	} else if (reg < PCI_CFG_SPACE_SIZE) {
-		/* Rest of PCI space not implemented */
-		*value = 0;
-		return PCIBIOS_SUCCESSFUL;
-	} else {
+	} else if (reg >= PCI_CFG_SPACE_SIZE && bridge->has_pcie) {
 		/* PCIe extended capability space */
 		reg -= PCI_CFG_SPACE_SIZE;
 		read_op = bridge->ops->read_ext;
 		cfgspace = NULL;
 		behavior = NULL;
+	} else {
+		/* Not implemented */
+		*value = 0;
+		return PCIBIOS_SUCCESSFUL;
 	}
 
 	if (read_op)
@@ -500,24 +532,21 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 		write_op = bridge->ops->write_base;
 		cfgspace = (__le32 *) &bridge->conf;
 		behavior = bridge->pci_regs_behavior;
-	} else if (!bridge->has_pcie) {
-		/* PCIe space is not implemented, and no PCI capabilities */
-		return PCIBIOS_SUCCESSFUL;
-	} else if (reg < PCI_CAP_PCIE_END) {
+	} else if (reg >= PCI_CAP_PCIE_START && reg < PCI_CAP_PCIE_END && bridge->has_pcie) {
 		/* Our emulated PCIe capability */
 		reg -= PCI_CAP_PCIE_START;
 		write_op = bridge->ops->write_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
-	} else if (reg < PCI_CFG_SPACE_SIZE) {
-		/* Rest of PCI space not implemented */
-		return PCIBIOS_SUCCESSFUL;
-	} else {
+	} else if (reg >= PCI_CFG_SPACE_SIZE && bridge->has_pcie) {
 		/* PCIe extended capability space */
 		reg -= PCI_CFG_SPACE_SIZE;
 		write_op = bridge->ops->write_ext;
 		cfgspace = NULL;
 		behavior = NULL;
+	} else {
+		/* Not implemented */
+		return PCIBIOS_SUCCESSFUL;
 	}
 
 	shift = (where & 0x3) * 8;
diff --git a/drivers/pci/pci-bridge-emul.h b/drivers/pci/pci-bridge-emul.h
index 6b5f75b2ad02..71392b67471d 100644
--- a/drivers/pci/pci-bridge-emul.h
+++ b/drivers/pci/pci-bridge-emul.h
@@ -132,6 +132,8 @@ struct pci_bridge_emul {
 	struct pci_bridge_reg_behavior *pcie_cap_regs_behavior;
 	void *data;
 	bool has_pcie;
+	u16 subsystem_vendor_id;
+	u16 subsystem_id;
 };
 
 enum {
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 03/11] PCI: pci-bridge-emul: Add support for PCI Bridge Subsystem Vendor ID capability
@ 2022-01-05 15:02   ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

This is read-only capability in PCI config space. Put it between base PCI
capability and base PCI Express capability.

Driver just have to specify subsystem_vendor_id and subsystem_id fields in
emulated bridge structure and pci-bridge-emul takes care of correctly
compose PCI Bridge Subsystem Vendor ID capability.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/pci-bridge-emul.c | 69 +++++++++++++++++++++++++----------
 drivers/pci/pci-bridge-emul.h |  2 +
 2 files changed, 51 insertions(+), 20 deletions(-)

diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c
index 9f4f173f0650..c84f423a5893 100644
--- a/drivers/pci/pci-bridge-emul.c
+++ b/drivers/pci/pci-bridge-emul.c
@@ -21,8 +21,11 @@
 #include "pci-bridge-emul.h"
 
 #define PCI_BRIDGE_CONF_END	PCI_STD_HEADER_SIZEOF
+#define PCI_CAP_SSID_SIZEOF	(PCI_SSVID_DEVICE_ID + 2)
+#define PCI_CAP_SSID_START	PCI_BRIDGE_CONF_END
+#define PCI_CAP_SSID_END	(PCI_CAP_SSID_START + PCI_CAP_SSID_SIZEOF)
 #define PCI_CAP_PCIE_SIZEOF	(PCI_EXP_SLTSTA2 + 2)
-#define PCI_CAP_PCIE_START	PCI_BRIDGE_CONF_END
+#define PCI_CAP_PCIE_START	PCI_CAP_SSID_END
 #define PCI_CAP_PCIE_END	(PCI_CAP_PCIE_START + PCI_CAP_PCIE_SIZEOF)
 
 /**
@@ -315,6 +318,25 @@ struct pci_bridge_reg_behavior pcie_cap_regs_behavior[PCI_CAP_PCIE_SIZEOF / 4] =
 	},
 };
 
+static pci_bridge_emul_read_status_t
+pci_bridge_emul_read_ssid(struct pci_bridge_emul *bridge, int reg, u32 *value)
+{
+	switch (reg) {
+	case PCI_CAP_LIST_ID:
+		*value = PCI_CAP_ID_SSVID |
+			(bridge->has_pcie ? (PCI_CAP_PCIE_START << 8) : 0);
+		return PCI_BRIDGE_EMUL_HANDLED;
+
+	case PCI_SSVID_VENDOR_ID:
+		*value = bridge->subsystem_vendor_id |
+			(bridge->subsystem_id << 16);
+		return PCI_BRIDGE_EMUL_HANDLED;
+
+	default:
+		return PCI_BRIDGE_EMUL_NOT_HANDLED;
+	}
+}
+
 /*
  * Initialize a pci_bridge_emul structure to represent a fake PCI
  * bridge configuration space. The caller needs to have initialized
@@ -337,9 +359,17 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
 	if (!bridge->pci_regs_behavior)
 		return -ENOMEM;
 
-	if (bridge->has_pcie) {
+	if (bridge->subsystem_vendor_id)
+		bridge->conf.capabilities_pointer = PCI_CAP_SSID_START;
+	else if (bridge->has_pcie)
 		bridge->conf.capabilities_pointer = PCI_CAP_PCIE_START;
+	else
+		bridge->conf.capabilities_pointer = 0;
+
+	if (bridge->conf.capabilities_pointer)
 		bridge->conf.status |= cpu_to_le16(PCI_STATUS_CAP_LIST);
+
+	if (bridge->has_pcie) {
 		bridge->pcie_conf.cap_id = PCI_CAP_ID_EXP;
 		bridge->pcie_conf.cap |= cpu_to_le16(PCI_EXP_TYPE_ROOT_PORT << 4);
 		bridge->pcie_cap_regs_behavior =
@@ -423,26 +453,28 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
 		read_op = bridge->ops->read_base;
 		cfgspace = (__le32 *) &bridge->conf;
 		behavior = bridge->pci_regs_behavior;
-	} else if (!bridge->has_pcie) {
-		/* PCIe space is not implemented, and no PCI capabilities */
-		*value = 0;
-		return PCIBIOS_SUCCESSFUL;
-	} else if (reg < PCI_CAP_PCIE_END) {
+	} else if (reg >= PCI_CAP_SSID_START && reg < PCI_CAP_SSID_END && bridge->subsystem_vendor_id) {
+		/* Emulated PCI Bridge Subsystem Vendor ID capability */
+		reg -= PCI_CAP_SSID_START;
+		read_op = pci_bridge_emul_read_ssid;
+		cfgspace = NULL;
+		behavior = NULL;
+	} else if (reg >= PCI_CAP_PCIE_START && reg < PCI_CAP_PCIE_END && bridge->has_pcie) {
 		/* Our emulated PCIe capability */
 		reg -= PCI_CAP_PCIE_START;
 		read_op = bridge->ops->read_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
-	} else if (reg < PCI_CFG_SPACE_SIZE) {
-		/* Rest of PCI space not implemented */
-		*value = 0;
-		return PCIBIOS_SUCCESSFUL;
-	} else {
+	} else if (reg >= PCI_CFG_SPACE_SIZE && bridge->has_pcie) {
 		/* PCIe extended capability space */
 		reg -= PCI_CFG_SPACE_SIZE;
 		read_op = bridge->ops->read_ext;
 		cfgspace = NULL;
 		behavior = NULL;
+	} else {
+		/* Not implemented */
+		*value = 0;
+		return PCIBIOS_SUCCESSFUL;
 	}
 
 	if (read_op)
@@ -500,24 +532,21 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 		write_op = bridge->ops->write_base;
 		cfgspace = (__le32 *) &bridge->conf;
 		behavior = bridge->pci_regs_behavior;
-	} else if (!bridge->has_pcie) {
-		/* PCIe space is not implemented, and no PCI capabilities */
-		return PCIBIOS_SUCCESSFUL;
-	} else if (reg < PCI_CAP_PCIE_END) {
+	} else if (reg >= PCI_CAP_PCIE_START && reg < PCI_CAP_PCIE_END && bridge->has_pcie) {
 		/* Our emulated PCIe capability */
 		reg -= PCI_CAP_PCIE_START;
 		write_op = bridge->ops->write_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
-	} else if (reg < PCI_CFG_SPACE_SIZE) {
-		/* Rest of PCI space not implemented */
-		return PCIBIOS_SUCCESSFUL;
-	} else {
+	} else if (reg >= PCI_CFG_SPACE_SIZE && bridge->has_pcie) {
 		/* PCIe extended capability space */
 		reg -= PCI_CFG_SPACE_SIZE;
 		write_op = bridge->ops->write_ext;
 		cfgspace = NULL;
 		behavior = NULL;
+	} else {
+		/* Not implemented */
+		return PCIBIOS_SUCCESSFUL;
 	}
 
 	shift = (where & 0x3) * 8;
diff --git a/drivers/pci/pci-bridge-emul.h b/drivers/pci/pci-bridge-emul.h
index 6b5f75b2ad02..71392b67471d 100644
--- a/drivers/pci/pci-bridge-emul.h
+++ b/drivers/pci/pci-bridge-emul.h
@@ -132,6 +132,8 @@ struct pci_bridge_emul {
 	struct pci_bridge_reg_behavior *pcie_cap_regs_behavior;
 	void *data;
 	bool has_pcie;
+	u16 subsystem_vendor_id;
+	u16 subsystem_id;
 };
 
 enum {
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 04/11] dt-bindings: PCI: mvebu: Add num-lanes property
  2022-01-05 15:02 ` Pali Rohár
@ 2022-01-05 15:02   ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Andrew Lunn, Gregory Clement
  Cc: linux-pci, linux-kernel, linux-arm-kernel, devicetree

Controller driver needs to correctly configure PCIe link if it contains 1
or 4 SerDes PCIe lanes. Therefore add a new 'num-lanes' DT property for
mvebu PCIe controller. Property 'num-lanes' seems to be de-facto standard
way how number of lanes is specified in other PCIe controllers.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 Documentation/devicetree/bindings/pci/mvebu-pci.txt | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/mvebu-pci.txt b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
index 6173af6885f8..24225852bce0 100644
--- a/Documentation/devicetree/bindings/pci/mvebu-pci.txt
+++ b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
@@ -77,6 +77,7 @@ and the following optional properties:
 - marvell,pcie-lane: the physical PCIe lane number, for ports having
   multiple lanes. If this property is not found, we assume that the
   value is 0.
+- num-lanes: number of SerDes PCIe lanes for this link (1 or 4)
 - reset-gpios: optional GPIO to PERST#
 - reset-delay-us: delay in us to wait after reset de-assertion, if not
   specified will default to 100ms, as required by the PCIe specification.
@@ -141,6 +142,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 58>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <0>;
+		num-lanes = <1>;
 		/* low-active PERST# reset on GPIO 25 */
 		reset-gpios = <&gpio0 25 1>;
 		/* wait 20ms for device settle after reset deassertion */
@@ -161,6 +163,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 59>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <1>;
+		num-lanes = <1>;
 		clocks = <&gateclk 6>;
 	};
 
@@ -177,6 +180,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 60>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <2>;
+		num-lanes = <1>;
 		clocks = <&gateclk 7>;
 	};
 
@@ -193,6 +197,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 61>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <3>;
+		num-lanes = <1>;
 		clocks = <&gateclk 8>;
 	};
 
@@ -209,6 +214,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 62>;
 		marvell,pcie-port = <1>;
 		marvell,pcie-lane = <0>;
+		num-lanes = <1>;
 		clocks = <&gateclk 9>;
 	};
 
@@ -225,6 +231,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 63>;
 		marvell,pcie-port = <1>;
 		marvell,pcie-lane = <1>;
+		num-lanes = <1>;
 		clocks = <&gateclk 10>;
 	};
 
@@ -241,6 +248,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 64>;
 		marvell,pcie-port = <1>;
 		marvell,pcie-lane = <2>;
+		num-lanes = <1>;
 		clocks = <&gateclk 11>;
 	};
 
@@ -257,6 +265,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 65>;
 		marvell,pcie-port = <1>;
 		marvell,pcie-lane = <3>;
+		num-lanes = <1>;
 		clocks = <&gateclk 12>;
 	};
 
@@ -273,6 +282,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 99>;
 		marvell,pcie-port = <2>;
 		marvell,pcie-lane = <0>;
+		num-lanes = <1>;
 		clocks = <&gateclk 26>;
 	};
 
@@ -289,6 +299,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 103>;
 		marvell,pcie-port = <3>;
 		marvell,pcie-lane = <0>;
+		num-lanes = <1>;
 		clocks = <&gateclk 27>;
 	};
 };
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 04/11] dt-bindings: PCI: mvebu: Add num-lanes property
@ 2022-01-05 15:02   ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Andrew Lunn, Gregory Clement
  Cc: linux-pci, linux-kernel, linux-arm-kernel, devicetree

Controller driver needs to correctly configure PCIe link if it contains 1
or 4 SerDes PCIe lanes. Therefore add a new 'num-lanes' DT property for
mvebu PCIe controller. Property 'num-lanes' seems to be de-facto standard
way how number of lanes is specified in other PCIe controllers.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 Documentation/devicetree/bindings/pci/mvebu-pci.txt | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/mvebu-pci.txt b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
index 6173af6885f8..24225852bce0 100644
--- a/Documentation/devicetree/bindings/pci/mvebu-pci.txt
+++ b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
@@ -77,6 +77,7 @@ and the following optional properties:
 - marvell,pcie-lane: the physical PCIe lane number, for ports having
   multiple lanes. If this property is not found, we assume that the
   value is 0.
+- num-lanes: number of SerDes PCIe lanes for this link (1 or 4)
 - reset-gpios: optional GPIO to PERST#
 - reset-delay-us: delay in us to wait after reset de-assertion, if not
   specified will default to 100ms, as required by the PCIe specification.
@@ -141,6 +142,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 58>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <0>;
+		num-lanes = <1>;
 		/* low-active PERST# reset on GPIO 25 */
 		reset-gpios = <&gpio0 25 1>;
 		/* wait 20ms for device settle after reset deassertion */
@@ -161,6 +163,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 59>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <1>;
+		num-lanes = <1>;
 		clocks = <&gateclk 6>;
 	};
 
@@ -177,6 +180,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 60>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <2>;
+		num-lanes = <1>;
 		clocks = <&gateclk 7>;
 	};
 
@@ -193,6 +197,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 61>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <3>;
+		num-lanes = <1>;
 		clocks = <&gateclk 8>;
 	};
 
@@ -209,6 +214,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 62>;
 		marvell,pcie-port = <1>;
 		marvell,pcie-lane = <0>;
+		num-lanes = <1>;
 		clocks = <&gateclk 9>;
 	};
 
@@ -225,6 +231,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 63>;
 		marvell,pcie-port = <1>;
 		marvell,pcie-lane = <1>;
+		num-lanes = <1>;
 		clocks = <&gateclk 10>;
 	};
 
@@ -241,6 +248,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 64>;
 		marvell,pcie-port = <1>;
 		marvell,pcie-lane = <2>;
+		num-lanes = <1>;
 		clocks = <&gateclk 11>;
 	};
 
@@ -257,6 +265,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 65>;
 		marvell,pcie-port = <1>;
 		marvell,pcie-lane = <3>;
+		num-lanes = <1>;
 		clocks = <&gateclk 12>;
 	};
 
@@ -273,6 +282,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 99>;
 		marvell,pcie-port = <2>;
 		marvell,pcie-lane = <0>;
+		num-lanes = <1>;
 		clocks = <&gateclk 26>;
 	};
 
@@ -289,6 +299,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 103>;
 		marvell,pcie-port = <3>;
 		marvell,pcie-lane = <0>;
+		num-lanes = <1>;
 		clocks = <&gateclk 27>;
 	};
 };
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 05/11] PCI: mvebu: Correctly configure x1/x4 mode
  2022-01-05 15:02 ` Pali Rohár
@ 2022-01-05 15:02   ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

If x1/x4 mode is not set correctly then link with endpoint card is not
established.

Use DTS property 'num-lanes' to deteriminate x1/x4 mode.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index a075ba26cff1..0f2ec0a17874 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -93,6 +93,7 @@ struct mvebu_pcie_port {
 	void __iomem *base;
 	u32 port;
 	u32 lane;
+	bool is_x4;
 	int devfn;
 	unsigned int mem_target;
 	unsigned int mem_attr;
@@ -233,13 +234,25 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
 
 static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 {
-	u32 ctrl, cmd, dev_rev, mask;
+	u32 ctrl, lnkcap, cmd, dev_rev, mask;
 
 	/* Setup PCIe controller to Root Complex mode. */
 	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
 	ctrl |= PCIE_CTRL_RC_MODE;
 	mvebu_writel(port, ctrl, PCIE_CTRL_OFF);
 
+	/*
+	 * Set Maximum Link Width to X1 or X4 in Root Port's PCIe Link
+	 * Capability register. This register is defined by PCIe specification
+	 * as read-only but this mvebu controller has it as read-write and must
+	 * be set to number of SerDes PCIe lanes (1 or 4). If this register is
+	 * not set correctly then link with endpoint card is not established.
+	 */
+	lnkcap = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
+	lnkcap &= ~PCI_EXP_LNKCAP_MLW;
+	lnkcap |= (port->is_x4 ? 4 : 1) << 4;
+	mvebu_writel(port, lnkcap, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
+
 	/* Disable Root Bridge I/O space, memory space and bus mastering. */
 	cmd = mvebu_readl(port, PCIE_CMD_OFF);
 	cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
@@ -986,6 +999,7 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
 	struct device *dev = &pcie->pdev->dev;
 	enum of_gpio_flags flags;
 	int reset_gpio, ret;
+	u32 num_lanes;
 
 	port->pcie = pcie;
 
@@ -998,6 +1012,9 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
 	if (of_property_read_u32(child, "marvell,pcie-lane", &port->lane))
 		port->lane = 0;
 
+	if (!of_property_read_u32(child, "num-lanes", &num_lanes) && num_lanes == 4)
+		port->is_x4 = true;
+
 	port->name = devm_kasprintf(dev, GFP_KERNEL, "pcie%d.%d", port->port,
 				    port->lane);
 	if (!port->name) {
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 05/11] PCI: mvebu: Correctly configure x1/x4 mode
@ 2022-01-05 15:02   ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

If x1/x4 mode is not set correctly then link with endpoint card is not
established.

Use DTS property 'num-lanes' to deteriminate x1/x4 mode.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index a075ba26cff1..0f2ec0a17874 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -93,6 +93,7 @@ struct mvebu_pcie_port {
 	void __iomem *base;
 	u32 port;
 	u32 lane;
+	bool is_x4;
 	int devfn;
 	unsigned int mem_target;
 	unsigned int mem_attr;
@@ -233,13 +234,25 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
 
 static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 {
-	u32 ctrl, cmd, dev_rev, mask;
+	u32 ctrl, lnkcap, cmd, dev_rev, mask;
 
 	/* Setup PCIe controller to Root Complex mode. */
 	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
 	ctrl |= PCIE_CTRL_RC_MODE;
 	mvebu_writel(port, ctrl, PCIE_CTRL_OFF);
 
+	/*
+	 * Set Maximum Link Width to X1 or X4 in Root Port's PCIe Link
+	 * Capability register. This register is defined by PCIe specification
+	 * as read-only but this mvebu controller has it as read-write and must
+	 * be set to number of SerDes PCIe lanes (1 or 4). If this register is
+	 * not set correctly then link with endpoint card is not established.
+	 */
+	lnkcap = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
+	lnkcap &= ~PCI_EXP_LNKCAP_MLW;
+	lnkcap |= (port->is_x4 ? 4 : 1) << 4;
+	mvebu_writel(port, lnkcap, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
+
 	/* Disable Root Bridge I/O space, memory space and bus mastering. */
 	cmd = mvebu_readl(port, PCIE_CMD_OFF);
 	cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
@@ -986,6 +999,7 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
 	struct device *dev = &pcie->pdev->dev;
 	enum of_gpio_flags flags;
 	int reset_gpio, ret;
+	u32 num_lanes;
 
 	port->pcie = pcie;
 
@@ -998,6 +1012,9 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
 	if (of_property_read_u32(child, "marvell,pcie-lane", &port->lane))
 		port->lane = 0;
 
+	if (!of_property_read_u32(child, "num-lanes", &num_lanes) && num_lanes == 4)
+		port->is_x4 = true;
+
 	port->name = devm_kasprintf(dev, GFP_KERNEL, "pcie%d.%d", port->port,
 				    port->lane);
 	if (!port->name) {
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 06/11] PCI: mvebu: Add support for PCI Bridge Subsystem Vendor ID on emulated bridge
  2022-01-05 15:02 ` Pali Rohár
@ 2022-01-05 15:02   ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

Register with Subsystem Device/Vendor ID is at offset 0x2c. Export is via
emulated bridge.

After this change Subsystem ID is visible in lspci output at line:

  Capabilities: [40] Subsystem

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 0f2ec0a17874..811af9e6ede5 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -32,6 +32,7 @@
 #define PCIE_DEV_REV_OFF	0x0008
 #define PCIE_BAR_LO_OFF(n)	(0x0010 + ((n) << 3))
 #define PCIE_BAR_HI_OFF(n)	(0x0014 + ((n) << 3))
+#define PCIE_SSDEV_ID_OFF	0x002c
 #define PCIE_CAP_PCIEXP		0x0060
 #define PCIE_HEADER_LOG_4_OFF	0x0128
 #define PCIE_BAR_CTRL_OFF(n)	(0x1804 + (((n) - 1) * 4))
@@ -731,6 +732,7 @@ static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port)
 	struct pci_bridge_emul *bridge = &port->bridge;
 	u32 dev_id = mvebu_readl(port, PCIE_DEV_ID_OFF);
 	u32 dev_rev = mvebu_readl(port, PCIE_DEV_REV_OFF);
+	u32 ssdev_id = mvebu_readl(port, PCIE_SSDEV_ID_OFF);
 	u32 pcie_cap = mvebu_readl(port, PCIE_CAP_PCIEXP);
 	u8 pcie_cap_ver = ((pcie_cap >> 16) & PCI_EXP_FLAGS_VERS);
 
@@ -752,6 +754,8 @@ static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port)
 	 */
 	bridge->pcie_conf.cap = cpu_to_le16(pcie_cap_ver);
 
+	bridge->subsystem_vendor_id = ssdev_id & 0xffff;
+	bridge->subsystem_id = ssdev_id >> 16;
 	bridge->has_pcie = true;
 	bridge->data = port;
 	bridge->ops = &mvebu_pci_bridge_emul_ops;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 06/11] PCI: mvebu: Add support for PCI Bridge Subsystem Vendor ID on emulated bridge
@ 2022-01-05 15:02   ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

Register with Subsystem Device/Vendor ID is at offset 0x2c. Export is via
emulated bridge.

After this change Subsystem ID is visible in lspci output at line:

  Capabilities: [40] Subsystem

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 0f2ec0a17874..811af9e6ede5 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -32,6 +32,7 @@
 #define PCIE_DEV_REV_OFF	0x0008
 #define PCIE_BAR_LO_OFF(n)	(0x0010 + ((n) << 3))
 #define PCIE_BAR_HI_OFF(n)	(0x0014 + ((n) << 3))
+#define PCIE_SSDEV_ID_OFF	0x002c
 #define PCIE_CAP_PCIEXP		0x0060
 #define PCIE_HEADER_LOG_4_OFF	0x0128
 #define PCIE_BAR_CTRL_OFF(n)	(0x1804 + (((n) - 1) * 4))
@@ -731,6 +732,7 @@ static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port)
 	struct pci_bridge_emul *bridge = &port->bridge;
 	u32 dev_id = mvebu_readl(port, PCIE_DEV_ID_OFF);
 	u32 dev_rev = mvebu_readl(port, PCIE_DEV_REV_OFF);
+	u32 ssdev_id = mvebu_readl(port, PCIE_SSDEV_ID_OFF);
 	u32 pcie_cap = mvebu_readl(port, PCIE_CAP_PCIEXP);
 	u8 pcie_cap_ver = ((pcie_cap >> 16) & PCI_EXP_FLAGS_VERS);
 
@@ -752,6 +754,8 @@ static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port)
 	 */
 	bridge->pcie_conf.cap = cpu_to_le16(pcie_cap_ver);
 
+	bridge->subsystem_vendor_id = ssdev_id & 0xffff;
+	bridge->subsystem_id = ssdev_id >> 16;
 	bridge->has_pcie = true;
 	bridge->data = port;
 	bridge->ops = &mvebu_pci_bridge_emul_ops;
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 07/11] PCI: mvebu: Add support for Advanced Error Reporting registers on emulated bridge
  2022-01-05 15:02 ` Pali Rohár
@ 2022-01-05 15:02   ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

AER registers start at mvebu offset 0x0100. Registers PCI_ERR_ROOT_COMMAND,
PCI_ERR_ROOT_STATUS and PCI_ERR_ROOT_ERR_SRC are not supported on pre-XP
hardware and returns zeros.

Note that AER interrupt is not supported yet as mvebu emulated bridge does
not implement interrupts support at all yet.

Also remove custom macro PCIE_HEADER_LOG_4_OFF as it is unused and
correctly this register should be referenced via standard macros with
offset, e.g. as: PCIE_CAP_PCIERR_OFF + PCI_ERR_HEADER_LOG + 4.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 67 +++++++++++++++++++++++++++++-
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 811af9e6ede5..9ea2f6a7c2b0 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -34,7 +34,7 @@
 #define PCIE_BAR_HI_OFF(n)	(0x0014 + ((n) << 3))
 #define PCIE_SSDEV_ID_OFF	0x002c
 #define PCIE_CAP_PCIEXP		0x0060
-#define PCIE_HEADER_LOG_4_OFF	0x0128
+#define PCIE_CAP_PCIERR_OFF	0x0100
 #define PCIE_BAR_CTRL_OFF(n)	(0x1804 + (((n) - 1) * 4))
 #define PCIE_WIN04_CTRL_OFF(n)	(0x1820 + ((n) << 4))
 #define PCIE_WIN04_BASE_OFF(n)	(0x1824 + ((n) << 4))
@@ -603,6 +603,37 @@ mvebu_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
 	return PCI_BRIDGE_EMUL_HANDLED;
 }
 
+static pci_bridge_emul_read_status_t
+mvebu_pci_bridge_emul_ext_conf_read(struct pci_bridge_emul *bridge,
+				    int reg, u32 *value)
+{
+	struct mvebu_pcie_port *port = bridge->data;
+
+	switch (reg) {
+	case 0:
+	case PCI_ERR_UNCOR_STATUS:
+	case PCI_ERR_UNCOR_MASK:
+	case PCI_ERR_UNCOR_SEVER:
+	case PCI_ERR_COR_STATUS:
+	case PCI_ERR_COR_MASK:
+	case PCI_ERR_CAP:
+	case PCI_ERR_HEADER_LOG+0:
+	case PCI_ERR_HEADER_LOG+4:
+	case PCI_ERR_HEADER_LOG+8:
+	case PCI_ERR_HEADER_LOG+12:
+	case PCI_ERR_ROOT_COMMAND:
+	case PCI_ERR_ROOT_STATUS:
+	case PCI_ERR_ROOT_ERR_SRC:
+		*value = mvebu_readl(port, PCIE_CAP_PCIERR_OFF + reg);
+		break;
+
+	default:
+		return PCI_BRIDGE_EMUL_NOT_HANDLED;
+	}
+
+	return PCI_BRIDGE_EMUL_HANDLED;
+}
+
 static void
 mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
 				      int reg, u32 old, u32 new, u32 mask)
@@ -715,11 +746,45 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
 	}
 }
 
+static void
+mvebu_pci_bridge_emul_ext_conf_write(struct pci_bridge_emul *bridge,
+				     int reg, u32 old, u32 new, u32 mask)
+{
+	struct mvebu_pcie_port *port = bridge->data;
+
+	switch (reg) {
+	/* These are W1C registers, so clear other bits */
+	case PCI_ERR_UNCOR_STATUS:
+	case PCI_ERR_COR_STATUS:
+	case PCI_ERR_ROOT_STATUS:
+		new &= mask;
+		fallthrough;
+
+	case PCI_ERR_UNCOR_MASK:
+	case PCI_ERR_UNCOR_SEVER:
+	case PCI_ERR_COR_MASK:
+	case PCI_ERR_CAP:
+	case PCI_ERR_HEADER_LOG+0:
+	case PCI_ERR_HEADER_LOG+4:
+	case PCI_ERR_HEADER_LOG+8:
+	case PCI_ERR_HEADER_LOG+12:
+	case PCI_ERR_ROOT_COMMAND:
+	case PCI_ERR_ROOT_ERR_SRC:
+		mvebu_writel(port, new, PCIE_CAP_PCIERR_OFF + reg);
+		break;
+
+	default:
+		break;
+	}
+}
+
 static const struct pci_bridge_emul_ops mvebu_pci_bridge_emul_ops = {
 	.read_base = mvebu_pci_bridge_emul_base_conf_read,
 	.write_base = mvebu_pci_bridge_emul_base_conf_write,
 	.read_pcie = mvebu_pci_bridge_emul_pcie_conf_read,
 	.write_pcie = mvebu_pci_bridge_emul_pcie_conf_write,
+	.read_ext = mvebu_pci_bridge_emul_ext_conf_read,
+	.write_ext = mvebu_pci_bridge_emul_ext_conf_write,
 };
 
 /*
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 07/11] PCI: mvebu: Add support for Advanced Error Reporting registers on emulated bridge
@ 2022-01-05 15:02   ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

AER registers start at mvebu offset 0x0100. Registers PCI_ERR_ROOT_COMMAND,
PCI_ERR_ROOT_STATUS and PCI_ERR_ROOT_ERR_SRC are not supported on pre-XP
hardware and returns zeros.

Note that AER interrupt is not supported yet as mvebu emulated bridge does
not implement interrupts support at all yet.

Also remove custom macro PCIE_HEADER_LOG_4_OFF as it is unused and
correctly this register should be referenced via standard macros with
offset, e.g. as: PCIE_CAP_PCIERR_OFF + PCI_ERR_HEADER_LOG + 4.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 67 +++++++++++++++++++++++++++++-
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 811af9e6ede5..9ea2f6a7c2b0 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -34,7 +34,7 @@
 #define PCIE_BAR_HI_OFF(n)	(0x0014 + ((n) << 3))
 #define PCIE_SSDEV_ID_OFF	0x002c
 #define PCIE_CAP_PCIEXP		0x0060
-#define PCIE_HEADER_LOG_4_OFF	0x0128
+#define PCIE_CAP_PCIERR_OFF	0x0100
 #define PCIE_BAR_CTRL_OFF(n)	(0x1804 + (((n) - 1) * 4))
 #define PCIE_WIN04_CTRL_OFF(n)	(0x1820 + ((n) << 4))
 #define PCIE_WIN04_BASE_OFF(n)	(0x1824 + ((n) << 4))
@@ -603,6 +603,37 @@ mvebu_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
 	return PCI_BRIDGE_EMUL_HANDLED;
 }
 
+static pci_bridge_emul_read_status_t
+mvebu_pci_bridge_emul_ext_conf_read(struct pci_bridge_emul *bridge,
+				    int reg, u32 *value)
+{
+	struct mvebu_pcie_port *port = bridge->data;
+
+	switch (reg) {
+	case 0:
+	case PCI_ERR_UNCOR_STATUS:
+	case PCI_ERR_UNCOR_MASK:
+	case PCI_ERR_UNCOR_SEVER:
+	case PCI_ERR_COR_STATUS:
+	case PCI_ERR_COR_MASK:
+	case PCI_ERR_CAP:
+	case PCI_ERR_HEADER_LOG+0:
+	case PCI_ERR_HEADER_LOG+4:
+	case PCI_ERR_HEADER_LOG+8:
+	case PCI_ERR_HEADER_LOG+12:
+	case PCI_ERR_ROOT_COMMAND:
+	case PCI_ERR_ROOT_STATUS:
+	case PCI_ERR_ROOT_ERR_SRC:
+		*value = mvebu_readl(port, PCIE_CAP_PCIERR_OFF + reg);
+		break;
+
+	default:
+		return PCI_BRIDGE_EMUL_NOT_HANDLED;
+	}
+
+	return PCI_BRIDGE_EMUL_HANDLED;
+}
+
 static void
 mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
 				      int reg, u32 old, u32 new, u32 mask)
@@ -715,11 +746,45 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
 	}
 }
 
+static void
+mvebu_pci_bridge_emul_ext_conf_write(struct pci_bridge_emul *bridge,
+				     int reg, u32 old, u32 new, u32 mask)
+{
+	struct mvebu_pcie_port *port = bridge->data;
+
+	switch (reg) {
+	/* These are W1C registers, so clear other bits */
+	case PCI_ERR_UNCOR_STATUS:
+	case PCI_ERR_COR_STATUS:
+	case PCI_ERR_ROOT_STATUS:
+		new &= mask;
+		fallthrough;
+
+	case PCI_ERR_UNCOR_MASK:
+	case PCI_ERR_UNCOR_SEVER:
+	case PCI_ERR_COR_MASK:
+	case PCI_ERR_CAP:
+	case PCI_ERR_HEADER_LOG+0:
+	case PCI_ERR_HEADER_LOG+4:
+	case PCI_ERR_HEADER_LOG+8:
+	case PCI_ERR_HEADER_LOG+12:
+	case PCI_ERR_ROOT_COMMAND:
+	case PCI_ERR_ROOT_ERR_SRC:
+		mvebu_writel(port, new, PCIE_CAP_PCIERR_OFF + reg);
+		break;
+
+	default:
+		break;
+	}
+}
+
 static const struct pci_bridge_emul_ops mvebu_pci_bridge_emul_ops = {
 	.read_base = mvebu_pci_bridge_emul_base_conf_read,
 	.write_base = mvebu_pci_bridge_emul_base_conf_write,
 	.read_pcie = mvebu_pci_bridge_emul_pcie_conf_read,
 	.write_pcie = mvebu_pci_bridge_emul_pcie_conf_write,
+	.read_ext = mvebu_pci_bridge_emul_ext_conf_read,
+	.write_ext = mvebu_pci_bridge_emul_ext_conf_write,
 };
 
 /*
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 08/11] PCI: mvebu: Use child_ops API
  2022-01-05 15:02 ` Pali Rohár
@ 2022-01-05 15:02   ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

Split struct pci_ops between ops and child_ops. Member ops is used for
accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
accessing real PCIe cards.

There is no need to mix these two struct pci_ops into one as PCI core code
already provides separate callbacks via bridge->ops and bridge->child_ops.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 82 ++++++++++++++++--------------
 1 file changed, 44 insertions(+), 38 deletions(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 9ea2f6a7c2b0..1e90ab888075 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -294,11 +294,29 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 	mvebu_writel(port, mask, PCIE_MASK_OFF);
 }
 
-static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
-				 struct pci_bus *bus,
-				 u32 devfn, int where, int size, u32 *val)
+static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
+						    struct pci_bus *bus,
+						    int devfn);
+
+static int mvebu_pcie_child_rd_conf(struct pci_bus *bus, u32 devfn, int where,
+				    int size, u32 *val)
 {
-	void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
+	struct mvebu_pcie *pcie = bus->sysdata;
+	struct mvebu_pcie_port *port;
+	void __iomem *conf_data;
+
+	port = mvebu_pcie_find_port(pcie, bus, devfn);
+	if (!port) {
+		*val = 0xffffffff;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	if (!mvebu_pcie_link_up(port)) {
+		*val = 0xffffffff;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	conf_data = port->base + PCIE_CONF_DATA_OFF;
 
 	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
 		     PCIE_CONF_ADDR_OFF);
@@ -321,11 +339,21 @@ static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
-				 struct pci_bus *bus,
-				 u32 devfn, int where, int size, u32 val)
+static int mvebu_pcie_child_wr_conf(struct pci_bus *bus, u32 devfn,
+				    int where, int size, u32 val)
 {
-	void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
+	struct mvebu_pcie *pcie = bus->sysdata;
+	struct mvebu_pcie_port *port;
+	void __iomem *conf_data;
+
+	port = mvebu_pcie_find_port(pcie, bus, devfn);
+	if (!port)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (!mvebu_pcie_link_up(port))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	conf_data = port->base + PCIE_CONF_DATA_OFF;
 
 	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
 		     PCIE_CONF_ADDR_OFF);
@@ -347,6 +375,11 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
 	return PCIBIOS_SUCCESSFUL;
 }
 
+static struct pci_ops mvebu_pcie_child_ops = {
+	.read = mvebu_pcie_child_rd_conf,
+	.write = mvebu_pcie_child_wr_conf,
+};
+
 /*
  * Remove windows, starting from the largest ones to the smallest
  * ones.
@@ -862,25 +895,12 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 {
 	struct mvebu_pcie *pcie = bus->sysdata;
 	struct mvebu_pcie_port *port;
-	int ret;
 
 	port = mvebu_pcie_find_port(pcie, bus, devfn);
 	if (!port)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	/* Access the emulated PCI-to-PCI bridge */
-	if (bus->number == 0)
-		return pci_bridge_emul_conf_write(&port->bridge, where,
-						  size, val);
-
-	if (!mvebu_pcie_link_up(port))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/* Access the real PCIe interface */
-	ret = mvebu_pcie_hw_wr_conf(port, bus, devfn,
-				    where, size, val);
-
-	return ret;
+	return pci_bridge_emul_conf_write(&port->bridge, where, size, val);
 }
 
 /* PCI configuration space read function */
@@ -889,7 +909,6 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 {
 	struct mvebu_pcie *pcie = bus->sysdata;
 	struct mvebu_pcie_port *port;
-	int ret;
 
 	port = mvebu_pcie_find_port(pcie, bus, devfn);
 	if (!port) {
@@ -897,21 +916,7 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 		return PCIBIOS_DEVICE_NOT_FOUND;
 	}
 
-	/* Access the emulated PCI-to-PCI bridge */
-	if (bus->number == 0)
-		return pci_bridge_emul_conf_read(&port->bridge, where,
-						 size, val);
-
-	if (!mvebu_pcie_link_up(port)) {
-		*val = 0xffffffff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-
-	/* Access the real PCIe interface */
-	ret = mvebu_pcie_hw_rd_conf(port, bus, devfn,
-				    where, size, val);
-
-	return ret;
+	return pci_bridge_emul_conf_read(&port->bridge, where, size, val);
 }
 
 static struct pci_ops mvebu_pcie_ops = {
@@ -1421,6 +1426,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 
 	bridge->sysdata = pcie;
 	bridge->ops = &mvebu_pcie_ops;
+	bridge->child_ops = &mvebu_pcie_child_ops;
 	bridge->align_resource = mvebu_pcie_align_resource;
 	bridge->map_irq = mvebu_pcie_map_irq;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 08/11] PCI: mvebu: Use child_ops API
@ 2022-01-05 15:02   ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

Split struct pci_ops between ops and child_ops. Member ops is used for
accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
accessing real PCIe cards.

There is no need to mix these two struct pci_ops into one as PCI core code
already provides separate callbacks via bridge->ops and bridge->child_ops.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 82 ++++++++++++++++--------------
 1 file changed, 44 insertions(+), 38 deletions(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 9ea2f6a7c2b0..1e90ab888075 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -294,11 +294,29 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 	mvebu_writel(port, mask, PCIE_MASK_OFF);
 }
 
-static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
-				 struct pci_bus *bus,
-				 u32 devfn, int where, int size, u32 *val)
+static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
+						    struct pci_bus *bus,
+						    int devfn);
+
+static int mvebu_pcie_child_rd_conf(struct pci_bus *bus, u32 devfn, int where,
+				    int size, u32 *val)
 {
-	void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
+	struct mvebu_pcie *pcie = bus->sysdata;
+	struct mvebu_pcie_port *port;
+	void __iomem *conf_data;
+
+	port = mvebu_pcie_find_port(pcie, bus, devfn);
+	if (!port) {
+		*val = 0xffffffff;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	if (!mvebu_pcie_link_up(port)) {
+		*val = 0xffffffff;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	conf_data = port->base + PCIE_CONF_DATA_OFF;
 
 	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
 		     PCIE_CONF_ADDR_OFF);
@@ -321,11 +339,21 @@ static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
-				 struct pci_bus *bus,
-				 u32 devfn, int where, int size, u32 val)
+static int mvebu_pcie_child_wr_conf(struct pci_bus *bus, u32 devfn,
+				    int where, int size, u32 val)
 {
-	void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
+	struct mvebu_pcie *pcie = bus->sysdata;
+	struct mvebu_pcie_port *port;
+	void __iomem *conf_data;
+
+	port = mvebu_pcie_find_port(pcie, bus, devfn);
+	if (!port)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (!mvebu_pcie_link_up(port))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	conf_data = port->base + PCIE_CONF_DATA_OFF;
 
 	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
 		     PCIE_CONF_ADDR_OFF);
@@ -347,6 +375,11 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
 	return PCIBIOS_SUCCESSFUL;
 }
 
+static struct pci_ops mvebu_pcie_child_ops = {
+	.read = mvebu_pcie_child_rd_conf,
+	.write = mvebu_pcie_child_wr_conf,
+};
+
 /*
  * Remove windows, starting from the largest ones to the smallest
  * ones.
@@ -862,25 +895,12 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 {
 	struct mvebu_pcie *pcie = bus->sysdata;
 	struct mvebu_pcie_port *port;
-	int ret;
 
 	port = mvebu_pcie_find_port(pcie, bus, devfn);
 	if (!port)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	/* Access the emulated PCI-to-PCI bridge */
-	if (bus->number == 0)
-		return pci_bridge_emul_conf_write(&port->bridge, where,
-						  size, val);
-
-	if (!mvebu_pcie_link_up(port))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/* Access the real PCIe interface */
-	ret = mvebu_pcie_hw_wr_conf(port, bus, devfn,
-				    where, size, val);
-
-	return ret;
+	return pci_bridge_emul_conf_write(&port->bridge, where, size, val);
 }
 
 /* PCI configuration space read function */
@@ -889,7 +909,6 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 {
 	struct mvebu_pcie *pcie = bus->sysdata;
 	struct mvebu_pcie_port *port;
-	int ret;
 
 	port = mvebu_pcie_find_port(pcie, bus, devfn);
 	if (!port) {
@@ -897,21 +916,7 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 		return PCIBIOS_DEVICE_NOT_FOUND;
 	}
 
-	/* Access the emulated PCI-to-PCI bridge */
-	if (bus->number == 0)
-		return pci_bridge_emul_conf_read(&port->bridge, where,
-						 size, val);
-
-	if (!mvebu_pcie_link_up(port)) {
-		*val = 0xffffffff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-
-	/* Access the real PCIe interface */
-	ret = mvebu_pcie_hw_rd_conf(port, bus, devfn,
-				    where, size, val);
-
-	return ret;
+	return pci_bridge_emul_conf_read(&port->bridge, where, size, val);
 }
 
 static struct pci_ops mvebu_pcie_ops = {
@@ -1421,6 +1426,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 
 	bridge->sysdata = pcie;
 	bridge->ops = &mvebu_pcie_ops;
+	bridge->child_ops = &mvebu_pcie_child_ops;
 	bridge->align_resource = mvebu_pcie_align_resource;
 	bridge->map_irq = mvebu_pcie_map_irq;
 
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 09/11] dt-bindings: PCI: mvebu: Update information about intx interrupts
  2022-01-05 15:02 ` Pali Rohár
@ 2022-01-05 15:02   ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Andrew Lunn, Gregory Clement
  Cc: linux-pci, linux-kernel, linux-arm-kernel, devicetree

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 Documentation/devicetree/bindings/pci/mvebu-pci.txt | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/mvebu-pci.txt b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
index 24225852bce0..6d022a9d36ee 100644
--- a/Documentation/devicetree/bindings/pci/mvebu-pci.txt
+++ b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
@@ -81,6 +81,11 @@ and the following optional properties:
 - reset-gpios: optional GPIO to PERST#
 - reset-delay-us: delay in us to wait after reset de-assertion, if not
   specified will default to 100ms, as required by the PCIe specification.
+- interrupt-names: list of interrupt names, supported are:
+   - "intx" - interrupt line triggered by one of the legacy interrupt
+- interrupts or interrupts-extended: List of the interrupt sources which
+  corresponding to the "interrupt-names". If non-empty then also additional
+  'interrupt-controller' subnode must be defined.
 
 Example:
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 09/11] dt-bindings: PCI: mvebu: Update information about intx interrupts
@ 2022-01-05 15:02   ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Andrew Lunn, Gregory Clement
  Cc: linux-pci, linux-kernel, linux-arm-kernel, devicetree

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 Documentation/devicetree/bindings/pci/mvebu-pci.txt | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/mvebu-pci.txt b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
index 24225852bce0..6d022a9d36ee 100644
--- a/Documentation/devicetree/bindings/pci/mvebu-pci.txt
+++ b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
@@ -81,6 +81,11 @@ and the following optional properties:
 - reset-gpios: optional GPIO to PERST#
 - reset-delay-us: delay in us to wait after reset de-assertion, if not
   specified will default to 100ms, as required by the PCIe specification.
+- interrupt-names: list of interrupt names, supported are:
+   - "intx" - interrupt line triggered by one of the legacy interrupt
+- interrupts or interrupts-extended: List of the interrupt sources which
+  corresponding to the "interrupt-names". If non-empty then also additional
+  'interrupt-controller' subnode must be defined.
 
 Example:
 
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-01-05 15:02 ` Pali Rohár
@ 2022-01-05 15:02   ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier
  Cc: linux-pci, linux-kernel, linux-arm-kernel

This adds support for legacy INTx interrupts received from other PCIe
devices and which are reported by a new INTx irq chip.

With this change, kernel can distinguish between INTA, INTB, INTC and INTD
interrupts.

Note that for this support, device tree files has to be properly adjusted
to provide "interrupts" or "interrupts-extended" property with intx
interrupt source, "interrupt-names" property with "intx" string and also
'interrupt-controller' subnode must be defined.

If device tree files do not provide these nodes then driver would work as
before.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 182 +++++++++++++++++++++++++++--
 1 file changed, 174 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 1e90ab888075..04bcdd7b7a6d 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -54,9 +54,10 @@
 	 PCIE_CONF_ADDR_EN)
 #define PCIE_CONF_DATA_OFF	0x18fc
 #define PCIE_INT_CAUSE_OFF	0x1900
+#define PCIE_INT_UNMASK_OFF	0x1910
+#define  PCIE_INT_INTX(i)		BIT(24+i)
 #define  PCIE_INT_PM_PME		BIT(28)
-#define PCIE_MASK_OFF		0x1910
-#define  PCIE_MASK_ENABLE_INTS          0x0f000000
+#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
 #define PCIE_CTRL_OFF		0x1a00
 #define  PCIE_CTRL_X1_MODE		0x0001
 #define  PCIE_CTRL_RC_MODE		BIT(1)
@@ -110,6 +111,10 @@ struct mvebu_pcie_port {
 	struct mvebu_pcie_window iowin;
 	u32 saved_pcie_stat;
 	struct resource regs;
+	struct irq_domain *intx_irq_domain;
+	struct irq_chip intx_irq_chip;
+	raw_spinlock_t irq_lock;
+	int intx_irq;
 };
 
 static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
@@ -235,7 +240,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
 
 static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 {
-	u32 ctrl, lnkcap, cmd, dev_rev, mask;
+	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
 
 	/* Setup PCIe controller to Root Complex mode. */
 	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
@@ -288,10 +293,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 	/* Point PCIe unit MBUS decode windows to DRAM space. */
 	mvebu_pcie_setup_wins(port);
 
-	/* Enable interrupt lines A-D. */
-	mask = mvebu_readl(port, PCIE_MASK_OFF);
-	mask |= PCIE_MASK_ENABLE_INTS;
-	mvebu_writel(port, mask, PCIE_MASK_OFF);
+	/* Mask all interrupt sources. */
+	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
+
+	/* Clear all interrupt causes. */
+	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
+
+	if (port->intx_irq <= 0) {
+		/*
+		 * When neither "summary" interrupt, nor "intx" interrupt was
+		 * specified in DT then unmask all legacy INTx interrupts as in
+		 * this case driver does not provide a way for masking and
+		 * unmasking of individual legacy INTx interrupts. In this case
+		 * all interrupts, including legacy INTx are reported via one
+		 * shared GIC source and therefore kernel cannot distinguish
+		 * which individual legacy INTx was triggered. These interrupts
+		 * are shared, so it should not cause any issue. Just
+		 * performance penalty as every PCIe interrupt handler needs to
+		 * be called when some interrupt is triggered.
+		 */
+		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
+			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
+		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	}
 }
 
 static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
@@ -924,6 +949,109 @@ static struct pci_ops mvebu_pcie_ops = {
 	.write = mvebu_pcie_wr_conf,
 };
 
+static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
+{
+	struct mvebu_pcie_port *port = d->domain->host_data;
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+	unsigned long flags;
+	u32 unmask;
+
+	raw_spin_lock_irqsave(&port->irq_lock, flags);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	unmask &= ~PCIE_INT_INTX(hwirq);
+	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
+}
+
+static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
+{
+	struct mvebu_pcie_port *port = d->domain->host_data;
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+	unsigned long flags;
+	u32 unmask;
+
+	raw_spin_lock_irqsave(&port->irq_lock, flags);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	unmask |= PCIE_INT_INTX(hwirq);
+	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
+}
+
+static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
+				   unsigned int virq, irq_hw_number_t hwirq)
+{
+	struct mvebu_pcie_port *port = h->host_data;
+
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, &port->intx_irq_chip, handle_level_irq);
+	irq_set_chip_data(virq, port);
+
+	return 0;
+}
+
+static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
+	.map = mvebu_pcie_intx_irq_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
+{
+	struct device *dev = &port->pcie->pdev->dev;
+	struct device_node *pcie_intc_node;
+
+	raw_spin_lock_init(&port->irq_lock);
+
+	port->intx_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL,
+						  "mvebu-%s-INTx",
+						  port->name);
+	port->intx_irq_chip.irq_mask = mvebu_pcie_intx_irq_mask;
+	port->intx_irq_chip.irq_unmask = mvebu_pcie_intx_irq_unmask;
+
+	pcie_intc_node = of_get_next_child(port->dn, NULL);
+	if (!pcie_intc_node) {
+		dev_err(dev, "No PCIe Intc node found for %s\n", port->name);
+		return -ENODEV;
+	}
+
+	port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
+						      &mvebu_pcie_intx_irq_domain_ops,
+						      port);
+	of_node_put(pcie_intc_node);
+	if (!port->intx_irq_domain) {
+		devm_kfree(dev, port->intx_irq_chip.name);
+		dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void mvebu_pcie_irq_handler(struct irq_desc *desc)
+{
+	struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct device *dev = &port->pcie->pdev->dev;
+	u32 cause, unmask, status;
+	int i;
+
+	chained_irq_enter(chip, desc);
+
+	cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	status = cause & unmask;
+
+	/* Process legacy INTx interrupts */
+	for (i = 0; i < PCI_NUM_INTX; i++) {
+		if (!(status & PCIE_INT_INTX(i)))
+			continue;
+
+		if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL)
+			dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A');
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
 static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	/* Interrupt support on mvebu emulated bridges is not implemented yet */
@@ -1121,6 +1249,16 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
 		port->io_attr = -1;
 	}
 
+	/*
+	 * Old DT bindings do not contain "intx" interrupt
+	 * so do not fail probing driver when interrupt does not exist.
+	 */
+	port->intx_irq = of_irq_get_byname(child, "intx");
+	if (port->intx_irq == -EPROBE_DEFER) {
+		ret = port->intx_irq;
+		goto err;
+	}
+
 	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
 	if (reset_gpio == -EPROBE_DEFER) {
 		ret = reset_gpio;
@@ -1317,6 +1455,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 
 	for (i = 0; i < pcie->nports; i++) {
 		struct mvebu_pcie_port *port = &pcie->ports[i];
+		int irq = port->intx_irq;
 
 		child = port->dn;
 		if (!child)
@@ -1344,6 +1483,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 			continue;
 		}
 
+		if (irq > 0) {
+			ret = mvebu_pcie_init_irq_domain(port);
+			if (ret) {
+				dev_err(dev, "%s: cannot init irq domain\n",
+					port->name);
+				pci_bridge_emul_cleanup(&port->bridge);
+				devm_iounmap(dev, port->base);
+				port->base = NULL;
+				mvebu_pcie_powerdown(port);
+				continue;
+			}
+			irq_set_chained_handler_and_data(irq,
+							 mvebu_pcie_irq_handler,
+							 port);
+		}
+
 		/*
 		 * PCIe topology exported by mvebu hw is quite complicated. In
 		 * reality has something like N fully independent host bridges
@@ -1448,6 +1603,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
 
 	for (i = 0; i < pcie->nports; i++) {
 		struct mvebu_pcie_port *port = &pcie->ports[i];
+		int irq = port->intx_irq;
 
 		if (!port->base)
 			continue;
@@ -1458,7 +1614,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
 		mvebu_writel(port, cmd, PCIE_CMD_OFF);
 
 		/* Mask all interrupt sources. */
-		mvebu_writel(port, 0, PCIE_MASK_OFF);
+		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
+
+		/* Clear all interrupt causes. */
+		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
+
+		/* Remove IRQ domains. */
+		if (port->intx_irq_domain)
+			irq_domain_remove(port->intx_irq_domain);
+
+		if (irq > 0)
+			irq_set_chained_handler_and_data(irq, NULL, NULL);
 
 		/* Free config space for emulated root bridge. */
 		pci_bridge_emul_cleanup(&port->bridge);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-01-05 15:02   ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier
  Cc: linux-pci, linux-kernel, linux-arm-kernel

This adds support for legacy INTx interrupts received from other PCIe
devices and which are reported by a new INTx irq chip.

With this change, kernel can distinguish between INTA, INTB, INTC and INTD
interrupts.

Note that for this support, device tree files has to be properly adjusted
to provide "interrupts" or "interrupts-extended" property with intx
interrupt source, "interrupt-names" property with "intx" string and also
'interrupt-controller' subnode must be defined.

If device tree files do not provide these nodes then driver would work as
before.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 182 +++++++++++++++++++++++++++--
 1 file changed, 174 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 1e90ab888075..04bcdd7b7a6d 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -54,9 +54,10 @@
 	 PCIE_CONF_ADDR_EN)
 #define PCIE_CONF_DATA_OFF	0x18fc
 #define PCIE_INT_CAUSE_OFF	0x1900
+#define PCIE_INT_UNMASK_OFF	0x1910
+#define  PCIE_INT_INTX(i)		BIT(24+i)
 #define  PCIE_INT_PM_PME		BIT(28)
-#define PCIE_MASK_OFF		0x1910
-#define  PCIE_MASK_ENABLE_INTS          0x0f000000
+#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
 #define PCIE_CTRL_OFF		0x1a00
 #define  PCIE_CTRL_X1_MODE		0x0001
 #define  PCIE_CTRL_RC_MODE		BIT(1)
@@ -110,6 +111,10 @@ struct mvebu_pcie_port {
 	struct mvebu_pcie_window iowin;
 	u32 saved_pcie_stat;
 	struct resource regs;
+	struct irq_domain *intx_irq_domain;
+	struct irq_chip intx_irq_chip;
+	raw_spinlock_t irq_lock;
+	int intx_irq;
 };
 
 static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
@@ -235,7 +240,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
 
 static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 {
-	u32 ctrl, lnkcap, cmd, dev_rev, mask;
+	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
 
 	/* Setup PCIe controller to Root Complex mode. */
 	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
@@ -288,10 +293,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 	/* Point PCIe unit MBUS decode windows to DRAM space. */
 	mvebu_pcie_setup_wins(port);
 
-	/* Enable interrupt lines A-D. */
-	mask = mvebu_readl(port, PCIE_MASK_OFF);
-	mask |= PCIE_MASK_ENABLE_INTS;
-	mvebu_writel(port, mask, PCIE_MASK_OFF);
+	/* Mask all interrupt sources. */
+	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
+
+	/* Clear all interrupt causes. */
+	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
+
+	if (port->intx_irq <= 0) {
+		/*
+		 * When neither "summary" interrupt, nor "intx" interrupt was
+		 * specified in DT then unmask all legacy INTx interrupts as in
+		 * this case driver does not provide a way for masking and
+		 * unmasking of individual legacy INTx interrupts. In this case
+		 * all interrupts, including legacy INTx are reported via one
+		 * shared GIC source and therefore kernel cannot distinguish
+		 * which individual legacy INTx was triggered. These interrupts
+		 * are shared, so it should not cause any issue. Just
+		 * performance penalty as every PCIe interrupt handler needs to
+		 * be called when some interrupt is triggered.
+		 */
+		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
+			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
+		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	}
 }
 
 static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
@@ -924,6 +949,109 @@ static struct pci_ops mvebu_pcie_ops = {
 	.write = mvebu_pcie_wr_conf,
 };
 
+static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
+{
+	struct mvebu_pcie_port *port = d->domain->host_data;
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+	unsigned long flags;
+	u32 unmask;
+
+	raw_spin_lock_irqsave(&port->irq_lock, flags);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	unmask &= ~PCIE_INT_INTX(hwirq);
+	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
+}
+
+static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
+{
+	struct mvebu_pcie_port *port = d->domain->host_data;
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+	unsigned long flags;
+	u32 unmask;
+
+	raw_spin_lock_irqsave(&port->irq_lock, flags);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	unmask |= PCIE_INT_INTX(hwirq);
+	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
+}
+
+static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
+				   unsigned int virq, irq_hw_number_t hwirq)
+{
+	struct mvebu_pcie_port *port = h->host_data;
+
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, &port->intx_irq_chip, handle_level_irq);
+	irq_set_chip_data(virq, port);
+
+	return 0;
+}
+
+static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
+	.map = mvebu_pcie_intx_irq_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
+{
+	struct device *dev = &port->pcie->pdev->dev;
+	struct device_node *pcie_intc_node;
+
+	raw_spin_lock_init(&port->irq_lock);
+
+	port->intx_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL,
+						  "mvebu-%s-INTx",
+						  port->name);
+	port->intx_irq_chip.irq_mask = mvebu_pcie_intx_irq_mask;
+	port->intx_irq_chip.irq_unmask = mvebu_pcie_intx_irq_unmask;
+
+	pcie_intc_node = of_get_next_child(port->dn, NULL);
+	if (!pcie_intc_node) {
+		dev_err(dev, "No PCIe Intc node found for %s\n", port->name);
+		return -ENODEV;
+	}
+
+	port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
+						      &mvebu_pcie_intx_irq_domain_ops,
+						      port);
+	of_node_put(pcie_intc_node);
+	if (!port->intx_irq_domain) {
+		devm_kfree(dev, port->intx_irq_chip.name);
+		dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void mvebu_pcie_irq_handler(struct irq_desc *desc)
+{
+	struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct device *dev = &port->pcie->pdev->dev;
+	u32 cause, unmask, status;
+	int i;
+
+	chained_irq_enter(chip, desc);
+
+	cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	status = cause & unmask;
+
+	/* Process legacy INTx interrupts */
+	for (i = 0; i < PCI_NUM_INTX; i++) {
+		if (!(status & PCIE_INT_INTX(i)))
+			continue;
+
+		if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL)
+			dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A');
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
 static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	/* Interrupt support on mvebu emulated bridges is not implemented yet */
@@ -1121,6 +1249,16 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
 		port->io_attr = -1;
 	}
 
+	/*
+	 * Old DT bindings do not contain "intx" interrupt
+	 * so do not fail probing driver when interrupt does not exist.
+	 */
+	port->intx_irq = of_irq_get_byname(child, "intx");
+	if (port->intx_irq == -EPROBE_DEFER) {
+		ret = port->intx_irq;
+		goto err;
+	}
+
 	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
 	if (reset_gpio == -EPROBE_DEFER) {
 		ret = reset_gpio;
@@ -1317,6 +1455,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 
 	for (i = 0; i < pcie->nports; i++) {
 		struct mvebu_pcie_port *port = &pcie->ports[i];
+		int irq = port->intx_irq;
 
 		child = port->dn;
 		if (!child)
@@ -1344,6 +1483,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 			continue;
 		}
 
+		if (irq > 0) {
+			ret = mvebu_pcie_init_irq_domain(port);
+			if (ret) {
+				dev_err(dev, "%s: cannot init irq domain\n",
+					port->name);
+				pci_bridge_emul_cleanup(&port->bridge);
+				devm_iounmap(dev, port->base);
+				port->base = NULL;
+				mvebu_pcie_powerdown(port);
+				continue;
+			}
+			irq_set_chained_handler_and_data(irq,
+							 mvebu_pcie_irq_handler,
+							 port);
+		}
+
 		/*
 		 * PCIe topology exported by mvebu hw is quite complicated. In
 		 * reality has something like N fully independent host bridges
@@ -1448,6 +1603,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
 
 	for (i = 0; i < pcie->nports; i++) {
 		struct mvebu_pcie_port *port = &pcie->ports[i];
+		int irq = port->intx_irq;
 
 		if (!port->base)
 			continue;
@@ -1458,7 +1614,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
 		mvebu_writel(port, cmd, PCIE_CMD_OFF);
 
 		/* Mask all interrupt sources. */
-		mvebu_writel(port, 0, PCIE_MASK_OFF);
+		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
+
+		/* Clear all interrupt causes. */
+		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
+
+		/* Remove IRQ domains. */
+		if (port->intx_irq_domain)
+			irq_domain_remove(port->intx_irq_domain);
+
+		if (irq > 0)
+			irq_set_chained_handler_and_data(irq, NULL, NULL);
 
 		/* Free config space for emulated root bridge. */
 		pci_bridge_emul_cleanup(&port->bridge);
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
  2022-01-05 15:02 ` Pali Rohár
@ 2022-01-05 15:02   ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Andrew Lunn, Gregory Clement
  Cc: linux-pci, linux-kernel, linux-arm-kernel, devicetree

With this change legacy INTA, INTB, INTC and INTD interrupts are reported
separately and not mixed into one Linux virq source anymore.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----
 1 file changed, 44 insertions(+), 8 deletions(-)

diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
index f0022d10c715..83392b92dae2 100644
--- a/arch/arm/boot/dts/armada-385.dtsi
+++ b/arch/arm/boot/dts/armada-385.dtsi
@@ -69,16 +69,25 @@
 				reg = <0x0800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
+				interrupt-names = "intx";
+				interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <1>;
 				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
 					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
 				bus-range = <0x00 0xff>;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-map-mask = <0 0 0 7>;
+				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>;
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 8>;
 				status = "disabled";
+				pcie1_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
 			};
 
 			/* x1 port */
@@ -88,16 +97,25 @@
 				reg = <0x1000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
+				interrupt-names = "intx";
+				interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <1>;
 				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
 					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
 				bus-range = <0x00 0xff>;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &pcie2_intc 0>,
+						<0 0 0 2 &pcie2_intc 1>,
+						<0 0 0 3 &pcie2_intc 2>,
+						<0 0 0 4 &pcie2_intc 3>;
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
 				status = "disabled";
+				pcie2_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
 			};
 
 			/* x1 port */
@@ -107,16 +125,25 @@
 				reg = <0x1800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
+				interrupt-names = "intx";
+				interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <1>;
 				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
 					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
 				bus-range = <0x00 0xff>;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &pcie3_intc 0>,
+						<0 0 0 2 &pcie3_intc 1>,
+						<0 0 0 3 &pcie3_intc 2>,
+						<0 0 0 4 &pcie3_intc 3>;
 				marvell,pcie-port = <2>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 6>;
 				status = "disabled";
+				pcie3_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
 			};
 
 			/*
@@ -129,16 +156,25 @@
 				reg = <0x2000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
+				interrupt-names = "intx";
+				interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <1>;
 				ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
 					  0x81000000 0 0 0x81000000 0x4 0 1 0>;
 				bus-range = <0x00 0xff>;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &pcie4_intc 0>,
+						<0 0 0 2 &pcie4_intc 1>,
+						<0 0 0 3 &pcie4_intc 2>,
+						<0 0 0 4 &pcie4_intc 3>;
 				marvell,pcie-port = <3>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 7>;
 				status = "disabled";
+				pcie4_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
 			};
 		};
 	};
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
@ 2022-01-05 15:02   ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:02 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Andrew Lunn, Gregory Clement
  Cc: linux-pci, linux-kernel, linux-arm-kernel, devicetree

With this change legacy INTA, INTB, INTC and INTD interrupts are reported
separately and not mixed into one Linux virq source anymore.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----
 1 file changed, 44 insertions(+), 8 deletions(-)

diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
index f0022d10c715..83392b92dae2 100644
--- a/arch/arm/boot/dts/armada-385.dtsi
+++ b/arch/arm/boot/dts/armada-385.dtsi
@@ -69,16 +69,25 @@
 				reg = <0x0800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
+				interrupt-names = "intx";
+				interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <1>;
 				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
 					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
 				bus-range = <0x00 0xff>;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-map-mask = <0 0 0 7>;
+				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>;
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 8>;
 				status = "disabled";
+				pcie1_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
 			};
 
 			/* x1 port */
@@ -88,16 +97,25 @@
 				reg = <0x1000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
+				interrupt-names = "intx";
+				interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <1>;
 				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
 					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
 				bus-range = <0x00 0xff>;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &pcie2_intc 0>,
+						<0 0 0 2 &pcie2_intc 1>,
+						<0 0 0 3 &pcie2_intc 2>,
+						<0 0 0 4 &pcie2_intc 3>;
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
 				status = "disabled";
+				pcie2_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
 			};
 
 			/* x1 port */
@@ -107,16 +125,25 @@
 				reg = <0x1800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
+				interrupt-names = "intx";
+				interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <1>;
 				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
 					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
 				bus-range = <0x00 0xff>;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &pcie3_intc 0>,
+						<0 0 0 2 &pcie3_intc 1>,
+						<0 0 0 3 &pcie3_intc 2>,
+						<0 0 0 4 &pcie3_intc 3>;
 				marvell,pcie-port = <2>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 6>;
 				status = "disabled";
+				pcie3_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
 			};
 
 			/*
@@ -129,16 +156,25 @@
 				reg = <0x2000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
+				interrupt-names = "intx";
+				interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <1>;
 				ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
 					  0x81000000 0 0 0x81000000 0x4 0 1 0>;
 				bus-range = <0x00 0xff>;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &pcie4_intc 0>,
+						<0 0 0 2 &pcie4_intc 1>,
+						<0 0 0 3 &pcie4_intc 2>,
+						<0 0 0 4 &pcie4_intc 3>;
 				marvell,pcie-port = <3>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 7>;
 				status = "disabled";
+				pcie4_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
 			};
 		};
 	};
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* Re: [PATCH 08/11] PCI: mvebu: Use child_ops API
  2022-01-05 15:02   ` Pali Rohár
@ 2022-01-05 15:41     ` Rob Herring
  -1 siblings, 0 replies; 130+ messages in thread
From: Rob Herring @ 2022-01-05 15:41 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King, PCI,
	linux-kernel, linux-arm-kernel

On Wed, Jan 5, 2022 at 9:03 AM Pali Rohár <pali@kernel.org> wrote:
>
> Split struct pci_ops between ops and child_ops. Member ops is used for
> accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
> accessing real PCIe cards.
>
> There is no need to mix these two struct pci_ops into one as PCI core code
> already provides separate callbacks via bridge->ops and bridge->child_ops.

I had similar patches including mvebu that I never got around to
sending out. I pushed the branch out now at least[1].

> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  drivers/pci/controller/pci-mvebu.c | 82 ++++++++++++++++--------------
>  1 file changed, 44 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> index 9ea2f6a7c2b0..1e90ab888075 100644
> --- a/drivers/pci/controller/pci-mvebu.c
> +++ b/drivers/pci/controller/pci-mvebu.c
> @@ -294,11 +294,29 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
>         mvebu_writel(port, mask, PCIE_MASK_OFF);
>  }
>
> -static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
> -                                struct pci_bus *bus,
> -                                u32 devfn, int where, int size, u32 *val)
> +static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> +                                                   struct pci_bus *bus,
> +                                                   int devfn);
> +
> +static int mvebu_pcie_child_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> +                                   int size, u32 *val)
>  {
> -       void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
> +       struct mvebu_pcie *pcie = bus->sysdata;
> +       struct mvebu_pcie_port *port;
> +       void __iomem *conf_data;
> +
> +       port = mvebu_pcie_find_port(pcie, bus, devfn);
> +       if (!port) {
> +               *val = 0xffffffff;
> +               return PCIBIOS_DEVICE_NOT_FOUND;
> +       }
> +
> +       if (!mvebu_pcie_link_up(port)) {
> +               *val = 0xffffffff;
> +               return PCIBIOS_DEVICE_NOT_FOUND;
> +       }
> +
> +       conf_data = port->base + PCIE_CONF_DATA_OFF;
>
>         mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
>                      PCIE_CONF_ADDR_OFF);
> @@ -321,11 +339,21 @@ static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
>         return PCIBIOS_SUCCESSFUL;
>  }
>
> -static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
> -                                struct pci_bus *bus,
> -                                u32 devfn, int where, int size, u32 val)
> +static int mvebu_pcie_child_wr_conf(struct pci_bus *bus, u32 devfn,
> +                                   int where, int size, u32 val)
>  {
> -       void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
> +       struct mvebu_pcie *pcie = bus->sysdata;
> +       struct mvebu_pcie_port *port;
> +       void __iomem *conf_data;
> +
> +       port = mvebu_pcie_find_port(pcie, bus, devfn);
> +       if (!port)
> +               return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +       if (!mvebu_pcie_link_up(port))
> +               return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +       conf_data = port->base + PCIE_CONF_DATA_OFF;

The same code in read and write is a hint to use .map_bus().

>
>         mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
>                      PCIE_CONF_ADDR_OFF);
> @@ -347,6 +375,11 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
>         return PCIBIOS_SUCCESSFUL;
>  }
>
> +static struct pci_ops mvebu_pcie_child_ops = {
> +       .read = mvebu_pcie_child_rd_conf,
> +       .write = mvebu_pcie_child_wr_conf,
> +};
> +
>  /*
>   * Remove windows, starting from the largest ones to the smallest
>   * ones.
> @@ -862,25 +895,12 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
>  {
>         struct mvebu_pcie *pcie = bus->sysdata;
>         struct mvebu_pcie_port *port;
> -       int ret;
>
>         port = mvebu_pcie_find_port(pcie, bus, devfn);
>         if (!port)
>                 return PCIBIOS_DEVICE_NOT_FOUND;

It would be nice to go from 'bus' to 'bridge' ptr directly, but I
still had this in my version. I guess a standard RP struct as part of
decoupling host bridges from RPs would solve this issue.

Rob

[1] https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git/log/?h=pci-child-bus-ops

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 08/11] PCI: mvebu: Use child_ops API
@ 2022-01-05 15:41     ` Rob Herring
  0 siblings, 0 replies; 130+ messages in thread
From: Rob Herring @ 2022-01-05 15:41 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King, PCI,
	linux-kernel, linux-arm-kernel

On Wed, Jan 5, 2022 at 9:03 AM Pali Rohár <pali@kernel.org> wrote:
>
> Split struct pci_ops between ops and child_ops. Member ops is used for
> accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
> accessing real PCIe cards.
>
> There is no need to mix these two struct pci_ops into one as PCI core code
> already provides separate callbacks via bridge->ops and bridge->child_ops.

I had similar patches including mvebu that I never got around to
sending out. I pushed the branch out now at least[1].

> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  drivers/pci/controller/pci-mvebu.c | 82 ++++++++++++++++--------------
>  1 file changed, 44 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> index 9ea2f6a7c2b0..1e90ab888075 100644
> --- a/drivers/pci/controller/pci-mvebu.c
> +++ b/drivers/pci/controller/pci-mvebu.c
> @@ -294,11 +294,29 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
>         mvebu_writel(port, mask, PCIE_MASK_OFF);
>  }
>
> -static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
> -                                struct pci_bus *bus,
> -                                u32 devfn, int where, int size, u32 *val)
> +static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> +                                                   struct pci_bus *bus,
> +                                                   int devfn);
> +
> +static int mvebu_pcie_child_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> +                                   int size, u32 *val)
>  {
> -       void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
> +       struct mvebu_pcie *pcie = bus->sysdata;
> +       struct mvebu_pcie_port *port;
> +       void __iomem *conf_data;
> +
> +       port = mvebu_pcie_find_port(pcie, bus, devfn);
> +       if (!port) {
> +               *val = 0xffffffff;
> +               return PCIBIOS_DEVICE_NOT_FOUND;
> +       }
> +
> +       if (!mvebu_pcie_link_up(port)) {
> +               *val = 0xffffffff;
> +               return PCIBIOS_DEVICE_NOT_FOUND;
> +       }
> +
> +       conf_data = port->base + PCIE_CONF_DATA_OFF;
>
>         mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
>                      PCIE_CONF_ADDR_OFF);
> @@ -321,11 +339,21 @@ static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
>         return PCIBIOS_SUCCESSFUL;
>  }
>
> -static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
> -                                struct pci_bus *bus,
> -                                u32 devfn, int where, int size, u32 val)
> +static int mvebu_pcie_child_wr_conf(struct pci_bus *bus, u32 devfn,
> +                                   int where, int size, u32 val)
>  {
> -       void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
> +       struct mvebu_pcie *pcie = bus->sysdata;
> +       struct mvebu_pcie_port *port;
> +       void __iomem *conf_data;
> +
> +       port = mvebu_pcie_find_port(pcie, bus, devfn);
> +       if (!port)
> +               return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +       if (!mvebu_pcie_link_up(port))
> +               return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +       conf_data = port->base + PCIE_CONF_DATA_OFF;

The same code in read and write is a hint to use .map_bus().

>
>         mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
>                      PCIE_CONF_ADDR_OFF);
> @@ -347,6 +375,11 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
>         return PCIBIOS_SUCCESSFUL;
>  }
>
> +static struct pci_ops mvebu_pcie_child_ops = {
> +       .read = mvebu_pcie_child_rd_conf,
> +       .write = mvebu_pcie_child_wr_conf,
> +};
> +
>  /*
>   * Remove windows, starting from the largest ones to the smallest
>   * ones.
> @@ -862,25 +895,12 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
>  {
>         struct mvebu_pcie *pcie = bus->sysdata;
>         struct mvebu_pcie_port *port;
> -       int ret;
>
>         port = mvebu_pcie_find_port(pcie, bus, devfn);
>         if (!port)
>                 return PCIBIOS_DEVICE_NOT_FOUND;

It would be nice to go from 'bus' to 'bridge' ptr directly, but I
still had this in my version. I guess a standard RP struct as part of
decoupling host bridges from RPs would solve this issue.

Rob

[1] https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git/log/?h=pci-child-bus-ops

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 08/11] PCI: mvebu: Use child_ops API
  2022-01-05 15:41     ` Rob Herring
@ 2022-01-05 15:49       ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:49 UTC (permalink / raw)
  To: Rob Herring
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King, PCI,
	linux-kernel, linux-arm-kernel

On Wednesday 05 January 2022 09:41:51 Rob Herring wrote:
> > @@ -347,6 +375,11 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
> >         return PCIBIOS_SUCCESSFUL;
> >  }
> >
> > +static struct pci_ops mvebu_pcie_child_ops = {
> > +       .read = mvebu_pcie_child_rd_conf,
> > +       .write = mvebu_pcie_child_wr_conf,
> > +};
> > +
> >  /*
> >   * Remove windows, starting from the largest ones to the smallest
> >   * ones.
> > @@ -862,25 +895,12 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
> >  {
> >         struct mvebu_pcie *pcie = bus->sysdata;
> >         struct mvebu_pcie_port *port;
> > -       int ret;
> >
> >         port = mvebu_pcie_find_port(pcie, bus, devfn);
> >         if (!port)
> >                 return PCIBIOS_DEVICE_NOT_FOUND;
> 
> It would be nice to go from 'bus' to 'bridge' ptr directly, but I
> still had this in my version. I guess a standard RP struct as part of
> decoupling host bridges from RPs would solve this issue.

Hello!

The problem is somewhere else. This driver is misusing bus 0 for doing
non-transparent bus-bridging between multiple PCI domains by registering
roots ports across all domains into domain 0, bus 0. All details are
in this my patch which documents this strange driver behavior:
https://lore.kernel.org/linux-pci/20211125124605.25915-12-pali@kernel.org/

So the correct solution is is split these multidomain mixing and then
every domain would have exactly one root port (as it is designed in HW).

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 08/11] PCI: mvebu: Use child_ops API
@ 2022-01-05 15:49       ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-05 15:49 UTC (permalink / raw)
  To: Rob Herring
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King, PCI,
	linux-kernel, linux-arm-kernel

On Wednesday 05 January 2022 09:41:51 Rob Herring wrote:
> > @@ -347,6 +375,11 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
> >         return PCIBIOS_SUCCESSFUL;
> >  }
> >
> > +static struct pci_ops mvebu_pcie_child_ops = {
> > +       .read = mvebu_pcie_child_rd_conf,
> > +       .write = mvebu_pcie_child_wr_conf,
> > +};
> > +
> >  /*
> >   * Remove windows, starting from the largest ones to the smallest
> >   * ones.
> > @@ -862,25 +895,12 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
> >  {
> >         struct mvebu_pcie *pcie = bus->sysdata;
> >         struct mvebu_pcie_port *port;
> > -       int ret;
> >
> >         port = mvebu_pcie_find_port(pcie, bus, devfn);
> >         if (!port)
> >                 return PCIBIOS_DEVICE_NOT_FOUND;
> 
> It would be nice to go from 'bus' to 'bridge' ptr directly, but I
> still had this in my version. I guess a standard RP struct as part of
> decoupling host bridges from RPs would solve this issue.

Hello!

The problem is somewhere else. This driver is misusing bus 0 for doing
non-transparent bus-bridging between multiple PCI domains by registering
roots ports across all domains into domain 0, bus 0. All details are
in this my patch which documents this strange driver behavior:
https://lore.kernel.org/linux-pci/20211125124605.25915-12-pali@kernel.org/

So the correct solution is is split these multidomain mixing and then
every domain would have exactly one root port (as it is designed in HW).

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-01-05 15:02   ` Pali Rohár
@ 2022-01-06 15:28     ` Marc Zyngier
  -1 siblings, 0 replies; 130+ messages in thread
From: Marc Zyngier @ 2022-01-06 15:28 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Wed, 05 Jan 2022 15:02:38 +0000,
Pali Rohár <pali@kernel.org> wrote:
> 
> This adds support for legacy INTx interrupts received from other PCIe
> devices and which are reported by a new INTx irq chip.
> 
> With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> interrupts.
> 
> Note that for this support, device tree files has to be properly adjusted
> to provide "interrupts" or "interrupts-extended" property with intx
> interrupt source, "interrupt-names" property with "intx" string and also
> 'interrupt-controller' subnode must be defined.
> 
> If device tree files do not provide these nodes then driver would work as
> before.
> 
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  drivers/pci/controller/pci-mvebu.c | 182 +++++++++++++++++++++++++++--
>  1 file changed, 174 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> index 1e90ab888075..04bcdd7b7a6d 100644
> --- a/drivers/pci/controller/pci-mvebu.c
> +++ b/drivers/pci/controller/pci-mvebu.c
> @@ -54,9 +54,10 @@
>  	 PCIE_CONF_ADDR_EN)
>  #define PCIE_CONF_DATA_OFF	0x18fc
>  #define PCIE_INT_CAUSE_OFF	0x1900
> +#define PCIE_INT_UNMASK_OFF	0x1910
> +#define  PCIE_INT_INTX(i)		BIT(24+i)
>  #define  PCIE_INT_PM_PME		BIT(28)
> -#define PCIE_MASK_OFF		0x1910
> -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
>  #define PCIE_CTRL_OFF		0x1a00
>  #define  PCIE_CTRL_X1_MODE		0x0001
>  #define  PCIE_CTRL_RC_MODE		BIT(1)
> @@ -110,6 +111,10 @@ struct mvebu_pcie_port {
>  	struct mvebu_pcie_window iowin;
>  	u32 saved_pcie_stat;
>  	struct resource regs;
> +	struct irq_domain *intx_irq_domain;
> +	struct irq_chip intx_irq_chip;

Why is this structure per port? It really should be global. Printing
the port number in the name isn't enough of a reason.

> +	raw_spinlock_t irq_lock;
> +	int intx_irq;
>  };
>  
>  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> @@ -235,7 +240,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
>  
>  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
>  {
> -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
>  
>  	/* Setup PCIe controller to Root Complex mode. */
>  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> @@ -288,10 +293,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
>  	/* Point PCIe unit MBUS decode windows to DRAM space. */
>  	mvebu_pcie_setup_wins(port);
>  
> -	/* Enable interrupt lines A-D. */
> -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> -	mask |= PCIE_MASK_ENABLE_INTS;
> -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> +	/* Mask all interrupt sources. */
> +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> +
> +	/* Clear all interrupt causes. */
> +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> +
> +	if (port->intx_irq <= 0) {
> +		/*
> +		 * When neither "summary" interrupt, nor "intx" interrupt was
> +		 * specified in DT then unmask all legacy INTx interrupts as in
> +		 * this case driver does not provide a way for masking and
> +		 * unmasking of individual legacy INTx interrupts. In this case
> +		 * all interrupts, including legacy INTx are reported via one
> +		 * shared GIC source and therefore kernel cannot distinguish
> +		 * which individual legacy INTx was triggered. These interrupts
> +		 * are shared, so it should not cause any issue. Just
> +		 * performance penalty as every PCIe interrupt handler needs to
> +		 * be called when some interrupt is triggered.
> +		 */
> +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);

Maybe worth printing a warning here, so that the user knows they are
on thin ice.

> +	}
>  }
>  
>  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> @@ -924,6 +949,109 @@ static struct pci_ops mvebu_pcie_ops = {
>  	.write = mvebu_pcie_wr_conf,
>  };
>  
> +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> +{
> +	struct mvebu_pcie_port *port = d->domain->host_data;
> +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> +	unsigned long flags;
> +	u32 unmask;
> +
> +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> +	unmask &= ~PCIE_INT_INTX(hwirq);
> +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> +}
> +
> +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> +{
> +	struct mvebu_pcie_port *port = d->domain->host_data;
> +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> +	unsigned long flags;
> +	u32 unmask;
> +
> +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> +	unmask |= PCIE_INT_INTX(hwirq);
> +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> +}
> +
> +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> +				   unsigned int virq, irq_hw_number_t hwirq)
> +{
> +	struct mvebu_pcie_port *port = h->host_data;
> +
> +	irq_set_status_flags(virq, IRQ_LEVEL);
> +	irq_set_chip_and_handler(virq, &port->intx_irq_chip, handle_level_irq);
> +	irq_set_chip_data(virq, port);
> +
> +	return 0;
> +}
> +
> +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> +	.map = mvebu_pcie_intx_irq_map,
> +	.xlate = irq_domain_xlate_onecell,
> +};
> +
> +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> +{
> +	struct device *dev = &port->pcie->pdev->dev;
> +	struct device_node *pcie_intc_node;
> +
> +	raw_spin_lock_init(&port->irq_lock);
> +
> +	port->intx_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL,
> +						  "mvebu-%s-INTx",
> +						  port->name);

That's exactly what I really don't want to see. It prevents sharing of
the irq_chip structure, and gets in the way of making it const in the
future. Yes, I know that some drivers do that. I can't fix those,
because /proc/interrupts is ABI. But I really don't want to see more
of these.

/sys/kernel/debug/irqs already has all the information you need, as it
will happily give you the domain name and the interrupt topology.

> +	port->intx_irq_chip.irq_mask = mvebu_pcie_intx_irq_mask;
> +	port->intx_irq_chip.irq_unmask = mvebu_pcie_intx_irq_unmask;
> +
> +	pcie_intc_node = of_get_next_child(port->dn, NULL);
> +	if (!pcie_intc_node) {
> +		dev_err(dev, "No PCIe Intc node found for %s\n", port->name);
> +		return -ENODEV;
> +	}
> +
> +	port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
> +						      &mvebu_pcie_intx_irq_domain_ops,
> +						      port);
> +	of_node_put(pcie_intc_node);
> +	if (!port->intx_irq_domain) {
> +		devm_kfree(dev, port->intx_irq_chip.name);
> +		dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name);
> +		return -ENOMEM;
> +	}
> +
> +	return 0;
> +}
> +
> +static void mvebu_pcie_irq_handler(struct irq_desc *desc)
> +{
> +	struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc);
> +	struct irq_chip *chip = irq_desc_get_chip(desc);
> +	struct device *dev = &port->pcie->pdev->dev;
> +	u32 cause, unmask, status;
> +	int i;
> +
> +	chained_irq_enter(chip, desc);
> +
> +	cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF);
> +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);

Why do you need to read this? If the CAUSE register also returns the
masked interrupts that are pending, it may be worth keeping a shadow
copy of the this register, as you end-up having an extra MMIO read on
each and every interrupt, which can't be great for performance.

> +	status = cause & unmask;
> +
> +	/* Process legacy INTx interrupts */
> +	for (i = 0; i < PCI_NUM_INTX; i++) {
> +		if (!(status & PCIE_INT_INTX(i)))
> +			continue;
> +
> +		if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL)
> +			dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A');
> +	}
> +
> +	chained_irq_exit(chip, desc);
> +}
> +
>  static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
>  {
>  	/* Interrupt support on mvebu emulated bridges is not implemented yet */
> @@ -1121,6 +1249,16 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
>  		port->io_attr = -1;
>  	}
>  
> +	/*
> +	 * Old DT bindings do not contain "intx" interrupt
> +	 * so do not fail probing driver when interrupt does not exist.
> +	 */
> +	port->intx_irq = of_irq_get_byname(child, "intx");
> +	if (port->intx_irq == -EPROBE_DEFER) {
> +		ret = port->intx_irq;
> +		goto err;
> +	}
> +
>  	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
>  	if (reset_gpio == -EPROBE_DEFER) {
>  		ret = reset_gpio;
> @@ -1317,6 +1455,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
>  
>  	for (i = 0; i < pcie->nports; i++) {
>  		struct mvebu_pcie_port *port = &pcie->ports[i];
> +		int irq = port->intx_irq;
>  
>  		child = port->dn;
>  		if (!child)
> @@ -1344,6 +1483,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
>  			continue;
>  		}
>  
> +		if (irq > 0) {
> +			ret = mvebu_pcie_init_irq_domain(port);
> +			if (ret) {
> +				dev_err(dev, "%s: cannot init irq domain\n",
> +					port->name);
> +				pci_bridge_emul_cleanup(&port->bridge);
> +				devm_iounmap(dev, port->base);
> +				port->base = NULL;
> +				mvebu_pcie_powerdown(port);
> +				continue;
> +			}
> +			irq_set_chained_handler_and_data(irq,
> +							 mvebu_pcie_irq_handler,
> +							 port);
> +		}
> +
>  		/*
>  		 * PCIe topology exported by mvebu hw is quite complicated. In
>  		 * reality has something like N fully independent host bridges
> @@ -1448,6 +1603,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
>  
>  	for (i = 0; i < pcie->nports; i++) {
>  		struct mvebu_pcie_port *port = &pcie->ports[i];
> +		int irq = port->intx_irq;
>  
>  		if (!port->base)
>  			continue;
> @@ -1458,7 +1614,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
>  		mvebu_writel(port, cmd, PCIE_CMD_OFF);
>  
>  		/* Mask all interrupt sources. */
> -		mvebu_writel(port, 0, PCIE_MASK_OFF);
> +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> +
> +		/* Clear all interrupt causes. */
> +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> +
> +		/* Remove IRQ domains. */
> +		if (port->intx_irq_domain)
> +			irq_domain_remove(port->intx_irq_domain);
> +
> +		if (irq > 0)
> +			irq_set_chained_handler_and_data(irq, NULL, NULL);
>  
>  		/* Free config space for emulated root bridge. */
>  		pci_bridge_emul_cleanup(&port->bridge);

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-01-06 15:28     ` Marc Zyngier
  0 siblings, 0 replies; 130+ messages in thread
From: Marc Zyngier @ 2022-01-06 15:28 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Wed, 05 Jan 2022 15:02:38 +0000,
Pali Rohár <pali@kernel.org> wrote:
> 
> This adds support for legacy INTx interrupts received from other PCIe
> devices and which are reported by a new INTx irq chip.
> 
> With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> interrupts.
> 
> Note that for this support, device tree files has to be properly adjusted
> to provide "interrupts" or "interrupts-extended" property with intx
> interrupt source, "interrupt-names" property with "intx" string and also
> 'interrupt-controller' subnode must be defined.
> 
> If device tree files do not provide these nodes then driver would work as
> before.
> 
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  drivers/pci/controller/pci-mvebu.c | 182 +++++++++++++++++++++++++++--
>  1 file changed, 174 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> index 1e90ab888075..04bcdd7b7a6d 100644
> --- a/drivers/pci/controller/pci-mvebu.c
> +++ b/drivers/pci/controller/pci-mvebu.c
> @@ -54,9 +54,10 @@
>  	 PCIE_CONF_ADDR_EN)
>  #define PCIE_CONF_DATA_OFF	0x18fc
>  #define PCIE_INT_CAUSE_OFF	0x1900
> +#define PCIE_INT_UNMASK_OFF	0x1910
> +#define  PCIE_INT_INTX(i)		BIT(24+i)
>  #define  PCIE_INT_PM_PME		BIT(28)
> -#define PCIE_MASK_OFF		0x1910
> -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
>  #define PCIE_CTRL_OFF		0x1a00
>  #define  PCIE_CTRL_X1_MODE		0x0001
>  #define  PCIE_CTRL_RC_MODE		BIT(1)
> @@ -110,6 +111,10 @@ struct mvebu_pcie_port {
>  	struct mvebu_pcie_window iowin;
>  	u32 saved_pcie_stat;
>  	struct resource regs;
> +	struct irq_domain *intx_irq_domain;
> +	struct irq_chip intx_irq_chip;

Why is this structure per port? It really should be global. Printing
the port number in the name isn't enough of a reason.

> +	raw_spinlock_t irq_lock;
> +	int intx_irq;
>  };
>  
>  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> @@ -235,7 +240,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
>  
>  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
>  {
> -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
>  
>  	/* Setup PCIe controller to Root Complex mode. */
>  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> @@ -288,10 +293,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
>  	/* Point PCIe unit MBUS decode windows to DRAM space. */
>  	mvebu_pcie_setup_wins(port);
>  
> -	/* Enable interrupt lines A-D. */
> -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> -	mask |= PCIE_MASK_ENABLE_INTS;
> -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> +	/* Mask all interrupt sources. */
> +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> +
> +	/* Clear all interrupt causes. */
> +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> +
> +	if (port->intx_irq <= 0) {
> +		/*
> +		 * When neither "summary" interrupt, nor "intx" interrupt was
> +		 * specified in DT then unmask all legacy INTx interrupts as in
> +		 * this case driver does not provide a way for masking and
> +		 * unmasking of individual legacy INTx interrupts. In this case
> +		 * all interrupts, including legacy INTx are reported via one
> +		 * shared GIC source and therefore kernel cannot distinguish
> +		 * which individual legacy INTx was triggered. These interrupts
> +		 * are shared, so it should not cause any issue. Just
> +		 * performance penalty as every PCIe interrupt handler needs to
> +		 * be called when some interrupt is triggered.
> +		 */
> +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);

Maybe worth printing a warning here, so that the user knows they are
on thin ice.

> +	}
>  }
>  
>  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> @@ -924,6 +949,109 @@ static struct pci_ops mvebu_pcie_ops = {
>  	.write = mvebu_pcie_wr_conf,
>  };
>  
> +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> +{
> +	struct mvebu_pcie_port *port = d->domain->host_data;
> +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> +	unsigned long flags;
> +	u32 unmask;
> +
> +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> +	unmask &= ~PCIE_INT_INTX(hwirq);
> +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> +}
> +
> +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> +{
> +	struct mvebu_pcie_port *port = d->domain->host_data;
> +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> +	unsigned long flags;
> +	u32 unmask;
> +
> +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> +	unmask |= PCIE_INT_INTX(hwirq);
> +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> +}
> +
> +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> +				   unsigned int virq, irq_hw_number_t hwirq)
> +{
> +	struct mvebu_pcie_port *port = h->host_data;
> +
> +	irq_set_status_flags(virq, IRQ_LEVEL);
> +	irq_set_chip_and_handler(virq, &port->intx_irq_chip, handle_level_irq);
> +	irq_set_chip_data(virq, port);
> +
> +	return 0;
> +}
> +
> +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> +	.map = mvebu_pcie_intx_irq_map,
> +	.xlate = irq_domain_xlate_onecell,
> +};
> +
> +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> +{
> +	struct device *dev = &port->pcie->pdev->dev;
> +	struct device_node *pcie_intc_node;
> +
> +	raw_spin_lock_init(&port->irq_lock);
> +
> +	port->intx_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL,
> +						  "mvebu-%s-INTx",
> +						  port->name);

That's exactly what I really don't want to see. It prevents sharing of
the irq_chip structure, and gets in the way of making it const in the
future. Yes, I know that some drivers do that. I can't fix those,
because /proc/interrupts is ABI. But I really don't want to see more
of these.

/sys/kernel/debug/irqs already has all the information you need, as it
will happily give you the domain name and the interrupt topology.

> +	port->intx_irq_chip.irq_mask = mvebu_pcie_intx_irq_mask;
> +	port->intx_irq_chip.irq_unmask = mvebu_pcie_intx_irq_unmask;
> +
> +	pcie_intc_node = of_get_next_child(port->dn, NULL);
> +	if (!pcie_intc_node) {
> +		dev_err(dev, "No PCIe Intc node found for %s\n", port->name);
> +		return -ENODEV;
> +	}
> +
> +	port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
> +						      &mvebu_pcie_intx_irq_domain_ops,
> +						      port);
> +	of_node_put(pcie_intc_node);
> +	if (!port->intx_irq_domain) {
> +		devm_kfree(dev, port->intx_irq_chip.name);
> +		dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name);
> +		return -ENOMEM;
> +	}
> +
> +	return 0;
> +}
> +
> +static void mvebu_pcie_irq_handler(struct irq_desc *desc)
> +{
> +	struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc);
> +	struct irq_chip *chip = irq_desc_get_chip(desc);
> +	struct device *dev = &port->pcie->pdev->dev;
> +	u32 cause, unmask, status;
> +	int i;
> +
> +	chained_irq_enter(chip, desc);
> +
> +	cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF);
> +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);

Why do you need to read this? If the CAUSE register also returns the
masked interrupts that are pending, it may be worth keeping a shadow
copy of the this register, as you end-up having an extra MMIO read on
each and every interrupt, which can't be great for performance.

> +	status = cause & unmask;
> +
> +	/* Process legacy INTx interrupts */
> +	for (i = 0; i < PCI_NUM_INTX; i++) {
> +		if (!(status & PCIE_INT_INTX(i)))
> +			continue;
> +
> +		if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL)
> +			dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A');
> +	}
> +
> +	chained_irq_exit(chip, desc);
> +}
> +
>  static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
>  {
>  	/* Interrupt support on mvebu emulated bridges is not implemented yet */
> @@ -1121,6 +1249,16 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
>  		port->io_attr = -1;
>  	}
>  
> +	/*
> +	 * Old DT bindings do not contain "intx" interrupt
> +	 * so do not fail probing driver when interrupt does not exist.
> +	 */
> +	port->intx_irq = of_irq_get_byname(child, "intx");
> +	if (port->intx_irq == -EPROBE_DEFER) {
> +		ret = port->intx_irq;
> +		goto err;
> +	}
> +
>  	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
>  	if (reset_gpio == -EPROBE_DEFER) {
>  		ret = reset_gpio;
> @@ -1317,6 +1455,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
>  
>  	for (i = 0; i < pcie->nports; i++) {
>  		struct mvebu_pcie_port *port = &pcie->ports[i];
> +		int irq = port->intx_irq;
>  
>  		child = port->dn;
>  		if (!child)
> @@ -1344,6 +1483,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
>  			continue;
>  		}
>  
> +		if (irq > 0) {
> +			ret = mvebu_pcie_init_irq_domain(port);
> +			if (ret) {
> +				dev_err(dev, "%s: cannot init irq domain\n",
> +					port->name);
> +				pci_bridge_emul_cleanup(&port->bridge);
> +				devm_iounmap(dev, port->base);
> +				port->base = NULL;
> +				mvebu_pcie_powerdown(port);
> +				continue;
> +			}
> +			irq_set_chained_handler_and_data(irq,
> +							 mvebu_pcie_irq_handler,
> +							 port);
> +		}
> +
>  		/*
>  		 * PCIe topology exported by mvebu hw is quite complicated. In
>  		 * reality has something like N fully independent host bridges
> @@ -1448,6 +1603,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
>  
>  	for (i = 0; i < pcie->nports; i++) {
>  		struct mvebu_pcie_port *port = &pcie->ports[i];
> +		int irq = port->intx_irq;
>  
>  		if (!port->base)
>  			continue;
> @@ -1458,7 +1614,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
>  		mvebu_writel(port, cmd, PCIE_CMD_OFF);
>  
>  		/* Mask all interrupt sources. */
> -		mvebu_writel(port, 0, PCIE_MASK_OFF);
> +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> +
> +		/* Clear all interrupt causes. */
> +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> +
> +		/* Remove IRQ domains. */
> +		if (port->intx_irq_domain)
> +			irq_domain_remove(port->intx_irq_domain);
> +
> +		if (irq > 0)
> +			irq_set_chained_handler_and_data(irq, NULL, NULL);
>  
>  		/* Free config space for emulated root bridge. */
>  		pci_bridge_emul_cleanup(&port->bridge);

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-01-06 15:28     ` Marc Zyngier
@ 2022-01-06 15:44       ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-06 15:44 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thursday 06 January 2022 15:28:20 Marc Zyngier wrote:
> On Wed, 05 Jan 2022 15:02:38 +0000,
> Pali Rohár <pali@kernel.org> wrote:
> > 
> > This adds support for legacy INTx interrupts received from other PCIe
> > devices and which are reported by a new INTx irq chip.
> > 
> > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > interrupts.
> > 
> > Note that for this support, device tree files has to be properly adjusted
> > to provide "interrupts" or "interrupts-extended" property with intx
> > interrupt source, "interrupt-names" property with "intx" string and also
> > 'interrupt-controller' subnode must be defined.
> > 
> > If device tree files do not provide these nodes then driver would work as
> > before.
> > 
> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > ---
> >  drivers/pci/controller/pci-mvebu.c | 182 +++++++++++++++++++++++++++--
> >  1 file changed, 174 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > index 1e90ab888075..04bcdd7b7a6d 100644
> > --- a/drivers/pci/controller/pci-mvebu.c
> > +++ b/drivers/pci/controller/pci-mvebu.c
> > @@ -54,9 +54,10 @@
> >  	 PCIE_CONF_ADDR_EN)
> >  #define PCIE_CONF_DATA_OFF	0x18fc
> >  #define PCIE_INT_CAUSE_OFF	0x1900
> > +#define PCIE_INT_UNMASK_OFF	0x1910
> > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> >  #define  PCIE_INT_PM_PME		BIT(28)
> > -#define PCIE_MASK_OFF		0x1910
> > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> >  #define PCIE_CTRL_OFF		0x1a00
> >  #define  PCIE_CTRL_X1_MODE		0x0001
> >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > @@ -110,6 +111,10 @@ struct mvebu_pcie_port {
> >  	struct mvebu_pcie_window iowin;
> >  	u32 saved_pcie_stat;
> >  	struct resource regs;
> > +	struct irq_domain *intx_irq_domain;
> > +	struct irq_chip intx_irq_chip;
> 
> Why is this structure per port? It really should be global. Printing
> the port number in the name isn't enough of a reason.

Because each port has its own independent set of INTA-INTD interrupts.

> > +	raw_spinlock_t irq_lock;
> > +	int intx_irq;
> >  };
> >  
> >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > @@ -235,7 +240,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> >  
> >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> >  {
> > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> >  
> >  	/* Setup PCIe controller to Root Complex mode. */
> >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > @@ -288,10 +293,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> >  	mvebu_pcie_setup_wins(port);
> >  
> > -	/* Enable interrupt lines A-D. */
> > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > -	mask |= PCIE_MASK_ENABLE_INTS;
> > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > +	/* Mask all interrupt sources. */
> > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > +
> > +	/* Clear all interrupt causes. */
> > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > +
> > +	if (port->intx_irq <= 0) {
> > +		/*
> > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > +		 * this case driver does not provide a way for masking and
> > +		 * unmasking of individual legacy INTx interrupts. In this case
> > +		 * all interrupts, including legacy INTx are reported via one
> > +		 * shared GIC source and therefore kernel cannot distinguish
> > +		 * which individual legacy INTx was triggered. These interrupts
> > +		 * are shared, so it should not cause any issue. Just
> > +		 * performance penalty as every PCIe interrupt handler needs to
> > +		 * be called when some interrupt is triggered.
> > +		 */
> > +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> > +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> > +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> 
> Maybe worth printing a warning here, so that the user knows they are
> on thin ice.

Ok. I can add it here. Anyway, this is default current state without
this patch.

> > +	}
> >  }
> >  
> >  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > @@ -924,6 +949,109 @@ static struct pci_ops mvebu_pcie_ops = {
> >  	.write = mvebu_pcie_wr_conf,
> >  };
> >  
> > +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> > +{
> > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > +	unsigned long flags;
> > +	u32 unmask;
> > +
> > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > +	unmask &= ~PCIE_INT_INTX(hwirq);
> > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > +}
> > +
> > +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> > +{
> > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > +	unsigned long flags;
> > +	u32 unmask;
> > +
> > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > +	unmask |= PCIE_INT_INTX(hwirq);
> > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > +}
> > +
> > +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> > +				   unsigned int virq, irq_hw_number_t hwirq)
> > +{
> > +	struct mvebu_pcie_port *port = h->host_data;
> > +
> > +	irq_set_status_flags(virq, IRQ_LEVEL);
> > +	irq_set_chip_and_handler(virq, &port->intx_irq_chip, handle_level_irq);
> > +	irq_set_chip_data(virq, port);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> > +	.map = mvebu_pcie_intx_irq_map,
> > +	.xlate = irq_domain_xlate_onecell,
> > +};
> > +
> > +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> > +{
> > +	struct device *dev = &port->pcie->pdev->dev;
> > +	struct device_node *pcie_intc_node;
> > +
> > +	raw_spin_lock_init(&port->irq_lock);
> > +
> > +	port->intx_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL,
> > +						  "mvebu-%s-INTx",
> > +						  port->name);
> 
> That's exactly what I really don't want to see. It prevents sharing of
> the irq_chip structure, and gets in the way of making it const in the
> future. Yes, I know that some drivers do that. I can't fix those,
> because /proc/interrupts is ABI. But I really don't want to see more
> of these.

Well, I do not understand why it should be shared and with who. HW has N
independent IRQ chips for legacy interrupts. And each one will be
specified in DT per HW layout / design.

> /sys/kernel/debug/irqs already has all the information you need, as it
> will happily give you the domain name and the interrupt topology.
> 
> > +	port->intx_irq_chip.irq_mask = mvebu_pcie_intx_irq_mask;
> > +	port->intx_irq_chip.irq_unmask = mvebu_pcie_intx_irq_unmask;
> > +
> > +	pcie_intc_node = of_get_next_child(port->dn, NULL);
> > +	if (!pcie_intc_node) {
> > +		dev_err(dev, "No PCIe Intc node found for %s\n", port->name);
> > +		return -ENODEV;
> > +	}
> > +
> > +	port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
> > +						      &mvebu_pcie_intx_irq_domain_ops,
> > +						      port);
> > +	of_node_put(pcie_intc_node);
> > +	if (!port->intx_irq_domain) {
> > +		devm_kfree(dev, port->intx_irq_chip.name);
> > +		dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static void mvebu_pcie_irq_handler(struct irq_desc *desc)
> > +{
> > +	struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc);
> > +	struct irq_chip *chip = irq_desc_get_chip(desc);
> > +	struct device *dev = &port->pcie->pdev->dev;
> > +	u32 cause, unmask, status;
> > +	int i;
> > +
> > +	chained_irq_enter(chip, desc);
> > +
> > +	cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF);
> > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> 
> Why do you need to read this? If the CAUSE register also returns the
> masked interrupts that are pending,

Yes, it returns all interrupts, even those which are masked for which is
not system interested.

> it may be worth keeping a shadow
> copy of the this register, as you end-up having an extra MMIO read on
> each and every interrupt, which can't be great for performance.

Ok. I can set shadow copy of unmask register into port structure. But it
has really performance impact when reading directly unmask register from
hw and when reading it from port shadow copy structure?

> > +	status = cause & unmask;
> > +
> > +	/* Process legacy INTx interrupts */
> > +	for (i = 0; i < PCI_NUM_INTX; i++) {
> > +		if (!(status & PCIE_INT_INTX(i)))
> > +			continue;
> > +
> > +		if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL)
> > +			dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A');
> > +	}
> > +
> > +	chained_irq_exit(chip, desc);
> > +}
> > +
> >  static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> >  {
> >  	/* Interrupt support on mvebu emulated bridges is not implemented yet */
> > @@ -1121,6 +1249,16 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
> >  		port->io_attr = -1;
> >  	}
> >  
> > +	/*
> > +	 * Old DT bindings do not contain "intx" interrupt
> > +	 * so do not fail probing driver when interrupt does not exist.
> > +	 */
> > +	port->intx_irq = of_irq_get_byname(child, "intx");
> > +	if (port->intx_irq == -EPROBE_DEFER) {
> > +		ret = port->intx_irq;
> > +		goto err;
> > +	}
> > +
> >  	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
> >  	if (reset_gpio == -EPROBE_DEFER) {
> >  		ret = reset_gpio;
> > @@ -1317,6 +1455,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
> >  
> >  	for (i = 0; i < pcie->nports; i++) {
> >  		struct mvebu_pcie_port *port = &pcie->ports[i];
> > +		int irq = port->intx_irq;
> >  
> >  		child = port->dn;
> >  		if (!child)
> > @@ -1344,6 +1483,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
> >  			continue;
> >  		}
> >  
> > +		if (irq > 0) {
> > +			ret = mvebu_pcie_init_irq_domain(port);
> > +			if (ret) {
> > +				dev_err(dev, "%s: cannot init irq domain\n",
> > +					port->name);
> > +				pci_bridge_emul_cleanup(&port->bridge);
> > +				devm_iounmap(dev, port->base);
> > +				port->base = NULL;
> > +				mvebu_pcie_powerdown(port);
> > +				continue;
> > +			}
> > +			irq_set_chained_handler_and_data(irq,
> > +							 mvebu_pcie_irq_handler,
> > +							 port);
> > +		}
> > +
> >  		/*
> >  		 * PCIe topology exported by mvebu hw is quite complicated. In
> >  		 * reality has something like N fully independent host bridges
> > @@ -1448,6 +1603,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
> >  
> >  	for (i = 0; i < pcie->nports; i++) {
> >  		struct mvebu_pcie_port *port = &pcie->ports[i];
> > +		int irq = port->intx_irq;
> >  
> >  		if (!port->base)
> >  			continue;
> > @@ -1458,7 +1614,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
> >  		mvebu_writel(port, cmd, PCIE_CMD_OFF);
> >  
> >  		/* Mask all interrupt sources. */
> > -		mvebu_writel(port, 0, PCIE_MASK_OFF);
> > +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > +
> > +		/* Clear all interrupt causes. */
> > +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > +
> > +		/* Remove IRQ domains. */
> > +		if (port->intx_irq_domain)
> > +			irq_domain_remove(port->intx_irq_domain);
> > +
> > +		if (irq > 0)
> > +			irq_set_chained_handler_and_data(irq, NULL, NULL);
> >  
> >  		/* Free config space for emulated root bridge. */
> >  		pci_bridge_emul_cleanup(&port->bridge);
> 
> Thanks,
> 
> 	M.
> 
> -- 
> Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-01-06 15:44       ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-06 15:44 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thursday 06 January 2022 15:28:20 Marc Zyngier wrote:
> On Wed, 05 Jan 2022 15:02:38 +0000,
> Pali Rohár <pali@kernel.org> wrote:
> > 
> > This adds support for legacy INTx interrupts received from other PCIe
> > devices and which are reported by a new INTx irq chip.
> > 
> > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > interrupts.
> > 
> > Note that for this support, device tree files has to be properly adjusted
> > to provide "interrupts" or "interrupts-extended" property with intx
> > interrupt source, "interrupt-names" property with "intx" string and also
> > 'interrupt-controller' subnode must be defined.
> > 
> > If device tree files do not provide these nodes then driver would work as
> > before.
> > 
> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > ---
> >  drivers/pci/controller/pci-mvebu.c | 182 +++++++++++++++++++++++++++--
> >  1 file changed, 174 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > index 1e90ab888075..04bcdd7b7a6d 100644
> > --- a/drivers/pci/controller/pci-mvebu.c
> > +++ b/drivers/pci/controller/pci-mvebu.c
> > @@ -54,9 +54,10 @@
> >  	 PCIE_CONF_ADDR_EN)
> >  #define PCIE_CONF_DATA_OFF	0x18fc
> >  #define PCIE_INT_CAUSE_OFF	0x1900
> > +#define PCIE_INT_UNMASK_OFF	0x1910
> > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> >  #define  PCIE_INT_PM_PME		BIT(28)
> > -#define PCIE_MASK_OFF		0x1910
> > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> >  #define PCIE_CTRL_OFF		0x1a00
> >  #define  PCIE_CTRL_X1_MODE		0x0001
> >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > @@ -110,6 +111,10 @@ struct mvebu_pcie_port {
> >  	struct mvebu_pcie_window iowin;
> >  	u32 saved_pcie_stat;
> >  	struct resource regs;
> > +	struct irq_domain *intx_irq_domain;
> > +	struct irq_chip intx_irq_chip;
> 
> Why is this structure per port? It really should be global. Printing
> the port number in the name isn't enough of a reason.

Because each port has its own independent set of INTA-INTD interrupts.

> > +	raw_spinlock_t irq_lock;
> > +	int intx_irq;
> >  };
> >  
> >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > @@ -235,7 +240,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> >  
> >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> >  {
> > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> >  
> >  	/* Setup PCIe controller to Root Complex mode. */
> >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > @@ -288,10 +293,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> >  	mvebu_pcie_setup_wins(port);
> >  
> > -	/* Enable interrupt lines A-D. */
> > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > -	mask |= PCIE_MASK_ENABLE_INTS;
> > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > +	/* Mask all interrupt sources. */
> > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > +
> > +	/* Clear all interrupt causes. */
> > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > +
> > +	if (port->intx_irq <= 0) {
> > +		/*
> > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > +		 * this case driver does not provide a way for masking and
> > +		 * unmasking of individual legacy INTx interrupts. In this case
> > +		 * all interrupts, including legacy INTx are reported via one
> > +		 * shared GIC source and therefore kernel cannot distinguish
> > +		 * which individual legacy INTx was triggered. These interrupts
> > +		 * are shared, so it should not cause any issue. Just
> > +		 * performance penalty as every PCIe interrupt handler needs to
> > +		 * be called when some interrupt is triggered.
> > +		 */
> > +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> > +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> > +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> 
> Maybe worth printing a warning here, so that the user knows they are
> on thin ice.

Ok. I can add it here. Anyway, this is default current state without
this patch.

> > +	}
> >  }
> >  
> >  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > @@ -924,6 +949,109 @@ static struct pci_ops mvebu_pcie_ops = {
> >  	.write = mvebu_pcie_wr_conf,
> >  };
> >  
> > +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> > +{
> > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > +	unsigned long flags;
> > +	u32 unmask;
> > +
> > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > +	unmask &= ~PCIE_INT_INTX(hwirq);
> > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > +}
> > +
> > +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> > +{
> > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > +	unsigned long flags;
> > +	u32 unmask;
> > +
> > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > +	unmask |= PCIE_INT_INTX(hwirq);
> > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > +}
> > +
> > +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> > +				   unsigned int virq, irq_hw_number_t hwirq)
> > +{
> > +	struct mvebu_pcie_port *port = h->host_data;
> > +
> > +	irq_set_status_flags(virq, IRQ_LEVEL);
> > +	irq_set_chip_and_handler(virq, &port->intx_irq_chip, handle_level_irq);
> > +	irq_set_chip_data(virq, port);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> > +	.map = mvebu_pcie_intx_irq_map,
> > +	.xlate = irq_domain_xlate_onecell,
> > +};
> > +
> > +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> > +{
> > +	struct device *dev = &port->pcie->pdev->dev;
> > +	struct device_node *pcie_intc_node;
> > +
> > +	raw_spin_lock_init(&port->irq_lock);
> > +
> > +	port->intx_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL,
> > +						  "mvebu-%s-INTx",
> > +						  port->name);
> 
> That's exactly what I really don't want to see. It prevents sharing of
> the irq_chip structure, and gets in the way of making it const in the
> future. Yes, I know that some drivers do that. I can't fix those,
> because /proc/interrupts is ABI. But I really don't want to see more
> of these.

Well, I do not understand why it should be shared and with who. HW has N
independent IRQ chips for legacy interrupts. And each one will be
specified in DT per HW layout / design.

> /sys/kernel/debug/irqs already has all the information you need, as it
> will happily give you the domain name and the interrupt topology.
> 
> > +	port->intx_irq_chip.irq_mask = mvebu_pcie_intx_irq_mask;
> > +	port->intx_irq_chip.irq_unmask = mvebu_pcie_intx_irq_unmask;
> > +
> > +	pcie_intc_node = of_get_next_child(port->dn, NULL);
> > +	if (!pcie_intc_node) {
> > +		dev_err(dev, "No PCIe Intc node found for %s\n", port->name);
> > +		return -ENODEV;
> > +	}
> > +
> > +	port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
> > +						      &mvebu_pcie_intx_irq_domain_ops,
> > +						      port);
> > +	of_node_put(pcie_intc_node);
> > +	if (!port->intx_irq_domain) {
> > +		devm_kfree(dev, port->intx_irq_chip.name);
> > +		dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static void mvebu_pcie_irq_handler(struct irq_desc *desc)
> > +{
> > +	struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc);
> > +	struct irq_chip *chip = irq_desc_get_chip(desc);
> > +	struct device *dev = &port->pcie->pdev->dev;
> > +	u32 cause, unmask, status;
> > +	int i;
> > +
> > +	chained_irq_enter(chip, desc);
> > +
> > +	cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF);
> > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> 
> Why do you need to read this? If the CAUSE register also returns the
> masked interrupts that are pending,

Yes, it returns all interrupts, even those which are masked for which is
not system interested.

> it may be worth keeping a shadow
> copy of the this register, as you end-up having an extra MMIO read on
> each and every interrupt, which can't be great for performance.

Ok. I can set shadow copy of unmask register into port structure. But it
has really performance impact when reading directly unmask register from
hw and when reading it from port shadow copy structure?

> > +	status = cause & unmask;
> > +
> > +	/* Process legacy INTx interrupts */
> > +	for (i = 0; i < PCI_NUM_INTX; i++) {
> > +		if (!(status & PCIE_INT_INTX(i)))
> > +			continue;
> > +
> > +		if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL)
> > +			dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A');
> > +	}
> > +
> > +	chained_irq_exit(chip, desc);
> > +}
> > +
> >  static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> >  {
> >  	/* Interrupt support on mvebu emulated bridges is not implemented yet */
> > @@ -1121,6 +1249,16 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
> >  		port->io_attr = -1;
> >  	}
> >  
> > +	/*
> > +	 * Old DT bindings do not contain "intx" interrupt
> > +	 * so do not fail probing driver when interrupt does not exist.
> > +	 */
> > +	port->intx_irq = of_irq_get_byname(child, "intx");
> > +	if (port->intx_irq == -EPROBE_DEFER) {
> > +		ret = port->intx_irq;
> > +		goto err;
> > +	}
> > +
> >  	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
> >  	if (reset_gpio == -EPROBE_DEFER) {
> >  		ret = reset_gpio;
> > @@ -1317,6 +1455,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
> >  
> >  	for (i = 0; i < pcie->nports; i++) {
> >  		struct mvebu_pcie_port *port = &pcie->ports[i];
> > +		int irq = port->intx_irq;
> >  
> >  		child = port->dn;
> >  		if (!child)
> > @@ -1344,6 +1483,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
> >  			continue;
> >  		}
> >  
> > +		if (irq > 0) {
> > +			ret = mvebu_pcie_init_irq_domain(port);
> > +			if (ret) {
> > +				dev_err(dev, "%s: cannot init irq domain\n",
> > +					port->name);
> > +				pci_bridge_emul_cleanup(&port->bridge);
> > +				devm_iounmap(dev, port->base);
> > +				port->base = NULL;
> > +				mvebu_pcie_powerdown(port);
> > +				continue;
> > +			}
> > +			irq_set_chained_handler_and_data(irq,
> > +							 mvebu_pcie_irq_handler,
> > +							 port);
> > +		}
> > +
> >  		/*
> >  		 * PCIe topology exported by mvebu hw is quite complicated. In
> >  		 * reality has something like N fully independent host bridges
> > @@ -1448,6 +1603,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
> >  
> >  	for (i = 0; i < pcie->nports; i++) {
> >  		struct mvebu_pcie_port *port = &pcie->ports[i];
> > +		int irq = port->intx_irq;
> >  
> >  		if (!port->base)
> >  			continue;
> > @@ -1458,7 +1614,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
> >  		mvebu_writel(port, cmd, PCIE_CMD_OFF);
> >  
> >  		/* Mask all interrupt sources. */
> > -		mvebu_writel(port, 0, PCIE_MASK_OFF);
> > +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > +
> > +		/* Clear all interrupt causes. */
> > +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > +
> > +		/* Remove IRQ domains. */
> > +		if (port->intx_irq_domain)
> > +			irq_domain_remove(port->intx_irq_domain);
> > +
> > +		if (irq > 0)
> > +			irq_set_chained_handler_and_data(irq, NULL, NULL);
> >  
> >  		/* Free config space for emulated root bridge. */
> >  		pci_bridge_emul_cleanup(&port->bridge);
> 
> Thanks,
> 
> 	M.
> 
> -- 
> Without deviation from the norm, progress is not possible.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-01-06 15:44       ` Pali Rohár
@ 2022-01-06 15:55         ` Marc Zyngier
  -1 siblings, 0 replies; 130+ messages in thread
From: Marc Zyngier @ 2022-01-06 15:55 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thu, 06 Jan 2022 15:44:47 +0000,
Pali Rohár <pali@kernel.org> wrote:
> 
> On Thursday 06 January 2022 15:28:20 Marc Zyngier wrote:
> > On Wed, 05 Jan 2022 15:02:38 +0000,
> > Pali Rohár <pali@kernel.org> wrote:
> > > 
> > > This adds support for legacy INTx interrupts received from other PCIe
> > > devices and which are reported by a new INTx irq chip.
> > > 
> > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > interrupts.
> > > 
> > > Note that for this support, device tree files has to be properly adjusted
> > > to provide "interrupts" or "interrupts-extended" property with intx
> > > interrupt source, "interrupt-names" property with "intx" string and also
> > > 'interrupt-controller' subnode must be defined.
> > > 
> > > If device tree files do not provide these nodes then driver would work as
> > > before.
> > > 
> > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > ---
> > >  drivers/pci/controller/pci-mvebu.c | 182 +++++++++++++++++++++++++++--
> > >  1 file changed, 174 insertions(+), 8 deletions(-)
> > > 
> > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > index 1e90ab888075..04bcdd7b7a6d 100644
> > > --- a/drivers/pci/controller/pci-mvebu.c
> > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > @@ -54,9 +54,10 @@
> > >  	 PCIE_CONF_ADDR_EN)
> > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > -#define PCIE_MASK_OFF		0x1910
> > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > >  #define PCIE_CTRL_OFF		0x1a00
> > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > @@ -110,6 +111,10 @@ struct mvebu_pcie_port {
> > >  	struct mvebu_pcie_window iowin;
> > >  	u32 saved_pcie_stat;
> > >  	struct resource regs;
> > > +	struct irq_domain *intx_irq_domain;
> > > +	struct irq_chip intx_irq_chip;
> > 
> > Why is this structure per port? It really should be global. Printing
> > the port number in the name isn't enough of a reason.
> 
> Because each port has its own independent set of INTA-INTD
> interrupts.

That doesn't warrant a copy of an irq_chip structure that contains the
exact same callbacks, and only differs by *a string*. And the use of
this string is only to end-up in /proc/interrupts, which is totally
pointless.

> 
> > > +	raw_spinlock_t irq_lock;
> > > +	int intx_irq;
> > >  };
> > >  
> > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > @@ -235,7 +240,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > >  
> > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > >  {
> > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > >  
> > >  	/* Setup PCIe controller to Root Complex mode. */
> > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > @@ -288,10 +293,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > >  	mvebu_pcie_setup_wins(port);
> > >  
> > > -	/* Enable interrupt lines A-D. */
> > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > +	/* Mask all interrupt sources. */
> > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > +
> > > +	/* Clear all interrupt causes. */
> > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > +
> > > +	if (port->intx_irq <= 0) {
> > > +		/*
> > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > +		 * this case driver does not provide a way for masking and
> > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > +		 * all interrupts, including legacy INTx are reported via one
> > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > +		 * which individual legacy INTx was triggered. These interrupts
> > > +		 * are shared, so it should not cause any issue. Just
> > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > +		 * be called when some interrupt is triggered.
> > > +		 */
> > > +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> > > +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> > > +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > 
> > Maybe worth printing a warning here, so that the user knows they are
> > on thin ice.
> 
> Ok. I can add it here. Anyway, this is default current state without
> this patch.
> 
> > > +	}
> > >  }
> > >  
> > >  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > > @@ -924,6 +949,109 @@ static struct pci_ops mvebu_pcie_ops = {
> > >  	.write = mvebu_pcie_wr_conf,
> > >  };
> > >  
> > > +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> > > +{
> > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > +	unsigned long flags;
> > > +	u32 unmask;
> > > +
> > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > +	unmask &= ~PCIE_INT_INTX(hwirq);
> > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > +}
> > > +
> > > +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> > > +{
> > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > +	unsigned long flags;
> > > +	u32 unmask;
> > > +
> > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > +	unmask |= PCIE_INT_INTX(hwirq);
> > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > +}
> > > +
> > > +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> > > +				   unsigned int virq, irq_hw_number_t hwirq)
> > > +{
> > > +	struct mvebu_pcie_port *port = h->host_data;
> > > +
> > > +	irq_set_status_flags(virq, IRQ_LEVEL);
> > > +	irq_set_chip_and_handler(virq, &port->intx_irq_chip, handle_level_irq);
> > > +	irq_set_chip_data(virq, port);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> > > +	.map = mvebu_pcie_intx_irq_map,
> > > +	.xlate = irq_domain_xlate_onecell,
> > > +};
> > > +
> > > +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> > > +{
> > > +	struct device *dev = &port->pcie->pdev->dev;
> > > +	struct device_node *pcie_intc_node;
> > > +
> > > +	raw_spin_lock_init(&port->irq_lock);
> > > +
> > > +	port->intx_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL,
> > > +						  "mvebu-%s-INTx",
> > > +						  port->name);
> > 
> > That's exactly what I really don't want to see. It prevents sharing of
> > the irq_chip structure, and gets in the way of making it const in the
> > future. Yes, I know that some drivers do that. I can't fix those,
> > because /proc/interrupts is ABI. But I really don't want to see more
> > of these.
> 
> Well, I do not understand why it should be shared and with who. HW has N
> independent IRQ chips for legacy interrupts. And each one will be
> specified in DT per HW layout / design.

If you have multiple ports, all the ports can share the irq_chip
structure. Actually scratch that. They *MUST* share the structure. The
only reason you're not sharing it is to be able to print this useless
string in /proc/interrupts.

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-01-06 15:55         ` Marc Zyngier
  0 siblings, 0 replies; 130+ messages in thread
From: Marc Zyngier @ 2022-01-06 15:55 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thu, 06 Jan 2022 15:44:47 +0000,
Pali Rohár <pali@kernel.org> wrote:
> 
> On Thursday 06 January 2022 15:28:20 Marc Zyngier wrote:
> > On Wed, 05 Jan 2022 15:02:38 +0000,
> > Pali Rohár <pali@kernel.org> wrote:
> > > 
> > > This adds support for legacy INTx interrupts received from other PCIe
> > > devices and which are reported by a new INTx irq chip.
> > > 
> > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > interrupts.
> > > 
> > > Note that for this support, device tree files has to be properly adjusted
> > > to provide "interrupts" or "interrupts-extended" property with intx
> > > interrupt source, "interrupt-names" property with "intx" string and also
> > > 'interrupt-controller' subnode must be defined.
> > > 
> > > If device tree files do not provide these nodes then driver would work as
> > > before.
> > > 
> > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > ---
> > >  drivers/pci/controller/pci-mvebu.c | 182 +++++++++++++++++++++++++++--
> > >  1 file changed, 174 insertions(+), 8 deletions(-)
> > > 
> > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > index 1e90ab888075..04bcdd7b7a6d 100644
> > > --- a/drivers/pci/controller/pci-mvebu.c
> > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > @@ -54,9 +54,10 @@
> > >  	 PCIE_CONF_ADDR_EN)
> > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > -#define PCIE_MASK_OFF		0x1910
> > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > >  #define PCIE_CTRL_OFF		0x1a00
> > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > @@ -110,6 +111,10 @@ struct mvebu_pcie_port {
> > >  	struct mvebu_pcie_window iowin;
> > >  	u32 saved_pcie_stat;
> > >  	struct resource regs;
> > > +	struct irq_domain *intx_irq_domain;
> > > +	struct irq_chip intx_irq_chip;
> > 
> > Why is this structure per port? It really should be global. Printing
> > the port number in the name isn't enough of a reason.
> 
> Because each port has its own independent set of INTA-INTD
> interrupts.

That doesn't warrant a copy of an irq_chip structure that contains the
exact same callbacks, and only differs by *a string*. And the use of
this string is only to end-up in /proc/interrupts, which is totally
pointless.

> 
> > > +	raw_spinlock_t irq_lock;
> > > +	int intx_irq;
> > >  };
> > >  
> > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > @@ -235,7 +240,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > >  
> > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > >  {
> > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > >  
> > >  	/* Setup PCIe controller to Root Complex mode. */
> > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > @@ -288,10 +293,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > >  	mvebu_pcie_setup_wins(port);
> > >  
> > > -	/* Enable interrupt lines A-D. */
> > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > +	/* Mask all interrupt sources. */
> > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > +
> > > +	/* Clear all interrupt causes. */
> > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > +
> > > +	if (port->intx_irq <= 0) {
> > > +		/*
> > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > +		 * this case driver does not provide a way for masking and
> > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > +		 * all interrupts, including legacy INTx are reported via one
> > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > +		 * which individual legacy INTx was triggered. These interrupts
> > > +		 * are shared, so it should not cause any issue. Just
> > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > +		 * be called when some interrupt is triggered.
> > > +		 */
> > > +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> > > +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> > > +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > 
> > Maybe worth printing a warning here, so that the user knows they are
> > on thin ice.
> 
> Ok. I can add it here. Anyway, this is default current state without
> this patch.
> 
> > > +	}
> > >  }
> > >  
> > >  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > > @@ -924,6 +949,109 @@ static struct pci_ops mvebu_pcie_ops = {
> > >  	.write = mvebu_pcie_wr_conf,
> > >  };
> > >  
> > > +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> > > +{
> > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > +	unsigned long flags;
> > > +	u32 unmask;
> > > +
> > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > +	unmask &= ~PCIE_INT_INTX(hwirq);
> > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > +}
> > > +
> > > +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> > > +{
> > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > +	unsigned long flags;
> > > +	u32 unmask;
> > > +
> > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > +	unmask |= PCIE_INT_INTX(hwirq);
> > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > +}
> > > +
> > > +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> > > +				   unsigned int virq, irq_hw_number_t hwirq)
> > > +{
> > > +	struct mvebu_pcie_port *port = h->host_data;
> > > +
> > > +	irq_set_status_flags(virq, IRQ_LEVEL);
> > > +	irq_set_chip_and_handler(virq, &port->intx_irq_chip, handle_level_irq);
> > > +	irq_set_chip_data(virq, port);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> > > +	.map = mvebu_pcie_intx_irq_map,
> > > +	.xlate = irq_domain_xlate_onecell,
> > > +};
> > > +
> > > +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> > > +{
> > > +	struct device *dev = &port->pcie->pdev->dev;
> > > +	struct device_node *pcie_intc_node;
> > > +
> > > +	raw_spin_lock_init(&port->irq_lock);
> > > +
> > > +	port->intx_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL,
> > > +						  "mvebu-%s-INTx",
> > > +						  port->name);
> > 
> > That's exactly what I really don't want to see. It prevents sharing of
> > the irq_chip structure, and gets in the way of making it const in the
> > future. Yes, I know that some drivers do that. I can't fix those,
> > because /proc/interrupts is ABI. But I really don't want to see more
> > of these.
> 
> Well, I do not understand why it should be shared and with who. HW has N
> independent IRQ chips for legacy interrupts. And each one will be
> specified in DT per HW layout / design.

If you have multiple ports, all the ports can share the irq_chip
structure. Actually scratch that. They *MUST* share the structure. The
only reason you're not sharing it is to be able to print this useless
string in /proc/interrupts.

	M.

-- 
Without deviation from the norm, progress is not possible.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-01-06 15:55         ` Marc Zyngier
@ 2022-01-06 16:20           ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-06 16:20 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thursday 06 January 2022 15:55:11 Marc Zyngier wrote:
> On Thu, 06 Jan 2022 15:44:47 +0000,
> Pali Rohár <pali@kernel.org> wrote:
> > 
> > On Thursday 06 January 2022 15:28:20 Marc Zyngier wrote:
> > > On Wed, 05 Jan 2022 15:02:38 +0000,
> > > Pali Rohár <pali@kernel.org> wrote:
> > > > 
> > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > devices and which are reported by a new INTx irq chip.
> > > > 
> > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > interrupts.
> > > > 
> > > > Note that for this support, device tree files has to be properly adjusted
> > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > 'interrupt-controller' subnode must be defined.
> > > > 
> > > > If device tree files do not provide these nodes then driver would work as
> > > > before.
> > > > 
> > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > ---
> > > >  drivers/pci/controller/pci-mvebu.c | 182 +++++++++++++++++++++++++++--
> > > >  1 file changed, 174 insertions(+), 8 deletions(-)
> > > > 
> > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > index 1e90ab888075..04bcdd7b7a6d 100644
> > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > @@ -54,9 +54,10 @@
> > > >  	 PCIE_CONF_ADDR_EN)
> > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > -#define PCIE_MASK_OFF		0x1910
> > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > >  #define PCIE_CTRL_OFF		0x1a00
> > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > @@ -110,6 +111,10 @@ struct mvebu_pcie_port {
> > > >  	struct mvebu_pcie_window iowin;
> > > >  	u32 saved_pcie_stat;
> > > >  	struct resource regs;
> > > > +	struct irq_domain *intx_irq_domain;
> > > > +	struct irq_chip intx_irq_chip;
> > > 
> > > Why is this structure per port? It really should be global. Printing
> > > the port number in the name isn't enough of a reason.
> > 
> > Because each port has its own independent set of INTA-INTD
> > interrupts.
> 
> That doesn't warrant a copy of an irq_chip structure that contains the
> exact same callbacks, and only differs by *a string*. And the use of
> this string is only to end-up in /proc/interrupts, which is totally
> pointless.
> 
> > 
> > > > +	raw_spinlock_t irq_lock;
> > > > +	int intx_irq;
> > > >  };
> > > >  
> > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > @@ -235,7 +240,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > >  
> > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > >  {
> > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > >  
> > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > @@ -288,10 +293,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > >  	mvebu_pcie_setup_wins(port);
> > > >  
> > > > -	/* Enable interrupt lines A-D. */
> > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > +	/* Mask all interrupt sources. */
> > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > +
> > > > +	/* Clear all interrupt causes. */
> > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > +
> > > > +	if (port->intx_irq <= 0) {
> > > > +		/*
> > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > +		 * this case driver does not provide a way for masking and
> > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > +		 * are shared, so it should not cause any issue. Just
> > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > +		 * be called when some interrupt is triggered.
> > > > +		 */
> > > > +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> > > > +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> > > > +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > 
> > > Maybe worth printing a warning here, so that the user knows they are
> > > on thin ice.
> > 
> > Ok. I can add it here. Anyway, this is default current state without
> > this patch.
> > 
> > > > +	}
> > > >  }
> > > >  
> > > >  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > > > @@ -924,6 +949,109 @@ static struct pci_ops mvebu_pcie_ops = {
> > > >  	.write = mvebu_pcie_wr_conf,
> > > >  };
> > > >  
> > > > +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> > > > +{
> > > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > > +	unsigned long flags;
> > > > +	u32 unmask;
> > > > +
> > > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > +	unmask &= ~PCIE_INT_INTX(hwirq);
> > > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > > +}
> > > > +
> > > > +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> > > > +{
> > > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > > +	unsigned long flags;
> > > > +	u32 unmask;
> > > > +
> > > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > +	unmask |= PCIE_INT_INTX(hwirq);
> > > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > > +}
> > > > +
> > > > +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> > > > +				   unsigned int virq, irq_hw_number_t hwirq)
> > > > +{
> > > > +	struct mvebu_pcie_port *port = h->host_data;
> > > > +
> > > > +	irq_set_status_flags(virq, IRQ_LEVEL);
> > > > +	irq_set_chip_and_handler(virq, &port->intx_irq_chip, handle_level_irq);
> > > > +	irq_set_chip_data(virq, port);
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> > > > +	.map = mvebu_pcie_intx_irq_map,
> > > > +	.xlate = irq_domain_xlate_onecell,
> > > > +};
> > > > +
> > > > +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> > > > +{
> > > > +	struct device *dev = &port->pcie->pdev->dev;
> > > > +	struct device_node *pcie_intc_node;
> > > > +
> > > > +	raw_spin_lock_init(&port->irq_lock);
> > > > +
> > > > +	port->intx_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL,
> > > > +						  "mvebu-%s-INTx",
> > > > +						  port->name);
> > > 
> > > That's exactly what I really don't want to see. It prevents sharing of
> > > the irq_chip structure, and gets in the way of making it const in the
> > > future. Yes, I know that some drivers do that. I can't fix those,
> > > because /proc/interrupts is ABI. But I really don't want to see more
> > > of these.
> > 
> > Well, I do not understand why it should be shared and with who. HW has N
> > independent IRQ chips for legacy interrupts. And each one will be
> > specified in DT per HW layout / design.
> 
> If you have multiple ports, all the ports can share the irq_chip
> structure. Actually scratch that. They *MUST* share the structure. The
> only reason you're not sharing it is to be able to print this useless
> string in /proc/interrupts.

What is the point of sharing one irq chip if HW has N independent irq
chips (for legacy interrupts)? I do not catch it yet. And I do not care
here for /proc/interrupts, so also I have not caught what do you mean be
last sentence with "the only reason".

And I still do not see how it could even work to have just one irq chip
and one irq domain as each irq domain needs to know to which port it
belongs, so it can mask/unmask interrupts from correct port. Also
initialization of domain is taking DT node and for each port it is
different.

So I'm somehow confused here...

The improvement in this patch is to be able to mask INTA interrupts on
port 1 and let INTA interrupts unmasked on port 2 if there drivers are
interested only for interrupts from device connected to port 2.

And if all interrupts are going to be shared (again) then it does not
solve any problem.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-01-06 16:20           ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-06 16:20 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thursday 06 January 2022 15:55:11 Marc Zyngier wrote:
> On Thu, 06 Jan 2022 15:44:47 +0000,
> Pali Rohár <pali@kernel.org> wrote:
> > 
> > On Thursday 06 January 2022 15:28:20 Marc Zyngier wrote:
> > > On Wed, 05 Jan 2022 15:02:38 +0000,
> > > Pali Rohár <pali@kernel.org> wrote:
> > > > 
> > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > devices and which are reported by a new INTx irq chip.
> > > > 
> > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > interrupts.
> > > > 
> > > > Note that for this support, device tree files has to be properly adjusted
> > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > 'interrupt-controller' subnode must be defined.
> > > > 
> > > > If device tree files do not provide these nodes then driver would work as
> > > > before.
> > > > 
> > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > ---
> > > >  drivers/pci/controller/pci-mvebu.c | 182 +++++++++++++++++++++++++++--
> > > >  1 file changed, 174 insertions(+), 8 deletions(-)
> > > > 
> > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > index 1e90ab888075..04bcdd7b7a6d 100644
> > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > @@ -54,9 +54,10 @@
> > > >  	 PCIE_CONF_ADDR_EN)
> > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > -#define PCIE_MASK_OFF		0x1910
> > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > >  #define PCIE_CTRL_OFF		0x1a00
> > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > @@ -110,6 +111,10 @@ struct mvebu_pcie_port {
> > > >  	struct mvebu_pcie_window iowin;
> > > >  	u32 saved_pcie_stat;
> > > >  	struct resource regs;
> > > > +	struct irq_domain *intx_irq_domain;
> > > > +	struct irq_chip intx_irq_chip;
> > > 
> > > Why is this structure per port? It really should be global. Printing
> > > the port number in the name isn't enough of a reason.
> > 
> > Because each port has its own independent set of INTA-INTD
> > interrupts.
> 
> That doesn't warrant a copy of an irq_chip structure that contains the
> exact same callbacks, and only differs by *a string*. And the use of
> this string is only to end-up in /proc/interrupts, which is totally
> pointless.
> 
> > 
> > > > +	raw_spinlock_t irq_lock;
> > > > +	int intx_irq;
> > > >  };
> > > >  
> > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > @@ -235,7 +240,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > >  
> > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > >  {
> > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > >  
> > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > @@ -288,10 +293,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > >  	mvebu_pcie_setup_wins(port);
> > > >  
> > > > -	/* Enable interrupt lines A-D. */
> > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > +	/* Mask all interrupt sources. */
> > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > +
> > > > +	/* Clear all interrupt causes. */
> > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > +
> > > > +	if (port->intx_irq <= 0) {
> > > > +		/*
> > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > +		 * this case driver does not provide a way for masking and
> > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > +		 * are shared, so it should not cause any issue. Just
> > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > +		 * be called when some interrupt is triggered.
> > > > +		 */
> > > > +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> > > > +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> > > > +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > 
> > > Maybe worth printing a warning here, so that the user knows they are
> > > on thin ice.
> > 
> > Ok. I can add it here. Anyway, this is default current state without
> > this patch.
> > 
> > > > +	}
> > > >  }
> > > >  
> > > >  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > > > @@ -924,6 +949,109 @@ static struct pci_ops mvebu_pcie_ops = {
> > > >  	.write = mvebu_pcie_wr_conf,
> > > >  };
> > > >  
> > > > +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> > > > +{
> > > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > > +	unsigned long flags;
> > > > +	u32 unmask;
> > > > +
> > > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > +	unmask &= ~PCIE_INT_INTX(hwirq);
> > > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > > +}
> > > > +
> > > > +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> > > > +{
> > > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > > +	unsigned long flags;
> > > > +	u32 unmask;
> > > > +
> > > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > +	unmask |= PCIE_INT_INTX(hwirq);
> > > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > > +}
> > > > +
> > > > +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> > > > +				   unsigned int virq, irq_hw_number_t hwirq)
> > > > +{
> > > > +	struct mvebu_pcie_port *port = h->host_data;
> > > > +
> > > > +	irq_set_status_flags(virq, IRQ_LEVEL);
> > > > +	irq_set_chip_and_handler(virq, &port->intx_irq_chip, handle_level_irq);
> > > > +	irq_set_chip_data(virq, port);
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> > > > +	.map = mvebu_pcie_intx_irq_map,
> > > > +	.xlate = irq_domain_xlate_onecell,
> > > > +};
> > > > +
> > > > +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> > > > +{
> > > > +	struct device *dev = &port->pcie->pdev->dev;
> > > > +	struct device_node *pcie_intc_node;
> > > > +
> > > > +	raw_spin_lock_init(&port->irq_lock);
> > > > +
> > > > +	port->intx_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL,
> > > > +						  "mvebu-%s-INTx",
> > > > +						  port->name);
> > > 
> > > That's exactly what I really don't want to see. It prevents sharing of
> > > the irq_chip structure, and gets in the way of making it const in the
> > > future. Yes, I know that some drivers do that. I can't fix those,
> > > because /proc/interrupts is ABI. But I really don't want to see more
> > > of these.
> > 
> > Well, I do not understand why it should be shared and with who. HW has N
> > independent IRQ chips for legacy interrupts. And each one will be
> > specified in DT per HW layout / design.
> 
> If you have multiple ports, all the ports can share the irq_chip
> structure. Actually scratch that. They *MUST* share the structure. The
> only reason you're not sharing it is to be able to print this useless
> string in /proc/interrupts.

What is the point of sharing one irq chip if HW has N independent irq
chips (for legacy interrupts)? I do not catch it yet. And I do not care
here for /proc/interrupts, so also I have not caught what do you mean be
last sentence with "the only reason".

And I still do not see how it could even work to have just one irq chip
and one irq domain as each irq domain needs to know to which port it
belongs, so it can mask/unmask interrupts from correct port. Also
initialization of domain is taking DT node and for each port it is
different.

So I'm somehow confused here...

The improvement in this patch is to be able to mask INTA interrupts on
port 1 and let INTA interrupts unmasked on port 2 if there drivers are
interested only for interrupts from device connected to port 2.

And if all interrupts are going to be shared (again) then it does not
solve any problem.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-01-06 16:20           ` Pali Rohár
@ 2022-01-06 16:27             ` Marc Zyngier
  -1 siblings, 0 replies; 130+ messages in thread
From: Marc Zyngier @ 2022-01-06 16:27 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thu, 06 Jan 2022 16:20:47 +0000,
Pali Rohár <pali@kernel.org> wrote:
> 
> On Thursday 06 January 2022 15:55:11 Marc Zyngier wrote:
> > On Thu, 06 Jan 2022 15:44:47 +0000,
> > Pali Rohár <pali@kernel.org> wrote:
> > > 
> > > On Thursday 06 January 2022 15:28:20 Marc Zyngier wrote:
> > > > On Wed, 05 Jan 2022 15:02:38 +0000,
> > > > Pali Rohár <pali@kernel.org> wrote:
> > > > > 
> > > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > > devices and which are reported by a new INTx irq chip.
> > > > > 
> > > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > > interrupts.
> > > > > 
> > > > > Note that for this support, device tree files has to be properly adjusted
> > > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > > 'interrupt-controller' subnode must be defined.
> > > > > 
> > > > > If device tree files do not provide these nodes then driver would work as
> > > > > before.
> > > > > 
> > > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > > ---
> > > > >  drivers/pci/controller/pci-mvebu.c | 182 +++++++++++++++++++++++++++--
> > > > >  1 file changed, 174 insertions(+), 8 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > > index 1e90ab888075..04bcdd7b7a6d 100644
> > > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > > @@ -54,9 +54,10 @@
> > > > >  	 PCIE_CONF_ADDR_EN)
> > > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > > -#define PCIE_MASK_OFF		0x1910
> > > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > > >  #define PCIE_CTRL_OFF		0x1a00
> > > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > > @@ -110,6 +111,10 @@ struct mvebu_pcie_port {
> > > > >  	struct mvebu_pcie_window iowin;
> > > > >  	u32 saved_pcie_stat;
> > > > >  	struct resource regs;
> > > > > +	struct irq_domain *intx_irq_domain;
> > > > > +	struct irq_chip intx_irq_chip;
> > > > 
> > > > Why is this structure per port? It really should be global. Printing
> > > > the port number in the name isn't enough of a reason.
> > > 
> > > Because each port has its own independent set of INTA-INTD
> > > interrupts.
> > 
> > That doesn't warrant a copy of an irq_chip structure that contains the
> > exact same callbacks, and only differs by *a string*. And the use of
> > this string is only to end-up in /proc/interrupts, which is totally
> > pointless.
> > 
> > > 
> > > > > +	raw_spinlock_t irq_lock;
> > > > > +	int intx_irq;
> > > > >  };
> > > > >  
> > > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > > @@ -235,7 +240,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > > >  
> > > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > >  {
> > > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > > >  
> > > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > > @@ -288,10 +293,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > > >  	mvebu_pcie_setup_wins(port);
> > > > >  
> > > > > -	/* Enable interrupt lines A-D. */
> > > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > > +	/* Mask all interrupt sources. */
> > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > > +
> > > > > +	/* Clear all interrupt causes. */
> > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > > +
> > > > > +	if (port->intx_irq <= 0) {
> > > > > +		/*
> > > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > > +		 * this case driver does not provide a way for masking and
> > > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > > +		 * are shared, so it should not cause any issue. Just
> > > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > > +		 * be called when some interrupt is triggered.
> > > > > +		 */
> > > > > +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > > +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> > > > > +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> > > > > +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > > 
> > > > Maybe worth printing a warning here, so that the user knows they are
> > > > on thin ice.
> > > 
> > > Ok. I can add it here. Anyway, this is default current state without
> > > this patch.
> > > 
> > > > > +	}
> > > > >  }
> > > > >  
> > > > >  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > > > > @@ -924,6 +949,109 @@ static struct pci_ops mvebu_pcie_ops = {
> > > > >  	.write = mvebu_pcie_wr_conf,
> > > > >  };
> > > > >  
> > > > > +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> > > > > +{
> > > > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > > > +	unsigned long flags;
> > > > > +	u32 unmask;
> > > > > +
> > > > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > > +	unmask &= ~PCIE_INT_INTX(hwirq);
> > > > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > > > +}
> > > > > +
> > > > > +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> > > > > +{
> > > > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > > > +	unsigned long flags;
> > > > > +	u32 unmask;
> > > > > +
> > > > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > > +	unmask |= PCIE_INT_INTX(hwirq);
> > > > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > > > +}
> > > > > +
> > > > > +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> > > > > +				   unsigned int virq, irq_hw_number_t hwirq)
> > > > > +{
> > > > > +	struct mvebu_pcie_port *port = h->host_data;
> > > > > +
> > > > > +	irq_set_status_flags(virq, IRQ_LEVEL);
> > > > > +	irq_set_chip_and_handler(virq, &port->intx_irq_chip, handle_level_irq);
> > > > > +	irq_set_chip_data(virq, port);
> > > > > +
> > > > > +	return 0;
> > > > > +}
> > > > > +
> > > > > +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> > > > > +	.map = mvebu_pcie_intx_irq_map,
> > > > > +	.xlate = irq_domain_xlate_onecell,
> > > > > +};
> > > > > +
> > > > > +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> > > > > +{
> > > > > +	struct device *dev = &port->pcie->pdev->dev;
> > > > > +	struct device_node *pcie_intc_node;
> > > > > +
> > > > > +	raw_spin_lock_init(&port->irq_lock);
> > > > > +
> > > > > +	port->intx_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL,
> > > > > +						  "mvebu-%s-INTx",
> > > > > +						  port->name);
> > > > 
> > > > That's exactly what I really don't want to see. It prevents sharing of
> > > > the irq_chip structure, and gets in the way of making it const in the
> > > > future. Yes, I know that some drivers do that. I can't fix those,
> > > > because /proc/interrupts is ABI. But I really don't want to see more
> > > > of these.
> > > 
> > > Well, I do not understand why it should be shared and with who. HW has N
> > > independent IRQ chips for legacy interrupts. And each one will be
> > > specified in DT per HW layout / design.
> > 
> > If you have multiple ports, all the ports can share the irq_chip
> > structure. Actually scratch that. They *MUST* share the structure. The
> > only reason you're not sharing it is to be able to print this useless
> > string in /proc/interrupts.
> 
> What is the point of sharing one irq chip if HW has N independent irq
> chips (for legacy interrupts)? I do not catch it yet. And I do not care
> here for /proc/interrupts, so also I have not caught what do you mean be
> last sentence with "the only reason".
> 
> And I still do not see how it could even work to have just one irq chip
> and one irq domain as each irq domain needs to know to which port it
> belongs, so it can mask/unmask interrupts from correct port. Also
> initialization of domain is taking DT node and for each port it is
> different.
> 
> So I'm somehow confused here...
> 
> The improvement in this patch is to be able to mask INTA interrupts on
> port 1 and let INTA interrupts unmasked on port 2 if there drivers are
> interested only for interrupts from device connected to port 2.
> 
> And if all interrupts are going to be shared (again) then it does not
> solve any problem.

You are completely missing my point. I'm talking about data
structures, you're talking about interrupts. You have this:

struct mvebu_pcie_port {
       // Tons of stuff
       struct irq_chip intx_chip;
};

What I want you to do is:

struct mvebu_pcie_port {
       // Tons of stuff
};

static struct irq_chip intx_chip = {
	.name		= "INTx",
	.irq_mask	= mvebu_pcie_intx_irq_mask,
	.irq_unmask	= mvebu_pcie_intx_irq_unmask;
};

That's it. No more, no less.

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-01-06 16:27             ` Marc Zyngier
  0 siblings, 0 replies; 130+ messages in thread
From: Marc Zyngier @ 2022-01-06 16:27 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thu, 06 Jan 2022 16:20:47 +0000,
Pali Rohár <pali@kernel.org> wrote:
> 
> On Thursday 06 January 2022 15:55:11 Marc Zyngier wrote:
> > On Thu, 06 Jan 2022 15:44:47 +0000,
> > Pali Rohár <pali@kernel.org> wrote:
> > > 
> > > On Thursday 06 January 2022 15:28:20 Marc Zyngier wrote:
> > > > On Wed, 05 Jan 2022 15:02:38 +0000,
> > > > Pali Rohár <pali@kernel.org> wrote:
> > > > > 
> > > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > > devices and which are reported by a new INTx irq chip.
> > > > > 
> > > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > > interrupts.
> > > > > 
> > > > > Note that for this support, device tree files has to be properly adjusted
> > > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > > 'interrupt-controller' subnode must be defined.
> > > > > 
> > > > > If device tree files do not provide these nodes then driver would work as
> > > > > before.
> > > > > 
> > > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > > ---
> > > > >  drivers/pci/controller/pci-mvebu.c | 182 +++++++++++++++++++++++++++--
> > > > >  1 file changed, 174 insertions(+), 8 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > > index 1e90ab888075..04bcdd7b7a6d 100644
> > > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > > @@ -54,9 +54,10 @@
> > > > >  	 PCIE_CONF_ADDR_EN)
> > > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > > -#define PCIE_MASK_OFF		0x1910
> > > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > > >  #define PCIE_CTRL_OFF		0x1a00
> > > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > > @@ -110,6 +111,10 @@ struct mvebu_pcie_port {
> > > > >  	struct mvebu_pcie_window iowin;
> > > > >  	u32 saved_pcie_stat;
> > > > >  	struct resource regs;
> > > > > +	struct irq_domain *intx_irq_domain;
> > > > > +	struct irq_chip intx_irq_chip;
> > > > 
> > > > Why is this structure per port? It really should be global. Printing
> > > > the port number in the name isn't enough of a reason.
> > > 
> > > Because each port has its own independent set of INTA-INTD
> > > interrupts.
> > 
> > That doesn't warrant a copy of an irq_chip structure that contains the
> > exact same callbacks, and only differs by *a string*. And the use of
> > this string is only to end-up in /proc/interrupts, which is totally
> > pointless.
> > 
> > > 
> > > > > +	raw_spinlock_t irq_lock;
> > > > > +	int intx_irq;
> > > > >  };
> > > > >  
> > > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > > @@ -235,7 +240,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > > >  
> > > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > >  {
> > > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > > >  
> > > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > > @@ -288,10 +293,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > > >  	mvebu_pcie_setup_wins(port);
> > > > >  
> > > > > -	/* Enable interrupt lines A-D. */
> > > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > > +	/* Mask all interrupt sources. */
> > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > > +
> > > > > +	/* Clear all interrupt causes. */
> > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > > +
> > > > > +	if (port->intx_irq <= 0) {
> > > > > +		/*
> > > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > > +		 * this case driver does not provide a way for masking and
> > > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > > +		 * are shared, so it should not cause any issue. Just
> > > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > > +		 * be called when some interrupt is triggered.
> > > > > +		 */
> > > > > +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > > +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> > > > > +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> > > > > +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > > 
> > > > Maybe worth printing a warning here, so that the user knows they are
> > > > on thin ice.
> > > 
> > > Ok. I can add it here. Anyway, this is default current state without
> > > this patch.
> > > 
> > > > > +	}
> > > > >  }
> > > > >  
> > > > >  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > > > > @@ -924,6 +949,109 @@ static struct pci_ops mvebu_pcie_ops = {
> > > > >  	.write = mvebu_pcie_wr_conf,
> > > > >  };
> > > > >  
> > > > > +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> > > > > +{
> > > > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > > > +	unsigned long flags;
> > > > > +	u32 unmask;
> > > > > +
> > > > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > > +	unmask &= ~PCIE_INT_INTX(hwirq);
> > > > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > > > +}
> > > > > +
> > > > > +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> > > > > +{
> > > > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > > > +	unsigned long flags;
> > > > > +	u32 unmask;
> > > > > +
> > > > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > > +	unmask |= PCIE_INT_INTX(hwirq);
> > > > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > > > +}
> > > > > +
> > > > > +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> > > > > +				   unsigned int virq, irq_hw_number_t hwirq)
> > > > > +{
> > > > > +	struct mvebu_pcie_port *port = h->host_data;
> > > > > +
> > > > > +	irq_set_status_flags(virq, IRQ_LEVEL);
> > > > > +	irq_set_chip_and_handler(virq, &port->intx_irq_chip, handle_level_irq);
> > > > > +	irq_set_chip_data(virq, port);
> > > > > +
> > > > > +	return 0;
> > > > > +}
> > > > > +
> > > > > +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> > > > > +	.map = mvebu_pcie_intx_irq_map,
> > > > > +	.xlate = irq_domain_xlate_onecell,
> > > > > +};
> > > > > +
> > > > > +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> > > > > +{
> > > > > +	struct device *dev = &port->pcie->pdev->dev;
> > > > > +	struct device_node *pcie_intc_node;
> > > > > +
> > > > > +	raw_spin_lock_init(&port->irq_lock);
> > > > > +
> > > > > +	port->intx_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL,
> > > > > +						  "mvebu-%s-INTx",
> > > > > +						  port->name);
> > > > 
> > > > That's exactly what I really don't want to see. It prevents sharing of
> > > > the irq_chip structure, and gets in the way of making it const in the
> > > > future. Yes, I know that some drivers do that. I can't fix those,
> > > > because /proc/interrupts is ABI. But I really don't want to see more
> > > > of these.
> > > 
> > > Well, I do not understand why it should be shared and with who. HW has N
> > > independent IRQ chips for legacy interrupts. And each one will be
> > > specified in DT per HW layout / design.
> > 
> > If you have multiple ports, all the ports can share the irq_chip
> > structure. Actually scratch that. They *MUST* share the structure. The
> > only reason you're not sharing it is to be able to print this useless
> > string in /proc/interrupts.
> 
> What is the point of sharing one irq chip if HW has N independent irq
> chips (for legacy interrupts)? I do not catch it yet. And I do not care
> here for /proc/interrupts, so also I have not caught what do you mean be
> last sentence with "the only reason".
> 
> And I still do not see how it could even work to have just one irq chip
> and one irq domain as each irq domain needs to know to which port it
> belongs, so it can mask/unmask interrupts from correct port. Also
> initialization of domain is taking DT node and for each port it is
> different.
> 
> So I'm somehow confused here...
> 
> The improvement in this patch is to be able to mask INTA interrupts on
> port 1 and let INTA interrupts unmasked on port 2 if there drivers are
> interested only for interrupts from device connected to port 2.
> 
> And if all interrupts are going to be shared (again) then it does not
> solve any problem.

You are completely missing my point. I'm talking about data
structures, you're talking about interrupts. You have this:

struct mvebu_pcie_port {
       // Tons of stuff
       struct irq_chip intx_chip;
};

What I want you to do is:

struct mvebu_pcie_port {
       // Tons of stuff
};

static struct irq_chip intx_chip = {
	.name		= "INTx",
	.irq_mask	= mvebu_pcie_intx_irq_mask,
	.irq_unmask	= mvebu_pcie_intx_irq_unmask;
};

That's it. No more, no less.

	M.

-- 
Without deviation from the norm, progress is not possible.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-01-06 16:27             ` Marc Zyngier
@ 2022-01-06 17:20               ` Marek Behún
  -1 siblings, 0 replies; 130+ messages in thread
From: Marek Behún @ 2022-01-06 17:20 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Pali Rohár, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thu, 06 Jan 2022 16:27:44 +0000
Marc Zyngier <maz@kernel.org> wrote:

> On Thu, 06 Jan 2022 16:20:47 +0000,
> Pali Rohár <pali@kernel.org> wrote:
> > 
> > On Thursday 06 January 2022 15:55:11 Marc Zyngier wrote:  
> > > On Thu, 06 Jan 2022 15:44:47 +0000,
> > > Pali Rohár <pali@kernel.org> wrote:  
> > > > 
> > > > On Thursday 06 January 2022 15:28:20 Marc Zyngier wrote:  
> > > > > On Wed, 05 Jan 2022 15:02:38 +0000,
> > > > > Pali Rohár <pali@kernel.org> wrote:  
> > > > > > 
> > > > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > > > devices and which are reported by a new INTx irq chip.
> > > > > > 
> > > > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > > > interrupts.
> > > > > > 
> > > > > > Note that for this support, device tree files has to be properly adjusted
> > > > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > > > 'interrupt-controller' subnode must be defined.
> > > > > > 
> > > > > > If device tree files do not provide these nodes then driver would work as
> > > > > > before.
> > > > > > 
> > > > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > > > ---
> > > > > >  drivers/pci/controller/pci-mvebu.c | 182 +++++++++++++++++++++++++++--
> > > > > >  1 file changed, 174 insertions(+), 8 deletions(-)
> > > > > > 
> > > > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > > > index 1e90ab888075..04bcdd7b7a6d 100644
> > > > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > > > @@ -54,9 +54,10 @@
> > > > > >  	 PCIE_CONF_ADDR_EN)
> > > > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > > > -#define PCIE_MASK_OFF		0x1910
> > > > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > > > >  #define PCIE_CTRL_OFF		0x1a00
> > > > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > > > @@ -110,6 +111,10 @@ struct mvebu_pcie_port {
> > > > > >  	struct mvebu_pcie_window iowin;
> > > > > >  	u32 saved_pcie_stat;
> > > > > >  	struct resource regs;
> > > > > > +	struct irq_domain *intx_irq_domain;
> > > > > > +	struct irq_chip intx_irq_chip;  
> > > > > 
> > > > > Why is this structure per port? It really should be global. Printing
> > > > > the port number in the name isn't enough of a reason.  
> > > > 
> > > > Because each port has its own independent set of INTA-INTD
> > > > interrupts.  
> > > 
> > > That doesn't warrant a copy of an irq_chip structure that contains the
> > > exact same callbacks, and only differs by *a string*. And the use of
> > > this string is only to end-up in /proc/interrupts, which is totally
> > > pointless.
> > >   
> > > >   
> > > > > > +	raw_spinlock_t irq_lock;
> > > > > > +	int intx_irq;
> > > > > >  };
> > > > > >  
> > > > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > > > @@ -235,7 +240,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > > > >  
> > > > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > >  {
> > > > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > > > >  
> > > > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > > > @@ -288,10 +293,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > > > >  	mvebu_pcie_setup_wins(port);
> > > > > >  
> > > > > > -	/* Enable interrupt lines A-D. */
> > > > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > > > +	/* Mask all interrupt sources. */
> > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > > > +
> > > > > > +	/* Clear all interrupt causes. */
> > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > > > +
> > > > > > +	if (port->intx_irq <= 0) {
> > > > > > +		/*
> > > > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > > > +		 * this case driver does not provide a way for masking and
> > > > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > > > +		 * are shared, so it should not cause any issue. Just
> > > > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > > > +		 * be called when some interrupt is triggered.
> > > > > > +		 */
> > > > > > +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > > > +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> > > > > > +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> > > > > > +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);  
> > > > > 
> > > > > Maybe worth printing a warning here, so that the user knows they are
> > > > > on thin ice.  
> > > > 
> > > > Ok. I can add it here. Anyway, this is default current state without
> > > > this patch.
> > > >   
> > > > > > +	}
> > > > > >  }
> > > > > >  
> > > > > >  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > > > > > @@ -924,6 +949,109 @@ static struct pci_ops mvebu_pcie_ops = {
> > > > > >  	.write = mvebu_pcie_wr_conf,
> > > > > >  };
> > > > > >  
> > > > > > +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> > > > > > +{
> > > > > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > > > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > > > > +	unsigned long flags;
> > > > > > +	u32 unmask;
> > > > > > +
> > > > > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > > > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > > > +	unmask &= ~PCIE_INT_INTX(hwirq);
> > > > > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > > > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > > > > +}
> > > > > > +
> > > > > > +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> > > > > > +{
> > > > > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > > > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > > > > +	unsigned long flags;
> > > > > > +	u32 unmask;
> > > > > > +
> > > > > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > > > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > > > +	unmask |= PCIE_INT_INTX(hwirq);
> > > > > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > > > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > > > > +}
> > > > > > +
> > > > > > +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> > > > > > +				   unsigned int virq, irq_hw_number_t hwirq)
> > > > > > +{
> > > > > > +	struct mvebu_pcie_port *port = h->host_data;
> > > > > > +
> > > > > > +	irq_set_status_flags(virq, IRQ_LEVEL);
> > > > > > +	irq_set_chip_and_handler(virq, &port->intx_irq_chip, handle_level_irq);
> > > > > > +	irq_set_chip_data(virq, port);
> > > > > > +
> > > > > > +	return 0;
> > > > > > +}
> > > > > > +
> > > > > > +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> > > > > > +	.map = mvebu_pcie_intx_irq_map,
> > > > > > +	.xlate = irq_domain_xlate_onecell,
> > > > > > +};
> > > > > > +
> > > > > > +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> > > > > > +{
> > > > > > +	struct device *dev = &port->pcie->pdev->dev;
> > > > > > +	struct device_node *pcie_intc_node;
> > > > > > +
> > > > > > +	raw_spin_lock_init(&port->irq_lock);
> > > > > > +
> > > > > > +	port->intx_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL,
> > > > > > +						  "mvebu-%s-INTx",
> > > > > > +						  port->name);  
> > > > > 
> > > > > That's exactly what I really don't want to see. It prevents sharing of
> > > > > the irq_chip structure, and gets in the way of making it const in the
> > > > > future. Yes, I know that some drivers do that. I can't fix those,
> > > > > because /proc/interrupts is ABI. But I really don't want to see more
> > > > > of these.  
> > > > 
> > > > Well, I do not understand why it should be shared and with who. HW has N
> > > > independent IRQ chips for legacy interrupts. And each one will be
> > > > specified in DT per HW layout / design.  
> > > 
> > > If you have multiple ports, all the ports can share the irq_chip
> > > structure. Actually scratch that. They *MUST* share the structure. The
> > > only reason you're not sharing it is to be able to print this useless
> > > string in /proc/interrupts.  
> > 
> > What is the point of sharing one irq chip if HW has N independent irq
> > chips (for legacy interrupts)? I do not catch it yet. And I do not care
> > here for /proc/interrupts, so also I have not caught what do you mean be
> > last sentence with "the only reason".
> > 
> > And I still do not see how it could even work to have just one irq chip
> > and one irq domain as each irq domain needs to know to which port it
> > belongs, so it can mask/unmask interrupts from correct port. Also
> > initialization of domain is taking DT node and for each port it is
> > different.
> > 
> > So I'm somehow confused here...
> > 
> > The improvement in this patch is to be able to mask INTA interrupts on
> > port 1 and let INTA interrupts unmasked on port 2 if there drivers are
> > interested only for interrupts from device connected to port 2.
> > 
> > And if all interrupts are going to be shared (again) then it does not
> > solve any problem.  
> 
> You are completely missing my point. I'm talking about data
> structures, you're talking about interrupts. You have this:
> 
> struct mvebu_pcie_port {
>        // Tons of stuff
>        struct irq_chip intx_chip;
> };
> 
> What I want you to do is:
> 
> struct mvebu_pcie_port {
>        // Tons of stuff
> };
> 
> static struct irq_chip intx_chip = {
> 	.name		= "INTx",
> 	.irq_mask	= mvebu_pcie_intx_irq_mask,
> 	.irq_unmask	= mvebu_pcie_intx_irq_unmask;
> };
> 
> That's it. No more, no less.
> 
> 	M.
> 

Hmm, but struct irq_chip contains a dynamic member,
  struct device *parent_device;
Isn't that used? Or are you planning to kill it?

Marek

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-01-06 17:20               ` Marek Behún
  0 siblings, 0 replies; 130+ messages in thread
From: Marek Behún @ 2022-01-06 17:20 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Pali Rohár, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thu, 06 Jan 2022 16:27:44 +0000
Marc Zyngier <maz@kernel.org> wrote:

> On Thu, 06 Jan 2022 16:20:47 +0000,
> Pali Rohár <pali@kernel.org> wrote:
> > 
> > On Thursday 06 January 2022 15:55:11 Marc Zyngier wrote:  
> > > On Thu, 06 Jan 2022 15:44:47 +0000,
> > > Pali Rohár <pali@kernel.org> wrote:  
> > > > 
> > > > On Thursday 06 January 2022 15:28:20 Marc Zyngier wrote:  
> > > > > On Wed, 05 Jan 2022 15:02:38 +0000,
> > > > > Pali Rohár <pali@kernel.org> wrote:  
> > > > > > 
> > > > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > > > devices and which are reported by a new INTx irq chip.
> > > > > > 
> > > > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > > > interrupts.
> > > > > > 
> > > > > > Note that for this support, device tree files has to be properly adjusted
> > > > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > > > 'interrupt-controller' subnode must be defined.
> > > > > > 
> > > > > > If device tree files do not provide these nodes then driver would work as
> > > > > > before.
> > > > > > 
> > > > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > > > ---
> > > > > >  drivers/pci/controller/pci-mvebu.c | 182 +++++++++++++++++++++++++++--
> > > > > >  1 file changed, 174 insertions(+), 8 deletions(-)
> > > > > > 
> > > > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > > > index 1e90ab888075..04bcdd7b7a6d 100644
> > > > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > > > @@ -54,9 +54,10 @@
> > > > > >  	 PCIE_CONF_ADDR_EN)
> > > > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > > > -#define PCIE_MASK_OFF		0x1910
> > > > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > > > >  #define PCIE_CTRL_OFF		0x1a00
> > > > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > > > @@ -110,6 +111,10 @@ struct mvebu_pcie_port {
> > > > > >  	struct mvebu_pcie_window iowin;
> > > > > >  	u32 saved_pcie_stat;
> > > > > >  	struct resource regs;
> > > > > > +	struct irq_domain *intx_irq_domain;
> > > > > > +	struct irq_chip intx_irq_chip;  
> > > > > 
> > > > > Why is this structure per port? It really should be global. Printing
> > > > > the port number in the name isn't enough of a reason.  
> > > > 
> > > > Because each port has its own independent set of INTA-INTD
> > > > interrupts.  
> > > 
> > > That doesn't warrant a copy of an irq_chip structure that contains the
> > > exact same callbacks, and only differs by *a string*. And the use of
> > > this string is only to end-up in /proc/interrupts, which is totally
> > > pointless.
> > >   
> > > >   
> > > > > > +	raw_spinlock_t irq_lock;
> > > > > > +	int intx_irq;
> > > > > >  };
> > > > > >  
> > > > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > > > @@ -235,7 +240,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > > > >  
> > > > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > >  {
> > > > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > > > >  
> > > > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > > > @@ -288,10 +293,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > > > >  	mvebu_pcie_setup_wins(port);
> > > > > >  
> > > > > > -	/* Enable interrupt lines A-D. */
> > > > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > > > +	/* Mask all interrupt sources. */
> > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > > > +
> > > > > > +	/* Clear all interrupt causes. */
> > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > > > +
> > > > > > +	if (port->intx_irq <= 0) {
> > > > > > +		/*
> > > > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > > > +		 * this case driver does not provide a way for masking and
> > > > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > > > +		 * are shared, so it should not cause any issue. Just
> > > > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > > > +		 * be called when some interrupt is triggered.
> > > > > > +		 */
> > > > > > +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > > > +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> > > > > > +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> > > > > > +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);  
> > > > > 
> > > > > Maybe worth printing a warning here, so that the user knows they are
> > > > > on thin ice.  
> > > > 
> > > > Ok. I can add it here. Anyway, this is default current state without
> > > > this patch.
> > > >   
> > > > > > +	}
> > > > > >  }
> > > > > >  
> > > > > >  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > > > > > @@ -924,6 +949,109 @@ static struct pci_ops mvebu_pcie_ops = {
> > > > > >  	.write = mvebu_pcie_wr_conf,
> > > > > >  };
> > > > > >  
> > > > > > +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> > > > > > +{
> > > > > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > > > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > > > > +	unsigned long flags;
> > > > > > +	u32 unmask;
> > > > > > +
> > > > > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > > > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > > > +	unmask &= ~PCIE_INT_INTX(hwirq);
> > > > > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > > > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > > > > +}
> > > > > > +
> > > > > > +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> > > > > > +{
> > > > > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > > > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > > > > +	unsigned long flags;
> > > > > > +	u32 unmask;
> > > > > > +
> > > > > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > > > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > > > > +	unmask |= PCIE_INT_INTX(hwirq);
> > > > > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > > > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > > > > +}
> > > > > > +
> > > > > > +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> > > > > > +				   unsigned int virq, irq_hw_number_t hwirq)
> > > > > > +{
> > > > > > +	struct mvebu_pcie_port *port = h->host_data;
> > > > > > +
> > > > > > +	irq_set_status_flags(virq, IRQ_LEVEL);
> > > > > > +	irq_set_chip_and_handler(virq, &port->intx_irq_chip, handle_level_irq);
> > > > > > +	irq_set_chip_data(virq, port);
> > > > > > +
> > > > > > +	return 0;
> > > > > > +}
> > > > > > +
> > > > > > +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> > > > > > +	.map = mvebu_pcie_intx_irq_map,
> > > > > > +	.xlate = irq_domain_xlate_onecell,
> > > > > > +};
> > > > > > +
> > > > > > +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> > > > > > +{
> > > > > > +	struct device *dev = &port->pcie->pdev->dev;
> > > > > > +	struct device_node *pcie_intc_node;
> > > > > > +
> > > > > > +	raw_spin_lock_init(&port->irq_lock);
> > > > > > +
> > > > > > +	port->intx_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL,
> > > > > > +						  "mvebu-%s-INTx",
> > > > > > +						  port->name);  
> > > > > 
> > > > > That's exactly what I really don't want to see. It prevents sharing of
> > > > > the irq_chip structure, and gets in the way of making it const in the
> > > > > future. Yes, I know that some drivers do that. I can't fix those,
> > > > > because /proc/interrupts is ABI. But I really don't want to see more
> > > > > of these.  
> > > > 
> > > > Well, I do not understand why it should be shared and with who. HW has N
> > > > independent IRQ chips for legacy interrupts. And each one will be
> > > > specified in DT per HW layout / design.  
> > > 
> > > If you have multiple ports, all the ports can share the irq_chip
> > > structure. Actually scratch that. They *MUST* share the structure. The
> > > only reason you're not sharing it is to be able to print this useless
> > > string in /proc/interrupts.  
> > 
> > What is the point of sharing one irq chip if HW has N independent irq
> > chips (for legacy interrupts)? I do not catch it yet. And I do not care
> > here for /proc/interrupts, so also I have not caught what do you mean be
> > last sentence with "the only reason".
> > 
> > And I still do not see how it could even work to have just one irq chip
> > and one irq domain as each irq domain needs to know to which port it
> > belongs, so it can mask/unmask interrupts from correct port. Also
> > initialization of domain is taking DT node and for each port it is
> > different.
> > 
> > So I'm somehow confused here...
> > 
> > The improvement in this patch is to be able to mask INTA interrupts on
> > port 1 and let INTA interrupts unmasked on port 2 if there drivers are
> > interested only for interrupts from device connected to port 2.
> > 
> > And if all interrupts are going to be shared (again) then it does not
> > solve any problem.  
> 
> You are completely missing my point. I'm talking about data
> structures, you're talking about interrupts. You have this:
> 
> struct mvebu_pcie_port {
>        // Tons of stuff
>        struct irq_chip intx_chip;
> };
> 
> What I want you to do is:
> 
> struct mvebu_pcie_port {
>        // Tons of stuff
> };
> 
> static struct irq_chip intx_chip = {
> 	.name		= "INTx",
> 	.irq_mask	= mvebu_pcie_intx_irq_mask,
> 	.irq_unmask	= mvebu_pcie_intx_irq_unmask;
> };
> 
> That's it. No more, no less.
> 
> 	M.
> 

Hmm, but struct irq_chip contains a dynamic member,
  struct device *parent_device;
Isn't that used? Or are you planning to kill it?

Marek

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-01-06 17:20               ` Marek Behún
@ 2022-01-06 17:31                 ` Marc Zyngier
  -1 siblings, 0 replies; 130+ messages in thread
From: Marc Zyngier @ 2022-01-06 17:31 UTC (permalink / raw)
  To: Marek Behún
  Cc: Pali Rohár, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thu, 06 Jan 2022 17:20:44 +0000,
Marek Behún <kabel@kernel.org> wrote:
> 
> On Thu, 06 Jan 2022 16:27:44 +0000
> Marc Zyngier <maz@kernel.org> wrote:
> > You are completely missing my point. I'm talking about data
> > structures, you're talking about interrupts. You have this:
> > 
> > struct mvebu_pcie_port {
> >        // Tons of stuff
> >        struct irq_chip intx_chip;
> > };
> > 
> > What I want you to do is:
> > 
> > struct mvebu_pcie_port {
> >        // Tons of stuff
> > };
> > 
> > static struct irq_chip intx_chip = {
> > 	.name		= "INTx",
> > 	.irq_mask	= mvebu_pcie_intx_irq_mask,
> > 	.irq_unmask	= mvebu_pcie_intx_irq_unmask;
> > };
> > 
> > That's it. No more, no less.
> > 
> > 	M.
> > 
> 
> Hmm, but struct irq_chip contains a dynamic member,
>   struct device *parent_device;
> Isn't that used? Or are you planning to kill it?

Indeed, and I am definitely planning to kill it. This is the wrong
place for this stuff, and I want it gone. There are thankfully very
few users of this misfeature.

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-01-06 17:31                 ` Marc Zyngier
  0 siblings, 0 replies; 130+ messages in thread
From: Marc Zyngier @ 2022-01-06 17:31 UTC (permalink / raw)
  To: Marek Behún
  Cc: Pali Rohár, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thu, 06 Jan 2022 17:20:44 +0000,
Marek Behún <kabel@kernel.org> wrote:
> 
> On Thu, 06 Jan 2022 16:27:44 +0000
> Marc Zyngier <maz@kernel.org> wrote:
> > You are completely missing my point. I'm talking about data
> > structures, you're talking about interrupts. You have this:
> > 
> > struct mvebu_pcie_port {
> >        // Tons of stuff
> >        struct irq_chip intx_chip;
> > };
> > 
> > What I want you to do is:
> > 
> > struct mvebu_pcie_port {
> >        // Tons of stuff
> > };
> > 
> > static struct irq_chip intx_chip = {
> > 	.name		= "INTx",
> > 	.irq_mask	= mvebu_pcie_intx_irq_mask,
> > 	.irq_unmask	= mvebu_pcie_intx_irq_unmask;
> > };
> > 
> > That's it. No more, no less.
> > 
> > 	M.
> > 
> 
> Hmm, but struct irq_chip contains a dynamic member,
>   struct device *parent_device;
> Isn't that used? Or are you planning to kill it?

Indeed, and I am definitely planning to kill it. This is the wrong
place for this stuff, and I want it gone. There are thankfully very
few users of this misfeature.

	M.

-- 
Without deviation from the norm, progress is not possible.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-01-06 17:31                 ` Marc Zyngier
@ 2022-01-07 11:50                   ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-07 11:50 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Marek Behún, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thursday 06 January 2022 17:31:36 Marc Zyngier wrote:
> On Thu, 06 Jan 2022 17:20:44 +0000,
> Marek Behún <kabel@kernel.org> wrote:
> > 
> > On Thu, 06 Jan 2022 16:27:44 +0000
> > Marc Zyngier <maz@kernel.org> wrote:
> > > You are completely missing my point. I'm talking about data
> > > structures, you're talking about interrupts. You have this:
> > > 
> > > struct mvebu_pcie_port {
> > >        // Tons of stuff
> > >        struct irq_chip intx_chip;
> > > };
> > > 
> > > What I want you to do is:
> > > 
> > > struct mvebu_pcie_port {
> > >        // Tons of stuff
> > > };
> > > 
> > > static struct irq_chip intx_chip = {
> > > 	.name		= "INTx",
> > > 	.irq_mask	= mvebu_pcie_intx_irq_mask,
> > > 	.irq_unmask	= mvebu_pcie_intx_irq_unmask;
> > > };
> > > 
> > > That's it. No more, no less.
> > > 
> > > 	M.
> > > 
> > 
> > Hmm, but struct irq_chip contains a dynamic member,
> >   struct device *parent_device;
> > Isn't that used? Or are you planning to kill it?
> 
> Indeed, and I am definitely planning to kill it. This is the wrong
> place for this stuff, and I want it gone. There are thankfully very
> few users of this misfeature.

Ok, so what about this change?

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 1e90ab888075..5c816338a569 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -54,9 +54,10 @@
 	 PCIE_CONF_ADDR_EN)
 #define PCIE_CONF_DATA_OFF	0x18fc
 #define PCIE_INT_CAUSE_OFF	0x1900
+#define PCIE_INT_UNMASK_OFF	0x1910
+#define  PCIE_INT_INTX(i)		BIT(24+i)
 #define  PCIE_INT_PM_PME		BIT(28)
-#define PCIE_MASK_OFF		0x1910
-#define  PCIE_MASK_ENABLE_INTS          0x0f000000
+#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
 #define PCIE_CTRL_OFF		0x1a00
 #define  PCIE_CTRL_X1_MODE		0x0001
 #define  PCIE_CTRL_RC_MODE		BIT(1)
@@ -110,6 +111,9 @@ struct mvebu_pcie_port {
 	struct mvebu_pcie_window iowin;
 	u32 saved_pcie_stat;
 	struct resource regs;
+	struct irq_domain *intx_irq_domain;
+	raw_spinlock_t irq_lock;
+	int intx_irq;
 };
 
 static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
@@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
 
 static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 {
-	u32 ctrl, lnkcap, cmd, dev_rev, mask;
+	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
 
 	/* Setup PCIe controller to Root Complex mode. */
 	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
@@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 	/* Point PCIe unit MBUS decode windows to DRAM space. */
 	mvebu_pcie_setup_wins(port);
 
-	/* Enable interrupt lines A-D. */
-	mask = mvebu_readl(port, PCIE_MASK_OFF);
-	mask |= PCIE_MASK_ENABLE_INTS;
-	mvebu_writel(port, mask, PCIE_MASK_OFF);
+	/* Mask all interrupt sources. */
+	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
+
+	/* Clear all interrupt causes. */
+	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
+
+	if (port->intx_irq <= 0) {
+		/*
+		 * When neither "summary" interrupt, nor "intx" interrupt was
+		 * specified in DT then unmask all legacy INTx interrupts as in
+		 * this case driver does not provide a way for masking and
+		 * unmasking of individual legacy INTx interrupts. In this case
+		 * all interrupts, including legacy INTx are reported via one
+		 * shared GIC source and therefore kernel cannot distinguish
+		 * which individual legacy INTx was triggered. These interrupts
+		 * are shared, so it should not cause any issue. Just
+		 * performance penalty as every PCIe interrupt handler needs to
+		 * be called when some interrupt is triggered.
+		 */
+		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
+			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
+		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	}
 }
 
 static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
@@ -924,6 +948,108 @@ static struct pci_ops mvebu_pcie_ops = {
 	.write = mvebu_pcie_wr_conf,
 };
 
+static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
+{
+	struct mvebu_pcie_port *port = d->domain->host_data;
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+	unsigned long flags;
+	u32 unmask;
+
+	raw_spin_lock_irqsave(&port->irq_lock, flags);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	unmask &= ~PCIE_INT_INTX(hwirq);
+	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
+}
+
+static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
+{
+	struct mvebu_pcie_port *port = d->domain->host_data;
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+	unsigned long flags;
+	u32 unmask;
+
+	raw_spin_lock_irqsave(&port->irq_lock, flags);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	unmask |= PCIE_INT_INTX(hwirq);
+	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
+}
+
+static struct irq_chip intx_irq_chip = {
+	.name = "mvebu-INTx",
+	.irq_mask = mvebu_pcie_intx_irq_mask,
+	.irq_unmask = mvebu_pcie_intx_irq_unmask,
+};
+
+static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
+				   unsigned int virq, irq_hw_number_t hwirq)
+{
+	struct mvebu_pcie_port *port = h->host_data;
+
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, &intx_irq_chip, handle_level_irq);
+	irq_set_chip_data(virq, port);
+
+	return 0;
+}
+
+static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
+	.map = mvebu_pcie_intx_irq_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
+{
+	struct device *dev = &port->pcie->pdev->dev;
+	struct device_node *pcie_intc_node;
+
+	raw_spin_lock_init(&port->irq_lock);
+
+	pcie_intc_node = of_get_next_child(port->dn, NULL);
+	if (!pcie_intc_node) {
+		dev_err(dev, "No PCIe Intc node found for %s\n", port->name);
+		return -ENODEV;
+	}
+
+	port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
+						      &mvebu_pcie_intx_irq_domain_ops,
+						      port);
+	of_node_put(pcie_intc_node);
+	if (!port->intx_irq_domain) {
+		dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void mvebu_pcie_irq_handler(struct irq_desc *desc)
+{
+	struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct device *dev = &port->pcie->pdev->dev;
+	u32 cause, unmask, status;
+	int i;
+
+	chained_irq_enter(chip, desc);
+
+	cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	status = cause & unmask;
+
+	/* Process legacy INTx interrupts */
+	for (i = 0; i < PCI_NUM_INTX; i++) {
+		if (!(status & PCIE_INT_INTX(i)))
+			continue;
+
+		if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL)
+			dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A');
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
 static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	/* Interrupt support on mvebu emulated bridges is not implemented yet */
@@ -1121,6 +1247,21 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
 		port->io_attr = -1;
 	}
 
+	/*
+	 * Old DT bindings do not contain "intx" interrupt
+	 * so do not fail probing driver when interrupt does not exist.
+	 */
+	port->intx_irq = of_irq_get_byname(child, "intx");
+	if (port->intx_irq == -EPROBE_DEFER) {
+		ret = port->intx_irq;
+		goto err;
+	}
+	if (port->intx_irq <= 0) {
+		dev_warn(dev, "%s: legacy INTx interrupts cannot be masked individually, "
+			      "%pOF does not contain intx interrupt\n",
+			 port->name, child);
+	}
+
 	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
 	if (reset_gpio == -EPROBE_DEFER) {
 		ret = reset_gpio;
@@ -1317,6 +1458,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 
 	for (i = 0; i < pcie->nports; i++) {
 		struct mvebu_pcie_port *port = &pcie->ports[i];
+		int irq = port->intx_irq;
 
 		child = port->dn;
 		if (!child)
@@ -1344,6 +1486,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 			continue;
 		}
 
+		if (irq > 0) {
+			ret = mvebu_pcie_init_irq_domain(port);
+			if (ret) {
+				dev_err(dev, "%s: cannot init irq domain\n",
+					port->name);
+				pci_bridge_emul_cleanup(&port->bridge);
+				devm_iounmap(dev, port->base);
+				port->base = NULL;
+				mvebu_pcie_powerdown(port);
+				continue;
+			}
+			irq_set_chained_handler_and_data(irq,
+							 mvebu_pcie_irq_handler,
+							 port);
+		}
+
 		/*
 		 * PCIe topology exported by mvebu hw is quite complicated. In
 		 * reality has something like N fully independent host bridges
@@ -1448,6 +1606,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
 
 	for (i = 0; i < pcie->nports; i++) {
 		struct mvebu_pcie_port *port = &pcie->ports[i];
+		int irq = port->intx_irq;
 
 		if (!port->base)
 			continue;
@@ -1458,7 +1617,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
 		mvebu_writel(port, cmd, PCIE_CMD_OFF);
 
 		/* Mask all interrupt sources. */
-		mvebu_writel(port, 0, PCIE_MASK_OFF);
+		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
+
+		/* Clear all interrupt causes. */
+		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
+
+		/* Remove IRQ domains. */
+		if (port->intx_irq_domain)
+			irq_domain_remove(port->intx_irq_domain);
+
+		if (irq > 0)
+			irq_set_chained_handler_and_data(irq, NULL, NULL);
 
 		/* Free config space for emulated root bridge. */
 		pci_bridge_emul_cleanup(&port->bridge);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-01-07 11:50                   ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-07 11:50 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Marek Behún, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thursday 06 January 2022 17:31:36 Marc Zyngier wrote:
> On Thu, 06 Jan 2022 17:20:44 +0000,
> Marek Behún <kabel@kernel.org> wrote:
> > 
> > On Thu, 06 Jan 2022 16:27:44 +0000
> > Marc Zyngier <maz@kernel.org> wrote:
> > > You are completely missing my point. I'm talking about data
> > > structures, you're talking about interrupts. You have this:
> > > 
> > > struct mvebu_pcie_port {
> > >        // Tons of stuff
> > >        struct irq_chip intx_chip;
> > > };
> > > 
> > > What I want you to do is:
> > > 
> > > struct mvebu_pcie_port {
> > >        // Tons of stuff
> > > };
> > > 
> > > static struct irq_chip intx_chip = {
> > > 	.name		= "INTx",
> > > 	.irq_mask	= mvebu_pcie_intx_irq_mask,
> > > 	.irq_unmask	= mvebu_pcie_intx_irq_unmask;
> > > };
> > > 
> > > That's it. No more, no less.
> > > 
> > > 	M.
> > > 
> > 
> > Hmm, but struct irq_chip contains a dynamic member,
> >   struct device *parent_device;
> > Isn't that used? Or are you planning to kill it?
> 
> Indeed, and I am definitely planning to kill it. This is the wrong
> place for this stuff, and I want it gone. There are thankfully very
> few users of this misfeature.

Ok, so what about this change?

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 1e90ab888075..5c816338a569 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -54,9 +54,10 @@
 	 PCIE_CONF_ADDR_EN)
 #define PCIE_CONF_DATA_OFF	0x18fc
 #define PCIE_INT_CAUSE_OFF	0x1900
+#define PCIE_INT_UNMASK_OFF	0x1910
+#define  PCIE_INT_INTX(i)		BIT(24+i)
 #define  PCIE_INT_PM_PME		BIT(28)
-#define PCIE_MASK_OFF		0x1910
-#define  PCIE_MASK_ENABLE_INTS          0x0f000000
+#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
 #define PCIE_CTRL_OFF		0x1a00
 #define  PCIE_CTRL_X1_MODE		0x0001
 #define  PCIE_CTRL_RC_MODE		BIT(1)
@@ -110,6 +111,9 @@ struct mvebu_pcie_port {
 	struct mvebu_pcie_window iowin;
 	u32 saved_pcie_stat;
 	struct resource regs;
+	struct irq_domain *intx_irq_domain;
+	raw_spinlock_t irq_lock;
+	int intx_irq;
 };
 
 static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
@@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
 
 static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 {
-	u32 ctrl, lnkcap, cmd, dev_rev, mask;
+	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
 
 	/* Setup PCIe controller to Root Complex mode. */
 	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
@@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 	/* Point PCIe unit MBUS decode windows to DRAM space. */
 	mvebu_pcie_setup_wins(port);
 
-	/* Enable interrupt lines A-D. */
-	mask = mvebu_readl(port, PCIE_MASK_OFF);
-	mask |= PCIE_MASK_ENABLE_INTS;
-	mvebu_writel(port, mask, PCIE_MASK_OFF);
+	/* Mask all interrupt sources. */
+	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
+
+	/* Clear all interrupt causes. */
+	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
+
+	if (port->intx_irq <= 0) {
+		/*
+		 * When neither "summary" interrupt, nor "intx" interrupt was
+		 * specified in DT then unmask all legacy INTx interrupts as in
+		 * this case driver does not provide a way for masking and
+		 * unmasking of individual legacy INTx interrupts. In this case
+		 * all interrupts, including legacy INTx are reported via one
+		 * shared GIC source and therefore kernel cannot distinguish
+		 * which individual legacy INTx was triggered. These interrupts
+		 * are shared, so it should not cause any issue. Just
+		 * performance penalty as every PCIe interrupt handler needs to
+		 * be called when some interrupt is triggered.
+		 */
+		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
+			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
+		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	}
 }
 
 static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
@@ -924,6 +948,108 @@ static struct pci_ops mvebu_pcie_ops = {
 	.write = mvebu_pcie_wr_conf,
 };
 
+static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
+{
+	struct mvebu_pcie_port *port = d->domain->host_data;
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+	unsigned long flags;
+	u32 unmask;
+
+	raw_spin_lock_irqsave(&port->irq_lock, flags);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	unmask &= ~PCIE_INT_INTX(hwirq);
+	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
+}
+
+static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
+{
+	struct mvebu_pcie_port *port = d->domain->host_data;
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+	unsigned long flags;
+	u32 unmask;
+
+	raw_spin_lock_irqsave(&port->irq_lock, flags);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	unmask |= PCIE_INT_INTX(hwirq);
+	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
+}
+
+static struct irq_chip intx_irq_chip = {
+	.name = "mvebu-INTx",
+	.irq_mask = mvebu_pcie_intx_irq_mask,
+	.irq_unmask = mvebu_pcie_intx_irq_unmask,
+};
+
+static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
+				   unsigned int virq, irq_hw_number_t hwirq)
+{
+	struct mvebu_pcie_port *port = h->host_data;
+
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, &intx_irq_chip, handle_level_irq);
+	irq_set_chip_data(virq, port);
+
+	return 0;
+}
+
+static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
+	.map = mvebu_pcie_intx_irq_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
+{
+	struct device *dev = &port->pcie->pdev->dev;
+	struct device_node *pcie_intc_node;
+
+	raw_spin_lock_init(&port->irq_lock);
+
+	pcie_intc_node = of_get_next_child(port->dn, NULL);
+	if (!pcie_intc_node) {
+		dev_err(dev, "No PCIe Intc node found for %s\n", port->name);
+		return -ENODEV;
+	}
+
+	port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
+						      &mvebu_pcie_intx_irq_domain_ops,
+						      port);
+	of_node_put(pcie_intc_node);
+	if (!port->intx_irq_domain) {
+		dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void mvebu_pcie_irq_handler(struct irq_desc *desc)
+{
+	struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct device *dev = &port->pcie->pdev->dev;
+	u32 cause, unmask, status;
+	int i;
+
+	chained_irq_enter(chip, desc);
+
+	cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	status = cause & unmask;
+
+	/* Process legacy INTx interrupts */
+	for (i = 0; i < PCI_NUM_INTX; i++) {
+		if (!(status & PCIE_INT_INTX(i)))
+			continue;
+
+		if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL)
+			dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A');
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
 static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	/* Interrupt support on mvebu emulated bridges is not implemented yet */
@@ -1121,6 +1247,21 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
 		port->io_attr = -1;
 	}
 
+	/*
+	 * Old DT bindings do not contain "intx" interrupt
+	 * so do not fail probing driver when interrupt does not exist.
+	 */
+	port->intx_irq = of_irq_get_byname(child, "intx");
+	if (port->intx_irq == -EPROBE_DEFER) {
+		ret = port->intx_irq;
+		goto err;
+	}
+	if (port->intx_irq <= 0) {
+		dev_warn(dev, "%s: legacy INTx interrupts cannot be masked individually, "
+			      "%pOF does not contain intx interrupt\n",
+			 port->name, child);
+	}
+
 	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
 	if (reset_gpio == -EPROBE_DEFER) {
 		ret = reset_gpio;
@@ -1317,6 +1458,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 
 	for (i = 0; i < pcie->nports; i++) {
 		struct mvebu_pcie_port *port = &pcie->ports[i];
+		int irq = port->intx_irq;
 
 		child = port->dn;
 		if (!child)
@@ -1344,6 +1486,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 			continue;
 		}
 
+		if (irq > 0) {
+			ret = mvebu_pcie_init_irq_domain(port);
+			if (ret) {
+				dev_err(dev, "%s: cannot init irq domain\n",
+					port->name);
+				pci_bridge_emul_cleanup(&port->bridge);
+				devm_iounmap(dev, port->base);
+				port->base = NULL;
+				mvebu_pcie_powerdown(port);
+				continue;
+			}
+			irq_set_chained_handler_and_data(irq,
+							 mvebu_pcie_irq_handler,
+							 port);
+		}
+
 		/*
 		 * PCIe topology exported by mvebu hw is quite complicated. In
 		 * reality has something like N fully independent host bridges
@@ -1448,6 +1606,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
 
 	for (i = 0; i < pcie->nports; i++) {
 		struct mvebu_pcie_port *port = &pcie->ports[i];
+		int irq = port->intx_irq;
 
 		if (!port->base)
 			continue;
@@ -1458,7 +1617,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
 		mvebu_writel(port, cmd, PCIE_CMD_OFF);
 
 		/* Mask all interrupt sources. */
-		mvebu_writel(port, 0, PCIE_MASK_OFF);
+		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
+
+		/* Clear all interrupt causes. */
+		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
+
+		/* Remove IRQ domains. */
+		if (port->intx_irq_domain)
+			irq_domain_remove(port->intx_irq_domain);
+
+		if (irq > 0)
+			irq_set_chained_handler_and_data(irq, NULL, NULL);
 
 		/* Free config space for emulated root bridge. */
 		pci_bridge_emul_cleanup(&port->bridge);
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-01-07 11:50                   ` Pali Rohár
@ 2022-01-07 18:53                     ` Marc Zyngier
  -1 siblings, 0 replies; 130+ messages in thread
From: Marc Zyngier @ 2022-01-07 18:53 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Marek Behún, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Fri, 07 Jan 2022 11:50:53 +0000,
Pali Rohár <pali@kernel.org> wrote:
> 
> On Thursday 06 January 2022 17:31:36 Marc Zyngier wrote:
> > On Thu, 06 Jan 2022 17:20:44 +0000,
> > Marek Behún <kabel@kernel.org> wrote:
> > > 
> > > On Thu, 06 Jan 2022 16:27:44 +0000
> > > Marc Zyngier <maz@kernel.org> wrote:
> > > > You are completely missing my point. I'm talking about data
> > > > structures, you're talking about interrupts. You have this:
> > > > 
> > > > struct mvebu_pcie_port {
> > > >        // Tons of stuff
> > > >        struct irq_chip intx_chip;
> > > > };
> > > > 
> > > > What I want you to do is:
> > > > 
> > > > struct mvebu_pcie_port {
> > > >        // Tons of stuff
> > > > };
> > > > 
> > > > static struct irq_chip intx_chip = {
> > > > 	.name		= "INTx",
> > > > 	.irq_mask	= mvebu_pcie_intx_irq_mask,
> > > > 	.irq_unmask	= mvebu_pcie_intx_irq_unmask;
> > > > };
> > > > 
> > > > That's it. No more, no less.
> > > > 
> > > > 	M.
> > > > 
> > > 
> > > Hmm, but struct irq_chip contains a dynamic member,
> > >   struct device *parent_device;
> > > Isn't that used? Or are you planning to kill it?
> > 
> > Indeed, and I am definitely planning to kill it. This is the wrong
> > place for this stuff, and I want it gone. There are thankfully very
> > few users of this misfeature.
> 
> Ok, so what about this change?
> 
> @@ -1458,7 +1617,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
>  		mvebu_writel(port, cmd, PCIE_CMD_OFF);
>  
>  		/* Mask all interrupt sources. */
> -		mvebu_writel(port, 0, PCIE_MASK_OFF);
> +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> +
> +		/* Clear all interrupt causes. */
> +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> +
> +		/* Remove IRQ domains. */
> +		if (port->intx_irq_domain)
> +			irq_domain_remove(port->intx_irq_domain);
> +
> +		if (irq > 0)
> +			irq_set_chained_handler_and_data(irq, NULL, NULL);

You really want this to be done *before* you remove the domain, as
there still could be interrupts in flight at this point.

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-01-07 18:53                     ` Marc Zyngier
  0 siblings, 0 replies; 130+ messages in thread
From: Marc Zyngier @ 2022-01-07 18:53 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Marek Behún, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Fri, 07 Jan 2022 11:50:53 +0000,
Pali Rohár <pali@kernel.org> wrote:
> 
> On Thursday 06 January 2022 17:31:36 Marc Zyngier wrote:
> > On Thu, 06 Jan 2022 17:20:44 +0000,
> > Marek Behún <kabel@kernel.org> wrote:
> > > 
> > > On Thu, 06 Jan 2022 16:27:44 +0000
> > > Marc Zyngier <maz@kernel.org> wrote:
> > > > You are completely missing my point. I'm talking about data
> > > > structures, you're talking about interrupts. You have this:
> > > > 
> > > > struct mvebu_pcie_port {
> > > >        // Tons of stuff
> > > >        struct irq_chip intx_chip;
> > > > };
> > > > 
> > > > What I want you to do is:
> > > > 
> > > > struct mvebu_pcie_port {
> > > >        // Tons of stuff
> > > > };
> > > > 
> > > > static struct irq_chip intx_chip = {
> > > > 	.name		= "INTx",
> > > > 	.irq_mask	= mvebu_pcie_intx_irq_mask,
> > > > 	.irq_unmask	= mvebu_pcie_intx_irq_unmask;
> > > > };
> > > > 
> > > > That's it. No more, no less.
> > > > 
> > > > 	M.
> > > > 
> > > 
> > > Hmm, but struct irq_chip contains a dynamic member,
> > >   struct device *parent_device;
> > > Isn't that used? Or are you planning to kill it?
> > 
> > Indeed, and I am definitely planning to kill it. This is the wrong
> > place for this stuff, and I want it gone. There are thankfully very
> > few users of this misfeature.
> 
> Ok, so what about this change?
> 
> @@ -1458,7 +1617,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
>  		mvebu_writel(port, cmd, PCIE_CMD_OFF);
>  
>  		/* Mask all interrupt sources. */
> -		mvebu_writel(port, 0, PCIE_MASK_OFF);
> +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> +
> +		/* Clear all interrupt causes. */
> +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> +
> +		/* Remove IRQ domains. */
> +		if (port->intx_irq_domain)
> +			irq_domain_remove(port->intx_irq_domain);
> +
> +		if (irq > 0)
> +			irq_set_chained_handler_and_data(irq, NULL, NULL);

You really want this to be done *before* you remove the domain, as
there still could be interrupts in flight at this point.

	M.

-- 
Without deviation from the norm, progress is not possible.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 04/11] dt-bindings: PCI: mvebu: Add num-lanes property
  2022-01-05 15:02   ` Pali Rohár
@ 2022-01-12  1:29     ` Rob Herring
  -1 siblings, 0 replies; 130+ messages in thread
From: Rob Herring @ 2022-01-12  1:29 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Krzysztof Wilczyński, Thomas Petazzoni, linux-arm-kernel,
	Rob Herring, Bjorn Helgaas, Marek Behún, linux-pci,
	linux-kernel, Russell King, devicetree, Andrew Lunn,
	Gregory Clement, Lorenzo Pieralisi

On Wed, 05 Jan 2022 16:02:32 +0100, Pali Rohár wrote:
> Controller driver needs to correctly configure PCIe link if it contains 1
> or 4 SerDes PCIe lanes. Therefore add a new 'num-lanes' DT property for
> mvebu PCIe controller. Property 'num-lanes' seems to be de-facto standard
> way how number of lanes is specified in other PCIe controllers.
> 
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  Documentation/devicetree/bindings/pci/mvebu-pci.txt | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 04/11] dt-bindings: PCI: mvebu: Add num-lanes property
@ 2022-01-12  1:29     ` Rob Herring
  0 siblings, 0 replies; 130+ messages in thread
From: Rob Herring @ 2022-01-12  1:29 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Krzysztof Wilczyński, Thomas Petazzoni, linux-arm-kernel,
	Rob Herring, Bjorn Helgaas, Marek Behún, linux-pci,
	linux-kernel, Russell King, devicetree, Andrew Lunn,
	Gregory Clement, Lorenzo Pieralisi

On Wed, 05 Jan 2022 16:02:32 +0100, Pali Rohár wrote:
> Controller driver needs to correctly configure PCIe link if it contains 1
> or 4 SerDes PCIe lanes. Therefore add a new 'num-lanes' DT property for
> mvebu PCIe controller. Property 'num-lanes' seems to be de-facto standard
> way how number of lanes is specified in other PCIe controllers.
> 
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  Documentation/devicetree/bindings/pci/mvebu-pci.txt | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 09/11] dt-bindings: PCI: mvebu: Update information about intx interrupts
  2022-01-05 15:02   ` Pali Rohár
@ 2022-01-12  1:30     ` Rob Herring
  -1 siblings, 0 replies; 130+ messages in thread
From: Rob Herring @ 2022-01-12  1:30 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Russell King, Gregory Clement, devicetree, Rob Herring,
	linux-kernel, linux-pci, Krzysztof Wilczyński,
	Bjorn Helgaas, linux-arm-kernel, Marek Behún, Andrew Lunn,
	Thomas Petazzoni, Lorenzo Pieralisi

On Wed, 05 Jan 2022 16:02:37 +0100, Pali Rohár wrote:
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  Documentation/devicetree/bindings/pci/mvebu-pci.txt | 5 +++++
>  1 file changed, 5 insertions(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 09/11] dt-bindings: PCI: mvebu: Update information about intx interrupts
@ 2022-01-12  1:30     ` Rob Herring
  0 siblings, 0 replies; 130+ messages in thread
From: Rob Herring @ 2022-01-12  1:30 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Russell King, Gregory Clement, devicetree, Rob Herring,
	linux-kernel, linux-pci, Krzysztof Wilczyński,
	Bjorn Helgaas, linux-arm-kernel, Marek Behún, Andrew Lunn,
	Thomas Petazzoni, Lorenzo Pieralisi

On Wed, 05 Jan 2022 16:02:37 +0100, Pali Rohár wrote:
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  Documentation/devicetree/bindings/pci/mvebu-pci.txt | 5 +++++
>  1 file changed, 5 insertions(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 08/11] PCI: mvebu: Use child_ops API
  2022-01-05 15:41     ` Rob Herring
@ 2022-01-12  1:43       ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12  1:43 UTC (permalink / raw)
  To: Rob Herring
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King, PCI,
	linux-kernel, linux-arm-kernel

On Wednesday 05 January 2022 09:41:51 Rob Herring wrote:
> On Wed, Jan 5, 2022 at 9:03 AM Pali Rohár <pali@kernel.org> wrote:
> >
> > Split struct pci_ops between ops and child_ops. Member ops is used for
> > accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
> > accessing real PCIe cards.
> >
> > There is no need to mix these two struct pci_ops into one as PCI core code
> > already provides separate callbacks via bridge->ops and bridge->child_ops.
> 
> I had similar patches including mvebu that I never got around to
> sending out. I pushed the branch out now at least[1].

Are you going to finish your patch series and send it? Because if yes,
I can drop this my patch in v3 and let all ->child_ops conversion for
you.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 08/11] PCI: mvebu: Use child_ops API
@ 2022-01-12  1:43       ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12  1:43 UTC (permalink / raw)
  To: Rob Herring
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King, PCI,
	linux-kernel, linux-arm-kernel

On Wednesday 05 January 2022 09:41:51 Rob Herring wrote:
> On Wed, Jan 5, 2022 at 9:03 AM Pali Rohár <pali@kernel.org> wrote:
> >
> > Split struct pci_ops between ops and child_ops. Member ops is used for
> > accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
> > accessing real PCIe cards.
> >
> > There is no need to mix these two struct pci_ops into one as PCI core code
> > already provides separate callbacks via bridge->ops and bridge->child_ops.
> 
> I had similar patches including mvebu that I never got around to
> sending out. I pushed the branch out now at least[1].

Are you going to finish your patch series and send it? Because if yes,
I can drop this my patch in v3 and let all ->child_ops conversion for
you.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 08/11] PCI: mvebu: Use child_ops API
  2022-01-12  1:43       ` Pali Rohár
@ 2022-01-12 14:53         ` Rob Herring
  -1 siblings, 0 replies; 130+ messages in thread
From: Rob Herring @ 2022-01-12 14:53 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King, PCI,
	linux-kernel, linux-arm-kernel

On Tue, Jan 11, 2022 at 7:44 PM Pali Rohár <pali@kernel.org> wrote:
>
> On Wednesday 05 January 2022 09:41:51 Rob Herring wrote:
> > On Wed, Jan 5, 2022 at 9:03 AM Pali Rohár <pali@kernel.org> wrote:
> > >
> > > Split struct pci_ops between ops and child_ops. Member ops is used for
> > > accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
> > > accessing real PCIe cards.
> > >
> > > There is no need to mix these two struct pci_ops into one as PCI core code
> > > already provides separate callbacks via bridge->ops and bridge->child_ops.
> >
> > I had similar patches including mvebu that I never got around to
> > sending out. I pushed the branch out now at least[1].
>
> Are you going to finish your patch series and send it? Because if yes,
> I can drop this my patch in v3 and let all ->child_ops conversion for
> you.

Not any time soon.

Rob

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 08/11] PCI: mvebu: Use child_ops API
@ 2022-01-12 14:53         ` Rob Herring
  0 siblings, 0 replies; 130+ messages in thread
From: Rob Herring @ 2022-01-12 14:53 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King, PCI,
	linux-kernel, linux-arm-kernel

On Tue, Jan 11, 2022 at 7:44 PM Pali Rohár <pali@kernel.org> wrote:
>
> On Wednesday 05 January 2022 09:41:51 Rob Herring wrote:
> > On Wed, Jan 5, 2022 at 9:03 AM Pali Rohár <pali@kernel.org> wrote:
> > >
> > > Split struct pci_ops between ops and child_ops. Member ops is used for
> > > accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
> > > accessing real PCIe cards.
> > >
> > > There is no need to mix these two struct pci_ops into one as PCI core code
> > > already provides separate callbacks via bridge->ops and bridge->child_ops.
> >
> > I had similar patches including mvebu that I never got around to
> > sending out. I pushed the branch out now at least[1].
>
> Are you going to finish your patch series and send it? Because if yes,
> I can drop this my patch in v3 and let all ->child_ops conversion for
> you.

Not any time soon.

Rob

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v2 00/11] PCI: mvebu: subsystem ids, AER and INTx
  2022-01-05 15:02 ` Pali Rohár
@ 2022-01-12 15:18   ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

This patch series extends pci-bridge-emul.c driver to emulate PCI Subsystem
Vendor ID capability and PCIe extended capabilities. And then implement
in pci-mvebu.c driver support for PCI Subsystem Vendor IDs, PCIe AER
registers, support for legacy INTx interrupts, configuration for X1/X4
mode and usage of new PCI child_ops API.

This patch series depends on other pci-mvebu and pci-bridge-emul patches from:
https://lore.kernel.org/linux-pci/20220104153529.31647-1-pali@kernel.org/

Changes in v2:
* use static structures for INTx interrupts
* remove INTx domain after unregistering INTx handler

Pali Rohár (9):
  PCI: pci-bridge-emul: Add support for PCI Bridge Subsystem Vendor ID
    capability
  dt-bindings: PCI: mvebu: Add num-lanes property
  PCI: mvebu: Correctly configure x1/x4 mode
  PCI: mvebu: Add support for PCI Bridge Subsystem Vendor ID on emulated
    bridge
  PCI: mvebu: Add support for Advanced Error Reporting registers on
    emulated bridge
  PCI: mvebu: Use child_ops API
  dt-bindings: PCI: mvebu: Update information about intx interrupts
  PCI: mvebu: Implement support for legacy INTx interrupts
  ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx
    interrupts

Russell King (2):
  PCI: pci-bridge-emul: Re-arrange register tests
  PCI: pci-bridge-emul: Add support for PCIe extended capabilities

 .../devicetree/bindings/pci/mvebu-pci.txt     |  16 +
 arch/arm/boot/dts/armada-385.dtsi             |  52 ++-
 drivers/pci/controller/pci-mvebu.c            | 355 +++++++++++++++---
 drivers/pci/pci-bridge-emul.c                 | 167 +++++---
 drivers/pci/pci-bridge-emul.h                 |  17 +
 5 files changed, 497 insertions(+), 110 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v2 00/11] PCI: mvebu: subsystem ids, AER and INTx
@ 2022-01-12 15:18   ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

This patch series extends pci-bridge-emul.c driver to emulate PCI Subsystem
Vendor ID capability and PCIe extended capabilities. And then implement
in pci-mvebu.c driver support for PCI Subsystem Vendor IDs, PCIe AER
registers, support for legacy INTx interrupts, configuration for X1/X4
mode and usage of new PCI child_ops API.

This patch series depends on other pci-mvebu and pci-bridge-emul patches from:
https://lore.kernel.org/linux-pci/20220104153529.31647-1-pali@kernel.org/

Changes in v2:
* use static structures for INTx interrupts
* remove INTx domain after unregistering INTx handler

Pali Rohár (9):
  PCI: pci-bridge-emul: Add support for PCI Bridge Subsystem Vendor ID
    capability
  dt-bindings: PCI: mvebu: Add num-lanes property
  PCI: mvebu: Correctly configure x1/x4 mode
  PCI: mvebu: Add support for PCI Bridge Subsystem Vendor ID on emulated
    bridge
  PCI: mvebu: Add support for Advanced Error Reporting registers on
    emulated bridge
  PCI: mvebu: Use child_ops API
  dt-bindings: PCI: mvebu: Update information about intx interrupts
  PCI: mvebu: Implement support for legacy INTx interrupts
  ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx
    interrupts

Russell King (2):
  PCI: pci-bridge-emul: Re-arrange register tests
  PCI: pci-bridge-emul: Add support for PCIe extended capabilities

 .../devicetree/bindings/pci/mvebu-pci.txt     |  16 +
 arch/arm/boot/dts/armada-385.dtsi             |  52 ++-
 drivers/pci/controller/pci-mvebu.c            | 355 +++++++++++++++---
 drivers/pci/pci-bridge-emul.c                 | 167 +++++---
 drivers/pci/pci-bridge-emul.h                 |  17 +
 5 files changed, 497 insertions(+), 110 deletions(-)

-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v2 01/11] PCI: pci-bridge-emul: Re-arrange register tests
  2022-01-12 15:18   ` Pali Rohár
@ 2022-01-12 15:18     ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

From: Russell King <rmk+kernel@armlinux.org.uk>

Re-arrange the tests for which sets of registers are being accessed so that
it is easier to add further regions later. No functional change.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
[pali: Fix reading old value in pci_bridge_emul_conf_write]
Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/pci-bridge-emul.c | 61 ++++++++++++++++++-----------------
 1 file changed, 31 insertions(+), 30 deletions(-)

diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c
index 033bbeb99176..56b2cb741498 100644
--- a/drivers/pci/pci-bridge-emul.c
+++ b/drivers/pci/pci-bridge-emul.c
@@ -418,25 +418,25 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
 	__le32 *cfgspace;
 	const struct pci_bridge_reg_behavior *behavior;
 
-	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_END) {
-		*value = 0;
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	if (!bridge->has_pcie && reg >= PCI_BRIDGE_CONF_END) {
+	if (reg < PCI_BRIDGE_CONF_END) {
+		/* Emulated PCI space */
+		read_op = bridge->ops->read_base;
+		cfgspace = (__le32 *) &bridge->conf;
+		behavior = bridge->pci_regs_behavior;
+	} else if (!bridge->has_pcie) {
+		/* PCIe space is not implemented, and no PCI capabilities */
 		*value = 0;
 		return PCIBIOS_SUCCESSFUL;
-	}
-
-	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_START) {
+	} else if (reg < PCI_CAP_PCIE_END) {
+		/* Our emulated PCIe capability */
 		reg -= PCI_CAP_PCIE_START;
 		read_op = bridge->ops->read_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
 	} else {
-		read_op = bridge->ops->read_base;
-		cfgspace = (__le32 *) &bridge->conf;
-		behavior = bridge->pci_regs_behavior;
+		/* Beyond our PCIe space */
+		*value = 0;
+		return PCIBIOS_SUCCESSFUL;
 	}
 
 	if (read_op)
@@ -480,11 +480,27 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 	__le32 *cfgspace;
 	const struct pci_bridge_reg_behavior *behavior;
 
-	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_END)
-		return PCIBIOS_SUCCESSFUL;
+	ret = pci_bridge_emul_conf_read(bridge, reg, 4, &old);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		return ret;
 
-	if (!bridge->has_pcie && reg >= PCI_BRIDGE_CONF_END)
+	if (reg < PCI_BRIDGE_CONF_END) {
+		/* Emulated PCI space */
+		write_op = bridge->ops->write_base;
+		cfgspace = (__le32 *) &bridge->conf;
+		behavior = bridge->pci_regs_behavior;
+	} else if (!bridge->has_pcie) {
+		/* PCIe space is not implemented, and no PCI capabilities */
 		return PCIBIOS_SUCCESSFUL;
+	} else if (reg < PCI_CAP_PCIE_END) {
+		/* Our emulated PCIe capability */
+		reg -= PCI_CAP_PCIE_START;
+		write_op = bridge->ops->write_pcie;
+		cfgspace = (__le32 *) &bridge->pcie_conf;
+		behavior = bridge->pcie_cap_regs_behavior;
+	} else {
+		return PCIBIOS_SUCCESSFUL;
+	}
 
 	shift = (where & 0x3) * 8;
 
@@ -497,21 +513,6 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 	else
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
-	ret = pci_bridge_emul_conf_read(bridge, reg, 4, &old);
-	if (ret != PCIBIOS_SUCCESSFUL)
-		return ret;
-
-	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_START) {
-		reg -= PCI_CAP_PCIE_START;
-		write_op = bridge->ops->write_pcie;
-		cfgspace = (__le32 *) &bridge->pcie_conf;
-		behavior = bridge->pcie_cap_regs_behavior;
-	} else {
-		write_op = bridge->ops->write_base;
-		cfgspace = (__le32 *) &bridge->conf;
-		behavior = bridge->pci_regs_behavior;
-	}
-
 	/* Keep all bits, except the RW bits */
 	new = old & (~mask | ~behavior[reg / 4].rw);
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 01/11] PCI: pci-bridge-emul: Re-arrange register tests
@ 2022-01-12 15:18     ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

From: Russell King <rmk+kernel@armlinux.org.uk>

Re-arrange the tests for which sets of registers are being accessed so that
it is easier to add further regions later. No functional change.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
[pali: Fix reading old value in pci_bridge_emul_conf_write]
Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/pci-bridge-emul.c | 61 ++++++++++++++++++-----------------
 1 file changed, 31 insertions(+), 30 deletions(-)

diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c
index 033bbeb99176..56b2cb741498 100644
--- a/drivers/pci/pci-bridge-emul.c
+++ b/drivers/pci/pci-bridge-emul.c
@@ -418,25 +418,25 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
 	__le32 *cfgspace;
 	const struct pci_bridge_reg_behavior *behavior;
 
-	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_END) {
-		*value = 0;
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	if (!bridge->has_pcie && reg >= PCI_BRIDGE_CONF_END) {
+	if (reg < PCI_BRIDGE_CONF_END) {
+		/* Emulated PCI space */
+		read_op = bridge->ops->read_base;
+		cfgspace = (__le32 *) &bridge->conf;
+		behavior = bridge->pci_regs_behavior;
+	} else if (!bridge->has_pcie) {
+		/* PCIe space is not implemented, and no PCI capabilities */
 		*value = 0;
 		return PCIBIOS_SUCCESSFUL;
-	}
-
-	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_START) {
+	} else if (reg < PCI_CAP_PCIE_END) {
+		/* Our emulated PCIe capability */
 		reg -= PCI_CAP_PCIE_START;
 		read_op = bridge->ops->read_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
 	} else {
-		read_op = bridge->ops->read_base;
-		cfgspace = (__le32 *) &bridge->conf;
-		behavior = bridge->pci_regs_behavior;
+		/* Beyond our PCIe space */
+		*value = 0;
+		return PCIBIOS_SUCCESSFUL;
 	}
 
 	if (read_op)
@@ -480,11 +480,27 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 	__le32 *cfgspace;
 	const struct pci_bridge_reg_behavior *behavior;
 
-	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_END)
-		return PCIBIOS_SUCCESSFUL;
+	ret = pci_bridge_emul_conf_read(bridge, reg, 4, &old);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		return ret;
 
-	if (!bridge->has_pcie && reg >= PCI_BRIDGE_CONF_END)
+	if (reg < PCI_BRIDGE_CONF_END) {
+		/* Emulated PCI space */
+		write_op = bridge->ops->write_base;
+		cfgspace = (__le32 *) &bridge->conf;
+		behavior = bridge->pci_regs_behavior;
+	} else if (!bridge->has_pcie) {
+		/* PCIe space is not implemented, and no PCI capabilities */
 		return PCIBIOS_SUCCESSFUL;
+	} else if (reg < PCI_CAP_PCIE_END) {
+		/* Our emulated PCIe capability */
+		reg -= PCI_CAP_PCIE_START;
+		write_op = bridge->ops->write_pcie;
+		cfgspace = (__le32 *) &bridge->pcie_conf;
+		behavior = bridge->pcie_cap_regs_behavior;
+	} else {
+		return PCIBIOS_SUCCESSFUL;
+	}
 
 	shift = (where & 0x3) * 8;
 
@@ -497,21 +513,6 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 	else
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
-	ret = pci_bridge_emul_conf_read(bridge, reg, 4, &old);
-	if (ret != PCIBIOS_SUCCESSFUL)
-		return ret;
-
-	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_START) {
-		reg -= PCI_CAP_PCIE_START;
-		write_op = bridge->ops->write_pcie;
-		cfgspace = (__le32 *) &bridge->pcie_conf;
-		behavior = bridge->pcie_cap_regs_behavior;
-	} else {
-		write_op = bridge->ops->write_base;
-		cfgspace = (__le32 *) &bridge->conf;
-		behavior = bridge->pci_regs_behavior;
-	}
-
 	/* Keep all bits, except the RW bits */
 	new = old & (~mask | ~behavior[reg / 4].rw);
 
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 02/11] PCI: pci-bridge-emul: Add support for PCIe extended capabilities
  2022-01-12 15:18   ` Pali Rohár
@ 2022-01-12 15:18     ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

From: Russell King <rmk+kernel@armlinux.org.uk>

Add support for PCIe extended capabilities, which we just redirect to the
emulating driver.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
[pali: Fix writing new value with W1C bits]
Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/pci-bridge-emul.c | 77 +++++++++++++++++++++++------------
 drivers/pci/pci-bridge-emul.h | 15 +++++++
 2 files changed, 67 insertions(+), 25 deletions(-)

diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c
index 56b2cb741498..9f4f173f0650 100644
--- a/drivers/pci/pci-bridge-emul.c
+++ b/drivers/pci/pci-bridge-emul.c
@@ -433,10 +433,16 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
 		read_op = bridge->ops->read_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
-	} else {
-		/* Beyond our PCIe space */
+	} else if (reg < PCI_CFG_SPACE_SIZE) {
+		/* Rest of PCI space not implemented */
 		*value = 0;
 		return PCIBIOS_SUCCESSFUL;
+	} else {
+		/* PCIe extended capability space */
+		reg -= PCI_CFG_SPACE_SIZE;
+		read_op = bridge->ops->read_ext;
+		cfgspace = NULL;
+		behavior = NULL;
 	}
 
 	if (read_op)
@@ -444,15 +450,20 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
 	else
 		ret = PCI_BRIDGE_EMUL_NOT_HANDLED;
 
-	if (ret == PCI_BRIDGE_EMUL_NOT_HANDLED)
-		*value = le32_to_cpu(cfgspace[reg / 4]);
+	if (ret == PCI_BRIDGE_EMUL_NOT_HANDLED) {
+		if (cfgspace)
+			*value = le32_to_cpu(cfgspace[reg / 4]);
+		else
+			*value = 0;
+	}
 
 	/*
 	 * Make sure we never return any reserved bit with a value
 	 * different from 0.
 	 */
-	*value &= behavior[reg / 4].ro | behavior[reg / 4].rw |
-		  behavior[reg / 4].w1c;
+	if (behavior)
+		*value &= behavior[reg / 4].ro | behavior[reg / 4].rw |
+			  behavior[reg / 4].w1c;
 
 	if (size == 1)
 		*value = (*value >> (8 * (where & 3))) & 0xff;
@@ -498,8 +509,15 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 		write_op = bridge->ops->write_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
-	} else {
+	} else if (reg < PCI_CFG_SPACE_SIZE) {
+		/* Rest of PCI space not implemented */
 		return PCIBIOS_SUCCESSFUL;
+	} else {
+		/* PCIe extended capability space */
+		reg -= PCI_CFG_SPACE_SIZE;
+		write_op = bridge->ops->write_ext;
+		cfgspace = NULL;
+		behavior = NULL;
 	}
 
 	shift = (where & 0x3) * 8;
@@ -513,29 +531,38 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 	else
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
-	/* Keep all bits, except the RW bits */
-	new = old & (~mask | ~behavior[reg / 4].rw);
+	if (behavior) {
+		/* Keep all bits, except the RW bits */
+		new = old & (~mask | ~behavior[reg / 4].rw);
 
-	/* Update the value of the RW bits */
-	new |= (value << shift) & (behavior[reg / 4].rw & mask);
+		/* Update the value of the RW bits */
+		new |= (value << shift) & (behavior[reg / 4].rw & mask);
 
-	/* Clear the W1C bits */
-	new &= ~((value << shift) & (behavior[reg / 4].w1c & mask));
+		/* Clear the W1C bits */
+		new &= ~((value << shift) & (behavior[reg / 4].w1c & mask));
+	} else {
+		new = old & ~mask;
+		new |= (value << shift) & mask;
+	}
 
-	/* Save the new value with the cleared W1C bits into the cfgspace */
-	cfgspace[reg / 4] = cpu_to_le32(new);
+	if (cfgspace) {
+		/* Save the new value with the cleared W1C bits into the cfgspace */
+		cfgspace[reg / 4] = cpu_to_le32(new);
+	}
 
-	/*
-	 * Clear the W1C bits not specified by the write mask, so that the
-	 * write_op() does not clear them.
-	 */
-	new &= ~(behavior[reg / 4].w1c & ~mask);
+	if (behavior) {
+		/*
+		 * Clear the W1C bits not specified by the write mask, so that the
+		 * write_op() does not clear them.
+		 */
+		new &= ~(behavior[reg / 4].w1c & ~mask);
 
-	/*
-	 * Set the W1C bits specified by the write mask, so that write_op()
-	 * knows about that they are to be cleared.
-	 */
-	new |= (value << shift) & (behavior[reg / 4].w1c & mask);
+		/*
+		 * Set the W1C bits specified by the write mask, so that write_op()
+		 * knows about that they are to be cleared.
+		 */
+		new |= (value << shift) & (behavior[reg / 4].w1c & mask);
+	}
 
 	if (write_op)
 		write_op(bridge, reg, old, new, mask);
diff --git a/drivers/pci/pci-bridge-emul.h b/drivers/pci/pci-bridge-emul.h
index 4953274cac18..6b5f75b2ad02 100644
--- a/drivers/pci/pci-bridge-emul.h
+++ b/drivers/pci/pci-bridge-emul.h
@@ -90,6 +90,14 @@ struct pci_bridge_emul_ops {
 	 */
 	pci_bridge_emul_read_status_t (*read_pcie)(struct pci_bridge_emul *bridge,
 						   int reg, u32 *value);
+
+	/*
+	 * Same as ->read_base(), except it is for reading from the
+	 * PCIe extended capability configuration space.
+	 */
+	pci_bridge_emul_read_status_t (*read_ext)(struct pci_bridge_emul *bridge,
+						  int reg, u32 *value);
+
 	/*
 	 * Called when writing to the regular PCI bridge configuration
 	 * space. old is the current value, new is the new value being
@@ -105,6 +113,13 @@ struct pci_bridge_emul_ops {
 	 */
 	void (*write_pcie)(struct pci_bridge_emul *bridge, int reg,
 			   u32 old, u32 new, u32 mask);
+
+	/*
+	 * Same as ->write_base(), except it is for writing from the
+	 * PCIe extended capability configuration space.
+	 */
+	void (*write_ext)(struct pci_bridge_emul *bridge, int reg,
+			  u32 old, u32 new, u32 mask);
 };
 
 struct pci_bridge_reg_behavior;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 02/11] PCI: pci-bridge-emul: Add support for PCIe extended capabilities
@ 2022-01-12 15:18     ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

From: Russell King <rmk+kernel@armlinux.org.uk>

Add support for PCIe extended capabilities, which we just redirect to the
emulating driver.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
[pali: Fix writing new value with W1C bits]
Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/pci-bridge-emul.c | 77 +++++++++++++++++++++++------------
 drivers/pci/pci-bridge-emul.h | 15 +++++++
 2 files changed, 67 insertions(+), 25 deletions(-)

diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c
index 56b2cb741498..9f4f173f0650 100644
--- a/drivers/pci/pci-bridge-emul.c
+++ b/drivers/pci/pci-bridge-emul.c
@@ -433,10 +433,16 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
 		read_op = bridge->ops->read_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
-	} else {
-		/* Beyond our PCIe space */
+	} else if (reg < PCI_CFG_SPACE_SIZE) {
+		/* Rest of PCI space not implemented */
 		*value = 0;
 		return PCIBIOS_SUCCESSFUL;
+	} else {
+		/* PCIe extended capability space */
+		reg -= PCI_CFG_SPACE_SIZE;
+		read_op = bridge->ops->read_ext;
+		cfgspace = NULL;
+		behavior = NULL;
 	}
 
 	if (read_op)
@@ -444,15 +450,20 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
 	else
 		ret = PCI_BRIDGE_EMUL_NOT_HANDLED;
 
-	if (ret == PCI_BRIDGE_EMUL_NOT_HANDLED)
-		*value = le32_to_cpu(cfgspace[reg / 4]);
+	if (ret == PCI_BRIDGE_EMUL_NOT_HANDLED) {
+		if (cfgspace)
+			*value = le32_to_cpu(cfgspace[reg / 4]);
+		else
+			*value = 0;
+	}
 
 	/*
 	 * Make sure we never return any reserved bit with a value
 	 * different from 0.
 	 */
-	*value &= behavior[reg / 4].ro | behavior[reg / 4].rw |
-		  behavior[reg / 4].w1c;
+	if (behavior)
+		*value &= behavior[reg / 4].ro | behavior[reg / 4].rw |
+			  behavior[reg / 4].w1c;
 
 	if (size == 1)
 		*value = (*value >> (8 * (where & 3))) & 0xff;
@@ -498,8 +509,15 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 		write_op = bridge->ops->write_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
-	} else {
+	} else if (reg < PCI_CFG_SPACE_SIZE) {
+		/* Rest of PCI space not implemented */
 		return PCIBIOS_SUCCESSFUL;
+	} else {
+		/* PCIe extended capability space */
+		reg -= PCI_CFG_SPACE_SIZE;
+		write_op = bridge->ops->write_ext;
+		cfgspace = NULL;
+		behavior = NULL;
 	}
 
 	shift = (where & 0x3) * 8;
@@ -513,29 +531,38 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 	else
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
-	/* Keep all bits, except the RW bits */
-	new = old & (~mask | ~behavior[reg / 4].rw);
+	if (behavior) {
+		/* Keep all bits, except the RW bits */
+		new = old & (~mask | ~behavior[reg / 4].rw);
 
-	/* Update the value of the RW bits */
-	new |= (value << shift) & (behavior[reg / 4].rw & mask);
+		/* Update the value of the RW bits */
+		new |= (value << shift) & (behavior[reg / 4].rw & mask);
 
-	/* Clear the W1C bits */
-	new &= ~((value << shift) & (behavior[reg / 4].w1c & mask));
+		/* Clear the W1C bits */
+		new &= ~((value << shift) & (behavior[reg / 4].w1c & mask));
+	} else {
+		new = old & ~mask;
+		new |= (value << shift) & mask;
+	}
 
-	/* Save the new value with the cleared W1C bits into the cfgspace */
-	cfgspace[reg / 4] = cpu_to_le32(new);
+	if (cfgspace) {
+		/* Save the new value with the cleared W1C bits into the cfgspace */
+		cfgspace[reg / 4] = cpu_to_le32(new);
+	}
 
-	/*
-	 * Clear the W1C bits not specified by the write mask, so that the
-	 * write_op() does not clear them.
-	 */
-	new &= ~(behavior[reg / 4].w1c & ~mask);
+	if (behavior) {
+		/*
+		 * Clear the W1C bits not specified by the write mask, so that the
+		 * write_op() does not clear them.
+		 */
+		new &= ~(behavior[reg / 4].w1c & ~mask);
 
-	/*
-	 * Set the W1C bits specified by the write mask, so that write_op()
-	 * knows about that they are to be cleared.
-	 */
-	new |= (value << shift) & (behavior[reg / 4].w1c & mask);
+		/*
+		 * Set the W1C bits specified by the write mask, so that write_op()
+		 * knows about that they are to be cleared.
+		 */
+		new |= (value << shift) & (behavior[reg / 4].w1c & mask);
+	}
 
 	if (write_op)
 		write_op(bridge, reg, old, new, mask);
diff --git a/drivers/pci/pci-bridge-emul.h b/drivers/pci/pci-bridge-emul.h
index 4953274cac18..6b5f75b2ad02 100644
--- a/drivers/pci/pci-bridge-emul.h
+++ b/drivers/pci/pci-bridge-emul.h
@@ -90,6 +90,14 @@ struct pci_bridge_emul_ops {
 	 */
 	pci_bridge_emul_read_status_t (*read_pcie)(struct pci_bridge_emul *bridge,
 						   int reg, u32 *value);
+
+	/*
+	 * Same as ->read_base(), except it is for reading from the
+	 * PCIe extended capability configuration space.
+	 */
+	pci_bridge_emul_read_status_t (*read_ext)(struct pci_bridge_emul *bridge,
+						  int reg, u32 *value);
+
 	/*
 	 * Called when writing to the regular PCI bridge configuration
 	 * space. old is the current value, new is the new value being
@@ -105,6 +113,13 @@ struct pci_bridge_emul_ops {
 	 */
 	void (*write_pcie)(struct pci_bridge_emul *bridge, int reg,
 			   u32 old, u32 new, u32 mask);
+
+	/*
+	 * Same as ->write_base(), except it is for writing from the
+	 * PCIe extended capability configuration space.
+	 */
+	void (*write_ext)(struct pci_bridge_emul *bridge, int reg,
+			  u32 old, u32 new, u32 mask);
 };
 
 struct pci_bridge_reg_behavior;
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 03/11] PCI: pci-bridge-emul: Add support for PCI Bridge Subsystem Vendor ID capability
  2022-01-12 15:18   ` Pali Rohár
@ 2022-01-12 15:18     ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

This is read-only capability in PCI config space. Put it between base PCI
capability and base PCI Express capability.

Driver just have to specify subsystem_vendor_id and subsystem_id fields in
emulated bridge structure and pci-bridge-emul takes care of correctly
compose PCI Bridge Subsystem Vendor ID capability.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/pci-bridge-emul.c | 69 +++++++++++++++++++++++++----------
 drivers/pci/pci-bridge-emul.h |  2 +
 2 files changed, 51 insertions(+), 20 deletions(-)

diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c
index 9f4f173f0650..c84f423a5893 100644
--- a/drivers/pci/pci-bridge-emul.c
+++ b/drivers/pci/pci-bridge-emul.c
@@ -21,8 +21,11 @@
 #include "pci-bridge-emul.h"
 
 #define PCI_BRIDGE_CONF_END	PCI_STD_HEADER_SIZEOF
+#define PCI_CAP_SSID_SIZEOF	(PCI_SSVID_DEVICE_ID + 2)
+#define PCI_CAP_SSID_START	PCI_BRIDGE_CONF_END
+#define PCI_CAP_SSID_END	(PCI_CAP_SSID_START + PCI_CAP_SSID_SIZEOF)
 #define PCI_CAP_PCIE_SIZEOF	(PCI_EXP_SLTSTA2 + 2)
-#define PCI_CAP_PCIE_START	PCI_BRIDGE_CONF_END
+#define PCI_CAP_PCIE_START	PCI_CAP_SSID_END
 #define PCI_CAP_PCIE_END	(PCI_CAP_PCIE_START + PCI_CAP_PCIE_SIZEOF)
 
 /**
@@ -315,6 +318,25 @@ struct pci_bridge_reg_behavior pcie_cap_regs_behavior[PCI_CAP_PCIE_SIZEOF / 4] =
 	},
 };
 
+static pci_bridge_emul_read_status_t
+pci_bridge_emul_read_ssid(struct pci_bridge_emul *bridge, int reg, u32 *value)
+{
+	switch (reg) {
+	case PCI_CAP_LIST_ID:
+		*value = PCI_CAP_ID_SSVID |
+			(bridge->has_pcie ? (PCI_CAP_PCIE_START << 8) : 0);
+		return PCI_BRIDGE_EMUL_HANDLED;
+
+	case PCI_SSVID_VENDOR_ID:
+		*value = bridge->subsystem_vendor_id |
+			(bridge->subsystem_id << 16);
+		return PCI_BRIDGE_EMUL_HANDLED;
+
+	default:
+		return PCI_BRIDGE_EMUL_NOT_HANDLED;
+	}
+}
+
 /*
  * Initialize a pci_bridge_emul structure to represent a fake PCI
  * bridge configuration space. The caller needs to have initialized
@@ -337,9 +359,17 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
 	if (!bridge->pci_regs_behavior)
 		return -ENOMEM;
 
-	if (bridge->has_pcie) {
+	if (bridge->subsystem_vendor_id)
+		bridge->conf.capabilities_pointer = PCI_CAP_SSID_START;
+	else if (bridge->has_pcie)
 		bridge->conf.capabilities_pointer = PCI_CAP_PCIE_START;
+	else
+		bridge->conf.capabilities_pointer = 0;
+
+	if (bridge->conf.capabilities_pointer)
 		bridge->conf.status |= cpu_to_le16(PCI_STATUS_CAP_LIST);
+
+	if (bridge->has_pcie) {
 		bridge->pcie_conf.cap_id = PCI_CAP_ID_EXP;
 		bridge->pcie_conf.cap |= cpu_to_le16(PCI_EXP_TYPE_ROOT_PORT << 4);
 		bridge->pcie_cap_regs_behavior =
@@ -423,26 +453,28 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
 		read_op = bridge->ops->read_base;
 		cfgspace = (__le32 *) &bridge->conf;
 		behavior = bridge->pci_regs_behavior;
-	} else if (!bridge->has_pcie) {
-		/* PCIe space is not implemented, and no PCI capabilities */
-		*value = 0;
-		return PCIBIOS_SUCCESSFUL;
-	} else if (reg < PCI_CAP_PCIE_END) {
+	} else if (reg >= PCI_CAP_SSID_START && reg < PCI_CAP_SSID_END && bridge->subsystem_vendor_id) {
+		/* Emulated PCI Bridge Subsystem Vendor ID capability */
+		reg -= PCI_CAP_SSID_START;
+		read_op = pci_bridge_emul_read_ssid;
+		cfgspace = NULL;
+		behavior = NULL;
+	} else if (reg >= PCI_CAP_PCIE_START && reg < PCI_CAP_PCIE_END && bridge->has_pcie) {
 		/* Our emulated PCIe capability */
 		reg -= PCI_CAP_PCIE_START;
 		read_op = bridge->ops->read_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
-	} else if (reg < PCI_CFG_SPACE_SIZE) {
-		/* Rest of PCI space not implemented */
-		*value = 0;
-		return PCIBIOS_SUCCESSFUL;
-	} else {
+	} else if (reg >= PCI_CFG_SPACE_SIZE && bridge->has_pcie) {
 		/* PCIe extended capability space */
 		reg -= PCI_CFG_SPACE_SIZE;
 		read_op = bridge->ops->read_ext;
 		cfgspace = NULL;
 		behavior = NULL;
+	} else {
+		/* Not implemented */
+		*value = 0;
+		return PCIBIOS_SUCCESSFUL;
 	}
 
 	if (read_op)
@@ -500,24 +532,21 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 		write_op = bridge->ops->write_base;
 		cfgspace = (__le32 *) &bridge->conf;
 		behavior = bridge->pci_regs_behavior;
-	} else if (!bridge->has_pcie) {
-		/* PCIe space is not implemented, and no PCI capabilities */
-		return PCIBIOS_SUCCESSFUL;
-	} else if (reg < PCI_CAP_PCIE_END) {
+	} else if (reg >= PCI_CAP_PCIE_START && reg < PCI_CAP_PCIE_END && bridge->has_pcie) {
 		/* Our emulated PCIe capability */
 		reg -= PCI_CAP_PCIE_START;
 		write_op = bridge->ops->write_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
-	} else if (reg < PCI_CFG_SPACE_SIZE) {
-		/* Rest of PCI space not implemented */
-		return PCIBIOS_SUCCESSFUL;
-	} else {
+	} else if (reg >= PCI_CFG_SPACE_SIZE && bridge->has_pcie) {
 		/* PCIe extended capability space */
 		reg -= PCI_CFG_SPACE_SIZE;
 		write_op = bridge->ops->write_ext;
 		cfgspace = NULL;
 		behavior = NULL;
+	} else {
+		/* Not implemented */
+		return PCIBIOS_SUCCESSFUL;
 	}
 
 	shift = (where & 0x3) * 8;
diff --git a/drivers/pci/pci-bridge-emul.h b/drivers/pci/pci-bridge-emul.h
index 6b5f75b2ad02..71392b67471d 100644
--- a/drivers/pci/pci-bridge-emul.h
+++ b/drivers/pci/pci-bridge-emul.h
@@ -132,6 +132,8 @@ struct pci_bridge_emul {
 	struct pci_bridge_reg_behavior *pcie_cap_regs_behavior;
 	void *data;
 	bool has_pcie;
+	u16 subsystem_vendor_id;
+	u16 subsystem_id;
 };
 
 enum {
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 03/11] PCI: pci-bridge-emul: Add support for PCI Bridge Subsystem Vendor ID capability
@ 2022-01-12 15:18     ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

This is read-only capability in PCI config space. Put it between base PCI
capability and base PCI Express capability.

Driver just have to specify subsystem_vendor_id and subsystem_id fields in
emulated bridge structure and pci-bridge-emul takes care of correctly
compose PCI Bridge Subsystem Vendor ID capability.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/pci-bridge-emul.c | 69 +++++++++++++++++++++++++----------
 drivers/pci/pci-bridge-emul.h |  2 +
 2 files changed, 51 insertions(+), 20 deletions(-)

diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c
index 9f4f173f0650..c84f423a5893 100644
--- a/drivers/pci/pci-bridge-emul.c
+++ b/drivers/pci/pci-bridge-emul.c
@@ -21,8 +21,11 @@
 #include "pci-bridge-emul.h"
 
 #define PCI_BRIDGE_CONF_END	PCI_STD_HEADER_SIZEOF
+#define PCI_CAP_SSID_SIZEOF	(PCI_SSVID_DEVICE_ID + 2)
+#define PCI_CAP_SSID_START	PCI_BRIDGE_CONF_END
+#define PCI_CAP_SSID_END	(PCI_CAP_SSID_START + PCI_CAP_SSID_SIZEOF)
 #define PCI_CAP_PCIE_SIZEOF	(PCI_EXP_SLTSTA2 + 2)
-#define PCI_CAP_PCIE_START	PCI_BRIDGE_CONF_END
+#define PCI_CAP_PCIE_START	PCI_CAP_SSID_END
 #define PCI_CAP_PCIE_END	(PCI_CAP_PCIE_START + PCI_CAP_PCIE_SIZEOF)
 
 /**
@@ -315,6 +318,25 @@ struct pci_bridge_reg_behavior pcie_cap_regs_behavior[PCI_CAP_PCIE_SIZEOF / 4] =
 	},
 };
 
+static pci_bridge_emul_read_status_t
+pci_bridge_emul_read_ssid(struct pci_bridge_emul *bridge, int reg, u32 *value)
+{
+	switch (reg) {
+	case PCI_CAP_LIST_ID:
+		*value = PCI_CAP_ID_SSVID |
+			(bridge->has_pcie ? (PCI_CAP_PCIE_START << 8) : 0);
+		return PCI_BRIDGE_EMUL_HANDLED;
+
+	case PCI_SSVID_VENDOR_ID:
+		*value = bridge->subsystem_vendor_id |
+			(bridge->subsystem_id << 16);
+		return PCI_BRIDGE_EMUL_HANDLED;
+
+	default:
+		return PCI_BRIDGE_EMUL_NOT_HANDLED;
+	}
+}
+
 /*
  * Initialize a pci_bridge_emul structure to represent a fake PCI
  * bridge configuration space. The caller needs to have initialized
@@ -337,9 +359,17 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
 	if (!bridge->pci_regs_behavior)
 		return -ENOMEM;
 
-	if (bridge->has_pcie) {
+	if (bridge->subsystem_vendor_id)
+		bridge->conf.capabilities_pointer = PCI_CAP_SSID_START;
+	else if (bridge->has_pcie)
 		bridge->conf.capabilities_pointer = PCI_CAP_PCIE_START;
+	else
+		bridge->conf.capabilities_pointer = 0;
+
+	if (bridge->conf.capabilities_pointer)
 		bridge->conf.status |= cpu_to_le16(PCI_STATUS_CAP_LIST);
+
+	if (bridge->has_pcie) {
 		bridge->pcie_conf.cap_id = PCI_CAP_ID_EXP;
 		bridge->pcie_conf.cap |= cpu_to_le16(PCI_EXP_TYPE_ROOT_PORT << 4);
 		bridge->pcie_cap_regs_behavior =
@@ -423,26 +453,28 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
 		read_op = bridge->ops->read_base;
 		cfgspace = (__le32 *) &bridge->conf;
 		behavior = bridge->pci_regs_behavior;
-	} else if (!bridge->has_pcie) {
-		/* PCIe space is not implemented, and no PCI capabilities */
-		*value = 0;
-		return PCIBIOS_SUCCESSFUL;
-	} else if (reg < PCI_CAP_PCIE_END) {
+	} else if (reg >= PCI_CAP_SSID_START && reg < PCI_CAP_SSID_END && bridge->subsystem_vendor_id) {
+		/* Emulated PCI Bridge Subsystem Vendor ID capability */
+		reg -= PCI_CAP_SSID_START;
+		read_op = pci_bridge_emul_read_ssid;
+		cfgspace = NULL;
+		behavior = NULL;
+	} else if (reg >= PCI_CAP_PCIE_START && reg < PCI_CAP_PCIE_END && bridge->has_pcie) {
 		/* Our emulated PCIe capability */
 		reg -= PCI_CAP_PCIE_START;
 		read_op = bridge->ops->read_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
-	} else if (reg < PCI_CFG_SPACE_SIZE) {
-		/* Rest of PCI space not implemented */
-		*value = 0;
-		return PCIBIOS_SUCCESSFUL;
-	} else {
+	} else if (reg >= PCI_CFG_SPACE_SIZE && bridge->has_pcie) {
 		/* PCIe extended capability space */
 		reg -= PCI_CFG_SPACE_SIZE;
 		read_op = bridge->ops->read_ext;
 		cfgspace = NULL;
 		behavior = NULL;
+	} else {
+		/* Not implemented */
+		*value = 0;
+		return PCIBIOS_SUCCESSFUL;
 	}
 
 	if (read_op)
@@ -500,24 +532,21 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
 		write_op = bridge->ops->write_base;
 		cfgspace = (__le32 *) &bridge->conf;
 		behavior = bridge->pci_regs_behavior;
-	} else if (!bridge->has_pcie) {
-		/* PCIe space is not implemented, and no PCI capabilities */
-		return PCIBIOS_SUCCESSFUL;
-	} else if (reg < PCI_CAP_PCIE_END) {
+	} else if (reg >= PCI_CAP_PCIE_START && reg < PCI_CAP_PCIE_END && bridge->has_pcie) {
 		/* Our emulated PCIe capability */
 		reg -= PCI_CAP_PCIE_START;
 		write_op = bridge->ops->write_pcie;
 		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
-	} else if (reg < PCI_CFG_SPACE_SIZE) {
-		/* Rest of PCI space not implemented */
-		return PCIBIOS_SUCCESSFUL;
-	} else {
+	} else if (reg >= PCI_CFG_SPACE_SIZE && bridge->has_pcie) {
 		/* PCIe extended capability space */
 		reg -= PCI_CFG_SPACE_SIZE;
 		write_op = bridge->ops->write_ext;
 		cfgspace = NULL;
 		behavior = NULL;
+	} else {
+		/* Not implemented */
+		return PCIBIOS_SUCCESSFUL;
 	}
 
 	shift = (where & 0x3) * 8;
diff --git a/drivers/pci/pci-bridge-emul.h b/drivers/pci/pci-bridge-emul.h
index 6b5f75b2ad02..71392b67471d 100644
--- a/drivers/pci/pci-bridge-emul.h
+++ b/drivers/pci/pci-bridge-emul.h
@@ -132,6 +132,8 @@ struct pci_bridge_emul {
 	struct pci_bridge_reg_behavior *pcie_cap_regs_behavior;
 	void *data;
 	bool has_pcie;
+	u16 subsystem_vendor_id;
+	u16 subsystem_id;
 };
 
 enum {
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 04/11] dt-bindings: PCI: mvebu: Add num-lanes property
  2022-01-12 15:18   ` Pali Rohár
@ 2022-01-12 15:18     ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

Controller driver needs to correctly configure PCIe link if it contains 1
or 4 SerDes PCIe lanes. Therefore add a new 'num-lanes' DT property for
mvebu PCIe controller. Property 'num-lanes' seems to be de-facto standard
way how number of lanes is specified in other PCIe controllers.

Signed-off-by: Pali Rohár <pali@kernel.org>
Acked-by: Rob Herring <robh@kernel.org>
---
 Documentation/devicetree/bindings/pci/mvebu-pci.txt | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/mvebu-pci.txt b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
index 6173af6885f8..24225852bce0 100644
--- a/Documentation/devicetree/bindings/pci/mvebu-pci.txt
+++ b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
@@ -77,6 +77,7 @@ and the following optional properties:
 - marvell,pcie-lane: the physical PCIe lane number, for ports having
   multiple lanes. If this property is not found, we assume that the
   value is 0.
+- num-lanes: number of SerDes PCIe lanes for this link (1 or 4)
 - reset-gpios: optional GPIO to PERST#
 - reset-delay-us: delay in us to wait after reset de-assertion, if not
   specified will default to 100ms, as required by the PCIe specification.
@@ -141,6 +142,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 58>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <0>;
+		num-lanes = <1>;
 		/* low-active PERST# reset on GPIO 25 */
 		reset-gpios = <&gpio0 25 1>;
 		/* wait 20ms for device settle after reset deassertion */
@@ -161,6 +163,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 59>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <1>;
+		num-lanes = <1>;
 		clocks = <&gateclk 6>;
 	};
 
@@ -177,6 +180,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 60>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <2>;
+		num-lanes = <1>;
 		clocks = <&gateclk 7>;
 	};
 
@@ -193,6 +197,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 61>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <3>;
+		num-lanes = <1>;
 		clocks = <&gateclk 8>;
 	};
 
@@ -209,6 +214,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 62>;
 		marvell,pcie-port = <1>;
 		marvell,pcie-lane = <0>;
+		num-lanes = <1>;
 		clocks = <&gateclk 9>;
 	};
 
@@ -225,6 +231,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 63>;
 		marvell,pcie-port = <1>;
 		marvell,pcie-lane = <1>;
+		num-lanes = <1>;
 		clocks = <&gateclk 10>;
 	};
 
@@ -241,6 +248,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 64>;
 		marvell,pcie-port = <1>;
 		marvell,pcie-lane = <2>;
+		num-lanes = <1>;
 		clocks = <&gateclk 11>;
 	};
 
@@ -257,6 +265,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 65>;
 		marvell,pcie-port = <1>;
 		marvell,pcie-lane = <3>;
+		num-lanes = <1>;
 		clocks = <&gateclk 12>;
 	};
 
@@ -273,6 +282,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 99>;
 		marvell,pcie-port = <2>;
 		marvell,pcie-lane = <0>;
+		num-lanes = <1>;
 		clocks = <&gateclk 26>;
 	};
 
@@ -289,6 +299,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 103>;
 		marvell,pcie-port = <3>;
 		marvell,pcie-lane = <0>;
+		num-lanes = <1>;
 		clocks = <&gateclk 27>;
 	};
 };
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 04/11] dt-bindings: PCI: mvebu: Add num-lanes property
@ 2022-01-12 15:18     ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

Controller driver needs to correctly configure PCIe link if it contains 1
or 4 SerDes PCIe lanes. Therefore add a new 'num-lanes' DT property for
mvebu PCIe controller. Property 'num-lanes' seems to be de-facto standard
way how number of lanes is specified in other PCIe controllers.

Signed-off-by: Pali Rohár <pali@kernel.org>
Acked-by: Rob Herring <robh@kernel.org>
---
 Documentation/devicetree/bindings/pci/mvebu-pci.txt | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/mvebu-pci.txt b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
index 6173af6885f8..24225852bce0 100644
--- a/Documentation/devicetree/bindings/pci/mvebu-pci.txt
+++ b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
@@ -77,6 +77,7 @@ and the following optional properties:
 - marvell,pcie-lane: the physical PCIe lane number, for ports having
   multiple lanes. If this property is not found, we assume that the
   value is 0.
+- num-lanes: number of SerDes PCIe lanes for this link (1 or 4)
 - reset-gpios: optional GPIO to PERST#
 - reset-delay-us: delay in us to wait after reset de-assertion, if not
   specified will default to 100ms, as required by the PCIe specification.
@@ -141,6 +142,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 58>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <0>;
+		num-lanes = <1>;
 		/* low-active PERST# reset on GPIO 25 */
 		reset-gpios = <&gpio0 25 1>;
 		/* wait 20ms for device settle after reset deassertion */
@@ -161,6 +163,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 59>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <1>;
+		num-lanes = <1>;
 		clocks = <&gateclk 6>;
 	};
 
@@ -177,6 +180,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 60>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <2>;
+		num-lanes = <1>;
 		clocks = <&gateclk 7>;
 	};
 
@@ -193,6 +197,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 61>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <3>;
+		num-lanes = <1>;
 		clocks = <&gateclk 8>;
 	};
 
@@ -209,6 +214,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 62>;
 		marvell,pcie-port = <1>;
 		marvell,pcie-lane = <0>;
+		num-lanes = <1>;
 		clocks = <&gateclk 9>;
 	};
 
@@ -225,6 +231,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 63>;
 		marvell,pcie-port = <1>;
 		marvell,pcie-lane = <1>;
+		num-lanes = <1>;
 		clocks = <&gateclk 10>;
 	};
 
@@ -241,6 +248,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 64>;
 		marvell,pcie-port = <1>;
 		marvell,pcie-lane = <2>;
+		num-lanes = <1>;
 		clocks = <&gateclk 11>;
 	};
 
@@ -257,6 +265,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 65>;
 		marvell,pcie-port = <1>;
 		marvell,pcie-lane = <3>;
+		num-lanes = <1>;
 		clocks = <&gateclk 12>;
 	};
 
@@ -273,6 +282,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 99>;
 		marvell,pcie-port = <2>;
 		marvell,pcie-lane = <0>;
+		num-lanes = <1>;
 		clocks = <&gateclk 26>;
 	};
 
@@ -289,6 +299,7 @@ pcie-controller {
 		interrupt-map = <0 0 0 0 &mpic 103>;
 		marvell,pcie-port = <3>;
 		marvell,pcie-lane = <0>;
+		num-lanes = <1>;
 		clocks = <&gateclk 27>;
 	};
 };
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 05/11] PCI: mvebu: Correctly configure x1/x4 mode
  2022-01-12 15:18   ` Pali Rohár
@ 2022-01-12 15:18     ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

If x1/x4 mode is not set correctly then link with endpoint card is not
established.

Use DTS property 'num-lanes' to deteriminate x1/x4 mode.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index a075ba26cff1..0f2ec0a17874 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -93,6 +93,7 @@ struct mvebu_pcie_port {
 	void __iomem *base;
 	u32 port;
 	u32 lane;
+	bool is_x4;
 	int devfn;
 	unsigned int mem_target;
 	unsigned int mem_attr;
@@ -233,13 +234,25 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
 
 static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 {
-	u32 ctrl, cmd, dev_rev, mask;
+	u32 ctrl, lnkcap, cmd, dev_rev, mask;
 
 	/* Setup PCIe controller to Root Complex mode. */
 	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
 	ctrl |= PCIE_CTRL_RC_MODE;
 	mvebu_writel(port, ctrl, PCIE_CTRL_OFF);
 
+	/*
+	 * Set Maximum Link Width to X1 or X4 in Root Port's PCIe Link
+	 * Capability register. This register is defined by PCIe specification
+	 * as read-only but this mvebu controller has it as read-write and must
+	 * be set to number of SerDes PCIe lanes (1 or 4). If this register is
+	 * not set correctly then link with endpoint card is not established.
+	 */
+	lnkcap = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
+	lnkcap &= ~PCI_EXP_LNKCAP_MLW;
+	lnkcap |= (port->is_x4 ? 4 : 1) << 4;
+	mvebu_writel(port, lnkcap, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
+
 	/* Disable Root Bridge I/O space, memory space and bus mastering. */
 	cmd = mvebu_readl(port, PCIE_CMD_OFF);
 	cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
@@ -986,6 +999,7 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
 	struct device *dev = &pcie->pdev->dev;
 	enum of_gpio_flags flags;
 	int reset_gpio, ret;
+	u32 num_lanes;
 
 	port->pcie = pcie;
 
@@ -998,6 +1012,9 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
 	if (of_property_read_u32(child, "marvell,pcie-lane", &port->lane))
 		port->lane = 0;
 
+	if (!of_property_read_u32(child, "num-lanes", &num_lanes) && num_lanes == 4)
+		port->is_x4 = true;
+
 	port->name = devm_kasprintf(dev, GFP_KERNEL, "pcie%d.%d", port->port,
 				    port->lane);
 	if (!port->name) {
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 05/11] PCI: mvebu: Correctly configure x1/x4 mode
@ 2022-01-12 15:18     ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

If x1/x4 mode is not set correctly then link with endpoint card is not
established.

Use DTS property 'num-lanes' to deteriminate x1/x4 mode.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index a075ba26cff1..0f2ec0a17874 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -93,6 +93,7 @@ struct mvebu_pcie_port {
 	void __iomem *base;
 	u32 port;
 	u32 lane;
+	bool is_x4;
 	int devfn;
 	unsigned int mem_target;
 	unsigned int mem_attr;
@@ -233,13 +234,25 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
 
 static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 {
-	u32 ctrl, cmd, dev_rev, mask;
+	u32 ctrl, lnkcap, cmd, dev_rev, mask;
 
 	/* Setup PCIe controller to Root Complex mode. */
 	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
 	ctrl |= PCIE_CTRL_RC_MODE;
 	mvebu_writel(port, ctrl, PCIE_CTRL_OFF);
 
+	/*
+	 * Set Maximum Link Width to X1 or X4 in Root Port's PCIe Link
+	 * Capability register. This register is defined by PCIe specification
+	 * as read-only but this mvebu controller has it as read-write and must
+	 * be set to number of SerDes PCIe lanes (1 or 4). If this register is
+	 * not set correctly then link with endpoint card is not established.
+	 */
+	lnkcap = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
+	lnkcap &= ~PCI_EXP_LNKCAP_MLW;
+	lnkcap |= (port->is_x4 ? 4 : 1) << 4;
+	mvebu_writel(port, lnkcap, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
+
 	/* Disable Root Bridge I/O space, memory space and bus mastering. */
 	cmd = mvebu_readl(port, PCIE_CMD_OFF);
 	cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
@@ -986,6 +999,7 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
 	struct device *dev = &pcie->pdev->dev;
 	enum of_gpio_flags flags;
 	int reset_gpio, ret;
+	u32 num_lanes;
 
 	port->pcie = pcie;
 
@@ -998,6 +1012,9 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
 	if (of_property_read_u32(child, "marvell,pcie-lane", &port->lane))
 		port->lane = 0;
 
+	if (!of_property_read_u32(child, "num-lanes", &num_lanes) && num_lanes == 4)
+		port->is_x4 = true;
+
 	port->name = devm_kasprintf(dev, GFP_KERNEL, "pcie%d.%d", port->port,
 				    port->lane);
 	if (!port->name) {
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 06/11] PCI: mvebu: Add support for PCI Bridge Subsystem Vendor ID on emulated bridge
  2022-01-12 15:18   ` Pali Rohár
@ 2022-01-12 15:18     ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

Register with Subsystem Device/Vendor ID is at offset 0x2c. Export is via
emulated bridge.

After this change Subsystem ID is visible in lspci output at line:

  Capabilities: [40] Subsystem

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 0f2ec0a17874..811af9e6ede5 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -32,6 +32,7 @@
 #define PCIE_DEV_REV_OFF	0x0008
 #define PCIE_BAR_LO_OFF(n)	(0x0010 + ((n) << 3))
 #define PCIE_BAR_HI_OFF(n)	(0x0014 + ((n) << 3))
+#define PCIE_SSDEV_ID_OFF	0x002c
 #define PCIE_CAP_PCIEXP		0x0060
 #define PCIE_HEADER_LOG_4_OFF	0x0128
 #define PCIE_BAR_CTRL_OFF(n)	(0x1804 + (((n) - 1) * 4))
@@ -731,6 +732,7 @@ static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port)
 	struct pci_bridge_emul *bridge = &port->bridge;
 	u32 dev_id = mvebu_readl(port, PCIE_DEV_ID_OFF);
 	u32 dev_rev = mvebu_readl(port, PCIE_DEV_REV_OFF);
+	u32 ssdev_id = mvebu_readl(port, PCIE_SSDEV_ID_OFF);
 	u32 pcie_cap = mvebu_readl(port, PCIE_CAP_PCIEXP);
 	u8 pcie_cap_ver = ((pcie_cap >> 16) & PCI_EXP_FLAGS_VERS);
 
@@ -752,6 +754,8 @@ static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port)
 	 */
 	bridge->pcie_conf.cap = cpu_to_le16(pcie_cap_ver);
 
+	bridge->subsystem_vendor_id = ssdev_id & 0xffff;
+	bridge->subsystem_id = ssdev_id >> 16;
 	bridge->has_pcie = true;
 	bridge->data = port;
 	bridge->ops = &mvebu_pci_bridge_emul_ops;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 06/11] PCI: mvebu: Add support for PCI Bridge Subsystem Vendor ID on emulated bridge
@ 2022-01-12 15:18     ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

Register with Subsystem Device/Vendor ID is at offset 0x2c. Export is via
emulated bridge.

After this change Subsystem ID is visible in lspci output at line:

  Capabilities: [40] Subsystem

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 0f2ec0a17874..811af9e6ede5 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -32,6 +32,7 @@
 #define PCIE_DEV_REV_OFF	0x0008
 #define PCIE_BAR_LO_OFF(n)	(0x0010 + ((n) << 3))
 #define PCIE_BAR_HI_OFF(n)	(0x0014 + ((n) << 3))
+#define PCIE_SSDEV_ID_OFF	0x002c
 #define PCIE_CAP_PCIEXP		0x0060
 #define PCIE_HEADER_LOG_4_OFF	0x0128
 #define PCIE_BAR_CTRL_OFF(n)	(0x1804 + (((n) - 1) * 4))
@@ -731,6 +732,7 @@ static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port)
 	struct pci_bridge_emul *bridge = &port->bridge;
 	u32 dev_id = mvebu_readl(port, PCIE_DEV_ID_OFF);
 	u32 dev_rev = mvebu_readl(port, PCIE_DEV_REV_OFF);
+	u32 ssdev_id = mvebu_readl(port, PCIE_SSDEV_ID_OFF);
 	u32 pcie_cap = mvebu_readl(port, PCIE_CAP_PCIEXP);
 	u8 pcie_cap_ver = ((pcie_cap >> 16) & PCI_EXP_FLAGS_VERS);
 
@@ -752,6 +754,8 @@ static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port)
 	 */
 	bridge->pcie_conf.cap = cpu_to_le16(pcie_cap_ver);
 
+	bridge->subsystem_vendor_id = ssdev_id & 0xffff;
+	bridge->subsystem_id = ssdev_id >> 16;
 	bridge->has_pcie = true;
 	bridge->data = port;
 	bridge->ops = &mvebu_pci_bridge_emul_ops;
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 07/11] PCI: mvebu: Add support for Advanced Error Reporting registers on emulated bridge
  2022-01-12 15:18   ` Pali Rohár
@ 2022-01-12 15:18     ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

AER registers start at mvebu offset 0x0100. Registers PCI_ERR_ROOT_COMMAND,
PCI_ERR_ROOT_STATUS and PCI_ERR_ROOT_ERR_SRC are not supported on pre-XP
hardware and returns zeros.

Note that AER interrupt is not supported yet as mvebu emulated bridge does
not implement interrupts support at all yet.

Also remove custom macro PCIE_HEADER_LOG_4_OFF as it is unused and
correctly this register should be referenced via standard macros with
offset, e.g. as: PCIE_CAP_PCIERR_OFF + PCI_ERR_HEADER_LOG + 4.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 67 +++++++++++++++++++++++++++++-
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 811af9e6ede5..9ea2f6a7c2b0 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -34,7 +34,7 @@
 #define PCIE_BAR_HI_OFF(n)	(0x0014 + ((n) << 3))
 #define PCIE_SSDEV_ID_OFF	0x002c
 #define PCIE_CAP_PCIEXP		0x0060
-#define PCIE_HEADER_LOG_4_OFF	0x0128
+#define PCIE_CAP_PCIERR_OFF	0x0100
 #define PCIE_BAR_CTRL_OFF(n)	(0x1804 + (((n) - 1) * 4))
 #define PCIE_WIN04_CTRL_OFF(n)	(0x1820 + ((n) << 4))
 #define PCIE_WIN04_BASE_OFF(n)	(0x1824 + ((n) << 4))
@@ -603,6 +603,37 @@ mvebu_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
 	return PCI_BRIDGE_EMUL_HANDLED;
 }
 
+static pci_bridge_emul_read_status_t
+mvebu_pci_bridge_emul_ext_conf_read(struct pci_bridge_emul *bridge,
+				    int reg, u32 *value)
+{
+	struct mvebu_pcie_port *port = bridge->data;
+
+	switch (reg) {
+	case 0:
+	case PCI_ERR_UNCOR_STATUS:
+	case PCI_ERR_UNCOR_MASK:
+	case PCI_ERR_UNCOR_SEVER:
+	case PCI_ERR_COR_STATUS:
+	case PCI_ERR_COR_MASK:
+	case PCI_ERR_CAP:
+	case PCI_ERR_HEADER_LOG+0:
+	case PCI_ERR_HEADER_LOG+4:
+	case PCI_ERR_HEADER_LOG+8:
+	case PCI_ERR_HEADER_LOG+12:
+	case PCI_ERR_ROOT_COMMAND:
+	case PCI_ERR_ROOT_STATUS:
+	case PCI_ERR_ROOT_ERR_SRC:
+		*value = mvebu_readl(port, PCIE_CAP_PCIERR_OFF + reg);
+		break;
+
+	default:
+		return PCI_BRIDGE_EMUL_NOT_HANDLED;
+	}
+
+	return PCI_BRIDGE_EMUL_HANDLED;
+}
+
 static void
 mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
 				      int reg, u32 old, u32 new, u32 mask)
@@ -715,11 +746,45 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
 	}
 }
 
+static void
+mvebu_pci_bridge_emul_ext_conf_write(struct pci_bridge_emul *bridge,
+				     int reg, u32 old, u32 new, u32 mask)
+{
+	struct mvebu_pcie_port *port = bridge->data;
+
+	switch (reg) {
+	/* These are W1C registers, so clear other bits */
+	case PCI_ERR_UNCOR_STATUS:
+	case PCI_ERR_COR_STATUS:
+	case PCI_ERR_ROOT_STATUS:
+		new &= mask;
+		fallthrough;
+
+	case PCI_ERR_UNCOR_MASK:
+	case PCI_ERR_UNCOR_SEVER:
+	case PCI_ERR_COR_MASK:
+	case PCI_ERR_CAP:
+	case PCI_ERR_HEADER_LOG+0:
+	case PCI_ERR_HEADER_LOG+4:
+	case PCI_ERR_HEADER_LOG+8:
+	case PCI_ERR_HEADER_LOG+12:
+	case PCI_ERR_ROOT_COMMAND:
+	case PCI_ERR_ROOT_ERR_SRC:
+		mvebu_writel(port, new, PCIE_CAP_PCIERR_OFF + reg);
+		break;
+
+	default:
+		break;
+	}
+}
+
 static const struct pci_bridge_emul_ops mvebu_pci_bridge_emul_ops = {
 	.read_base = mvebu_pci_bridge_emul_base_conf_read,
 	.write_base = mvebu_pci_bridge_emul_base_conf_write,
 	.read_pcie = mvebu_pci_bridge_emul_pcie_conf_read,
 	.write_pcie = mvebu_pci_bridge_emul_pcie_conf_write,
+	.read_ext = mvebu_pci_bridge_emul_ext_conf_read,
+	.write_ext = mvebu_pci_bridge_emul_ext_conf_write,
 };
 
 /*
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 07/11] PCI: mvebu: Add support for Advanced Error Reporting registers on emulated bridge
@ 2022-01-12 15:18     ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

AER registers start at mvebu offset 0x0100. Registers PCI_ERR_ROOT_COMMAND,
PCI_ERR_ROOT_STATUS and PCI_ERR_ROOT_ERR_SRC are not supported on pre-XP
hardware and returns zeros.

Note that AER interrupt is not supported yet as mvebu emulated bridge does
not implement interrupts support at all yet.

Also remove custom macro PCIE_HEADER_LOG_4_OFF as it is unused and
correctly this register should be referenced via standard macros with
offset, e.g. as: PCIE_CAP_PCIERR_OFF + PCI_ERR_HEADER_LOG + 4.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 67 +++++++++++++++++++++++++++++-
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 811af9e6ede5..9ea2f6a7c2b0 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -34,7 +34,7 @@
 #define PCIE_BAR_HI_OFF(n)	(0x0014 + ((n) << 3))
 #define PCIE_SSDEV_ID_OFF	0x002c
 #define PCIE_CAP_PCIEXP		0x0060
-#define PCIE_HEADER_LOG_4_OFF	0x0128
+#define PCIE_CAP_PCIERR_OFF	0x0100
 #define PCIE_BAR_CTRL_OFF(n)	(0x1804 + (((n) - 1) * 4))
 #define PCIE_WIN04_CTRL_OFF(n)	(0x1820 + ((n) << 4))
 #define PCIE_WIN04_BASE_OFF(n)	(0x1824 + ((n) << 4))
@@ -603,6 +603,37 @@ mvebu_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
 	return PCI_BRIDGE_EMUL_HANDLED;
 }
 
+static pci_bridge_emul_read_status_t
+mvebu_pci_bridge_emul_ext_conf_read(struct pci_bridge_emul *bridge,
+				    int reg, u32 *value)
+{
+	struct mvebu_pcie_port *port = bridge->data;
+
+	switch (reg) {
+	case 0:
+	case PCI_ERR_UNCOR_STATUS:
+	case PCI_ERR_UNCOR_MASK:
+	case PCI_ERR_UNCOR_SEVER:
+	case PCI_ERR_COR_STATUS:
+	case PCI_ERR_COR_MASK:
+	case PCI_ERR_CAP:
+	case PCI_ERR_HEADER_LOG+0:
+	case PCI_ERR_HEADER_LOG+4:
+	case PCI_ERR_HEADER_LOG+8:
+	case PCI_ERR_HEADER_LOG+12:
+	case PCI_ERR_ROOT_COMMAND:
+	case PCI_ERR_ROOT_STATUS:
+	case PCI_ERR_ROOT_ERR_SRC:
+		*value = mvebu_readl(port, PCIE_CAP_PCIERR_OFF + reg);
+		break;
+
+	default:
+		return PCI_BRIDGE_EMUL_NOT_HANDLED;
+	}
+
+	return PCI_BRIDGE_EMUL_HANDLED;
+}
+
 static void
 mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
 				      int reg, u32 old, u32 new, u32 mask)
@@ -715,11 +746,45 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
 	}
 }
 
+static void
+mvebu_pci_bridge_emul_ext_conf_write(struct pci_bridge_emul *bridge,
+				     int reg, u32 old, u32 new, u32 mask)
+{
+	struct mvebu_pcie_port *port = bridge->data;
+
+	switch (reg) {
+	/* These are W1C registers, so clear other bits */
+	case PCI_ERR_UNCOR_STATUS:
+	case PCI_ERR_COR_STATUS:
+	case PCI_ERR_ROOT_STATUS:
+		new &= mask;
+		fallthrough;
+
+	case PCI_ERR_UNCOR_MASK:
+	case PCI_ERR_UNCOR_SEVER:
+	case PCI_ERR_COR_MASK:
+	case PCI_ERR_CAP:
+	case PCI_ERR_HEADER_LOG+0:
+	case PCI_ERR_HEADER_LOG+4:
+	case PCI_ERR_HEADER_LOG+8:
+	case PCI_ERR_HEADER_LOG+12:
+	case PCI_ERR_ROOT_COMMAND:
+	case PCI_ERR_ROOT_ERR_SRC:
+		mvebu_writel(port, new, PCIE_CAP_PCIERR_OFF + reg);
+		break;
+
+	default:
+		break;
+	}
+}
+
 static const struct pci_bridge_emul_ops mvebu_pci_bridge_emul_ops = {
 	.read_base = mvebu_pci_bridge_emul_base_conf_read,
 	.write_base = mvebu_pci_bridge_emul_base_conf_write,
 	.read_pcie = mvebu_pci_bridge_emul_pcie_conf_read,
 	.write_pcie = mvebu_pci_bridge_emul_pcie_conf_write,
+	.read_ext = mvebu_pci_bridge_emul_ext_conf_read,
+	.write_ext = mvebu_pci_bridge_emul_ext_conf_write,
 };
 
 /*
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 08/11] PCI: mvebu: Use child_ops API
  2022-01-12 15:18   ` Pali Rohár
@ 2022-01-12 15:18     ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

Split struct pci_ops between ops and child_ops. Member ops is used for
accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
accessing real PCIe cards.

There is no need to mix these two struct pci_ops into one as PCI core code
already provides separate callbacks via bridge->ops and bridge->child_ops.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 82 ++++++++++++++++--------------
 1 file changed, 44 insertions(+), 38 deletions(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 9ea2f6a7c2b0..1e90ab888075 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -294,11 +294,29 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 	mvebu_writel(port, mask, PCIE_MASK_OFF);
 }
 
-static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
-				 struct pci_bus *bus,
-				 u32 devfn, int where, int size, u32 *val)
+static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
+						    struct pci_bus *bus,
+						    int devfn);
+
+static int mvebu_pcie_child_rd_conf(struct pci_bus *bus, u32 devfn, int where,
+				    int size, u32 *val)
 {
-	void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
+	struct mvebu_pcie *pcie = bus->sysdata;
+	struct mvebu_pcie_port *port;
+	void __iomem *conf_data;
+
+	port = mvebu_pcie_find_port(pcie, bus, devfn);
+	if (!port) {
+		*val = 0xffffffff;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	if (!mvebu_pcie_link_up(port)) {
+		*val = 0xffffffff;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	conf_data = port->base + PCIE_CONF_DATA_OFF;
 
 	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
 		     PCIE_CONF_ADDR_OFF);
@@ -321,11 +339,21 @@ static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
-				 struct pci_bus *bus,
-				 u32 devfn, int where, int size, u32 val)
+static int mvebu_pcie_child_wr_conf(struct pci_bus *bus, u32 devfn,
+				    int where, int size, u32 val)
 {
-	void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
+	struct mvebu_pcie *pcie = bus->sysdata;
+	struct mvebu_pcie_port *port;
+	void __iomem *conf_data;
+
+	port = mvebu_pcie_find_port(pcie, bus, devfn);
+	if (!port)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (!mvebu_pcie_link_up(port))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	conf_data = port->base + PCIE_CONF_DATA_OFF;
 
 	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
 		     PCIE_CONF_ADDR_OFF);
@@ -347,6 +375,11 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
 	return PCIBIOS_SUCCESSFUL;
 }
 
+static struct pci_ops mvebu_pcie_child_ops = {
+	.read = mvebu_pcie_child_rd_conf,
+	.write = mvebu_pcie_child_wr_conf,
+};
+
 /*
  * Remove windows, starting from the largest ones to the smallest
  * ones.
@@ -862,25 +895,12 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 {
 	struct mvebu_pcie *pcie = bus->sysdata;
 	struct mvebu_pcie_port *port;
-	int ret;
 
 	port = mvebu_pcie_find_port(pcie, bus, devfn);
 	if (!port)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	/* Access the emulated PCI-to-PCI bridge */
-	if (bus->number == 0)
-		return pci_bridge_emul_conf_write(&port->bridge, where,
-						  size, val);
-
-	if (!mvebu_pcie_link_up(port))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/* Access the real PCIe interface */
-	ret = mvebu_pcie_hw_wr_conf(port, bus, devfn,
-				    where, size, val);
-
-	return ret;
+	return pci_bridge_emul_conf_write(&port->bridge, where, size, val);
 }
 
 /* PCI configuration space read function */
@@ -889,7 +909,6 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 {
 	struct mvebu_pcie *pcie = bus->sysdata;
 	struct mvebu_pcie_port *port;
-	int ret;
 
 	port = mvebu_pcie_find_port(pcie, bus, devfn);
 	if (!port) {
@@ -897,21 +916,7 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 		return PCIBIOS_DEVICE_NOT_FOUND;
 	}
 
-	/* Access the emulated PCI-to-PCI bridge */
-	if (bus->number == 0)
-		return pci_bridge_emul_conf_read(&port->bridge, where,
-						 size, val);
-
-	if (!mvebu_pcie_link_up(port)) {
-		*val = 0xffffffff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-
-	/* Access the real PCIe interface */
-	ret = mvebu_pcie_hw_rd_conf(port, bus, devfn,
-				    where, size, val);
-
-	return ret;
+	return pci_bridge_emul_conf_read(&port->bridge, where, size, val);
 }
 
 static struct pci_ops mvebu_pcie_ops = {
@@ -1421,6 +1426,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 
 	bridge->sysdata = pcie;
 	bridge->ops = &mvebu_pcie_ops;
+	bridge->child_ops = &mvebu_pcie_child_ops;
 	bridge->align_resource = mvebu_pcie_align_resource;
 	bridge->map_irq = mvebu_pcie_map_irq;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 08/11] PCI: mvebu: Use child_ops API
@ 2022-01-12 15:18     ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

Split struct pci_ops between ops and child_ops. Member ops is used for
accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
accessing real PCIe cards.

There is no need to mix these two struct pci_ops into one as PCI core code
already provides separate callbacks via bridge->ops and bridge->child_ops.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 82 ++++++++++++++++--------------
 1 file changed, 44 insertions(+), 38 deletions(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 9ea2f6a7c2b0..1e90ab888075 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -294,11 +294,29 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 	mvebu_writel(port, mask, PCIE_MASK_OFF);
 }
 
-static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
-				 struct pci_bus *bus,
-				 u32 devfn, int where, int size, u32 *val)
+static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
+						    struct pci_bus *bus,
+						    int devfn);
+
+static int mvebu_pcie_child_rd_conf(struct pci_bus *bus, u32 devfn, int where,
+				    int size, u32 *val)
 {
-	void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
+	struct mvebu_pcie *pcie = bus->sysdata;
+	struct mvebu_pcie_port *port;
+	void __iomem *conf_data;
+
+	port = mvebu_pcie_find_port(pcie, bus, devfn);
+	if (!port) {
+		*val = 0xffffffff;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	if (!mvebu_pcie_link_up(port)) {
+		*val = 0xffffffff;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	conf_data = port->base + PCIE_CONF_DATA_OFF;
 
 	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
 		     PCIE_CONF_ADDR_OFF);
@@ -321,11 +339,21 @@ static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
-				 struct pci_bus *bus,
-				 u32 devfn, int where, int size, u32 val)
+static int mvebu_pcie_child_wr_conf(struct pci_bus *bus, u32 devfn,
+				    int where, int size, u32 val)
 {
-	void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
+	struct mvebu_pcie *pcie = bus->sysdata;
+	struct mvebu_pcie_port *port;
+	void __iomem *conf_data;
+
+	port = mvebu_pcie_find_port(pcie, bus, devfn);
+	if (!port)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (!mvebu_pcie_link_up(port))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	conf_data = port->base + PCIE_CONF_DATA_OFF;
 
 	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
 		     PCIE_CONF_ADDR_OFF);
@@ -347,6 +375,11 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
 	return PCIBIOS_SUCCESSFUL;
 }
 
+static struct pci_ops mvebu_pcie_child_ops = {
+	.read = mvebu_pcie_child_rd_conf,
+	.write = mvebu_pcie_child_wr_conf,
+};
+
 /*
  * Remove windows, starting from the largest ones to the smallest
  * ones.
@@ -862,25 +895,12 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 {
 	struct mvebu_pcie *pcie = bus->sysdata;
 	struct mvebu_pcie_port *port;
-	int ret;
 
 	port = mvebu_pcie_find_port(pcie, bus, devfn);
 	if (!port)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	/* Access the emulated PCI-to-PCI bridge */
-	if (bus->number == 0)
-		return pci_bridge_emul_conf_write(&port->bridge, where,
-						  size, val);
-
-	if (!mvebu_pcie_link_up(port))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/* Access the real PCIe interface */
-	ret = mvebu_pcie_hw_wr_conf(port, bus, devfn,
-				    where, size, val);
-
-	return ret;
+	return pci_bridge_emul_conf_write(&port->bridge, where, size, val);
 }
 
 /* PCI configuration space read function */
@@ -889,7 +909,6 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 {
 	struct mvebu_pcie *pcie = bus->sysdata;
 	struct mvebu_pcie_port *port;
-	int ret;
 
 	port = mvebu_pcie_find_port(pcie, bus, devfn);
 	if (!port) {
@@ -897,21 +916,7 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 		return PCIBIOS_DEVICE_NOT_FOUND;
 	}
 
-	/* Access the emulated PCI-to-PCI bridge */
-	if (bus->number == 0)
-		return pci_bridge_emul_conf_read(&port->bridge, where,
-						 size, val);
-
-	if (!mvebu_pcie_link_up(port)) {
-		*val = 0xffffffff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-
-	/* Access the real PCIe interface */
-	ret = mvebu_pcie_hw_rd_conf(port, bus, devfn,
-				    where, size, val);
-
-	return ret;
+	return pci_bridge_emul_conf_read(&port->bridge, where, size, val);
 }
 
 static struct pci_ops mvebu_pcie_ops = {
@@ -1421,6 +1426,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 
 	bridge->sysdata = pcie;
 	bridge->ops = &mvebu_pcie_ops;
+	bridge->child_ops = &mvebu_pcie_child_ops;
 	bridge->align_resource = mvebu_pcie_align_resource;
 	bridge->map_irq = mvebu_pcie_map_irq;
 
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 09/11] dt-bindings: PCI: mvebu: Update information about intx interrupts
  2022-01-12 15:18   ` Pali Rohár
@ 2022-01-12 15:18     ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

Signed-off-by: Pali Rohár <pali@kernel.org>
Acked-by: Rob Herring <robh@kernel.org>
---
 Documentation/devicetree/bindings/pci/mvebu-pci.txt | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/mvebu-pci.txt b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
index 24225852bce0..6d022a9d36ee 100644
--- a/Documentation/devicetree/bindings/pci/mvebu-pci.txt
+++ b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
@@ -81,6 +81,11 @@ and the following optional properties:
 - reset-gpios: optional GPIO to PERST#
 - reset-delay-us: delay in us to wait after reset de-assertion, if not
   specified will default to 100ms, as required by the PCIe specification.
+- interrupt-names: list of interrupt names, supported are:
+   - "intx" - interrupt line triggered by one of the legacy interrupt
+- interrupts or interrupts-extended: List of the interrupt sources which
+  corresponding to the "interrupt-names". If non-empty then also additional
+  'interrupt-controller' subnode must be defined.
 
 Example:
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 09/11] dt-bindings: PCI: mvebu: Update information about intx interrupts
@ 2022-01-12 15:18     ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King
  Cc: linux-pci, linux-kernel, linux-arm-kernel

Signed-off-by: Pali Rohár <pali@kernel.org>
Acked-by: Rob Herring <robh@kernel.org>
---
 Documentation/devicetree/bindings/pci/mvebu-pci.txt | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/mvebu-pci.txt b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
index 24225852bce0..6d022a9d36ee 100644
--- a/Documentation/devicetree/bindings/pci/mvebu-pci.txt
+++ b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
@@ -81,6 +81,11 @@ and the following optional properties:
 - reset-gpios: optional GPIO to PERST#
 - reset-delay-us: delay in us to wait after reset de-assertion, if not
   specified will default to 100ms, as required by the PCIe specification.
+- interrupt-names: list of interrupt names, supported are:
+   - "intx" - interrupt line triggered by one of the legacy interrupt
+- interrupts or interrupts-extended: List of the interrupt sources which
+  corresponding to the "interrupt-names". If non-empty then also additional
+  'interrupt-controller' subnode must be defined.
 
 Example:
 
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-01-12 15:18   ` Pali Rohár
@ 2022-01-12 15:18     ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier
  Cc: linux-pci, linux-kernel, linux-arm-kernel

This adds support for legacy INTx interrupts received from other PCIe
devices and which are reported by a new INTx irq chip.

With this change, kernel can distinguish between INTA, INTB, INTC and INTD
interrupts.

Note that for this support, device tree files has to be properly adjusted
to provide "interrupts" or "interrupts-extended" property with intx
interrupt source, "interrupt-names" property with "intx" string and also
'interrupt-controller' subnode must be defined.

If device tree files do not provide these nodes then driver would work as
before.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
 1 file changed, 177 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 1e90ab888075..dbb6ecb4cb70 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -54,9 +54,10 @@
 	 PCIE_CONF_ADDR_EN)
 #define PCIE_CONF_DATA_OFF	0x18fc
 #define PCIE_INT_CAUSE_OFF	0x1900
+#define PCIE_INT_UNMASK_OFF	0x1910
+#define  PCIE_INT_INTX(i)		BIT(24+i)
 #define  PCIE_INT_PM_PME		BIT(28)
-#define PCIE_MASK_OFF		0x1910
-#define  PCIE_MASK_ENABLE_INTS          0x0f000000
+#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
 #define PCIE_CTRL_OFF		0x1a00
 #define  PCIE_CTRL_X1_MODE		0x0001
 #define  PCIE_CTRL_RC_MODE		BIT(1)
@@ -110,6 +111,9 @@ struct mvebu_pcie_port {
 	struct mvebu_pcie_window iowin;
 	u32 saved_pcie_stat;
 	struct resource regs;
+	struct irq_domain *intx_irq_domain;
+	raw_spinlock_t irq_lock;
+	int intx_irq;
 };
 
 static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
@@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
 
 static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 {
-	u32 ctrl, lnkcap, cmd, dev_rev, mask;
+	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
 
 	/* Setup PCIe controller to Root Complex mode. */
 	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
@@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 	/* Point PCIe unit MBUS decode windows to DRAM space. */
 	mvebu_pcie_setup_wins(port);
 
-	/* Enable interrupt lines A-D. */
-	mask = mvebu_readl(port, PCIE_MASK_OFF);
-	mask |= PCIE_MASK_ENABLE_INTS;
-	mvebu_writel(port, mask, PCIE_MASK_OFF);
+	/* Mask all interrupt sources. */
+	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
+
+	/* Clear all interrupt causes. */
+	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
+
+	if (port->intx_irq <= 0) {
+		/*
+		 * When neither "summary" interrupt, nor "intx" interrupt was
+		 * specified in DT then unmask all legacy INTx interrupts as in
+		 * this case driver does not provide a way for masking and
+		 * unmasking of individual legacy INTx interrupts. In this case
+		 * all interrupts, including legacy INTx are reported via one
+		 * shared GIC source and therefore kernel cannot distinguish
+		 * which individual legacy INTx was triggered. These interrupts
+		 * are shared, so it should not cause any issue. Just
+		 * performance penalty as every PCIe interrupt handler needs to
+		 * be called when some interrupt is triggered.
+		 */
+		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
+			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
+		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	}
 }
 
 static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
@@ -924,6 +948,108 @@ static struct pci_ops mvebu_pcie_ops = {
 	.write = mvebu_pcie_wr_conf,
 };
 
+static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
+{
+	struct mvebu_pcie_port *port = d->domain->host_data;
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+	unsigned long flags;
+	u32 unmask;
+
+	raw_spin_lock_irqsave(&port->irq_lock, flags);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	unmask &= ~PCIE_INT_INTX(hwirq);
+	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
+}
+
+static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
+{
+	struct mvebu_pcie_port *port = d->domain->host_data;
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+	unsigned long flags;
+	u32 unmask;
+
+	raw_spin_lock_irqsave(&port->irq_lock, flags);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	unmask |= PCIE_INT_INTX(hwirq);
+	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
+}
+
+static struct irq_chip intx_irq_chip = {
+	.name = "mvebu-INTx",
+	.irq_mask = mvebu_pcie_intx_irq_mask,
+	.irq_unmask = mvebu_pcie_intx_irq_unmask,
+};
+
+static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
+				   unsigned int virq, irq_hw_number_t hwirq)
+{
+	struct mvebu_pcie_port *port = h->host_data;
+
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, &intx_irq_chip, handle_level_irq);
+	irq_set_chip_data(virq, port);
+
+	return 0;
+}
+
+static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
+	.map = mvebu_pcie_intx_irq_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
+{
+	struct device *dev = &port->pcie->pdev->dev;
+	struct device_node *pcie_intc_node;
+
+	raw_spin_lock_init(&port->irq_lock);
+
+	pcie_intc_node = of_get_next_child(port->dn, NULL);
+	if (!pcie_intc_node) {
+		dev_err(dev, "No PCIe Intc node found for %s\n", port->name);
+		return -ENODEV;
+	}
+
+	port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
+						      &mvebu_pcie_intx_irq_domain_ops,
+						      port);
+	of_node_put(pcie_intc_node);
+	if (!port->intx_irq_domain) {
+		dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void mvebu_pcie_irq_handler(struct irq_desc *desc)
+{
+	struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct device *dev = &port->pcie->pdev->dev;
+	u32 cause, unmask, status;
+	int i;
+
+	chained_irq_enter(chip, desc);
+
+	cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	status = cause & unmask;
+
+	/* Process legacy INTx interrupts */
+	for (i = 0; i < PCI_NUM_INTX; i++) {
+		if (!(status & PCIE_INT_INTX(i)))
+			continue;
+
+		if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL)
+			dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A');
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
 static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	/* Interrupt support on mvebu emulated bridges is not implemented yet */
@@ -1121,6 +1247,21 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
 		port->io_attr = -1;
 	}
 
+	/*
+	 * Old DT bindings do not contain "intx" interrupt
+	 * so do not fail probing driver when interrupt does not exist.
+	 */
+	port->intx_irq = of_irq_get_byname(child, "intx");
+	if (port->intx_irq == -EPROBE_DEFER) {
+		ret = port->intx_irq;
+		goto err;
+	}
+	if (port->intx_irq <= 0) {
+		dev_warn(dev, "%s: legacy INTx interrupts cannot be masked individually, "
+			      "%pOF does not contain intx interrupt\n",
+			 port->name, child);
+	}
+
 	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
 	if (reset_gpio == -EPROBE_DEFER) {
 		ret = reset_gpio;
@@ -1317,6 +1458,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 
 	for (i = 0; i < pcie->nports; i++) {
 		struct mvebu_pcie_port *port = &pcie->ports[i];
+		int irq = port->intx_irq;
 
 		child = port->dn;
 		if (!child)
@@ -1344,6 +1486,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 			continue;
 		}
 
+		if (irq > 0) {
+			ret = mvebu_pcie_init_irq_domain(port);
+			if (ret) {
+				dev_err(dev, "%s: cannot init irq domain\n",
+					port->name);
+				pci_bridge_emul_cleanup(&port->bridge);
+				devm_iounmap(dev, port->base);
+				port->base = NULL;
+				mvebu_pcie_powerdown(port);
+				continue;
+			}
+			irq_set_chained_handler_and_data(irq,
+							 mvebu_pcie_irq_handler,
+							 port);
+		}
+
 		/*
 		 * PCIe topology exported by mvebu hw is quite complicated. In
 		 * reality has something like N fully independent host bridges
@@ -1448,6 +1606,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
 
 	for (i = 0; i < pcie->nports; i++) {
 		struct mvebu_pcie_port *port = &pcie->ports[i];
+		int irq = port->intx_irq;
 
 		if (!port->base)
 			continue;
@@ -1458,7 +1617,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
 		mvebu_writel(port, cmd, PCIE_CMD_OFF);
 
 		/* Mask all interrupt sources. */
-		mvebu_writel(port, 0, PCIE_MASK_OFF);
+		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
+
+		/* Clear all interrupt causes. */
+		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
+
+		if (irq > 0)
+			irq_set_chained_handler_and_data(irq, NULL, NULL);
+
+		/* Remove IRQ domains. */
+		if (port->intx_irq_domain)
+			irq_domain_remove(port->intx_irq_domain);
 
 		/* Free config space for emulated root bridge. */
 		pci_bridge_emul_cleanup(&port->bridge);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-01-12 15:18     ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier
  Cc: linux-pci, linux-kernel, linux-arm-kernel

This adds support for legacy INTx interrupts received from other PCIe
devices and which are reported by a new INTx irq chip.

With this change, kernel can distinguish between INTA, INTB, INTC and INTD
interrupts.

Note that for this support, device tree files has to be properly adjusted
to provide "interrupts" or "interrupts-extended" property with intx
interrupt source, "interrupt-names" property with "intx" string and also
'interrupt-controller' subnode must be defined.

If device tree files do not provide these nodes then driver would work as
before.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
 1 file changed, 177 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 1e90ab888075..dbb6ecb4cb70 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -54,9 +54,10 @@
 	 PCIE_CONF_ADDR_EN)
 #define PCIE_CONF_DATA_OFF	0x18fc
 #define PCIE_INT_CAUSE_OFF	0x1900
+#define PCIE_INT_UNMASK_OFF	0x1910
+#define  PCIE_INT_INTX(i)		BIT(24+i)
 #define  PCIE_INT_PM_PME		BIT(28)
-#define PCIE_MASK_OFF		0x1910
-#define  PCIE_MASK_ENABLE_INTS          0x0f000000
+#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
 #define PCIE_CTRL_OFF		0x1a00
 #define  PCIE_CTRL_X1_MODE		0x0001
 #define  PCIE_CTRL_RC_MODE		BIT(1)
@@ -110,6 +111,9 @@ struct mvebu_pcie_port {
 	struct mvebu_pcie_window iowin;
 	u32 saved_pcie_stat;
 	struct resource regs;
+	struct irq_domain *intx_irq_domain;
+	raw_spinlock_t irq_lock;
+	int intx_irq;
 };
 
 static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
@@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
 
 static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 {
-	u32 ctrl, lnkcap, cmd, dev_rev, mask;
+	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
 
 	/* Setup PCIe controller to Root Complex mode. */
 	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
@@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 	/* Point PCIe unit MBUS decode windows to DRAM space. */
 	mvebu_pcie_setup_wins(port);
 
-	/* Enable interrupt lines A-D. */
-	mask = mvebu_readl(port, PCIE_MASK_OFF);
-	mask |= PCIE_MASK_ENABLE_INTS;
-	mvebu_writel(port, mask, PCIE_MASK_OFF);
+	/* Mask all interrupt sources. */
+	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
+
+	/* Clear all interrupt causes. */
+	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
+
+	if (port->intx_irq <= 0) {
+		/*
+		 * When neither "summary" interrupt, nor "intx" interrupt was
+		 * specified in DT then unmask all legacy INTx interrupts as in
+		 * this case driver does not provide a way for masking and
+		 * unmasking of individual legacy INTx interrupts. In this case
+		 * all interrupts, including legacy INTx are reported via one
+		 * shared GIC source and therefore kernel cannot distinguish
+		 * which individual legacy INTx was triggered. These interrupts
+		 * are shared, so it should not cause any issue. Just
+		 * performance penalty as every PCIe interrupt handler needs to
+		 * be called when some interrupt is triggered.
+		 */
+		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
+			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
+		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	}
 }
 
 static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
@@ -924,6 +948,108 @@ static struct pci_ops mvebu_pcie_ops = {
 	.write = mvebu_pcie_wr_conf,
 };
 
+static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
+{
+	struct mvebu_pcie_port *port = d->domain->host_data;
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+	unsigned long flags;
+	u32 unmask;
+
+	raw_spin_lock_irqsave(&port->irq_lock, flags);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	unmask &= ~PCIE_INT_INTX(hwirq);
+	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
+}
+
+static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
+{
+	struct mvebu_pcie_port *port = d->domain->host_data;
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+	unsigned long flags;
+	u32 unmask;
+
+	raw_spin_lock_irqsave(&port->irq_lock, flags);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	unmask |= PCIE_INT_INTX(hwirq);
+	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
+	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
+}
+
+static struct irq_chip intx_irq_chip = {
+	.name = "mvebu-INTx",
+	.irq_mask = mvebu_pcie_intx_irq_mask,
+	.irq_unmask = mvebu_pcie_intx_irq_unmask,
+};
+
+static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
+				   unsigned int virq, irq_hw_number_t hwirq)
+{
+	struct mvebu_pcie_port *port = h->host_data;
+
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, &intx_irq_chip, handle_level_irq);
+	irq_set_chip_data(virq, port);
+
+	return 0;
+}
+
+static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
+	.map = mvebu_pcie_intx_irq_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
+{
+	struct device *dev = &port->pcie->pdev->dev;
+	struct device_node *pcie_intc_node;
+
+	raw_spin_lock_init(&port->irq_lock);
+
+	pcie_intc_node = of_get_next_child(port->dn, NULL);
+	if (!pcie_intc_node) {
+		dev_err(dev, "No PCIe Intc node found for %s\n", port->name);
+		return -ENODEV;
+	}
+
+	port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
+						      &mvebu_pcie_intx_irq_domain_ops,
+						      port);
+	of_node_put(pcie_intc_node);
+	if (!port->intx_irq_domain) {
+		dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void mvebu_pcie_irq_handler(struct irq_desc *desc)
+{
+	struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct device *dev = &port->pcie->pdev->dev;
+	u32 cause, unmask, status;
+	int i;
+
+	chained_irq_enter(chip, desc);
+
+	cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF);
+	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
+	status = cause & unmask;
+
+	/* Process legacy INTx interrupts */
+	for (i = 0; i < PCI_NUM_INTX; i++) {
+		if (!(status & PCIE_INT_INTX(i)))
+			continue;
+
+		if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL)
+			dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A');
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
 static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	/* Interrupt support on mvebu emulated bridges is not implemented yet */
@@ -1121,6 +1247,21 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
 		port->io_attr = -1;
 	}
 
+	/*
+	 * Old DT bindings do not contain "intx" interrupt
+	 * so do not fail probing driver when interrupt does not exist.
+	 */
+	port->intx_irq = of_irq_get_byname(child, "intx");
+	if (port->intx_irq == -EPROBE_DEFER) {
+		ret = port->intx_irq;
+		goto err;
+	}
+	if (port->intx_irq <= 0) {
+		dev_warn(dev, "%s: legacy INTx interrupts cannot be masked individually, "
+			      "%pOF does not contain intx interrupt\n",
+			 port->name, child);
+	}
+
 	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
 	if (reset_gpio == -EPROBE_DEFER) {
 		ret = reset_gpio;
@@ -1317,6 +1458,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 
 	for (i = 0; i < pcie->nports; i++) {
 		struct mvebu_pcie_port *port = &pcie->ports[i];
+		int irq = port->intx_irq;
 
 		child = port->dn;
 		if (!child)
@@ -1344,6 +1486,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 			continue;
 		}
 
+		if (irq > 0) {
+			ret = mvebu_pcie_init_irq_domain(port);
+			if (ret) {
+				dev_err(dev, "%s: cannot init irq domain\n",
+					port->name);
+				pci_bridge_emul_cleanup(&port->bridge);
+				devm_iounmap(dev, port->base);
+				port->base = NULL;
+				mvebu_pcie_powerdown(port);
+				continue;
+			}
+			irq_set_chained_handler_and_data(irq,
+							 mvebu_pcie_irq_handler,
+							 port);
+		}
+
 		/*
 		 * PCIe topology exported by mvebu hw is quite complicated. In
 		 * reality has something like N fully independent host bridges
@@ -1448,6 +1606,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
 
 	for (i = 0; i < pcie->nports; i++) {
 		struct mvebu_pcie_port *port = &pcie->ports[i];
+		int irq = port->intx_irq;
 
 		if (!port->base)
 			continue;
@@ -1458,7 +1617,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
 		mvebu_writel(port, cmd, PCIE_CMD_OFF);
 
 		/* Mask all interrupt sources. */
-		mvebu_writel(port, 0, PCIE_MASK_OFF);
+		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
+
+		/* Clear all interrupt causes. */
+		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
+
+		if (irq > 0)
+			irq_set_chained_handler_and_data(irq, NULL, NULL);
+
+		/* Remove IRQ domains. */
+		if (port->intx_irq_domain)
+			irq_domain_remove(port->intx_irq_domain);
 
 		/* Free config space for emulated root bridge. */
 		pci_bridge_emul_cleanup(&port->bridge);
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
  2022-01-12 15:18   ` Pali Rohár
@ 2022-01-12 15:18     ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Andrew Lunn, Gregory Clement
  Cc: linux-pci, linux-kernel, linux-arm-kernel, devicetree

With this change legacy INTA, INTB, INTC and INTD interrupts are reported
separately and not mixed into one Linux virq source anymore.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----
 1 file changed, 44 insertions(+), 8 deletions(-)

diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
index f0022d10c715..83392b92dae2 100644
--- a/arch/arm/boot/dts/armada-385.dtsi
+++ b/arch/arm/boot/dts/armada-385.dtsi
@@ -69,16 +69,25 @@
 				reg = <0x0800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
+				interrupt-names = "intx";
+				interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <1>;
 				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
 					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
 				bus-range = <0x00 0xff>;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-map-mask = <0 0 0 7>;
+				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>;
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 8>;
 				status = "disabled";
+				pcie1_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
 			};
 
 			/* x1 port */
@@ -88,16 +97,25 @@
 				reg = <0x1000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
+				interrupt-names = "intx";
+				interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <1>;
 				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
 					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
 				bus-range = <0x00 0xff>;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &pcie2_intc 0>,
+						<0 0 0 2 &pcie2_intc 1>,
+						<0 0 0 3 &pcie2_intc 2>,
+						<0 0 0 4 &pcie2_intc 3>;
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
 				status = "disabled";
+				pcie2_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
 			};
 
 			/* x1 port */
@@ -107,16 +125,25 @@
 				reg = <0x1800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
+				interrupt-names = "intx";
+				interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <1>;
 				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
 					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
 				bus-range = <0x00 0xff>;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &pcie3_intc 0>,
+						<0 0 0 2 &pcie3_intc 1>,
+						<0 0 0 3 &pcie3_intc 2>,
+						<0 0 0 4 &pcie3_intc 3>;
 				marvell,pcie-port = <2>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 6>;
 				status = "disabled";
+				pcie3_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
 			};
 
 			/*
@@ -129,16 +156,25 @@
 				reg = <0x2000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
+				interrupt-names = "intx";
+				interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <1>;
 				ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
 					  0x81000000 0 0 0x81000000 0x4 0 1 0>;
 				bus-range = <0x00 0xff>;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &pcie4_intc 0>,
+						<0 0 0 2 &pcie4_intc 1>,
+						<0 0 0 3 &pcie4_intc 2>,
+						<0 0 0 4 &pcie4_intc 3>;
 				marvell,pcie-port = <3>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 7>;
 				status = "disabled";
+				pcie4_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
 			};
 		};
 	};
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
@ 2022-01-12 15:18     ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-12 15:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Andrew Lunn, Gregory Clement
  Cc: linux-pci, linux-kernel, linux-arm-kernel, devicetree

With this change legacy INTA, INTB, INTC and INTD interrupts are reported
separately and not mixed into one Linux virq source anymore.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----
 1 file changed, 44 insertions(+), 8 deletions(-)

diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
index f0022d10c715..83392b92dae2 100644
--- a/arch/arm/boot/dts/armada-385.dtsi
+++ b/arch/arm/boot/dts/armada-385.dtsi
@@ -69,16 +69,25 @@
 				reg = <0x0800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
+				interrupt-names = "intx";
+				interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <1>;
 				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
 					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
 				bus-range = <0x00 0xff>;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-map-mask = <0 0 0 7>;
+				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>;
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 8>;
 				status = "disabled";
+				pcie1_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
 			};
 
 			/* x1 port */
@@ -88,16 +97,25 @@
 				reg = <0x1000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
+				interrupt-names = "intx";
+				interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <1>;
 				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
 					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
 				bus-range = <0x00 0xff>;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &pcie2_intc 0>,
+						<0 0 0 2 &pcie2_intc 1>,
+						<0 0 0 3 &pcie2_intc 2>,
+						<0 0 0 4 &pcie2_intc 3>;
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
 				status = "disabled";
+				pcie2_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
 			};
 
 			/* x1 port */
@@ -107,16 +125,25 @@
 				reg = <0x1800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
+				interrupt-names = "intx";
+				interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <1>;
 				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
 					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
 				bus-range = <0x00 0xff>;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &pcie3_intc 0>,
+						<0 0 0 2 &pcie3_intc 1>,
+						<0 0 0 3 &pcie3_intc 2>,
+						<0 0 0 4 &pcie3_intc 3>;
 				marvell,pcie-port = <2>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 6>;
 				status = "disabled";
+				pcie3_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
 			};
 
 			/*
@@ -129,16 +156,25 @@
 				reg = <0x2000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
+				interrupt-names = "intx";
+				interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <1>;
 				ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
 					  0x81000000 0 0 0x81000000 0x4 0 1 0>;
 				bus-range = <0x00 0xff>;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &pcie4_intc 0>,
+						<0 0 0 2 &pcie4_intc 1>,
+						<0 0 0 3 &pcie4_intc 2>,
+						<0 0 0 4 &pcie4_intc 3>;
 				marvell,pcie-port = <3>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 7>;
 				status = "disabled";
+				pcie4_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
 			};
 		};
 	};
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 09/11] dt-bindings: PCI: mvebu: Update information about intx interrupts
  2022-01-12 15:18     ` Pali Rohár
@ 2022-01-12 15:36       ` Marek Behún
  -1 siblings, 0 replies; 130+ messages in thread
From: Marek Behún @ 2022-01-12 15:36 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Russell King, linux-pci, linux-kernel,
	linux-arm-kernel

On Wed, 12 Jan 2022 16:18:12 +0100
Pali Rohár <pali@kernel.org> wrote:

> Signed-off-by: Pali Rohár <pali@kernel.org>
> Acked-by: Rob Herring <robh@kernel.org>
> ---
>  Documentation/devicetree/bindings/pci/mvebu-pci.txt | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/pci/mvebu-pci.txt b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
> index 24225852bce0..6d022a9d36ee 100644
> --- a/Documentation/devicetree/bindings/pci/mvebu-pci.txt
> +++ b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
> @@ -81,6 +81,11 @@ and the following optional properties:
>  - reset-gpios: optional GPIO to PERST#
>  - reset-delay-us: delay in us to wait after reset de-assertion, if not
>    specified will default to 100ms, as required by the PCIe specification.
> +- interrupt-names: list of interrupt names, supported are:
> +   - "intx" - interrupt line triggered by one of the legacy interrupt
> +- interrupts or interrupts-extended: List of the interrupt sources which
> +  corresponding to the "interrupt-names". If non-empty then also additional
> +  'interrupt-controller' subnode must be defined.
>  
>  Example:
>  

Empty commit message. At least add something like this:

Document the following additional properties in the mvebu-pci DT
binding:
- interrupt-names
- interrupts / interrupts-extended


Marek

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 09/11] dt-bindings: PCI: mvebu: Update information about intx interrupts
@ 2022-01-12 15:36       ` Marek Behún
  0 siblings, 0 replies; 130+ messages in thread
From: Marek Behún @ 2022-01-12 15:36 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Russell King, linux-pci, linux-kernel,
	linux-arm-kernel

On Wed, 12 Jan 2022 16:18:12 +0100
Pali Rohár <pali@kernel.org> wrote:

> Signed-off-by: Pali Rohár <pali@kernel.org>
> Acked-by: Rob Herring <robh@kernel.org>
> ---
>  Documentation/devicetree/bindings/pci/mvebu-pci.txt | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/pci/mvebu-pci.txt b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
> index 24225852bce0..6d022a9d36ee 100644
> --- a/Documentation/devicetree/bindings/pci/mvebu-pci.txt
> +++ b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
> @@ -81,6 +81,11 @@ and the following optional properties:
>  - reset-gpios: optional GPIO to PERST#
>  - reset-delay-us: delay in us to wait after reset de-assertion, if not
>    specified will default to 100ms, as required by the PCIe specification.
> +- interrupt-names: list of interrupt names, supported are:
> +   - "intx" - interrupt line triggered by one of the legacy interrupt
> +- interrupts or interrupts-extended: List of the interrupt sources which
> +  corresponding to the "interrupt-names". If non-empty then also additional
> +  'interrupt-controller' subnode must be defined.
>  
>  Example:
>  

Empty commit message. At least add something like this:

Document the following additional properties in the mvebu-pci DT
binding:
- interrupt-names
- interrupts / interrupts-extended


Marek

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 08/11] PCI: mvebu: Use child_ops API
  2022-01-12 15:18     ` Pali Rohár
@ 2022-01-20 16:49       ` Rob Herring
  -1 siblings, 0 replies; 130+ messages in thread
From: Rob Herring @ 2022-01-20 16:49 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Wed, Jan 12, 2022 at 04:18:11PM +0100, Pali Rohár wrote:
> Split struct pci_ops between ops and child_ops. Member ops is used for
> accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
> accessing real PCIe cards.
> 
> There is no need to mix these two struct pci_ops into one as PCI core code
> already provides separate callbacks via bridge->ops and bridge->child_ops.
> 
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  drivers/pci/controller/pci-mvebu.c | 82 ++++++++++++++++--------------
>  1 file changed, 44 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> index 9ea2f6a7c2b0..1e90ab888075 100644
> --- a/drivers/pci/controller/pci-mvebu.c
> +++ b/drivers/pci/controller/pci-mvebu.c
> @@ -294,11 +294,29 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
>  	mvebu_writel(port, mask, PCIE_MASK_OFF);
>  }
>  
> -static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
> -				 struct pci_bus *bus,
> -				 u32 devfn, int where, int size, u32 *val)
> +static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> +						    struct pci_bus *bus,
> +						    int devfn);
> +
> +static int mvebu_pcie_child_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> +				    int size, u32 *val)
>  {
> -	void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
> +	struct mvebu_pcie *pcie = bus->sysdata;
> +	struct mvebu_pcie_port *port;
> +	void __iomem *conf_data;
> +
> +	port = mvebu_pcie_find_port(pcie, bus, devfn);
> +	if (!port) {
> +		*val = 0xffffffff;
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +	}
> +
> +	if (!mvebu_pcie_link_up(port)) {
> +		*val = 0xffffffff;
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +	}
> +
> +	conf_data = port->base + PCIE_CONF_DATA_OFF;
>  
>  	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
>  		     PCIE_CONF_ADDR_OFF);
> @@ -321,11 +339,21 @@ static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
>  	return PCIBIOS_SUCCESSFUL;
>  }
>  
> -static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
> -				 struct pci_bus *bus,
> -				 u32 devfn, int where, int size, u32 val)
> +static int mvebu_pcie_child_wr_conf(struct pci_bus *bus, u32 devfn,
> +				    int where, int size, u32 val)
>  {
> -	void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
> +	struct mvebu_pcie *pcie = bus->sysdata;
> +	struct mvebu_pcie_port *port;
> +	void __iomem *conf_data;
> +

> +	port = mvebu_pcie_find_port(pcie, bus, devfn);
> +	if (!port)
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	if (!mvebu_pcie_link_up(port))
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	conf_data = port->base + PCIE_CONF_DATA_OFF;

Again, the same setup code in read and write is a sign to use 
.map_bus(). You can copy it from my version I pointed you to.

Rob

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 08/11] PCI: mvebu: Use child_ops API
@ 2022-01-20 16:49       ` Rob Herring
  0 siblings, 0 replies; 130+ messages in thread
From: Rob Herring @ 2022-01-20 16:49 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Wed, Jan 12, 2022 at 04:18:11PM +0100, Pali Rohár wrote:
> Split struct pci_ops between ops and child_ops. Member ops is used for
> accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
> accessing real PCIe cards.
> 
> There is no need to mix these two struct pci_ops into one as PCI core code
> already provides separate callbacks via bridge->ops and bridge->child_ops.
> 
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  drivers/pci/controller/pci-mvebu.c | 82 ++++++++++++++++--------------
>  1 file changed, 44 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> index 9ea2f6a7c2b0..1e90ab888075 100644
> --- a/drivers/pci/controller/pci-mvebu.c
> +++ b/drivers/pci/controller/pci-mvebu.c
> @@ -294,11 +294,29 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
>  	mvebu_writel(port, mask, PCIE_MASK_OFF);
>  }
>  
> -static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
> -				 struct pci_bus *bus,
> -				 u32 devfn, int where, int size, u32 *val)
> +static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> +						    struct pci_bus *bus,
> +						    int devfn);
> +
> +static int mvebu_pcie_child_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> +				    int size, u32 *val)
>  {
> -	void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
> +	struct mvebu_pcie *pcie = bus->sysdata;
> +	struct mvebu_pcie_port *port;
> +	void __iomem *conf_data;
> +
> +	port = mvebu_pcie_find_port(pcie, bus, devfn);
> +	if (!port) {
> +		*val = 0xffffffff;
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +	}
> +
> +	if (!mvebu_pcie_link_up(port)) {
> +		*val = 0xffffffff;
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +	}
> +
> +	conf_data = port->base + PCIE_CONF_DATA_OFF;
>  
>  	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
>  		     PCIE_CONF_ADDR_OFF);
> @@ -321,11 +339,21 @@ static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
>  	return PCIBIOS_SUCCESSFUL;
>  }
>  
> -static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
> -				 struct pci_bus *bus,
> -				 u32 devfn, int where, int size, u32 val)
> +static int mvebu_pcie_child_wr_conf(struct pci_bus *bus, u32 devfn,
> +				    int where, int size, u32 val)
>  {
> -	void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
> +	struct mvebu_pcie *pcie = bus->sysdata;
> +	struct mvebu_pcie_port *port;
> +	void __iomem *conf_data;
> +

> +	port = mvebu_pcie_find_port(pcie, bus, devfn);
> +	if (!port)
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	if (!mvebu_pcie_link_up(port))
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	conf_data = port->base + PCIE_CONF_DATA_OFF;

Again, the same setup code in read and write is a sign to use 
.map_bus(). You can copy it from my version I pointed you to.

Rob

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 08/11] PCI: mvebu: Use child_ops API
  2022-01-20 16:49       ` Rob Herring
@ 2022-01-20 16:55         ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-20 16:55 UTC (permalink / raw)
  To: Rob Herring
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thursday 20 January 2022 10:49:05 Rob Herring wrote:
> On Wed, Jan 12, 2022 at 04:18:11PM +0100, Pali Rohár wrote:
> > Split struct pci_ops between ops and child_ops. Member ops is used for
> > accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
> > accessing real PCIe cards.
> > 
> > There is no need to mix these two struct pci_ops into one as PCI core code
> > already provides separate callbacks via bridge->ops and bridge->child_ops.
> > 
> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > ---
> >  drivers/pci/controller/pci-mvebu.c | 82 ++++++++++++++++--------------
> >  1 file changed, 44 insertions(+), 38 deletions(-)
> > 
> > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > index 9ea2f6a7c2b0..1e90ab888075 100644
> > --- a/drivers/pci/controller/pci-mvebu.c
> > +++ b/drivers/pci/controller/pci-mvebu.c
> > @@ -294,11 +294,29 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> >  	mvebu_writel(port, mask, PCIE_MASK_OFF);
> >  }
> >  
> > -static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
> > -				 struct pci_bus *bus,
> > -				 u32 devfn, int where, int size, u32 *val)
> > +static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > +						    struct pci_bus *bus,
> > +						    int devfn);
> > +
> > +static int mvebu_pcie_child_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> > +				    int size, u32 *val)
> >  {
> > -	void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
> > +	struct mvebu_pcie *pcie = bus->sysdata;
> > +	struct mvebu_pcie_port *port;
> > +	void __iomem *conf_data;
> > +
> > +	port = mvebu_pcie_find_port(pcie, bus, devfn);
> > +	if (!port) {
> > +		*val = 0xffffffff;
> > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > +	}
> > +
> > +	if (!mvebu_pcie_link_up(port)) {
> > +		*val = 0xffffffff;
> > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > +	}
> > +
> > +	conf_data = port->base + PCIE_CONF_DATA_OFF;
> >  
> >  	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
> >  		     PCIE_CONF_ADDR_OFF);
> > @@ -321,11 +339,21 @@ static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
> >  	return PCIBIOS_SUCCESSFUL;
> >  }
> >  
> > -static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
> > -				 struct pci_bus *bus,
> > -				 u32 devfn, int where, int size, u32 val)
> > +static int mvebu_pcie_child_wr_conf(struct pci_bus *bus, u32 devfn,
> > +				    int where, int size, u32 val)
> >  {
> > -	void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
> > +	struct mvebu_pcie *pcie = bus->sysdata;
> > +	struct mvebu_pcie_port *port;
> > +	void __iomem *conf_data;
> > +
> 
> > +	port = mvebu_pcie_find_port(pcie, bus, devfn);
> > +	if (!port)
> > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > +
> > +	if (!mvebu_pcie_link_up(port))
> > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > +
> > +	conf_data = port->base + PCIE_CONF_DATA_OFF;
> 
> Again, the same setup code in read and write is a sign to use 
> .map_bus(). You can copy it from my version I pointed you to.
> 
> Rob

I'm planning to do other cleanup in followup patches. But there are too
many mvebu and aardvark patches on the list waiting, and I do not want
to send another batch.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 08/11] PCI: mvebu: Use child_ops API
@ 2022-01-20 16:55         ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-20 16:55 UTC (permalink / raw)
  To: Rob Herring
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thursday 20 January 2022 10:49:05 Rob Herring wrote:
> On Wed, Jan 12, 2022 at 04:18:11PM +0100, Pali Rohár wrote:
> > Split struct pci_ops between ops and child_ops. Member ops is used for
> > accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
> > accessing real PCIe cards.
> > 
> > There is no need to mix these two struct pci_ops into one as PCI core code
> > already provides separate callbacks via bridge->ops and bridge->child_ops.
> > 
> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > ---
> >  drivers/pci/controller/pci-mvebu.c | 82 ++++++++++++++++--------------
> >  1 file changed, 44 insertions(+), 38 deletions(-)
> > 
> > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > index 9ea2f6a7c2b0..1e90ab888075 100644
> > --- a/drivers/pci/controller/pci-mvebu.c
> > +++ b/drivers/pci/controller/pci-mvebu.c
> > @@ -294,11 +294,29 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> >  	mvebu_writel(port, mask, PCIE_MASK_OFF);
> >  }
> >  
> > -static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
> > -				 struct pci_bus *bus,
> > -				 u32 devfn, int where, int size, u32 *val)
> > +static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > +						    struct pci_bus *bus,
> > +						    int devfn);
> > +
> > +static int mvebu_pcie_child_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> > +				    int size, u32 *val)
> >  {
> > -	void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
> > +	struct mvebu_pcie *pcie = bus->sysdata;
> > +	struct mvebu_pcie_port *port;
> > +	void __iomem *conf_data;
> > +
> > +	port = mvebu_pcie_find_port(pcie, bus, devfn);
> > +	if (!port) {
> > +		*val = 0xffffffff;
> > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > +	}
> > +
> > +	if (!mvebu_pcie_link_up(port)) {
> > +		*val = 0xffffffff;
> > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > +	}
> > +
> > +	conf_data = port->base + PCIE_CONF_DATA_OFF;
> >  
> >  	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
> >  		     PCIE_CONF_ADDR_OFF);
> > @@ -321,11 +339,21 @@ static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
> >  	return PCIBIOS_SUCCESSFUL;
> >  }
> >  
> > -static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
> > -				 struct pci_bus *bus,
> > -				 u32 devfn, int where, int size, u32 val)
> > +static int mvebu_pcie_child_wr_conf(struct pci_bus *bus, u32 devfn,
> > +				    int where, int size, u32 val)
> >  {
> > -	void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
> > +	struct mvebu_pcie *pcie = bus->sysdata;
> > +	struct mvebu_pcie_port *port;
> > +	void __iomem *conf_data;
> > +
> 
> > +	port = mvebu_pcie_find_port(pcie, bus, devfn);
> > +	if (!port)
> > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > +
> > +	if (!mvebu_pcie_link_up(port))
> > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > +
> > +	conf_data = port->base + PCIE_CONF_DATA_OFF;
> 
> Again, the same setup code in read and write is a sign to use 
> .map_bus(). You can copy it from my version I pointed you to.
> 
> Rob

I'm planning to do other cleanup in followup patches. But there are too
many mvebu and aardvark patches on the list waiting, and I do not want
to send another batch.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 05/11] PCI: mvebu: Correctly configure x1/x4 mode
  2022-01-12 15:18     ` Pali Rohár
@ 2022-01-20 17:09       ` Rob Herring
  -1 siblings, 0 replies; 130+ messages in thread
From: Rob Herring @ 2022-01-20 17:09 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Wed, Jan 12, 2022 at 04:18:08PM +0100, Pali Rohár wrote:
> If x1/x4 mode is not set correctly then link with endpoint card is not
> established.
> 
> Use DTS property 'num-lanes' to deteriminate x1/x4 mode.
> 
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  drivers/pci/controller/pci-mvebu.c | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> index a075ba26cff1..0f2ec0a17874 100644
> --- a/drivers/pci/controller/pci-mvebu.c
> +++ b/drivers/pci/controller/pci-mvebu.c
> @@ -93,6 +93,7 @@ struct mvebu_pcie_port {
>  	void __iomem *base;
>  	u32 port;
>  	u32 lane;
> +	bool is_x4;

I would just store the number of lanes.

>  	int devfn;
>  	unsigned int mem_target;
>  	unsigned int mem_attr;
> @@ -233,13 +234,25 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
>  
>  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
>  {
> -	u32 ctrl, cmd, dev_rev, mask;
> +	u32 ctrl, lnkcap, cmd, dev_rev, mask;
>  
>  	/* Setup PCIe controller to Root Complex mode. */
>  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
>  	ctrl |= PCIE_CTRL_RC_MODE;
>  	mvebu_writel(port, ctrl, PCIE_CTRL_OFF);
>  
> +	/*
> +	 * Set Maximum Link Width to X1 or X4 in Root Port's PCIe Link
> +	 * Capability register. This register is defined by PCIe specification
> +	 * as read-only but this mvebu controller has it as read-write and must
> +	 * be set to number of SerDes PCIe lanes (1 or 4). If this register is
> +	 * not set correctly then link with endpoint card is not established.
> +	 */
> +	lnkcap = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
> +	lnkcap &= ~PCI_EXP_LNKCAP_MLW;
> +	lnkcap |= (port->is_x4 ? 4 : 1) << 4;

then this is just: lanes << 4

> +	mvebu_writel(port, lnkcap, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
> +
>  	/* Disable Root Bridge I/O space, memory space and bus mastering. */
>  	cmd = mvebu_readl(port, PCIE_CMD_OFF);
>  	cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
> @@ -986,6 +999,7 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
>  	struct device *dev = &pcie->pdev->dev;
>  	enum of_gpio_flags flags;
>  	int reset_gpio, ret;
> +	u32 num_lanes;
>  
>  	port->pcie = pcie;
>  
> @@ -998,6 +1012,9 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
>  	if (of_property_read_u32(child, "marvell,pcie-lane", &port->lane))
>  		port->lane = 0;
>  
> +	if (!of_property_read_u32(child, "num-lanes", &num_lanes) && num_lanes == 4)
> +		port->is_x4 = true;

And this can be:

num_lanes = 1;
of_property_read_u32(child, "num-lanes", &num_lanes);

If you want to validate the DT is only 1 or 4, make the DT schema do 
that.


> +
>  	port->name = devm_kasprintf(dev, GFP_KERNEL, "pcie%d.%d", port->port,
>  				    port->lane);
>  	if (!port->name) {
> -- 
> 2.20.1
> 
> 

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 05/11] PCI: mvebu: Correctly configure x1/x4 mode
@ 2022-01-20 17:09       ` Rob Herring
  0 siblings, 0 replies; 130+ messages in thread
From: Rob Herring @ 2022-01-20 17:09 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Wed, Jan 12, 2022 at 04:18:08PM +0100, Pali Rohár wrote:
> If x1/x4 mode is not set correctly then link with endpoint card is not
> established.
> 
> Use DTS property 'num-lanes' to deteriminate x1/x4 mode.
> 
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  drivers/pci/controller/pci-mvebu.c | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> index a075ba26cff1..0f2ec0a17874 100644
> --- a/drivers/pci/controller/pci-mvebu.c
> +++ b/drivers/pci/controller/pci-mvebu.c
> @@ -93,6 +93,7 @@ struct mvebu_pcie_port {
>  	void __iomem *base;
>  	u32 port;
>  	u32 lane;
> +	bool is_x4;

I would just store the number of lanes.

>  	int devfn;
>  	unsigned int mem_target;
>  	unsigned int mem_attr;
> @@ -233,13 +234,25 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
>  
>  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
>  {
> -	u32 ctrl, cmd, dev_rev, mask;
> +	u32 ctrl, lnkcap, cmd, dev_rev, mask;
>  
>  	/* Setup PCIe controller to Root Complex mode. */
>  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
>  	ctrl |= PCIE_CTRL_RC_MODE;
>  	mvebu_writel(port, ctrl, PCIE_CTRL_OFF);
>  
> +	/*
> +	 * Set Maximum Link Width to X1 or X4 in Root Port's PCIe Link
> +	 * Capability register. This register is defined by PCIe specification
> +	 * as read-only but this mvebu controller has it as read-write and must
> +	 * be set to number of SerDes PCIe lanes (1 or 4). If this register is
> +	 * not set correctly then link with endpoint card is not established.
> +	 */
> +	lnkcap = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
> +	lnkcap &= ~PCI_EXP_LNKCAP_MLW;
> +	lnkcap |= (port->is_x4 ? 4 : 1) << 4;

then this is just: lanes << 4

> +	mvebu_writel(port, lnkcap, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
> +
>  	/* Disable Root Bridge I/O space, memory space and bus mastering. */
>  	cmd = mvebu_readl(port, PCIE_CMD_OFF);
>  	cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
> @@ -986,6 +999,7 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
>  	struct device *dev = &pcie->pdev->dev;
>  	enum of_gpio_flags flags;
>  	int reset_gpio, ret;
> +	u32 num_lanes;
>  
>  	port->pcie = pcie;
>  
> @@ -998,6 +1012,9 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
>  	if (of_property_read_u32(child, "marvell,pcie-lane", &port->lane))
>  		port->lane = 0;
>  
> +	if (!of_property_read_u32(child, "num-lanes", &num_lanes) && num_lanes == 4)
> +		port->is_x4 = true;

And this can be:

num_lanes = 1;
of_property_read_u32(child, "num-lanes", &num_lanes);

If you want to validate the DT is only 1 or 4, make the DT schema do 
that.


> +
>  	port->name = devm_kasprintf(dev, GFP_KERNEL, "pcie%d.%d", port->port,
>  				    port->lane);
>  	if (!port->name) {
> -- 
> 2.20.1
> 
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 05/11] PCI: mvebu: Correctly configure x1/x4 mode
  2022-01-20 17:09       ` Rob Herring
@ 2022-01-20 17:19         ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-20 17:19 UTC (permalink / raw)
  To: Rob Herring
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thursday 20 January 2022 11:09:17 Rob Herring wrote:
> On Wed, Jan 12, 2022 at 04:18:08PM +0100, Pali Rohár wrote:
> > If x1/x4 mode is not set correctly then link with endpoint card is not
> > established.
> > 
> > Use DTS property 'num-lanes' to deteriminate x1/x4 mode.
> > 
> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > ---
> >  drivers/pci/controller/pci-mvebu.c | 19 ++++++++++++++++++-
> >  1 file changed, 18 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > index a075ba26cff1..0f2ec0a17874 100644
> > --- a/drivers/pci/controller/pci-mvebu.c
> > +++ b/drivers/pci/controller/pci-mvebu.c
> > @@ -93,6 +93,7 @@ struct mvebu_pcie_port {
> >  	void __iomem *base;
> >  	u32 port;
> >  	u32 lane;
> > +	bool is_x4;
> 
> I would just store the number of lanes.
> 
> >  	int devfn;
> >  	unsigned int mem_target;
> >  	unsigned int mem_attr;
> > @@ -233,13 +234,25 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> >  
> >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> >  {
> > -	u32 ctrl, cmd, dev_rev, mask;
> > +	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> >  
> >  	/* Setup PCIe controller to Root Complex mode. */
> >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> >  	ctrl |= PCIE_CTRL_RC_MODE;
> >  	mvebu_writel(port, ctrl, PCIE_CTRL_OFF);
> >  
> > +	/*
> > +	 * Set Maximum Link Width to X1 or X4 in Root Port's PCIe Link
> > +	 * Capability register. This register is defined by PCIe specification
> > +	 * as read-only but this mvebu controller has it as read-write and must
> > +	 * be set to number of SerDes PCIe lanes (1 or 4). If this register is
> > +	 * not set correctly then link with endpoint card is not established.
> > +	 */
> > +	lnkcap = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
> > +	lnkcap &= ~PCI_EXP_LNKCAP_MLW;
> > +	lnkcap |= (port->is_x4 ? 4 : 1) << 4;
> 
> then this is just: lanes << 4

As only 1 and 4 are valid valid values, I chose this style (is_x4) to
ensure that no other (invalid) value is written into mvebu register.
Setting width to smaller number (if incorrect value is provided) still
allows controller to work and link should be negotiated. So setting 1 is
a sane default when controller does not have configured 4 SerDes lines
to PCIe.

> > +	mvebu_writel(port, lnkcap, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
> > +
> >  	/* Disable Root Bridge I/O space, memory space and bus mastering. */
> >  	cmd = mvebu_readl(port, PCIE_CMD_OFF);
> >  	cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
> > @@ -986,6 +999,7 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
> >  	struct device *dev = &pcie->pdev->dev;
> >  	enum of_gpio_flags flags;
> >  	int reset_gpio, ret;
> > +	u32 num_lanes;
> >  
> >  	port->pcie = pcie;
> >  
> > @@ -998,6 +1012,9 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
> >  	if (of_property_read_u32(child, "marvell,pcie-lane", &port->lane))
> >  		port->lane = 0;
> >  
> > +	if (!of_property_read_u32(child, "num-lanes", &num_lanes) && num_lanes == 4)
> > +		port->is_x4 = true;
> 
> And this can be:
> 
> num_lanes = 1;
> of_property_read_u32(child, "num-lanes", &num_lanes);
> 
> If you want to validate the DT is only 1 or 4, make the DT schema do 
> that.

The problem is that there is no schema for this platform and PCIe yet.
So adding it would mean to first convert everything to schema and then
this constrain can be expressed in schema.

I'm planning to look at possibility to write schema for this platform
but I do not want to do it before open issues with representation of
other pcie properties in dts schema are resolved.

> 
> > +
> >  	port->name = devm_kasprintf(dev, GFP_KERNEL, "pcie%d.%d", port->port,
> >  				    port->lane);
> >  	if (!port->name) {
> > -- 
> > 2.20.1
> > 
> > 

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 05/11] PCI: mvebu: Correctly configure x1/x4 mode
@ 2022-01-20 17:19         ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-01-20 17:19 UTC (permalink / raw)
  To: Rob Herring
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Thursday 20 January 2022 11:09:17 Rob Herring wrote:
> On Wed, Jan 12, 2022 at 04:18:08PM +0100, Pali Rohár wrote:
> > If x1/x4 mode is not set correctly then link with endpoint card is not
> > established.
> > 
> > Use DTS property 'num-lanes' to deteriminate x1/x4 mode.
> > 
> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > ---
> >  drivers/pci/controller/pci-mvebu.c | 19 ++++++++++++++++++-
> >  1 file changed, 18 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > index a075ba26cff1..0f2ec0a17874 100644
> > --- a/drivers/pci/controller/pci-mvebu.c
> > +++ b/drivers/pci/controller/pci-mvebu.c
> > @@ -93,6 +93,7 @@ struct mvebu_pcie_port {
> >  	void __iomem *base;
> >  	u32 port;
> >  	u32 lane;
> > +	bool is_x4;
> 
> I would just store the number of lanes.
> 
> >  	int devfn;
> >  	unsigned int mem_target;
> >  	unsigned int mem_attr;
> > @@ -233,13 +234,25 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> >  
> >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> >  {
> > -	u32 ctrl, cmd, dev_rev, mask;
> > +	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> >  
> >  	/* Setup PCIe controller to Root Complex mode. */
> >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> >  	ctrl |= PCIE_CTRL_RC_MODE;
> >  	mvebu_writel(port, ctrl, PCIE_CTRL_OFF);
> >  
> > +	/*
> > +	 * Set Maximum Link Width to X1 or X4 in Root Port's PCIe Link
> > +	 * Capability register. This register is defined by PCIe specification
> > +	 * as read-only but this mvebu controller has it as read-write and must
> > +	 * be set to number of SerDes PCIe lanes (1 or 4). If this register is
> > +	 * not set correctly then link with endpoint card is not established.
> > +	 */
> > +	lnkcap = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
> > +	lnkcap &= ~PCI_EXP_LNKCAP_MLW;
> > +	lnkcap |= (port->is_x4 ? 4 : 1) << 4;
> 
> then this is just: lanes << 4

As only 1 and 4 are valid valid values, I chose this style (is_x4) to
ensure that no other (invalid) value is written into mvebu register.
Setting width to smaller number (if incorrect value is provided) still
allows controller to work and link should be negotiated. So setting 1 is
a sane default when controller does not have configured 4 SerDes lines
to PCIe.

> > +	mvebu_writel(port, lnkcap, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
> > +
> >  	/* Disable Root Bridge I/O space, memory space and bus mastering. */
> >  	cmd = mvebu_readl(port, PCIE_CMD_OFF);
> >  	cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
> > @@ -986,6 +999,7 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
> >  	struct device *dev = &pcie->pdev->dev;
> >  	enum of_gpio_flags flags;
> >  	int reset_gpio, ret;
> > +	u32 num_lanes;
> >  
> >  	port->pcie = pcie;
> >  
> > @@ -998,6 +1012,9 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
> >  	if (of_property_read_u32(child, "marvell,pcie-lane", &port->lane))
> >  		port->lane = 0;
> >  
> > +	if (!of_property_read_u32(child, "num-lanes", &num_lanes) && num_lanes == 4)
> > +		port->is_x4 = true;
> 
> And this can be:
> 
> num_lanes = 1;
> of_property_read_u32(child, "num-lanes", &num_lanes);
> 
> If you want to validate the DT is only 1 or 4, make the DT schema do 
> that.

The problem is that there is no schema for this platform and PCIe yet.
So adding it would mean to first convert everything to schema and then
this constrain can be expressed in schema.

I'm planning to look at possibility to write schema for this platform
but I do not want to do it before open issues with representation of
other pcie properties in dts schema are resolved.

> 
> > +
> >  	port->name = devm_kasprintf(dev, GFP_KERNEL, "pcie%d.%d", port->port,
> >  				    port->lane);
> >  	if (!port->name) {
> > -- 
> > 2.20.1
> > 
> > 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 08/11] PCI: mvebu: Use child_ops API
  2022-01-20 16:55         ` Pali Rohár
@ 2022-01-20 18:40           ` Rob Herring
  -1 siblings, 0 replies; 130+ messages in thread
From: Rob Herring @ 2022-01-20 18:40 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King, PCI,
	linux-kernel, linux-arm-kernel

On Thu, Jan 20, 2022 at 10:55 AM Pali Rohár <pali@kernel.org> wrote:
>
> On Thursday 20 January 2022 10:49:05 Rob Herring wrote:
> > On Wed, Jan 12, 2022 at 04:18:11PM +0100, Pali Rohár wrote:
> > > Split struct pci_ops between ops and child_ops. Member ops is used for
> > > accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
> > > accessing real PCIe cards.
> > >
> > > There is no need to mix these two struct pci_ops into one as PCI core code
> > > already provides separate callbacks via bridge->ops and bridge->child_ops.
> > >
> > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > ---
> > >  drivers/pci/controller/pci-mvebu.c | 82 ++++++++++++++++--------------
> > >  1 file changed, 44 insertions(+), 38 deletions(-)
> > >
> > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > index 9ea2f6a7c2b0..1e90ab888075 100644
> > > --- a/drivers/pci/controller/pci-mvebu.c
> > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > @@ -294,11 +294,29 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > >     mvebu_writel(port, mask, PCIE_MASK_OFF);
> > >  }
> > >
> > > -static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
> > > -                            struct pci_bus *bus,
> > > -                            u32 devfn, int where, int size, u32 *val)
> > > +static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > > +                                               struct pci_bus *bus,
> > > +                                               int devfn);
> > > +
> > > +static int mvebu_pcie_child_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> > > +                               int size, u32 *val)
> > >  {
> > > -   void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
> > > +   struct mvebu_pcie *pcie = bus->sysdata;
> > > +   struct mvebu_pcie_port *port;
> > > +   void __iomem *conf_data;
> > > +
> > > +   port = mvebu_pcie_find_port(pcie, bus, devfn);
> > > +   if (!port) {
> > > +           *val = 0xffffffff;
> > > +           return PCIBIOS_DEVICE_NOT_FOUND;
> > > +   }
> > > +
> > > +   if (!mvebu_pcie_link_up(port)) {
> > > +           *val = 0xffffffff;
> > > +           return PCIBIOS_DEVICE_NOT_FOUND;
> > > +   }
> > > +
> > > +   conf_data = port->base + PCIE_CONF_DATA_OFF;
> > >
> > >     mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
> > >                  PCIE_CONF_ADDR_OFF);
> > > @@ -321,11 +339,21 @@ static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
> > >     return PCIBIOS_SUCCESSFUL;
> > >  }
> > >
> > > -static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
> > > -                            struct pci_bus *bus,
> > > -                            u32 devfn, int where, int size, u32 val)
> > > +static int mvebu_pcie_child_wr_conf(struct pci_bus *bus, u32 devfn,
> > > +                               int where, int size, u32 val)
> > >  {
> > > -   void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
> > > +   struct mvebu_pcie *pcie = bus->sysdata;
> > > +   struct mvebu_pcie_port *port;
> > > +   void __iomem *conf_data;
> > > +
> >
> > > +   port = mvebu_pcie_find_port(pcie, bus, devfn);
> > > +   if (!port)
> > > +           return PCIBIOS_DEVICE_NOT_FOUND;
> > > +
> > > +   if (!mvebu_pcie_link_up(port))
> > > +           return PCIBIOS_DEVICE_NOT_FOUND;
> > > +
> > > +   conf_data = port->base + PCIE_CONF_DATA_OFF;
> >
> > Again, the same setup code in read and write is a sign to use
> > .map_bus(). You can copy it from my version I pointed you to.
> >
> > Rob
>
> I'm planning to do other cleanup in followup patches. But there are too
> many mvebu and aardvark patches on the list waiting, and I do not want
> to send another batch.

It can all be part of this patch.

Rob

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 08/11] PCI: mvebu: Use child_ops API
@ 2022-01-20 18:40           ` Rob Herring
  0 siblings, 0 replies; 130+ messages in thread
From: Rob Herring @ 2022-01-20 18:40 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King, PCI,
	linux-kernel, linux-arm-kernel

On Thu, Jan 20, 2022 at 10:55 AM Pali Rohár <pali@kernel.org> wrote:
>
> On Thursday 20 January 2022 10:49:05 Rob Herring wrote:
> > On Wed, Jan 12, 2022 at 04:18:11PM +0100, Pali Rohár wrote:
> > > Split struct pci_ops between ops and child_ops. Member ops is used for
> > > accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
> > > accessing real PCIe cards.
> > >
> > > There is no need to mix these two struct pci_ops into one as PCI core code
> > > already provides separate callbacks via bridge->ops and bridge->child_ops.
> > >
> > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > ---
> > >  drivers/pci/controller/pci-mvebu.c | 82 ++++++++++++++++--------------
> > >  1 file changed, 44 insertions(+), 38 deletions(-)
> > >
> > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > index 9ea2f6a7c2b0..1e90ab888075 100644
> > > --- a/drivers/pci/controller/pci-mvebu.c
> > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > @@ -294,11 +294,29 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > >     mvebu_writel(port, mask, PCIE_MASK_OFF);
> > >  }
> > >
> > > -static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
> > > -                            struct pci_bus *bus,
> > > -                            u32 devfn, int where, int size, u32 *val)
> > > +static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > > +                                               struct pci_bus *bus,
> > > +                                               int devfn);
> > > +
> > > +static int mvebu_pcie_child_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> > > +                               int size, u32 *val)
> > >  {
> > > -   void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
> > > +   struct mvebu_pcie *pcie = bus->sysdata;
> > > +   struct mvebu_pcie_port *port;
> > > +   void __iomem *conf_data;
> > > +
> > > +   port = mvebu_pcie_find_port(pcie, bus, devfn);
> > > +   if (!port) {
> > > +           *val = 0xffffffff;
> > > +           return PCIBIOS_DEVICE_NOT_FOUND;
> > > +   }
> > > +
> > > +   if (!mvebu_pcie_link_up(port)) {
> > > +           *val = 0xffffffff;
> > > +           return PCIBIOS_DEVICE_NOT_FOUND;
> > > +   }
> > > +
> > > +   conf_data = port->base + PCIE_CONF_DATA_OFF;
> > >
> > >     mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
> > >                  PCIE_CONF_ADDR_OFF);
> > > @@ -321,11 +339,21 @@ static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
> > >     return PCIBIOS_SUCCESSFUL;
> > >  }
> > >
> > > -static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
> > > -                            struct pci_bus *bus,
> > > -                            u32 devfn, int where, int size, u32 val)
> > > +static int mvebu_pcie_child_wr_conf(struct pci_bus *bus, u32 devfn,
> > > +                               int where, int size, u32 val)
> > >  {
> > > -   void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
> > > +   struct mvebu_pcie *pcie = bus->sysdata;
> > > +   struct mvebu_pcie_port *port;
> > > +   void __iomem *conf_data;
> > > +
> >
> > > +   port = mvebu_pcie_find_port(pcie, bus, devfn);
> > > +   if (!port)
> > > +           return PCIBIOS_DEVICE_NOT_FOUND;
> > > +
> > > +   if (!mvebu_pcie_link_up(port))
> > > +           return PCIBIOS_DEVICE_NOT_FOUND;
> > > +
> > > +   conf_data = port->base + PCIE_CONF_DATA_OFF;
> >
> > Again, the same setup code in read and write is a sign to use
> > .map_bus(). You can copy it from my version I pointed you to.
> >
> > Rob
>
> I'm planning to do other cleanup in followup patches. But there are too
> many mvebu and aardvark patches on the list waiting, and I do not want
> to send another batch.

It can all be part of this patch.

Rob

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-01-12 15:18     ` Pali Rohár
@ 2022-02-11 17:19       ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 130+ messages in thread
From: Lorenzo Pieralisi @ 2022-02-11 17:19 UTC (permalink / raw)
  To: Pali Rohár, robh+dt
  Cc: Bjorn Helgaas, Thomas Petazzoni, Krzysztof Wilczyński,
	Marek Behún, Russell King, Marc Zyngier, linux-pci,
	linux-kernel, linux-arm-kernel

On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> This adds support for legacy INTx interrupts received from other PCIe
> devices and which are reported by a new INTx irq chip.
> 
> With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> interrupts.
> 
> Note that for this support, device tree files has to be properly adjusted
> to provide "interrupts" or "interrupts-extended" property with intx
> interrupt source, "interrupt-names" property with "intx" string and also
> 'interrupt-controller' subnode must be defined.
> 
> If device tree files do not provide these nodes then driver would work as
> before.

Nit: this information is not useful. DT rules are written in DT
bindings, not in kernel commit logs. All I am saying is that firmware
developers should not have to read this log to write firmware.

> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
>  1 file changed, 177 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> index 1e90ab888075..dbb6ecb4cb70 100644
> --- a/drivers/pci/controller/pci-mvebu.c
> +++ b/drivers/pci/controller/pci-mvebu.c
> @@ -54,9 +54,10 @@
>  	 PCIE_CONF_ADDR_EN)
>  #define PCIE_CONF_DATA_OFF	0x18fc
>  #define PCIE_INT_CAUSE_OFF	0x1900
> +#define PCIE_INT_UNMASK_OFF	0x1910

Nit: I understand it is tempting but here you are redefining or better
giving a proper label to a register. Separate patch please.

> +#define  PCIE_INT_INTX(i)		BIT(24+i)
>  #define  PCIE_INT_PM_PME		BIT(28)
> -#define PCIE_MASK_OFF		0x1910

See above.

> -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
>  #define PCIE_CTRL_OFF		0x1a00
>  #define  PCIE_CTRL_X1_MODE		0x0001
>  #define  PCIE_CTRL_RC_MODE		BIT(1)
> @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
>  	struct mvebu_pcie_window iowin;
>  	u32 saved_pcie_stat;
>  	struct resource regs;
> +	struct irq_domain *intx_irq_domain;
> +	raw_spinlock_t irq_lock;
> +	int intx_irq;
>  };
>  
>  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
>  
>  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
>  {
> -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
>  
>  	/* Setup PCIe controller to Root Complex mode. */
>  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
>  	/* Point PCIe unit MBUS decode windows to DRAM space. */
>  	mvebu_pcie_setup_wins(port);
>  
> -	/* Enable interrupt lines A-D. */
> -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> -	mask |= PCIE_MASK_ENABLE_INTS;
> -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> +	/* Mask all interrupt sources. */
> +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> +
> +	/* Clear all interrupt causes. */
> +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> +
> +	if (port->intx_irq <= 0) {
> +		/*
> +		 * When neither "summary" interrupt, nor "intx" interrupt was
> +		 * specified in DT then unmask all legacy INTx interrupts as in
> +		 * this case driver does not provide a way for masking and
> +		 * unmasking of individual legacy INTx interrupts. In this case
> +		 * all interrupts, including legacy INTx are reported via one
> +		 * shared GIC source and therefore kernel cannot distinguish
> +		 * which individual legacy INTx was triggered. These interrupts
> +		 * are shared, so it should not cause any issue. Just
> +		 * performance penalty as every PCIe interrupt handler needs to
> +		 * be called when some interrupt is triggered.
> +		 */

This comment applies to current mainline right (ie it describes how
current mainline handles INTx) ? IMO you should split it out in a
separate patch.

I understand it is hard but a patch is a logical _change_, this
comment is a change per se, it is a clarification on current
behaviour.

> +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> +	}
>  }
>  
>  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> @@ -924,6 +948,108 @@ static struct pci_ops mvebu_pcie_ops = {
>  	.write = mvebu_pcie_wr_conf,
>  };
>  
> +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> +{
> +	struct mvebu_pcie_port *port = d->domain->host_data;
> +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> +	unsigned long flags;
> +	u32 unmask;
> +
> +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> +	unmask &= ~PCIE_INT_INTX(hwirq);
> +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> +}
> +
> +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> +{
> +	struct mvebu_pcie_port *port = d->domain->host_data;
> +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> +	unsigned long flags;
> +	u32 unmask;
> +
> +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> +	unmask |= PCIE_INT_INTX(hwirq);
> +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> +}
> +
> +static struct irq_chip intx_irq_chip = {
> +	.name = "mvebu-INTx",
> +	.irq_mask = mvebu_pcie_intx_irq_mask,
> +	.irq_unmask = mvebu_pcie_intx_irq_unmask,
> +};
> +
> +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> +				   unsigned int virq, irq_hw_number_t hwirq)
> +{
> +	struct mvebu_pcie_port *port = h->host_data;
> +
> +	irq_set_status_flags(virq, IRQ_LEVEL);
> +	irq_set_chip_and_handler(virq, &intx_irq_chip, handle_level_irq);
> +	irq_set_chip_data(virq, port);
> +
> +	return 0;
> +}
> +
> +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> +	.map = mvebu_pcie_intx_irq_map,
> +	.xlate = irq_domain_xlate_onecell,
> +};
> +
> +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> +{
> +	struct device *dev = &port->pcie->pdev->dev;
> +	struct device_node *pcie_intc_node;
> +
> +	raw_spin_lock_init(&port->irq_lock);
> +
> +	pcie_intc_node = of_get_next_child(port->dn, NULL);
> +	if (!pcie_intc_node) {
> +		dev_err(dev, "No PCIe Intc node found for %s\n", port->name);
> +		return -ENODEV;
> +	}
> +
> +	port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
> +						      &mvebu_pcie_intx_irq_domain_ops,
> +						      port);
> +	of_node_put(pcie_intc_node);
> +	if (!port->intx_irq_domain) {
> +		dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name);
> +		return -ENOMEM;
> +	}
> +
> +	return 0;
> +}
> +
> +static void mvebu_pcie_irq_handler(struct irq_desc *desc)
> +{
> +	struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc);
> +	struct irq_chip *chip = irq_desc_get_chip(desc);
> +	struct device *dev = &port->pcie->pdev->dev;
> +	u32 cause, unmask, status;
> +	int i;
> +
> +	chained_irq_enter(chip, desc);
> +
> +	cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF);
> +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> +	status = cause & unmask;
> +
> +	/* Process legacy INTx interrupts */
> +	for (i = 0; i < PCI_NUM_INTX; i++) {
> +		if (!(status & PCIE_INT_INTX(i)))
> +			continue;
> +
> +		if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL)
> +			dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A');
> +	}
> +
> +	chained_irq_exit(chip, desc);
> +}
> +
>  static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
>  {
>  	/* Interrupt support on mvebu emulated bridges is not implemented yet */
> @@ -1121,6 +1247,21 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
>  		port->io_attr = -1;
>  	}
>  
> +	/*
> +	 * Old DT bindings do not contain "intx" interrupt
> +	 * so do not fail probing driver when interrupt does not exist.
> +	 */
> +	port->intx_irq = of_irq_get_byname(child, "intx");
> +	if (port->intx_irq == -EPROBE_DEFER) {
> +		ret = port->intx_irq;
> +		goto err;
> +	}
> +	if (port->intx_irq <= 0) {
> +		dev_warn(dev, "%s: legacy INTx interrupts cannot be masked individually, "
> +			      "%pOF does not contain intx interrupt\n",
> +			 port->name, child);

Here you end up with a new warning on existing firmware. Is it
legitimate ? I would remove the dev_warn().

Rob certainly has more insightful advice on this.

Thanks,
Lorenzo

> +	}
> +
>  	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
>  	if (reset_gpio == -EPROBE_DEFER) {
>  		ret = reset_gpio;
> @@ -1317,6 +1458,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
>  
>  	for (i = 0; i < pcie->nports; i++) {
>  		struct mvebu_pcie_port *port = &pcie->ports[i];
> +		int irq = port->intx_irq;
>  
>  		child = port->dn;
>  		if (!child)
> @@ -1344,6 +1486,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
>  			continue;
>  		}
>  
> +		if (irq > 0) {
> +			ret = mvebu_pcie_init_irq_domain(port);
> +			if (ret) {
> +				dev_err(dev, "%s: cannot init irq domain\n",
> +					port->name);
> +				pci_bridge_emul_cleanup(&port->bridge);
> +				devm_iounmap(dev, port->base);
> +				port->base = NULL;
> +				mvebu_pcie_powerdown(port);
> +				continue;
> +			}
> +			irq_set_chained_handler_and_data(irq,
> +							 mvebu_pcie_irq_handler,
> +							 port);
> +		}
> +
>  		/*
>  		 * PCIe topology exported by mvebu hw is quite complicated. In
>  		 * reality has something like N fully independent host bridges
> @@ -1448,6 +1606,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
>  
>  	for (i = 0; i < pcie->nports; i++) {
>  		struct mvebu_pcie_port *port = &pcie->ports[i];
> +		int irq = port->intx_irq;
>  
>  		if (!port->base)
>  			continue;
> @@ -1458,7 +1617,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
>  		mvebu_writel(port, cmd, PCIE_CMD_OFF);
>  
>  		/* Mask all interrupt sources. */
> -		mvebu_writel(port, 0, PCIE_MASK_OFF);
> +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> +
> +		/* Clear all interrupt causes. */
> +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> +
> +		if (irq > 0)
> +			irq_set_chained_handler_and_data(irq, NULL, NULL);
> +
> +		/* Remove IRQ domains. */
> +		if (port->intx_irq_domain)
> +			irq_domain_remove(port->intx_irq_domain);
>  
>  		/* Free config space for emulated root bridge. */
>  		pci_bridge_emul_cleanup(&port->bridge);
> -- 
> 2.20.1
> 

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-02-11 17:19       ` Lorenzo Pieralisi
  0 siblings, 0 replies; 130+ messages in thread
From: Lorenzo Pieralisi @ 2022-02-11 17:19 UTC (permalink / raw)
  To: Pali Rohár, robh+dt
  Cc: Bjorn Helgaas, Thomas Petazzoni, Krzysztof Wilczyński,
	Marek Behún, Russell King, Marc Zyngier, linux-pci,
	linux-kernel, linux-arm-kernel

On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> This adds support for legacy INTx interrupts received from other PCIe
> devices and which are reported by a new INTx irq chip.
> 
> With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> interrupts.
> 
> Note that for this support, device tree files has to be properly adjusted
> to provide "interrupts" or "interrupts-extended" property with intx
> interrupt source, "interrupt-names" property with "intx" string and also
> 'interrupt-controller' subnode must be defined.
> 
> If device tree files do not provide these nodes then driver would work as
> before.

Nit: this information is not useful. DT rules are written in DT
bindings, not in kernel commit logs. All I am saying is that firmware
developers should not have to read this log to write firmware.

> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
>  1 file changed, 177 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> index 1e90ab888075..dbb6ecb4cb70 100644
> --- a/drivers/pci/controller/pci-mvebu.c
> +++ b/drivers/pci/controller/pci-mvebu.c
> @@ -54,9 +54,10 @@
>  	 PCIE_CONF_ADDR_EN)
>  #define PCIE_CONF_DATA_OFF	0x18fc
>  #define PCIE_INT_CAUSE_OFF	0x1900
> +#define PCIE_INT_UNMASK_OFF	0x1910

Nit: I understand it is tempting but here you are redefining or better
giving a proper label to a register. Separate patch please.

> +#define  PCIE_INT_INTX(i)		BIT(24+i)
>  #define  PCIE_INT_PM_PME		BIT(28)
> -#define PCIE_MASK_OFF		0x1910

See above.

> -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
>  #define PCIE_CTRL_OFF		0x1a00
>  #define  PCIE_CTRL_X1_MODE		0x0001
>  #define  PCIE_CTRL_RC_MODE		BIT(1)
> @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
>  	struct mvebu_pcie_window iowin;
>  	u32 saved_pcie_stat;
>  	struct resource regs;
> +	struct irq_domain *intx_irq_domain;
> +	raw_spinlock_t irq_lock;
> +	int intx_irq;
>  };
>  
>  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
>  
>  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
>  {
> -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
>  
>  	/* Setup PCIe controller to Root Complex mode. */
>  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
>  	/* Point PCIe unit MBUS decode windows to DRAM space. */
>  	mvebu_pcie_setup_wins(port);
>  
> -	/* Enable interrupt lines A-D. */
> -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> -	mask |= PCIE_MASK_ENABLE_INTS;
> -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> +	/* Mask all interrupt sources. */
> +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> +
> +	/* Clear all interrupt causes. */
> +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> +
> +	if (port->intx_irq <= 0) {
> +		/*
> +		 * When neither "summary" interrupt, nor "intx" interrupt was
> +		 * specified in DT then unmask all legacy INTx interrupts as in
> +		 * this case driver does not provide a way for masking and
> +		 * unmasking of individual legacy INTx interrupts. In this case
> +		 * all interrupts, including legacy INTx are reported via one
> +		 * shared GIC source and therefore kernel cannot distinguish
> +		 * which individual legacy INTx was triggered. These interrupts
> +		 * are shared, so it should not cause any issue. Just
> +		 * performance penalty as every PCIe interrupt handler needs to
> +		 * be called when some interrupt is triggered.
> +		 */

This comment applies to current mainline right (ie it describes how
current mainline handles INTx) ? IMO you should split it out in a
separate patch.

I understand it is hard but a patch is a logical _change_, this
comment is a change per se, it is a clarification on current
behaviour.

> +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> +	}
>  }
>  
>  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> @@ -924,6 +948,108 @@ static struct pci_ops mvebu_pcie_ops = {
>  	.write = mvebu_pcie_wr_conf,
>  };
>  
> +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> +{
> +	struct mvebu_pcie_port *port = d->domain->host_data;
> +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> +	unsigned long flags;
> +	u32 unmask;
> +
> +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> +	unmask &= ~PCIE_INT_INTX(hwirq);
> +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> +}
> +
> +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> +{
> +	struct mvebu_pcie_port *port = d->domain->host_data;
> +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> +	unsigned long flags;
> +	u32 unmask;
> +
> +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> +	unmask |= PCIE_INT_INTX(hwirq);
> +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> +}
> +
> +static struct irq_chip intx_irq_chip = {
> +	.name = "mvebu-INTx",
> +	.irq_mask = mvebu_pcie_intx_irq_mask,
> +	.irq_unmask = mvebu_pcie_intx_irq_unmask,
> +};
> +
> +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> +				   unsigned int virq, irq_hw_number_t hwirq)
> +{
> +	struct mvebu_pcie_port *port = h->host_data;
> +
> +	irq_set_status_flags(virq, IRQ_LEVEL);
> +	irq_set_chip_and_handler(virq, &intx_irq_chip, handle_level_irq);
> +	irq_set_chip_data(virq, port);
> +
> +	return 0;
> +}
> +
> +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> +	.map = mvebu_pcie_intx_irq_map,
> +	.xlate = irq_domain_xlate_onecell,
> +};
> +
> +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> +{
> +	struct device *dev = &port->pcie->pdev->dev;
> +	struct device_node *pcie_intc_node;
> +
> +	raw_spin_lock_init(&port->irq_lock);
> +
> +	pcie_intc_node = of_get_next_child(port->dn, NULL);
> +	if (!pcie_intc_node) {
> +		dev_err(dev, "No PCIe Intc node found for %s\n", port->name);
> +		return -ENODEV;
> +	}
> +
> +	port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
> +						      &mvebu_pcie_intx_irq_domain_ops,
> +						      port);
> +	of_node_put(pcie_intc_node);
> +	if (!port->intx_irq_domain) {
> +		dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name);
> +		return -ENOMEM;
> +	}
> +
> +	return 0;
> +}
> +
> +static void mvebu_pcie_irq_handler(struct irq_desc *desc)
> +{
> +	struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc);
> +	struct irq_chip *chip = irq_desc_get_chip(desc);
> +	struct device *dev = &port->pcie->pdev->dev;
> +	u32 cause, unmask, status;
> +	int i;
> +
> +	chained_irq_enter(chip, desc);
> +
> +	cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF);
> +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> +	status = cause & unmask;
> +
> +	/* Process legacy INTx interrupts */
> +	for (i = 0; i < PCI_NUM_INTX; i++) {
> +		if (!(status & PCIE_INT_INTX(i)))
> +			continue;
> +
> +		if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL)
> +			dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A');
> +	}
> +
> +	chained_irq_exit(chip, desc);
> +}
> +
>  static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
>  {
>  	/* Interrupt support on mvebu emulated bridges is not implemented yet */
> @@ -1121,6 +1247,21 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
>  		port->io_attr = -1;
>  	}
>  
> +	/*
> +	 * Old DT bindings do not contain "intx" interrupt
> +	 * so do not fail probing driver when interrupt does not exist.
> +	 */
> +	port->intx_irq = of_irq_get_byname(child, "intx");
> +	if (port->intx_irq == -EPROBE_DEFER) {
> +		ret = port->intx_irq;
> +		goto err;
> +	}
> +	if (port->intx_irq <= 0) {
> +		dev_warn(dev, "%s: legacy INTx interrupts cannot be masked individually, "
> +			      "%pOF does not contain intx interrupt\n",
> +			 port->name, child);

Here you end up with a new warning on existing firmware. Is it
legitimate ? I would remove the dev_warn().

Rob certainly has more insightful advice on this.

Thanks,
Lorenzo

> +	}
> +
>  	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
>  	if (reset_gpio == -EPROBE_DEFER) {
>  		ret = reset_gpio;
> @@ -1317,6 +1458,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
>  
>  	for (i = 0; i < pcie->nports; i++) {
>  		struct mvebu_pcie_port *port = &pcie->ports[i];
> +		int irq = port->intx_irq;
>  
>  		child = port->dn;
>  		if (!child)
> @@ -1344,6 +1486,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
>  			continue;
>  		}
>  
> +		if (irq > 0) {
> +			ret = mvebu_pcie_init_irq_domain(port);
> +			if (ret) {
> +				dev_err(dev, "%s: cannot init irq domain\n",
> +					port->name);
> +				pci_bridge_emul_cleanup(&port->bridge);
> +				devm_iounmap(dev, port->base);
> +				port->base = NULL;
> +				mvebu_pcie_powerdown(port);
> +				continue;
> +			}
> +			irq_set_chained_handler_and_data(irq,
> +							 mvebu_pcie_irq_handler,
> +							 port);
> +		}
> +
>  		/*
>  		 * PCIe topology exported by mvebu hw is quite complicated. In
>  		 * reality has something like N fully independent host bridges
> @@ -1448,6 +1606,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
>  
>  	for (i = 0; i < pcie->nports; i++) {
>  		struct mvebu_pcie_port *port = &pcie->ports[i];
> +		int irq = port->intx_irq;
>  
>  		if (!port->base)
>  			continue;
> @@ -1458,7 +1617,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
>  		mvebu_writel(port, cmd, PCIE_CMD_OFF);
>  
>  		/* Mask all interrupt sources. */
> -		mvebu_writel(port, 0, PCIE_MASK_OFF);
> +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> +
> +		/* Clear all interrupt causes. */
> +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> +
> +		if (irq > 0)
> +			irq_set_chained_handler_and_data(irq, NULL, NULL);
> +
> +		/* Remove IRQ domains. */
> +		if (port->intx_irq_domain)
> +			irq_domain_remove(port->intx_irq_domain);
>  
>  		/* Free config space for emulated root bridge. */
>  		pci_bridge_emul_cleanup(&port->bridge);
> -- 
> 2.20.1
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 00/11] PCI: mvebu: subsystem ids, AER and INTx
  2022-01-05 15:02 ` Pali Rohár
@ 2022-02-11 17:50   ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 130+ messages in thread
From: Lorenzo Pieralisi @ 2022-02-11 17:50 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Wed, Jan 05, 2022 at 04:02:28PM +0100, Pali Rohár wrote:
> This patch series extends pci-bridge-emul.c driver to emulate PCI Subsystem
> Vendor ID capability and PCIe extended capabilities. And then implement
> in pci-mvebu.c driver support for PCI Subsystem Vendor IDs, PCIe AER
> registers, support for legacy INTx interrupts, configuration for X1/X4
> mode and usage of new PCI child_ops API.
> 
> This patch series depends on other pci-mvebu and pci-bridge-emul patches from:
> https://lore.kernel.org/linux-pci/20220104153529.31647-1-pali@kernel.org/
Hi Pali,

I went through the series quickly and I don't think there is anything
controversial, posted some minor comments. Do not repost yet, I will
be back at v5.17-rc5 and work towards merging it for v5.18.

Lorenzo

> 
> Pali Rohár (9):
>   PCI: pci-bridge-emul: Add support for PCI Bridge Subsystem Vendor ID
>     capability
>   dt-bindings: PCI: mvebu: Add num-lanes property
>   PCI: mvebu: Correctly configure x1/x4 mode
>   PCI: mvebu: Add support for PCI Bridge Subsystem Vendor ID on emulated
>     bridge
>   PCI: mvebu: Add support for Advanced Error Reporting registers on
>     emulated bridge
>   PCI: mvebu: Use child_ops API
>   dt-bindings: PCI: mvebu: Update information about intx interrupts
>   PCI: mvebu: Implement support for legacy INTx interrupts
>   ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx
>     interrupts
> 
> Russell King (2):
>   PCI: pci-bridge-emul: Re-arrange register tests
>   PCI: pci-bridge-emul: Add support for PCIe extended capabilities
> 
>  .../devicetree/bindings/pci/mvebu-pci.txt     |  16 +
>  arch/arm/boot/dts/armada-385.dtsi             |  52 ++-
>  drivers/pci/controller/pci-mvebu.c            | 352 +++++++++++++++---
>  drivers/pci/pci-bridge-emul.c                 | 167 ++++++---
>  drivers/pci/pci-bridge-emul.h                 |  17 +
>  5 files changed, 494 insertions(+), 110 deletions(-)
> 
> -- 
> 2.20.1
> 

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 00/11] PCI: mvebu: subsystem ids, AER and INTx
@ 2022-02-11 17:50   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 130+ messages in thread
From: Lorenzo Pieralisi @ 2022-02-11 17:50 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Wed, Jan 05, 2022 at 04:02:28PM +0100, Pali Rohár wrote:
> This patch series extends pci-bridge-emul.c driver to emulate PCI Subsystem
> Vendor ID capability and PCIe extended capabilities. And then implement
> in pci-mvebu.c driver support for PCI Subsystem Vendor IDs, PCIe AER
> registers, support for legacy INTx interrupts, configuration for X1/X4
> mode and usage of new PCI child_ops API.
> 
> This patch series depends on other pci-mvebu and pci-bridge-emul patches from:
> https://lore.kernel.org/linux-pci/20220104153529.31647-1-pali@kernel.org/
Hi Pali,

I went through the series quickly and I don't think there is anything
controversial, posted some minor comments. Do not repost yet, I will
be back at v5.17-rc5 and work towards merging it for v5.18.

Lorenzo

> 
> Pali Rohár (9):
>   PCI: pci-bridge-emul: Add support for PCI Bridge Subsystem Vendor ID
>     capability
>   dt-bindings: PCI: mvebu: Add num-lanes property
>   PCI: mvebu: Correctly configure x1/x4 mode
>   PCI: mvebu: Add support for PCI Bridge Subsystem Vendor ID on emulated
>     bridge
>   PCI: mvebu: Add support for Advanced Error Reporting registers on
>     emulated bridge
>   PCI: mvebu: Use child_ops API
>   dt-bindings: PCI: mvebu: Update information about intx interrupts
>   PCI: mvebu: Implement support for legacy INTx interrupts
>   ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx
>     interrupts
> 
> Russell King (2):
>   PCI: pci-bridge-emul: Re-arrange register tests
>   PCI: pci-bridge-emul: Add support for PCIe extended capabilities
> 
>  .../devicetree/bindings/pci/mvebu-pci.txt     |  16 +
>  arch/arm/boot/dts/armada-385.dtsi             |  52 ++-
>  drivers/pci/controller/pci-mvebu.c            | 352 +++++++++++++++---
>  drivers/pci/pci-bridge-emul.c                 | 167 ++++++---
>  drivers/pci/pci-bridge-emul.h                 |  17 +
>  5 files changed, 494 insertions(+), 110 deletions(-)
> 
> -- 
> 2.20.1
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-02-11 17:19       ` Lorenzo Pieralisi
@ 2022-02-11 17:52         ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-11 17:52 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Friday 11 February 2022 17:19:17 Lorenzo Pieralisi wrote:
> On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> > This adds support for legacy INTx interrupts received from other PCIe
> > devices and which are reported by a new INTx irq chip.
> > 
> > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > interrupts.
> > 
> > Note that for this support, device tree files has to be properly adjusted
> > to provide "interrupts" or "interrupts-extended" property with intx
> > interrupt source, "interrupt-names" property with "intx" string and also
> > 'interrupt-controller' subnode must be defined.
> > 
> > If device tree files do not provide these nodes then driver would work as
> > before.
> 
> Nit: this information is not useful. DT rules are written in DT
> bindings, not in kernel commit logs. All I am saying is that firmware
> developers should not have to read this log to write firmware.

It was not intended for firmware developers, but for reviewers of this
patch to understand, what is happening in code and that with old DT
files this patch does not change driver behavior (= work as before).

> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > ---
> >  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
> >  1 file changed, 177 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > index 1e90ab888075..dbb6ecb4cb70 100644
> > --- a/drivers/pci/controller/pci-mvebu.c
> > +++ b/drivers/pci/controller/pci-mvebu.c
> > @@ -54,9 +54,10 @@
> >  	 PCIE_CONF_ADDR_EN)
> >  #define PCIE_CONF_DATA_OFF	0x18fc
> >  #define PCIE_INT_CAUSE_OFF	0x1900
> > +#define PCIE_INT_UNMASK_OFF	0x1910
> 
> Nit: I understand it is tempting but here you are redefining or better
> giving a proper label to a register. Separate patch please.

Ok!

> > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> >  #define  PCIE_INT_PM_PME		BIT(28)
> > -#define PCIE_MASK_OFF		0x1910
> 
> See above.
> 
> > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> >  #define PCIE_CTRL_OFF		0x1a00
> >  #define  PCIE_CTRL_X1_MODE		0x0001
> >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
> >  	struct mvebu_pcie_window iowin;
> >  	u32 saved_pcie_stat;
> >  	struct resource regs;
> > +	struct irq_domain *intx_irq_domain;
> > +	raw_spinlock_t irq_lock;
> > +	int intx_irq;
> >  };
> >  
> >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> >  
> >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> >  {
> > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> >  
> >  	/* Setup PCIe controller to Root Complex mode. */
> >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> >  	mvebu_pcie_setup_wins(port);
> >  
> > -	/* Enable interrupt lines A-D. */
> > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > -	mask |= PCIE_MASK_ENABLE_INTS;
> > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > +	/* Mask all interrupt sources. */
> > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > +
> > +	/* Clear all interrupt causes. */
> > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > +
> > +	if (port->intx_irq <= 0) {
> > +		/*
> > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > +		 * this case driver does not provide a way for masking and
> > +		 * unmasking of individual legacy INTx interrupts. In this case
> > +		 * all interrupts, including legacy INTx are reported via one
> > +		 * shared GIC source and therefore kernel cannot distinguish
> > +		 * which individual legacy INTx was triggered. These interrupts
> > +		 * are shared, so it should not cause any issue. Just
> > +		 * performance penalty as every PCIe interrupt handler needs to
> > +		 * be called when some interrupt is triggered.
> > +		 */
> 
> This comment applies to current mainline right (ie it describes how
> current mainline handles INTx) ? IMO you should split it out in a
> separate patch.

This above comment describe what happens in if-branch when intx_irq is
not set (as written in comment "when intx interrupt was not specified in
DT"). You are right that this is also the behavior in the current
mainline.

I'm not sure if this comment can be split out as support for "intx"
interrupt is in this patch.

> I understand it is hard but a patch is a logical _change_, this
> comment is a change per se, it is a clarification on current
> behaviour.

Ok, I could try to split this comment into two patches, but part about
if-branch comment needs to stay in "this" patch.

> > +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> > +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> > +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > +	}
> >  }
> >  
> >  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > @@ -924,6 +948,108 @@ static struct pci_ops mvebu_pcie_ops = {
> >  	.write = mvebu_pcie_wr_conf,
> >  };
> >  
> > +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> > +{
> > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > +	unsigned long flags;
> > +	u32 unmask;
> > +
> > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > +	unmask &= ~PCIE_INT_INTX(hwirq);
> > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > +}
> > +
> > +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> > +{
> > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > +	unsigned long flags;
> > +	u32 unmask;
> > +
> > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > +	unmask |= PCIE_INT_INTX(hwirq);
> > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > +}
> > +
> > +static struct irq_chip intx_irq_chip = {
> > +	.name = "mvebu-INTx",
> > +	.irq_mask = mvebu_pcie_intx_irq_mask,
> > +	.irq_unmask = mvebu_pcie_intx_irq_unmask,
> > +};
> > +
> > +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> > +				   unsigned int virq, irq_hw_number_t hwirq)
> > +{
> > +	struct mvebu_pcie_port *port = h->host_data;
> > +
> > +	irq_set_status_flags(virq, IRQ_LEVEL);
> > +	irq_set_chip_and_handler(virq, &intx_irq_chip, handle_level_irq);
> > +	irq_set_chip_data(virq, port);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> > +	.map = mvebu_pcie_intx_irq_map,
> > +	.xlate = irq_domain_xlate_onecell,
> > +};
> > +
> > +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> > +{
> > +	struct device *dev = &port->pcie->pdev->dev;
> > +	struct device_node *pcie_intc_node;
> > +
> > +	raw_spin_lock_init(&port->irq_lock);
> > +
> > +	pcie_intc_node = of_get_next_child(port->dn, NULL);
> > +	if (!pcie_intc_node) {
> > +		dev_err(dev, "No PCIe Intc node found for %s\n", port->name);
> > +		return -ENODEV;
> > +	}
> > +
> > +	port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
> > +						      &mvebu_pcie_intx_irq_domain_ops,
> > +						      port);
> > +	of_node_put(pcie_intc_node);
> > +	if (!port->intx_irq_domain) {
> > +		dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static void mvebu_pcie_irq_handler(struct irq_desc *desc)
> > +{
> > +	struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc);
> > +	struct irq_chip *chip = irq_desc_get_chip(desc);
> > +	struct device *dev = &port->pcie->pdev->dev;
> > +	u32 cause, unmask, status;
> > +	int i;
> > +
> > +	chained_irq_enter(chip, desc);
> > +
> > +	cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF);
> > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > +	status = cause & unmask;
> > +
> > +	/* Process legacy INTx interrupts */
> > +	for (i = 0; i < PCI_NUM_INTX; i++) {
> > +		if (!(status & PCIE_INT_INTX(i)))
> > +			continue;
> > +
> > +		if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL)
> > +			dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A');
> > +	}
> > +
> > +	chained_irq_exit(chip, desc);
> > +}
> > +
> >  static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> >  {
> >  	/* Interrupt support on mvebu emulated bridges is not implemented yet */
> > @@ -1121,6 +1247,21 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
> >  		port->io_attr = -1;
> >  	}
> >  
> > +	/*
> > +	 * Old DT bindings do not contain "intx" interrupt
> > +	 * so do not fail probing driver when interrupt does not exist.
> > +	 */
> > +	port->intx_irq = of_irq_get_byname(child, "intx");
> > +	if (port->intx_irq == -EPROBE_DEFER) {
> > +		ret = port->intx_irq;
> > +		goto err;
> > +	}
> > +	if (port->intx_irq <= 0) {
> > +		dev_warn(dev, "%s: legacy INTx interrupts cannot be masked individually, "
> > +			      "%pOF does not contain intx interrupt\n",
> > +			 port->name, child);
> 
> Here you end up with a new warning on existing firmware. Is it
> legitimate ? I would remove the dev_warn().

I added this warning in v2 because Marc wanted it.

Should I (again) remove it in v3?

> Rob certainly has more insightful advice on this.
> 
> Thanks,
> Lorenzo
> 
> > +	}
> > +
> >  	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
> >  	if (reset_gpio == -EPROBE_DEFER) {
> >  		ret = reset_gpio;
> > @@ -1317,6 +1458,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
> >  
> >  	for (i = 0; i < pcie->nports; i++) {
> >  		struct mvebu_pcie_port *port = &pcie->ports[i];
> > +		int irq = port->intx_irq;
> >  
> >  		child = port->dn;
> >  		if (!child)
> > @@ -1344,6 +1486,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
> >  			continue;
> >  		}
> >  
> > +		if (irq > 0) {
> > +			ret = mvebu_pcie_init_irq_domain(port);
> > +			if (ret) {
> > +				dev_err(dev, "%s: cannot init irq domain\n",
> > +					port->name);
> > +				pci_bridge_emul_cleanup(&port->bridge);
> > +				devm_iounmap(dev, port->base);
> > +				port->base = NULL;
> > +				mvebu_pcie_powerdown(port);
> > +				continue;
> > +			}
> > +			irq_set_chained_handler_and_data(irq,
> > +							 mvebu_pcie_irq_handler,
> > +							 port);
> > +		}
> > +
> >  		/*
> >  		 * PCIe topology exported by mvebu hw is quite complicated. In
> >  		 * reality has something like N fully independent host bridges
> > @@ -1448,6 +1606,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
> >  
> >  	for (i = 0; i < pcie->nports; i++) {
> >  		struct mvebu_pcie_port *port = &pcie->ports[i];
> > +		int irq = port->intx_irq;
> >  
> >  		if (!port->base)
> >  			continue;
> > @@ -1458,7 +1617,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
> >  		mvebu_writel(port, cmd, PCIE_CMD_OFF);
> >  
> >  		/* Mask all interrupt sources. */
> > -		mvebu_writel(port, 0, PCIE_MASK_OFF);
> > +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > +
> > +		/* Clear all interrupt causes. */
> > +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > +
> > +		if (irq > 0)
> > +			irq_set_chained_handler_and_data(irq, NULL, NULL);
> > +
> > +		/* Remove IRQ domains. */
> > +		if (port->intx_irq_domain)
> > +			irq_domain_remove(port->intx_irq_domain);
> >  
> >  		/* Free config space for emulated root bridge. */
> >  		pci_bridge_emul_cleanup(&port->bridge);
> > -- 
> > 2.20.1
> > 

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-02-11 17:52         ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-11 17:52 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Friday 11 February 2022 17:19:17 Lorenzo Pieralisi wrote:
> On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> > This adds support for legacy INTx interrupts received from other PCIe
> > devices and which are reported by a new INTx irq chip.
> > 
> > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > interrupts.
> > 
> > Note that for this support, device tree files has to be properly adjusted
> > to provide "interrupts" or "interrupts-extended" property with intx
> > interrupt source, "interrupt-names" property with "intx" string and also
> > 'interrupt-controller' subnode must be defined.
> > 
> > If device tree files do not provide these nodes then driver would work as
> > before.
> 
> Nit: this information is not useful. DT rules are written in DT
> bindings, not in kernel commit logs. All I am saying is that firmware
> developers should not have to read this log to write firmware.

It was not intended for firmware developers, but for reviewers of this
patch to understand, what is happening in code and that with old DT
files this patch does not change driver behavior (= work as before).

> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > ---
> >  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
> >  1 file changed, 177 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > index 1e90ab888075..dbb6ecb4cb70 100644
> > --- a/drivers/pci/controller/pci-mvebu.c
> > +++ b/drivers/pci/controller/pci-mvebu.c
> > @@ -54,9 +54,10 @@
> >  	 PCIE_CONF_ADDR_EN)
> >  #define PCIE_CONF_DATA_OFF	0x18fc
> >  #define PCIE_INT_CAUSE_OFF	0x1900
> > +#define PCIE_INT_UNMASK_OFF	0x1910
> 
> Nit: I understand it is tempting but here you are redefining or better
> giving a proper label to a register. Separate patch please.

Ok!

> > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> >  #define  PCIE_INT_PM_PME		BIT(28)
> > -#define PCIE_MASK_OFF		0x1910
> 
> See above.
> 
> > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> >  #define PCIE_CTRL_OFF		0x1a00
> >  #define  PCIE_CTRL_X1_MODE		0x0001
> >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
> >  	struct mvebu_pcie_window iowin;
> >  	u32 saved_pcie_stat;
> >  	struct resource regs;
> > +	struct irq_domain *intx_irq_domain;
> > +	raw_spinlock_t irq_lock;
> > +	int intx_irq;
> >  };
> >  
> >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> >  
> >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> >  {
> > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> >  
> >  	/* Setup PCIe controller to Root Complex mode. */
> >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> >  	mvebu_pcie_setup_wins(port);
> >  
> > -	/* Enable interrupt lines A-D. */
> > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > -	mask |= PCIE_MASK_ENABLE_INTS;
> > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > +	/* Mask all interrupt sources. */
> > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > +
> > +	/* Clear all interrupt causes. */
> > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > +
> > +	if (port->intx_irq <= 0) {
> > +		/*
> > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > +		 * this case driver does not provide a way for masking and
> > +		 * unmasking of individual legacy INTx interrupts. In this case
> > +		 * all interrupts, including legacy INTx are reported via one
> > +		 * shared GIC source and therefore kernel cannot distinguish
> > +		 * which individual legacy INTx was triggered. These interrupts
> > +		 * are shared, so it should not cause any issue. Just
> > +		 * performance penalty as every PCIe interrupt handler needs to
> > +		 * be called when some interrupt is triggered.
> > +		 */
> 
> This comment applies to current mainline right (ie it describes how
> current mainline handles INTx) ? IMO you should split it out in a
> separate patch.

This above comment describe what happens in if-branch when intx_irq is
not set (as written in comment "when intx interrupt was not specified in
DT"). You are right that this is also the behavior in the current
mainline.

I'm not sure if this comment can be split out as support for "intx"
interrupt is in this patch.

> I understand it is hard but a patch is a logical _change_, this
> comment is a change per se, it is a clarification on current
> behaviour.

Ok, I could try to split this comment into two patches, but part about
if-branch comment needs to stay in "this" patch.

> > +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> > +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> > +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > +	}
> >  }
> >  
> >  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > @@ -924,6 +948,108 @@ static struct pci_ops mvebu_pcie_ops = {
> >  	.write = mvebu_pcie_wr_conf,
> >  };
> >  
> > +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> > +{
> > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > +	unsigned long flags;
> > +	u32 unmask;
> > +
> > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > +	unmask &= ~PCIE_INT_INTX(hwirq);
> > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > +}
> > +
> > +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> > +{
> > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > +	unsigned long flags;
> > +	u32 unmask;
> > +
> > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > +	unmask |= PCIE_INT_INTX(hwirq);
> > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > +}
> > +
> > +static struct irq_chip intx_irq_chip = {
> > +	.name = "mvebu-INTx",
> > +	.irq_mask = mvebu_pcie_intx_irq_mask,
> > +	.irq_unmask = mvebu_pcie_intx_irq_unmask,
> > +};
> > +
> > +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> > +				   unsigned int virq, irq_hw_number_t hwirq)
> > +{
> > +	struct mvebu_pcie_port *port = h->host_data;
> > +
> > +	irq_set_status_flags(virq, IRQ_LEVEL);
> > +	irq_set_chip_and_handler(virq, &intx_irq_chip, handle_level_irq);
> > +	irq_set_chip_data(virq, port);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> > +	.map = mvebu_pcie_intx_irq_map,
> > +	.xlate = irq_domain_xlate_onecell,
> > +};
> > +
> > +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> > +{
> > +	struct device *dev = &port->pcie->pdev->dev;
> > +	struct device_node *pcie_intc_node;
> > +
> > +	raw_spin_lock_init(&port->irq_lock);
> > +
> > +	pcie_intc_node = of_get_next_child(port->dn, NULL);
> > +	if (!pcie_intc_node) {
> > +		dev_err(dev, "No PCIe Intc node found for %s\n", port->name);
> > +		return -ENODEV;
> > +	}
> > +
> > +	port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
> > +						      &mvebu_pcie_intx_irq_domain_ops,
> > +						      port);
> > +	of_node_put(pcie_intc_node);
> > +	if (!port->intx_irq_domain) {
> > +		dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static void mvebu_pcie_irq_handler(struct irq_desc *desc)
> > +{
> > +	struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc);
> > +	struct irq_chip *chip = irq_desc_get_chip(desc);
> > +	struct device *dev = &port->pcie->pdev->dev;
> > +	u32 cause, unmask, status;
> > +	int i;
> > +
> > +	chained_irq_enter(chip, desc);
> > +
> > +	cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF);
> > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > +	status = cause & unmask;
> > +
> > +	/* Process legacy INTx interrupts */
> > +	for (i = 0; i < PCI_NUM_INTX; i++) {
> > +		if (!(status & PCIE_INT_INTX(i)))
> > +			continue;
> > +
> > +		if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL)
> > +			dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A');
> > +	}
> > +
> > +	chained_irq_exit(chip, desc);
> > +}
> > +
> >  static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> >  {
> >  	/* Interrupt support on mvebu emulated bridges is not implemented yet */
> > @@ -1121,6 +1247,21 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
> >  		port->io_attr = -1;
> >  	}
> >  
> > +	/*
> > +	 * Old DT bindings do not contain "intx" interrupt
> > +	 * so do not fail probing driver when interrupt does not exist.
> > +	 */
> > +	port->intx_irq = of_irq_get_byname(child, "intx");
> > +	if (port->intx_irq == -EPROBE_DEFER) {
> > +		ret = port->intx_irq;
> > +		goto err;
> > +	}
> > +	if (port->intx_irq <= 0) {
> > +		dev_warn(dev, "%s: legacy INTx interrupts cannot be masked individually, "
> > +			      "%pOF does not contain intx interrupt\n",
> > +			 port->name, child);
> 
> Here you end up with a new warning on existing firmware. Is it
> legitimate ? I would remove the dev_warn().

I added this warning in v2 because Marc wanted it.

Should I (again) remove it in v3?

> Rob certainly has more insightful advice on this.
> 
> Thanks,
> Lorenzo
> 
> > +	}
> > +
> >  	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
> >  	if (reset_gpio == -EPROBE_DEFER) {
> >  		ret = reset_gpio;
> > @@ -1317,6 +1458,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
> >  
> >  	for (i = 0; i < pcie->nports; i++) {
> >  		struct mvebu_pcie_port *port = &pcie->ports[i];
> > +		int irq = port->intx_irq;
> >  
> >  		child = port->dn;
> >  		if (!child)
> > @@ -1344,6 +1486,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
> >  			continue;
> >  		}
> >  
> > +		if (irq > 0) {
> > +			ret = mvebu_pcie_init_irq_domain(port);
> > +			if (ret) {
> > +				dev_err(dev, "%s: cannot init irq domain\n",
> > +					port->name);
> > +				pci_bridge_emul_cleanup(&port->bridge);
> > +				devm_iounmap(dev, port->base);
> > +				port->base = NULL;
> > +				mvebu_pcie_powerdown(port);
> > +				continue;
> > +			}
> > +			irq_set_chained_handler_and_data(irq,
> > +							 mvebu_pcie_irq_handler,
> > +							 port);
> > +		}
> > +
> >  		/*
> >  		 * PCIe topology exported by mvebu hw is quite complicated. In
> >  		 * reality has something like N fully independent host bridges
> > @@ -1448,6 +1606,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
> >  
> >  	for (i = 0; i < pcie->nports; i++) {
> >  		struct mvebu_pcie_port *port = &pcie->ports[i];
> > +		int irq = port->intx_irq;
> >  
> >  		if (!port->base)
> >  			continue;
> > @@ -1458,7 +1617,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
> >  		mvebu_writel(port, cmd, PCIE_CMD_OFF);
> >  
> >  		/* Mask all interrupt sources. */
> > -		mvebu_writel(port, 0, PCIE_MASK_OFF);
> > +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > +
> > +		/* Clear all interrupt causes. */
> > +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > +
> > +		if (irq > 0)
> > +			irq_set_chained_handler_and_data(irq, NULL, NULL);
> > +
> > +		/* Remove IRQ domains. */
> > +		if (port->intx_irq_domain)
> > +			irq_domain_remove(port->intx_irq_domain);
> >  
> >  		/* Free config space for emulated root bridge. */
> >  		pci_bridge_emul_cleanup(&port->bridge);
> > -- 
> > 2.20.1
> > 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 00/11] PCI: mvebu: subsystem ids, AER and INTx
  2022-02-11 17:50   ` Lorenzo Pieralisi
@ 2022-02-11 18:01     ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-11 18:01 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Friday 11 February 2022 17:50:45 Lorenzo Pieralisi wrote:
> Do not repost yet, I will be back at v5.17-rc5 and work towards merging it for v5.18.

Ok!

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 00/11] PCI: mvebu: subsystem ids, AER and INTx
@ 2022-02-11 18:01     ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-11 18:01 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Friday 11 February 2022 17:50:45 Lorenzo Pieralisi wrote:
> Do not repost yet, I will be back at v5.17-rc5 and work towards merging it for v5.18.

Ok!

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-02-11 17:52         ` Pali Rohár
@ 2022-02-11 18:21           ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 130+ messages in thread
From: Lorenzo Pieralisi @ 2022-02-11 18:21 UTC (permalink / raw)
  To: Pali Rohár
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Fri, Feb 11, 2022 at 06:52:02PM +0100, Pali Rohár wrote:

[...]

> > > @@ -1121,6 +1247,21 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
> > >  		port->io_attr = -1;
> > >  	}
> > >  
> > > +	/*
> > > +	 * Old DT bindings do not contain "intx" interrupt
> > > +	 * so do not fail probing driver when interrupt does not exist.
> > > +	 */
> > > +	port->intx_irq = of_irq_get_byname(child, "intx");
> > > +	if (port->intx_irq == -EPROBE_DEFER) {
> > > +		ret = port->intx_irq;
> > > +		goto err;
> > > +	}
> > > +	if (port->intx_irq <= 0) {
> > > +		dev_warn(dev, "%s: legacy INTx interrupts cannot be masked individually, "
> > > +			      "%pOF does not contain intx interrupt\n",
> > > +			 port->name, child);
> > 
> > Here you end up with a new warning on existing firmware. Is it
> > legitimate ? I would remove the dev_warn().
> 
> I added this warning in v2 because Marc wanted it.
> 
> Should I (again) remove it in v3?

No, I asked a question and gave an opinion, I appreciate Marc's concern
so leave it (ie not everyone running a new kernel with new warnings on
existing firmware would be happy - maybe it is a good way of forcing a
firmware upgrade, you will tell me).

Lorenzo

> > Rob certainly has more insightful advice on this.
> > 
> > Thanks,
> > Lorenzo
> > 
> > > +	}
> > > +
> > >  	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
> > >  	if (reset_gpio == -EPROBE_DEFER) {
> > >  		ret = reset_gpio;
> > > @@ -1317,6 +1458,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
> > >  
> > >  	for (i = 0; i < pcie->nports; i++) {
> > >  		struct mvebu_pcie_port *port = &pcie->ports[i];
> > > +		int irq = port->intx_irq;
> > >  
> > >  		child = port->dn;
> > >  		if (!child)
> > > @@ -1344,6 +1486,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
> > >  			continue;
> > >  		}
> > >  
> > > +		if (irq > 0) {
> > > +			ret = mvebu_pcie_init_irq_domain(port);
> > > +			if (ret) {
> > > +				dev_err(dev, "%s: cannot init irq domain\n",
> > > +					port->name);
> > > +				pci_bridge_emul_cleanup(&port->bridge);
> > > +				devm_iounmap(dev, port->base);
> > > +				port->base = NULL;
> > > +				mvebu_pcie_powerdown(port);
> > > +				continue;
> > > +			}
> > > +			irq_set_chained_handler_and_data(irq,
> > > +							 mvebu_pcie_irq_handler,
> > > +							 port);
> > > +		}
> > > +
> > >  		/*
> > >  		 * PCIe topology exported by mvebu hw is quite complicated. In
> > >  		 * reality has something like N fully independent host bridges
> > > @@ -1448,6 +1606,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
> > >  
> > >  	for (i = 0; i < pcie->nports; i++) {
> > >  		struct mvebu_pcie_port *port = &pcie->ports[i];
> > > +		int irq = port->intx_irq;
> > >  
> > >  		if (!port->base)
> > >  			continue;
> > > @@ -1458,7 +1617,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
> > >  		mvebu_writel(port, cmd, PCIE_CMD_OFF);
> > >  
> > >  		/* Mask all interrupt sources. */
> > > -		mvebu_writel(port, 0, PCIE_MASK_OFF);
> > > +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > +
> > > +		/* Clear all interrupt causes. */
> > > +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > +
> > > +		if (irq > 0)
> > > +			irq_set_chained_handler_and_data(irq, NULL, NULL);
> > > +
> > > +		/* Remove IRQ domains. */
> > > +		if (port->intx_irq_domain)
> > > +			irq_domain_remove(port->intx_irq_domain);
> > >  
> > >  		/* Free config space for emulated root bridge. */
> > >  		pci_bridge_emul_cleanup(&port->bridge);
> > > -- 
> > > 2.20.1
> > > 

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-02-11 18:21           ` Lorenzo Pieralisi
  0 siblings, 0 replies; 130+ messages in thread
From: Lorenzo Pieralisi @ 2022-02-11 18:21 UTC (permalink / raw)
  To: Pali Rohár
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Fri, Feb 11, 2022 at 06:52:02PM +0100, Pali Rohár wrote:

[...]

> > > @@ -1121,6 +1247,21 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
> > >  		port->io_attr = -1;
> > >  	}
> > >  
> > > +	/*
> > > +	 * Old DT bindings do not contain "intx" interrupt
> > > +	 * so do not fail probing driver when interrupt does not exist.
> > > +	 */
> > > +	port->intx_irq = of_irq_get_byname(child, "intx");
> > > +	if (port->intx_irq == -EPROBE_DEFER) {
> > > +		ret = port->intx_irq;
> > > +		goto err;
> > > +	}
> > > +	if (port->intx_irq <= 0) {
> > > +		dev_warn(dev, "%s: legacy INTx interrupts cannot be masked individually, "
> > > +			      "%pOF does not contain intx interrupt\n",
> > > +			 port->name, child);
> > 
> > Here you end up with a new warning on existing firmware. Is it
> > legitimate ? I would remove the dev_warn().
> 
> I added this warning in v2 because Marc wanted it.
> 
> Should I (again) remove it in v3?

No, I asked a question and gave an opinion, I appreciate Marc's concern
so leave it (ie not everyone running a new kernel with new warnings on
existing firmware would be happy - maybe it is a good way of forcing a
firmware upgrade, you will tell me).

Lorenzo

> > Rob certainly has more insightful advice on this.
> > 
> > Thanks,
> > Lorenzo
> > 
> > > +	}
> > > +
> > >  	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
> > >  	if (reset_gpio == -EPROBE_DEFER) {
> > >  		ret = reset_gpio;
> > > @@ -1317,6 +1458,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
> > >  
> > >  	for (i = 0; i < pcie->nports; i++) {
> > >  		struct mvebu_pcie_port *port = &pcie->ports[i];
> > > +		int irq = port->intx_irq;
> > >  
> > >  		child = port->dn;
> > >  		if (!child)
> > > @@ -1344,6 +1486,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
> > >  			continue;
> > >  		}
> > >  
> > > +		if (irq > 0) {
> > > +			ret = mvebu_pcie_init_irq_domain(port);
> > > +			if (ret) {
> > > +				dev_err(dev, "%s: cannot init irq domain\n",
> > > +					port->name);
> > > +				pci_bridge_emul_cleanup(&port->bridge);
> > > +				devm_iounmap(dev, port->base);
> > > +				port->base = NULL;
> > > +				mvebu_pcie_powerdown(port);
> > > +				continue;
> > > +			}
> > > +			irq_set_chained_handler_and_data(irq,
> > > +							 mvebu_pcie_irq_handler,
> > > +							 port);
> > > +		}
> > > +
> > >  		/*
> > >  		 * PCIe topology exported by mvebu hw is quite complicated. In
> > >  		 * reality has something like N fully independent host bridges
> > > @@ -1448,6 +1606,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
> > >  
> > >  	for (i = 0; i < pcie->nports; i++) {
> > >  		struct mvebu_pcie_port *port = &pcie->ports[i];
> > > +		int irq = port->intx_irq;
> > >  
> > >  		if (!port->base)
> > >  			continue;
> > > @@ -1458,7 +1617,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
> > >  		mvebu_writel(port, cmd, PCIE_CMD_OFF);
> > >  
> > >  		/* Mask all interrupt sources. */
> > > -		mvebu_writel(port, 0, PCIE_MASK_OFF);
> > > +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > +
> > > +		/* Clear all interrupt causes. */
> > > +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > +
> > > +		if (irq > 0)
> > > +			irq_set_chained_handler_and_data(irq, NULL, NULL);
> > > +
> > > +		/* Remove IRQ domains. */
> > > +		if (port->intx_irq_domain)
> > > +			irq_domain_remove(port->intx_irq_domain);
> > >  
> > >  		/* Free config space for emulated root bridge. */
> > >  		pci_bridge_emul_cleanup(&port->bridge);
> > > -- 
> > > 2.20.1
> > > 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-02-11 18:21           ` Lorenzo Pieralisi
@ 2022-02-12 10:59             ` Marc Zyngier
  -1 siblings, 0 replies; 130+ messages in thread
From: Marc Zyngier @ 2022-02-12 10:59 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Pali Rohár, robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Fri, 11 Feb 2022 18:21:37 +0000,
Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> wrote:
> 
> On Fri, Feb 11, 2022 at 06:52:02PM +0100, Pali Rohár wrote:
> 
> [...]
> 
> > > > @@ -1121,6 +1247,21 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
> > > >  		port->io_attr = -1;
> > > >  	}
> > > >  
> > > > +	/*
> > > > +	 * Old DT bindings do not contain "intx" interrupt
> > > > +	 * so do not fail probing driver when interrupt does not exist.
> > > > +	 */
> > > > +	port->intx_irq = of_irq_get_byname(child, "intx");
> > > > +	if (port->intx_irq == -EPROBE_DEFER) {
> > > > +		ret = port->intx_irq;
> > > > +		goto err;
> > > > +	}
> > > > +	if (port->intx_irq <= 0) {
> > > > +		dev_warn(dev, "%s: legacy INTx interrupts cannot be masked individually, "
> > > > +			      "%pOF does not contain intx interrupt\n",
> > > > +			 port->name, child);
> > > 
> > > Here you end up with a new warning on existing firmware. Is it
> > > legitimate ? I would remove the dev_warn().
> > 
> > I added this warning in v2 because Marc wanted it.
> > 
> > Should I (again) remove it in v3?
> 
> No, I asked a question and gave an opinion, I appreciate Marc's concern
> so leave it (ie not everyone running a new kernel with new warnings on
> existing firmware would be happy - maybe it is a good way of forcing a
> firmware upgrade, you will tell me).

My concern is that short of being able to mask these interrupts, it is
possible for a device to assert an interrupt that no driver handles,
and the kernel spurious interrupt detector won't be able to shut it
up. At this stage, the machine is totally dead (screaming *level*
interrupt).

The dev_warn() could toned down to a dev_warn_once() though.

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-02-12 10:59             ` Marc Zyngier
  0 siblings, 0 replies; 130+ messages in thread
From: Marc Zyngier @ 2022-02-12 10:59 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Pali Rohár, robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	linux-pci, linux-kernel, linux-arm-kernel

On Fri, 11 Feb 2022 18:21:37 +0000,
Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> wrote:
> 
> On Fri, Feb 11, 2022 at 06:52:02PM +0100, Pali Rohár wrote:
> 
> [...]
> 
> > > > @@ -1121,6 +1247,21 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
> > > >  		port->io_attr = -1;
> > > >  	}
> > > >  
> > > > +	/*
> > > > +	 * Old DT bindings do not contain "intx" interrupt
> > > > +	 * so do not fail probing driver when interrupt does not exist.
> > > > +	 */
> > > > +	port->intx_irq = of_irq_get_byname(child, "intx");
> > > > +	if (port->intx_irq == -EPROBE_DEFER) {
> > > > +		ret = port->intx_irq;
> > > > +		goto err;
> > > > +	}
> > > > +	if (port->intx_irq <= 0) {
> > > > +		dev_warn(dev, "%s: legacy INTx interrupts cannot be masked individually, "
> > > > +			      "%pOF does not contain intx interrupt\n",
> > > > +			 port->name, child);
> > > 
> > > Here you end up with a new warning on existing firmware. Is it
> > > legitimate ? I would remove the dev_warn().
> > 
> > I added this warning in v2 because Marc wanted it.
> > 
> > Should I (again) remove it in v3?
> 
> No, I asked a question and gave an opinion, I appreciate Marc's concern
> so leave it (ie not everyone running a new kernel with new warnings on
> existing firmware would be happy - maybe it is a good way of forcing a
> firmware upgrade, you will tell me).

My concern is that short of being able to mask these interrupts, it is
possible for a device to assert an interrupt that no driver handles,
and the kernel spurious interrupt detector won't be able to shut it
up. At this stage, the machine is totally dead (screaming *level*
interrupt).

The dev_warn() could toned down to a dev_warn_once() though.

	M.

-- 
Without deviation from the norm, progress is not possible.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
  2022-01-12 15:18     ` Pali Rohár
@ 2022-02-14 15:07       ` Gregory CLEMENT
  -1 siblings, 0 replies; 130+ messages in thread
From: Gregory CLEMENT @ 2022-02-14 15:07 UTC (permalink / raw)
  To: Pali Rohár, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Marek Behún,
	Russell King, Andrew Lunn
  Cc: linux-pci, linux-kernel, linux-arm-kernel, devicetree

Hello Pali,

> With this change legacy INTA, INTB, INTC and INTD interrupts are reported
> separately and not mixed into one Linux virq source anymore.
>
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----

Is there any reason for not doing the same change in armada-380.dtsi ?

Grégory

>  1 file changed, 44 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
> index f0022d10c715..83392b92dae2 100644
> --- a/arch/arm/boot/dts/armada-385.dtsi
> +++ b/arch/arm/boot/dts/armada-385.dtsi
> @@ -69,16 +69,25 @@
>  				reg = <0x0800 0 0 0 0>;
>  				#address-cells = <3>;
>  				#size-cells = <2>;
> +				interrupt-names = "intx";
> +				interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
>  				#interrupt-cells = <1>;
>  				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
>  					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
>  				bus-range = <0x00 0xff>;
> -				interrupt-map-mask = <0 0 0 0>;
> -				interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-map-mask = <0 0 0 7>;
> +				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>;
>  				marvell,pcie-port = <0>;
>  				marvell,pcie-lane = <0>;
>  				clocks = <&gateclk 8>;
>  				status = "disabled";
> +				pcie1_intc: interrupt-controller {
> +					interrupt-controller;
> +					#interrupt-cells = <1>;
> +				};
>  			};
>  
>  			/* x1 port */
> @@ -88,16 +97,25 @@
>  				reg = <0x1000 0 0 0 0>;
>  				#address-cells = <3>;
>  				#size-cells = <2>;
> +				interrupt-names = "intx";
> +				interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
>  				#interrupt-cells = <1>;
>  				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
>  					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
>  				bus-range = <0x00 0xff>;
> -				interrupt-map-mask = <0 0 0 0>;
> -				interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-map-mask = <0 0 0 7>;
> +				interrupt-map = <0 0 0 1 &pcie2_intc 0>,
> +						<0 0 0 2 &pcie2_intc 1>,
> +						<0 0 0 3 &pcie2_intc 2>,
> +						<0 0 0 4 &pcie2_intc 3>;
>  				marvell,pcie-port = <1>;
>  				marvell,pcie-lane = <0>;
>  				clocks = <&gateclk 5>;
>  				status = "disabled";
> +				pcie2_intc: interrupt-controller {
> +					interrupt-controller;
> +					#interrupt-cells = <1>;
> +				};
>  			};
>  
>  			/* x1 port */
> @@ -107,16 +125,25 @@
>  				reg = <0x1800 0 0 0 0>;
>  				#address-cells = <3>;
>  				#size-cells = <2>;
> +				interrupt-names = "intx";
> +				interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
>  				#interrupt-cells = <1>;
>  				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
>  					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
>  				bus-range = <0x00 0xff>;
> -				interrupt-map-mask = <0 0 0 0>;
> -				interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-map-mask = <0 0 0 7>;
> +				interrupt-map = <0 0 0 1 &pcie3_intc 0>,
> +						<0 0 0 2 &pcie3_intc 1>,
> +						<0 0 0 3 &pcie3_intc 2>,
> +						<0 0 0 4 &pcie3_intc 3>;
>  				marvell,pcie-port = <2>;
>  				marvell,pcie-lane = <0>;
>  				clocks = <&gateclk 6>;
>  				status = "disabled";
> +				pcie3_intc: interrupt-controller {
> +					interrupt-controller;
> +					#interrupt-cells = <1>;
> +				};
>  			};
>  
>  			/*
> @@ -129,16 +156,25 @@
>  				reg = <0x2000 0 0 0 0>;
>  				#address-cells = <3>;
>  				#size-cells = <2>;
> +				interrupt-names = "intx";
> +				interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
>  				#interrupt-cells = <1>;
>  				ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
>  					  0x81000000 0 0 0x81000000 0x4 0 1 0>;
>  				bus-range = <0x00 0xff>;
> -				interrupt-map-mask = <0 0 0 0>;
> -				interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-map-mask = <0 0 0 7>;
> +				interrupt-map = <0 0 0 1 &pcie4_intc 0>,
> +						<0 0 0 2 &pcie4_intc 1>,
> +						<0 0 0 3 &pcie4_intc 2>,
> +						<0 0 0 4 &pcie4_intc 3>;
>  				marvell,pcie-port = <3>;
>  				marvell,pcie-lane = <0>;
>  				clocks = <&gateclk 7>;
>  				status = "disabled";
> +				pcie4_intc: interrupt-controller {
> +					interrupt-controller;
> +					#interrupt-cells = <1>;
> +				};
>  			};
>  		};
>  	};
> -- 
> 2.20.1
>

-- 
Gregory Clement, Bootlin
Embedded Linux and Kernel engineering
http://bootlin.com

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
@ 2022-02-14 15:07       ` Gregory CLEMENT
  0 siblings, 0 replies; 130+ messages in thread
From: Gregory CLEMENT @ 2022-02-14 15:07 UTC (permalink / raw)
  To: Pali Rohár, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Marek Behún,
	Russell King, Andrew Lunn
  Cc: linux-pci, linux-kernel, linux-arm-kernel, devicetree

Hello Pali,

> With this change legacy INTA, INTB, INTC and INTD interrupts are reported
> separately and not mixed into one Linux virq source anymore.
>
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----

Is there any reason for not doing the same change in armada-380.dtsi ?

Grégory

>  1 file changed, 44 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
> index f0022d10c715..83392b92dae2 100644
> --- a/arch/arm/boot/dts/armada-385.dtsi
> +++ b/arch/arm/boot/dts/armada-385.dtsi
> @@ -69,16 +69,25 @@
>  				reg = <0x0800 0 0 0 0>;
>  				#address-cells = <3>;
>  				#size-cells = <2>;
> +				interrupt-names = "intx";
> +				interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
>  				#interrupt-cells = <1>;
>  				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
>  					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
>  				bus-range = <0x00 0xff>;
> -				interrupt-map-mask = <0 0 0 0>;
> -				interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-map-mask = <0 0 0 7>;
> +				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>;
>  				marvell,pcie-port = <0>;
>  				marvell,pcie-lane = <0>;
>  				clocks = <&gateclk 8>;
>  				status = "disabled";
> +				pcie1_intc: interrupt-controller {
> +					interrupt-controller;
> +					#interrupt-cells = <1>;
> +				};
>  			};
>  
>  			/* x1 port */
> @@ -88,16 +97,25 @@
>  				reg = <0x1000 0 0 0 0>;
>  				#address-cells = <3>;
>  				#size-cells = <2>;
> +				interrupt-names = "intx";
> +				interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
>  				#interrupt-cells = <1>;
>  				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
>  					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
>  				bus-range = <0x00 0xff>;
> -				interrupt-map-mask = <0 0 0 0>;
> -				interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-map-mask = <0 0 0 7>;
> +				interrupt-map = <0 0 0 1 &pcie2_intc 0>,
> +						<0 0 0 2 &pcie2_intc 1>,
> +						<0 0 0 3 &pcie2_intc 2>,
> +						<0 0 0 4 &pcie2_intc 3>;
>  				marvell,pcie-port = <1>;
>  				marvell,pcie-lane = <0>;
>  				clocks = <&gateclk 5>;
>  				status = "disabled";
> +				pcie2_intc: interrupt-controller {
> +					interrupt-controller;
> +					#interrupt-cells = <1>;
> +				};
>  			};
>  
>  			/* x1 port */
> @@ -107,16 +125,25 @@
>  				reg = <0x1800 0 0 0 0>;
>  				#address-cells = <3>;
>  				#size-cells = <2>;
> +				interrupt-names = "intx";
> +				interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
>  				#interrupt-cells = <1>;
>  				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
>  					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
>  				bus-range = <0x00 0xff>;
> -				interrupt-map-mask = <0 0 0 0>;
> -				interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-map-mask = <0 0 0 7>;
> +				interrupt-map = <0 0 0 1 &pcie3_intc 0>,
> +						<0 0 0 2 &pcie3_intc 1>,
> +						<0 0 0 3 &pcie3_intc 2>,
> +						<0 0 0 4 &pcie3_intc 3>;
>  				marvell,pcie-port = <2>;
>  				marvell,pcie-lane = <0>;
>  				clocks = <&gateclk 6>;
>  				status = "disabled";
> +				pcie3_intc: interrupt-controller {
> +					interrupt-controller;
> +					#interrupt-cells = <1>;
> +				};
>  			};
>  
>  			/*
> @@ -129,16 +156,25 @@
>  				reg = <0x2000 0 0 0 0>;
>  				#address-cells = <3>;
>  				#size-cells = <2>;
> +				interrupt-names = "intx";
> +				interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
>  				#interrupt-cells = <1>;
>  				ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
>  					  0x81000000 0 0 0x81000000 0x4 0 1 0>;
>  				bus-range = <0x00 0xff>;
> -				interrupt-map-mask = <0 0 0 0>;
> -				interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-map-mask = <0 0 0 7>;
> +				interrupt-map = <0 0 0 1 &pcie4_intc 0>,
> +						<0 0 0 2 &pcie4_intc 1>,
> +						<0 0 0 3 &pcie4_intc 2>,
> +						<0 0 0 4 &pcie4_intc 3>;
>  				marvell,pcie-port = <3>;
>  				marvell,pcie-lane = <0>;
>  				clocks = <&gateclk 7>;
>  				status = "disabled";
> +				pcie4_intc: interrupt-controller {
> +					interrupt-controller;
> +					#interrupt-cells = <1>;
> +				};
>  			};
>  		};
>  	};
> -- 
> 2.20.1
>

-- 
Gregory Clement, Bootlin
Embedded Linux and Kernel engineering
http://bootlin.com

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
  2022-02-14 15:07       ` Gregory CLEMENT
@ 2022-02-14 15:09         ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-14 15:09 UTC (permalink / raw)
  To: Gregory CLEMENT
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Andrew Lunn, linux-pci, linux-kernel, linux-arm-kernel,
	devicetree

On Monday 14 February 2022 16:07:13 Gregory CLEMENT wrote:
> Hello Pali,
> 
> > With this change legacy INTA, INTB, INTC and INTD interrupts are reported
> > separately and not mixed into one Linux virq source anymore.
> >
> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > ---
> >  arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----
> 
> Is there any reason for not doing the same change in armada-380.dtsi ?

I do not have A380 HW, so I did this change only for A385 which I have tested.

> Grégory
> 
> >  1 file changed, 44 insertions(+), 8 deletions(-)
> >
> > diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
> > index f0022d10c715..83392b92dae2 100644
> > --- a/arch/arm/boot/dts/armada-385.dtsi
> > +++ b/arch/arm/boot/dts/armada-385.dtsi
> > @@ -69,16 +69,25 @@
> >  				reg = <0x0800 0 0 0 0>;
> >  				#address-cells = <3>;
> >  				#size-cells = <2>;
> > +				interrupt-names = "intx";
> > +				interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> >  				#interrupt-cells = <1>;
> >  				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
> >  					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
> >  				bus-range = <0x00 0xff>;
> > -				interrupt-map-mask = <0 0 0 0>;
> > -				interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> > +				interrupt-map-mask = <0 0 0 7>;
> > +				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>;
> >  				marvell,pcie-port = <0>;
> >  				marvell,pcie-lane = <0>;
> >  				clocks = <&gateclk 8>;
> >  				status = "disabled";
> > +				pcie1_intc: interrupt-controller {
> > +					interrupt-controller;
> > +					#interrupt-cells = <1>;
> > +				};
> >  			};
> >  
> >  			/* x1 port */
> > @@ -88,16 +97,25 @@
> >  				reg = <0x1000 0 0 0 0>;
> >  				#address-cells = <3>;
> >  				#size-cells = <2>;
> > +				interrupt-names = "intx";
> > +				interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> >  				#interrupt-cells = <1>;
> >  				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
> >  					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
> >  				bus-range = <0x00 0xff>;
> > -				interrupt-map-mask = <0 0 0 0>;
> > -				interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> > +				interrupt-map-mask = <0 0 0 7>;
> > +				interrupt-map = <0 0 0 1 &pcie2_intc 0>,
> > +						<0 0 0 2 &pcie2_intc 1>,
> > +						<0 0 0 3 &pcie2_intc 2>,
> > +						<0 0 0 4 &pcie2_intc 3>;
> >  				marvell,pcie-port = <1>;
> >  				marvell,pcie-lane = <0>;
> >  				clocks = <&gateclk 5>;
> >  				status = "disabled";
> > +				pcie2_intc: interrupt-controller {
> > +					interrupt-controller;
> > +					#interrupt-cells = <1>;
> > +				};
> >  			};
> >  
> >  			/* x1 port */
> > @@ -107,16 +125,25 @@
> >  				reg = <0x1800 0 0 0 0>;
> >  				#address-cells = <3>;
> >  				#size-cells = <2>;
> > +				interrupt-names = "intx";
> > +				interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> >  				#interrupt-cells = <1>;
> >  				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
> >  					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
> >  				bus-range = <0x00 0xff>;
> > -				interrupt-map-mask = <0 0 0 0>;
> > -				interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> > +				interrupt-map-mask = <0 0 0 7>;
> > +				interrupt-map = <0 0 0 1 &pcie3_intc 0>,
> > +						<0 0 0 2 &pcie3_intc 1>,
> > +						<0 0 0 3 &pcie3_intc 2>,
> > +						<0 0 0 4 &pcie3_intc 3>;
> >  				marvell,pcie-port = <2>;
> >  				marvell,pcie-lane = <0>;
> >  				clocks = <&gateclk 6>;
> >  				status = "disabled";
> > +				pcie3_intc: interrupt-controller {
> > +					interrupt-controller;
> > +					#interrupt-cells = <1>;
> > +				};
> >  			};
> >  
> >  			/*
> > @@ -129,16 +156,25 @@
> >  				reg = <0x2000 0 0 0 0>;
> >  				#address-cells = <3>;
> >  				#size-cells = <2>;
> > +				interrupt-names = "intx";
> > +				interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> >  				#interrupt-cells = <1>;
> >  				ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
> >  					  0x81000000 0 0 0x81000000 0x4 0 1 0>;
> >  				bus-range = <0x00 0xff>;
> > -				interrupt-map-mask = <0 0 0 0>;
> > -				interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> > +				interrupt-map-mask = <0 0 0 7>;
> > +				interrupt-map = <0 0 0 1 &pcie4_intc 0>,
> > +						<0 0 0 2 &pcie4_intc 1>,
> > +						<0 0 0 3 &pcie4_intc 2>,
> > +						<0 0 0 4 &pcie4_intc 3>;
> >  				marvell,pcie-port = <3>;
> >  				marvell,pcie-lane = <0>;
> >  				clocks = <&gateclk 7>;
> >  				status = "disabled";
> > +				pcie4_intc: interrupt-controller {
> > +					interrupt-controller;
> > +					#interrupt-cells = <1>;
> > +				};
> >  			};
> >  		};
> >  	};
> > -- 
> > 2.20.1
> >
> 
> -- 
> Gregory Clement, Bootlin
> Embedded Linux and Kernel engineering
> http://bootlin.com

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
@ 2022-02-14 15:09         ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-14 15:09 UTC (permalink / raw)
  To: Gregory CLEMENT
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Andrew Lunn, linux-pci, linux-kernel, linux-arm-kernel,
	devicetree

On Monday 14 February 2022 16:07:13 Gregory CLEMENT wrote:
> Hello Pali,
> 
> > With this change legacy INTA, INTB, INTC and INTD interrupts are reported
> > separately and not mixed into one Linux virq source anymore.
> >
> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > ---
> >  arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----
> 
> Is there any reason for not doing the same change in armada-380.dtsi ?

I do not have A380 HW, so I did this change only for A385 which I have tested.

> Grégory
> 
> >  1 file changed, 44 insertions(+), 8 deletions(-)
> >
> > diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
> > index f0022d10c715..83392b92dae2 100644
> > --- a/arch/arm/boot/dts/armada-385.dtsi
> > +++ b/arch/arm/boot/dts/armada-385.dtsi
> > @@ -69,16 +69,25 @@
> >  				reg = <0x0800 0 0 0 0>;
> >  				#address-cells = <3>;
> >  				#size-cells = <2>;
> > +				interrupt-names = "intx";
> > +				interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> >  				#interrupt-cells = <1>;
> >  				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
> >  					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
> >  				bus-range = <0x00 0xff>;
> > -				interrupt-map-mask = <0 0 0 0>;
> > -				interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> > +				interrupt-map-mask = <0 0 0 7>;
> > +				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>;
> >  				marvell,pcie-port = <0>;
> >  				marvell,pcie-lane = <0>;
> >  				clocks = <&gateclk 8>;
> >  				status = "disabled";
> > +				pcie1_intc: interrupt-controller {
> > +					interrupt-controller;
> > +					#interrupt-cells = <1>;
> > +				};
> >  			};
> >  
> >  			/* x1 port */
> > @@ -88,16 +97,25 @@
> >  				reg = <0x1000 0 0 0 0>;
> >  				#address-cells = <3>;
> >  				#size-cells = <2>;
> > +				interrupt-names = "intx";
> > +				interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> >  				#interrupt-cells = <1>;
> >  				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
> >  					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
> >  				bus-range = <0x00 0xff>;
> > -				interrupt-map-mask = <0 0 0 0>;
> > -				interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> > +				interrupt-map-mask = <0 0 0 7>;
> > +				interrupt-map = <0 0 0 1 &pcie2_intc 0>,
> > +						<0 0 0 2 &pcie2_intc 1>,
> > +						<0 0 0 3 &pcie2_intc 2>,
> > +						<0 0 0 4 &pcie2_intc 3>;
> >  				marvell,pcie-port = <1>;
> >  				marvell,pcie-lane = <0>;
> >  				clocks = <&gateclk 5>;
> >  				status = "disabled";
> > +				pcie2_intc: interrupt-controller {
> > +					interrupt-controller;
> > +					#interrupt-cells = <1>;
> > +				};
> >  			};
> >  
> >  			/* x1 port */
> > @@ -107,16 +125,25 @@
> >  				reg = <0x1800 0 0 0 0>;
> >  				#address-cells = <3>;
> >  				#size-cells = <2>;
> > +				interrupt-names = "intx";
> > +				interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> >  				#interrupt-cells = <1>;
> >  				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
> >  					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
> >  				bus-range = <0x00 0xff>;
> > -				interrupt-map-mask = <0 0 0 0>;
> > -				interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> > +				interrupt-map-mask = <0 0 0 7>;
> > +				interrupt-map = <0 0 0 1 &pcie3_intc 0>,
> > +						<0 0 0 2 &pcie3_intc 1>,
> > +						<0 0 0 3 &pcie3_intc 2>,
> > +						<0 0 0 4 &pcie3_intc 3>;
> >  				marvell,pcie-port = <2>;
> >  				marvell,pcie-lane = <0>;
> >  				clocks = <&gateclk 6>;
> >  				status = "disabled";
> > +				pcie3_intc: interrupt-controller {
> > +					interrupt-controller;
> > +					#interrupt-cells = <1>;
> > +				};
> >  			};
> >  
> >  			/*
> > @@ -129,16 +156,25 @@
> >  				reg = <0x2000 0 0 0 0>;
> >  				#address-cells = <3>;
> >  				#size-cells = <2>;
> > +				interrupt-names = "intx";
> > +				interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> >  				#interrupt-cells = <1>;
> >  				ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
> >  					  0x81000000 0 0 0x81000000 0x4 0 1 0>;
> >  				bus-range = <0x00 0xff>;
> > -				interrupt-map-mask = <0 0 0 0>;
> > -				interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> > +				interrupt-map-mask = <0 0 0 7>;
> > +				interrupt-map = <0 0 0 1 &pcie4_intc 0>,
> > +						<0 0 0 2 &pcie4_intc 1>,
> > +						<0 0 0 3 &pcie4_intc 2>,
> > +						<0 0 0 4 &pcie4_intc 3>;
> >  				marvell,pcie-port = <3>;
> >  				marvell,pcie-lane = <0>;
> >  				clocks = <&gateclk 7>;
> >  				status = "disabled";
> > +				pcie4_intc: interrupt-controller {
> > +					interrupt-controller;
> > +					#interrupt-cells = <1>;
> > +				};
> >  			};
> >  		};
> >  	};
> > -- 
> > 2.20.1
> >
> 
> -- 
> Gregory Clement, Bootlin
> Embedded Linux and Kernel engineering
> http://bootlin.com

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
  2022-02-14 15:09         ` Pali Rohár
@ 2022-02-14 15:26           ` Gregory CLEMENT
  -1 siblings, 0 replies; 130+ messages in thread
From: Gregory CLEMENT @ 2022-02-14 15:26 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Andrew Lunn, linux-pci, linux-kernel, linux-arm-kernel,
	devicetree

Hello,

> On Monday 14 February 2022 16:07:13 Gregory CLEMENT wrote:
>> Hello Pali,
>> 
>> > With this change legacy INTA, INTB, INTC and INTD interrupts are reported
>> > separately and not mixed into one Linux virq source anymore.
>> >
>> > Signed-off-by: Pali Rohár <pali@kernel.org>
>> > ---
>> >  arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----
>> 
>> Is there any reason for not doing the same change in armada-380.dtsi ?
>
> I do not have A380 HW, so I did this change only for A385 which I have
> tested.

OK fair enough.

So you can add my
Acked-by: Gregory CLEMENT <gregory.clement@bootlin.com>

Moreover to keep biscetability  this patch should be merged after the
support in the driver. So the easier is to let merge it through the PCI
subsystem with the other patches from this series. I do not think there
will be any other changes in this file so there won't be any merge
conflicts.

Thanks,

Grégory


>
>> Grégory
>> 
>> >  1 file changed, 44 insertions(+), 8 deletions(-)
>> >
>> > diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
>> > index f0022d10c715..83392b92dae2 100644
>> > --- a/arch/arm/boot/dts/armada-385.dtsi
>> > +++ b/arch/arm/boot/dts/armada-385.dtsi
>> > @@ -69,16 +69,25 @@
>> >  				reg = <0x0800 0 0 0 0>;
>> >  				#address-cells = <3>;
>> >  				#size-cells = <2>;
>> > +				interrupt-names = "intx";
>> > +				interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
>> >  				#interrupt-cells = <1>;
>> >  				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
>> >  					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
>> >  				bus-range = <0x00 0xff>;
>> > -				interrupt-map-mask = <0 0 0 0>;
>> > -				interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
>> > +				interrupt-map-mask = <0 0 0 7>;
>> > +				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>;
>> >  				marvell,pcie-port = <0>;
>> >  				marvell,pcie-lane = <0>;
>> >  				clocks = <&gateclk 8>;
>> >  				status = "disabled";
>> > +				pcie1_intc: interrupt-controller {
>> > +					interrupt-controller;
>> > +					#interrupt-cells = <1>;
>> > +				};
>> >  			};
>> >  
>> >  			/* x1 port */
>> > @@ -88,16 +97,25 @@
>> >  				reg = <0x1000 0 0 0 0>;
>> >  				#address-cells = <3>;
>> >  				#size-cells = <2>;
>> > +				interrupt-names = "intx";
>> > +				interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
>> >  				#interrupt-cells = <1>;
>> >  				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
>> >  					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
>> >  				bus-range = <0x00 0xff>;
>> > -				interrupt-map-mask = <0 0 0 0>;
>> > -				interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
>> > +				interrupt-map-mask = <0 0 0 7>;
>> > +				interrupt-map = <0 0 0 1 &pcie2_intc 0>,
>> > +						<0 0 0 2 &pcie2_intc 1>,
>> > +						<0 0 0 3 &pcie2_intc 2>,
>> > +						<0 0 0 4 &pcie2_intc 3>;
>> >  				marvell,pcie-port = <1>;
>> >  				marvell,pcie-lane = <0>;
>> >  				clocks = <&gateclk 5>;
>> >  				status = "disabled";
>> > +				pcie2_intc: interrupt-controller {
>> > +					interrupt-controller;
>> > +					#interrupt-cells = <1>;
>> > +				};
>> >  			};
>> >  
>> >  			/* x1 port */
>> > @@ -107,16 +125,25 @@
>> >  				reg = <0x1800 0 0 0 0>;
>> >  				#address-cells = <3>;
>> >  				#size-cells = <2>;
>> > +				interrupt-names = "intx";
>> > +				interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
>> >  				#interrupt-cells = <1>;
>> >  				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
>> >  					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
>> >  				bus-range = <0x00 0xff>;
>> > -				interrupt-map-mask = <0 0 0 0>;
>> > -				interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
>> > +				interrupt-map-mask = <0 0 0 7>;
>> > +				interrupt-map = <0 0 0 1 &pcie3_intc 0>,
>> > +						<0 0 0 2 &pcie3_intc 1>,
>> > +						<0 0 0 3 &pcie3_intc 2>,
>> > +						<0 0 0 4 &pcie3_intc 3>;
>> >  				marvell,pcie-port = <2>;
>> >  				marvell,pcie-lane = <0>;
>> >  				clocks = <&gateclk 6>;
>> >  				status = "disabled";
>> > +				pcie3_intc: interrupt-controller {
>> > +					interrupt-controller;
>> > +					#interrupt-cells = <1>;
>> > +				};
>> >  			};
>> >  
>> >  			/*
>> > @@ -129,16 +156,25 @@
>> >  				reg = <0x2000 0 0 0 0>;
>> >  				#address-cells = <3>;
>> >  				#size-cells = <2>;
>> > +				interrupt-names = "intx";
>> > +				interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
>> >  				#interrupt-cells = <1>;
>> >  				ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
>> >  					  0x81000000 0 0 0x81000000 0x4 0 1 0>;
>> >  				bus-range = <0x00 0xff>;
>> > -				interrupt-map-mask = <0 0 0 0>;
>> > -				interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
>> > +				interrupt-map-mask = <0 0 0 7>;
>> > +				interrupt-map = <0 0 0 1 &pcie4_intc 0>,
>> > +						<0 0 0 2 &pcie4_intc 1>,
>> > +						<0 0 0 3 &pcie4_intc 2>,
>> > +						<0 0 0 4 &pcie4_intc 3>;
>> >  				marvell,pcie-port = <3>;
>> >  				marvell,pcie-lane = <0>;
>> >  				clocks = <&gateclk 7>;
>> >  				status = "disabled";
>> > +				pcie4_intc: interrupt-controller {
>> > +					interrupt-controller;
>> > +					#interrupt-cells = <1>;
>> > +				};
>> >  			};
>> >  		};
>> >  	};
>> > -- 
>> > 2.20.1
>> >
>> 
>> -- 
>> Gregory Clement, Bootlin
>> Embedded Linux and Kernel engineering
>> http://bootlin.com

-- 
Gregory Clement, Bootlin
Embedded Linux and Kernel engineering
http://bootlin.com

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
@ 2022-02-14 15:26           ` Gregory CLEMENT
  0 siblings, 0 replies; 130+ messages in thread
From: Gregory CLEMENT @ 2022-02-14 15:26 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Andrew Lunn, linux-pci, linux-kernel, linux-arm-kernel,
	devicetree

Hello,

> On Monday 14 February 2022 16:07:13 Gregory CLEMENT wrote:
>> Hello Pali,
>> 
>> > With this change legacy INTA, INTB, INTC and INTD interrupts are reported
>> > separately and not mixed into one Linux virq source anymore.
>> >
>> > Signed-off-by: Pali Rohár <pali@kernel.org>
>> > ---
>> >  arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----
>> 
>> Is there any reason for not doing the same change in armada-380.dtsi ?
>
> I do not have A380 HW, so I did this change only for A385 which I have
> tested.

OK fair enough.

So you can add my
Acked-by: Gregory CLEMENT <gregory.clement@bootlin.com>

Moreover to keep biscetability  this patch should be merged after the
support in the driver. So the easier is to let merge it through the PCI
subsystem with the other patches from this series. I do not think there
will be any other changes in this file so there won't be any merge
conflicts.

Thanks,

Grégory


>
>> Grégory
>> 
>> >  1 file changed, 44 insertions(+), 8 deletions(-)
>> >
>> > diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
>> > index f0022d10c715..83392b92dae2 100644
>> > --- a/arch/arm/boot/dts/armada-385.dtsi
>> > +++ b/arch/arm/boot/dts/armada-385.dtsi
>> > @@ -69,16 +69,25 @@
>> >  				reg = <0x0800 0 0 0 0>;
>> >  				#address-cells = <3>;
>> >  				#size-cells = <2>;
>> > +				interrupt-names = "intx";
>> > +				interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
>> >  				#interrupt-cells = <1>;
>> >  				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
>> >  					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
>> >  				bus-range = <0x00 0xff>;
>> > -				interrupt-map-mask = <0 0 0 0>;
>> > -				interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
>> > +				interrupt-map-mask = <0 0 0 7>;
>> > +				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>;
>> >  				marvell,pcie-port = <0>;
>> >  				marvell,pcie-lane = <0>;
>> >  				clocks = <&gateclk 8>;
>> >  				status = "disabled";
>> > +				pcie1_intc: interrupt-controller {
>> > +					interrupt-controller;
>> > +					#interrupt-cells = <1>;
>> > +				};
>> >  			};
>> >  
>> >  			/* x1 port */
>> > @@ -88,16 +97,25 @@
>> >  				reg = <0x1000 0 0 0 0>;
>> >  				#address-cells = <3>;
>> >  				#size-cells = <2>;
>> > +				interrupt-names = "intx";
>> > +				interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
>> >  				#interrupt-cells = <1>;
>> >  				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
>> >  					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
>> >  				bus-range = <0x00 0xff>;
>> > -				interrupt-map-mask = <0 0 0 0>;
>> > -				interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
>> > +				interrupt-map-mask = <0 0 0 7>;
>> > +				interrupt-map = <0 0 0 1 &pcie2_intc 0>,
>> > +						<0 0 0 2 &pcie2_intc 1>,
>> > +						<0 0 0 3 &pcie2_intc 2>,
>> > +						<0 0 0 4 &pcie2_intc 3>;
>> >  				marvell,pcie-port = <1>;
>> >  				marvell,pcie-lane = <0>;
>> >  				clocks = <&gateclk 5>;
>> >  				status = "disabled";
>> > +				pcie2_intc: interrupt-controller {
>> > +					interrupt-controller;
>> > +					#interrupt-cells = <1>;
>> > +				};
>> >  			};
>> >  
>> >  			/* x1 port */
>> > @@ -107,16 +125,25 @@
>> >  				reg = <0x1800 0 0 0 0>;
>> >  				#address-cells = <3>;
>> >  				#size-cells = <2>;
>> > +				interrupt-names = "intx";
>> > +				interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
>> >  				#interrupt-cells = <1>;
>> >  				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
>> >  					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
>> >  				bus-range = <0x00 0xff>;
>> > -				interrupt-map-mask = <0 0 0 0>;
>> > -				interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
>> > +				interrupt-map-mask = <0 0 0 7>;
>> > +				interrupt-map = <0 0 0 1 &pcie3_intc 0>,
>> > +						<0 0 0 2 &pcie3_intc 1>,
>> > +						<0 0 0 3 &pcie3_intc 2>,
>> > +						<0 0 0 4 &pcie3_intc 3>;
>> >  				marvell,pcie-port = <2>;
>> >  				marvell,pcie-lane = <0>;
>> >  				clocks = <&gateclk 6>;
>> >  				status = "disabled";
>> > +				pcie3_intc: interrupt-controller {
>> > +					interrupt-controller;
>> > +					#interrupt-cells = <1>;
>> > +				};
>> >  			};
>> >  
>> >  			/*
>> > @@ -129,16 +156,25 @@
>> >  				reg = <0x2000 0 0 0 0>;
>> >  				#address-cells = <3>;
>> >  				#size-cells = <2>;
>> > +				interrupt-names = "intx";
>> > +				interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
>> >  				#interrupt-cells = <1>;
>> >  				ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
>> >  					  0x81000000 0 0 0x81000000 0x4 0 1 0>;
>> >  				bus-range = <0x00 0xff>;
>> > -				interrupt-map-mask = <0 0 0 0>;
>> > -				interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
>> > +				interrupt-map-mask = <0 0 0 7>;
>> > +				interrupt-map = <0 0 0 1 &pcie4_intc 0>,
>> > +						<0 0 0 2 &pcie4_intc 1>,
>> > +						<0 0 0 3 &pcie4_intc 2>,
>> > +						<0 0 0 4 &pcie4_intc 3>;
>> >  				marvell,pcie-port = <3>;
>> >  				marvell,pcie-lane = <0>;
>> >  				clocks = <&gateclk 7>;
>> >  				status = "disabled";
>> > +				pcie4_intc: interrupt-controller {
>> > +					interrupt-controller;
>> > +					#interrupt-cells = <1>;
>> > +				};
>> >  			};
>> >  		};
>> >  	};
>> > -- 
>> > 2.20.1
>> >
>> 
>> -- 
>> Gregory Clement, Bootlin
>> Embedded Linux and Kernel engineering
>> http://bootlin.com

-- 
Gregory Clement, Bootlin
Embedded Linux and Kernel engineering
http://bootlin.com

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
       [not found]           ` <CAEzXK1qYKVk7QiSY_DwqkZ7WV6WU06WBtiqZx0JJCc+mOP-7Kg@mail.gmail.com>
@ 2022-02-15 10:48               ` Luís Mendes
  0 siblings, 0 replies; 130+ messages in thread
From: Luís Mendes @ 2022-02-15 10:48 UTC (permalink / raw)
  To: Gregory CLEMENT
  Cc: Pali Rohár, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Marek Behún,
	Russell King, Andrew Lunn, Linux PCI, Linux Kernel Mailing List,
	linux-arm-kernel, devicetree

Hello,

Sorry for jumping in the conversation, but I read this thread and I
have an Armada A388 HW so I can test it, if desired.

Luís


On Tue, Feb 15, 2022 at 10:47 AM Luís Mendes <luis.p.mendes@gmail.com> wrote:
>
> Hello,
>
> Sorry for jumping in the conversation, but I read this thread and I have an Armada A388 HW so I can test it, if desired.
>
> Luís
>
> On Mon, Feb 14, 2022 at 7:57 PM Gregory CLEMENT <gregory.clement@bootlin.com> wrote:
>>
>> Hello,
>>
>> > On Monday 14 February 2022 16:07:13 Gregory CLEMENT wrote:
>> >> Hello Pali,
>> >>
>> >> > With this change legacy INTA, INTB, INTC and INTD interrupts are reported
>> >> > separately and not mixed into one Linux virq source anymore.
>> >> >
>> >> > Signed-off-by: Pali Rohár <pali@kernel.org>
>> >> > ---
>> >> >  arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----
>> >>
>> >> Is there any reason for not doing the same change in armada-380.dtsi ?
>> >
>> > I do not have A380 HW, so I did this change only for A385 which I have
>> > tested.
>>
>> OK fair enough.
>>
>> So you can add my
>> Acked-by: Gregory CLEMENT <gregory.clement@bootlin.com>
>>
>> Moreover to keep biscetability  this patch should be merged after the
>> support in the driver. So the easier is to let merge it through the PCI
>> subsystem with the other patches from this series. I do not think there
>> will be any other changes in this file so there won't be any merge
>> conflicts.
>>
>> Thanks,
>>
>> Grégory
>>
>>
>> >
>> >> Grégory
>> >>
>> >> >  1 file changed, 44 insertions(+), 8 deletions(-)
>> >> >
>> >> > diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
>> >> > index f0022d10c715..83392b92dae2 100644
>> >> > --- a/arch/arm/boot/dts/armada-385.dtsi
>> >> > +++ b/arch/arm/boot/dts/armada-385.dtsi
>> >> > @@ -69,16 +69,25 @@
>> >> >                            reg = <0x0800 0 0 0 0>;
>> >> >                            #address-cells = <3>;
>> >> >                            #size-cells = <2>;
>> >> > +                          interrupt-names = "intx";
>> >> > +                          interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
>> >> >                            #interrupt-cells = <1>;
>> >> >                            ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
>> >> >                                      0x81000000 0 0 0x81000000 0x1 0 1 0>;
>> >> >                            bus-range = <0x00 0xff>;
>> >> > -                          interrupt-map-mask = <0 0 0 0>;
>> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
>> >> > +                          interrupt-map-mask = <0 0 0 7>;
>> >> > +                          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>;
>> >> >                            marvell,pcie-port = <0>;
>> >> >                            marvell,pcie-lane = <0>;
>> >> >                            clocks = <&gateclk 8>;
>> >> >                            status = "disabled";
>> >> > +                          pcie1_intc: interrupt-controller {
>> >> > +                                  interrupt-controller;
>> >> > +                                  #interrupt-cells = <1>;
>> >> > +                          };
>> >> >                    };
>> >> >
>> >> >                    /* x1 port */
>> >> > @@ -88,16 +97,25 @@
>> >> >                            reg = <0x1000 0 0 0 0>;
>> >> >                            #address-cells = <3>;
>> >> >                            #size-cells = <2>;
>> >> > +                          interrupt-names = "intx";
>> >> > +                          interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
>> >> >                            #interrupt-cells = <1>;
>> >> >                            ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
>> >> >                                      0x81000000 0 0 0x81000000 0x2 0 1 0>;
>> >> >                            bus-range = <0x00 0xff>;
>> >> > -                          interrupt-map-mask = <0 0 0 0>;
>> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
>> >> > +                          interrupt-map-mask = <0 0 0 7>;
>> >> > +                          interrupt-map = <0 0 0 1 &pcie2_intc 0>,
>> >> > +                                          <0 0 0 2 &pcie2_intc 1>,
>> >> > +                                          <0 0 0 3 &pcie2_intc 2>,
>> >> > +                                          <0 0 0 4 &pcie2_intc 3>;
>> >> >                            marvell,pcie-port = <1>;
>> >> >                            marvell,pcie-lane = <0>;
>> >> >                            clocks = <&gateclk 5>;
>> >> >                            status = "disabled";
>> >> > +                          pcie2_intc: interrupt-controller {
>> >> > +                                  interrupt-controller;
>> >> > +                                  #interrupt-cells = <1>;
>> >> > +                          };
>> >> >                    };
>> >> >
>> >> >                    /* x1 port */
>> >> > @@ -107,16 +125,25 @@
>> >> >                            reg = <0x1800 0 0 0 0>;
>> >> >                            #address-cells = <3>;
>> >> >                            #size-cells = <2>;
>> >> > +                          interrupt-names = "intx";
>> >> > +                          interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
>> >> >                            #interrupt-cells = <1>;
>> >> >                            ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
>> >> >                                      0x81000000 0 0 0x81000000 0x3 0 1 0>;
>> >> >                            bus-range = <0x00 0xff>;
>> >> > -                          interrupt-map-mask = <0 0 0 0>;
>> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
>> >> > +                          interrupt-map-mask = <0 0 0 7>;
>> >> > +                          interrupt-map = <0 0 0 1 &pcie3_intc 0>,
>> >> > +                                          <0 0 0 2 &pcie3_intc 1>,
>> >> > +                                          <0 0 0 3 &pcie3_intc 2>,
>> >> > +                                          <0 0 0 4 &pcie3_intc 3>;
>> >> >                            marvell,pcie-port = <2>;
>> >> >                            marvell,pcie-lane = <0>;
>> >> >                            clocks = <&gateclk 6>;
>> >> >                            status = "disabled";
>> >> > +                          pcie3_intc: interrupt-controller {
>> >> > +                                  interrupt-controller;
>> >> > +                                  #interrupt-cells = <1>;
>> >> > +                          };
>> >> >                    };
>> >> >
>> >> >                    /*
>> >> > @@ -129,16 +156,25 @@
>> >> >                            reg = <0x2000 0 0 0 0>;
>> >> >                            #address-cells = <3>;
>> >> >                            #size-cells = <2>;
>> >> > +                          interrupt-names = "intx";
>> >> > +                          interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
>> >> >                            #interrupt-cells = <1>;
>> >> >                            ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
>> >> >                                      0x81000000 0 0 0x81000000 0x4 0 1 0>;
>> >> >                            bus-range = <0x00 0xff>;
>> >> > -                          interrupt-map-mask = <0 0 0 0>;
>> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
>> >> > +                          interrupt-map-mask = <0 0 0 7>;
>> >> > +                          interrupt-map = <0 0 0 1 &pcie4_intc 0>,
>> >> > +                                          <0 0 0 2 &pcie4_intc 1>,
>> >> > +                                          <0 0 0 3 &pcie4_intc 2>,
>> >> > +                                          <0 0 0 4 &pcie4_intc 3>;
>> >> >                            marvell,pcie-port = <3>;
>> >> >                            marvell,pcie-lane = <0>;
>> >> >                            clocks = <&gateclk 7>;
>> >> >                            status = "disabled";
>> >> > +                          pcie4_intc: interrupt-controller {
>> >> > +                                  interrupt-controller;
>> >> > +                                  #interrupt-cells = <1>;
>> >> > +                          };
>> >> >                    };
>> >> >            };
>> >> >    };
>> >> > --
>> >> > 2.20.1
>> >> >
>> >>
>> >> --
>> >> Gregory Clement, Bootlin
>> >> Embedded Linux and Kernel engineering
>> >> http://bootlin.com
>>
>> --
>> Gregory Clement, Bootlin
>> Embedded Linux and Kernel engineering
>> http://bootlin.com

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
@ 2022-02-15 10:48               ` Luís Mendes
  0 siblings, 0 replies; 130+ messages in thread
From: Luís Mendes @ 2022-02-15 10:48 UTC (permalink / raw)
  To: Gregory CLEMENT
  Cc: Pali Rohár, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Marek Behún,
	Russell King, Andrew Lunn, Linux PCI, Linux Kernel Mailing List,
	linux-arm-kernel, devicetree

Hello,

Sorry for jumping in the conversation, but I read this thread and I
have an Armada A388 HW so I can test it, if desired.

Luís


On Tue, Feb 15, 2022 at 10:47 AM Luís Mendes <luis.p.mendes@gmail.com> wrote:
>
> Hello,
>
> Sorry for jumping in the conversation, but I read this thread and I have an Armada A388 HW so I can test it, if desired.
>
> Luís
>
> On Mon, Feb 14, 2022 at 7:57 PM Gregory CLEMENT <gregory.clement@bootlin.com> wrote:
>>
>> Hello,
>>
>> > On Monday 14 February 2022 16:07:13 Gregory CLEMENT wrote:
>> >> Hello Pali,
>> >>
>> >> > With this change legacy INTA, INTB, INTC and INTD interrupts are reported
>> >> > separately and not mixed into one Linux virq source anymore.
>> >> >
>> >> > Signed-off-by: Pali Rohár <pali@kernel.org>
>> >> > ---
>> >> >  arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----
>> >>
>> >> Is there any reason for not doing the same change in armada-380.dtsi ?
>> >
>> > I do not have A380 HW, so I did this change only for A385 which I have
>> > tested.
>>
>> OK fair enough.
>>
>> So you can add my
>> Acked-by: Gregory CLEMENT <gregory.clement@bootlin.com>
>>
>> Moreover to keep biscetability  this patch should be merged after the
>> support in the driver. So the easier is to let merge it through the PCI
>> subsystem with the other patches from this series. I do not think there
>> will be any other changes in this file so there won't be any merge
>> conflicts.
>>
>> Thanks,
>>
>> Grégory
>>
>>
>> >
>> >> Grégory
>> >>
>> >> >  1 file changed, 44 insertions(+), 8 deletions(-)
>> >> >
>> >> > diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
>> >> > index f0022d10c715..83392b92dae2 100644
>> >> > --- a/arch/arm/boot/dts/armada-385.dtsi
>> >> > +++ b/arch/arm/boot/dts/armada-385.dtsi
>> >> > @@ -69,16 +69,25 @@
>> >> >                            reg = <0x0800 0 0 0 0>;
>> >> >                            #address-cells = <3>;
>> >> >                            #size-cells = <2>;
>> >> > +                          interrupt-names = "intx";
>> >> > +                          interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
>> >> >                            #interrupt-cells = <1>;
>> >> >                            ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
>> >> >                                      0x81000000 0 0 0x81000000 0x1 0 1 0>;
>> >> >                            bus-range = <0x00 0xff>;
>> >> > -                          interrupt-map-mask = <0 0 0 0>;
>> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
>> >> > +                          interrupt-map-mask = <0 0 0 7>;
>> >> > +                          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>;
>> >> >                            marvell,pcie-port = <0>;
>> >> >                            marvell,pcie-lane = <0>;
>> >> >                            clocks = <&gateclk 8>;
>> >> >                            status = "disabled";
>> >> > +                          pcie1_intc: interrupt-controller {
>> >> > +                                  interrupt-controller;
>> >> > +                                  #interrupt-cells = <1>;
>> >> > +                          };
>> >> >                    };
>> >> >
>> >> >                    /* x1 port */
>> >> > @@ -88,16 +97,25 @@
>> >> >                            reg = <0x1000 0 0 0 0>;
>> >> >                            #address-cells = <3>;
>> >> >                            #size-cells = <2>;
>> >> > +                          interrupt-names = "intx";
>> >> > +                          interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
>> >> >                            #interrupt-cells = <1>;
>> >> >                            ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
>> >> >                                      0x81000000 0 0 0x81000000 0x2 0 1 0>;
>> >> >                            bus-range = <0x00 0xff>;
>> >> > -                          interrupt-map-mask = <0 0 0 0>;
>> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
>> >> > +                          interrupt-map-mask = <0 0 0 7>;
>> >> > +                          interrupt-map = <0 0 0 1 &pcie2_intc 0>,
>> >> > +                                          <0 0 0 2 &pcie2_intc 1>,
>> >> > +                                          <0 0 0 3 &pcie2_intc 2>,
>> >> > +                                          <0 0 0 4 &pcie2_intc 3>;
>> >> >                            marvell,pcie-port = <1>;
>> >> >                            marvell,pcie-lane = <0>;
>> >> >                            clocks = <&gateclk 5>;
>> >> >                            status = "disabled";
>> >> > +                          pcie2_intc: interrupt-controller {
>> >> > +                                  interrupt-controller;
>> >> > +                                  #interrupt-cells = <1>;
>> >> > +                          };
>> >> >                    };
>> >> >
>> >> >                    /* x1 port */
>> >> > @@ -107,16 +125,25 @@
>> >> >                            reg = <0x1800 0 0 0 0>;
>> >> >                            #address-cells = <3>;
>> >> >                            #size-cells = <2>;
>> >> > +                          interrupt-names = "intx";
>> >> > +                          interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
>> >> >                            #interrupt-cells = <1>;
>> >> >                            ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
>> >> >                                      0x81000000 0 0 0x81000000 0x3 0 1 0>;
>> >> >                            bus-range = <0x00 0xff>;
>> >> > -                          interrupt-map-mask = <0 0 0 0>;
>> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
>> >> > +                          interrupt-map-mask = <0 0 0 7>;
>> >> > +                          interrupt-map = <0 0 0 1 &pcie3_intc 0>,
>> >> > +                                          <0 0 0 2 &pcie3_intc 1>,
>> >> > +                                          <0 0 0 3 &pcie3_intc 2>,
>> >> > +                                          <0 0 0 4 &pcie3_intc 3>;
>> >> >                            marvell,pcie-port = <2>;
>> >> >                            marvell,pcie-lane = <0>;
>> >> >                            clocks = <&gateclk 6>;
>> >> >                            status = "disabled";
>> >> > +                          pcie3_intc: interrupt-controller {
>> >> > +                                  interrupt-controller;
>> >> > +                                  #interrupt-cells = <1>;
>> >> > +                          };
>> >> >                    };
>> >> >
>> >> >                    /*
>> >> > @@ -129,16 +156,25 @@
>> >> >                            reg = <0x2000 0 0 0 0>;
>> >> >                            #address-cells = <3>;
>> >> >                            #size-cells = <2>;
>> >> > +                          interrupt-names = "intx";
>> >> > +                          interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
>> >> >                            #interrupt-cells = <1>;
>> >> >                            ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
>> >> >                                      0x81000000 0 0 0x81000000 0x4 0 1 0>;
>> >> >                            bus-range = <0x00 0xff>;
>> >> > -                          interrupt-map-mask = <0 0 0 0>;
>> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
>> >> > +                          interrupt-map-mask = <0 0 0 7>;
>> >> > +                          interrupt-map = <0 0 0 1 &pcie4_intc 0>,
>> >> > +                                          <0 0 0 2 &pcie4_intc 1>,
>> >> > +                                          <0 0 0 3 &pcie4_intc 2>,
>> >> > +                                          <0 0 0 4 &pcie4_intc 3>;
>> >> >                            marvell,pcie-port = <3>;
>> >> >                            marvell,pcie-lane = <0>;
>> >> >                            clocks = <&gateclk 7>;
>> >> >                            status = "disabled";
>> >> > +                          pcie4_intc: interrupt-controller {
>> >> > +                                  interrupt-controller;
>> >> > +                                  #interrupt-cells = <1>;
>> >> > +                          };
>> >> >                    };
>> >> >            };
>> >> >    };
>> >> > --
>> >> > 2.20.1
>> >> >
>> >>
>> >> --
>> >> Gregory Clement, Bootlin
>> >> Embedded Linux and Kernel engineering
>> >> http://bootlin.com
>>
>> --
>> Gregory Clement, Bootlin
>> Embedded Linux and Kernel engineering
>> http://bootlin.com

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
  2022-02-15 10:48               ` Luís Mendes
@ 2022-02-15 10:52                 ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-15 10:52 UTC (permalink / raw)
  To: Luís Mendes
  Cc: Gregory CLEMENT, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Marek Behún,
	Russell King, Andrew Lunn, Linux PCI, Linux Kernel Mailing List,
	linux-arm-kernel, devicetree

Hello! armada-388.dtsi file has #include "armada-385.dtsi" line and
therefore is already covered by this my patch.

Gregory's question was about A380.

But if you want, you can test this patch series (which already covers
A388) on your A388 HW. It is still better to do tests on more HW.

On Tuesday 15 February 2022 10:48:17 Luís Mendes wrote:
> Hello,
> 
> Sorry for jumping in the conversation, but I read this thread and I
> have an Armada A388 HW so I can test it, if desired.
> 
> Luís
> 
> 
> On Tue, Feb 15, 2022 at 10:47 AM Luís Mendes <luis.p.mendes@gmail.com> wrote:
> >
> > Hello,
> >
> > Sorry for jumping in the conversation, but I read this thread and I have an Armada A388 HW so I can test it, if desired.
> >
> > Luís
> >
> > On Mon, Feb 14, 2022 at 7:57 PM Gregory CLEMENT <gregory.clement@bootlin.com> wrote:
> >>
> >> Hello,
> >>
> >> > On Monday 14 February 2022 16:07:13 Gregory CLEMENT wrote:
> >> >> Hello Pali,
> >> >>
> >> >> > With this change legacy INTA, INTB, INTC and INTD interrupts are reported
> >> >> > separately and not mixed into one Linux virq source anymore.
> >> >> >
> >> >> > Signed-off-by: Pali Rohár <pali@kernel.org>
> >> >> > ---
> >> >> >  arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----
> >> >>
> >> >> Is there any reason for not doing the same change in armada-380.dtsi ?
> >> >
> >> > I do not have A380 HW, so I did this change only for A385 which I have
> >> > tested.
> >>
> >> OK fair enough.
> >>
> >> So you can add my
> >> Acked-by: Gregory CLEMENT <gregory.clement@bootlin.com>
> >>
> >> Moreover to keep biscetability  this patch should be merged after the
> >> support in the driver. So the easier is to let merge it through the PCI
> >> subsystem with the other patches from this series. I do not think there
> >> will be any other changes in this file so there won't be any merge
> >> conflicts.
> >>
> >> Thanks,
> >>
> >> Grégory
> >>
> >>
> >> >
> >> >> Grégory
> >> >>
> >> >> >  1 file changed, 44 insertions(+), 8 deletions(-)
> >> >> >
> >> >> > diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
> >> >> > index f0022d10c715..83392b92dae2 100644
> >> >> > --- a/arch/arm/boot/dts/armada-385.dtsi
> >> >> > +++ b/arch/arm/boot/dts/armada-385.dtsi
> >> >> > @@ -69,16 +69,25 @@
> >> >> >                            reg = <0x0800 0 0 0 0>;
> >> >> >                            #address-cells = <3>;
> >> >> >                            #size-cells = <2>;
> >> >> > +                          interrupt-names = "intx";
> >> >> > +                          interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> >> >> >                            #interrupt-cells = <1>;
> >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
> >> >> >                                      0x81000000 0 0 0x81000000 0x1 0 1 0>;
> >> >> >                            bus-range = <0x00 0xff>;
> >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> >> >> > +                          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>;
> >> >> >                            marvell,pcie-port = <0>;
> >> >> >                            marvell,pcie-lane = <0>;
> >> >> >                            clocks = <&gateclk 8>;
> >> >> >                            status = "disabled";
> >> >> > +                          pcie1_intc: interrupt-controller {
> >> >> > +                                  interrupt-controller;
> >> >> > +                                  #interrupt-cells = <1>;
> >> >> > +                          };
> >> >> >                    };
> >> >> >
> >> >> >                    /* x1 port */
> >> >> > @@ -88,16 +97,25 @@
> >> >> >                            reg = <0x1000 0 0 0 0>;
> >> >> >                            #address-cells = <3>;
> >> >> >                            #size-cells = <2>;
> >> >> > +                          interrupt-names = "intx";
> >> >> > +                          interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> >> >> >                            #interrupt-cells = <1>;
> >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
> >> >> >                                      0x81000000 0 0 0x81000000 0x2 0 1 0>;
> >> >> >                            bus-range = <0x00 0xff>;
> >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> >> >> > +                          interrupt-map = <0 0 0 1 &pcie2_intc 0>,
> >> >> > +                                          <0 0 0 2 &pcie2_intc 1>,
> >> >> > +                                          <0 0 0 3 &pcie2_intc 2>,
> >> >> > +                                          <0 0 0 4 &pcie2_intc 3>;
> >> >> >                            marvell,pcie-port = <1>;
> >> >> >                            marvell,pcie-lane = <0>;
> >> >> >                            clocks = <&gateclk 5>;
> >> >> >                            status = "disabled";
> >> >> > +                          pcie2_intc: interrupt-controller {
> >> >> > +                                  interrupt-controller;
> >> >> > +                                  #interrupt-cells = <1>;
> >> >> > +                          };
> >> >> >                    };
> >> >> >
> >> >> >                    /* x1 port */
> >> >> > @@ -107,16 +125,25 @@
> >> >> >                            reg = <0x1800 0 0 0 0>;
> >> >> >                            #address-cells = <3>;
> >> >> >                            #size-cells = <2>;
> >> >> > +                          interrupt-names = "intx";
> >> >> > +                          interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> >> >> >                            #interrupt-cells = <1>;
> >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
> >> >> >                                      0x81000000 0 0 0x81000000 0x3 0 1 0>;
> >> >> >                            bus-range = <0x00 0xff>;
> >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> >> >> > +                          interrupt-map = <0 0 0 1 &pcie3_intc 0>,
> >> >> > +                                          <0 0 0 2 &pcie3_intc 1>,
> >> >> > +                                          <0 0 0 3 &pcie3_intc 2>,
> >> >> > +                                          <0 0 0 4 &pcie3_intc 3>;
> >> >> >                            marvell,pcie-port = <2>;
> >> >> >                            marvell,pcie-lane = <0>;
> >> >> >                            clocks = <&gateclk 6>;
> >> >> >                            status = "disabled";
> >> >> > +                          pcie3_intc: interrupt-controller {
> >> >> > +                                  interrupt-controller;
> >> >> > +                                  #interrupt-cells = <1>;
> >> >> > +                          };
> >> >> >                    };
> >> >> >
> >> >> >                    /*
> >> >> > @@ -129,16 +156,25 @@
> >> >> >                            reg = <0x2000 0 0 0 0>;
> >> >> >                            #address-cells = <3>;
> >> >> >                            #size-cells = <2>;
> >> >> > +                          interrupt-names = "intx";
> >> >> > +                          interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> >> >> >                            #interrupt-cells = <1>;
> >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
> >> >> >                                      0x81000000 0 0 0x81000000 0x4 0 1 0>;
> >> >> >                            bus-range = <0x00 0xff>;
> >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> >> >> > +                          interrupt-map = <0 0 0 1 &pcie4_intc 0>,
> >> >> > +                                          <0 0 0 2 &pcie4_intc 1>,
> >> >> > +                                          <0 0 0 3 &pcie4_intc 2>,
> >> >> > +                                          <0 0 0 4 &pcie4_intc 3>;
> >> >> >                            marvell,pcie-port = <3>;
> >> >> >                            marvell,pcie-lane = <0>;
> >> >> >                            clocks = <&gateclk 7>;
> >> >> >                            status = "disabled";
> >> >> > +                          pcie4_intc: interrupt-controller {
> >> >> > +                                  interrupt-controller;
> >> >> > +                                  #interrupt-cells = <1>;
> >> >> > +                          };
> >> >> >                    };
> >> >> >            };
> >> >> >    };
> >> >> > --
> >> >> > 2.20.1
> >> >> >
> >> >>
> >> >> --
> >> >> Gregory Clement, Bootlin
> >> >> Embedded Linux and Kernel engineering
> >> >> http://bootlin.com
> >>
> >> --
> >> Gregory Clement, Bootlin
> >> Embedded Linux and Kernel engineering
> >> http://bootlin.com

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
@ 2022-02-15 10:52                 ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-15 10:52 UTC (permalink / raw)
  To: Luís Mendes
  Cc: Gregory CLEMENT, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Marek Behún,
	Russell King, Andrew Lunn, Linux PCI, Linux Kernel Mailing List,
	linux-arm-kernel, devicetree

Hello! armada-388.dtsi file has #include "armada-385.dtsi" line and
therefore is already covered by this my patch.

Gregory's question was about A380.

But if you want, you can test this patch series (which already covers
A388) on your A388 HW. It is still better to do tests on more HW.

On Tuesday 15 February 2022 10:48:17 Luís Mendes wrote:
> Hello,
> 
> Sorry for jumping in the conversation, but I read this thread and I
> have an Armada A388 HW so I can test it, if desired.
> 
> Luís
> 
> 
> On Tue, Feb 15, 2022 at 10:47 AM Luís Mendes <luis.p.mendes@gmail.com> wrote:
> >
> > Hello,
> >
> > Sorry for jumping in the conversation, but I read this thread and I have an Armada A388 HW so I can test it, if desired.
> >
> > Luís
> >
> > On Mon, Feb 14, 2022 at 7:57 PM Gregory CLEMENT <gregory.clement@bootlin.com> wrote:
> >>
> >> Hello,
> >>
> >> > On Monday 14 February 2022 16:07:13 Gregory CLEMENT wrote:
> >> >> Hello Pali,
> >> >>
> >> >> > With this change legacy INTA, INTB, INTC and INTD interrupts are reported
> >> >> > separately and not mixed into one Linux virq source anymore.
> >> >> >
> >> >> > Signed-off-by: Pali Rohár <pali@kernel.org>
> >> >> > ---
> >> >> >  arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----
> >> >>
> >> >> Is there any reason for not doing the same change in armada-380.dtsi ?
> >> >
> >> > I do not have A380 HW, so I did this change only for A385 which I have
> >> > tested.
> >>
> >> OK fair enough.
> >>
> >> So you can add my
> >> Acked-by: Gregory CLEMENT <gregory.clement@bootlin.com>
> >>
> >> Moreover to keep biscetability  this patch should be merged after the
> >> support in the driver. So the easier is to let merge it through the PCI
> >> subsystem with the other patches from this series. I do not think there
> >> will be any other changes in this file so there won't be any merge
> >> conflicts.
> >>
> >> Thanks,
> >>
> >> Grégory
> >>
> >>
> >> >
> >> >> Grégory
> >> >>
> >> >> >  1 file changed, 44 insertions(+), 8 deletions(-)
> >> >> >
> >> >> > diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
> >> >> > index f0022d10c715..83392b92dae2 100644
> >> >> > --- a/arch/arm/boot/dts/armada-385.dtsi
> >> >> > +++ b/arch/arm/boot/dts/armada-385.dtsi
> >> >> > @@ -69,16 +69,25 @@
> >> >> >                            reg = <0x0800 0 0 0 0>;
> >> >> >                            #address-cells = <3>;
> >> >> >                            #size-cells = <2>;
> >> >> > +                          interrupt-names = "intx";
> >> >> > +                          interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> >> >> >                            #interrupt-cells = <1>;
> >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
> >> >> >                                      0x81000000 0 0 0x81000000 0x1 0 1 0>;
> >> >> >                            bus-range = <0x00 0xff>;
> >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> >> >> > +                          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>;
> >> >> >                            marvell,pcie-port = <0>;
> >> >> >                            marvell,pcie-lane = <0>;
> >> >> >                            clocks = <&gateclk 8>;
> >> >> >                            status = "disabled";
> >> >> > +                          pcie1_intc: interrupt-controller {
> >> >> > +                                  interrupt-controller;
> >> >> > +                                  #interrupt-cells = <1>;
> >> >> > +                          };
> >> >> >                    };
> >> >> >
> >> >> >                    /* x1 port */
> >> >> > @@ -88,16 +97,25 @@
> >> >> >                            reg = <0x1000 0 0 0 0>;
> >> >> >                            #address-cells = <3>;
> >> >> >                            #size-cells = <2>;
> >> >> > +                          interrupt-names = "intx";
> >> >> > +                          interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> >> >> >                            #interrupt-cells = <1>;
> >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
> >> >> >                                      0x81000000 0 0 0x81000000 0x2 0 1 0>;
> >> >> >                            bus-range = <0x00 0xff>;
> >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> >> >> > +                          interrupt-map = <0 0 0 1 &pcie2_intc 0>,
> >> >> > +                                          <0 0 0 2 &pcie2_intc 1>,
> >> >> > +                                          <0 0 0 3 &pcie2_intc 2>,
> >> >> > +                                          <0 0 0 4 &pcie2_intc 3>;
> >> >> >                            marvell,pcie-port = <1>;
> >> >> >                            marvell,pcie-lane = <0>;
> >> >> >                            clocks = <&gateclk 5>;
> >> >> >                            status = "disabled";
> >> >> > +                          pcie2_intc: interrupt-controller {
> >> >> > +                                  interrupt-controller;
> >> >> > +                                  #interrupt-cells = <1>;
> >> >> > +                          };
> >> >> >                    };
> >> >> >
> >> >> >                    /* x1 port */
> >> >> > @@ -107,16 +125,25 @@
> >> >> >                            reg = <0x1800 0 0 0 0>;
> >> >> >                            #address-cells = <3>;
> >> >> >                            #size-cells = <2>;
> >> >> > +                          interrupt-names = "intx";
> >> >> > +                          interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> >> >> >                            #interrupt-cells = <1>;
> >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
> >> >> >                                      0x81000000 0 0 0x81000000 0x3 0 1 0>;
> >> >> >                            bus-range = <0x00 0xff>;
> >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> >> >> > +                          interrupt-map = <0 0 0 1 &pcie3_intc 0>,
> >> >> > +                                          <0 0 0 2 &pcie3_intc 1>,
> >> >> > +                                          <0 0 0 3 &pcie3_intc 2>,
> >> >> > +                                          <0 0 0 4 &pcie3_intc 3>;
> >> >> >                            marvell,pcie-port = <2>;
> >> >> >                            marvell,pcie-lane = <0>;
> >> >> >                            clocks = <&gateclk 6>;
> >> >> >                            status = "disabled";
> >> >> > +                          pcie3_intc: interrupt-controller {
> >> >> > +                                  interrupt-controller;
> >> >> > +                                  #interrupt-cells = <1>;
> >> >> > +                          };
> >> >> >                    };
> >> >> >
> >> >> >                    /*
> >> >> > @@ -129,16 +156,25 @@
> >> >> >                            reg = <0x2000 0 0 0 0>;
> >> >> >                            #address-cells = <3>;
> >> >> >                            #size-cells = <2>;
> >> >> > +                          interrupt-names = "intx";
> >> >> > +                          interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> >> >> >                            #interrupt-cells = <1>;
> >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
> >> >> >                                      0x81000000 0 0 0x81000000 0x4 0 1 0>;
> >> >> >                            bus-range = <0x00 0xff>;
> >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> >> >> > +                          interrupt-map = <0 0 0 1 &pcie4_intc 0>,
> >> >> > +                                          <0 0 0 2 &pcie4_intc 1>,
> >> >> > +                                          <0 0 0 3 &pcie4_intc 2>,
> >> >> > +                                          <0 0 0 4 &pcie4_intc 3>;
> >> >> >                            marvell,pcie-port = <3>;
> >> >> >                            marvell,pcie-lane = <0>;
> >> >> >                            clocks = <&gateclk 7>;
> >> >> >                            status = "disabled";
> >> >> > +                          pcie4_intc: interrupt-controller {
> >> >> > +                                  interrupt-controller;
> >> >> > +                                  #interrupt-cells = <1>;
> >> >> > +                          };
> >> >> >                    };
> >> >> >            };
> >> >> >    };
> >> >> > --
> >> >> > 2.20.1
> >> >> >
> >> >>
> >> >> --
> >> >> Gregory Clement, Bootlin
> >> >> Embedded Linux and Kernel engineering
> >> >> http://bootlin.com
> >>
> >> --
> >> Gregory Clement, Bootlin
> >> Embedded Linux and Kernel engineering
> >> http://bootlin.com

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-02-11 17:52         ` Pali Rohár
@ 2022-02-16 23:40           ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-16 23:40 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Friday 11 February 2022 18:52:02 Pali Rohár wrote:
> On Friday 11 February 2022 17:19:17 Lorenzo Pieralisi wrote:
> > On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> > > This adds support for legacy INTx interrupts received from other PCIe
> > > devices and which are reported by a new INTx irq chip.
> > > 
> > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > interrupts.
> > > 
> > > Note that for this support, device tree files has to be properly adjusted
> > > to provide "interrupts" or "interrupts-extended" property with intx
> > > interrupt source, "interrupt-names" property with "intx" string and also
> > > 'interrupt-controller' subnode must be defined.
> > > 
> > > If device tree files do not provide these nodes then driver would work as
> > > before.
> > 
> > Nit: this information is not useful. DT rules are written in DT
> > bindings, not in kernel commit logs. All I am saying is that firmware
> > developers should not have to read this log to write firmware.
> 
> It was not intended for firmware developers, but for reviewers of this
> patch to understand, what is happening in code and that with old DT
> files this patch does not change driver behavior (= work as before).
> 
> > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > ---
> > >  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
> > >  1 file changed, 177 insertions(+), 8 deletions(-)
> > > 
> > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > index 1e90ab888075..dbb6ecb4cb70 100644
> > > --- a/drivers/pci/controller/pci-mvebu.c
> > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > @@ -54,9 +54,10 @@
> > >  	 PCIE_CONF_ADDR_EN)
> > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > 
> > Nit: I understand it is tempting but here you are redefining or better
> > giving a proper label to a register. Separate patch please.
> 
> Ok!
> 
> > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > -#define PCIE_MASK_OFF		0x1910
> > 
> > See above.
> > 
> > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > >  #define PCIE_CTRL_OFF		0x1a00
> > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
> > >  	struct mvebu_pcie_window iowin;
> > >  	u32 saved_pcie_stat;
> > >  	struct resource regs;
> > > +	struct irq_domain *intx_irq_domain;
> > > +	raw_spinlock_t irq_lock;
> > > +	int intx_irq;
> > >  };
> > >  
> > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > >  
> > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > >  {
> > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > >  
> > >  	/* Setup PCIe controller to Root Complex mode. */
> > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > >  	mvebu_pcie_setup_wins(port);
> > >  
> > > -	/* Enable interrupt lines A-D. */
> > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > +	/* Mask all interrupt sources. */
> > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > +
> > > +	/* Clear all interrupt causes. */
> > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > +
> > > +	if (port->intx_irq <= 0) {
> > > +		/*
> > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > +		 * this case driver does not provide a way for masking and
> > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > +		 * all interrupts, including legacy INTx are reported via one
> > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > +		 * which individual legacy INTx was triggered. These interrupts
> > > +		 * are shared, so it should not cause any issue. Just
> > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > +		 * be called when some interrupt is triggered.
> > > +		 */
> > 
> > This comment applies to current mainline right (ie it describes how
> > current mainline handles INTx) ? IMO you should split it out in a
> > separate patch.
> 
> This above comment describe what happens in if-branch when intx_irq is
> not set (as written in comment "when intx interrupt was not specified in
> DT"). You are right that this is also the behavior in the current
> mainline.
> 
> I'm not sure if this comment can be split out as support for "intx"
> interrupt is in this patch.
> 
> > I understand it is hard but a patch is a logical _change_, this
> > comment is a change per se, it is a clarification on current
> > behaviour.
> 
> Ok, I could try to split this comment into two patches, but part about
> if-branch comment needs to stay in "this" patch.

I have done it locally.

Let me know when I should resend this patch series and I will include
into it also these changes.

> > > +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> > > +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> > > +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > +	}
> > >  }
> > >  
> > >  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > > @@ -924,6 +948,108 @@ static struct pci_ops mvebu_pcie_ops = {
> > >  	.write = mvebu_pcie_wr_conf,
> > >  };
> > >  
> > > +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> > > +{
> > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > +	unsigned long flags;
> > > +	u32 unmask;
> > > +
> > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > +	unmask &= ~PCIE_INT_INTX(hwirq);
> > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > +}
> > > +
> > > +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> > > +{
> > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > +	unsigned long flags;
> > > +	u32 unmask;
> > > +
> > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > +	unmask |= PCIE_INT_INTX(hwirq);
> > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > +}
> > > +
> > > +static struct irq_chip intx_irq_chip = {
> > > +	.name = "mvebu-INTx",
> > > +	.irq_mask = mvebu_pcie_intx_irq_mask,
> > > +	.irq_unmask = mvebu_pcie_intx_irq_unmask,
> > > +};
> > > +
> > > +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> > > +				   unsigned int virq, irq_hw_number_t hwirq)
> > > +{
> > > +	struct mvebu_pcie_port *port = h->host_data;
> > > +
> > > +	irq_set_status_flags(virq, IRQ_LEVEL);
> > > +	irq_set_chip_and_handler(virq, &intx_irq_chip, handle_level_irq);
> > > +	irq_set_chip_data(virq, port);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> > > +	.map = mvebu_pcie_intx_irq_map,
> > > +	.xlate = irq_domain_xlate_onecell,
> > > +};
> > > +
> > > +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> > > +{
> > > +	struct device *dev = &port->pcie->pdev->dev;
> > > +	struct device_node *pcie_intc_node;
> > > +
> > > +	raw_spin_lock_init(&port->irq_lock);
> > > +
> > > +	pcie_intc_node = of_get_next_child(port->dn, NULL);
> > > +	if (!pcie_intc_node) {
> > > +		dev_err(dev, "No PCIe Intc node found for %s\n", port->name);
> > > +		return -ENODEV;
> > > +	}
> > > +
> > > +	port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
> > > +						      &mvebu_pcie_intx_irq_domain_ops,
> > > +						      port);
> > > +	of_node_put(pcie_intc_node);
> > > +	if (!port->intx_irq_domain) {
> > > +		dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name);
> > > +		return -ENOMEM;
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static void mvebu_pcie_irq_handler(struct irq_desc *desc)
> > > +{
> > > +	struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc);
> > > +	struct irq_chip *chip = irq_desc_get_chip(desc);
> > > +	struct device *dev = &port->pcie->pdev->dev;
> > > +	u32 cause, unmask, status;
> > > +	int i;
> > > +
> > > +	chained_irq_enter(chip, desc);
> > > +
> > > +	cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF);
> > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > +	status = cause & unmask;
> > > +
> > > +	/* Process legacy INTx interrupts */
> > > +	for (i = 0; i < PCI_NUM_INTX; i++) {
> > > +		if (!(status & PCIE_INT_INTX(i)))
> > > +			continue;
> > > +
> > > +		if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL)
> > > +			dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A');
> > > +	}
> > > +
> > > +	chained_irq_exit(chip, desc);
> > > +}
> > > +
> > >  static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> > >  {
> > >  	/* Interrupt support on mvebu emulated bridges is not implemented yet */
> > > @@ -1121,6 +1247,21 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
> > >  		port->io_attr = -1;
> > >  	}
> > >  
> > > +	/*
> > > +	 * Old DT bindings do not contain "intx" interrupt
> > > +	 * so do not fail probing driver when interrupt does not exist.
> > > +	 */
> > > +	port->intx_irq = of_irq_get_byname(child, "intx");
> > > +	if (port->intx_irq == -EPROBE_DEFER) {
> > > +		ret = port->intx_irq;
> > > +		goto err;
> > > +	}
> > > +	if (port->intx_irq <= 0) {
> > > +		dev_warn(dev, "%s: legacy INTx interrupts cannot be masked individually, "
> > > +			      "%pOF does not contain intx interrupt\n",
> > > +			 port->name, child);
> > 
> > Here you end up with a new warning on existing firmware. Is it
> > legitimate ? I would remove the dev_warn().
> 
> I added this warning in v2 because Marc wanted it.
> 
> Should I (again) remove it in v3?
> 
> > Rob certainly has more insightful advice on this.
> > 
> > Thanks,
> > Lorenzo
> > 
> > > +	}
> > > +
> > >  	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
> > >  	if (reset_gpio == -EPROBE_DEFER) {
> > >  		ret = reset_gpio;
> > > @@ -1317,6 +1458,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
> > >  
> > >  	for (i = 0; i < pcie->nports; i++) {
> > >  		struct mvebu_pcie_port *port = &pcie->ports[i];
> > > +		int irq = port->intx_irq;
> > >  
> > >  		child = port->dn;
> > >  		if (!child)
> > > @@ -1344,6 +1486,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
> > >  			continue;
> > >  		}
> > >  
> > > +		if (irq > 0) {
> > > +			ret = mvebu_pcie_init_irq_domain(port);
> > > +			if (ret) {
> > > +				dev_err(dev, "%s: cannot init irq domain\n",
> > > +					port->name);
> > > +				pci_bridge_emul_cleanup(&port->bridge);
> > > +				devm_iounmap(dev, port->base);
> > > +				port->base = NULL;
> > > +				mvebu_pcie_powerdown(port);
> > > +				continue;
> > > +			}
> > > +			irq_set_chained_handler_and_data(irq,
> > > +							 mvebu_pcie_irq_handler,
> > > +							 port);
> > > +		}
> > > +
> > >  		/*
> > >  		 * PCIe topology exported by mvebu hw is quite complicated. In
> > >  		 * reality has something like N fully independent host bridges
> > > @@ -1448,6 +1606,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
> > >  
> > >  	for (i = 0; i < pcie->nports; i++) {
> > >  		struct mvebu_pcie_port *port = &pcie->ports[i];
> > > +		int irq = port->intx_irq;
> > >  
> > >  		if (!port->base)
> > >  			continue;
> > > @@ -1458,7 +1617,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
> > >  		mvebu_writel(port, cmd, PCIE_CMD_OFF);
> > >  
> > >  		/* Mask all interrupt sources. */
> > > -		mvebu_writel(port, 0, PCIE_MASK_OFF);
> > > +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > +
> > > +		/* Clear all interrupt causes. */
> > > +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > +
> > > +		if (irq > 0)
> > > +			irq_set_chained_handler_and_data(irq, NULL, NULL);
> > > +
> > > +		/* Remove IRQ domains. */
> > > +		if (port->intx_irq_domain)
> > > +			irq_domain_remove(port->intx_irq_domain);
> > >  
> > >  		/* Free config space for emulated root bridge. */
> > >  		pci_bridge_emul_cleanup(&port->bridge);
> > > -- 
> > > 2.20.1
> > > 

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-02-16 23:40           ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-16 23:40 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Friday 11 February 2022 18:52:02 Pali Rohár wrote:
> On Friday 11 February 2022 17:19:17 Lorenzo Pieralisi wrote:
> > On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> > > This adds support for legacy INTx interrupts received from other PCIe
> > > devices and which are reported by a new INTx irq chip.
> > > 
> > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > interrupts.
> > > 
> > > Note that for this support, device tree files has to be properly adjusted
> > > to provide "interrupts" or "interrupts-extended" property with intx
> > > interrupt source, "interrupt-names" property with "intx" string and also
> > > 'interrupt-controller' subnode must be defined.
> > > 
> > > If device tree files do not provide these nodes then driver would work as
> > > before.
> > 
> > Nit: this information is not useful. DT rules are written in DT
> > bindings, not in kernel commit logs. All I am saying is that firmware
> > developers should not have to read this log to write firmware.
> 
> It was not intended for firmware developers, but for reviewers of this
> patch to understand, what is happening in code and that with old DT
> files this patch does not change driver behavior (= work as before).
> 
> > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > ---
> > >  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
> > >  1 file changed, 177 insertions(+), 8 deletions(-)
> > > 
> > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > index 1e90ab888075..dbb6ecb4cb70 100644
> > > --- a/drivers/pci/controller/pci-mvebu.c
> > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > @@ -54,9 +54,10 @@
> > >  	 PCIE_CONF_ADDR_EN)
> > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > 
> > Nit: I understand it is tempting but here you are redefining or better
> > giving a proper label to a register. Separate patch please.
> 
> Ok!
> 
> > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > -#define PCIE_MASK_OFF		0x1910
> > 
> > See above.
> > 
> > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > >  #define PCIE_CTRL_OFF		0x1a00
> > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
> > >  	struct mvebu_pcie_window iowin;
> > >  	u32 saved_pcie_stat;
> > >  	struct resource regs;
> > > +	struct irq_domain *intx_irq_domain;
> > > +	raw_spinlock_t irq_lock;
> > > +	int intx_irq;
> > >  };
> > >  
> > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > >  
> > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > >  {
> > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > >  
> > >  	/* Setup PCIe controller to Root Complex mode. */
> > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > >  	mvebu_pcie_setup_wins(port);
> > >  
> > > -	/* Enable interrupt lines A-D. */
> > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > +	/* Mask all interrupt sources. */
> > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > +
> > > +	/* Clear all interrupt causes. */
> > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > +
> > > +	if (port->intx_irq <= 0) {
> > > +		/*
> > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > +		 * this case driver does not provide a way for masking and
> > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > +		 * all interrupts, including legacy INTx are reported via one
> > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > +		 * which individual legacy INTx was triggered. These interrupts
> > > +		 * are shared, so it should not cause any issue. Just
> > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > +		 * be called when some interrupt is triggered.
> > > +		 */
> > 
> > This comment applies to current mainline right (ie it describes how
> > current mainline handles INTx) ? IMO you should split it out in a
> > separate patch.
> 
> This above comment describe what happens in if-branch when intx_irq is
> not set (as written in comment "when intx interrupt was not specified in
> DT"). You are right that this is also the behavior in the current
> mainline.
> 
> I'm not sure if this comment can be split out as support for "intx"
> interrupt is in this patch.
> 
> > I understand it is hard but a patch is a logical _change_, this
> > comment is a change per se, it is a clarification on current
> > behaviour.
> 
> Ok, I could try to split this comment into two patches, but part about
> if-branch comment needs to stay in "this" patch.

I have done it locally.

Let me know when I should resend this patch series and I will include
into it also these changes.

> > > +		unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > +		unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) |
> > > +			  PCIE_INT_INTX(2) | PCIE_INT_INTX(3);
> > > +		mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > +	}
> > >  }
> > >  
> > >  static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
> > > @@ -924,6 +948,108 @@ static struct pci_ops mvebu_pcie_ops = {
> > >  	.write = mvebu_pcie_wr_conf,
> > >  };
> > >  
> > > +static void mvebu_pcie_intx_irq_mask(struct irq_data *d)
> > > +{
> > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > +	unsigned long flags;
> > > +	u32 unmask;
> > > +
> > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > +	unmask &= ~PCIE_INT_INTX(hwirq);
> > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > +}
> > > +
> > > +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d)
> > > +{
> > > +	struct mvebu_pcie_port *port = d->domain->host_data;
> > > +	irq_hw_number_t hwirq = irqd_to_hwirq(d);
> > > +	unsigned long flags;
> > > +	u32 unmask;
> > > +
> > > +	raw_spin_lock_irqsave(&port->irq_lock, flags);
> > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > +	unmask |= PCIE_INT_INTX(hwirq);
> > > +	mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF);
> > > +	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
> > > +}
> > > +
> > > +static struct irq_chip intx_irq_chip = {
> > > +	.name = "mvebu-INTx",
> > > +	.irq_mask = mvebu_pcie_intx_irq_mask,
> > > +	.irq_unmask = mvebu_pcie_intx_irq_unmask,
> > > +};
> > > +
> > > +static int mvebu_pcie_intx_irq_map(struct irq_domain *h,
> > > +				   unsigned int virq, irq_hw_number_t hwirq)
> > > +{
> > > +	struct mvebu_pcie_port *port = h->host_data;
> > > +
> > > +	irq_set_status_flags(virq, IRQ_LEVEL);
> > > +	irq_set_chip_and_handler(virq, &intx_irq_chip, handle_level_irq);
> > > +	irq_set_chip_data(virq, port);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = {
> > > +	.map = mvebu_pcie_intx_irq_map,
> > > +	.xlate = irq_domain_xlate_onecell,
> > > +};
> > > +
> > > +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port)
> > > +{
> > > +	struct device *dev = &port->pcie->pdev->dev;
> > > +	struct device_node *pcie_intc_node;
> > > +
> > > +	raw_spin_lock_init(&port->irq_lock);
> > > +
> > > +	pcie_intc_node = of_get_next_child(port->dn, NULL);
> > > +	if (!pcie_intc_node) {
> > > +		dev_err(dev, "No PCIe Intc node found for %s\n", port->name);
> > > +		return -ENODEV;
> > > +	}
> > > +
> > > +	port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
> > > +						      &mvebu_pcie_intx_irq_domain_ops,
> > > +						      port);
> > > +	of_node_put(pcie_intc_node);
> > > +	if (!port->intx_irq_domain) {
> > > +		dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name);
> > > +		return -ENOMEM;
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static void mvebu_pcie_irq_handler(struct irq_desc *desc)
> > > +{
> > > +	struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc);
> > > +	struct irq_chip *chip = irq_desc_get_chip(desc);
> > > +	struct device *dev = &port->pcie->pdev->dev;
> > > +	u32 cause, unmask, status;
> > > +	int i;
> > > +
> > > +	chained_irq_enter(chip, desc);
> > > +
> > > +	cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF);
> > > +	unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
> > > +	status = cause & unmask;
> > > +
> > > +	/* Process legacy INTx interrupts */
> > > +	for (i = 0; i < PCI_NUM_INTX; i++) {
> > > +		if (!(status & PCIE_INT_INTX(i)))
> > > +			continue;
> > > +
> > > +		if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL)
> > > +			dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A');
> > > +	}
> > > +
> > > +	chained_irq_exit(chip, desc);
> > > +}
> > > +
> > >  static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> > >  {
> > >  	/* Interrupt support on mvebu emulated bridges is not implemented yet */
> > > @@ -1121,6 +1247,21 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
> > >  		port->io_attr = -1;
> > >  	}
> > >  
> > > +	/*
> > > +	 * Old DT bindings do not contain "intx" interrupt
> > > +	 * so do not fail probing driver when interrupt does not exist.
> > > +	 */
> > > +	port->intx_irq = of_irq_get_byname(child, "intx");
> > > +	if (port->intx_irq == -EPROBE_DEFER) {
> > > +		ret = port->intx_irq;
> > > +		goto err;
> > > +	}
> > > +	if (port->intx_irq <= 0) {
> > > +		dev_warn(dev, "%s: legacy INTx interrupts cannot be masked individually, "
> > > +			      "%pOF does not contain intx interrupt\n",
> > > +			 port->name, child);
> > 
> > Here you end up with a new warning on existing firmware. Is it
> > legitimate ? I would remove the dev_warn().
> 
> I added this warning in v2 because Marc wanted it.
> 
> Should I (again) remove it in v3?
> 
> > Rob certainly has more insightful advice on this.
> > 
> > Thanks,
> > Lorenzo
> > 
> > > +	}
> > > +
> > >  	reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
> > >  	if (reset_gpio == -EPROBE_DEFER) {
> > >  		ret = reset_gpio;
> > > @@ -1317,6 +1458,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
> > >  
> > >  	for (i = 0; i < pcie->nports; i++) {
> > >  		struct mvebu_pcie_port *port = &pcie->ports[i];
> > > +		int irq = port->intx_irq;
> > >  
> > >  		child = port->dn;
> > >  		if (!child)
> > > @@ -1344,6 +1486,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
> > >  			continue;
> > >  		}
> > >  
> > > +		if (irq > 0) {
> > > +			ret = mvebu_pcie_init_irq_domain(port);
> > > +			if (ret) {
> > > +				dev_err(dev, "%s: cannot init irq domain\n",
> > > +					port->name);
> > > +				pci_bridge_emul_cleanup(&port->bridge);
> > > +				devm_iounmap(dev, port->base);
> > > +				port->base = NULL;
> > > +				mvebu_pcie_powerdown(port);
> > > +				continue;
> > > +			}
> > > +			irq_set_chained_handler_and_data(irq,
> > > +							 mvebu_pcie_irq_handler,
> > > +							 port);
> > > +		}
> > > +
> > >  		/*
> > >  		 * PCIe topology exported by mvebu hw is quite complicated. In
> > >  		 * reality has something like N fully independent host bridges
> > > @@ -1448,6 +1606,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
> > >  
> > >  	for (i = 0; i < pcie->nports; i++) {
> > >  		struct mvebu_pcie_port *port = &pcie->ports[i];
> > > +		int irq = port->intx_irq;
> > >  
> > >  		if (!port->base)
> > >  			continue;
> > > @@ -1458,7 +1617,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
> > >  		mvebu_writel(port, cmd, PCIE_CMD_OFF);
> > >  
> > >  		/* Mask all interrupt sources. */
> > > -		mvebu_writel(port, 0, PCIE_MASK_OFF);
> > > +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > +
> > > +		/* Clear all interrupt causes. */
> > > +		mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > +
> > > +		if (irq > 0)
> > > +			irq_set_chained_handler_and_data(irq, NULL, NULL);
> > > +
> > > +		/* Remove IRQ domains. */
> > > +		if (port->intx_irq_domain)
> > > +			irq_domain_remove(port->intx_irq_domain);
> > >  
> > >  		/* Free config space for emulated root bridge. */
> > >  		pci_bridge_emul_cleanup(&port->bridge);
> > > -- 
> > > 2.20.1
> > > 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
  2022-02-15 10:52                 ` Pali Rohár
@ 2022-02-18 21:53                   ` Luís Mendes
  -1 siblings, 0 replies; 130+ messages in thread
From: Luís Mendes @ 2022-02-18 21:53 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Gregory CLEMENT, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Marek Behún,
	Russell King, Andrew Lunn, Linux PCI, Linux Kernel Mailing List,
	linux-arm-kernel, devicetree

Successfully tested on my custom A388 system with two PCI express slots.

If you wish you can add a:
Tested-by: Luis Mendes <luis.p.mendes@gmail.com>

On Tue, Feb 15, 2022 at 10:52 AM Pali Rohár <pali@kernel.org> wrote:
>
> Hello! armada-388.dtsi file has #include "armada-385.dtsi" line and
> therefore is already covered by this my patch.
>
> Gregory's question was about A380.
>
> But if you want, you can test this patch series (which already covers
> A388) on your A388 HW. It is still better to do tests on more HW.
>
> On Tuesday 15 February 2022 10:48:17 Luís Mendes wrote:
> > Hello,
> >
> > Sorry for jumping in the conversation, but I read this thread and I
> > have an Armada A388 HW so I can test it, if desired.
> >
> > Luís
> >
> >
> > On Tue, Feb 15, 2022 at 10:47 AM Luís Mendes <luis.p.mendes@gmail.com> wrote:
> > >
> > > Hello,
> > >
> > > Sorry for jumping in the conversation, but I read this thread and I have an Armada A388 HW so I can test it, if desired.
> > >
> > > Luís
> > >
> > > On Mon, Feb 14, 2022 at 7:57 PM Gregory CLEMENT <gregory.clement@bootlin.com> wrote:
> > >>
> > >> Hello,
> > >>
> > >> > On Monday 14 February 2022 16:07:13 Gregory CLEMENT wrote:
> > >> >> Hello Pali,
> > >> >>
> > >> >> > With this change legacy INTA, INTB, INTC and INTD interrupts are reported
> > >> >> > separately and not mixed into one Linux virq source anymore.
> > >> >> >
> > >> >> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > >> >> > ---
> > >> >> >  arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----
> > >> >>
> > >> >> Is there any reason for not doing the same change in armada-380.dtsi ?
> > >> >
> > >> > I do not have A380 HW, so I did this change only for A385 which I have
> > >> > tested.
> > >>
> > >> OK fair enough.
> > >>
> > >> So you can add my
> > >> Acked-by: Gregory CLEMENT <gregory.clement@bootlin.com>
> > >>
> > >> Moreover to keep biscetability  this patch should be merged after the
> > >> support in the driver. So the easier is to let merge it through the PCI
> > >> subsystem with the other patches from this series. I do not think there
> > >> will be any other changes in this file so there won't be any merge
> > >> conflicts.
> > >>
> > >> Thanks,
> > >>
> > >> Grégory
> > >>
> > >>
> > >> >
> > >> >> Grégory
> > >> >>
> > >> >> >  1 file changed, 44 insertions(+), 8 deletions(-)
> > >> >> >
> > >> >> > diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
> > >> >> > index f0022d10c715..83392b92dae2 100644
> > >> >> > --- a/arch/arm/boot/dts/armada-385.dtsi
> > >> >> > +++ b/arch/arm/boot/dts/armada-385.dtsi
> > >> >> > @@ -69,16 +69,25 @@
> > >> >> >                            reg = <0x0800 0 0 0 0>;
> > >> >> >                            #address-cells = <3>;
> > >> >> >                            #size-cells = <2>;
> > >> >> > +                          interrupt-names = "intx";
> > >> >> > +                          interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> > >> >> >                            #interrupt-cells = <1>;
> > >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
> > >> >> >                                      0x81000000 0 0 0x81000000 0x1 0 1 0>;
> > >> >> >                            bus-range = <0x00 0xff>;
> > >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> > >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> > >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> > >> >> > +                          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>;
> > >> >> >                            marvell,pcie-port = <0>;
> > >> >> >                            marvell,pcie-lane = <0>;
> > >> >> >                            clocks = <&gateclk 8>;
> > >> >> >                            status = "disabled";
> > >> >> > +                          pcie1_intc: interrupt-controller {
> > >> >> > +                                  interrupt-controller;
> > >> >> > +                                  #interrupt-cells = <1>;
> > >> >> > +                          };
> > >> >> >                    };
> > >> >> >
> > >> >> >                    /* x1 port */
> > >> >> > @@ -88,16 +97,25 @@
> > >> >> >                            reg = <0x1000 0 0 0 0>;
> > >> >> >                            #address-cells = <3>;
> > >> >> >                            #size-cells = <2>;
> > >> >> > +                          interrupt-names = "intx";
> > >> >> > +                          interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> > >> >> >                            #interrupt-cells = <1>;
> > >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
> > >> >> >                                      0x81000000 0 0 0x81000000 0x2 0 1 0>;
> > >> >> >                            bus-range = <0x00 0xff>;
> > >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> > >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> > >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> > >> >> > +                          interrupt-map = <0 0 0 1 &pcie2_intc 0>,
> > >> >> > +                                          <0 0 0 2 &pcie2_intc 1>,
> > >> >> > +                                          <0 0 0 3 &pcie2_intc 2>,
> > >> >> > +                                          <0 0 0 4 &pcie2_intc 3>;
> > >> >> >                            marvell,pcie-port = <1>;
> > >> >> >                            marvell,pcie-lane = <0>;
> > >> >> >                            clocks = <&gateclk 5>;
> > >> >> >                            status = "disabled";
> > >> >> > +                          pcie2_intc: interrupt-controller {
> > >> >> > +                                  interrupt-controller;
> > >> >> > +                                  #interrupt-cells = <1>;
> > >> >> > +                          };
> > >> >> >                    };
> > >> >> >
> > >> >> >                    /* x1 port */
> > >> >> > @@ -107,16 +125,25 @@
> > >> >> >                            reg = <0x1800 0 0 0 0>;
> > >> >> >                            #address-cells = <3>;
> > >> >> >                            #size-cells = <2>;
> > >> >> > +                          interrupt-names = "intx";
> > >> >> > +                          interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> > >> >> >                            #interrupt-cells = <1>;
> > >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
> > >> >> >                                      0x81000000 0 0 0x81000000 0x3 0 1 0>;
> > >> >> >                            bus-range = <0x00 0xff>;
> > >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> > >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> > >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> > >> >> > +                          interrupt-map = <0 0 0 1 &pcie3_intc 0>,
> > >> >> > +                                          <0 0 0 2 &pcie3_intc 1>,
> > >> >> > +                                          <0 0 0 3 &pcie3_intc 2>,
> > >> >> > +                                          <0 0 0 4 &pcie3_intc 3>;
> > >> >> >                            marvell,pcie-port = <2>;
> > >> >> >                            marvell,pcie-lane = <0>;
> > >> >> >                            clocks = <&gateclk 6>;
> > >> >> >                            status = "disabled";
> > >> >> > +                          pcie3_intc: interrupt-controller {
> > >> >> > +                                  interrupt-controller;
> > >> >> > +                                  #interrupt-cells = <1>;
> > >> >> > +                          };
> > >> >> >                    };
> > >> >> >
> > >> >> >                    /*
> > >> >> > @@ -129,16 +156,25 @@
> > >> >> >                            reg = <0x2000 0 0 0 0>;
> > >> >> >                            #address-cells = <3>;
> > >> >> >                            #size-cells = <2>;
> > >> >> > +                          interrupt-names = "intx";
> > >> >> > +                          interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> > >> >> >                            #interrupt-cells = <1>;
> > >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
> > >> >> >                                      0x81000000 0 0 0x81000000 0x4 0 1 0>;
> > >> >> >                            bus-range = <0x00 0xff>;
> > >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> > >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> > >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> > >> >> > +                          interrupt-map = <0 0 0 1 &pcie4_intc 0>,
> > >> >> > +                                          <0 0 0 2 &pcie4_intc 1>,
> > >> >> > +                                          <0 0 0 3 &pcie4_intc 2>,
> > >> >> > +                                          <0 0 0 4 &pcie4_intc 3>;
> > >> >> >                            marvell,pcie-port = <3>;
> > >> >> >                            marvell,pcie-lane = <0>;
> > >> >> >                            clocks = <&gateclk 7>;
> > >> >> >                            status = "disabled";
> > >> >> > +                          pcie4_intc: interrupt-controller {
> > >> >> > +                                  interrupt-controller;
> > >> >> > +                                  #interrupt-cells = <1>;
> > >> >> > +                          };
> > >> >> >                    };
> > >> >> >            };
> > >> >> >    };
> > >> >> > --
> > >> >> > 2.20.1
> > >> >> >
> > >> >>
> > >> >> --
> > >> >> Gregory Clement, Bootlin
> > >> >> Embedded Linux and Kernel engineering
> > >> >> http://bootlin.com
> > >>
> > >> --
> > >> Gregory Clement, Bootlin
> > >> Embedded Linux and Kernel engineering
> > >> http://bootlin.com

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
@ 2022-02-18 21:53                   ` Luís Mendes
  0 siblings, 0 replies; 130+ messages in thread
From: Luís Mendes @ 2022-02-18 21:53 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Gregory CLEMENT, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Marek Behún,
	Russell King, Andrew Lunn, Linux PCI, Linux Kernel Mailing List,
	linux-arm-kernel, devicetree

Successfully tested on my custom A388 system with two PCI express slots.

If you wish you can add a:
Tested-by: Luis Mendes <luis.p.mendes@gmail.com>

On Tue, Feb 15, 2022 at 10:52 AM Pali Rohár <pali@kernel.org> wrote:
>
> Hello! armada-388.dtsi file has #include "armada-385.dtsi" line and
> therefore is already covered by this my patch.
>
> Gregory's question was about A380.
>
> But if you want, you can test this patch series (which already covers
> A388) on your A388 HW. It is still better to do tests on more HW.
>
> On Tuesday 15 February 2022 10:48:17 Luís Mendes wrote:
> > Hello,
> >
> > Sorry for jumping in the conversation, but I read this thread and I
> > have an Armada A388 HW so I can test it, if desired.
> >
> > Luís
> >
> >
> > On Tue, Feb 15, 2022 at 10:47 AM Luís Mendes <luis.p.mendes@gmail.com> wrote:
> > >
> > > Hello,
> > >
> > > Sorry for jumping in the conversation, but I read this thread and I have an Armada A388 HW so I can test it, if desired.
> > >
> > > Luís
> > >
> > > On Mon, Feb 14, 2022 at 7:57 PM Gregory CLEMENT <gregory.clement@bootlin.com> wrote:
> > >>
> > >> Hello,
> > >>
> > >> > On Monday 14 February 2022 16:07:13 Gregory CLEMENT wrote:
> > >> >> Hello Pali,
> > >> >>
> > >> >> > With this change legacy INTA, INTB, INTC and INTD interrupts are reported
> > >> >> > separately and not mixed into one Linux virq source anymore.
> > >> >> >
> > >> >> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > >> >> > ---
> > >> >> >  arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----
> > >> >>
> > >> >> Is there any reason for not doing the same change in armada-380.dtsi ?
> > >> >
> > >> > I do not have A380 HW, so I did this change only for A385 which I have
> > >> > tested.
> > >>
> > >> OK fair enough.
> > >>
> > >> So you can add my
> > >> Acked-by: Gregory CLEMENT <gregory.clement@bootlin.com>
> > >>
> > >> Moreover to keep biscetability  this patch should be merged after the
> > >> support in the driver. So the easier is to let merge it through the PCI
> > >> subsystem with the other patches from this series. I do not think there
> > >> will be any other changes in this file so there won't be any merge
> > >> conflicts.
> > >>
> > >> Thanks,
> > >>
> > >> Grégory
> > >>
> > >>
> > >> >
> > >> >> Grégory
> > >> >>
> > >> >> >  1 file changed, 44 insertions(+), 8 deletions(-)
> > >> >> >
> > >> >> > diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
> > >> >> > index f0022d10c715..83392b92dae2 100644
> > >> >> > --- a/arch/arm/boot/dts/armada-385.dtsi
> > >> >> > +++ b/arch/arm/boot/dts/armada-385.dtsi
> > >> >> > @@ -69,16 +69,25 @@
> > >> >> >                            reg = <0x0800 0 0 0 0>;
> > >> >> >                            #address-cells = <3>;
> > >> >> >                            #size-cells = <2>;
> > >> >> > +                          interrupt-names = "intx";
> > >> >> > +                          interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> > >> >> >                            #interrupt-cells = <1>;
> > >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
> > >> >> >                                      0x81000000 0 0 0x81000000 0x1 0 1 0>;
> > >> >> >                            bus-range = <0x00 0xff>;
> > >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> > >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> > >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> > >> >> > +                          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>;
> > >> >> >                            marvell,pcie-port = <0>;
> > >> >> >                            marvell,pcie-lane = <0>;
> > >> >> >                            clocks = <&gateclk 8>;
> > >> >> >                            status = "disabled";
> > >> >> > +                          pcie1_intc: interrupt-controller {
> > >> >> > +                                  interrupt-controller;
> > >> >> > +                                  #interrupt-cells = <1>;
> > >> >> > +                          };
> > >> >> >                    };
> > >> >> >
> > >> >> >                    /* x1 port */
> > >> >> > @@ -88,16 +97,25 @@
> > >> >> >                            reg = <0x1000 0 0 0 0>;
> > >> >> >                            #address-cells = <3>;
> > >> >> >                            #size-cells = <2>;
> > >> >> > +                          interrupt-names = "intx";
> > >> >> > +                          interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> > >> >> >                            #interrupt-cells = <1>;
> > >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
> > >> >> >                                      0x81000000 0 0 0x81000000 0x2 0 1 0>;
> > >> >> >                            bus-range = <0x00 0xff>;
> > >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> > >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> > >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> > >> >> > +                          interrupt-map = <0 0 0 1 &pcie2_intc 0>,
> > >> >> > +                                          <0 0 0 2 &pcie2_intc 1>,
> > >> >> > +                                          <0 0 0 3 &pcie2_intc 2>,
> > >> >> > +                                          <0 0 0 4 &pcie2_intc 3>;
> > >> >> >                            marvell,pcie-port = <1>;
> > >> >> >                            marvell,pcie-lane = <0>;
> > >> >> >                            clocks = <&gateclk 5>;
> > >> >> >                            status = "disabled";
> > >> >> > +                          pcie2_intc: interrupt-controller {
> > >> >> > +                                  interrupt-controller;
> > >> >> > +                                  #interrupt-cells = <1>;
> > >> >> > +                          };
> > >> >> >                    };
> > >> >> >
> > >> >> >                    /* x1 port */
> > >> >> > @@ -107,16 +125,25 @@
> > >> >> >                            reg = <0x1800 0 0 0 0>;
> > >> >> >                            #address-cells = <3>;
> > >> >> >                            #size-cells = <2>;
> > >> >> > +                          interrupt-names = "intx";
> > >> >> > +                          interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> > >> >> >                            #interrupt-cells = <1>;
> > >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
> > >> >> >                                      0x81000000 0 0 0x81000000 0x3 0 1 0>;
> > >> >> >                            bus-range = <0x00 0xff>;
> > >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> > >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> > >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> > >> >> > +                          interrupt-map = <0 0 0 1 &pcie3_intc 0>,
> > >> >> > +                                          <0 0 0 2 &pcie3_intc 1>,
> > >> >> > +                                          <0 0 0 3 &pcie3_intc 2>,
> > >> >> > +                                          <0 0 0 4 &pcie3_intc 3>;
> > >> >> >                            marvell,pcie-port = <2>;
> > >> >> >                            marvell,pcie-lane = <0>;
> > >> >> >                            clocks = <&gateclk 6>;
> > >> >> >                            status = "disabled";
> > >> >> > +                          pcie3_intc: interrupt-controller {
> > >> >> > +                                  interrupt-controller;
> > >> >> > +                                  #interrupt-cells = <1>;
> > >> >> > +                          };
> > >> >> >                    };
> > >> >> >
> > >> >> >                    /*
> > >> >> > @@ -129,16 +156,25 @@
> > >> >> >                            reg = <0x2000 0 0 0 0>;
> > >> >> >                            #address-cells = <3>;
> > >> >> >                            #size-cells = <2>;
> > >> >> > +                          interrupt-names = "intx";
> > >> >> > +                          interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> > >> >> >                            #interrupt-cells = <1>;
> > >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
> > >> >> >                                      0x81000000 0 0 0x81000000 0x4 0 1 0>;
> > >> >> >                            bus-range = <0x00 0xff>;
> > >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> > >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> > >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> > >> >> > +                          interrupt-map = <0 0 0 1 &pcie4_intc 0>,
> > >> >> > +                                          <0 0 0 2 &pcie4_intc 1>,
> > >> >> > +                                          <0 0 0 3 &pcie4_intc 2>,
> > >> >> > +                                          <0 0 0 4 &pcie4_intc 3>;
> > >> >> >                            marvell,pcie-port = <3>;
> > >> >> >                            marvell,pcie-lane = <0>;
> > >> >> >                            clocks = <&gateclk 7>;
> > >> >> >                            status = "disabled";
> > >> >> > +                          pcie4_intc: interrupt-controller {
> > >> >> > +                                  interrupt-controller;
> > >> >> > +                                  #interrupt-cells = <1>;
> > >> >> > +                          };
> > >> >> >                    };
> > >> >> >            };
> > >> >> >    };
> > >> >> > --
> > >> >> > 2.20.1
> > >> >> >
> > >> >>
> > >> >> --
> > >> >> Gregory Clement, Bootlin
> > >> >> Embedded Linux and Kernel engineering
> > >> >> http://bootlin.com
> > >>
> > >> --
> > >> Gregory Clement, Bootlin
> > >> Embedded Linux and Kernel engineering
> > >> http://bootlin.com

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
  2022-02-18 21:53                   ` Luís Mendes
@ 2022-02-19 13:36                     ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-19 13:36 UTC (permalink / raw)
  To: Luís Mendes
  Cc: Gregory CLEMENT, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Marek Behún,
	Russell King, Andrew Lunn, Linux PCI, Linux Kernel Mailing List,
	linux-arm-kernel, devicetree

Perfect, thanks!

On Friday 18 February 2022 21:53:43 Luís Mendes wrote:
> Successfully tested on my custom A388 system with two PCI express slots.
> 
> If you wish you can add a:
> Tested-by: Luis Mendes <luis.p.mendes@gmail.com>
> 
> On Tue, Feb 15, 2022 at 10:52 AM Pali Rohár <pali@kernel.org> wrote:
> >
> > Hello! armada-388.dtsi file has #include "armada-385.dtsi" line and
> > therefore is already covered by this my patch.
> >
> > Gregory's question was about A380.
> >
> > But if you want, you can test this patch series (which already covers
> > A388) on your A388 HW. It is still better to do tests on more HW.
> >
> > On Tuesday 15 February 2022 10:48:17 Luís Mendes wrote:
> > > Hello,
> > >
> > > Sorry for jumping in the conversation, but I read this thread and I
> > > have an Armada A388 HW so I can test it, if desired.
> > >
> > > Luís
> > >
> > >
> > > On Tue, Feb 15, 2022 at 10:47 AM Luís Mendes <luis.p.mendes@gmail.com> wrote:
> > > >
> > > > Hello,
> > > >
> > > > Sorry for jumping in the conversation, but I read this thread and I have an Armada A388 HW so I can test it, if desired.
> > > >
> > > > Luís
> > > >
> > > > On Mon, Feb 14, 2022 at 7:57 PM Gregory CLEMENT <gregory.clement@bootlin.com> wrote:
> > > >>
> > > >> Hello,
> > > >>
> > > >> > On Monday 14 February 2022 16:07:13 Gregory CLEMENT wrote:
> > > >> >> Hello Pali,
> > > >> >>
> > > >> >> > With this change legacy INTA, INTB, INTC and INTD interrupts are reported
> > > >> >> > separately and not mixed into one Linux virq source anymore.
> > > >> >> >
> > > >> >> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > >> >> > ---
> > > >> >> >  arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----
> > > >> >>
> > > >> >> Is there any reason for not doing the same change in armada-380.dtsi ?
> > > >> >
> > > >> > I do not have A380 HW, so I did this change only for A385 which I have
> > > >> > tested.
> > > >>
> > > >> OK fair enough.
> > > >>
> > > >> So you can add my
> > > >> Acked-by: Gregory CLEMENT <gregory.clement@bootlin.com>
> > > >>
> > > >> Moreover to keep biscetability  this patch should be merged after the
> > > >> support in the driver. So the easier is to let merge it through the PCI
> > > >> subsystem with the other patches from this series. I do not think there
> > > >> will be any other changes in this file so there won't be any merge
> > > >> conflicts.
> > > >>
> > > >> Thanks,
> > > >>
> > > >> Grégory
> > > >>
> > > >>
> > > >> >
> > > >> >> Grégory
> > > >> >>
> > > >> >> >  1 file changed, 44 insertions(+), 8 deletions(-)
> > > >> >> >
> > > >> >> > diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
> > > >> >> > index f0022d10c715..83392b92dae2 100644
> > > >> >> > --- a/arch/arm/boot/dts/armada-385.dtsi
> > > >> >> > +++ b/arch/arm/boot/dts/armada-385.dtsi
> > > >> >> > @@ -69,16 +69,25 @@
> > > >> >> >                            reg = <0x0800 0 0 0 0>;
> > > >> >> >                            #address-cells = <3>;
> > > >> >> >                            #size-cells = <2>;
> > > >> >> > +                          interrupt-names = "intx";
> > > >> >> > +                          interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> > > >> >> >                            #interrupt-cells = <1>;
> > > >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
> > > >> >> >                                      0x81000000 0 0 0x81000000 0x1 0 1 0>;
> > > >> >> >                            bus-range = <0x00 0xff>;
> > > >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> > > >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> > > >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> > > >> >> > +                          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>;
> > > >> >> >                            marvell,pcie-port = <0>;
> > > >> >> >                            marvell,pcie-lane = <0>;
> > > >> >> >                            clocks = <&gateclk 8>;
> > > >> >> >                            status = "disabled";
> > > >> >> > +                          pcie1_intc: interrupt-controller {
> > > >> >> > +                                  interrupt-controller;
> > > >> >> > +                                  #interrupt-cells = <1>;
> > > >> >> > +                          };
> > > >> >> >                    };
> > > >> >> >
> > > >> >> >                    /* x1 port */
> > > >> >> > @@ -88,16 +97,25 @@
> > > >> >> >                            reg = <0x1000 0 0 0 0>;
> > > >> >> >                            #address-cells = <3>;
> > > >> >> >                            #size-cells = <2>;
> > > >> >> > +                          interrupt-names = "intx";
> > > >> >> > +                          interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> > > >> >> >                            #interrupt-cells = <1>;
> > > >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
> > > >> >> >                                      0x81000000 0 0 0x81000000 0x2 0 1 0>;
> > > >> >> >                            bus-range = <0x00 0xff>;
> > > >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> > > >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> > > >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> > > >> >> > +                          interrupt-map = <0 0 0 1 &pcie2_intc 0>,
> > > >> >> > +                                          <0 0 0 2 &pcie2_intc 1>,
> > > >> >> > +                                          <0 0 0 3 &pcie2_intc 2>,
> > > >> >> > +                                          <0 0 0 4 &pcie2_intc 3>;
> > > >> >> >                            marvell,pcie-port = <1>;
> > > >> >> >                            marvell,pcie-lane = <0>;
> > > >> >> >                            clocks = <&gateclk 5>;
> > > >> >> >                            status = "disabled";
> > > >> >> > +                          pcie2_intc: interrupt-controller {
> > > >> >> > +                                  interrupt-controller;
> > > >> >> > +                                  #interrupt-cells = <1>;
> > > >> >> > +                          };
> > > >> >> >                    };
> > > >> >> >
> > > >> >> >                    /* x1 port */
> > > >> >> > @@ -107,16 +125,25 @@
> > > >> >> >                            reg = <0x1800 0 0 0 0>;
> > > >> >> >                            #address-cells = <3>;
> > > >> >> >                            #size-cells = <2>;
> > > >> >> > +                          interrupt-names = "intx";
> > > >> >> > +                          interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> > > >> >> >                            #interrupt-cells = <1>;
> > > >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
> > > >> >> >                                      0x81000000 0 0 0x81000000 0x3 0 1 0>;
> > > >> >> >                            bus-range = <0x00 0xff>;
> > > >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> > > >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> > > >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> > > >> >> > +                          interrupt-map = <0 0 0 1 &pcie3_intc 0>,
> > > >> >> > +                                          <0 0 0 2 &pcie3_intc 1>,
> > > >> >> > +                                          <0 0 0 3 &pcie3_intc 2>,
> > > >> >> > +                                          <0 0 0 4 &pcie3_intc 3>;
> > > >> >> >                            marvell,pcie-port = <2>;
> > > >> >> >                            marvell,pcie-lane = <0>;
> > > >> >> >                            clocks = <&gateclk 6>;
> > > >> >> >                            status = "disabled";
> > > >> >> > +                          pcie3_intc: interrupt-controller {
> > > >> >> > +                                  interrupt-controller;
> > > >> >> > +                                  #interrupt-cells = <1>;
> > > >> >> > +                          };
> > > >> >> >                    };
> > > >> >> >
> > > >> >> >                    /*
> > > >> >> > @@ -129,16 +156,25 @@
> > > >> >> >                            reg = <0x2000 0 0 0 0>;
> > > >> >> >                            #address-cells = <3>;
> > > >> >> >                            #size-cells = <2>;
> > > >> >> > +                          interrupt-names = "intx";
> > > >> >> > +                          interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> > > >> >> >                            #interrupt-cells = <1>;
> > > >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
> > > >> >> >                                      0x81000000 0 0 0x81000000 0x4 0 1 0>;
> > > >> >> >                            bus-range = <0x00 0xff>;
> > > >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> > > >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> > > >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> > > >> >> > +                          interrupt-map = <0 0 0 1 &pcie4_intc 0>,
> > > >> >> > +                                          <0 0 0 2 &pcie4_intc 1>,
> > > >> >> > +                                          <0 0 0 3 &pcie4_intc 2>,
> > > >> >> > +                                          <0 0 0 4 &pcie4_intc 3>;
> > > >> >> >                            marvell,pcie-port = <3>;
> > > >> >> >                            marvell,pcie-lane = <0>;
> > > >> >> >                            clocks = <&gateclk 7>;
> > > >> >> >                            status = "disabled";
> > > >> >> > +                          pcie4_intc: interrupt-controller {
> > > >> >> > +                                  interrupt-controller;
> > > >> >> > +                                  #interrupt-cells = <1>;
> > > >> >> > +                          };
> > > >> >> >                    };
> > > >> >> >            };
> > > >> >> >    };
> > > >> >> > --
> > > >> >> > 2.20.1
> > > >> >> >
> > > >> >>
> > > >> >> --
> > > >> >> Gregory Clement, Bootlin
> > > >> >> Embedded Linux and Kernel engineering
> > > >> >> http://bootlin.com
> > > >>
> > > >> --
> > > >> Gregory Clement, Bootlin
> > > >> Embedded Linux and Kernel engineering
> > > >> http://bootlin.com

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe legacy INTx interrupts
@ 2022-02-19 13:36                     ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-19 13:36 UTC (permalink / raw)
  To: Luís Mendes
  Cc: Gregory CLEMENT, Lorenzo Pieralisi, Bjorn Helgaas, Rob Herring,
	Thomas Petazzoni, Krzysztof Wilczyński, Marek Behún,
	Russell King, Andrew Lunn, Linux PCI, Linux Kernel Mailing List,
	linux-arm-kernel, devicetree

Perfect, thanks!

On Friday 18 February 2022 21:53:43 Luís Mendes wrote:
> Successfully tested on my custom A388 system with two PCI express slots.
> 
> If you wish you can add a:
> Tested-by: Luis Mendes <luis.p.mendes@gmail.com>
> 
> On Tue, Feb 15, 2022 at 10:52 AM Pali Rohár <pali@kernel.org> wrote:
> >
> > Hello! armada-388.dtsi file has #include "armada-385.dtsi" line and
> > therefore is already covered by this my patch.
> >
> > Gregory's question was about A380.
> >
> > But if you want, you can test this patch series (which already covers
> > A388) on your A388 HW. It is still better to do tests on more HW.
> >
> > On Tuesday 15 February 2022 10:48:17 Luís Mendes wrote:
> > > Hello,
> > >
> > > Sorry for jumping in the conversation, but I read this thread and I
> > > have an Armada A388 HW so I can test it, if desired.
> > >
> > > Luís
> > >
> > >
> > > On Tue, Feb 15, 2022 at 10:47 AM Luís Mendes <luis.p.mendes@gmail.com> wrote:
> > > >
> > > > Hello,
> > > >
> > > > Sorry for jumping in the conversation, but I read this thread and I have an Armada A388 HW so I can test it, if desired.
> > > >
> > > > Luís
> > > >
> > > > On Mon, Feb 14, 2022 at 7:57 PM Gregory CLEMENT <gregory.clement@bootlin.com> wrote:
> > > >>
> > > >> Hello,
> > > >>
> > > >> > On Monday 14 February 2022 16:07:13 Gregory CLEMENT wrote:
> > > >> >> Hello Pali,
> > > >> >>
> > > >> >> > With this change legacy INTA, INTB, INTC and INTD interrupts are reported
> > > >> >> > separately and not mixed into one Linux virq source anymore.
> > > >> >> >
> > > >> >> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > >> >> > ---
> > > >> >> >  arch/arm/boot/dts/armada-385.dtsi | 52 ++++++++++++++++++++++++++-----
> > > >> >>
> > > >> >> Is there any reason for not doing the same change in armada-380.dtsi ?
> > > >> >
> > > >> > I do not have A380 HW, so I did this change only for A385 which I have
> > > >> > tested.
> > > >>
> > > >> OK fair enough.
> > > >>
> > > >> So you can add my
> > > >> Acked-by: Gregory CLEMENT <gregory.clement@bootlin.com>
> > > >>
> > > >> Moreover to keep biscetability  this patch should be merged after the
> > > >> support in the driver. So the easier is to let merge it through the PCI
> > > >> subsystem with the other patches from this series. I do not think there
> > > >> will be any other changes in this file so there won't be any merge
> > > >> conflicts.
> > > >>
> > > >> Thanks,
> > > >>
> > > >> Grégory
> > > >>
> > > >>
> > > >> >
> > > >> >> Grégory
> > > >> >>
> > > >> >> >  1 file changed, 44 insertions(+), 8 deletions(-)
> > > >> >> >
> > > >> >> > diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
> > > >> >> > index f0022d10c715..83392b92dae2 100644
> > > >> >> > --- a/arch/arm/boot/dts/armada-385.dtsi
> > > >> >> > +++ b/arch/arm/boot/dts/armada-385.dtsi
> > > >> >> > @@ -69,16 +69,25 @@
> > > >> >> >                            reg = <0x0800 0 0 0 0>;
> > > >> >> >                            #address-cells = <3>;
> > > >> >> >                            #size-cells = <2>;
> > > >> >> > +                          interrupt-names = "intx";
> > > >> >> > +                          interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> > > >> >> >                            #interrupt-cells = <1>;
> > > >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
> > > >> >> >                                      0x81000000 0 0 0x81000000 0x1 0 1 0>;
> > > >> >> >                            bus-range = <0x00 0xff>;
> > > >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> > > >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> > > >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> > > >> >> > +                          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>;
> > > >> >> >                            marvell,pcie-port = <0>;
> > > >> >> >                            marvell,pcie-lane = <0>;
> > > >> >> >                            clocks = <&gateclk 8>;
> > > >> >> >                            status = "disabled";
> > > >> >> > +                          pcie1_intc: interrupt-controller {
> > > >> >> > +                                  interrupt-controller;
> > > >> >> > +                                  #interrupt-cells = <1>;
> > > >> >> > +                          };
> > > >> >> >                    };
> > > >> >> >
> > > >> >> >                    /* x1 port */
> > > >> >> > @@ -88,16 +97,25 @@
> > > >> >> >                            reg = <0x1000 0 0 0 0>;
> > > >> >> >                            #address-cells = <3>;
> > > >> >> >                            #size-cells = <2>;
> > > >> >> > +                          interrupt-names = "intx";
> > > >> >> > +                          interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> > > >> >> >                            #interrupt-cells = <1>;
> > > >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
> > > >> >> >                                      0x81000000 0 0 0x81000000 0x2 0 1 0>;
> > > >> >> >                            bus-range = <0x00 0xff>;
> > > >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> > > >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> > > >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> > > >> >> > +                          interrupt-map = <0 0 0 1 &pcie2_intc 0>,
> > > >> >> > +                                          <0 0 0 2 &pcie2_intc 1>,
> > > >> >> > +                                          <0 0 0 3 &pcie2_intc 2>,
> > > >> >> > +                                          <0 0 0 4 &pcie2_intc 3>;
> > > >> >> >                            marvell,pcie-port = <1>;
> > > >> >> >                            marvell,pcie-lane = <0>;
> > > >> >> >                            clocks = <&gateclk 5>;
> > > >> >> >                            status = "disabled";
> > > >> >> > +                          pcie2_intc: interrupt-controller {
> > > >> >> > +                                  interrupt-controller;
> > > >> >> > +                                  #interrupt-cells = <1>;
> > > >> >> > +                          };
> > > >> >> >                    };
> > > >> >> >
> > > >> >> >                    /* x1 port */
> > > >> >> > @@ -107,16 +125,25 @@
> > > >> >> >                            reg = <0x1800 0 0 0 0>;
> > > >> >> >                            #address-cells = <3>;
> > > >> >> >                            #size-cells = <2>;
> > > >> >> > +                          interrupt-names = "intx";
> > > >> >> > +                          interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> > > >> >> >                            #interrupt-cells = <1>;
> > > >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
> > > >> >> >                                      0x81000000 0 0 0x81000000 0x3 0 1 0>;
> > > >> >> >                            bus-range = <0x00 0xff>;
> > > >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> > > >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
> > > >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> > > >> >> > +                          interrupt-map = <0 0 0 1 &pcie3_intc 0>,
> > > >> >> > +                                          <0 0 0 2 &pcie3_intc 1>,
> > > >> >> > +                                          <0 0 0 3 &pcie3_intc 2>,
> > > >> >> > +                                          <0 0 0 4 &pcie3_intc 3>;
> > > >> >> >                            marvell,pcie-port = <2>;
> > > >> >> >                            marvell,pcie-lane = <0>;
> > > >> >> >                            clocks = <&gateclk 6>;
> > > >> >> >                            status = "disabled";
> > > >> >> > +                          pcie3_intc: interrupt-controller {
> > > >> >> > +                                  interrupt-controller;
> > > >> >> > +                                  #interrupt-cells = <1>;
> > > >> >> > +                          };
> > > >> >> >                    };
> > > >> >> >
> > > >> >> >                    /*
> > > >> >> > @@ -129,16 +156,25 @@
> > > >> >> >                            reg = <0x2000 0 0 0 0>;
> > > >> >> >                            #address-cells = <3>;
> > > >> >> >                            #size-cells = <2>;
> > > >> >> > +                          interrupt-names = "intx";
> > > >> >> > +                          interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> > > >> >> >                            #interrupt-cells = <1>;
> > > >> >> >                            ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
> > > >> >> >                                      0x81000000 0 0 0x81000000 0x4 0 1 0>;
> > > >> >> >                            bus-range = <0x00 0xff>;
> > > >> >> > -                          interrupt-map-mask = <0 0 0 0>;
> > > >> >> > -                          interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> > > >> >> > +                          interrupt-map-mask = <0 0 0 7>;
> > > >> >> > +                          interrupt-map = <0 0 0 1 &pcie4_intc 0>,
> > > >> >> > +                                          <0 0 0 2 &pcie4_intc 1>,
> > > >> >> > +                                          <0 0 0 3 &pcie4_intc 2>,
> > > >> >> > +                                          <0 0 0 4 &pcie4_intc 3>;
> > > >> >> >                            marvell,pcie-port = <3>;
> > > >> >> >                            marvell,pcie-lane = <0>;
> > > >> >> >                            clocks = <&gateclk 7>;
> > > >> >> >                            status = "disabled";
> > > >> >> > +                          pcie4_intc: interrupt-controller {
> > > >> >> > +                                  interrupt-controller;
> > > >> >> > +                                  #interrupt-cells = <1>;
> > > >> >> > +                          };
> > > >> >> >                    };
> > > >> >> >            };
> > > >> >> >    };
> > > >> >> > --
> > > >> >> > 2.20.1
> > > >> >> >
> > > >> >>
> > > >> >> --
> > > >> >> Gregory Clement, Bootlin
> > > >> >> Embedded Linux and Kernel engineering
> > > >> >> http://bootlin.com
> > > >>
> > > >> --
> > > >> Gregory Clement, Bootlin
> > > >> Embedded Linux and Kernel engineering
> > > >> http://bootlin.com

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-02-16 23:40           ` Pali Rohár
@ 2022-02-22 10:21             ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 130+ messages in thread
From: Lorenzo Pieralisi @ 2022-02-22 10:21 UTC (permalink / raw)
  To: Pali Rohár
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Thu, Feb 17, 2022 at 12:40:39AM +0100, Pali Rohár wrote:
> On Friday 11 February 2022 18:52:02 Pali Rohár wrote:
> > On Friday 11 February 2022 17:19:17 Lorenzo Pieralisi wrote:
> > > On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > devices and which are reported by a new INTx irq chip.
> > > > 
> > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > interrupts.
> > > > 
> > > > Note that for this support, device tree files has to be properly adjusted
> > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > 'interrupt-controller' subnode must be defined.
> > > > 
> > > > If device tree files do not provide these nodes then driver would work as
> > > > before.
> > > 
> > > Nit: this information is not useful. DT rules are written in DT
> > > bindings, not in kernel commit logs. All I am saying is that firmware
> > > developers should not have to read this log to write firmware.
> > 
> > It was not intended for firmware developers, but for reviewers of this
> > patch to understand, what is happening in code and that with old DT
> > files this patch does not change driver behavior (= work as before).
> > 
> > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > ---
> > > >  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
> > > >  1 file changed, 177 insertions(+), 8 deletions(-)
> > > > 
> > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > index 1e90ab888075..dbb6ecb4cb70 100644
> > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > @@ -54,9 +54,10 @@
> > > >  	 PCIE_CONF_ADDR_EN)
> > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > 
> > > Nit: I understand it is tempting but here you are redefining or better
> > > giving a proper label to a register. Separate patch please.
> > 
> > Ok!
> > 
> > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > -#define PCIE_MASK_OFF		0x1910
> > > 
> > > See above.
> > > 
> > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > >  #define PCIE_CTRL_OFF		0x1a00
> > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
> > > >  	struct mvebu_pcie_window iowin;
> > > >  	u32 saved_pcie_stat;
> > > >  	struct resource regs;
> > > > +	struct irq_domain *intx_irq_domain;
> > > > +	raw_spinlock_t irq_lock;
> > > > +	int intx_irq;
> > > >  };
> > > >  
> > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > >  
> > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > >  {
> > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > >  
> > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > >  	mvebu_pcie_setup_wins(port);
> > > >  
> > > > -	/* Enable interrupt lines A-D. */
> > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > +	/* Mask all interrupt sources. */
> > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > +
> > > > +	/* Clear all interrupt causes. */
> > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > +
> > > > +	if (port->intx_irq <= 0) {
> > > > +		/*
> > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > +		 * this case driver does not provide a way for masking and
> > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > +		 * are shared, so it should not cause any issue. Just
> > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > +		 * be called when some interrupt is triggered.
> > > > +		 */
> > > 
> > > This comment applies to current mainline right (ie it describes how
> > > current mainline handles INTx) ? IMO you should split it out in a
> > > separate patch.
> > 
> > This above comment describe what happens in if-branch when intx_irq is
> > not set (as written in comment "when intx interrupt was not specified in
> > DT"). You are right that this is also the behavior in the current
> > mainline.
> > 
> > I'm not sure if this comment can be split out as support for "intx"
> > interrupt is in this patch.
> > 
> > > I understand it is hard but a patch is a logical _change_, this
> > > comment is a change per se, it is a clarification on current
> > > behaviour.
> > 
> > Ok, I could try to split this comment into two patches, but part about
> > if-branch comment needs to stay in "this" patch.
> 
> I have done it locally.
> 
> Let me know when I should resend this patch series and I will include
> into it also these changes.

Hi,

yes please resend it and I will merge it.

Thanks,
Lorenzo

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-02-22 10:21             ` Lorenzo Pieralisi
  0 siblings, 0 replies; 130+ messages in thread
From: Lorenzo Pieralisi @ 2022-02-22 10:21 UTC (permalink / raw)
  To: Pali Rohár
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Thu, Feb 17, 2022 at 12:40:39AM +0100, Pali Rohár wrote:
> On Friday 11 February 2022 18:52:02 Pali Rohár wrote:
> > On Friday 11 February 2022 17:19:17 Lorenzo Pieralisi wrote:
> > > On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > devices and which are reported by a new INTx irq chip.
> > > > 
> > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > interrupts.
> > > > 
> > > > Note that for this support, device tree files has to be properly adjusted
> > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > 'interrupt-controller' subnode must be defined.
> > > > 
> > > > If device tree files do not provide these nodes then driver would work as
> > > > before.
> > > 
> > > Nit: this information is not useful. DT rules are written in DT
> > > bindings, not in kernel commit logs. All I am saying is that firmware
> > > developers should not have to read this log to write firmware.
> > 
> > It was not intended for firmware developers, but for reviewers of this
> > patch to understand, what is happening in code and that with old DT
> > files this patch does not change driver behavior (= work as before).
> > 
> > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > ---
> > > >  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
> > > >  1 file changed, 177 insertions(+), 8 deletions(-)
> > > > 
> > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > index 1e90ab888075..dbb6ecb4cb70 100644
> > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > @@ -54,9 +54,10 @@
> > > >  	 PCIE_CONF_ADDR_EN)
> > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > 
> > > Nit: I understand it is tempting but here you are redefining or better
> > > giving a proper label to a register. Separate patch please.
> > 
> > Ok!
> > 
> > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > -#define PCIE_MASK_OFF		0x1910
> > > 
> > > See above.
> > > 
> > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > >  #define PCIE_CTRL_OFF		0x1a00
> > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
> > > >  	struct mvebu_pcie_window iowin;
> > > >  	u32 saved_pcie_stat;
> > > >  	struct resource regs;
> > > > +	struct irq_domain *intx_irq_domain;
> > > > +	raw_spinlock_t irq_lock;
> > > > +	int intx_irq;
> > > >  };
> > > >  
> > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > >  
> > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > >  {
> > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > >  
> > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > >  	mvebu_pcie_setup_wins(port);
> > > >  
> > > > -	/* Enable interrupt lines A-D. */
> > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > +	/* Mask all interrupt sources. */
> > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > +
> > > > +	/* Clear all interrupt causes. */
> > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > +
> > > > +	if (port->intx_irq <= 0) {
> > > > +		/*
> > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > +		 * this case driver does not provide a way for masking and
> > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > +		 * are shared, so it should not cause any issue. Just
> > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > +		 * be called when some interrupt is triggered.
> > > > +		 */
> > > 
> > > This comment applies to current mainline right (ie it describes how
> > > current mainline handles INTx) ? IMO you should split it out in a
> > > separate patch.
> > 
> > This above comment describe what happens in if-branch when intx_irq is
> > not set (as written in comment "when intx interrupt was not specified in
> > DT"). You are right that this is also the behavior in the current
> > mainline.
> > 
> > I'm not sure if this comment can be split out as support for "intx"
> > interrupt is in this patch.
> > 
> > > I understand it is hard but a patch is a logical _change_, this
> > > comment is a change per se, it is a clarification on current
> > > behaviour.
> > 
> > Ok, I could try to split this comment into two patches, but part about
> > if-branch comment needs to stay in "this" patch.
> 
> I have done it locally.
> 
> Let me know when I should resend this patch series and I will include
> into it also these changes.

Hi,

yes please resend it and I will merge it.

Thanks,
Lorenzo

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-02-22 10:21             ` Lorenzo Pieralisi
@ 2022-02-22 10:51               ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-22 10:51 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Tuesday 22 February 2022 10:21:06 Lorenzo Pieralisi wrote:
> On Thu, Feb 17, 2022 at 12:40:39AM +0100, Pali Rohár wrote:
> > On Friday 11 February 2022 18:52:02 Pali Rohár wrote:
> > > On Friday 11 February 2022 17:19:17 Lorenzo Pieralisi wrote:
> > > > On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> > > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > > devices and which are reported by a new INTx irq chip.
> > > > > 
> > > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > > interrupts.
> > > > > 
> > > > > Note that for this support, device tree files has to be properly adjusted
> > > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > > 'interrupt-controller' subnode must be defined.
> > > > > 
> > > > > If device tree files do not provide these nodes then driver would work as
> > > > > before.
> > > > 
> > > > Nit: this information is not useful. DT rules are written in DT
> > > > bindings, not in kernel commit logs. All I am saying is that firmware
> > > > developers should not have to read this log to write firmware.
> > > 
> > > It was not intended for firmware developers, but for reviewers of this
> > > patch to understand, what is happening in code and that with old DT
> > > files this patch does not change driver behavior (= work as before).
> > > 
> > > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > > ---
> > > > >  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
> > > > >  1 file changed, 177 insertions(+), 8 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > > index 1e90ab888075..dbb6ecb4cb70 100644
> > > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > > @@ -54,9 +54,10 @@
> > > > >  	 PCIE_CONF_ADDR_EN)
> > > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > > 
> > > > Nit: I understand it is tempting but here you are redefining or better
> > > > giving a proper label to a register. Separate patch please.
> > > 
> > > Ok!
> > > 
> > > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > > -#define PCIE_MASK_OFF		0x1910
> > > > 
> > > > See above.
> > > > 
> > > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > > >  #define PCIE_CTRL_OFF		0x1a00
> > > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > > @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
> > > > >  	struct mvebu_pcie_window iowin;
> > > > >  	u32 saved_pcie_stat;
> > > > >  	struct resource regs;
> > > > > +	struct irq_domain *intx_irq_domain;
> > > > > +	raw_spinlock_t irq_lock;
> > > > > +	int intx_irq;
> > > > >  };
> > > > >  
> > > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > > @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > > >  
> > > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > >  {
> > > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > > >  
> > > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > > @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > > >  	mvebu_pcie_setup_wins(port);
> > > > >  
> > > > > -	/* Enable interrupt lines A-D. */
> > > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > > +	/* Mask all interrupt sources. */
> > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > > +
> > > > > +	/* Clear all interrupt causes. */
> > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > > +
> > > > > +	if (port->intx_irq <= 0) {
> > > > > +		/*
> > > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > > +		 * this case driver does not provide a way for masking and
> > > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > > +		 * are shared, so it should not cause any issue. Just
> > > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > > +		 * be called when some interrupt is triggered.
> > > > > +		 */
> > > > 
> > > > This comment applies to current mainline right (ie it describes how
> > > > current mainline handles INTx) ? IMO you should split it out in a
> > > > separate patch.
> > > 
> > > This above comment describe what happens in if-branch when intx_irq is
> > > not set (as written in comment "when intx interrupt was not specified in
> > > DT"). You are right that this is also the behavior in the current
> > > mainline.
> > > 
> > > I'm not sure if this comment can be split out as support for "intx"
> > > interrupt is in this patch.
> > > 
> > > > I understand it is hard but a patch is a logical _change_, this
> > > > comment is a change per se, it is a clarification on current
> > > > behaviour.
> > > 
> > > Ok, I could try to split this comment into two patches, but part about
> > > if-branch comment needs to stay in "this" patch.
> > 
> > I have done it locally.
> > 
> > Let me know when I should resend this patch series and I will include
> > into it also these changes.
> 
> Hi,
> 
> yes please resend it and I will merge it.

Done!
https://lore.kernel.org/linux-pci/20220222104625.28461-1-pali@kernel.org/T/#u

> 
> Thanks,
> Lorenzo

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-02-22 10:51               ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-22 10:51 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Tuesday 22 February 2022 10:21:06 Lorenzo Pieralisi wrote:
> On Thu, Feb 17, 2022 at 12:40:39AM +0100, Pali Rohár wrote:
> > On Friday 11 February 2022 18:52:02 Pali Rohár wrote:
> > > On Friday 11 February 2022 17:19:17 Lorenzo Pieralisi wrote:
> > > > On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> > > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > > devices and which are reported by a new INTx irq chip.
> > > > > 
> > > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > > interrupts.
> > > > > 
> > > > > Note that for this support, device tree files has to be properly adjusted
> > > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > > 'interrupt-controller' subnode must be defined.
> > > > > 
> > > > > If device tree files do not provide these nodes then driver would work as
> > > > > before.
> > > > 
> > > > Nit: this information is not useful. DT rules are written in DT
> > > > bindings, not in kernel commit logs. All I am saying is that firmware
> > > > developers should not have to read this log to write firmware.
> > > 
> > > It was not intended for firmware developers, but for reviewers of this
> > > patch to understand, what is happening in code and that with old DT
> > > files this patch does not change driver behavior (= work as before).
> > > 
> > > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > > ---
> > > > >  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
> > > > >  1 file changed, 177 insertions(+), 8 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > > index 1e90ab888075..dbb6ecb4cb70 100644
> > > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > > @@ -54,9 +54,10 @@
> > > > >  	 PCIE_CONF_ADDR_EN)
> > > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > > 
> > > > Nit: I understand it is tempting but here you are redefining or better
> > > > giving a proper label to a register. Separate patch please.
> > > 
> > > Ok!
> > > 
> > > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > > -#define PCIE_MASK_OFF		0x1910
> > > > 
> > > > See above.
> > > > 
> > > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > > >  #define PCIE_CTRL_OFF		0x1a00
> > > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > > @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
> > > > >  	struct mvebu_pcie_window iowin;
> > > > >  	u32 saved_pcie_stat;
> > > > >  	struct resource regs;
> > > > > +	struct irq_domain *intx_irq_domain;
> > > > > +	raw_spinlock_t irq_lock;
> > > > > +	int intx_irq;
> > > > >  };
> > > > >  
> > > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > > @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > > >  
> > > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > >  {
> > > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > > >  
> > > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > > @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > > >  	mvebu_pcie_setup_wins(port);
> > > > >  
> > > > > -	/* Enable interrupt lines A-D. */
> > > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > > +	/* Mask all interrupt sources. */
> > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > > +
> > > > > +	/* Clear all interrupt causes. */
> > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > > +
> > > > > +	if (port->intx_irq <= 0) {
> > > > > +		/*
> > > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > > +		 * this case driver does not provide a way for masking and
> > > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > > +		 * are shared, so it should not cause any issue. Just
> > > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > > +		 * be called when some interrupt is triggered.
> > > > > +		 */
> > > > 
> > > > This comment applies to current mainline right (ie it describes how
> > > > current mainline handles INTx) ? IMO you should split it out in a
> > > > separate patch.
> > > 
> > > This above comment describe what happens in if-branch when intx_irq is
> > > not set (as written in comment "when intx interrupt was not specified in
> > > DT"). You are right that this is also the behavior in the current
> > > mainline.
> > > 
> > > I'm not sure if this comment can be split out as support for "intx"
> > > interrupt is in this patch.
> > > 
> > > > I understand it is hard but a patch is a logical _change_, this
> > > > comment is a change per se, it is a clarification on current
> > > > behaviour.
> > > 
> > > Ok, I could try to split this comment into two patches, but part about
> > > if-branch comment needs to stay in "this" patch.
> > 
> > I have done it locally.
> > 
> > Let me know when I should resend this patch series and I will include
> > into it also these changes.
> 
> Hi,
> 
> yes please resend it and I will merge it.

Done!
https://lore.kernel.org/linux-pci/20220222104625.28461-1-pali@kernel.org/T/#u

> 
> Thanks,
> Lorenzo

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-02-22 10:51               ` Pali Rohár
@ 2022-02-22 15:24                 ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 130+ messages in thread
From: Lorenzo Pieralisi @ 2022-02-22 15:24 UTC (permalink / raw)
  To: Pali Rohár
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Tue, Feb 22, 2022 at 11:51:29AM +0100, Pali Rohár wrote:
> On Tuesday 22 February 2022 10:21:06 Lorenzo Pieralisi wrote:
> > On Thu, Feb 17, 2022 at 12:40:39AM +0100, Pali Rohár wrote:
> > > On Friday 11 February 2022 18:52:02 Pali Rohár wrote:
> > > > On Friday 11 February 2022 17:19:17 Lorenzo Pieralisi wrote:
> > > > > On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> > > > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > > > devices and which are reported by a new INTx irq chip.
> > > > > > 
> > > > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > > > interrupts.
> > > > > > 
> > > > > > Note that for this support, device tree files has to be properly adjusted
> > > > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > > > 'interrupt-controller' subnode must be defined.
> > > > > > 
> > > > > > If device tree files do not provide these nodes then driver would work as
> > > > > > before.
> > > > > 
> > > > > Nit: this information is not useful. DT rules are written in DT
> > > > > bindings, not in kernel commit logs. All I am saying is that firmware
> > > > > developers should not have to read this log to write firmware.
> > > > 
> > > > It was not intended for firmware developers, but for reviewers of this
> > > > patch to understand, what is happening in code and that with old DT
> > > > files this patch does not change driver behavior (= work as before).
> > > > 
> > > > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > > > ---
> > > > > >  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
> > > > > >  1 file changed, 177 insertions(+), 8 deletions(-)
> > > > > > 
> > > > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > > > index 1e90ab888075..dbb6ecb4cb70 100644
> > > > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > > > @@ -54,9 +54,10 @@
> > > > > >  	 PCIE_CONF_ADDR_EN)
> > > > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > > > 
> > > > > Nit: I understand it is tempting but here you are redefining or better
> > > > > giving a proper label to a register. Separate patch please.
> > > > 
> > > > Ok!
> > > > 
> > > > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > > > -#define PCIE_MASK_OFF		0x1910
> > > > > 
> > > > > See above.
> > > > > 
> > > > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > > > >  #define PCIE_CTRL_OFF		0x1a00
> > > > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > > > @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
> > > > > >  	struct mvebu_pcie_window iowin;
> > > > > >  	u32 saved_pcie_stat;
> > > > > >  	struct resource regs;
> > > > > > +	struct irq_domain *intx_irq_domain;
> > > > > > +	raw_spinlock_t irq_lock;
> > > > > > +	int intx_irq;
> > > > > >  };
> > > > > >  
> > > > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > > > @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > > > >  
> > > > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > >  {
> > > > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > > > >  
> > > > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > > > @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > > > >  	mvebu_pcie_setup_wins(port);
> > > > > >  
> > > > > > -	/* Enable interrupt lines A-D. */
> > > > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > > > +	/* Mask all interrupt sources. */
> > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > > > +
> > > > > > +	/* Clear all interrupt causes. */
> > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > > > +
> > > > > > +	if (port->intx_irq <= 0) {
> > > > > > +		/*
> > > > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > > > +		 * this case driver does not provide a way for masking and
> > > > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > > > +		 * are shared, so it should not cause any issue. Just
> > > > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > > > +		 * be called when some interrupt is triggered.
> > > > > > +		 */
> > > > > 
> > > > > This comment applies to current mainline right (ie it describes how
> > > > > current mainline handles INTx) ? IMO you should split it out in a
> > > > > separate patch.
> > > > 
> > > > This above comment describe what happens in if-branch when intx_irq is
> > > > not set (as written in comment "when intx interrupt was not specified in
> > > > DT"). You are right that this is also the behavior in the current
> > > > mainline.
> > > > 
> > > > I'm not sure if this comment can be split out as support for "intx"
> > > > interrupt is in this patch.
> > > > 
> > > > > I understand it is hard but a patch is a logical _change_, this
> > > > > comment is a change per se, it is a clarification on current
> > > > > behaviour.
> > > > 
> > > > Ok, I could try to split this comment into two patches, but part about
> > > > if-branch comment needs to stay in "this" patch.
> > > 
> > > I have done it locally.
> > > 
> > > Let me know when I should resend this patch series and I will include
> > > into it also these changes.
> > 
> > Hi,
> > 
> > yes please resend it and I will merge it.
> 
> Done!
> https://lore.kernel.org/linux-pci/20220222104625.28461-1-pali@kernel.org/T/#u

Can you rebase it please on top of my pci/mvebu branch ?

https://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/

Forgive me, I forgot to mention that, thanks.

Lorenzo

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-02-22 15:24                 ` Lorenzo Pieralisi
  0 siblings, 0 replies; 130+ messages in thread
From: Lorenzo Pieralisi @ 2022-02-22 15:24 UTC (permalink / raw)
  To: Pali Rohár
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Tue, Feb 22, 2022 at 11:51:29AM +0100, Pali Rohár wrote:
> On Tuesday 22 February 2022 10:21:06 Lorenzo Pieralisi wrote:
> > On Thu, Feb 17, 2022 at 12:40:39AM +0100, Pali Rohár wrote:
> > > On Friday 11 February 2022 18:52:02 Pali Rohár wrote:
> > > > On Friday 11 February 2022 17:19:17 Lorenzo Pieralisi wrote:
> > > > > On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> > > > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > > > devices and which are reported by a new INTx irq chip.
> > > > > > 
> > > > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > > > interrupts.
> > > > > > 
> > > > > > Note that for this support, device tree files has to be properly adjusted
> > > > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > > > 'interrupt-controller' subnode must be defined.
> > > > > > 
> > > > > > If device tree files do not provide these nodes then driver would work as
> > > > > > before.
> > > > > 
> > > > > Nit: this information is not useful. DT rules are written in DT
> > > > > bindings, not in kernel commit logs. All I am saying is that firmware
> > > > > developers should not have to read this log to write firmware.
> > > > 
> > > > It was not intended for firmware developers, but for reviewers of this
> > > > patch to understand, what is happening in code and that with old DT
> > > > files this patch does not change driver behavior (= work as before).
> > > > 
> > > > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > > > ---
> > > > > >  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
> > > > > >  1 file changed, 177 insertions(+), 8 deletions(-)
> > > > > > 
> > > > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > > > index 1e90ab888075..dbb6ecb4cb70 100644
> > > > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > > > @@ -54,9 +54,10 @@
> > > > > >  	 PCIE_CONF_ADDR_EN)
> > > > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > > > 
> > > > > Nit: I understand it is tempting but here you are redefining or better
> > > > > giving a proper label to a register. Separate patch please.
> > > > 
> > > > Ok!
> > > > 
> > > > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > > > -#define PCIE_MASK_OFF		0x1910
> > > > > 
> > > > > See above.
> > > > > 
> > > > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > > > >  #define PCIE_CTRL_OFF		0x1a00
> > > > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > > > @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
> > > > > >  	struct mvebu_pcie_window iowin;
> > > > > >  	u32 saved_pcie_stat;
> > > > > >  	struct resource regs;
> > > > > > +	struct irq_domain *intx_irq_domain;
> > > > > > +	raw_spinlock_t irq_lock;
> > > > > > +	int intx_irq;
> > > > > >  };
> > > > > >  
> > > > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > > > @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > > > >  
> > > > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > >  {
> > > > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > > > >  
> > > > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > > > @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > > > >  	mvebu_pcie_setup_wins(port);
> > > > > >  
> > > > > > -	/* Enable interrupt lines A-D. */
> > > > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > > > +	/* Mask all interrupt sources. */
> > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > > > +
> > > > > > +	/* Clear all interrupt causes. */
> > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > > > +
> > > > > > +	if (port->intx_irq <= 0) {
> > > > > > +		/*
> > > > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > > > +		 * this case driver does not provide a way for masking and
> > > > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > > > +		 * are shared, so it should not cause any issue. Just
> > > > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > > > +		 * be called when some interrupt is triggered.
> > > > > > +		 */
> > > > > 
> > > > > This comment applies to current mainline right (ie it describes how
> > > > > current mainline handles INTx) ? IMO you should split it out in a
> > > > > separate patch.
> > > > 
> > > > This above comment describe what happens in if-branch when intx_irq is
> > > > not set (as written in comment "when intx interrupt was not specified in
> > > > DT"). You are right that this is also the behavior in the current
> > > > mainline.
> > > > 
> > > > I'm not sure if this comment can be split out as support for "intx"
> > > > interrupt is in this patch.
> > > > 
> > > > > I understand it is hard but a patch is a logical _change_, this
> > > > > comment is a change per se, it is a clarification on current
> > > > > behaviour.
> > > > 
> > > > Ok, I could try to split this comment into two patches, but part about
> > > > if-branch comment needs to stay in "this" patch.
> > > 
> > > I have done it locally.
> > > 
> > > Let me know when I should resend this patch series and I will include
> > > into it also these changes.
> > 
> > Hi,
> > 
> > yes please resend it and I will merge it.
> 
> Done!
> https://lore.kernel.org/linux-pci/20220222104625.28461-1-pali@kernel.org/T/#u

Can you rebase it please on top of my pci/mvebu branch ?

https://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/

Forgive me, I forgot to mention that, thanks.

Lorenzo

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-02-22 15:24                 ` Lorenzo Pieralisi
@ 2022-02-22 15:42                   ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-22 15:42 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Tuesday 22 February 2022 15:24:09 Lorenzo Pieralisi wrote:
> On Tue, Feb 22, 2022 at 11:51:29AM +0100, Pali Rohár wrote:
> > On Tuesday 22 February 2022 10:21:06 Lorenzo Pieralisi wrote:
> > > On Thu, Feb 17, 2022 at 12:40:39AM +0100, Pali Rohár wrote:
> > > > On Friday 11 February 2022 18:52:02 Pali Rohár wrote:
> > > > > On Friday 11 February 2022 17:19:17 Lorenzo Pieralisi wrote:
> > > > > > On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> > > > > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > > > > devices and which are reported by a new INTx irq chip.
> > > > > > > 
> > > > > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > > > > interrupts.
> > > > > > > 
> > > > > > > Note that for this support, device tree files has to be properly adjusted
> > > > > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > > > > 'interrupt-controller' subnode must be defined.
> > > > > > > 
> > > > > > > If device tree files do not provide these nodes then driver would work as
> > > > > > > before.
> > > > > > 
> > > > > > Nit: this information is not useful. DT rules are written in DT
> > > > > > bindings, not in kernel commit logs. All I am saying is that firmware
> > > > > > developers should not have to read this log to write firmware.
> > > > > 
> > > > > It was not intended for firmware developers, but for reviewers of this
> > > > > patch to understand, what is happening in code and that with old DT
> > > > > files this patch does not change driver behavior (= work as before).
> > > > > 
> > > > > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > > > > ---
> > > > > > >  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
> > > > > > >  1 file changed, 177 insertions(+), 8 deletions(-)
> > > > > > > 
> > > > > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > > > > index 1e90ab888075..dbb6ecb4cb70 100644
> > > > > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > > > > @@ -54,9 +54,10 @@
> > > > > > >  	 PCIE_CONF_ADDR_EN)
> > > > > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > > > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > > > > 
> > > > > > Nit: I understand it is tempting but here you are redefining or better
> > > > > > giving a proper label to a register. Separate patch please.
> > > > > 
> > > > > Ok!
> > > > > 
> > > > > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > > > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > > > > -#define PCIE_MASK_OFF		0x1910
> > > > > > 
> > > > > > See above.
> > > > > > 
> > > > > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > > > > >  #define PCIE_CTRL_OFF		0x1a00
> > > > > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > > > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > > > > @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
> > > > > > >  	struct mvebu_pcie_window iowin;
> > > > > > >  	u32 saved_pcie_stat;
> > > > > > >  	struct resource regs;
> > > > > > > +	struct irq_domain *intx_irq_domain;
> > > > > > > +	raw_spinlock_t irq_lock;
> > > > > > > +	int intx_irq;
> > > > > > >  };
> > > > > > >  
> > > > > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > > > > @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > > > > >  
> > > > > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > > >  {
> > > > > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > > > > >  
> > > > > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > > > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > > > > @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > > > > >  	mvebu_pcie_setup_wins(port);
> > > > > > >  
> > > > > > > -	/* Enable interrupt lines A-D. */
> > > > > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > > > > +	/* Mask all interrupt sources. */
> > > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > > > > +
> > > > > > > +	/* Clear all interrupt causes. */
> > > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > > > > +
> > > > > > > +	if (port->intx_irq <= 0) {
> > > > > > > +		/*
> > > > > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > > > > +		 * this case driver does not provide a way for masking and
> > > > > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > > > > +		 * are shared, so it should not cause any issue. Just
> > > > > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > > > > +		 * be called when some interrupt is triggered.
> > > > > > > +		 */
> > > > > > 
> > > > > > This comment applies to current mainline right (ie it describes how
> > > > > > current mainline handles INTx) ? IMO you should split it out in a
> > > > > > separate patch.
> > > > > 
> > > > > This above comment describe what happens in if-branch when intx_irq is
> > > > > not set (as written in comment "when intx interrupt was not specified in
> > > > > DT"). You are right that this is also the behavior in the current
> > > > > mainline.
> > > > > 
> > > > > I'm not sure if this comment can be split out as support for "intx"
> > > > > interrupt is in this patch.
> > > > > 
> > > > > > I understand it is hard but a patch is a logical _change_, this
> > > > > > comment is a change per se, it is a clarification on current
> > > > > > behaviour.
> > > > > 
> > > > > Ok, I could try to split this comment into two patches, but part about
> > > > > if-branch comment needs to stay in "this" patch.
> > > > 
> > > > I have done it locally.
> > > > 
> > > > Let me know when I should resend this patch series and I will include
> > > > into it also these changes.
> > > 
> > > Hi,
> > > 
> > > yes please resend it and I will merge it.
> > 
> > Done!
> > https://lore.kernel.org/linux-pci/20220222104625.28461-1-pali@kernel.org/T/#u
> 
> Can you rebase it please on top of my pci/mvebu branch ?
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/
> 
> Forgive me, I forgot to mention that, thanks.
> 
> Lorenzo

Ok! I rebased V3 on top of c3bd7dc553eea5a3595ca3aa0adee9bf83622a1f
(pci/mvebu branch in your repo), fixed conflicts and pushed to my git
repo https://git.kernel.org/pub/scm/linux/kernel/git/pali/linux.git/
as commit 42402f0cfc362ffb0b7e464f420d6ead342dab2b (lpieralisi-pci-mvebu
branch). It is enough? Or do you want me to resend it via emails?

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-02-22 15:42                   ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-22 15:42 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Tuesday 22 February 2022 15:24:09 Lorenzo Pieralisi wrote:
> On Tue, Feb 22, 2022 at 11:51:29AM +0100, Pali Rohár wrote:
> > On Tuesday 22 February 2022 10:21:06 Lorenzo Pieralisi wrote:
> > > On Thu, Feb 17, 2022 at 12:40:39AM +0100, Pali Rohár wrote:
> > > > On Friday 11 February 2022 18:52:02 Pali Rohár wrote:
> > > > > On Friday 11 February 2022 17:19:17 Lorenzo Pieralisi wrote:
> > > > > > On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> > > > > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > > > > devices and which are reported by a new INTx irq chip.
> > > > > > > 
> > > > > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > > > > interrupts.
> > > > > > > 
> > > > > > > Note that for this support, device tree files has to be properly adjusted
> > > > > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > > > > 'interrupt-controller' subnode must be defined.
> > > > > > > 
> > > > > > > If device tree files do not provide these nodes then driver would work as
> > > > > > > before.
> > > > > > 
> > > > > > Nit: this information is not useful. DT rules are written in DT
> > > > > > bindings, not in kernel commit logs. All I am saying is that firmware
> > > > > > developers should not have to read this log to write firmware.
> > > > > 
> > > > > It was not intended for firmware developers, but for reviewers of this
> > > > > patch to understand, what is happening in code and that with old DT
> > > > > files this patch does not change driver behavior (= work as before).
> > > > > 
> > > > > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > > > > ---
> > > > > > >  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
> > > > > > >  1 file changed, 177 insertions(+), 8 deletions(-)
> > > > > > > 
> > > > > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > > > > index 1e90ab888075..dbb6ecb4cb70 100644
> > > > > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > > > > @@ -54,9 +54,10 @@
> > > > > > >  	 PCIE_CONF_ADDR_EN)
> > > > > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > > > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > > > > 
> > > > > > Nit: I understand it is tempting but here you are redefining or better
> > > > > > giving a proper label to a register. Separate patch please.
> > > > > 
> > > > > Ok!
> > > > > 
> > > > > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > > > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > > > > -#define PCIE_MASK_OFF		0x1910
> > > > > > 
> > > > > > See above.
> > > > > > 
> > > > > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > > > > >  #define PCIE_CTRL_OFF		0x1a00
> > > > > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > > > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > > > > @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
> > > > > > >  	struct mvebu_pcie_window iowin;
> > > > > > >  	u32 saved_pcie_stat;
> > > > > > >  	struct resource regs;
> > > > > > > +	struct irq_domain *intx_irq_domain;
> > > > > > > +	raw_spinlock_t irq_lock;
> > > > > > > +	int intx_irq;
> > > > > > >  };
> > > > > > >  
> > > > > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > > > > @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > > > > >  
> > > > > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > > >  {
> > > > > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > > > > >  
> > > > > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > > > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > > > > @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > > > > >  	mvebu_pcie_setup_wins(port);
> > > > > > >  
> > > > > > > -	/* Enable interrupt lines A-D. */
> > > > > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > > > > +	/* Mask all interrupt sources. */
> > > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > > > > +
> > > > > > > +	/* Clear all interrupt causes. */
> > > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > > > > +
> > > > > > > +	if (port->intx_irq <= 0) {
> > > > > > > +		/*
> > > > > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > > > > +		 * this case driver does not provide a way for masking and
> > > > > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > > > > +		 * are shared, so it should not cause any issue. Just
> > > > > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > > > > +		 * be called when some interrupt is triggered.
> > > > > > > +		 */
> > > > > > 
> > > > > > This comment applies to current mainline right (ie it describes how
> > > > > > current mainline handles INTx) ? IMO you should split it out in a
> > > > > > separate patch.
> > > > > 
> > > > > This above comment describe what happens in if-branch when intx_irq is
> > > > > not set (as written in comment "when intx interrupt was not specified in
> > > > > DT"). You are right that this is also the behavior in the current
> > > > > mainline.
> > > > > 
> > > > > I'm not sure if this comment can be split out as support for "intx"
> > > > > interrupt is in this patch.
> > > > > 
> > > > > > I understand it is hard but a patch is a logical _change_, this
> > > > > > comment is a change per se, it is a clarification on current
> > > > > > behaviour.
> > > > > 
> > > > > Ok, I could try to split this comment into two patches, but part about
> > > > > if-branch comment needs to stay in "this" patch.
> > > > 
> > > > I have done it locally.
> > > > 
> > > > Let me know when I should resend this patch series and I will include
> > > > into it also these changes.
> > > 
> > > Hi,
> > > 
> > > yes please resend it and I will merge it.
> > 
> > Done!
> > https://lore.kernel.org/linux-pci/20220222104625.28461-1-pali@kernel.org/T/#u
> 
> Can you rebase it please on top of my pci/mvebu branch ?
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/
> 
> Forgive me, I forgot to mention that, thanks.
> 
> Lorenzo

Ok! I rebased V3 on top of c3bd7dc553eea5a3595ca3aa0adee9bf83622a1f
(pci/mvebu branch in your repo), fixed conflicts and pushed to my git
repo https://git.kernel.org/pub/scm/linux/kernel/git/pali/linux.git/
as commit 42402f0cfc362ffb0b7e464f420d6ead342dab2b (lpieralisi-pci-mvebu
branch). It is enough? Or do you want me to resend it via emails?

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-02-22 15:42                   ` Pali Rohár
@ 2022-02-22 15:45                     ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 130+ messages in thread
From: Lorenzo Pieralisi @ 2022-02-22 15:45 UTC (permalink / raw)
  To: Pali Rohár
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Tue, Feb 22, 2022 at 04:42:26PM +0100, Pali Rohár wrote:
> On Tuesday 22 February 2022 15:24:09 Lorenzo Pieralisi wrote:
> > On Tue, Feb 22, 2022 at 11:51:29AM +0100, Pali Rohár wrote:
> > > On Tuesday 22 February 2022 10:21:06 Lorenzo Pieralisi wrote:
> > > > On Thu, Feb 17, 2022 at 12:40:39AM +0100, Pali Rohár wrote:
> > > > > On Friday 11 February 2022 18:52:02 Pali Rohár wrote:
> > > > > > On Friday 11 February 2022 17:19:17 Lorenzo Pieralisi wrote:
> > > > > > > On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> > > > > > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > > > > > devices and which are reported by a new INTx irq chip.
> > > > > > > > 
> > > > > > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > > > > > interrupts.
> > > > > > > > 
> > > > > > > > Note that for this support, device tree files has to be properly adjusted
> > > > > > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > > > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > > > > > 'interrupt-controller' subnode must be defined.
> > > > > > > > 
> > > > > > > > If device tree files do not provide these nodes then driver would work as
> > > > > > > > before.
> > > > > > > 
> > > > > > > Nit: this information is not useful. DT rules are written in DT
> > > > > > > bindings, not in kernel commit logs. All I am saying is that firmware
> > > > > > > developers should not have to read this log to write firmware.
> > > > > > 
> > > > > > It was not intended for firmware developers, but for reviewers of this
> > > > > > patch to understand, what is happening in code and that with old DT
> > > > > > files this patch does not change driver behavior (= work as before).
> > > > > > 
> > > > > > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > > > > > ---
> > > > > > > >  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
> > > > > > > >  1 file changed, 177 insertions(+), 8 deletions(-)
> > > > > > > > 
> > > > > > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > > > > > index 1e90ab888075..dbb6ecb4cb70 100644
> > > > > > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > > > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > > > > > @@ -54,9 +54,10 @@
> > > > > > > >  	 PCIE_CONF_ADDR_EN)
> > > > > > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > > > > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > > > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > > > > > 
> > > > > > > Nit: I understand it is tempting but here you are redefining or better
> > > > > > > giving a proper label to a register. Separate patch please.
> > > > > > 
> > > > > > Ok!
> > > > > > 
> > > > > > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > > > > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > > > > > -#define PCIE_MASK_OFF		0x1910
> > > > > > > 
> > > > > > > See above.
> > > > > > > 
> > > > > > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > > > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > > > > > >  #define PCIE_CTRL_OFF		0x1a00
> > > > > > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > > > > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > > > > > @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
> > > > > > > >  	struct mvebu_pcie_window iowin;
> > > > > > > >  	u32 saved_pcie_stat;
> > > > > > > >  	struct resource regs;
> > > > > > > > +	struct irq_domain *intx_irq_domain;
> > > > > > > > +	raw_spinlock_t irq_lock;
> > > > > > > > +	int intx_irq;
> > > > > > > >  };
> > > > > > > >  
> > > > > > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > > > > > @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > > > > > >  
> > > > > > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > > > >  {
> > > > > > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > > > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > > > > > >  
> > > > > > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > > > > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > > > > > @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > > > > > >  	mvebu_pcie_setup_wins(port);
> > > > > > > >  
> > > > > > > > -	/* Enable interrupt lines A-D. */
> > > > > > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > > > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > > > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > > > > > +	/* Mask all interrupt sources. */
> > > > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > > > > > +
> > > > > > > > +	/* Clear all interrupt causes. */
> > > > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > > > > > +
> > > > > > > > +	if (port->intx_irq <= 0) {
> > > > > > > > +		/*
> > > > > > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > > > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > > > > > +		 * this case driver does not provide a way for masking and
> > > > > > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > > > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > > > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > > > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > > > > > +		 * are shared, so it should not cause any issue. Just
> > > > > > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > > > > > +		 * be called when some interrupt is triggered.
> > > > > > > > +		 */
> > > > > > > 
> > > > > > > This comment applies to current mainline right (ie it describes how
> > > > > > > current mainline handles INTx) ? IMO you should split it out in a
> > > > > > > separate patch.
> > > > > > 
> > > > > > This above comment describe what happens in if-branch when intx_irq is
> > > > > > not set (as written in comment "when intx interrupt was not specified in
> > > > > > DT"). You are right that this is also the behavior in the current
> > > > > > mainline.
> > > > > > 
> > > > > > I'm not sure if this comment can be split out as support for "intx"
> > > > > > interrupt is in this patch.
> > > > > > 
> > > > > > > I understand it is hard but a patch is a logical _change_, this
> > > > > > > comment is a change per se, it is a clarification on current
> > > > > > > behaviour.
> > > > > > 
> > > > > > Ok, I could try to split this comment into two patches, but part about
> > > > > > if-branch comment needs to stay in "this" patch.
> > > > > 
> > > > > I have done it locally.
> > > > > 
> > > > > Let me know when I should resend this patch series and I will include
> > > > > into it also these changes.
> > > > 
> > > > Hi,
> > > > 
> > > > yes please resend it and I will merge it.
> > > 
> > > Done!
> > > https://lore.kernel.org/linux-pci/20220222104625.28461-1-pali@kernel.org/T/#u
> > 
> > Can you rebase it please on top of my pci/mvebu branch ?
> > 
> > https://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/
> > 
> > Forgive me, I forgot to mention that, thanks.
> > 
> > Lorenzo
> 
> Ok! I rebased V3 on top of c3bd7dc553eea5a3595ca3aa0adee9bf83622a1f
> (pci/mvebu branch in your repo), fixed conflicts and pushed to my git
> repo https://git.kernel.org/pub/scm/linux/kernel/git/pali/linux.git/
> as commit 42402f0cfc362ffb0b7e464f420d6ead342dab2b (lpieralisi-pci-mvebu
> branch). It is enough? Or do you want me to resend it via emails?

You need to re-send it to linux-pci ML, I only apply patches posted
there, sorry for the churn, thanks.

Lorenzo

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-02-22 15:45                     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 130+ messages in thread
From: Lorenzo Pieralisi @ 2022-02-22 15:45 UTC (permalink / raw)
  To: Pali Rohár
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Tue, Feb 22, 2022 at 04:42:26PM +0100, Pali Rohár wrote:
> On Tuesday 22 February 2022 15:24:09 Lorenzo Pieralisi wrote:
> > On Tue, Feb 22, 2022 at 11:51:29AM +0100, Pali Rohár wrote:
> > > On Tuesday 22 February 2022 10:21:06 Lorenzo Pieralisi wrote:
> > > > On Thu, Feb 17, 2022 at 12:40:39AM +0100, Pali Rohár wrote:
> > > > > On Friday 11 February 2022 18:52:02 Pali Rohár wrote:
> > > > > > On Friday 11 February 2022 17:19:17 Lorenzo Pieralisi wrote:
> > > > > > > On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> > > > > > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > > > > > devices and which are reported by a new INTx irq chip.
> > > > > > > > 
> > > > > > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > > > > > interrupts.
> > > > > > > > 
> > > > > > > > Note that for this support, device tree files has to be properly adjusted
> > > > > > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > > > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > > > > > 'interrupt-controller' subnode must be defined.
> > > > > > > > 
> > > > > > > > If device tree files do not provide these nodes then driver would work as
> > > > > > > > before.
> > > > > > > 
> > > > > > > Nit: this information is not useful. DT rules are written in DT
> > > > > > > bindings, not in kernel commit logs. All I am saying is that firmware
> > > > > > > developers should not have to read this log to write firmware.
> > > > > > 
> > > > > > It was not intended for firmware developers, but for reviewers of this
> > > > > > patch to understand, what is happening in code and that with old DT
> > > > > > files this patch does not change driver behavior (= work as before).
> > > > > > 
> > > > > > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > > > > > ---
> > > > > > > >  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
> > > > > > > >  1 file changed, 177 insertions(+), 8 deletions(-)
> > > > > > > > 
> > > > > > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > > > > > index 1e90ab888075..dbb6ecb4cb70 100644
> > > > > > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > > > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > > > > > @@ -54,9 +54,10 @@
> > > > > > > >  	 PCIE_CONF_ADDR_EN)
> > > > > > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > > > > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > > > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > > > > > 
> > > > > > > Nit: I understand it is tempting but here you are redefining or better
> > > > > > > giving a proper label to a register. Separate patch please.
> > > > > > 
> > > > > > Ok!
> > > > > > 
> > > > > > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > > > > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > > > > > -#define PCIE_MASK_OFF		0x1910
> > > > > > > 
> > > > > > > See above.
> > > > > > > 
> > > > > > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > > > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > > > > > >  #define PCIE_CTRL_OFF		0x1a00
> > > > > > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > > > > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > > > > > @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
> > > > > > > >  	struct mvebu_pcie_window iowin;
> > > > > > > >  	u32 saved_pcie_stat;
> > > > > > > >  	struct resource regs;
> > > > > > > > +	struct irq_domain *intx_irq_domain;
> > > > > > > > +	raw_spinlock_t irq_lock;
> > > > > > > > +	int intx_irq;
> > > > > > > >  };
> > > > > > > >  
> > > > > > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > > > > > @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > > > > > >  
> > > > > > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > > > >  {
> > > > > > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > > > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > > > > > >  
> > > > > > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > > > > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > > > > > @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > > > > > >  	mvebu_pcie_setup_wins(port);
> > > > > > > >  
> > > > > > > > -	/* Enable interrupt lines A-D. */
> > > > > > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > > > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > > > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > > > > > +	/* Mask all interrupt sources. */
> > > > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > > > > > +
> > > > > > > > +	/* Clear all interrupt causes. */
> > > > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > > > > > +
> > > > > > > > +	if (port->intx_irq <= 0) {
> > > > > > > > +		/*
> > > > > > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > > > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > > > > > +		 * this case driver does not provide a way for masking and
> > > > > > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > > > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > > > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > > > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > > > > > +		 * are shared, so it should not cause any issue. Just
> > > > > > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > > > > > +		 * be called when some interrupt is triggered.
> > > > > > > > +		 */
> > > > > > > 
> > > > > > > This comment applies to current mainline right (ie it describes how
> > > > > > > current mainline handles INTx) ? IMO you should split it out in a
> > > > > > > separate patch.
> > > > > > 
> > > > > > This above comment describe what happens in if-branch when intx_irq is
> > > > > > not set (as written in comment "when intx interrupt was not specified in
> > > > > > DT"). You are right that this is also the behavior in the current
> > > > > > mainline.
> > > > > > 
> > > > > > I'm not sure if this comment can be split out as support for "intx"
> > > > > > interrupt is in this patch.
> > > > > > 
> > > > > > > I understand it is hard but a patch is a logical _change_, this
> > > > > > > comment is a change per se, it is a clarification on current
> > > > > > > behaviour.
> > > > > > 
> > > > > > Ok, I could try to split this comment into two patches, but part about
> > > > > > if-branch comment needs to stay in "this" patch.
> > > > > 
> > > > > I have done it locally.
> > > > > 
> > > > > Let me know when I should resend this patch series and I will include
> > > > > into it also these changes.
> > > > 
> > > > Hi,
> > > > 
> > > > yes please resend it and I will merge it.
> > > 
> > > Done!
> > > https://lore.kernel.org/linux-pci/20220222104625.28461-1-pali@kernel.org/T/#u
> > 
> > Can you rebase it please on top of my pci/mvebu branch ?
> > 
> > https://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/
> > 
> > Forgive me, I forgot to mention that, thanks.
> > 
> > Lorenzo
> 
> Ok! I rebased V3 on top of c3bd7dc553eea5a3595ca3aa0adee9bf83622a1f
> (pci/mvebu branch in your repo), fixed conflicts and pushed to my git
> repo https://git.kernel.org/pub/scm/linux/kernel/git/pali/linux.git/
> as commit 42402f0cfc362ffb0b7e464f420d6ead342dab2b (lpieralisi-pci-mvebu
> branch). It is enough? Or do you want me to resend it via emails?

You need to re-send it to linux-pci ML, I only apply patches posted
there, sorry for the churn, thanks.

Lorenzo

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
  2022-02-22 15:45                     ` Lorenzo Pieralisi
@ 2022-02-22 15:55                       ` Pali Rohár
  -1 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-22 15:55 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Tuesday 22 February 2022 15:45:53 Lorenzo Pieralisi wrote:
> On Tue, Feb 22, 2022 at 04:42:26PM +0100, Pali Rohár wrote:
> > On Tuesday 22 February 2022 15:24:09 Lorenzo Pieralisi wrote:
> > > On Tue, Feb 22, 2022 at 11:51:29AM +0100, Pali Rohár wrote:
> > > > On Tuesday 22 February 2022 10:21:06 Lorenzo Pieralisi wrote:
> > > > > On Thu, Feb 17, 2022 at 12:40:39AM +0100, Pali Rohár wrote:
> > > > > > On Friday 11 February 2022 18:52:02 Pali Rohár wrote:
> > > > > > > On Friday 11 February 2022 17:19:17 Lorenzo Pieralisi wrote:
> > > > > > > > On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> > > > > > > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > > > > > > devices and which are reported by a new INTx irq chip.
> > > > > > > > > 
> > > > > > > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > > > > > > interrupts.
> > > > > > > > > 
> > > > > > > > > Note that for this support, device tree files has to be properly adjusted
> > > > > > > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > > > > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > > > > > > 'interrupt-controller' subnode must be defined.
> > > > > > > > > 
> > > > > > > > > If device tree files do not provide these nodes then driver would work as
> > > > > > > > > before.
> > > > > > > > 
> > > > > > > > Nit: this information is not useful. DT rules are written in DT
> > > > > > > > bindings, not in kernel commit logs. All I am saying is that firmware
> > > > > > > > developers should not have to read this log to write firmware.
> > > > > > > 
> > > > > > > It was not intended for firmware developers, but for reviewers of this
> > > > > > > patch to understand, what is happening in code and that with old DT
> > > > > > > files this patch does not change driver behavior (= work as before).
> > > > > > > 
> > > > > > > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > > > > > > ---
> > > > > > > > >  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
> > > > > > > > >  1 file changed, 177 insertions(+), 8 deletions(-)
> > > > > > > > > 
> > > > > > > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > > > > > > index 1e90ab888075..dbb6ecb4cb70 100644
> > > > > > > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > > > > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > > > > > > @@ -54,9 +54,10 @@
> > > > > > > > >  	 PCIE_CONF_ADDR_EN)
> > > > > > > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > > > > > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > > > > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > > > > > > 
> > > > > > > > Nit: I understand it is tempting but here you are redefining or better
> > > > > > > > giving a proper label to a register. Separate patch please.
> > > > > > > 
> > > > > > > Ok!
> > > > > > > 
> > > > > > > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > > > > > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > > > > > > -#define PCIE_MASK_OFF		0x1910
> > > > > > > > 
> > > > > > > > See above.
> > > > > > > > 
> > > > > > > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > > > > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > > > > > > >  #define PCIE_CTRL_OFF		0x1a00
> > > > > > > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > > > > > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > > > > > > @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
> > > > > > > > >  	struct mvebu_pcie_window iowin;
> > > > > > > > >  	u32 saved_pcie_stat;
> > > > > > > > >  	struct resource regs;
> > > > > > > > > +	struct irq_domain *intx_irq_domain;
> > > > > > > > > +	raw_spinlock_t irq_lock;
> > > > > > > > > +	int intx_irq;
> > > > > > > > >  };
> > > > > > > > >  
> > > > > > > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > > > > > > @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > > > > > > >  
> > > > > > > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > > > > >  {
> > > > > > > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > > > > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > > > > > > >  
> > > > > > > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > > > > > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > > > > > > @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > > > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > > > > > > >  	mvebu_pcie_setup_wins(port);
> > > > > > > > >  
> > > > > > > > > -	/* Enable interrupt lines A-D. */
> > > > > > > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > > > > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > > > > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > > > > > > +	/* Mask all interrupt sources. */
> > > > > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > > > > > > +
> > > > > > > > > +	/* Clear all interrupt causes. */
> > > > > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > > > > > > +
> > > > > > > > > +	if (port->intx_irq <= 0) {
> > > > > > > > > +		/*
> > > > > > > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > > > > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > > > > > > +		 * this case driver does not provide a way for masking and
> > > > > > > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > > > > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > > > > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > > > > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > > > > > > +		 * are shared, so it should not cause any issue. Just
> > > > > > > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > > > > > > +		 * be called when some interrupt is triggered.
> > > > > > > > > +		 */
> > > > > > > > 
> > > > > > > > This comment applies to current mainline right (ie it describes how
> > > > > > > > current mainline handles INTx) ? IMO you should split it out in a
> > > > > > > > separate patch.
> > > > > > > 
> > > > > > > This above comment describe what happens in if-branch when intx_irq is
> > > > > > > not set (as written in comment "when intx interrupt was not specified in
> > > > > > > DT"). You are right that this is also the behavior in the current
> > > > > > > mainline.
> > > > > > > 
> > > > > > > I'm not sure if this comment can be split out as support for "intx"
> > > > > > > interrupt is in this patch.
> > > > > > > 
> > > > > > > > I understand it is hard but a patch is a logical _change_, this
> > > > > > > > comment is a change per se, it is a clarification on current
> > > > > > > > behaviour.
> > > > > > > 
> > > > > > > Ok, I could try to split this comment into two patches, but part about
> > > > > > > if-branch comment needs to stay in "this" patch.
> > > > > > 
> > > > > > I have done it locally.
> > > > > > 
> > > > > > Let me know when I should resend this patch series and I will include
> > > > > > into it also these changes.
> > > > > 
> > > > > Hi,
> > > > > 
> > > > > yes please resend it and I will merge it.
> > > > 
> > > > Done!
> > > > https://lore.kernel.org/linux-pci/20220222104625.28461-1-pali@kernel.org/T/#u
> > > 
> > > Can you rebase it please on top of my pci/mvebu branch ?
> > > 
> > > https://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/
> > > 
> > > Forgive me, I forgot to mention that, thanks.
> > > 
> > > Lorenzo
> > 
> > Ok! I rebased V3 on top of c3bd7dc553eea5a3595ca3aa0adee9bf83622a1f
> > (pci/mvebu branch in your repo), fixed conflicts and pushed to my git
> > repo https://git.kernel.org/pub/scm/linux/kernel/git/pali/linux.git/
> > as commit 42402f0cfc362ffb0b7e464f420d6ead342dab2b (lpieralisi-pci-mvebu
> > branch). It is enough? Or do you want me to resend it via emails?
> 
> You need to re-send it to linux-pci ML, I only apply patches posted
> there, sorry for the churn, thanks.
> 
> Lorenzo

Done!
https://lore.kernel.org/linux-pci/20220222155030.988-1-pali@kernel.org/T/#u

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts
@ 2022-02-22 15:55                       ` Pali Rohár
  0 siblings, 0 replies; 130+ messages in thread
From: Pali Rohár @ 2022-02-22 15:55 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: robh+dt, Bjorn Helgaas, Thomas Petazzoni,
	Krzysztof Wilczyński, Marek Behún, Russell King,
	Marc Zyngier, linux-pci, linux-kernel, linux-arm-kernel

On Tuesday 22 February 2022 15:45:53 Lorenzo Pieralisi wrote:
> On Tue, Feb 22, 2022 at 04:42:26PM +0100, Pali Rohár wrote:
> > On Tuesday 22 February 2022 15:24:09 Lorenzo Pieralisi wrote:
> > > On Tue, Feb 22, 2022 at 11:51:29AM +0100, Pali Rohár wrote:
> > > > On Tuesday 22 February 2022 10:21:06 Lorenzo Pieralisi wrote:
> > > > > On Thu, Feb 17, 2022 at 12:40:39AM +0100, Pali Rohár wrote:
> > > > > > On Friday 11 February 2022 18:52:02 Pali Rohár wrote:
> > > > > > > On Friday 11 February 2022 17:19:17 Lorenzo Pieralisi wrote:
> > > > > > > > On Wed, Jan 12, 2022 at 04:18:13PM +0100, Pali Rohár wrote:
> > > > > > > > > This adds support for legacy INTx interrupts received from other PCIe
> > > > > > > > > devices and which are reported by a new INTx irq chip.
> > > > > > > > > 
> > > > > > > > > With this change, kernel can distinguish between INTA, INTB, INTC and INTD
> > > > > > > > > interrupts.
> > > > > > > > > 
> > > > > > > > > Note that for this support, device tree files has to be properly adjusted
> > > > > > > > > to provide "interrupts" or "interrupts-extended" property with intx
> > > > > > > > > interrupt source, "interrupt-names" property with "intx" string and also
> > > > > > > > > 'interrupt-controller' subnode must be defined.
> > > > > > > > > 
> > > > > > > > > If device tree files do not provide these nodes then driver would work as
> > > > > > > > > before.
> > > > > > > > 
> > > > > > > > Nit: this information is not useful. DT rules are written in DT
> > > > > > > > bindings, not in kernel commit logs. All I am saying is that firmware
> > > > > > > > developers should not have to read this log to write firmware.
> > > > > > > 
> > > > > > > It was not intended for firmware developers, but for reviewers of this
> > > > > > > patch to understand, what is happening in code and that with old DT
> > > > > > > files this patch does not change driver behavior (= work as before).
> > > > > > > 
> > > > > > > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > > > > > > ---
> > > > > > > > >  drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++--
> > > > > > > > >  1 file changed, 177 insertions(+), 8 deletions(-)
> > > > > > > > > 
> > > > > > > > > diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> > > > > > > > > index 1e90ab888075..dbb6ecb4cb70 100644
> > > > > > > > > --- a/drivers/pci/controller/pci-mvebu.c
> > > > > > > > > +++ b/drivers/pci/controller/pci-mvebu.c
> > > > > > > > > @@ -54,9 +54,10 @@
> > > > > > > > >  	 PCIE_CONF_ADDR_EN)
> > > > > > > > >  #define PCIE_CONF_DATA_OFF	0x18fc
> > > > > > > > >  #define PCIE_INT_CAUSE_OFF	0x1900
> > > > > > > > > +#define PCIE_INT_UNMASK_OFF	0x1910
> > > > > > > > 
> > > > > > > > Nit: I understand it is tempting but here you are redefining or better
> > > > > > > > giving a proper label to a register. Separate patch please.
> > > > > > > 
> > > > > > > Ok!
> > > > > > > 
> > > > > > > > > +#define  PCIE_INT_INTX(i)		BIT(24+i)
> > > > > > > > >  #define  PCIE_INT_PM_PME		BIT(28)
> > > > > > > > > -#define PCIE_MASK_OFF		0x1910
> > > > > > > > 
> > > > > > > > See above.
> > > > > > > > 
> > > > > > > > > -#define  PCIE_MASK_ENABLE_INTS          0x0f000000
> > > > > > > > > +#define  PCIE_INT_ALL_MASK		GENMASK(31, 0)
> > > > > > > > >  #define PCIE_CTRL_OFF		0x1a00
> > > > > > > > >  #define  PCIE_CTRL_X1_MODE		0x0001
> > > > > > > > >  #define  PCIE_CTRL_RC_MODE		BIT(1)
> > > > > > > > > @@ -110,6 +111,9 @@ struct mvebu_pcie_port {
> > > > > > > > >  	struct mvebu_pcie_window iowin;
> > > > > > > > >  	u32 saved_pcie_stat;
> > > > > > > > >  	struct resource regs;
> > > > > > > > > +	struct irq_domain *intx_irq_domain;
> > > > > > > > > +	raw_spinlock_t irq_lock;
> > > > > > > > > +	int intx_irq;
> > > > > > > > >  };
> > > > > > > > >  
> > > > > > > > >  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
> > > > > > > > > @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
> > > > > > > > >  
> > > > > > > > >  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > > > > >  {
> > > > > > > > > -	u32 ctrl, lnkcap, cmd, dev_rev, mask;
> > > > > > > > > +	u32 ctrl, lnkcap, cmd, dev_rev, unmask;
> > > > > > > > >  
> > > > > > > > >  	/* Setup PCIe controller to Root Complex mode. */
> > > > > > > > >  	ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
> > > > > > > > > @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
> > > > > > > > >  	/* Point PCIe unit MBUS decode windows to DRAM space. */
> > > > > > > > >  	mvebu_pcie_setup_wins(port);
> > > > > > > > >  
> > > > > > > > > -	/* Enable interrupt lines A-D. */
> > > > > > > > > -	mask = mvebu_readl(port, PCIE_MASK_OFF);
> > > > > > > > > -	mask |= PCIE_MASK_ENABLE_INTS;
> > > > > > > > > -	mvebu_writel(port, mask, PCIE_MASK_OFF);
> > > > > > > > > +	/* Mask all interrupt sources. */
> > > > > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
> > > > > > > > > +
> > > > > > > > > +	/* Clear all interrupt causes. */
> > > > > > > > > +	mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF);
> > > > > > > > > +
> > > > > > > > > +	if (port->intx_irq <= 0) {
> > > > > > > > > +		/*
> > > > > > > > > +		 * When neither "summary" interrupt, nor "intx" interrupt was
> > > > > > > > > +		 * specified in DT then unmask all legacy INTx interrupts as in
> > > > > > > > > +		 * this case driver does not provide a way for masking and
> > > > > > > > > +		 * unmasking of individual legacy INTx interrupts. In this case
> > > > > > > > > +		 * all interrupts, including legacy INTx are reported via one
> > > > > > > > > +		 * shared GIC source and therefore kernel cannot distinguish
> > > > > > > > > +		 * which individual legacy INTx was triggered. These interrupts
> > > > > > > > > +		 * are shared, so it should not cause any issue. Just
> > > > > > > > > +		 * performance penalty as every PCIe interrupt handler needs to
> > > > > > > > > +		 * be called when some interrupt is triggered.
> > > > > > > > > +		 */
> > > > > > > > 
> > > > > > > > This comment applies to current mainline right (ie it describes how
> > > > > > > > current mainline handles INTx) ? IMO you should split it out in a
> > > > > > > > separate patch.
> > > > > > > 
> > > > > > > This above comment describe what happens in if-branch when intx_irq is
> > > > > > > not set (as written in comment "when intx interrupt was not specified in
> > > > > > > DT"). You are right that this is also the behavior in the current
> > > > > > > mainline.
> > > > > > > 
> > > > > > > I'm not sure if this comment can be split out as support for "intx"
> > > > > > > interrupt is in this patch.
> > > > > > > 
> > > > > > > > I understand it is hard but a patch is a logical _change_, this
> > > > > > > > comment is a change per se, it is a clarification on current
> > > > > > > > behaviour.
> > > > > > > 
> > > > > > > Ok, I could try to split this comment into two patches, but part about
> > > > > > > if-branch comment needs to stay in "this" patch.
> > > > > > 
> > > > > > I have done it locally.
> > > > > > 
> > > > > > Let me know when I should resend this patch series and I will include
> > > > > > into it also these changes.
> > > > > 
> > > > > Hi,
> > > > > 
> > > > > yes please resend it and I will merge it.
> > > > 
> > > > Done!
> > > > https://lore.kernel.org/linux-pci/20220222104625.28461-1-pali@kernel.org/T/#u
> > > 
> > > Can you rebase it please on top of my pci/mvebu branch ?
> > > 
> > > https://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/
> > > 
> > > Forgive me, I forgot to mention that, thanks.
> > > 
> > > Lorenzo
> > 
> > Ok! I rebased V3 on top of c3bd7dc553eea5a3595ca3aa0adee9bf83622a1f
> > (pci/mvebu branch in your repo), fixed conflicts and pushed to my git
> > repo https://git.kernel.org/pub/scm/linux/kernel/git/pali/linux.git/
> > as commit 42402f0cfc362ffb0b7e464f420d6ead342dab2b (lpieralisi-pci-mvebu
> > branch). It is enough? Or do you want me to resend it via emails?
> 
> You need to re-send it to linux-pci ML, I only apply patches posted
> there, sorry for the churn, thanks.
> 
> Lorenzo

Done!
https://lore.kernel.org/linux-pci/20220222155030.988-1-pali@kernel.org/T/#u

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 130+ messages in thread

end of thread, other threads:[~2022-02-22 16:02 UTC | newest]

Thread overview: 130+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-05 15:02 [PATCH 00/11] PCI: mvebu: subsystem ids, AER and INTx Pali Rohár
2022-01-05 15:02 ` Pali Rohár
2022-01-05 15:02 ` [PATCH 01/11] PCI: pci-bridge-emul: Re-arrange register tests Pali Rohár
2022-01-05 15:02   ` Pali Rohár
2022-01-05 15:02 ` [PATCH 02/11] PCI: pci-bridge-emul: Add support for PCIe extended capabilities Pali Rohár
2022-01-05 15:02   ` Pali Rohár
2022-01-05 15:02 ` [PATCH 03/11] PCI: pci-bridge-emul: Add support for PCI Bridge Subsystem Vendor ID capability Pali Rohár
2022-01-05 15:02   ` Pali Rohár
2022-01-05 15:02 ` [PATCH 04/11] dt-bindings: PCI: mvebu: Add num-lanes property Pali Rohár
2022-01-05 15:02   ` Pali Rohár
2022-01-12  1:29   ` Rob Herring
2022-01-12  1:29     ` Rob Herring
2022-01-05 15:02 ` [PATCH 05/11] PCI: mvebu: Correctly configure x1/x4 mode Pali Rohár
2022-01-05 15:02   ` Pali Rohár
2022-01-05 15:02 ` [PATCH 06/11] PCI: mvebu: Add support for PCI Bridge Subsystem Vendor ID on emulated bridge Pali Rohár
2022-01-05 15:02   ` Pali Rohár
2022-01-05 15:02 ` [PATCH 07/11] PCI: mvebu: Add support for Advanced Error Reporting registers " Pali Rohár
2022-01-05 15:02   ` Pali Rohár
2022-01-05 15:02 ` [PATCH 08/11] PCI: mvebu: Use child_ops API Pali Rohár
2022-01-05 15:02   ` Pali Rohár
2022-01-05 15:41   ` Rob Herring
2022-01-05 15:41     ` Rob Herring
2022-01-05 15:49     ` Pali Rohár
2022-01-05 15:49       ` Pali Rohár
2022-01-12  1:43     ` Pali Rohár
2022-01-12  1:43       ` Pali Rohár
2022-01-12 14:53       ` Rob Herring
2022-01-12 14:53         ` Rob Herring
2022-01-05 15:02 ` [PATCH 09/11] dt-bindings: PCI: mvebu: Update information about intx interrupts Pali Rohár
2022-01-05 15:02   ` Pali Rohár
2022-01-12  1:30   ` Rob Herring
2022-01-12  1:30     ` Rob Herring
2022-01-05 15:02 ` [PATCH 10/11] PCI: mvebu: Implement support for legacy INTx interrupts Pali Rohár
2022-01-05 15:02   ` Pali Rohár
2022-01-06 15:28   ` Marc Zyngier
2022-01-06 15:28     ` Marc Zyngier
2022-01-06 15:44     ` Pali Rohár
2022-01-06 15:44       ` Pali Rohár
2022-01-06 15:55       ` Marc Zyngier
2022-01-06 15:55         ` Marc Zyngier
2022-01-06 16:20         ` Pali Rohár
2022-01-06 16:20           ` Pali Rohár
2022-01-06 16:27           ` Marc Zyngier
2022-01-06 16:27             ` Marc Zyngier
2022-01-06 17:20             ` Marek Behún
2022-01-06 17:20               ` Marek Behún
2022-01-06 17:31               ` Marc Zyngier
2022-01-06 17:31                 ` Marc Zyngier
2022-01-07 11:50                 ` Pali Rohár
2022-01-07 11:50                   ` Pali Rohár
2022-01-07 18:53                   ` Marc Zyngier
2022-01-07 18:53                     ` Marc Zyngier
2022-01-05 15:02 ` [PATCH 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe " Pali Rohár
2022-01-05 15:02   ` Pali Rohár
2022-01-12 15:18 ` [PATCH v2 00/11] PCI: mvebu: subsystem ids, AER and INTx Pali Rohár
2022-01-12 15:18   ` Pali Rohár
2022-01-12 15:18   ` [PATCH v2 01/11] PCI: pci-bridge-emul: Re-arrange register tests Pali Rohár
2022-01-12 15:18     ` Pali Rohár
2022-01-12 15:18   ` [PATCH v2 02/11] PCI: pci-bridge-emul: Add support for PCIe extended capabilities Pali Rohár
2022-01-12 15:18     ` Pali Rohár
2022-01-12 15:18   ` [PATCH v2 03/11] PCI: pci-bridge-emul: Add support for PCI Bridge Subsystem Vendor ID capability Pali Rohár
2022-01-12 15:18     ` Pali Rohár
2022-01-12 15:18   ` [PATCH v2 04/11] dt-bindings: PCI: mvebu: Add num-lanes property Pali Rohár
2022-01-12 15:18     ` Pali Rohár
2022-01-12 15:18   ` [PATCH v2 05/11] PCI: mvebu: Correctly configure x1/x4 mode Pali Rohár
2022-01-12 15:18     ` Pali Rohár
2022-01-20 17:09     ` Rob Herring
2022-01-20 17:09       ` Rob Herring
2022-01-20 17:19       ` Pali Rohár
2022-01-20 17:19         ` Pali Rohár
2022-01-12 15:18   ` [PATCH v2 06/11] PCI: mvebu: Add support for PCI Bridge Subsystem Vendor ID on emulated bridge Pali Rohár
2022-01-12 15:18     ` Pali Rohár
2022-01-12 15:18   ` [PATCH v2 07/11] PCI: mvebu: Add support for Advanced Error Reporting registers " Pali Rohár
2022-01-12 15:18     ` Pali Rohár
2022-01-12 15:18   ` [PATCH v2 08/11] PCI: mvebu: Use child_ops API Pali Rohár
2022-01-12 15:18     ` Pali Rohár
2022-01-20 16:49     ` Rob Herring
2022-01-20 16:49       ` Rob Herring
2022-01-20 16:55       ` Pali Rohár
2022-01-20 16:55         ` Pali Rohár
2022-01-20 18:40         ` Rob Herring
2022-01-20 18:40           ` Rob Herring
2022-01-12 15:18   ` [PATCH v2 09/11] dt-bindings: PCI: mvebu: Update information about intx interrupts Pali Rohár
2022-01-12 15:18     ` Pali Rohár
2022-01-12 15:36     ` Marek Behún
2022-01-12 15:36       ` Marek Behún
2022-01-12 15:18   ` [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts Pali Rohár
2022-01-12 15:18     ` Pali Rohár
2022-02-11 17:19     ` Lorenzo Pieralisi
2022-02-11 17:19       ` Lorenzo Pieralisi
2022-02-11 17:52       ` Pali Rohár
2022-02-11 17:52         ` Pali Rohár
2022-02-11 18:21         ` Lorenzo Pieralisi
2022-02-11 18:21           ` Lorenzo Pieralisi
2022-02-12 10:59           ` Marc Zyngier
2022-02-12 10:59             ` Marc Zyngier
2022-02-16 23:40         ` Pali Rohár
2022-02-16 23:40           ` Pali Rohár
2022-02-22 10:21           ` Lorenzo Pieralisi
2022-02-22 10:21             ` Lorenzo Pieralisi
2022-02-22 10:51             ` Pali Rohár
2022-02-22 10:51               ` Pali Rohár
2022-02-22 15:24               ` Lorenzo Pieralisi
2022-02-22 15:24                 ` Lorenzo Pieralisi
2022-02-22 15:42                 ` Pali Rohár
2022-02-22 15:42                   ` Pali Rohár
2022-02-22 15:45                   ` Lorenzo Pieralisi
2022-02-22 15:45                     ` Lorenzo Pieralisi
2022-02-22 15:55                     ` Pali Rohár
2022-02-22 15:55                       ` Pali Rohár
2022-01-12 15:18   ` [PATCH v2 11/11] ARM: dts: armada-385.dtsi: Add definitions for PCIe " Pali Rohár
2022-01-12 15:18     ` Pali Rohár
2022-02-14 15:07     ` Gregory CLEMENT
2022-02-14 15:07       ` Gregory CLEMENT
2022-02-14 15:09       ` Pali Rohár
2022-02-14 15:09         ` Pali Rohár
2022-02-14 15:26         ` Gregory CLEMENT
2022-02-14 15:26           ` Gregory CLEMENT
     [not found]           ` <CAEzXK1qYKVk7QiSY_DwqkZ7WV6WU06WBtiqZx0JJCc+mOP-7Kg@mail.gmail.com>
2022-02-15 10:48             ` Luís Mendes
2022-02-15 10:48               ` Luís Mendes
2022-02-15 10:52               ` Pali Rohár
2022-02-15 10:52                 ` Pali Rohár
2022-02-18 21:53                 ` Luís Mendes
2022-02-18 21:53                   ` Luís Mendes
2022-02-19 13:36                   ` Pali Rohár
2022-02-19 13:36                     ` Pali Rohár
2022-02-11 17:50 ` [PATCH 00/11] PCI: mvebu: subsystem ids, AER and INTx Lorenzo Pieralisi
2022-02-11 17:50   ` Lorenzo Pieralisi
2022-02-11 18:01   ` Pali Rohár
2022-02-11 18:01     ` Pali Rohár

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.