diff options
| -rw-r--r-- | arch/x86/pci/acpi.c | 9 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pcihp_slot.c | 45 | ||||
| -rw-r--r-- | drivers/pci/of.c | 2 | ||||
| -rw-r--r-- | drivers/pci/pci.c | 67 | ||||
| -rw-r--r-- | drivers/pci/pci.h | 4 | ||||
| -rw-r--r-- | drivers/pci/probe.c | 146 | ||||
| -rw-r--r-- | drivers/pci/setup-bus.c | 166 | ||||
| -rw-r--r-- | drivers/pci/setup-res.c | 152 | ||||
| -rw-r--r-- | include/linux/pci.h | 16 |
9 files changed, 454 insertions, 153 deletions
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index ae3cb23cd89b..c95330267f08 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c | |||
| @@ -360,6 +360,15 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) | |||
| 360 | } | 360 | } |
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | /* After the PCI-E bus has been walked and all devices discovered, | ||
| 364 | * configure any settings of the fabric that might be necessary. | ||
| 365 | */ | ||
| 366 | if (bus) { | ||
| 367 | struct pci_bus *child; | ||
| 368 | list_for_each_entry(child, &bus->children, node) | ||
| 369 | pcie_bus_configure_settings(child, child->self->pcie_mpss); | ||
| 370 | } | ||
| 371 | |||
| 363 | if (!bus) | 372 | if (!bus) |
| 364 | kfree(sd); | 373 | kfree(sd); |
| 365 | 374 | ||
diff --git a/drivers/pci/hotplug/pcihp_slot.c b/drivers/pci/hotplug/pcihp_slot.c index 749fdf070319..753b21aaea61 100644 --- a/drivers/pci/hotplug/pcihp_slot.c +++ b/drivers/pci/hotplug/pcihp_slot.c | |||
| @@ -158,47 +158,6 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) | |||
| 158 | */ | 158 | */ |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | /* Program PCIE MaxPayload setting on device: ensure parent maxpayload <= device */ | ||
| 162 | static int pci_set_payload(struct pci_dev *dev) | ||
| 163 | { | ||
| 164 | int pos, ppos; | ||
| 165 | u16 pctl, psz; | ||
| 166 | u16 dctl, dsz, dcap, dmax; | ||
| 167 | struct pci_dev *parent; | ||
| 168 | |||
| 169 | parent = dev->bus->self; | ||
| 170 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); | ||
| 171 | if (!pos) | ||
| 172 | return 0; | ||
| 173 | |||
| 174 | /* Read Device MaxPayload capability and setting */ | ||
| 175 | pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &dctl); | ||
| 176 | pci_read_config_word(dev, pos + PCI_EXP_DEVCAP, &dcap); | ||
| 177 | dsz = (dctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5; | ||
| 178 | dmax = (dcap & PCI_EXP_DEVCAP_PAYLOAD); | ||
| 179 | |||
| 180 | /* Read Parent MaxPayload setting */ | ||
| 181 | ppos = pci_find_capability(parent, PCI_CAP_ID_EXP); | ||
| 182 | if (!ppos) | ||
| 183 | return 0; | ||
| 184 | pci_read_config_word(parent, ppos + PCI_EXP_DEVCTL, &pctl); | ||
| 185 | psz = (pctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5; | ||
| 186 | |||
| 187 | /* If parent payload > device max payload -> error | ||
| 188 | * If parent payload > device payload -> set speed | ||
| 189 | * If parent payload <= device payload -> do nothing | ||
| 190 | */ | ||
| 191 | if (psz > dmax) | ||
| 192 | return -1; | ||
| 193 | else if (psz > dsz) { | ||
| 194 | dev_info(&dev->dev, "Setting MaxPayload to %d\n", 128 << psz); | ||
| 195 | pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, | ||
| 196 | (dctl & ~PCI_EXP_DEVCTL_PAYLOAD) + | ||
| 197 | (psz << 5)); | ||
| 198 | } | ||
| 199 | return 0; | ||
| 200 | } | ||
| 201 | |||
| 202 | void pci_configure_slot(struct pci_dev *dev) | 161 | void pci_configure_slot(struct pci_dev *dev) |
| 203 | { | 162 | { |
| 204 | struct pci_dev *cdev; | 163 | struct pci_dev *cdev; |
| @@ -210,9 +169,7 @@ void pci_configure_slot(struct pci_dev *dev) | |||
| 210 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) | 169 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) |
| 211 | return; | 170 | return; |
| 212 | 171 | ||
| 213 | ret = pci_set_payload(dev); | 172 | pcie_bus_configure_settings(dev->bus, dev->bus->self->pcie_mpss); |
| 214 | if (ret) | ||
| 215 | dev_warn(&dev->dev, "could not set device max payload\n"); | ||
| 216 | 173 | ||
| 217 | memset(&hpp, 0, sizeof(hpp)); | 174 | memset(&hpp, 0, sizeof(hpp)); |
| 218 | ret = pci_get_hp_params(dev, &hpp); | 175 | ret = pci_get_hp_params(dev, &hpp); |
diff --git a/drivers/pci/of.c b/drivers/pci/of.c index c94d37ec55c8..f0929934bb7a 100644 --- a/drivers/pci/of.c +++ b/drivers/pci/of.c | |||
| @@ -55,7 +55,7 @@ struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus) | |||
| 55 | */ | 55 | */ |
| 56 | if (bus->bridge->of_node) | 56 | if (bus->bridge->of_node) |
| 57 | return of_node_get(bus->bridge->of_node); | 57 | return of_node_get(bus->bridge->of_node); |
| 58 | if (bus->bridge->parent->of_node) | 58 | if (bus->bridge->parent && bus->bridge->parent->of_node) |
| 59 | return of_node_get(bus->bridge->parent->of_node); | 59 | return of_node_get(bus->bridge->parent->of_node); |
| 60 | return NULL; | 60 | return NULL; |
| 61 | } | 61 | } |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 08a95b369d85..466fad6e6ee2 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
| @@ -77,6 +77,8 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE; | |||
| 77 | unsigned long pci_hotplug_io_size = DEFAULT_HOTPLUG_IO_SIZE; | 77 | unsigned long pci_hotplug_io_size = DEFAULT_HOTPLUG_IO_SIZE; |
| 78 | unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE; | 78 | unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE; |
| 79 | 79 | ||
| 80 | enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_PERFORMANCE; | ||
| 81 | |||
| 80 | /* | 82 | /* |
| 81 | * The default CLS is used if arch didn't set CLS explicitly and not | 83 | * The default CLS is used if arch didn't set CLS explicitly and not |
| 82 | * all pci devices agree on the same value. Arch can override either | 84 | * all pci devices agree on the same value. Arch can override either |
| @@ -3223,6 +3225,67 @@ out: | |||
| 3223 | EXPORT_SYMBOL(pcie_set_readrq); | 3225 | EXPORT_SYMBOL(pcie_set_readrq); |
| 3224 | 3226 | ||
| 3225 | /** | 3227 | /** |
| 3228 | * pcie_get_mps - get PCI Express maximum payload size | ||
| 3229 | * @dev: PCI device to query | ||
| 3230 | * | ||
| 3231 | * Returns maximum payload size in bytes | ||
| 3232 | * or appropriate error value. | ||
| 3233 | */ | ||
| 3234 | int pcie_get_mps(struct pci_dev *dev) | ||
| 3235 | { | ||
| 3236 | int ret, cap; | ||
| 3237 | u16 ctl; | ||
| 3238 | |||
| 3239 | cap = pci_pcie_cap(dev); | ||
| 3240 | if (!cap) | ||
| 3241 | return -EINVAL; | ||
| 3242 | |||
| 3243 | ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); | ||
| 3244 | if (!ret) | ||
| 3245 | ret = 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); | ||
| 3246 | |||
| 3247 | return ret; | ||
| 3248 | } | ||
| 3249 | |||
| 3250 | /** | ||
| 3251 | * pcie_set_mps - set PCI Express maximum payload size | ||
| 3252 | * @dev: PCI device to query | ||
| 3253 | * @rq: maximum payload size in bytes | ||
| 3254 | * valid values are 128, 256, 512, 1024, 2048, 4096 | ||
| 3255 | * | ||
| 3256 | * If possible sets maximum payload size | ||
| 3257 | */ | ||
| 3258 | int pcie_set_mps(struct pci_dev *dev, int mps) | ||
| 3259 | { | ||
| 3260 | int cap, err = -EINVAL; | ||
| 3261 | u16 ctl, v; | ||
| 3262 | |||
| 3263 | if (mps < 128 || mps > 4096 || !is_power_of_2(mps)) | ||
| 3264 | goto out; | ||
| 3265 | |||
| 3266 | v = ffs(mps) - 8; | ||
| 3267 | if (v > dev->pcie_mpss) | ||
| 3268 | goto out; | ||
| 3269 | v <<= 5; | ||
| 3270 | |||
| 3271 | cap = pci_pcie_cap(dev); | ||
| 3272 | if (!cap) | ||
| 3273 | goto out; | ||
| 3274 | |||
| 3275 | err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); | ||
| 3276 | if (err) | ||
| 3277 | goto out; | ||
| 3278 | |||
| 3279 | if ((ctl & PCI_EXP_DEVCTL_PAYLOAD) != v) { | ||
| 3280 | ctl &= ~PCI_EXP_DEVCTL_PAYLOAD; | ||
| 3281 | ctl |= v; | ||
| 3282 | err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, ctl); | ||
| 3283 | } | ||
| 3284 | out: | ||
| 3285 | return err; | ||
| 3286 | } | ||
| 3287 | |||
| 3288 | /** | ||
| 3226 | * pci_select_bars - Make BAR mask from the type of resource | 3289 | * pci_select_bars - Make BAR mask from the type of resource |
| 3227 | * @dev: the PCI device for which BAR mask is made | 3290 | * @dev: the PCI device for which BAR mask is made |
| 3228 | * @flags: resource type mask to be selected | 3291 | * @flags: resource type mask to be selected |
| @@ -3505,6 +3568,10 @@ static int __init pci_setup(char *str) | |||
| 3505 | pci_hotplug_io_size = memparse(str + 9, &str); | 3568 | pci_hotplug_io_size = memparse(str + 9, &str); |
| 3506 | } else if (!strncmp(str, "hpmemsize=", 10)) { | 3569 | } else if (!strncmp(str, "hpmemsize=", 10)) { |
| 3507 | pci_hotplug_mem_size = memparse(str + 10, &str); | 3570 | pci_hotplug_mem_size = memparse(str + 10, &str); |
| 3571 | } else if (!strncmp(str, "pcie_bus_safe", 13)) { | ||
| 3572 | pcie_bus_config = PCIE_BUS_SAFE; | ||
| 3573 | } else if (!strncmp(str, "pcie_bus_perf", 13)) { | ||
| 3574 | pcie_bus_config = PCIE_BUS_PERFORMANCE; | ||
| 3508 | } else { | 3575 | } else { |
| 3509 | printk(KERN_ERR "PCI: Unknown option `%s'\n", | 3576 | printk(KERN_ERR "PCI: Unknown option `%s'\n", |
| 3510 | str); | 3577 | str); |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index c8cee764b0de..b74084e9ca12 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
| @@ -283,6 +283,8 @@ static inline int pci_iov_bus_range(struct pci_bus *bus) | |||
| 283 | 283 | ||
| 284 | #endif /* CONFIG_PCI_IOV */ | 284 | #endif /* CONFIG_PCI_IOV */ |
| 285 | 285 | ||
| 286 | extern unsigned long pci_cardbus_resource_alignment(struct resource *); | ||
| 287 | |||
| 286 | static inline resource_size_t pci_resource_alignment(struct pci_dev *dev, | 288 | static inline resource_size_t pci_resource_alignment(struct pci_dev *dev, |
| 287 | struct resource *res) | 289 | struct resource *res) |
| 288 | { | 290 | { |
| @@ -292,6 +294,8 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev, | |||
| 292 | if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END) | 294 | if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END) |
| 293 | return pci_sriov_resource_alignment(dev, resno); | 295 | return pci_sriov_resource_alignment(dev, resno); |
| 294 | #endif | 296 | #endif |
| 297 | if (dev->class >> 8 == PCI_CLASS_BRIDGE_CARDBUS) | ||
| 298 | return pci_cardbus_resource_alignment(res); | ||
| 295 | return resource_alignment(res); | 299 | return resource_alignment(res); |
| 296 | } | 300 | } |
| 297 | 301 | ||
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 795c9026d55f..8473727b29fa 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
| @@ -856,6 +856,8 @@ void set_pcie_port_type(struct pci_dev *pdev) | |||
| 856 | pdev->pcie_cap = pos; | 856 | pdev->pcie_cap = pos; |
| 857 | pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); | 857 | pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); |
| 858 | pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4; | 858 | pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4; |
| 859 | pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, ®16); | ||
| 860 | pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD; | ||
| 859 | } | 861 | } |
| 860 | 862 | ||
| 861 | void set_pcie_hotplug_bridge(struct pci_dev *pdev) | 863 | void set_pcie_hotplug_bridge(struct pci_dev *pdev) |
| @@ -1326,6 +1328,150 @@ int pci_scan_slot(struct pci_bus *bus, int devfn) | |||
| 1326 | return nr; | 1328 | return nr; |
| 1327 | } | 1329 | } |
| 1328 | 1330 | ||
| 1331 | static int pcie_find_smpss(struct pci_dev *dev, void *data) | ||
| 1332 | { | ||
| 1333 | u8 *smpss = data; | ||
| 1334 | |||
| 1335 | if (!pci_is_pcie(dev)) | ||
| 1336 | return 0; | ||
| 1337 | |||
| 1338 | /* For PCIE hotplug enabled slots not connected directly to a | ||
| 1339 | * PCI-E root port, there can be problems when hotplugging | ||
| 1340 | * devices. This is due to the possibility of hotplugging a | ||
| 1341 | * device into the fabric with a smaller MPS that the devices | ||
| 1342 | * currently running have configured. Modifying the MPS on the | ||
| 1343 | * running devices could cause a fatal bus error due to an | ||
| 1344 | * incoming frame being larger than the newly configured MPS. | ||
| 1345 | * To work around this, the MPS for the entire fabric must be | ||
| 1346 | * set to the minimum size. Any devices hotplugged into this | ||
| 1347 | * fabric will have the minimum MPS set. If the PCI hotplug | ||
| 1348 | * slot is directly connected to the root port and there are not | ||
| 1349 | * other devices on the fabric (which seems to be the most | ||
| 1350 | * common case), then this is not an issue and MPS discovery | ||
| 1351 | * will occur as normal. | ||
| 1352 | */ | ||
| 1353 | if (dev->is_hotplug_bridge && (!list_is_singular(&dev->bus->devices) || | ||
| 1354 | dev->bus->self->pcie_type != PCI_EXP_TYPE_ROOT_PORT)) | ||
| 1355 | *smpss = 0; | ||
| 1356 | |||
| 1357 | if (*smpss > dev->pcie_mpss) | ||
| 1358 | *smpss = dev->pcie_mpss; | ||
| 1359 | |||
| 1360 | return 0; | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | static void pcie_write_mps(struct pci_dev *dev, int mps) | ||
| 1364 | { | ||
| 1365 | int rc, dev_mpss; | ||
| 1366 | |||
| 1367 | dev_mpss = 128 << dev->pcie_mpss; | ||
| 1368 | |||
| 1369 | if (pcie_bus_config == PCIE_BUS_PERFORMANCE) { | ||
| 1370 | if (dev->bus->self) { | ||
| 1371 | dev_dbg(&dev->bus->dev, "Bus MPSS %d\n", | ||
| 1372 | 128 << dev->bus->self->pcie_mpss); | ||
| 1373 | |||
| 1374 | /* For "MPS Force Max", the assumption is made that | ||
| 1375 | * downstream communication will never be larger than | ||
| 1376 | * the MRRS. So, the MPS only needs to be configured | ||
| 1377 | * for the upstream communication. This being the case, | ||
| 1378 | * walk from the top down and set the MPS of the child | ||
| 1379 | * to that of the parent bus. | ||
| 1380 | */ | ||
| 1381 | mps = 128 << dev->bus->self->pcie_mpss; | ||
| 1382 | if (mps > dev_mpss) | ||
| 1383 | dev_warn(&dev->dev, "MPS configured higher than" | ||
| 1384 | " maximum supported by the device. If" | ||
| 1385 | " a bus issue occurs, try running with" | ||
| 1386 | " pci=pcie_bus_safe.\n"); | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | dev->pcie_mpss = ffs(mps) - 8; | ||
| 1390 | } | ||
| 1391 | |||
| 1392 | rc = pcie_set_mps(dev, mps); | ||
| 1393 | if (rc) | ||
| 1394 | dev_err(&dev->dev, "Failed attempting to set the MPS\n"); | ||
| 1395 | } | ||
| 1396 | |||
| 1397 | static void pcie_write_mrrs(struct pci_dev *dev, int mps) | ||
| 1398 | { | ||
| 1399 | int rc, mrrs; | ||
| 1400 | |||
| 1401 | if (pcie_bus_config == PCIE_BUS_PERFORMANCE) { | ||
| 1402 | int dev_mpss = 128 << dev->pcie_mpss; | ||
| 1403 | |||
| 1404 | /* For Max performance, the MRRS must be set to the largest | ||
| 1405 | * supported value. However, it cannot be configured larger | ||
| 1406 | * than the MPS the device or the bus can support. This assumes | ||
| 1407 | * that the largest MRRS available on the device cannot be | ||
| 1408 | * smaller than the device MPSS. | ||
| 1409 | */ | ||
| 1410 | mrrs = mps < dev_mpss ? mps : dev_mpss; | ||
| 1411 | } else | ||
| 1412 | /* In the "safe" case, configure the MRRS for fairness on the | ||
| 1413 | * bus by making all devices have the same size | ||
| 1414 | */ | ||
| 1415 | mrrs = mps; | ||
| 1416 | |||
| 1417 | |||
| 1418 | /* MRRS is a R/W register. Invalid values can be written, but a | ||
| 1419 | * subsiquent read will verify if the value is acceptable or not. | ||
| 1420 | * If the MRRS value provided is not acceptable (e.g., too large), | ||
| 1421 | * shrink the value until it is acceptable to the HW. | ||
| 1422 | */ | ||
| 1423 | while (mrrs != pcie_get_readrq(dev) && mrrs >= 128) { | ||
| 1424 | rc = pcie_set_readrq(dev, mrrs); | ||
| 1425 | if (rc) | ||
| 1426 | dev_err(&dev->dev, "Failed attempting to set the MRRS\n"); | ||
| 1427 | |||
| 1428 | mrrs /= 2; | ||
| 1429 | } | ||
| 1430 | } | ||
| 1431 | |||
| 1432 | static int pcie_bus_configure_set(struct pci_dev *dev, void *data) | ||
| 1433 | { | ||
| 1434 | int mps = 128 << *(u8 *)data; | ||
| 1435 | |||
| 1436 | if (!pci_is_pcie(dev)) | ||
| 1437 | return 0; | ||
| 1438 | |||
| 1439 | dev_info(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n", | ||
| 1440 | pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev)); | ||
| 1441 | |||
| 1442 | pcie_write_mps(dev, mps); | ||
| 1443 | pcie_write_mrrs(dev, mps); | ||
| 1444 | |||
| 1445 | dev_info(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n", | ||
| 1446 | pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev)); | ||
| 1447 | |||
| 1448 | return 0; | ||
| 1449 | } | ||
| 1450 | |||
| 1451 | /* pcie_bus_configure_mps requires that pci_walk_bus work in a top-down, | ||
| 1452 | * parents then children fashion. If this changes, then this code will not | ||
| 1453 | * work as designed. | ||
| 1454 | */ | ||
| 1455 | void pcie_bus_configure_settings(struct pci_bus *bus, u8 mpss) | ||
| 1456 | { | ||
| 1457 | u8 smpss = mpss; | ||
| 1458 | |||
| 1459 | if (!bus->self) | ||
| 1460 | return; | ||
| 1461 | |||
| 1462 | if (!pci_is_pcie(bus->self)) | ||
| 1463 | return; | ||
| 1464 | |||
| 1465 | if (pcie_bus_config == PCIE_BUS_SAFE) { | ||
| 1466 | pcie_find_smpss(bus->self, &smpss); | ||
| 1467 | pci_walk_bus(bus, pcie_find_smpss, &smpss); | ||
| 1468 | } | ||
| 1469 | |||
| 1470 | pcie_bus_configure_set(bus->self, &smpss); | ||
| 1471 | pci_walk_bus(bus, pcie_bus_configure_set, &smpss); | ||
| 1472 | } | ||
| 1473 | EXPORT_SYMBOL_GPL(pcie_bus_configure_settings); | ||
| 1474 | |||
| 1329 | unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) | 1475 | unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) |
| 1330 | { | 1476 | { |
| 1331 | unsigned int devfn, pass, max = bus->secondary; | 1477 | unsigned int devfn, pass, max = bus->secondary; |
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 8a1d3c7863a8..784da9d36029 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
| @@ -34,6 +34,7 @@ struct resource_list_x { | |||
| 34 | resource_size_t start; | 34 | resource_size_t start; |
| 35 | resource_size_t end; | 35 | resource_size_t end; |
| 36 | resource_size_t add_size; | 36 | resource_size_t add_size; |
| 37 | resource_size_t min_align; | ||
| 37 | unsigned long flags; | 38 | unsigned long flags; |
| 38 | }; | 39 | }; |
| 39 | 40 | ||
| @@ -65,7 +66,7 @@ void pci_realloc(void) | |||
| 65 | */ | 66 | */ |
| 66 | static void add_to_list(struct resource_list_x *head, | 67 | static void add_to_list(struct resource_list_x *head, |
| 67 | struct pci_dev *dev, struct resource *res, | 68 | struct pci_dev *dev, struct resource *res, |
| 68 | resource_size_t add_size) | 69 | resource_size_t add_size, resource_size_t min_align) |
| 69 | { | 70 | { |
| 70 | struct resource_list_x *list = head; | 71 | struct resource_list_x *list = head; |
| 71 | struct resource_list_x *ln = list->next; | 72 | struct resource_list_x *ln = list->next; |
| @@ -84,13 +85,16 @@ static void add_to_list(struct resource_list_x *head, | |||
| 84 | tmp->end = res->end; | 85 | tmp->end = res->end; |
| 85 | tmp->flags = res->flags; | 86 | tmp->flags = res->flags; |
| 86 | tmp->add_size = add_size; | 87 | tmp->add_size = add_size; |
| 88 | tmp->min_align = min_align; | ||
| 87 | list->next = tmp; | 89 | list->next = tmp; |
| 88 | } | 90 | } |
| 89 | 91 | ||
| 90 | static void add_to_failed_list(struct resource_list_x *head, | 92 | static void add_to_failed_list(struct resource_list_x *head, |
| 91 | struct pci_dev *dev, struct resource *res) | 93 | struct pci_dev *dev, struct resource *res) |
| 92 | { | 94 | { |
| 93 | add_to_list(head, dev, res, 0); | 95 | add_to_list(head, dev, res, |
| 96 | 0 /* dont care */, | ||
| 97 | 0 /* dont care */); | ||
| 94 | } | 98 | } |
| 95 | 99 | ||
| 96 | static void __dev_sort_resources(struct pci_dev *dev, | 100 | static void __dev_sort_resources(struct pci_dev *dev, |
| @@ -121,18 +125,18 @@ static inline void reset_resource(struct resource *res) | |||
| 121 | } | 125 | } |
| 122 | 126 | ||
| 123 | /** | 127 | /** |
| 124 | * adjust_resources_sorted() - satisfy any additional resource requests | 128 | * reassign_resources_sorted() - satisfy any additional resource requests |
| 125 | * | 129 | * |
| 126 | * @add_head : head of the list tracking requests requiring additional | 130 | * @realloc_head : head of the list tracking requests requiring additional |
| 127 | * resources | 131 | * resources |
| 128 | * @head : head of the list tracking requests with allocated | 132 | * @head : head of the list tracking requests with allocated |
| 129 | * resources | 133 | * resources |
| 130 | * | 134 | * |
| 131 | * Walk through each element of the add_head and try to procure | 135 | * Walk through each element of the realloc_head and try to procure |
| 132 | * additional resources for the element, provided the element | 136 | * additional resources for the element, provided the element |
| 133 | * is in the head list. | 137 | * is in the head list. |
| 134 | */ | 138 | */ |
| 135 | static void adjust_resources_sorted(struct resource_list_x *add_head, | 139 | static void reassign_resources_sorted(struct resource_list_x *realloc_head, |
| 136 | struct resource_list *head) | 140 | struct resource_list *head) |
| 137 | { | 141 | { |
| 138 | struct resource *res; | 142 | struct resource *res; |
| @@ -141,8 +145,8 @@ static void adjust_resources_sorted(struct resource_list_x *add_head, | |||
| 141 | resource_size_t add_size; | 145 | resource_size_t add_size; |
| 142 | int idx; | 146 | int idx; |
| 143 | 147 | ||
| 144 | prev = add_head; | 148 | prev = realloc_head; |
| 145 | for (list = add_head->next; list;) { | 149 | for (list = realloc_head->next; list;) { |
| 146 | res = list->res; | 150 | res = list->res; |
| 147 | /* skip resource that has been reset */ | 151 | /* skip resource that has been reset */ |
| 148 | if (!res->flags) | 152 | if (!res->flags) |
| @@ -159,13 +163,17 @@ static void adjust_resources_sorted(struct resource_list_x *add_head, | |||
| 159 | 163 | ||
| 160 | idx = res - &list->dev->resource[0]; | 164 | idx = res - &list->dev->resource[0]; |
| 161 | add_size=list->add_size; | 165 | add_size=list->add_size; |
| 162 | if (!resource_size(res) && add_size) { | 166 | if (!resource_size(res)) { |
| 163 | res->end = res->start + add_size - 1; | 167 | res->start = list->start; |
| 164 | if(pci_assign_resource(list->dev, idx)) | 168 | res->end = res->start + add_size - 1; |
| 169 | if(pci_assign_resource(list->dev, idx)) | ||
| 165 | reset_resource(res); | 170 | reset_resource(res); |
| 166 | } else if (add_size) { | 171 | } else { |
| 167 | adjust_resource(res, res->start, | 172 | resource_size_t align = list->min_align; |
| 168 | resource_size(res) + add_size); | 173 | res->flags |= list->flags & (IORESOURCE_STARTALIGN|IORESOURCE_SIZEALIGN); |
| 174 | if (pci_reassign_resource(list->dev, idx, add_size, align)) | ||
| 175 | dev_printk(KERN_DEBUG, &list->dev->dev, "failed to add optional resources res=%pR\n", | ||
| 176 | res); | ||
| 169 | } | 177 | } |
| 170 | out: | 178 | out: |
| 171 | tmp = list; | 179 | tmp = list; |
| @@ -210,16 +218,16 @@ static void assign_requested_resources_sorted(struct resource_list *head, | |||
| 210 | } | 218 | } |
| 211 | 219 | ||
| 212 | static void __assign_resources_sorted(struct resource_list *head, | 220 | static void __assign_resources_sorted(struct resource_list *head, |
| 213 | struct resource_list_x *add_head, | 221 | struct resource_list_x *realloc_head, |
| 214 | struct resource_list_x *fail_head) | 222 | struct resource_list_x *fail_head) |
| 215 | { | 223 | { |
| 216 | /* Satisfy the must-have resource requests */ | 224 | /* Satisfy the must-have resource requests */ |
| 217 | assign_requested_resources_sorted(head, fail_head); | 225 | assign_requested_resources_sorted(head, fail_head); |
| 218 | 226 | ||
| 219 | /* Try to satisfy any additional nice-to-have resource | 227 | /* Try to satisfy any additional optional resource |
| 220 | requests */ | 228 | requests */ |
| 221 | if (add_head) | 229 | if (realloc_head) |
| 222 | adjust_resources_sorted(add_head, head); | 230 | reassign_resources_sorted(realloc_head, head); |
| 223 | free_list(resource_list, head); | 231 | free_list(resource_list, head); |
| 224 | } | 232 | } |
| 225 | 233 | ||
| @@ -235,7 +243,7 @@ static void pdev_assign_resources_sorted(struct pci_dev *dev, | |||
| 235 | } | 243 | } |
| 236 | 244 | ||
| 237 | static void pbus_assign_resources_sorted(const struct pci_bus *bus, | 245 | static void pbus_assign_resources_sorted(const struct pci_bus *bus, |
| 238 | struct resource_list_x *add_head, | 246 | struct resource_list_x *realloc_head, |
| 239 | struct resource_list_x *fail_head) | 247 | struct resource_list_x *fail_head) |
| 240 | { | 248 | { |
| 241 | struct pci_dev *dev; | 249 | struct pci_dev *dev; |
| @@ -245,7 +253,7 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus, | |||
| 245 | list_for_each_entry(dev, &bus->devices, bus_list) | 253 | list_for_each_entry(dev, &bus->devices, bus_list) |
| 246 | __dev_sort_resources(dev, &head); | 254 | __dev_sort_resources(dev, &head); |
| 247 | 255 | ||
| 248 | __assign_resources_sorted(&head, add_head, fail_head); | 256 | __assign_resources_sorted(&head, realloc_head, fail_head); |
| 249 | } | 257 | } |
| 250 | 258 | ||
| 251 | void pci_setup_cardbus(struct pci_bus *bus) | 259 | void pci_setup_cardbus(struct pci_bus *bus) |
| @@ -540,13 +548,27 @@ static resource_size_t calculate_memsize(resource_size_t size, | |||
| 540 | return size; | 548 | return size; |
| 541 | } | 549 | } |
| 542 | 550 | ||
| 551 | static resource_size_t get_res_add_size(struct resource_list_x *realloc_head, | ||
| 552 | struct resource *res) | ||
| 553 | { | ||
| 554 | struct resource_list_x *list; | ||
| 555 | |||
| 556 | /* check if it is in realloc_head list */ | ||
| 557 | for (list = realloc_head->next; list && list->res != res; | ||
| 558 | list = list->next); | ||
| 559 | if (list) | ||
| 560 | return list->add_size; | ||
| 561 | |||
| 562 | return 0; | ||
| 563 | } | ||
| 564 | |||
| 543 | /** | 565 | /** |
| 544 | * pbus_size_io() - size the io window of a given bus | 566 | * pbus_size_io() - size the io window of a given bus |
| 545 | * | 567 | * |
| 546 | * @bus : the bus | 568 | * @bus : the bus |
| 547 | * @min_size : the minimum io window that must to be allocated | 569 | * @min_size : the minimum io window that must to be allocated |
| 548 | * @add_size : additional optional io window | 570 | * @add_size : additional optional io window |
| 549 | * @add_head : track the additional io window on this list | 571 | * @realloc_head : track the additional io window on this list |
| 550 | * | 572 | * |
| 551 | * Sizing the IO windows of the PCI-PCI bridge is trivial, | 573 | * Sizing the IO windows of the PCI-PCI bridge is trivial, |
| 552 | * since these windows have 4K granularity and the IO ranges | 574 | * since these windows have 4K granularity and the IO ranges |
| @@ -554,11 +576,12 @@ static resource_size_t calculate_memsize(resource_size_t size, | |||
| 554 | * We must be careful with the ISA aliasing though. | 576 | * We must be careful with the ISA aliasing though. |
| 555 | */ | 577 | */ |
| 556 | static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, | 578 | static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, |
| 557 | resource_size_t add_size, struct resource_list_x *add_head) | 579 | resource_size_t add_size, struct resource_list_x *realloc_head) |
| 558 | { | 580 | { |
| 559 | struct pci_dev *dev; | 581 | struct pci_dev *dev; |
| 560 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); | 582 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); |
| 561 | unsigned long size = 0, size0 = 0, size1 = 0; | 583 | unsigned long size = 0, size0 = 0, size1 = 0; |
| 584 | resource_size_t children_add_size = 0; | ||
| 562 | 585 | ||
| 563 | if (!b_res) | 586 | if (!b_res) |
| 564 | return; | 587 | return; |
| @@ -579,11 +602,16 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, | |||
| 579 | size += r_size; | 602 | size += r_size; |
| 580 | else | 603 | else |
| 581 | size1 += r_size; | 604 | size1 += r_size; |
| 605 | |||
| 606 | if (realloc_head) | ||
| 607 | children_add_size += get_res_add_size(realloc_head, r); | ||
| 582 | } | 608 | } |
| 583 | } | 609 | } |
| 584 | size0 = calculate_iosize(size, min_size, size1, | 610 | size0 = calculate_iosize(size, min_size, size1, |
| 585 | resource_size(b_res), 4096); | 611 | resource_size(b_res), 4096); |
| 586 | size1 = (!add_head || (add_head && !add_size)) ? size0 : | 612 | if (children_add_size > add_size) |
| 613 | add_size = children_add_size; | ||
| 614 | size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 : | ||
| 587 | calculate_iosize(size, min_size+add_size, size1, | 615 | calculate_iosize(size, min_size+add_size, size1, |
| 588 | resource_size(b_res), 4096); | 616 | resource_size(b_res), 4096); |
| 589 | if (!size0 && !size1) { | 617 | if (!size0 && !size1) { |
| @@ -598,8 +626,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, | |||
| 598 | b_res->start = 4096; | 626 | b_res->start = 4096; |
| 599 | b_res->end = b_res->start + size0 - 1; | 627 | b_res->end = b_res->start + size0 - 1; |
| 600 | b_res->flags |= IORESOURCE_STARTALIGN; | 628 | b_res->flags |= IORESOURCE_STARTALIGN; |
| 601 | if (size1 > size0 && add_head) | 629 | if (size1 > size0 && realloc_head) |
| 602 | add_to_list(add_head, bus->self, b_res, size1-size0); | 630 | add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096); |
| 603 | } | 631 | } |
| 604 | 632 | ||
| 605 | /** | 633 | /** |
| @@ -608,7 +636,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, | |||
| 608 | * @bus : the bus | 636 | * @bus : the bus |
| 609 | * @min_size : the minimum memory window that must to be allocated | 637 | * @min_size : the minimum memory window that must to be allocated |
| 610 | * @add_size : additional optional memory window | 638 | * @add_size : additional optional memory window |
| 611 | * @add_head : track the additional memory window on this list | 639 | * @realloc_head : track the additional memory window on this list |
| 612 | * | 640 | * |
| 613 | * Calculate the size of the bus and minimal alignment which | 641 | * Calculate the size of the bus and minimal alignment which |
| 614 | * guarantees that all child resources fit in this size. | 642 | * guarantees that all child resources fit in this size. |
| @@ -616,7 +644,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, | |||
| 616 | static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | 644 | static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, |
| 617 | unsigned long type, resource_size_t min_size, | 645 | unsigned long type, resource_size_t min_size, |
| 618 | resource_size_t add_size, | 646 | resource_size_t add_size, |
| 619 | struct resource_list_x *add_head) | 647 | struct resource_list_x *realloc_head) |
| 620 | { | 648 | { |
| 621 | struct pci_dev *dev; | 649 | struct pci_dev *dev; |
| 622 | resource_size_t min_align, align, size, size0, size1; | 650 | resource_size_t min_align, align, size, size0, size1; |
| @@ -624,6 +652,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
| 624 | int order, max_order; | 652 | int order, max_order; |
| 625 | struct resource *b_res = find_free_bus_resource(bus, type); | 653 | struct resource *b_res = find_free_bus_resource(bus, type); |
| 626 | unsigned int mem64_mask = 0; | 654 | unsigned int mem64_mask = 0; |
| 655 | resource_size_t children_add_size = 0; | ||
| 627 | 656 | ||
| 628 | if (!b_res) | 657 | if (!b_res) |
| 629 | return 0; | 658 | return 0; |
| @@ -645,6 +674,16 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
| 645 | if (r->parent || (r->flags & mask) != type) | 674 | if (r->parent || (r->flags & mask) != type) |
| 646 | continue; | 675 | continue; |
| 647 | r_size = resource_size(r); | 676 | r_size = resource_size(r); |
| 677 | #ifdef CONFIG_PCI_IOV | ||
| 678 | /* put SRIOV requested res to the optional list */ | ||
| 679 | if (realloc_head && i >= PCI_IOV_RESOURCES && | ||
| 680 | i <= PCI_IOV_RESOURCE_END) { | ||
| 681 | r->end = r->start - 1; | ||
| 682 | add_to_list(realloc_head, dev, r, r_size, 0/* dont' care */); | ||
| 683 | children_add_size += r_size; | ||
| 684 | continue; | ||
| 685 | } | ||
| 686 | #endif | ||
| 648 | /* For bridges size != alignment */ | 687 | /* For bridges size != alignment */ |
| 649 | align = pci_resource_alignment(dev, r); | 688 | align = pci_resource_alignment(dev, r); |
| 650 | order = __ffs(align) - 20; | 689 | order = __ffs(align) - 20; |
| @@ -665,6 +704,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
| 665 | if (order > max_order) | 704 | if (order > max_order) |
| 666 | max_order = order; | 705 | max_order = order; |
| 667 | mem64_mask &= r->flags & IORESOURCE_MEM_64; | 706 | mem64_mask &= r->flags & IORESOURCE_MEM_64; |
| 707 | |||
| 708 | if (realloc_head) | ||
| 709 | children_add_size += get_res_add_size(realloc_head, r); | ||
| 668 | } | 710 | } |
| 669 | } | 711 | } |
| 670 | align = 0; | 712 | align = 0; |
| @@ -681,7 +723,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
| 681 | align += aligns[order]; | 723 | align += aligns[order]; |
| 682 | } | 724 | } |
| 683 | size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align); | 725 | size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align); |
| 684 | size1 = (!add_head || (add_head && !add_size)) ? size0 : | 726 | if (children_add_size > add_size) |
| 727 | add_size = children_add_size; | ||
| 728 | size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 : | ||
| 685 | calculate_memsize(size, min_size+add_size, 0, | 729 | calculate_memsize(size, min_size+add_size, 0, |
| 686 | resource_size(b_res), min_align); | 730 | resource_size(b_res), min_align); |
| 687 | if (!size0 && !size1) { | 731 | if (!size0 && !size1) { |
| @@ -695,12 +739,22 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
| 695 | b_res->start = min_align; | 739 | b_res->start = min_align; |
| 696 | b_res->end = size0 + min_align - 1; | 740 | b_res->end = size0 + min_align - 1; |
| 697 | b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask; | 741 | b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask; |
| 698 | if (size1 > size0 && add_head) | 742 | if (size1 > size0 && realloc_head) |
| 699 | add_to_list(add_head, bus->self, b_res, size1-size0); | 743 | add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align); |
| 700 | return 1; | 744 | return 1; |
| 701 | } | 745 | } |
| 702 | 746 | ||
| 703 | static void pci_bus_size_cardbus(struct pci_bus *bus) | 747 | unsigned long pci_cardbus_resource_alignment(struct resource *res) |
| 748 | { | ||
| 749 | if (res->flags & IORESOURCE_IO) | ||
| 750 | return pci_cardbus_io_size; | ||
| 751 | if (res->flags & IORESOURCE_MEM) | ||
| 752 | return pci_cardbus_mem_size; | ||
| 753 | return 0; | ||
| 754 | } | ||
| 755 | |||
| 756 | static void pci_bus_size_cardbus(struct pci_bus *bus, | ||
| 757 | struct resource_list_x *realloc_head) | ||
| 704 | { | 758 | { |
| 705 | struct pci_dev *bridge = bus->self; | 759 | struct pci_dev *bridge = bus->self; |
| 706 | struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES]; | 760 | struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES]; |
| @@ -711,12 +765,14 @@ static void pci_bus_size_cardbus(struct pci_bus *bus) | |||
| 711 | * a fixed amount of bus space for CardBus bridges. | 765 | * a fixed amount of bus space for CardBus bridges. |
| 712 | */ | 766 | */ |
| 713 | b_res[0].start = 0; | 767 | b_res[0].start = 0; |
| 714 | b_res[0].end = pci_cardbus_io_size - 1; | ||
| 715 | b_res[0].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN; | 768 | b_res[0].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN; |
| 769 | if (realloc_head) | ||
| 770 | add_to_list(realloc_head, bridge, b_res, pci_cardbus_io_size, 0 /* dont care */); | ||
| 716 | 771 | ||
| 717 | b_res[1].start = 0; | 772 | b_res[1].start = 0; |
| 718 | b_res[1].end = pci_cardbus_io_size - 1; | ||
| 719 | b_res[1].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN; | 773 | b_res[1].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN; |
| 774 | if (realloc_head) | ||
| 775 | add_to_list(realloc_head, bridge, b_res+1, pci_cardbus_io_size, 0 /* dont care */); | ||
| 720 | 776 | ||
| 721 | /* | 777 | /* |
| 722 | * Check whether prefetchable memory is supported | 778 | * Check whether prefetchable memory is supported |
| @@ -736,21 +792,31 @@ static void pci_bus_size_cardbus(struct pci_bus *bus) | |||
| 736 | */ | 792 | */ |
| 737 | if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) { | 793 | if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) { |
| 738 | b_res[2].start = 0; | 794 | b_res[2].start = 0; |
| 739 | b_res[2].end = pci_cardbus_mem_size - 1; | ||
| 740 | b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_SIZEALIGN; | 795 | b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_SIZEALIGN; |
| 796 | if (realloc_head) | ||
| 797 | add_to_list(realloc_head, bridge, b_res+2, pci_cardbus_mem_size, 0 /* dont care */); | ||
| 741 | 798 | ||
| 742 | b_res[3].start = 0; | 799 | b_res[3].start = 0; |
| 743 | b_res[3].end = pci_cardbus_mem_size - 1; | ||
| 744 | b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN; | 800 | b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN; |
| 801 | if (realloc_head) | ||
| 802 | add_to_list(realloc_head, bridge, b_res+3, pci_cardbus_mem_size, 0 /* dont care */); | ||
| 745 | } else { | 803 | } else { |
| 746 | b_res[3].start = 0; | 804 | b_res[3].start = 0; |
| 747 | b_res[3].end = pci_cardbus_mem_size * 2 - 1; | ||
| 748 | b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN; | 805 | b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN; |
| 806 | if (realloc_head) | ||
| 807 | add_to_list(realloc_head, bridge, b_res+3, pci_cardbus_mem_size * 2, 0 /* dont care */); | ||
| 749 | } | 808 | } |
| 809 | |||
| 810 | /* set the size of the resource to zero, so that the resource does not | ||
| 811 | * get assigned during required-resource allocation cycle but gets assigned | ||
| 812 | * during the optional-resource allocation cycle. | ||
| 813 | */ | ||
| 814 | b_res[0].start = b_res[1].start = b_res[2].start = b_res[3].start = 1; | ||
| 815 | b_res[0].end = b_res[1].end = b_res[2].end = b_res[3].end = 0; | ||
| 750 | } | 816 | } |
| 751 | 817 | ||
| 752 | void __ref __pci_bus_size_bridges(struct pci_bus *bus, | 818 | void __ref __pci_bus_size_bridges(struct pci_bus *bus, |
| 753 | struct resource_list_x *add_head) | 819 | struct resource_list_x *realloc_head) |
| 754 | { | 820 | { |
| 755 | struct pci_dev *dev; | 821 | struct pci_dev *dev; |
| 756 | unsigned long mask, prefmask; | 822 | unsigned long mask, prefmask; |
| @@ -763,12 +829,12 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus, | |||
| 763 | 829 | ||
| 764 | switch (dev->class >> 8) { | 830 | switch (dev->class >> 8) { |
| 765 | case PCI_CLASS_BRIDGE_CARDBUS: | 831 | case PCI_CLASS_BRIDGE_CARDBUS: |
| 766 | pci_bus_size_cardbus(b); | 832 | pci_bus_size_cardbus(b, realloc_head); |
| 767 | break; | 833 | break; |
| 768 | 834 | ||
| 769 | case PCI_CLASS_BRIDGE_PCI: | 835 | case PCI_CLASS_BRIDGE_PCI: |
| 770 | default: | 836 | default: |
| 771 | __pci_bus_size_bridges(b, add_head); | 837 | __pci_bus_size_bridges(b, realloc_head); |
| 772 | break; | 838 | break; |
| 773 | } | 839 | } |
| 774 | } | 840 | } |
| @@ -792,7 +858,7 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus, | |||
| 792 | * Follow thru | 858 | * Follow thru |
| 793 | */ | 859 | */ |
| 794 | default: | 860 | default: |
| 795 | pbus_size_io(bus, 0, additional_io_size, add_head); | 861 | pbus_size_io(bus, 0, additional_io_size, realloc_head); |
| 796 | /* If the bridge supports prefetchable range, size it | 862 | /* If the bridge supports prefetchable range, size it |
| 797 | separately. If it doesn't, or its prefetchable window | 863 | separately. If it doesn't, or its prefetchable window |
| 798 | has already been allocated by arch code, try | 864 | has already been allocated by arch code, try |
| @@ -800,11 +866,11 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus, | |||
| 800 | resources. */ | 866 | resources. */ |
| 801 | mask = IORESOURCE_MEM; | 867 | mask = IORESOURCE_MEM; |
| 802 | prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; | 868 | prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; |
| 803 | if (pbus_size_mem(bus, prefmask, prefmask, 0, additional_mem_size, add_head)) | 869 | if (pbus_size_mem(bus, prefmask, prefmask, 0, additional_mem_size, realloc_head)) |
| 804 | mask = prefmask; /* Success, size non-prefetch only. */ | 870 | mask = prefmask; /* Success, size non-prefetch only. */ |
| 805 | else | 871 | else |
| 806 | additional_mem_size += additional_mem_size; | 872 | additional_mem_size += additional_mem_size; |
| 807 | pbus_size_mem(bus, mask, IORESOURCE_MEM, 0, additional_mem_size, add_head); | 873 | pbus_size_mem(bus, mask, IORESOURCE_MEM, 0, additional_mem_size, realloc_head); |
| 808 | break; | 874 | break; |
| 809 | } | 875 | } |
| 810 | } | 876 | } |
| @@ -816,20 +882,20 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus) | |||
| 816 | EXPORT_SYMBOL(pci_bus_size_bridges); | 882 | EXPORT_SYMBOL(pci_bus_size_bridges); |
| 817 | 883 | ||
| 818 | static void __ref __pci_bus_assign_resources(const struct pci_bus *bus, | 884 | static void __ref __pci_bus_assign_resources(const struct pci_bus *bus, |
| 819 | struct resource_list_x *add_head, | 885 | struct resource_list_x *realloc_head, |
| 820 | struct resource_list_x *fail_head) | 886 | struct resource_list_x *fail_head) |
| 821 | { | 887 | { |
| 822 | struct pci_bus *b; | 888 | struct pci_bus *b; |
| 823 | struct pci_dev *dev; | 889 | struct pci_dev *dev; |
| 824 | 890 | ||
| 825 | pbus_assign_resources_sorted(bus, add_head, fail_head); | 891 | pbus_assign_resources_sorted(bus, realloc_head, fail_head); |
| 826 | 892 | ||
| 827 | list_for_each_entry(dev, &bus->devices, bus_list) { | 893 | list_for_each_entry(dev, &bus->devices, bus_list) { |
| 828 | b = dev->subordinate; | 894 | b = dev->subordinate; |
| 829 | if (!b) | 895 | if (!b) |
| 830 | continue; | 896 | continue; |
| 831 | 897 | ||
| 832 | __pci_bus_assign_resources(b, add_head, fail_head); | 898 | __pci_bus_assign_resources(b, realloc_head, fail_head); |
| 833 | 899 | ||
| 834 | switch (dev->class >> 8) { | 900 | switch (dev->class >> 8) { |
| 835 | case PCI_CLASS_BRIDGE_PCI: | 901 | case PCI_CLASS_BRIDGE_PCI: |
| @@ -1039,7 +1105,7 @@ void __init | |||
| 1039 | pci_assign_unassigned_resources(void) | 1105 | pci_assign_unassigned_resources(void) |
| 1040 | { | 1106 | { |
| 1041 | struct pci_bus *bus; | 1107 | struct pci_bus *bus; |
| 1042 | struct resource_list_x add_list; /* list of resources that | 1108 | struct resource_list_x realloc_list; /* list of resources that |
| 1043 | want additional resources */ | 1109 | want additional resources */ |
| 1044 | int tried_times = 0; | 1110 | int tried_times = 0; |
| 1045 | enum release_type rel_type = leaf_only; | 1111 | enum release_type rel_type = leaf_only; |
| @@ -1052,7 +1118,7 @@ pci_assign_unassigned_resources(void) | |||
| 1052 | 1118 | ||
| 1053 | 1119 | ||
| 1054 | head.next = NULL; | 1120 | head.next = NULL; |
| 1055 | add_list.next = NULL; | 1121 | realloc_list.next = NULL; |
| 1056 | 1122 | ||
| 1057 | pci_try_num = max_depth + 1; | 1123 | pci_try_num = max_depth + 1; |
| 1058 | printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n", | 1124 | printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n", |
| @@ -1062,12 +1128,12 @@ again: | |||
| 1062 | /* Depth first, calculate sizes and alignments of all | 1128 | /* Depth first, calculate sizes and alignments of all |
| 1063 | subordinate buses. */ | 1129 | subordinate buses. */ |
| 1064 | list_for_each_entry(bus, &pci_root_buses, node) | 1130 | list_for_each_entry(bus, &pci_root_buses, node) |
| 1065 | __pci_bus_size_bridges(bus, &add_list); | 1131 | __pci_bus_size_bridges(bus, &realloc_list); |
| 1066 | 1132 | ||
| 1067 | /* Depth last, allocate resources and update the hardware. */ | 1133 | /* Depth last, allocate resources and update the hardware. */ |
| 1068 | list_for_each_entry(bus, &pci_root_buses, node) | 1134 | list_for_each_entry(bus, &pci_root_buses, node) |
| 1069 | __pci_bus_assign_resources(bus, &add_list, &head); | 1135 | __pci_bus_assign_resources(bus, &realloc_list, &head); |
| 1070 | BUG_ON(add_list.next); | 1136 | BUG_ON(realloc_list.next); |
| 1071 | tried_times++; | 1137 | tried_times++; |
| 1072 | 1138 | ||
| 1073 | /* any device complain? */ | 1139 | /* any device complain? */ |
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 319f359906e8..51a9095c7da4 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c | |||
| @@ -128,16 +128,16 @@ void pci_disable_bridge_window(struct pci_dev *dev) | |||
| 128 | } | 128 | } |
| 129 | #endif /* CONFIG_PCI_QUIRKS */ | 129 | #endif /* CONFIG_PCI_QUIRKS */ |
| 130 | 130 | ||
| 131 | |||
| 132 | |||
| 131 | static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, | 133 | static 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 | { | 135 | { |
| 134 | struct resource *res = dev->resource + resno; | 136 | struct resource *res = dev->resource + resno; |
| 135 | resource_size_t size, min, align; | 137 | resource_size_t min; |
| 136 | int ret; | 138 | int ret; |
| 137 | 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 | 141 | ||
| 142 | /* First, try exact prefetching match.. */ | 142 | /* First, try exact prefetching match.. */ |
| 143 | ret = pci_bus_alloc_resource(bus, res, size, align, min, | 143 | ret = pci_bus_alloc_resource(bus, res, size, align, min, |
| @@ -154,56 +154,101 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, | |||
| 154 | ret = pci_bus_alloc_resource(bus, res, size, align, min, 0, | 154 | ret = pci_bus_alloc_resource(bus, res, size, align, min, 0, |
| 155 | pcibios_align_resource, dev); | 155 | pcibios_align_resource, dev); |
| 156 | } | 156 | } |
| 157 | return ret; | ||
| 158 | } | ||
| 157 | 159 | ||
| 158 | if (ret < 0 && dev->fw_addr[resno]) { | 160 | static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev, |
| 159 | struct resource *root, *conflict; | 161 | int resno, resource_size_t size) |
| 160 | resource_size_t start, end; | 162 | { |
| 163 | struct resource *root, *conflict; | ||
| 164 | resource_size_t start, end; | ||
| 165 | int ret = 0; | ||
| 161 | 166 | ||
| 162 | /* | 167 | if (res->flags & IORESOURCE_IO) |
| 163 | * If we failed to assign anything, let's try the address | 168 | root = &ioport_resource; |
| 164 | * where firmware left it. That at least has a chance of | 169 | else |
| 165 | * working, which is better than just leaving it disabled. | 170 | root = &iomem_resource; |
| 166 | */ | 171 | |
| 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 | |||
| 190 | static 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; | ||
| 167 | 196 | ||
| 168 | if (res->flags & IORESOURCE_IO) | 197 | bus = dev->bus; |
| 169 | root = &ioport_resource; | 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"; |
| 172 | 214 | dev_info(&dev->dev, | |
| 173 | start = res->start; | 215 | "BAR %d: can't assign %s (size %#llx)\n", |
| 174 | end = res->end; | 216 | resno, type, (unsigned long long) resource_size(res)); |
| 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; | ||
| 188 | } | 217 | } |
| 189 | 218 | ||
| 219 | return ret; | ||
| 220 | } | ||
| 221 | |||
| 222 | int 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; | ||
| 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) { | 237 | if (!ret) { |
| 191 | res->flags &= ~IORESOURCE_STARTALIGN; | 238 | res->flags &= ~IORESOURCE_STARTALIGN; |
| 192 | dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res); | 239 | dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res); |
| 193 | if (resno < PCI_BRIDGE_RESOURCES) | 240 | if (resno < PCI_BRIDGE_RESOURCES) |
| 194 | pci_update_resource(dev, resno); | 241 | pci_update_resource(dev, resno); |
| 195 | } | 242 | } |
| 196 | |||
| 197 | return ret; | 243 | return ret; |
| 198 | } | 244 | } |
| 199 | 245 | ||
| 200 | int pci_assign_resource(struct pci_dev *dev, int resno) | 246 | int pci_assign_resource(struct pci_dev *dev, int resno) |
| 201 | { | 247 | { |
| 202 | struct resource *res = dev->resource + resno; | 248 | struct resource *res = dev->resource + resno; |
| 203 | resource_size_t align; | 249 | resource_size_t align, size; |
| 204 | struct pci_bus *bus; | 250 | struct pci_bus *bus; |
| 205 | int ret; | 251 | int ret; |
| 206 | char *type; | ||
| 207 | 252 | ||
| 208 | align = pci_resource_alignment(dev, res); | 253 | align = pci_resource_alignment(dev, res); |
| 209 | if (!align) { | 254 | if (!align) { |
| @@ -213,34 +258,27 @@ int pci_assign_resource(struct pci_dev *dev, int resno) | |||
| 213 | } | 258 | } |
| 214 | 259 | ||
| 215 | bus = dev->bus; | 260 | bus = dev->bus; |
| 216 | while ((ret = __pci_assign_resource(bus, dev, resno))) { | 261 | size = resource_size(res); |
| 217 | if (bus->parent && bus->self->transparent) | 262 | ret = _pci_assign_resource(dev, resno, size, align); |
| 218 | bus = bus->parent; | ||
| 219 | else | ||
| 220 | bus = NULL; | ||
| 221 | if (bus) | ||
| 222 | continue; | ||
| 223 | break; | ||
| 224 | } | ||
| 225 | 263 | ||
| 226 | if (ret) { | 264 | /* |
| 227 | if (res->flags & IORESOURCE_MEM) | 265 | * If we failed to assign anything, let's try the address |
| 228 | if (res->flags & IORESOURCE_PREFETCH) | 266 | * where firmware left it. That at least has a chance of |
| 229 | type = "mem pref"; | 267 | * working, which is better than just leaving it disabled. |
| 230 | else | 268 | */ |
| 231 | type = "mem"; | 269 | if (ret < 0 && dev->fw_addr[resno]) |
| 232 | else if (res->flags & IORESOURCE_IO) | 270 | ret = pci_revert_fw_address(res, dev, resno, size); |
| 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 | } | ||
| 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; | 278 | return ret; |
| 242 | } | 279 | } |
| 243 | 280 | ||
| 281 | |||
| 244 | /* Sort resources by alignment */ | 282 | /* Sort resources by alignment */ |
| 245 | void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) | 283 | void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) |
| 246 | { | 284 | { |
diff --git a/include/linux/pci.h b/include/linux/pci.h index f27893b3b724..8c230cbcbb48 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
| @@ -251,7 +251,8 @@ struct pci_dev { | |||
| 251 | u8 revision; /* PCI revision, low byte of class word */ | 251 | u8 revision; /* PCI revision, low byte of class word */ |
| 252 | u8 hdr_type; /* PCI header type (`multi' flag masked out) */ | 252 | u8 hdr_type; /* PCI header type (`multi' flag masked out) */ |
| 253 | u8 pcie_cap; /* PCI-E capability offset */ | 253 | u8 pcie_cap; /* PCI-E capability offset */ |
| 254 | u8 pcie_type; /* PCI-E device/port type */ | 254 | u8 pcie_type:4; /* PCI-E device/port type */ |
| 255 | u8 pcie_mpss:3; /* PCI-E Max Payload Size Supported */ | ||
| 255 | u8 rom_base_reg; /* which config register controls the ROM */ | 256 | u8 rom_base_reg; /* which config register controls the ROM */ |
| 256 | u8 pin; /* which interrupt pin this device uses */ | 257 | u8 pin; /* which interrupt pin this device uses */ |
| 257 | 258 | ||
| @@ -617,6 +618,16 @@ struct pci_driver { | |||
| 617 | /* these external functions are only available when PCI support is enabled */ | 618 | /* these external functions are only available when PCI support is enabled */ |
| 618 | #ifdef CONFIG_PCI | 619 | #ifdef CONFIG_PCI |
| 619 | 620 | ||
| 621 | extern void pcie_bus_configure_settings(struct pci_bus *bus, u8 smpss); | ||
| 622 | |||
| 623 | enum pcie_bus_config_types { | ||
| 624 | PCIE_BUS_PERFORMANCE, | ||
| 625 | PCIE_BUS_SAFE, | ||
| 626 | PCIE_BUS_PEER2PEER, | ||
| 627 | }; | ||
| 628 | |||
| 629 | extern enum pcie_bus_config_types pcie_bus_config; | ||
| 630 | |||
| 620 | extern struct bus_type pci_bus_type; | 631 | extern struct bus_type pci_bus_type; |
| 621 | 632 | ||
| 622 | /* Do NOT directly access these two variables, unless you are arch specific pci | 633 | /* Do NOT directly access these two variables, unless you are arch specific pci |
| @@ -796,10 +807,13 @@ int pcix_get_mmrbc(struct pci_dev *dev); | |||
| 796 | int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc); | 807 | int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc); |
| 797 | int pcie_get_readrq(struct pci_dev *dev); | 808 | int pcie_get_readrq(struct pci_dev *dev); |
| 798 | int pcie_set_readrq(struct pci_dev *dev, int rq); | 809 | int pcie_set_readrq(struct pci_dev *dev, int rq); |
| 810 | int pcie_get_mps(struct pci_dev *dev); | ||
| 811 | int pcie_set_mps(struct pci_dev *dev, int mps); | ||
| 799 | int __pci_reset_function(struct pci_dev *dev); | 812 | int __pci_reset_function(struct pci_dev *dev); |
| 800 | int pci_reset_function(struct pci_dev *dev); | 813 | int pci_reset_function(struct pci_dev *dev); |
| 801 | void pci_update_resource(struct pci_dev *dev, int resno); | 814 | void pci_update_resource(struct pci_dev *dev, int resno); |
| 802 | int __must_check pci_assign_resource(struct pci_dev *dev, int i); | 815 | int __must_check pci_assign_resource(struct pci_dev *dev, int i); |
| 816 | int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align); | ||
| 803 | int pci_select_bars(struct pci_dev *dev, unsigned long flags); | 817 | int pci_select_bars(struct pci_dev *dev, unsigned long flags); |
| 804 | 818 | ||
| 805 | /* ROM control related routines */ | 819 | /* ROM control related routines */ |
