Skip to content

Commit c6db0f4

Browse files
AkshGarg-19Sasha Levin
authored andcommitted
PCI: dwc: ep: Fix resizable BAR support for multi-PF configurations
[ Upstream commit 43d67ec ] The resizable BAR support added by the commit 3a3d4ca ("PCI: dwc: ep: Allow EPF drivers to configure the size of Resizable BARs") incorrectly configures the resizable BARs only for the first Physical Function (PF0) in EP mode. The resizable BAR configuration functions use generic dw_pcie_*_dbi() operations instead of physical function specific dw_pcie_ep_*_dbi() operations. This causes resizable BAR configuration to always target PF0 regardless of the requested function number. Additionally, dw_pcie_ep_init_non_sticky_registers() only initializes resizable BAR registers for PF0, leaving other PFs unconfigured during the execution of this function. Fix this by using physical function specific configuration space access operations throughout the resizable BAR code path and initializing registers for all the physical functions that support resizable BARs. Fixes: 3a3d4ca ("PCI: dwc: ep: Allow EPF drivers to configure the size of Resizable BARs") Signed-off-by: Aksh Garg <a-garg7@ti.com> [mani: added stable tag] Signed-off-by: Manivannan Sadhasivam <mani@kernel.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Niklas Cassel <cassel@kernel.org> Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260130115516.515082-2-a-garg7@ti.com Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 7c0c4b7 commit c6db0f4

1 file changed

Lines changed: 32 additions & 16 deletions

File tree

drivers/pci/controller/dwc/pcie-designware-ep.c

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,13 @@ static u8 dw_pcie_ep_find_capability(struct dw_pcie_ep *ep, u8 func_no, u8 cap)
7575
cap, NULL, ep, func_no);
7676
}
7777

78+
static u16 dw_pcie_ep_find_ext_capability(struct dw_pcie_ep *ep,
79+
u8 func_no, u8 cap)
80+
{
81+
return PCI_FIND_NEXT_EXT_CAP(dw_pcie_ep_read_cfg, 0,
82+
cap, NULL, ep, func_no);
83+
}
84+
7885
static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
7986
struct pci_epf_header *hdr)
8087
{
@@ -178,22 +185,22 @@ static void dw_pcie_ep_clear_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
178185
ep->bar_to_atu[bar] = 0;
179186
}
180187

