Skip to content

Commit a113afb

Browse files
committed
Merge branch 'pci/endpoint'
- Convert PCI device data so pci-epf-test works correctly on big-endian endpoint systems (Niklas Cassel) - Add BAR_RESIZABLE type to endpoint framework (Niklas Cassel) - Add pci_epc_bar_size_to_rebar_cap() to convert a size to the Resizable BAR Capability so endpoint drivers can configure what the Capability register advertises (Niklas Cassel) - Add DWC core support for EPF drivers to set BAR_RESIZABLE type and size via dw_pcie_ep_set_bar() (Niklas Cassel) - Describe TI AM65x (keystone) BARs 2 and 5 as Resizable, not Fixed (Niklas Cassel) - Reduce TI AM65x (keystone) BAR alignment requirement from 1MB to 64KB (Niklas Cassel) - Describe Rockchip rk3568 and rk3588 BARs as Resizable, not Fixed (Niklas Cassel) - Drop unused devm_pci_epc_destroy() (Zijun Hu) - Fix pci-epf-test double free that causes an oops if the host reboots and PERST# deassertion restarts endpoint BAR allocation (Christian Bruel) - Drop dw_pcie_ep_find_ext_capability() and use dw_pcie_find_ext_capability() instead (Niklas Cassel) * pci/endpoint: PCI: dwc: ep: Remove superfluous function dw_pcie_ep_find_ext_capability() PCI: endpoint: pci-epf-test: Fix double free that causes kernel to oops PCI: endpoint: Remove unused devm_pci_epc_destroy() PCI: dw-rockchip: Describe Resizable BARs as Resizable BARs PCI: keystone: Specify correct alignment requirement PCI: keystone: Describe Resizable BARs as Resizable BARs PCI: dwc: ep: Allow EPF drivers to configure the size of Resizable BARs PCI: dwc: ep: Move dw_pcie_ep_find_ext_capability() PCI: endpoint: Add pci_epc_bar_size_to_rebar_cap() PCI: endpoint: Allow EPF drivers to configure the size of Resizable BARs PCI: endpoint: pci-epf-test: Handle endianness properly
2 parents b810fec + a60a708 commit a113afb

File tree

8 files changed

+301
-132
lines changed

8 files changed

+301
-132
lines changed

Documentation/PCI/endpoint/pci-endpoint.rst

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,10 @@ by the PCI controller driver.
5757
The PCI controller driver can then create a new EPC device by invoking
5858
devm_pci_epc_create()/pci_epc_create().
5959

60-
* devm_pci_epc_destroy()/pci_epc_destroy()
60+
* pci_epc_destroy()
6161

62-
The PCI controller driver can destroy the EPC device created by either
63-
devm_pci_epc_create() or pci_epc_create() using devm_pci_epc_destroy() or
64-
pci_epc_destroy().
62+
The PCI controller driver can destroy the EPC device created by
63+
pci_epc_create() using pci_epc_destroy().
6564

6665
* pci_epc_linkup()
6766

drivers/pci/controller/dwc/pci-keystone.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -966,11 +966,11 @@ static const struct pci_epc_features ks_pcie_am654_epc_features = {
966966
.msix_capable = true,
967967
.bar[BAR_0] = { .type = BAR_RESERVED, },
968968
.bar[BAR_1] = { .type = BAR_RESERVED, },
969-
.bar[BAR_2] = { .type = BAR_FIXED, .fixed_size = SZ_1M, },
969+
.bar[BAR_2] = { .type = BAR_RESIZABLE, },
970970
.bar[BAR_3] = { .type = BAR_FIXED, .fixed_size = SZ_64K, },
971971
.bar[BAR_4] = { .type = BAR_FIXED, .fixed_size = 256, },
972-
.bar[BAR_5] = { .type = BAR_FIXED, .fixed_size = SZ_1M, },
973-
.align = SZ_1M,
972+
.bar[BAR_5] = { .type = BAR_RESIZABLE, },
973+
.align = SZ_64K,
974974
};
975975

976976
static const struct pci_epc_features*

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

Lines changed: 169 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -205,16 +205,135 @@ static void dw_pcie_ep_clear_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
205205
ep->bar_to_atu[bar] = 0;
206206
}
207207

