PCI: endpoint: Skip odd BAR when skipping 64bit BAR
authorAlan Mikhak <alan.mikhak@sifive.com>
Thu, 23 May 2019 21:55:40 +0000 (14:55 -0700)
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Tue, 11 Jun 2019 09:55:36 +0000 (10:55 +0100)
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>
drivers/pci/endpoint/functions/pci-epf-test.c

index 7d41e66..e8bcc92 100644 (file)
@@ -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;