PCI: aardvark: Clear all MSIs at setup
PATCH 1/2 PCI: aardvark: Clear all MSIs at setup
From: Pali Rohár <[email protected]>
[ Upstream commit 7d8dc1f7cd007a7ce94c5b4c20d63a8b8d6d7751 ]
We already clear all the other interrupts (ISR0, ISR1, HOST_CTRL_INT).
Define a new macro PCIE_MSI_ALL_MASK and do the same clearing for MSIs, to ensure that we don't start receiving spurious interrupts.
Use this new mask in advk_pcie_handle_msi();
--- drivers/pci/controller/pci-aardvark.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/pci/controller/pci-aardvark.c +4 -2
@@ -108,6 +108,7 @@#define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54)#define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58)#define PCIE_MSI_MASK_REG (CONTROL_BASE_ADDR + 0x5C) +#define PCIE_MSI_ALL_MASK GENMASK(31, 0)#define PCIE_MSI_PAYLOAD_REG (CONTROL_BASE_ADDR + 0x9C)#define PCIE_MSI_DATA_MASK GENMASK(15, 0)
@@ -561,6 +562,7 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)advk_writel (pcie, reg,PCIE_CORE_CTRL2_REG );/* Clear all interrupts */ +advk_writel (pcie,PCIE_MSI_ALL_MASK ,PCIE_MSI_STATUS_REG );advk_writel (pcie,PCIE_ISR0_ALL_MASK ,PCIE_ISR0_REG );advk_writel (pcie,PCIE_ISR1_ALL_MASK ,PCIE_ISR1_REG );advk_writel (pcie,PCIE_IRQ_ALL_MASK ,HOST_CTRL_INT_STATUS_REG );
@@ -573,7 +575,7 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)advk_writel (pcie,PCIE_ISR1_ALL_MASK ,PCIE_ISR1_MASK_REG );/* Unmask all MSIs */ -advk_writel (pcie,0 ,PCIE_MSI_MASK_REG ); +advk_writel (pcie, ~(u32 )PCIE_MSI_ALL_MASK ,PCIE_MSI_MASK_REG );/* Enable summary interrupt for GIC SPI source */ reg =PCIE_IRQ_ALL_MASK & (~PCIE_IRQ_ENABLE_INTS_MASK );
@@ -1374,7 +1376,7 @@ static void advk_pcie_handle_msi(struct advk_pcie *pcie) msi_mask =advk_readl (pcie,PCIE_MSI_MASK_REG ); msi_val =advk_readl (pcie,PCIE_MSI_STATUS_REG ); - msi_status = msi_val & ~msi_mask; + msi_status = msi_val & ((~msi_mask) &PCIE_MSI_ALL_MASK );for (msi_idx =0 ; msi_idx <MSI_IRQ_NUM ; msi_idx++) {if (!(BIT (msi_idx) & msi_status))
Signature · 1 line
2.35.1
PATCH 2/2 PCI: aardvark: Fix reading MSI interrupt number
From: Pali Rohár <[email protected]>
[ Upstream commit 805dfc18dd3d4dd97a987d4406593b5a225b1253 ]
In advk_pcie_handle_msi() the authors expect that when bit i in the W1C register PCIE_MSI_STATUS_REG is cleared, the PCIE_MSI_PAYLOAD_REG is updated to contain the MSI number corresponding to index i.
Experiments show that this is not so, and instead PCIE_MSI_PAYLOAD_REG always contains the number of the last received MSI, overall.
Do not read PCIE_MSI_PAYLOAD_REG register for determining MSI interrupt number. Since Aardvark already forbids more than 32 interrupts and uses own allocated hwirq numbers, the msi_idx already corresponds to the received MSI number.
---
As explained in https://lore.kernel.org/stable/[email protected]/
for 4.14, this needs to be applied ASAP to stable, since another commit was put into stable that breaks this driver.
Thx :)
--- drivers/pci/controller/pci-aardvark.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
drivers/pci/controller/pci-aardvark.c +3 -7
@@ -1372,7 +1372,7 @@ static void advk_pcie_remove_irq_domain(struct advk_pcie *pcie)static void advk_pcie_handle_msi (struct advk_pcie *pcie) {u32 msi_val, msi_mask, msi_status, msi_idx; -u16 msi_data; +int virq; msi_mask =advk_readl (pcie,PCIE_MSI_MASK_REG ); msi_val =advk_readl (pcie,PCIE_MSI_STATUS_REG );
@@ -1382,13 +1382,9 @@ static void advk_pcie_handle_msi(struct advk_pcie *pcie)if (!(BIT (msi_idx) & msi_status))continue ; -/* -* msi_idx contains bits [4:0] of the msi_data and msi_data -* contains 16bit MSI interrupt number -*/ advk_writel (pcie,BIT (msi_idx),PCIE_MSI_STATUS_REG ); - msi_data =advk_readl (pcie,PCIE_MSI_PAYLOAD_REG ) &PCIE_MSI_DATA_MASK ; -generic_handle_irq (msi_data); + virq =irq_find_mapping (pcie->msi_inner_domain, msi_idx); +generic_handle_irq (virq); } advk_writel(pcie, PCIE_ISR0_MSI_INT_PENDING,
Signature · 1 line
2.35.1