208+
static unsigned int dw_pcie_ep_get_rebar_offset(struct dw_pcie *pci,
209+
enum pci_barno bar)
210+
{
211+
u32 reg, bar_index;
212+
unsigned int offset, nbars;
213+
int i;
214+
215+
offset = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR);
216+
if (!offset)
217+
return offset;
218+
219+
reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
220+
nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >> PCI_REBAR_CTRL_NBAR_SHIFT;
221+
222+
for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL) {
223+
reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
224+
bar_index = reg & PCI_REBAR_CTRL_BAR_IDX;
225+
if (bar_index == bar)
226+
return offset;
227+
}
228+
229+
return 0;
230+
}
231+
232+
static int dw_pcie_ep_set_bar_resizable(struct dw_pcie_ep *ep, u8 func_no,
233+
struct pci_epf_bar *epf_bar)
234+
{
235+
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
236+
enum pci_barno bar = epf_bar->barno;
237+
size_t size = epf_bar->size;
238+
int flags = epf_bar->flags;
239+
u32 reg = PCI_BASE_ADDRESS_0 + (4 * bar);
240+
unsigned int rebar_offset;
241+
u32 rebar_cap, rebar_ctrl;
242+
int ret;
243+
244+
rebar_offset = dw_pcie_ep_get_rebar_offset(pci, bar);
245+
if (!rebar_offset)
246+
return -EINVAL;
247+
248+
ret = pci_epc_bar_size_to_rebar_cap(size, &rebar_cap);
249+
if (ret)
250+
return ret;
251+
252+
dw_pcie_dbi_ro_wr_en(pci);
253+
254+
/*
255+
* A BAR mask should not be written for a resizable BAR. The BAR mask
256+
* is automatically derived by the controller every time the "selected
257+
* size" bits are updated, see "Figure 3-26 Resizable BAR Example for
258+
* 32-bit Memory BAR0" in DWC EP databook 5.96a. We simply need to write
259+
* BIT(0) to set the BAR enable bit.
260+
*/
261+
dw_pcie_ep_writel_dbi2(ep, func_no, reg, BIT(0));
262+
dw_pcie_ep_writel_dbi(ep, func_no, reg, flags);
263+
264+
if (flags & PCI_BASE_ADDRESS_MEM_TYPE_64) {
265+
dw_pcie_ep_writel_dbi2(ep, func_no, reg + 4, 0);
266+
dw_pcie_ep_writel_dbi(ep, func_no, reg + 4, 0);
267+
}
268+
269+
/*
270+
* Bits 31:0 in PCI_REBAR_CAP define "supported sizes" bits for sizes
271+
* 1 MB to 128 TB. Bits 31:16 in PCI_REBAR_CTRL define "supported sizes"
272+
* bits for sizes 256 TB to 8 EB. Disallow sizes 256 TB to 8 EB.
273+
*/
274+
rebar_ctrl = dw_pcie_readl_dbi(pci, rebar_offset + PCI_REBAR_CTRL);
275+
rebar_ctrl &= ~GENMASK(31, 16);
276+
dw_pcie_writel_dbi(pci, rebar_offset + PCI_REBAR_CTRL, rebar_ctrl);
277+
278+
/*
279+
* The "selected size" (bits 13:8) in PCI_REBAR_CTRL are automatically
280+
* updated when writing PCI_REBAR_CAP, see "Figure 3-26 Resizable BAR
281+
* Example for 32-bit Memory BAR0" in DWC EP databook 5.96a.
282+
*/
283+
dw_pcie_writel_dbi(pci, rebar_offset + PCI_REBAR_CAP, rebar_cap);
284+
285+
dw_pcie_dbi_ro_wr_dis(pci);
286+
287+
return 0;
288+
}
289+
290+
static int dw_pcie_ep_set_bar_programmable(struct dw_pcie_ep *ep, u8 func_no,
291+
struct pci_epf_bar *epf_bar)
292+
{
293+
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
294+
enum pci_barno bar = epf_bar->barno;
295+
size_t size = epf_bar->size;
296+
int flags = epf_bar->flags;
297+
u32 reg = PCI_BASE_ADDRESS_0 + (4 * bar);
298+
299+
dw_pcie_dbi_ro_wr_en(pci);
300+
301+
dw_pcie_ep_writel_dbi2(ep, func_no, reg, lower_32_bits(size - 1));
302+
dw_pcie_ep_writel_dbi(ep, func_no, reg, flags);
303+
304+
if (flags & PCI_BASE_ADDRESS_MEM_TYPE_64) {
305+
dw_pcie_ep_writel_dbi2(ep, func_no, reg + 4, upper_32_bits(size - 1));
306+
dw_pcie_ep_writel_dbi(ep, func_no, reg + 4, 0);
307+
}
308+
309+
dw_pcie_dbi_ro_wr_dis(pci);
310+
311+
return 0;
312+
}
313+
314+
static enum pci_epc_bar_type dw_pcie_ep_get_bar_type(struct dw_pcie_ep *ep,
315+
enum pci_barno bar)
316+
{
317+
const struct pci_epc_features *epc_features;
318+
319+
if (!ep->ops->get_features)
320+
return BAR_PROGRAMMABLE;
321+
322+
epc_features = ep->ops->get_features(ep);
323+
324+
return epc_features->bar[bar].type;
325+
}
326+
208327
static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
209328
struct pci_epf_bar *epf_bar)
210329
{
211330
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
212331
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
213332
enum pci_barno bar = epf_bar->barno;
214333
size_t size = epf_bar->size;
334+
enum pci_epc_bar_type bar_type;
215335
int flags = epf_bar->flags;
216336
int ret, type;
217-
u32 reg;
218337

219338
/*
220339
* DWC does not allow BAR pairs to overlap, e.g. you cannot combine BARs
@@ -246,19 +365,30 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
246365
goto config_atu;
247366
}
248367

249-
reg = PCI_BASE_ADDRESS_0 + (4 * bar);
250-
251-
dw_pcie_dbi_ro_wr_en(pci);
252-
253-
dw_pcie_ep_writel_dbi2(ep, func_no, reg, lower_32_bits(size - 1));
254-
dw_pcie_ep_writel_dbi(ep, func_no, reg, flags);
255-
256-
if (flags & PCI_BASE_ADDRESS_MEM_TYPE_64) {
257-
dw_pcie_ep_writel_dbi2(ep, func_no, reg + 4, upper_32_bits(size - 1));
258-
dw_pcie_ep_writel_dbi(ep, func_no, reg + 4, 0);
368+
bar_type = dw_pcie_ep_get_bar_type(ep, bar);
369+
switch (bar_type) {
370+
case BAR_FIXED:
371+
/*
372+
* There is no need to write a BAR mask for a fixed BAR (except
373+
* to write 1 to the LSB of the BAR mask register, to enable the
374+
* BAR). Write the BAR mask regardless. (The fixed bits in the
375+
* BAR mask register will be read-only anyway.)
376+
*/
377+
fallthrough;
378+
case BAR_PROGRAMMABLE:
379+
ret = dw_pcie_ep_set_bar_programmable(ep, func_no, epf_bar);
380+
break;
381+
case BAR_RESIZABLE:
382+
ret = dw_pcie_ep_set_bar_resizable(ep, func_no, epf_bar);
383+
break;
384+
default:
385+
ret = -EINVAL;
386+
dev_err(pci->dev, "Invalid BAR type\n");
387+
break;
259388
}
260389

