diff options
Diffstat (limited to 'drivers/pci/setup-res.c')
-rw-r--r-- | drivers/pci/setup-res.c | 56 |
1 files changed, 42 insertions, 14 deletions
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 66c4d8f42233..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 | 28 | static void pci_std_update_resource(struct pci_dev *dev, int resno) | |
29 | void 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, ®ion, res); | 59 | pcibios_resource_to_bus(dev->bus, ®ion, 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 | ||
123 | void 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 | |||
113 | int pci_claim_resource(struct pci_dev *dev, int resource) | 133 | int 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]; |
@@ -121,6 +141,14 @@ int pci_claim_resource(struct pci_dev *dev, int resource) | |||
121 | return -EINVAL; | 141 | return -EINVAL; |
122 | } | 142 | } |
123 | 143 | ||
144 | /* | ||
145 | * If we have a shadow copy in RAM, the PCI device doesn't respond | ||
146 | * to the shadow range, so we don't need to claim it, and upstream | ||
147 | * bridges don't need to route the range to the device. | ||
148 | */ | ||
149 | if (res->flags & IORESOURCE_ROM_SHADOW) | ||
150 | return 0; | ||
151 | |||
124 | root = pci_find_parent_resource(dev, res); | 152 | root = pci_find_parent_resource(dev, res); |
125 | if (!root) { | 153 | if (!root) { |
126 | dev_info(&dev->dev, "can't claim BAR %d %pR: no compatible bridge window\n", | 154 | dev_info(&dev->dev, "can't claim BAR %d %pR: no compatible bridge window\n", |