diff options
Diffstat (limited to 'drivers/pci/endpoint/functions')
-rw-r--r-- | drivers/pci/endpoint/functions/pci-epf-test.c | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index e091193bd8a8..31617772ad51 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -301,15 +301,20 @@ static void pci_epf_test_clean_dma_chan(struct pci_epf_test *epf_test) if (!epf_test->dma_supported) return; - dma_release_channel(epf_test->dma_chan_tx); - if (epf_test->dma_chan_tx == epf_test->dma_chan_rx) { + if (epf_test->dma_chan_tx) { + dma_release_channel(epf_test->dma_chan_tx); + if (epf_test->dma_chan_tx == epf_test->dma_chan_rx) { + epf_test->dma_chan_tx = NULL; + epf_test->dma_chan_rx = NULL; + return; + } epf_test->dma_chan_tx = NULL; - epf_test->dma_chan_rx = NULL; - return; } - dma_release_channel(epf_test->dma_chan_rx); - epf_test->dma_chan_rx = NULL; + if (epf_test->dma_chan_rx) { + dma_release_channel(epf_test->dma_chan_rx); + epf_test->dma_chan_rx = NULL; + } } static void pci_epf_test_print_rate(struct pci_epf_test *epf_test, @@ -772,12 +777,24 @@ static void pci_epf_test_disable_doorbell(struct pci_epf_test *epf_test, u32 status = le32_to_cpu(reg->status); struct pci_epf *epf = epf_test->epf; struct pci_epc *epc = epf->epc; + int ret; if (bar < BAR_0) goto set_status_err; pci_epf_test_doorbell_cleanup(epf_test); - pci_epc_clear_bar(epc, epf->func_no, epf->vfunc_no, &epf_test->db_bar); + + /* + * The doorbell feature temporarily overrides the inbound translation + * to point to the address stored in epf_test->db_bar.phys_addr, i.e., + * it calls set_bar() twice without ever calling clear_bar(), as + * calling clear_bar() would clear the BAR's PCI address assigned by + * the host. Thus, when disabling the doorbell, restore the inbound + * translation to point to the memory allocated for the BAR. + */ + ret = pci_epc_set_bar(epc, epf->func_no, epf->vfunc_no, &epf->bar[bar]); + if (ret) + goto set_status_err; status |= STATUS_DOORBELL_DISABLE_SUCCESS; reg->status = cpu_to_le32(status); @@ -1050,7 +1067,12 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf) if (bar == test_reg_bar) continue; - base = pci_epf_alloc_space(epf, bar_size[bar], bar, + if (epc_features->bar[bar].type == BAR_FIXED) + test_reg_size = epc_features->bar[bar].fixed_size; + else + test_reg_size = bar_size[bar]; + + base = pci_epf_alloc_space(epf, test_reg_size, bar, epc_features, PRIMARY_INTERFACE); if (!base) dev_err(dev, "Failed to allocate space for BAR%d\n", |