Skip to content

Commit 74855f6

Browse files
committed
Merge branch 'pci/endpoint'
- Destroy the EPC device in devm_pci_epc_destroy(), which previously didn't call devres_release() (Zijun Hu) - Simplify pci_epc_get() with class_find_device_by_name() (Zijun Hu) - Finish virtual EP removal in pci_epf_remove_vepf(), which previously caused a subsequent pci_epf_add_vepf() to fail with -EBUSY (Zijun Hu) - Write BAR_MASK before iATU registers in pci_epc_set_bar() so we don't depend on the BAR_MASK reset value being larger than the requested BAR size (Niklas Cassel) - Prevent changing BAR size/flags in pci_epc_set_bar() to prevent reads from bypassing the iATU if we reduced the BAR size (Niklas Cassel) - Verify address alignment when programming iATU so we don't attempt to write bits that are read-only because of the BAR size, which could lead to directing accesses to the wrong address (Niklas Cassel) - Implement artpec6 pci_epc_features so we can rely on all drivers supporting it so we can use it in EPC core code (Niklas Cassel) - Check for BARs of fixed size to prevent endpoint drivers from trying to change their size (Niklas Cassel) - Verify that requested BAR size is a power of two when endpoint driver sets the BAR (Niklas Cassel) * pci/endpoint: PCI: endpoint: Verify that requested BAR size is a power of two PCI: endpoint: Add size check for fixed size BARs in pci_epc_set_bar() PCI: artpec6: Implement dw_pcie_ep operation get_features PCI: dwc: ep: Add 'address' alignment to 'size' check in dw_pcie_prog_ep_inbound_atu() PCI: dwc: ep: Prevent changing BAR size/flags in pci_epc_set_bar() PCI: dwc: ep: Write BAR_MASK before iATU registers in pci_epc_set_bar() PCI: endpoint: Finish virtual EP removal in pci_epf_remove_vepf() PCI: endpoint: Simplify pci_epc_get() PCI: endpoint: Destroy the EPC device in devm_pci_epc_destroy() PCI: endpoint: Replace magic number '6' by PCI_STD_NUM_BARS
2 parents 770b18a + 0e7faea commit 74855f6

File tree

7 files changed

+77
-37
lines changed

7 files changed

+77
-37
lines changed

drivers/pci/controller/dwc/pcie-artpec6.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,9 +369,22 @@ static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
369369
return 0;
370370
}
371371

372+
static const struct pci_epc_features artpec6_pcie_epc_features = {
373+
.linkup_notifier = false,
374+
.msi_capable = true,
375+
.msix_capable = false,
376+
};
377+
378+
static const struct pci_epc_features *
379+
artpec6_pcie_get_features(struct dw_pcie_ep *ep)
380+
{
381+
return &artpec6_pcie_epc_features;
382+
}
383+
372384
static const struct dw_pcie_ep_ops pcie_ep_ops = {
373385
.init = artpec6_pcie_ep_init,
374386
.raise_irq = artpec6_pcie_raise_irq,
387+
.get_features = artpec6_pcie_get_features,
375388
};
376389

377390
static int artpec6_pcie_probe(struct platform_device *pdev)

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

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
128128
}
129129

130130
static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type,
131-
dma_addr_t cpu_addr, enum pci_barno bar)
131+
dma_addr_t cpu_addr, enum pci_barno bar,
132+
size_t size)
132133
{
133134
int ret;
134135
u32 free_win;
@@ -145,7 +146,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type,
145146
}
146147

147148
ret = dw_pcie_prog_ep_inbound_atu(pci, func_no, free_win, type,
148-
cpu_addr, bar);
149+
cpu_addr, bar, size);
149150
if (ret < 0) {
150151
dev_err(pci->dev, "Failed to program IB window\n");
151152
return ret;
@@ -222,19 +223,30 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
222223
if ((flags & PCI_BASE_ADDRESS_MEM_TYPE_64) && (bar & 1))
223224
return -EINVAL;
224225

225-
reg = PCI_BASE_ADDRESS_0 + (4 * bar);
226-
227-
if (!(flags & PCI_BASE_ADDRESS_SPACE))
228-
type = PCIE_ATU_TYPE_MEM;
229-
else
230-
type = PCIE_ATU_TYPE_IO;
226+
/*
227+
* Certain EPF drivers dynamically change the physical address of a BAR
228+
* (i.e. they call set_bar() twice, without ever calling clear_bar(), as
229+
* calling clear_bar() would clear the BAR's PCI address assigned by the
230+
* host).
231+
*/
232+
if (ep->epf_bar[bar]) {
233+
/*
234+
* We can only dynamically change a BAR if the new BAR size and
235+
* BAR flags do not differ from the existing configuration.
236+
*/
237+
if (ep->epf_bar[bar]->barno != bar ||
238+
ep->epf_bar[bar]->size != size ||
239+
ep->epf_bar[bar]->flags != flags)
240+
return -EINVAL;
231241

232-
ret = dw_pcie_ep_inbound_atu(ep, func_no, type, epf_bar->phys_addr, bar);
233-
if (ret)
234-
return ret;
242+
/*
243+
* When dynamically changing a BAR, skip writing the BAR reg, as
244+
* that would clear the BAR's PCI address assigned by the host.
245+
*/
246+
goto config_atu;
247+
}
235248

236-
if (ep->epf_bar[bar])
237-
return 0;
249+
reg = PCI_BASE_ADDRESS_0 + (4 * bar);
238250

239251
dw_pcie_dbi_ro_wr_en(pci);
240252

@@ -246,9 +258,21 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
246258
dw_pcie_ep_writel_dbi(ep, func_no, reg + 4, 0);
247259
}
248260

