* [PATCH v2 0/2] PCI: dwc: ep: Multi-function endpoint configuration fixes
@ 2026-02-19 6:45 Aksh Garg
2026-02-19 6:45 ` [PATCH v2 1/2] PCI: dwc: ep: Fix MSI-X configuration to write to correct physical function Aksh Garg
2026-02-19 6:45 ` [PATCH v2 2/2] PCI: dwc: ep: Mirror the max link width and speed fields to all functions Aksh Garg
0 siblings, 2 replies; 5+ messages in thread
From: Aksh Garg @ 2026-02-19 6:45 UTC (permalink / raw)
To: linux-pci, jingoohan1, mani, lpieralisi, kwilczynski, robh,
bhelgaas, yoshihiro.shimoda.uh, fancer.lancer, Zhiqiang.Hou,
gustavo.pimentel, cassel
Cc: linux-kernel, s-vadapalli, danishanwar, Aksh Garg
This series addresses multi-function endpoint configuration issues in
the DWC PCIe controller driver. The changes enable proper operations
for physical functions and enhance the multi-function endpoint support.
This patch series can be seen as an extension of the patch series:
https://lore.kernel.org/all/20260130115516.515082-1-a-garg7@ti.com/
Changes from v1 to v2:
- Fixed the minor nits in the patches
v1: https://lore.kernel.org/all/20260202072758.101845-1-a-garg7@ti.com/
Aksh Garg (2):
PCI: dwc: ep: Fix MSI-X configuration to write to correct physical
function
PCI: dwc: ep: Mirror the max link width and speed fields to all
functions
.../pci/controller/dwc/pcie-designware-ep.c | 25 +++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH v2 1/2] PCI: dwc: ep: Fix MSI-X configuration to write to correct physical function 2026-02-19 6:45 [PATCH v2 0/2] PCI: dwc: ep: Multi-function endpoint configuration fixes Aksh Garg @ 2026-02-19 6:45 ` Aksh Garg 2026-02-19 6:45 ` [PATCH v2 2/2] PCI: dwc: ep: Mirror the max link width and speed fields to all functions Aksh Garg 1 sibling, 0 replies; 5+ messages in thread From: Aksh Garg @ 2026-02-19 6:45 UTC (permalink / raw) To: linux-pci, jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, yoshihiro.shimoda.uh, fancer.lancer, Zhiqiang.Hou, gustavo.pimentel, cassel Cc: linux-kernel, s-vadapalli, danishanwar, Aksh Garg The MSI-X configuration code reads from the correct physical function's register space using dw_pcie_ep_readw_dbi(), but writes back only to PF0 using the old dw_pcie_writew_dbi() helper. This causes incorrect MSI-X configuration for other PFs. Fix this by using dw_pcie_ep_writew_dbi() to write to the correct PF's register space, matching the read operation. Fixes: 70fa02ca1446 ("PCI: dwc: Add dw_pcie_ep_{read,write}_dbi[2] helpers") Reviewed-by: Niklas Cassel <cassel@kernel.org> Signed-off-by: Aksh Garg <a-garg7@ti.com> --- Changes from v1 to v2: - None v1: https://lore.kernel.org/all/20260202072758.101845-2-a-garg7@ti.com/ drivers/pci/controller/dwc/pcie-designware-ep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index 7e7844ff0f7e..771241e1a2c9 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -745,7 +745,7 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no, val = dw_pcie_ep_readw_dbi(ep, func_no, reg); val &= ~PCI_MSIX_FLAGS_QSIZE; val |= nr_irqs - 1; /* encoded as N-1 */ - dw_pcie_writew_dbi(pci, reg, val); + dw_pcie_ep_writew_dbi(ep, func_no, reg, val); reg = ep_func->msix_cap + PCI_MSIX_TABLE; val = offset | bir; -- 2.34.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 2/2] PCI: dwc: ep: Mirror the max link width and speed fields to all functions 2026-02-19 6:45 [PATCH v2 0/2] PCI: dwc: ep: Multi-function endpoint configuration fixes Aksh Garg 2026-02-19 6:45 ` [PATCH v2 1/2] PCI: dwc: ep: Fix MSI-X configuration to write to correct physical function Aksh Garg @ 2026-02-19 6:45 ` Aksh Garg 2026-02-23 18:55 ` Bjorn Helgaas 1 sibling, 1 reply; 5+ messages in thread From: Aksh Garg @ 2026-02-19 6:45 UTC (permalink / raw) To: linux-pci, jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, yoshihiro.shimoda.uh, fancer.lancer, Zhiqiang.Hou, gustavo.pimentel, cassel Cc: linux-kernel, s-vadapalli, danishanwar, Aksh Garg PCIe r6.0, section 7.5.3.6 states that for multi-function devices, the Max Link Width and Max Link Speed fields in the Link Capabilities Register must report the same values for all functions. Currently, dw_pcie_setup() programs these fields only for physical function 0 (PF0) via dw_pcie_link_set_max_speed() and dw_pcie_link_set_max_link_width(). For multi-function endpoint configurations, PF1 and beyond retain their default values, violating the PCIe specification. Fix this by reading the Max Link Width and Max Link Speed fields from PF0's Link Capabilities Register after dw_pcie_setup() completes, then mirroring these values to all other physical functions. Fixes: 24ede430fa49 ("PCI: designware-ep: Add multiple PFs support for DWC") Fixes: 89db0793c9f2 ("PCI: dwc: Add missing PCI_EXP_LNKCAP_MLW handling") Signed-off-by: Aksh Garg <a-garg7@ti.com> --- The link speed and width would be negotiated through PF0 during initialization that controls the link behaviour, hence it didn't broke the driver. However, the change is proposed just to make the driver compatible with the PCIe base specifications. The fix is implemented in pcie-designware-ep.c rather than modifying dw_pcie_setup() directly to keep pcie-designware.c independent of RC/EP specifics and maintain it as common code. Changes from v1 to v2: - Used FIELD_* macros v1: https://lore.kernel.org/all/20260202072758.101845-3-a-garg7@ti.com/ .../pci/controller/dwc/pcie-designware-ep.c | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index 771241e1a2c9..6b9f90810fec 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -1094,7 +1094,8 @@ static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci) { struct dw_pcie_ep *ep = &pci->ep; u8 funcs = ep->epc->max_functions; - u8 func_no; + u32 ref_lnkcap, lnkcap; + u8 func_no, offset; dw_pcie_dbi_ro_wr_en(pci); @@ -1102,6 +1103,26 @@ static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci) dw_pcie_ep_init_rebar_registers(ep, func_no); dw_pcie_setup(pci); + + /* + * PCIe r6.0, section 7.5.3.6 states that for multi-function endpoints, + * max link width and speed fields must report same values for all functions. + * However, dw_pcie_setup() programs these fields only for physical function 0. + * Hence, mirror these fields to all other physical functions as well. + */ + if (funcs > 1) { + offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); + ref_lnkcap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP); + ref_lnkcap = FIELD_GET(PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS, ref_lnkcap); + + for (func_no = 1; func_no < funcs; func_no++) { + offset = dw_pcie_ep_find_capability(ep, func_no, PCI_CAP_ID_EXP); + lnkcap = dw_pcie_ep_readl_dbi(ep, func_no, offset + PCI_EXP_LNKCAP); + FIELD_MODIFY(PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS, &lnkcap, ref_lnkcap); + dw_pcie_ep_writel_dbi(ep, func_no, offset + PCI_EXP_LNKCAP, lnkcap); + } + } + dw_pcie_dbi_ro_wr_dis(pci); } -- 2.34.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] PCI: dwc: ep: Mirror the max link width and speed fields to all functions 2026-02-19 6:45 ` [PATCH v2 2/2] PCI: dwc: ep: Mirror the max link width and speed fields to all functions Aksh Garg @ 2026-02-23 18:55 ` Bjorn Helgaas 2026-02-24 8:09 ` Aksh Garg 0 siblings, 1 reply; 5+ messages in thread From: Bjorn Helgaas @ 2026-02-23 18:55 UTC (permalink / raw) To: Aksh Garg Cc: linux-pci, jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, yoshihiro.shimoda.uh, fancer.lancer, Zhiqiang.Hou, gustavo.pimentel, cassel, linux-kernel, s-vadapalli, danishanwar On Thu, Feb 19, 2026 at 12:15:11PM +0530, Aksh Garg wrote: > PCIe r6.0, section 7.5.3.6 states that for multi-function devices, the > Max Link Width and Max Link Speed fields in the Link Capabilities > Register must report the same values for all functions. Please update the citations here and in the comment below to r7.0. > Currently, dw_pcie_setup() programs these fields only for physical > function 0 (PF0) via dw_pcie_link_set_max_speed() and > dw_pcie_link_set_max_link_width(). For multi-function endpoint > configurations, PF1 and beyond retain their default values, violating > the PCIe specification. > > Fix this by reading the Max Link Width and Max Link Speed fields from > PF0's Link Capabilities Register after dw_pcie_setup() completes, > then mirroring these values to all other physical functions. "PF" and "physical function" are terms that apply to SR-IOV, not to ordinary functions of a multi-function device, so it's confusing to use them here. Instead of "physical function 0" and "PF0", just refer to "Function 0" as the spec does. > Fixes: 24ede430fa49 ("PCI: designware-ep: Add multiple PFs support for DWC") Sorry I missed it earlier; it's also the wrong term here in the subject of 24ede430fa49, but it's too late to fix that. > Fixes: 89db0793c9f2 ("PCI: dwc: Add missing PCI_EXP_LNKCAP_MLW handling") > Signed-off-by: Aksh Garg <a-garg7@ti.com> > --- > > The link speed and width would be negotiated through PF0 during > initialization that controls the link behaviour, hence it didn't broke > the driver. However, the change is proposed just to make the driver > compatible with the PCIe base specifications. > > The fix is implemented in pcie-designware-ep.c rather than modifying > dw_pcie_setup() directly to keep pcie-designware.c independent of RC/EP > specifics and maintain it as common code. > > Changes from v1 to v2: > - Used FIELD_* macros > > v1: https://lore.kernel.org/all/20260202072758.101845-3-a-garg7@ti.com/ > > .../pci/controller/dwc/pcie-designware-ep.c | 23 ++++++++++++++++++- > 1 file changed, 22 insertions(+), 1 deletion(-) > > diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c > index 771241e1a2c9..6b9f90810fec 100644 > --- a/drivers/pci/controller/dwc/pcie-designware-ep.c > +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c > @@ -1094,7 +1094,8 @@ static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci) > { > struct dw_pcie_ep *ep = &pci->ep; > u8 funcs = ep->epc->max_functions; > - u8 func_no; > + u32 ref_lnkcap, lnkcap; > + u8 func_no, offset; > > dw_pcie_dbi_ro_wr_en(pci); > > @@ -1102,6 +1103,26 @@ static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci) > dw_pcie_ep_init_rebar_registers(ep, func_no); > > dw_pcie_setup(pci); > + > + /* > + * PCIe r6.0, section 7.5.3.6 states that for multi-function endpoints, > + * max link width and speed fields must report same values for all functions. > + * However, dw_pcie_setup() programs these fields only for physical function 0. > + * Hence, mirror these fields to all other physical functions as well. s/physical function 0/function 0/ Wrap this to fit in 80 columns like the rest of the file. > + */ > + if (funcs > 1) { > + offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); > + ref_lnkcap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP); > + ref_lnkcap = FIELD_GET(PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS, ref_lnkcap); > + > + for (func_no = 1; func_no < funcs; func_no++) { > + offset = dw_pcie_ep_find_capability(ep, func_no, PCI_CAP_ID_EXP); > + lnkcap = dw_pcie_ep_readl_dbi(ep, func_no, offset + PCI_EXP_LNKCAP); > + FIELD_MODIFY(PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS, &lnkcap, ref_lnkcap); > + dw_pcie_ep_writel_dbi(ep, func_no, offset + PCI_EXP_LNKCAP, lnkcap); Please wrap these too, it's not too hard to make these fit in 80 columns like (most of) the rest of the file. > + } > + } > + > dw_pcie_dbi_ro_wr_dis(pci); > } > > -- > 2.34.1 > ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] PCI: dwc: ep: Mirror the max link width and speed fields to all functions 2026-02-23 18:55 ` Bjorn Helgaas @ 2026-02-24 8:09 ` Aksh Garg 0 siblings, 0 replies; 5+ messages in thread From: Aksh Garg @ 2026-02-24 8:09 UTC (permalink / raw) To: Bjorn Helgaas Cc: linux-pci, jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, yoshihiro.shimoda.uh, fancer.lancer, Zhiqiang.Hou, gustavo.pimentel, cassel, linux-kernel, s-vadapalli, danishanwar On 24/02/26 00:25, Bjorn Helgaas wrote: > On Thu, Feb 19, 2026 at 12:15:11PM +0530, Aksh Garg wrote: >> PCIe r6.0, section 7.5.3.6 states that for multi-function devices, the >> Max Link Width and Max Link Speed fields in the Link Capabilities >> Register must report the same values for all functions. > > Please update the citations here and in the comment below to r7.0. > >> Currently, dw_pcie_setup() programs these fields only for physical >> function 0 (PF0) via dw_pcie_link_set_max_speed() and >> dw_pcie_link_set_max_link_width(). For multi-function endpoint >> configurations, PF1 and beyond retain their default values, violating >> the PCIe specification. >> >> Fix this by reading the Max Link Width and Max Link Speed fields from >> PF0's Link Capabilities Register after dw_pcie_setup() completes, >> then mirroring these values to all other physical functions. > > "PF" and "physical function" are terms that apply to SR-IOV, not to > ordinary functions of a multi-function device, so it's confusing to > use them here. Instead of "physical function 0" and "PF0", just refer > to "Function 0" as the spec does. > >> Fixes: 24ede430fa49 ("PCI: designware-ep: Add multiple PFs support for DWC") > > Sorry I missed it earlier; it's also the wrong term here in the > subject of 24ede430fa49, but it's too late to fix that. > >> Fixes: 89db0793c9f2 ("PCI: dwc: Add missing PCI_EXP_LNKCAP_MLW handling") >> Signed-off-by: Aksh Garg <a-garg7@ti.com> >> --- >> >> The link speed and width would be negotiated through PF0 during >> initialization that controls the link behaviour, hence it didn't broke >> the driver. However, the change is proposed just to make the driver >> compatible with the PCIe base specifications. >> >> The fix is implemented in pcie-designware-ep.c rather than modifying >> dw_pcie_setup() directly to keep pcie-designware.c independent of RC/EP >> specifics and maintain it as common code. >> >> Changes from v1 to v2: >> - Used FIELD_* macros >> >> v1: https://lore.kernel.org/all/20260202072758.101845-3-a-garg7@ti.com/ >> >> .../pci/controller/dwc/pcie-designware-ep.c | 23 ++++++++++++++++++- >> 1 file changed, 22 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c >> index 771241e1a2c9..6b9f90810fec 100644 >> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c >> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c >> @@ -1094,7 +1094,8 @@ static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci) >> { >> struct dw_pcie_ep *ep = &pci->ep; >> u8 funcs = ep->epc->max_functions; >> - u8 func_no; >> + u32 ref_lnkcap, lnkcap; >> + u8 func_no, offset; >> >> dw_pcie_dbi_ro_wr_en(pci); >> >> @@ -1102,6 +1103,26 @@ static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci) >> dw_pcie_ep_init_rebar_registers(ep, func_no); >> >> dw_pcie_setup(pci); >> + >> + /* >> + * PCIe r6.0, section 7.5.3.6 states that for multi-function endpoints, >> + * max link width and speed fields must report same values for all functions. >> + * However, dw_pcie_setup() programs these fields only for physical function 0. >> + * Hence, mirror these fields to all other physical functions as well. > > s/physical function 0/function 0/ > > Wrap this to fit in 80 columns like the rest of the file. > >> + */ >> + if (funcs > 1) { >> + offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); >> + ref_lnkcap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP); >> + ref_lnkcap = FIELD_GET(PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS, ref_lnkcap); >> + >> + for (func_no = 1; func_no < funcs; func_no++) { >> + offset = dw_pcie_ep_find_capability(ep, func_no, PCI_CAP_ID_EXP); >> + lnkcap = dw_pcie_ep_readl_dbi(ep, func_no, offset + PCI_EXP_LNKCAP); >> + FIELD_MODIFY(PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS, &lnkcap, ref_lnkcap); >> + dw_pcie_ep_writel_dbi(ep, func_no, offset + PCI_EXP_LNKCAP, lnkcap); > > Please wrap these too, it's not too hard to make these fit in 80 > columns like (most of) the rest of the file. > I will work on these feedbacks and post v3 series. Thanks! >> + } >> + } >> + >> dw_pcie_dbi_ro_wr_dis(pci); >> } >> >> -- >> 2.34.1 >> ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-02-24 8:10 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-02-19 6:45 [PATCH v2 0/2] PCI: dwc: ep: Multi-function endpoint configuration fixes Aksh Garg 2026-02-19 6:45 ` [PATCH v2 1/2] PCI: dwc: ep: Fix MSI-X configuration to write to correct physical function Aksh Garg 2026-02-19 6:45 ` [PATCH v2 2/2] PCI: dwc: ep: Mirror the max link width and speed fields to all functions Aksh Garg 2026-02-23 18:55 ` Bjorn Helgaas 2026-02-24 8:09 ` Aksh Garg
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®