aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/setup-res.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/setup-res.c')
-rw-r--r--drivers/pci/setup-res.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 9526e341988b..4bc589ee78d0 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -25,21 +25,18 @@
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include "pci.h" 26#include "pci.h"
27 27
28 28static void pci_std_update_resource(struct pci_dev *dev, int resno)
29void pci_update_resource(struct pci_dev *dev, int resno)
30{ 29{
31 struct pci_bus_region region; 30 struct pci_bus_region region;
32 bool disable; 31 bool disable;
33 u16 cmd; 32 u16 cmd;
34 u32 new, check, mask; 33 u32 new, check, mask;
35 int reg; 34 int reg;
36 enum pci_bar_type type;
37 struct resource *res = dev->resource + resno; 35 struct resource *res = dev->resource + resno;
38 36
39 if (dev->is_virtfn) { 37 /* Per SR-IOV spec 3.4.1.11, VF BARs are RO zero */
40 dev_warn(&dev->dev, "can't update VF BAR%d\n", resno); 38 if (dev->is_virtfn)
41 return; 39 return;
42 }
43 40
44 /* 41 /*
45 * Ignore resources for unimplemented BARs and unused resource slots 42 * Ignore resources for unimplemented BARs and unused resource slots
@@ -60,21 +57,34 @@ void pci_update_resource(struct pci_dev *dev, int resno)
60 return; 57 return;
61 58
62 pcibios_resource_to_bus(dev->bus, &region, res); 59 pcibios_resource_to_bus(dev->bus, &region, res);
60 new = region.start;
63 61
64 new = region.start | (res->flags & PCI_REGION_FLAG_MASK); 62 if (res->flags & IORESOURCE_IO) {
65 if (res->flags & IORESOURCE_IO)
66 mask = (u32)PCI_BASE_ADDRESS_IO_MASK; 63 mask = (u32)PCI_BASE_ADDRESS_IO_MASK;
67 else 64 new |= res->flags & ~PCI_BASE_ADDRESS_IO_MASK;
65 } else if (resno == PCI_ROM_RESOURCE) {
66 mask = (u32)PCI_ROM_ADDRESS_MASK;
67 } else {
68 mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; 68 mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
69 new |= res->flags & ~PCI_BASE_ADDRESS_MEM_MASK;
70 }
69 71
70 reg = pci_resource_bar(dev, resno, &type); 72 if (resno < PCI_ROM_RESOURCE) {
71 if (!reg) 73 reg = PCI_BASE_ADDRESS_0 + 4 * resno;
72 return; 74 } else if (resno == PCI_ROM_RESOURCE) {
73 if (type != pci_bar_unknown) { 75
76 /*
77 * Apparently some Matrox devices have ROM BARs that read
78 * as zero when disabled, so don't update ROM BARs unless
79 * they're enabled. See https://lkml.org/lkml/2005/8/30/138.
80 */
74 if (!(res->flags & IORESOURCE_ROM_ENABLE)) 81 if (!(res->flags & IORESOURCE_ROM_ENABLE))
75 return; 82 return;
83
84 reg = dev->rom_base_reg;
76 new |= PCI_ROM_ADDRESS_ENABLE; 85 new |= PCI_ROM_ADDRESS_ENABLE;
77 } 86 } else
87 return;
78 88
79 /* 89 /*
80 * We can't update a 64-bit BAR atomically, so when possible, 90 * We can't update a 64-bit BAR atomically, so when possible,
@@ -110,6 +120,16 @@ void pci_update_resource(struct pci_dev *dev, int resno)
110 pci_write_config_word(dev, PCI_COMMAND, cmd); 120 pci_write_config_word(dev, PCI_COMMAND, cmd);
111} 121}
112 122
123void pci_update_resource(struct pci_dev *dev, int resno)
124{
125 if (resno <= PCI_ROM_RESOURCE)
126 pci_std_update_resource(dev, resno);
127#ifdef CONFIG_PCI_IOV
128 else if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END)
129 pci_iov_update_resource(dev, resno);
130#endif
131}
132
113int pci_claim_resource(struct pci_dev *dev, int resource) 133int pci_claim_resource(struct pci_dev *dev, int resource)
114{ 134{
115 struct resource *res = &dev->resource[resource]; 135 struct resource *res = &dev->resource[resource];