261-
dw_pcie_dbi_ro_wr_dis(pci);
390+
if (ret)
391+
return ret;
262392

263393
config_atu:
264394
if (!(flags & PCI_BASE_ADDRESS_SPACE))
@@ -690,31 +820,15 @@ void dw_pcie_ep_deinit(struct dw_pcie_ep *ep)
690820
}
691821
EXPORT_SYMBOL_GPL(dw_pcie_ep_deinit);
692822

693-
static unsigned int dw_pcie_ep_find_ext_capability(struct dw_pcie *pci, int cap)
694-
{
695-
u32 header;
696-
int pos = PCI_CFG_SPACE_SIZE;
697-
698-
while (pos) {
699-
header = dw_pcie_readl_dbi(pci, pos);
700-
if (PCI_EXT_CAP_ID(header) == cap)
701-
return pos;
702-
703-
pos = PCI_EXT_CAP_NEXT(header);
704-
if (!pos)
705-
break;
706-
}
707-
708-
return 0;
709-
}
710-
711823
static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci)
712824
{
825+
struct dw_pcie_ep *ep = &pci->ep;
713826
unsigned int offset;
714827
unsigned int nbars;
715-
u32 reg, i;
828+
enum pci_barno bar;
829+
u32 reg, i, val;
716830

717-
offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR);
831+
offset = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR);
718832

719833
dw_pcie_dbi_ro_wr_en(pci);
720834

