From 955268e13f8f9422e7e89ee6350ec793dddd1e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Ko=C4=8D=C3=AD?= Date: Tue, 1 Nov 2022 09:44:59 +0100 Subject: nixos: try to fix Turris Omnia PCIe on Linux 6.0 Unfortunatelly this seems to not work. --- ...dd-support-for-PCI_EXP_SLTSTA_DLLSC-via-h.patch | 297 --------------------- 1 file changed, 297 deletions(-) delete mode 100644 nixos/modules/kernel-patches/0014-PCI-mvebu-Add-support-for-PCI_EXP_SLTSTA_DLLSC-via-h.patch (limited to 'nixos/modules/kernel-patches/0014-PCI-mvebu-Add-support-for-PCI_EXP_SLTSTA_DLLSC-via-h.patch') diff --git a/nixos/modules/kernel-patches/0014-PCI-mvebu-Add-support-for-PCI_EXP_SLTSTA_DLLSC-via-h.patch b/nixos/modules/kernel-patches/0014-PCI-mvebu-Add-support-for-PCI_EXP_SLTSTA_DLLSC-via-h.patch deleted file mode 100644 index febba42..0000000 --- a/nixos/modules/kernel-patches/0014-PCI-mvebu-Add-support-for-PCI_EXP_SLTSTA_DLLSC-via-h.patch +++ /dev/null @@ -1,297 +0,0 @@ -From 1acf23b5be75ad9981eafb94044e507a53cb29c8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pali=20Roh=C3=A1r?= -Date: Fri, 17 Sep 2021 14:53:11 +0200 -Subject: [PATCH 14/96] PCI: mvebu: Add support for PCI_EXP_SLTSTA_DLLSC via - hot plug interrupt -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -If link up/down state is changed in mvebu_pcie_link_up() then trigger -hot plug interrupt with DLLSC state change. - -Also triggers hot plug interrupt when mvebu triggers Link Failure interrupt -which indicates that link was changed from active state or when mvebu -triggers TxReq No Link interrupt which indicates that link is down while -trying to transmit PCIe transaction. - -And this hot plug interrupt also when explicit Link Disable or PCIe Host -Reset is issued as mvebu does not trigger Link Failure when dropping to -Detect via Hot Reset or Link Disable. - -Signed-off-by: Pali Rohár ---- - drivers/pci/controller/Kconfig | 3 + - drivers/pci/controller/pci-mvebu.c | 147 ++++++++++++++++++++++++++++- - 2 files changed, 149 insertions(+), 1 deletion(-) - -diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig -index b8d96d38064d..e4635712dbce 100644 ---- a/drivers/pci/controller/Kconfig -+++ b/drivers/pci/controller/Kconfig -@@ -10,6 +10,9 @@ config PCI_MVEBU - depends on ARM - depends on OF - select PCI_BRIDGE_EMUL -+ select PCIEPORTBUS -+ select HOTPLUG_PCI -+ select HOTPLUG_PCI_PCIE - help - Add support for Marvell EBU PCIe controller. This PCIe controller - is used on 32-bit Marvell ARM SoCs: Dove, Kirkwood, Armada 370, -diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c -index 56924b0a1969..d832c5135d5c 100644 ---- a/drivers/pci/controller/pci-mvebu.c -+++ b/drivers/pci/controller/pci-mvebu.c -@@ -56,12 +56,14 @@ - #define PCIE_CONF_DATA_OFF 0x18fc - #define PCIE_INT_CAUSE_OFF 0x1900 - #define PCIE_INT_UNMASK_OFF 0x1910 -+#define PCIE_INT_TXREQ_NOLINK BIT(0) - #define PCIE_INT_DET_COR BIT(8) - #define PCIE_INT_DET_NONFATAL BIT(9) - #define PCIE_INT_DET_FATAL BIT(10) - #define PCIE_INT_ERR_FATAL BIT(16) - #define PCIE_INT_ERR_NONFATAL BIT(17) - #define PCIE_INT_ERR_COR BIT(18) -+#define PCIE_INT_LINK_FAIL BIT(23) - #define PCIE_INT_INTX(i) BIT(24+i) - #define PCIE_INT_PM_PME BIT(28) - #define PCIE_INT_DET_MASK (PCIE_INT_DET_COR | PCIE_INT_DET_NONFATAL | PCIE_INT_DET_FATAL) -@@ -134,6 +136,8 @@ struct mvebu_pcie_port { - int error_irq; - int intx_irq; - bool pme_pending; -+ struct timer_list link_irq_timer; -+ bool link_was_up; - }; - - static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg) -@@ -153,7 +157,26 @@ static inline bool mvebu_has_ioport(struct mvebu_pcie_port *port) - - static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port) - { -- return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN); -+ bool link_is_up; -+ u16 slotsta; -+ -+ link_is_up = !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN); -+ -+ if (link_is_up != port->link_was_up) { -+ port->link_was_up = link_is_up; -+ /* -+ * Link IRQ timer/handler is available only when "error" -+ * interrupt was specified in DT. -+ */ -+ if (port->error_irq > 0) { -+ slotsta = le16_to_cpu(port->bridge.pcie_conf.slotsta); -+ port->bridge.pcie_conf.slotsta = -+ cpu_to_le16(slotsta | PCI_EXP_SLTSTA_DLLSC); -+ mod_timer(&port->link_irq_timer, jiffies + 1); -+ } -+ } -+ -+ return link_is_up; - } - - static u8 mvebu_pcie_get_local_bus_nr(struct mvebu_pcie_port *port) -@@ -346,6 +369,19 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port) - mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF); - } - -+ /* -+ * Unmask No Link and Link Failure interrupts to process Link Down -+ * events. These events are reported as Data Link Layer State Changed -+ * notification via Hot Plug Interrupt. Other parts of Link change -+ * events are available only when "error" interrupt was specified in DT. -+ * So enable these interrupts under same conditions. -+ */ -+ if (port->error_irq > 0) { -+ unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF); -+ unmask |= PCIE_INT_TXREQ_NOLINK | PCIE_INT_LINK_FAIL; -+ mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF); -+ } -+ - /* - * Fallback code when "intx" interrupt was not specified in DT: - * Unmask all legacy INTx interrupts as driver does not provide a way -@@ -692,6 +728,14 @@ mvebu_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge, - val |= slotctl & PCI_EXP_SLTCTL_ASPL_DISABLE; - else if (!(mvebu_readl(port, PCIE_SSPL_OFF) & PCIE_SSPL_ENABLE)) - val |= PCI_EXP_SLTCTL_ASPL_DISABLE; -+ /* -+ * HPIE and DLLSCE bits are stored only in emulated config -+ * space buffer and are supported only when or "error" interrupt -+ * was specified in DT. -+ */ -+ if (port->error_irq > 0) -+ val |= slotctl & (PCI_EXP_SLTCTL_HPIE | -+ PCI_EXP_SLTCTL_DLLSCE); - /* This callback is 32-bit and in high bits is slot status. */ - val |= slotsta << 16; - *value = val; -@@ -823,6 +867,25 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge, - else - ctrl &= ~PCIE_CTRL_MASTER_HOT_RESET; - mvebu_writel(port, ctrl, PCIE_CTRL_OFF); -+ /* -+ * When dropping to Detect via Hot Reset, Disable Link -+ * or Loopback states, the Link Failure interrupt is not -+ * asserted. So when setting Secondary Bus Reset / Hot -+ * Reset bit, call link IRQ timer/handler manually. -+ */ -+ if ((ctrl & PCIE_CTRL_MASTER_HOT_RESET) && port->link_was_up) { -+ port->link_was_up = false; -+ /* -+ * Link IRQ timer/handler is available only when -+ * "error" interrupt was specified in DT. -+ */ -+ if (port->error_irq > 0) { -+ u16 slotsta = le16_to_cpu(port->bridge.pcie_conf.slotsta); -+ port->bridge.pcie_conf.slotsta = -+ cpu_to_le16(slotsta | PCI_EXP_SLTSTA_DLLSC); -+ mod_timer(&port->link_irq_timer, jiffies + 1); -+ } -+ } - } - break; - -@@ -851,6 +914,25 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge, - new &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - - mvebu_writel(port, new, PCIE_CAP_PCIEXP + PCI_EXP_LNKCTL); -+ /* -+ * When dropping to Detect via Hot Reset, Disable Link -+ * or Loopback states, the Link Failure interrupt is not -+ * asserted. So when setting Link Disable bit, call link -+ * IRQ timer/handler manually. -+ */ -+ if ((new & PCI_EXP_LNKCTL_LD) && port->link_was_up) { -+ port->link_was_up = false; -+ /* -+ * Link IRQ timer/handler is available only when -+ * "error" interrupt was specified in DT. -+ */ -+ if (port->error_irq > 0) { -+ u16 slotsta = le16_to_cpu(port->bridge.pcie_conf.slotsta); -+ port->bridge.pcie_conf.slotsta = -+ cpu_to_le16(slotsta | PCI_EXP_SLTSTA_DLLSC); -+ mod_timer(&port->link_irq_timer, jiffies + 1); -+ } -+ } - break; - - case PCI_EXP_SLTCTL: -@@ -991,6 +1073,15 @@ static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port) - bridge->pcie_conf.cap = cpu_to_le16(pcie_cap_ver | PCI_EXP_FLAGS_SLOT); - - /* -+ * When "error" interrupt was specified in DT then driver is able to -+ * deliver Data Link Layer State Change interrupt. So in this case mark -+ * bridge as Hot Plug Capable as this is the way how to enable -+ * delivering of Data Link Layer State Change interrupts. -+ * -+ * No Command Completed Support is set because bridge does not support -+ * Command Completed Interrupt. Every command is executed immediately -+ * without any delay. -+ * - * Set Presence Detect State bit permanently as there is no support for - * unplugging PCIe card from the slot. Assume that PCIe card is always - * connected in slot. -@@ -1002,6 +1093,8 @@ static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port) - * Also set correct slot power limit. - */ - bridge->pcie_conf.slotcap = cpu_to_le32( -+ PCI_EXP_SLTCAP_NCCS | -+ (port->error_irq > 0 ? PCI_EXP_SLTCAP_HPC : 0) | - FIELD_PREP(PCI_EXP_SLTCAP_SPLV, port->slot_power_limit_value) | - FIELD_PREP(PCI_EXP_SLTCAP_SPLS, port->slot_power_limit_scale) | - FIELD_PREP(PCI_EXP_SLTCAP_PSN, port->port+1)); -@@ -1191,11 +1284,29 @@ static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port) - return 0; - } - -+static void mvebu_pcie_link_irq_handler(struct timer_list *timer) -+{ -+ struct mvebu_pcie_port *port = from_timer(port, timer, link_irq_timer); -+ struct device *dev = &port->pcie->pdev->dev; -+ u16 slotctl; -+ -+ dev_info(dev, "%s: link %s\n", port->name, port->link_was_up ? "up" : "down"); -+ -+ slotctl = le16_to_cpu(port->bridge.pcie_conf.slotctl); -+ if (!(slotctl & PCI_EXP_SLTCTL_DLLSCE) || -+ !(slotctl & PCI_EXP_SLTCTL_HPIE)) -+ return; -+ -+ if (generic_handle_domain_irq(port->rp_irq_domain, 0) == -EINVAL) -+ dev_err_ratelimited(dev, "unhandled HP IRQ\n"); -+} -+ - static irqreturn_t mvebu_pcie_error_irq_handler(int irq, void *arg) - { - struct mvebu_pcie_port *port = arg; - struct device *dev = &port->pcie->pdev->dev; - u32 cause, unmask, status; -+ u16 slotsta; - - cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF); - unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF); -@@ -1233,6 +1344,25 @@ static irqreturn_t mvebu_pcie_error_irq_handler(int irq, void *arg) - dev_err_ratelimited(dev, "unhandled ERR IRQ\n"); - } - -+ /* Process No Link and Link Failure interrupts as HP IRQ */ -+ if (status & (PCIE_INT_TXREQ_NOLINK | PCIE_INT_LINK_FAIL)) { -+ mvebu_writel(port, -+ ~(PCIE_INT_TXREQ_NOLINK | PCIE_INT_LINK_FAIL), -+ PCIE_INT_CAUSE_OFF); -+ if (port->link_was_up) { -+ port->link_was_up = false; -+ slotsta = le16_to_cpu(port->bridge.pcie_conf.slotsta); -+ port->bridge.pcie_conf.slotsta = -+ cpu_to_le16(slotsta | PCI_EXP_SLTSTA_DLLSC); -+ /* -+ * Deactivate timer and call mvebu_pcie_link_irq_handler() -+ * function directly as we are in the interrupt context. -+ */ -+ del_timer_sync(&port->link_irq_timer); -+ mvebu_pcie_link_irq_handler(&port->link_irq_timer); -+ } -+ } -+ - return status ? IRQ_HANDLED : IRQ_NONE; - } - -@@ -1798,6 +1928,18 @@ static int mvebu_pcie_probe(struct platform_device *pdev) - } - } - -+ /* -+ * Function mvebu_pcie_link_irq_handler() calls function -+ * generic_handle_irq() and it expects local IRQs to be disabled -+ * as normally generic_handle_irq() is called from the interrupt -+ * context. So use TIMER_IRQSAFE flag for this link_irq_timer. -+ * Available only if "or "error" interrupt was specified. -+ */ -+ if (port->error_irq > 0) -+ timer_setup(&port->link_irq_timer, -+ mvebu_pcie_link_irq_handler, -+ TIMER_IRQSAFE); -+ - /* - * PCIe topology exported by mvebu hw is quite complicated. In - * reality has something like N fully independent host bridges -@@ -1934,6 +2076,9 @@ static int mvebu_pcie_remove(struct platform_device *pdev) - irq_domain_remove(port->rp_irq_domain); - } - -+ if (port->error_irq > 0) -+ del_timer_sync(&port->link_irq_timer); -+ - /* Free config space for emulated root bridge. */ - pci_bridge_emul_cleanup(&port->bridge); - --- -2.37.2 - -- cgit v1.2.3