From db7a62482d2f6a63f36f30f62c4cbf1e53035719 Mon Sep 17 00:00:00 2001 From: Alan Mikhak Date: Thu, 23 May 2019 14:45:44 -0700 Subject: PCI: endpoint: Set endpoint controller pointer to NULL Set endpoint controller pointer to NULL in pci_epc_remove_epf() to avoid -EBUSY on subsequent call to pci_epc_add_epf(). Add a check for NULL endpoint function pointer. Signed-off-by: Alan Mikhak Signed-off-by: Lorenzo Pieralisi Acked-by: Kishon Vijay Abraham I --- drivers/pci/endpoint/pci-epc-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index e4712a0f249c..2091508c1620 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -519,11 +519,12 @@ void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf) { unsigned long flags; - if (!epc || IS_ERR(epc)) + if (!epc || IS_ERR(epc) || !epf) return; spin_lock_irqsave(&epc->lock, flags); list_del(&epf->list); + epf->epc = NULL; spin_unlock_irqrestore(&epc->lock, flags); } EXPORT_SYMBOL_GPL(pci_epc_remove_epf); -- cgit v1.2.3 From f16fb16ed16c7f561e9c41c9ae4107c7f6aa553c Mon Sep 17 00:00:00 2001 From: Alan Mikhak Date: Thu, 23 May 2019 14:47:59 -0700 Subject: PCI: endpoint: Allocate enough space for fixed size BAR PCI endpoint test function code should honor the .bar_fixed_size parameter from underlying endpoint controller drivers or results may be unexpected. In pci_epf_test_alloc_space(), check if BAR being used for test register space is a fixed size BAR. If so, allocate the required fixed size. Signed-off-by: Alan Mikhak Signed-off-by: Lorenzo Pieralisi Acked-by: Kishon Vijay Abraham I --- drivers/pci/endpoint/functions/pci-epf-test.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index 27806987e93b..7d41e6684b87 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -434,10 +434,16 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf) int bar; enum pci_barno test_reg_bar = epf_test->test_reg_bar; const struct pci_epc_features *epc_features; + size_t test_reg_size; epc_features = epf_test->epc_features; - base = pci_epf_alloc_space(epf, sizeof(struct pci_epf_test_reg), + if (epc_features->bar_fixed_size[test_reg_bar]) + test_reg_size = bar_size[test_reg_bar]; + else + test_reg_size = sizeof(struct pci_epf_test_reg); + + base = pci_epf_alloc_space(epf, test_reg_size, test_reg_bar, epc_features->align); if (!base) { dev_err(dev, "Failed to allocated register space\n"); -- cgit v1.2.3 From 3041a643613a2530ade35a9ae97709a9da4c0c72 Mon Sep 17 00:00:00 2001 From: Alan Mikhak Date: Thu, 23 May 2019 14:55:40 -0700 Subject: PCI: endpoint: Skip odd BAR when skipping 64bit BAR Always skip odd BAR when skipping 64bit BARs in pci_epf_test_set_bar() and pci_epf_test_alloc_space() otherwise pci_epf_test_set_bar() will call pci_epc_set_bar() on an odd loop index when skipping reserved 64bit BAR. Moreover, pci_epf_test_alloc_space() will call pci_epf_alloc_space() on bind for an odd loop index when BAR is 64bit but leaks on subsequent unbind by not calling pci_epf_free_space(). Signed-off-by: Alan Mikhak Signed-off-by: Lorenzo Pieralisi Acked-by: Kishon Vijay Abraham I Reviewed-by: Paul Walmsley --- drivers/pci/endpoint/functions/pci-epf-test.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index 7d41e6684b87..e8bcc924dbf8 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -389,7 +389,7 @@ static void pci_epf_test_unbind(struct pci_epf *epf) static int pci_epf_test_set_bar(struct pci_epf *epf) { - int bar; + int bar, add; int ret; struct pci_epf_bar *epf_bar; struct pci_epc *epc = epf->epc; @@ -400,8 +400,14 @@ static int pci_epf_test_set_bar(struct pci_epf *epf) epc_features = epf_test->epc_features; - for (bar = BAR_0; bar <= BAR_5; bar++) { + for (bar = BAR_0; bar <= BAR_5; bar += add) { epf_bar = &epf->bar[bar]; + /* + * pci_epc_set_bar() sets PCI_BASE_ADDRESS_MEM_TYPE_64 + * if the specific implementation required a 64-bit BAR, + * even if we only requested a 32-bit BAR. + */ + add = (epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) ? 2 : 1; if (!!(epc_features->reserved_bar & (1 << bar))) continue; @@ -413,13 +419,6 @@ static int pci_epf_test_set_bar(struct pci_epf *epf) if (bar == test_reg_bar) return ret; } - /* - * pci_epc_set_bar() sets PCI_BASE_ADDRESS_MEM_TYPE_64 - * if the specific implementation required a 64-bit BAR, - * even if we only requested a 32-bit BAR. - */ - if (epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) - bar++; } return 0; @@ -431,7 +430,7 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf) struct device *dev = &epf->dev; struct pci_epf_bar *epf_bar; void *base; - int bar; + int bar, add; enum pci_barno test_reg_bar = epf_test->test_reg_bar; const struct pci_epc_features *epc_features; size_t test_reg_size; @@ -451,8 +450,10 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf) } epf_test->reg[test_reg_bar] = base; - for (bar = BAR_0; bar <= BAR_5; bar++) { + for (bar = BAR_0; bar <= BAR_5; bar += add) { epf_bar = &epf->bar[bar]; + add = (epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) ? 2 : 1; + if (bar == test_reg_bar) continue; @@ -465,8 +466,6 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf) dev_err(dev, "Failed to allocate space for BAR%d\n", bar); epf_test->reg[bar] = base; - if (epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) - bar++; } return 0; -- cgit v1.2.3 From dbb7bbcc8ad248b1ab05bd27dfdb587ef4023dab Mon Sep 17 00:00:00 2001 From: Alan Mikhak Date: Thu, 23 May 2019 14:57:27 -0700 Subject: PCI: endpoint: Clear BAR before freeing its space Associated pci_epf_bar structure is needed in pci_epc_clear_bar() to clear a BAR correctly but it is reset in pci_epf_free_space() (that is called first) which results in pci_epc_clear_bar() failure. Reorder the pci_epc_clear_bar()/pci_epf_free_space() calls execution to fix the issue. Signed-off-by: Alan Mikhak [lorenzo.pieralisi@arm.com: reworded the commit log] Signed-off-by: Lorenzo Pieralisi Acked-by: Kishon Vijay Abraham I --- drivers/pci/endpoint/functions/pci-epf-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index e8bcc924dbf8..1cfe3687a211 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -381,8 +381,8 @@ static void pci_epf_test_unbind(struct pci_epf *epf) epf_bar = &epf->bar[bar]; if (epf_test->reg[bar]) { - pci_epf_free_space(epf, epf_test->reg[bar], bar); pci_epc_clear_bar(epc, epf->func_no, epf_bar); + pci_epf_free_space(epf, epf_test->reg[bar], bar); } } } -- cgit v1.2.3