setup-res.c (275d38585c742acdd6b8ab20f2588552f04c5d31) | setup-res.c (2bbc6942273b5b3097bd265d82227bdd84b351b2) |
---|---|
1/* 2 * drivers/pci/setup-res.c 3 * 4 * Extruded from code written by 5 * Dave Rusling (david.rusling@reo.mts.dec.com) 6 * David Mosberger (davidm@cs.arizona.edu) 7 * David Miller (davem@redhat.com) 8 * --- 114 unchanged lines hidden (view full) --- 123 124 /* Prefetchable MMIO Base/Limit */ 125 pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, 0); 126 pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, 0x0000fff0); 127 pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff); 128} 129#endif /* CONFIG_PCI_QUIRKS */ 130 | 1/* 2 * drivers/pci/setup-res.c 3 * 4 * Extruded from code written by 5 * Dave Rusling (david.rusling@reo.mts.dec.com) 6 * David Mosberger (davidm@cs.arizona.edu) 7 * David Miller (davem@redhat.com) 8 * --- 114 unchanged lines hidden (view full) --- 123 124 /* Prefetchable MMIO Base/Limit */ 125 pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, 0); 126 pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, 0x0000fff0); 127 pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff); 128} 129#endif /* CONFIG_PCI_QUIRKS */ 130 |
131 132 |
|
131static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, | 133static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, |
132 int resno) | 134 int resno, resource_size_t size, resource_size_t align) |
133{ 134 struct resource *res = dev->resource + resno; | 135{ 136 struct resource *res = dev->resource + resno; |
135 resource_size_t size, min, align; | 137 resource_size_t min; |
136 int ret; 137 | 138 int ret; 139 |
138 size = resource_size(res); | |
139 min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; | 140 min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; |
140 align = pci_resource_alignment(dev, res); | |
141 142 /* First, try exact prefetching match.. */ 143 ret = pci_bus_alloc_resource(bus, res, size, align, min, 144 IORESOURCE_PREFETCH, 145 pcibios_align_resource, dev); 146 147 if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) { 148 /* 149 * That failed. 150 * 151 * But a prefetching area can handle a non-prefetching 152 * window (it will just not perform as well). 153 */ 154 ret = pci_bus_alloc_resource(bus, res, size, align, min, 0, 155 pcibios_align_resource, dev); 156 } | 141 142 /* First, try exact prefetching match.. */ 143 ret = pci_bus_alloc_resource(bus, res, size, align, min, 144 IORESOURCE_PREFETCH, 145 pcibios_align_resource, dev); 146 147 if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) { 148 /* 149 * That failed. 150 * 151 * But a prefetching area can handle a non-prefetching 152 * window (it will just not perform as well). 153 */ 154 ret = pci_bus_alloc_resource(bus, res, size, align, min, 0, 155 pcibios_align_resource, dev); 156 } |
157 return ret; 158} |
|
157 | 159 |
158 if (ret < 0 && dev->fw_addr[resno]) { 159 struct resource *root, *conflict; 160 resource_size_t start, end; | 160static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev, 161 int resno, resource_size_t size) 162{ 163 struct resource *root, *conflict; 164 resource_size_t start, end; 165 int ret = 0; |
161 | 166 |
162 /* 163 * If we failed to assign anything, let's try the address 164 * where firmware left it. That at least has a chance of 165 * working, which is better than just leaving it disabled. 166 */ | 167 if (res->flags & IORESOURCE_IO) 168 root = &ioport_resource; 169 else 170 root = &iomem_resource; |
167 | 171 |
168 if (res->flags & IORESOURCE_IO) 169 root = &ioport_resource; | 172 start = res->start; 173 end = res->end; 174 res->start = dev->fw_addr[resno]; 175 res->end = res->start + size - 1; 176 dev_info(&dev->dev, "BAR %d: trying firmware assignment %pR\n", 177 resno, res); 178 conflict = request_resource_conflict(root, res); 179 if (conflict) { 180 dev_info(&dev->dev, 181 "BAR %d: %pR conflicts with %s %pR\n", resno, 182 res, conflict->name, conflict); 183 res->start = start; 184 res->end = end; 185 ret = 1; 186 } 187 return ret; 188} 189 190static int _pci_assign_resource(struct pci_dev *dev, int resno, int size, resource_size_t min_align) 191{ 192 struct resource *res = dev->resource + resno; 193 struct pci_bus *bus; 194 int ret; 195 char *type; 196 197 bus = dev->bus; 198 while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) { 199 if (!bus->parent || !bus->self->transparent) 200 break; 201 bus = bus->parent; 202 } 203 204 if (ret) { 205 if (res->flags & IORESOURCE_MEM) 206 if (res->flags & IORESOURCE_PREFETCH) 207 type = "mem pref"; 208 else 209 type = "mem"; 210 else if (res->flags & IORESOURCE_IO) 211 type = "io"; |
170 else | 212 else |
171 root = &iomem_resource; | 213 type = "unknown"; 214 dev_info(&dev->dev, 215 "BAR %d: can't assign %s (size %#llx)\n", 216 resno, type, (unsigned long long) resource_size(res)); 217 } |
172 | 218 |
173 start = res->start; 174 end = res->end; 175 res->start = dev->fw_addr[resno]; 176 res->end = res->start + size - 1; 177 dev_info(&dev->dev, "BAR %d: trying firmware assignment %pR\n", 178 resno, res); 179 conflict = request_resource_conflict(root, res); 180 if (conflict) { 181 dev_info(&dev->dev, 182 "BAR %d: %pR conflicts with %s %pR\n", resno, 183 res, conflict->name, conflict); 184 res->start = start; 185 res->end = end; 186 } else 187 ret = 0; | 219 return ret; 220} 221 222int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize, 223 resource_size_t min_align) 224{ 225 struct resource *res = dev->resource + resno; 226 resource_size_t new_size; 227 int ret; 228 229 if (!res->parent) { 230 dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resouce %pR " 231 "\n", resno, res); 232 return -EINVAL; |
188 } 189 | 233 } 234 |
235 new_size = resource_size(res) + addsize + min_align; 236 ret = _pci_assign_resource(dev, resno, new_size, min_align); |
|
190 if (!ret) { 191 res->flags &= ~IORESOURCE_STARTALIGN; 192 dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res); 193 if (resno < PCI_BRIDGE_RESOURCES) 194 pci_update_resource(dev, resno); 195 } | 237 if (!ret) { 238 res->flags &= ~IORESOURCE_STARTALIGN; 239 dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res); 240 if (resno < PCI_BRIDGE_RESOURCES) 241 pci_update_resource(dev, resno); 242 } |
196 | |
197 return ret; 198} 199 200int pci_assign_resource(struct pci_dev *dev, int resno) 201{ 202 struct resource *res = dev->resource + resno; | 243 return ret; 244} 245 246int pci_assign_resource(struct pci_dev *dev, int resno) 247{ 248 struct resource *res = dev->resource + resno; |
203 resource_size_t align; | 249 resource_size_t align, size; |
204 struct pci_bus *bus; 205 int ret; | 250 struct pci_bus *bus; 251 int ret; |
206 char *type; | |
207 208 align = pci_resource_alignment(dev, res); 209 if (!align) { 210 dev_info(&dev->dev, "BAR %d: can't assign %pR " 211 "(bogus alignment)\n", resno, res); 212 return -EINVAL; 213 } 214 215 bus = dev->bus; | 252 253 align = pci_resource_alignment(dev, res); 254 if (!align) { 255 dev_info(&dev->dev, "BAR %d: can't assign %pR " 256 "(bogus alignment)\n", resno, res); 257 return -EINVAL; 258 } 259 260 bus = dev->bus; |
216 while ((ret = __pci_assign_resource(bus, dev, resno))) { 217 if (bus->parent && bus->self->transparent) 218 bus = bus->parent; 219 else 220 bus = NULL; 221 if (bus) 222 continue; 223 break; 224 } | 261 size = resource_size(res); 262 ret = _pci_assign_resource(dev, resno, size, align); |
225 | 263 |
226 if (ret) { 227 if (res->flags & IORESOURCE_MEM) 228 if (res->flags & IORESOURCE_PREFETCH) 229 type = "mem pref"; 230 else 231 type = "mem"; 232 else if (res->flags & IORESOURCE_IO) 233 type = "io"; 234 else 235 type = "unknown"; 236 dev_info(&dev->dev, 237 "BAR %d: can't assign %s (size %#llx)\n", 238 resno, type, (unsigned long long) resource_size(res)); 239 } | 264 /* 265 * If we failed to assign anything, let's try the address 266 * where firmware left it. That at least has a chance of 267 * working, which is better than just leaving it disabled. 268 */ 269 if (ret < 0 && dev->fw_addr[resno]) 270 ret = pci_revert_fw_address(res, dev, resno, size); |
240 | 271 |
272 if (!ret) { 273 res->flags &= ~IORESOURCE_STARTALIGN; 274 dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res); 275 if (resno < PCI_BRIDGE_RESOURCES) 276 pci_update_resource(dev, resno); 277 } |
|
241 return ret; 242} 243 | 278 return ret; 279} 280 |
281 |
|
244/* Sort resources by alignment */ 245void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) 246{ 247 int i; 248 249 for (i = 0; i < PCI_NUM_RESOURCES; i++) { 250 struct resource *r; 251 struct resource_list *list, *tmp; --- 78 unchanged lines hidden --- | 282/* Sort resources by alignment */ 283void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) 284{ 285 int i; 286 287 for (i = 0; i < PCI_NUM_RESOURCES; i++) { 288 struct resource *r; 289 struct resource_list *list, *tmp; --- 78 unchanged lines hidden --- |