181-
static unsigned int dw_pcie_ep_get_rebar_offset(struct dw_pcie *pci,
188+
static unsigned int dw_pcie_ep_get_rebar_offset(struct dw_pcie_ep *ep, u8 func_no,
182189
enum pci_barno bar)
183190
{
184191
u32 reg, bar_index;
185192
unsigned int offset, nbars;
186193
int i;
187194

188-
offset = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR);
195+
offset = dw_pcie_ep_find_ext_capability(ep, func_no, PCI_EXT_CAP_ID_REBAR);
189196
if (!offset)
190197
return offset;
191198

192-
reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
199+
reg = dw_pcie_ep_readl_dbi(ep, func_no, offset + PCI_REBAR_CTRL);
193200
nbars = FIELD_GET(PCI_REBAR_CTRL_NBAR_MASK, reg);
194201

195202
for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL) {
196-
reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
203+
reg = dw_pcie_ep_readl_dbi(ep, func_no, offset + PCI_REBAR_CTRL);
197204
bar_index = FIELD_GET(PCI_REBAR_CTRL_BAR_IDX, reg);
198205
if (bar_index == bar)
199206
return offset;
@@ -214,7 +221,7 @@ static int dw_pcie_ep_set_bar_resizable(struct dw_pcie_ep *ep, u8 func_no,
214221
u32 rebar_cap, rebar_ctrl;
215222
int ret;
216223

217-
rebar_offset = dw_pcie_ep_get_rebar_offset(pci, bar);
224+
rebar_offset = dw_pcie_ep_get_rebar_offset(ep, func_no, bar);
218225
if (!rebar_offset)
219226
return -EINVAL;
220227

@@ -244,16 +251,16 @@ static int dw_pcie_ep_set_bar_resizable(struct dw_pcie_ep *ep, u8 func_no,
244251
* 1 MB to 128 TB. Bits 31:16 in PCI_REBAR_CTRL define "supported sizes"
245252
* bits for sizes 256 TB to 8 EB. Disallow sizes 256 TB to 8 EB.
246253
*/
247-
rebar_ctrl = dw_pcie_readl_dbi(pci, rebar_offset + PCI_REBAR_CTRL);
254+
rebar_ctrl = dw_pcie_ep_readl_dbi(ep, func_no, rebar_offset + PCI_REBAR_CTRL);
248255
rebar_ctrl &= ~GENMASK(31, 16);
249-
dw_pcie_writel_dbi(pci, rebar_offset + PCI_REBAR_CTRL, rebar_ctrl);
256+
dw_pcie_ep_writel_dbi(ep, func_no, rebar_offset + PCI_REBAR_CTRL, rebar_ctrl);
250257

251258
/*
252259
* The "selected size" (bits 13:8) in PCI_REBAR_CTRL are automatically
253260
* updated when writing PCI_REBAR_CAP, see "Figure 3-26 Resizable BAR
254261
* Example for 32-bit Memory BAR0" in DWC EP databook 5.96a.
255262
*/
256-
dw_pcie_writel_dbi(pci, rebar_offset + PCI_REBAR_CAP, rebar_cap);
263+
dw_pcie_ep_writel_dbi(ep, func_no, rebar_offset + PCI_REBAR_CAP, rebar_cap);
257264

258265
dw_pcie_dbi_ro_wr_dis(pci);
259266

@@ -799,20 +806,17 @@ void dw_pcie_ep_deinit(struct dw_pcie_ep *ep)
799806
}
800807
EXPORT_SYMBOL_GPL(dw_pcie_ep_deinit);
801808

802-
static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci)
809+
static void dw_pcie_ep_init_rebar_registers(struct dw_pcie_ep *ep, u8 func_no)
803810
{
804-
struct dw_pcie_ep *ep = &pci->ep;
805811
unsigned int offset;
806812
unsigned int nbars;
807813
enum pci_barno bar;
808814
u32 reg, i, val;
809815

810-
offset = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR);
811-
812-
dw_pcie_dbi_ro_wr_en(pci);
816+
offset = dw_pcie_ep_find_ext_capability(ep, func_no, PCI_EXT_CAP_ID_REBAR);
813817

814818
if (offset) {
815-
reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
819+
reg = dw_pcie_ep_readl_dbi(ep, func_no, offset + PCI_REBAR_CTRL);
816820
nbars = FIELD_GET(PCI_REBAR_CTRL_NBAR_MASK, reg);
817821

818822
/*
@@ -833,16 +837,28 @@ static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci)
833837
* the controller when RESBAR_CAP_REG is written, which
834838
* is why RESBAR_CAP_REG is written here.
835839
*/
836-
val = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
840+
val = dw_pcie_ep_readl_dbi(ep, func_no, offset + PCI_REBAR_CTRL);
837841
bar = FIELD_GET(PCI_REBAR_CTRL_BAR_IDX, val);
838842
if (ep->epf_bar[bar])
839843
pci_epc_bar_size_to_rebar_cap(ep->epf_bar[bar]->size, &val);
840844
else
841845
val = BIT(4);
842846

843-
dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, val);
847+
dw_pcie_ep_writel_dbi(ep, func_no, offset + PCI_REBAR_CAP, val);
844848
}
845849
}
850+
}
851+
852+
static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci)
853+
{
854+
struct dw_pcie_ep *ep = &pci->ep;
855+
u8 funcs = ep->epc->max_functions;
856+
u8 func_no;
857+
858+
dw_pcie_dbi_ro_wr_en(pci);
859+
860+
for (func_no = 0; func_no < funcs; func_no++)
861+
dw_pcie_ep_init_rebar_registers(ep, func_no);
846862

847863
dw_pcie_setup(pci);
848864
dw_pcie_dbi_ro_wr_dis(pci);

0 commit comments

Comments
 (0)