diff options
author | Alan Mikhak <alan.mikhak@sifive.com> | 2019-05-23 17:55:40 -0400 |
---|---|---|
committer | Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | 2019-06-11 05:55:36 -0400 |
commit | 3041a643613a2530ade35a9ae97709a9da4c0c72 (patch) | |
tree | 88456033c500f82bf26e4af96e9ea065901b9ab9 | |
parent | f16fb16ed16c7f561e9c41c9ae4107c7f6aa553c (diff) |
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 <alan.mikhak@sifive.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Kishon Vijay Abraham I <kishon@ti.com>
Reviewed-by: Paul Walmsley <paul.walmsley@sifive.com>
-rw-r--r-- | drivers/pci/endpoint/functions/pci-epf-test.c | 25 |
1 files changed, 12 insertions, 13 deletions
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) | |||
389 | 389 | ||
390 | static int pci_epf_test_set_bar(struct pci_epf *epf) | 390 | static int pci_epf_test_set_bar(struct pci_epf *epf) |
391 | { | 391 | { |
392 | int bar; | 392 | int bar, add; |
393 | int ret; | 393 | int ret; |
394 | struct pci_epf_bar *epf_bar; | 394 | struct pci_epf_bar *epf_bar; |
395 | struct pci_epc *epc = epf->epc; | 395 | struct pci_epc *epc = epf->epc; |
@@ -400,8 +400,14 @@ static int pci_epf_test_set_bar(struct pci_epf *epf) | |||
400 | 400 | ||
401 | epc_features = epf_test->epc_features; | 401 | epc_features = epf_test->epc_features; |
402 | 402 | ||
403 | for (bar = BAR_0; bar <= BAR_5; bar++) { | 403 | for (bar = BAR_0; bar <= BAR_5; bar += add) { |
404 | epf_bar = &epf->bar[bar]; | 404 | epf_bar = &epf->bar[bar]; |
405 | /* | ||
406 | * pci_epc_set_bar() sets PCI_BASE_ADDRESS_MEM_TYPE_64 | ||
407 | * if the specific implementation required a 64-bit BAR, | ||
408 | * even if we only requested a 32-bit BAR. | ||
409 | */ | ||
410 | add = (epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) ? 2 : 1; | ||
405 | 411 | ||
406 | if (!!(epc_features->reserved_bar & (1 << bar))) | 412 | if (!!(epc_features->reserved_bar & (1 << bar))) |
407 | continue; | 413 | continue; |
@@ -413,13 +419,6 @@ static int pci_epf_test_set_bar(struct pci_epf *epf) | |||
413 | if (bar == test_reg_bar) | 419 | if (bar == test_reg_bar) |
414 | return ret; | 420 | return ret; |
415 | } | 421 | } |
416 | /* | ||
417 | * pci_epc_set_bar() sets PCI_BASE_ADDRESS_MEM_TYPE_64 | ||
418 | * if the specific implementation required a 64-bit BAR, | ||
419 | * even if we only requested a 32-bit BAR. | ||
420 | */ | ||
421 | if (epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) | ||
422 | bar++; | ||
423 | } | 422 | } |
424 | 423 | ||
425 | return 0; | 424 | return 0; |
@@ -431,7 +430,7 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf) | |||
431 | struct device *dev = &epf->dev; | 430 | struct device *dev = &epf->dev; |
432 | struct pci_epf_bar *epf_bar; | 431 | struct pci_epf_bar *epf_bar; |
433 | void *base; | 432 | void *base; |
434 | int bar; | 433 | int bar, add; |
435 | enum pci_barno test_reg_bar = epf_test->test_reg_bar; | 434 | enum pci_barno test_reg_bar = epf_test->test_reg_bar; |
436 | const struct pci_epc_features *epc_features; | 435 | const struct pci_epc_features *epc_features; |
437 | size_t test_reg_size; | 436 | size_t test_reg_size; |
@@ -451,8 +450,10 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf) | |||
451 | } | 450 | } |
452 | epf_test->reg[test_reg_bar] = base; | 451 | epf_test->reg[test_reg_bar] = base; |
453 | 452 | ||
454 | for (bar = BAR_0; bar <= BAR_5; bar++) { | 453 | for (bar = BAR_0; bar <= BAR_5; bar += add) { |
455 | epf_bar = &epf->bar[bar]; | 454 | epf_bar = &epf->bar[bar]; |
455 | add = (epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) ? 2 : 1; | ||
456 | |||
456 | if (bar == test_reg_bar) | 457 | if (bar == test_reg_bar) |
457 | continue; | 458 | continue; |
458 | 459 | ||
@@ -465,8 +466,6 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf) | |||
465 | dev_err(dev, "Failed to allocate space for BAR%d\n", | 466 | dev_err(dev, "Failed to allocate space for BAR%d\n", |
466 | bar); | 467 | bar); |
467 | epf_test->reg[bar] = base; | 468 | epf_test->reg[bar] = base; |
468 | if (epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) | ||
469 | bar++; | ||
470 | } | 469 | } |
471 | 470 | ||
472 | return 0; | 471 | return 0; |