]> www.infradead.org Git - users/hch/misc.git/commitdiff
PCI: endpoint: pci-epf-test: Fix doorbell test support
authorNiklas Cassel <cassel@kernel.org>
Mon, 8 Sep 2025 16:19:42 +0000 (18:19 +0200)
committerBjorn Helgaas <bhelgaas@google.com>
Fri, 12 Sep 2025 20:09:32 +0000 (15:09 -0500)
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.

Without this, running the PCI endpoint kselftest doorbell test case more
than once would fail.

Fixes: eff0c286aa91 ("PCI: endpoint: pci-epf-test: Add doorbell test support")
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20250908161942.534799-2-cassel@kernel.org
drivers/pci/endpoint/functions/pci-epf-test.c

index 2418add64104a9417c1a61208e8f37f860485826..09e1b8b46b5578782ddac75270bb60df5159cb87 100644 (file)
@@ -772,12 +772,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);