@@ -727,9 +841,29 @@ static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci)
727841
* PCIe r6.0, sec 7.8.6.2 require us to support at least one
728842
* size in the range from 1 MB to 512 GB. Advertise support
729843
* for 1 MB BAR size only.
844+
*
845+
* For a BAR that has been configured via dw_pcie_ep_set_bar(),
846+
* advertise support for only that size instead.
730847
*/
731-
for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL)
732-
dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, BIT(4));
848+
for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL) {
849+
/*
850+
* While the RESBAR_CAP_REG_* fields are sticky, the
851+
* RESBAR_CTRL_REG_BAR_SIZE field is non-sticky (it is
852+
* sticky in certain versions of DWC PCIe, but not all).
853+
*
854+
* RESBAR_CTRL_REG_BAR_SIZE is updated automatically by
855+
* the controller when RESBAR_CAP_REG is written, which
856+
* is why RESBAR_CAP_REG is written here.
857+
*/
858+
val = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
859+
bar = val & PCI_REBAR_CTRL_BAR_IDX;
860+
if (ep->epf_bar[bar])
861+
pci_epc_bar_size_to_rebar_cap(ep->epf_bar[bar]->size, &val);
862+
else
863+
val = BIT(4);
864+
865+
dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, val);
866+
}
733867
}
734868

735869
dw_pcie_setup(pci);
@@ -817,7 +951,7 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
817951
if (ep->ops->init)
818952
ep->ops->init(ep);
819953

820-
ptm_cap_base = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_PTM);
954+
ptm_cap_base = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_PTM);
821955

822956
/*
823957
* PTM responder capability can be disabled only after disabling

drivers/pci/controller/dwc/pcie-dw-rockchip.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -273,12 +273,12 @@ static const struct pci_epc_features rockchip_pcie_epc_features_rk3568 = {
273273
.msi_capable = true,
274274
.msix_capable = true,
275275
.align = SZ_64K,
276-
.bar[BAR_0] = { .type = BAR_FIXED, .fixed_size = SZ_1M, },
277-
.bar[BAR_1] = { .type = BAR_FIXED, .fixed_size = SZ_1M, },
278-
.bar[BAR_2] = { .type = BAR_FIXED, .fixed_size = SZ_1M, },
279-
.bar[BAR_3] = { .type = BAR_FIXED, .fixed_size = SZ_1M, },
280-
.bar[BAR_4] = { .type = BAR_FIXED, .fixed_size = SZ_1M, },
281-
.bar[BAR_5] = { .type = BAR_FIXED, .fixed_size = SZ_1M, },
276+
.bar[BAR_0] = { .type = BAR_RESIZABLE, },
277+
.bar[BAR_1] = { .type = BAR_RESIZABLE, },
278+
.bar[BAR_2] = { .type = BAR_RESIZABLE, },
279+
.bar[BAR_3] = { .type = BAR_RESIZABLE, },
280+
.bar[BAR_4] = { .type = BAR_RESIZABLE, },
281+
.bar[BAR_5] = { .type = BAR_RESIZABLE, },
282282
};
283283

284284
/*
@@ -293,12 +293,12 @@ static const struct pci_epc_features rockchip_pcie_epc_features_rk3588 = {
293293
.msi_capable = true,
294294
.msix_capable = true,
295295
.align = SZ_64K,
296-
.bar[BAR_0] = { .type = BAR_FIXED, .fixed_size = SZ_1M, },
297-
.bar[BAR_1] = { .type = BAR_FIXED, .fixed_size = SZ_1M, },
298-
.bar[BAR_2] = { .type = BAR_FIXED, .fixed_size = SZ_1M, },
299-
.bar[BAR_3] = { .type = BAR_FIXED, .fixed_size = SZ_1M, },
296+
.bar[BAR_0] = { .type = BAR_RESIZABLE, },
297+
.bar[BAR_1] = { .type = BAR_RESIZABLE, },
298+
.bar[BAR_2] = { .type = BAR_RESIZABLE, },
299+
.bar[BAR_3] = { .type = BAR_RESIZABLE, },
300300
.bar[BAR_4] = { .type = BAR_RESERVED, },
301-
.bar[BAR_5] = { .type = BAR_FIXED, .fixed_size = SZ_1M, },
301+
.bar[BAR_5] = { .type = BAR_RESIZABLE, },
302302
};
303303

304304
static const struct pci_epc_features *

0 commit comments

Comments
 (0)