249-
ep->epf_bar[bar] = epf_bar;
250261
dw_pcie_dbi_ro_wr_dis(pci);
251262

263+
config_atu:
264+
if (!(flags & PCI_BASE_ADDRESS_SPACE))
265+
type = PCIE_ATU_TYPE_MEM;
266+
else
267+
type = PCIE_ATU_TYPE_IO;
268+
269+
ret = dw_pcie_ep_inbound_atu(ep, func_no, type, epf_bar->phys_addr, bar,
270+
size);
271+
if (ret)
272+
return ret;
273+
274+
ep->epf_bar[bar] = epf_bar;
275+
252276
return 0;
253277
}
254278

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -597,11 +597,12 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
597597
}
598598

599599
int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
600-
int type, u64 cpu_addr, u8 bar)
600+
int type, u64 cpu_addr, u8 bar, size_t size)
601601
{
602602
u32 retries, val;
603603

604-
if (!IS_ALIGNED(cpu_addr, pci->region_align))
604+
if (!IS_ALIGNED(cpu_addr, pci->region_align) ||
605+
!IS_ALIGNED(cpu_addr, size))
605606
return -EINVAL;
606607

607608
dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_LOWER_TARGET,

drivers/pci/controller/dwc/pcie-designware.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
491491
int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
492492
u64 cpu_addr, u64 pci_addr, u64 size);
493493
int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
494-
int type, u64 cpu_addr, u8 bar);
494+
int type, u64 cpu_addr, u8 bar, size_t size);
495495
void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index);
496496
void dw_pcie_setup(struct dw_pcie *pci);
497497
void dw_pcie_iatu_detect(struct dw_pcie *pci);

drivers/pci/endpoint/pci-epc-core.c

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -60,26 +60,17 @@ struct pci_epc *pci_epc_get(const char *epc_name)
6060
int ret = -EINVAL;
6161
struct pci_epc *epc;
6262
struct device *dev;
63-
struct class_dev_iter iter;
6463

65-
class_dev_iter_init(&iter, &pci_epc_class, NULL, NULL);
66-
while ((dev = class_dev_iter_next(&iter))) {
67-
if (strcmp(epc_name, dev_name(dev)))
68-
continue;
64+
dev = class_find_device_by_name(&pci_epc_class, epc_name);
65+
if (!dev)
66+
goto err;
6967

70-
epc = to_pci_epc(dev);
71-
if (!try_module_get(epc->ops->owner)) {
72-
ret = -EINVAL;
73-
goto err;
74-
}
75-
76-
class_dev_iter_exit(&iter);
77-
get_device(&epc->dev);
68+
epc = to_pci_epc(dev);
69+
if (try_module_get(epc->ops->owner))
7870
return epc;
79-
}
8071

8172
err:
82-
class_dev_iter_exit(&iter);
73+
put_device(dev);
8374
return ERR_PTR(ret);
8475
}
8576
EXPORT_SYMBOL_GPL(pci_epc_get);
@@ -609,10 +600,20 @@ EXPORT_SYMBOL_GPL(pci_epc_clear_bar);
609600
int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
610601
struct pci_epf_bar *epf_bar)
611602
{
612-
int ret;
603+
const struct pci_epc_features *epc_features;
604+
enum pci_barno bar = epf_bar->barno;
613605
int flags = epf_bar->flags;
606+
int ret;
614607

615-
if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
608+
epc_features = pci_epc_get_features(epc, func_no, vfunc_no);
609+
if (!epc_features)
610+
return -EINVAL;
611+
612+
if (epc_features->bar[bar].type == BAR_FIXED &&
613+
(epc_features->bar[bar].fixed_size != epf_bar->size))
614+
return -EINVAL;
615+
616+
if (!is_power_of_2(epf_bar->size))
616617
return -EINVAL;
617618

618619
if ((epf_bar->barno == BAR_5 && flags & PCI_BASE_ADDRESS_MEM_TYPE_64) ||
@@ -942,7 +943,7 @@ void devm_pci_epc_destroy(struct device *dev, struct pci_epc *epc)
942943
{
943944
int r;
944945

945-
r = devres_destroy(dev, devm_pci_epc_release, devm_pci_epc_match,
946+
r = devres_release(dev, devm_pci_epc_release, devm_pci_epc_match,
946947
epc);
947948
dev_WARN_ONCE(dev, r, "couldn't find PCI EPC resource\n");
948949
}

drivers/pci/endpoint/pci-epf-core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ void pci_epf_remove_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf)
202202

203203
mutex_lock(&epf_pf->lock);
204204
clear_bit(epf_vf->vfunc_no, &epf_pf->vfunction_num_map);
205+
epf_vf->epf_pf = NULL;
205206
list_del(&epf_vf->list);
206207
mutex_unlock(&epf_pf->lock);
207208
}

include/linux/pci-epf.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ struct pci_epf {
157157
struct device dev;
158158
const char *name;
159159
struct pci_epf_header *header;
160-
struct pci_epf_bar bar[6];
160+
struct pci_epf_bar bar[PCI_STD_NUM_BARS];
161161
u8 msi_interrupts;
162162
u16 msix_interrupts;
163163
u8 func_no;
@@ -174,7 +174,7 @@ struct pci_epf {
174174
/* Below members are to attach secondary EPC to an endpoint function */
175175
struct pci_epc *sec_epc;
176176
struct list_head sec_epc_list;
177-
struct pci_epf_bar sec_epc_bar[6];
177+
struct pci_epf_bar sec_epc_bar[PCI_STD_NUM_BARS];
178178
u8 sec_epc_func_no;
179179
struct config_group *group;
180180
unsigned int is_bound;

0 commit comments

Comments
 (0)