Currently, the DesignWare PCIe driver cannot configure interrupts on SoC that do not support MSIX. All MSI interrupts are handled by CPU0. Backport MSI affinity support for the PCI dwc driver from linux-next, so now we can adjust MSI interrupts to other CPU cores. Tested on HINLINK H28K (RK3528) and OrangePi R2S (Ky X1). Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn> Link: https://github.com/openwrt/openwrt/pull/21770 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
145 lines
4.5 KiB
Diff
145 lines
4.5 KiB
Diff
From a60d92f6d941bd77bf3aaec724a7c95857c0165b Mon Sep 17 00:00:00 2001
|
|
From: Mayank Rana <mayank.rana@oss.qualcomm.com>
|
|
Date: Mon, 16 Jun 2025 15:42:56 -0700
|
|
Subject: [PATCH] PCI: dwc: Export DWC MSI controller related APIs
|
|
|
|
Export dw_pcie_msi_host_init(), dw_pcie_msi_init(), and dw_pcie_free_msi()
|
|
APIs to allow them to be reused by the upcoming DWC based ECAM driver
|
|
implementation. Also, move MSI IRQ related initialization code to
|
|
dw_pcie_msi_init(), as this code must be executed before dw_pcie_msi_init()
|
|
API can be used with ECAM driver.
|
|
|
|
Signed-off-by: Mayank Rana <mayank.rana@oss.qualcomm.com>
|
|
[mani: commit message rewording]
|
|
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
|
|
Link: https://patch.msgid.link/20250616224259.3549811-2-mayank.rana@oss.qualcomm.com
|
|
---
|
|
.../pci/controller/dwc/pcie-designware-host.c | 38 ++++++++++---------
|
|
drivers/pci/controller/dwc/pcie-designware.h | 14 +++++++
|
|
2 files changed, 34 insertions(+), 18 deletions(-)
|
|
|
|
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
|
|
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
|
|
@@ -250,7 +250,7 @@ int dw_pcie_allocate_domains(struct dw_p
|
|
return 0;
|
|
}
|
|
|
|
-static void dw_pcie_free_msi(struct dw_pcie_rp *pp)
|
|
+void dw_pcie_free_msi(struct dw_pcie_rp *pp)
|
|
{
|
|
u32 ctrl;
|
|
|
|
@@ -263,19 +263,34 @@ static void dw_pcie_free_msi(struct dw_p
|
|
irq_domain_remove(pp->msi_domain);
|
|
irq_domain_remove(pp->irq_domain);
|
|
}
|
|
+EXPORT_SYMBOL_GPL(dw_pcie_free_msi);
|
|
|
|
-static void dw_pcie_msi_init(struct dw_pcie_rp *pp)
|
|
+void dw_pcie_msi_init(struct dw_pcie_rp *pp)
|
|
{
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
u64 msi_target = (u64)pp->msi_data;
|
|
+ u32 ctrl, num_ctrls;
|
|
|
|
if (!pci_msi_enabled() || !pp->has_msi_ctrl)
|
|
return;
|
|
|
|
+ num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
|
|
+
|
|
+ /* Initialize IRQ Status array */
|
|
+ for (ctrl = 0; ctrl < num_ctrls; ctrl++) {
|
|
+ dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK +
|
|
+ (ctrl * MSI_REG_CTRL_BLOCK_SIZE),
|
|
+ pp->irq_mask[ctrl]);
|
|
+ dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_ENABLE +
|
|
+ (ctrl * MSI_REG_CTRL_BLOCK_SIZE),
|
|
+ ~0);
|
|
+ }
|
|
+
|
|
/* Program the msi_data */
|
|
dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_LO, lower_32_bits(msi_target));
|
|
dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_HI, upper_32_bits(msi_target));
|
|
}
|
|
+EXPORT_SYMBOL_GPL(dw_pcie_msi_init);
|
|
|
|
static int dw_pcie_parse_split_msi_irq(struct dw_pcie_rp *pp)
|
|
{
|
|
@@ -317,7 +332,7 @@ static int dw_pcie_parse_split_msi_irq(s
|
|
return 0;
|
|
}
|
|
|
|
-static int dw_pcie_msi_host_init(struct dw_pcie_rp *pp)
|
|
+int dw_pcie_msi_host_init(struct dw_pcie_rp *pp)
|
|
{
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
struct device *dev = pci->dev;
|
|
@@ -391,6 +406,7 @@ static int dw_pcie_msi_host_init(struct
|
|
|
|
return 0;
|
|
}
|
|
+EXPORT_SYMBOL_GPL(dw_pcie_msi_host_init);
|
|
|
|
static void dw_pcie_host_request_msg_tlp_res(struct dw_pcie_rp *pp)
|
|
{
|
|
@@ -809,7 +825,7 @@ static int dw_pcie_iatu_setup(struct dw_
|
|
int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
|
|
{
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
- u32 val, ctrl, num_ctrls;
|
|
+ u32 val;
|
|
int ret;
|
|
|
|
/*
|
|
@@ -820,20 +836,6 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *
|
|
|
|
dw_pcie_setup(pci);
|
|
|
|
- if (pp->has_msi_ctrl) {
|
|
- num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
|
|
-
|
|
- /* Initialize IRQ Status array */
|
|
- for (ctrl = 0; ctrl < num_ctrls; ctrl++) {
|
|
- dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK +
|
|
- (ctrl * MSI_REG_CTRL_BLOCK_SIZE),
|
|
- pp->irq_mask[ctrl]);
|
|
- dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_ENABLE +
|
|
- (ctrl * MSI_REG_CTRL_BLOCK_SIZE),
|
|
- ~0);
|
|
- }
|
|
- }
|
|
-
|
|
dw_pcie_msi_init(pp);
|
|
|
|
/* Setup RC BARs */
|
|
--- a/drivers/pci/controller/dwc/pcie-designware.h
|
|
+++ b/drivers/pci/controller/dwc/pcie-designware.h
|
|
@@ -678,6 +678,9 @@ static inline enum dw_pcie_ltssm dw_pcie
|
|
int dw_pcie_suspend_noirq(struct dw_pcie *pci);
|
|
int dw_pcie_resume_noirq(struct dw_pcie *pci);
|
|
irqreturn_t dw_handle_msi_irq(struct dw_pcie_rp *pp);
|
|
+void dw_pcie_msi_init(struct dw_pcie_rp *pp);
|
|
+int dw_pcie_msi_host_init(struct dw_pcie_rp *pp);
|
|
+void dw_pcie_free_msi(struct dw_pcie_rp *pp);
|
|
int dw_pcie_setup_rc(struct dw_pcie_rp *pp);
|
|
int dw_pcie_host_init(struct dw_pcie_rp *pp);
|
|
void dw_pcie_host_deinit(struct dw_pcie_rp *pp);
|
|
@@ -700,6 +703,17 @@ static inline irqreturn_t dw_handle_msi_
|
|
return IRQ_NONE;
|
|
}
|
|
|
|
+static inline void dw_pcie_msi_init(struct dw_pcie_rp *pp)
|
|
+{ }
|
|
+
|
|
+static inline int dw_pcie_msi_host_init(struct dw_pcie_rp *pp)
|
|
+{
|
|
+ return -ENODEV;
|
|
+}
|
|
+
|
|
+static inline void dw_pcie_free_msi(struct dw_pcie_rp *pp)
|
|
+{ }
|
|
+
|
|
static inline int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
|
|
{
|
|
return 0;
|