diff options
Diffstat (limited to 'drivers/pci/pci-sysfs.c')
| -rw-r--r-- | drivers/pci/pci-sysfs.c | 196 |
1 files changed, 144 insertions, 52 deletions
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 02d107b15281..9c6e9bb674ec 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
| @@ -284,7 +284,6 @@ msi_bus_store(struct device *dev, struct device_attribute *attr, | |||
| 284 | return count; | 284 | return count; |
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | #ifdef CONFIG_HOTPLUG | ||
| 288 | static DEFINE_MUTEX(pci_remove_rescan_mutex); | 287 | static DEFINE_MUTEX(pci_remove_rescan_mutex); |
| 289 | static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf, | 288 | static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf, |
| 290 | size_t count) | 289 | size_t count) |
| @@ -377,8 +376,6 @@ dev_bus_rescan_store(struct device *dev, struct device_attribute *attr, | |||
| 377 | return count; | 376 | return count; |
| 378 | } | 377 | } |
| 379 | 378 | ||
| 380 | #endif | ||
| 381 | |||
| 382 | #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI) | 379 | #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI) |
| 383 | static ssize_t d3cold_allowed_store(struct device *dev, | 380 | static ssize_t d3cold_allowed_store(struct device *dev, |
| 384 | struct device_attribute *attr, | 381 | struct device_attribute *attr, |
| @@ -404,6 +401,89 @@ static ssize_t d3cold_allowed_show(struct device *dev, | |||
| 404 | } | 401 | } |
| 405 | #endif | 402 | #endif |
| 406 | 403 | ||
| 404 | #ifdef CONFIG_PCI_IOV | ||
| 405 | static ssize_t sriov_totalvfs_show(struct device *dev, | ||
| 406 | struct device_attribute *attr, | ||
| 407 | char *buf) | ||
| 408 | { | ||
| 409 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 410 | |||
| 411 | return sprintf(buf, "%u\n", pci_sriov_get_totalvfs(pdev)); | ||
| 412 | } | ||
| 413 | |||
| 414 | |||
| 415 | static ssize_t sriov_numvfs_show(struct device *dev, | ||
| 416 | struct device_attribute *attr, | ||
| 417 | char *buf) | ||
| 418 | { | ||
| 419 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 420 | |||
| 421 | return sprintf(buf, "%u\n", pdev->sriov->num_VFs); | ||
| 422 | } | ||
| 423 | |||
| 424 | /* | ||
| 425 | * num_vfs > 0; number of VFs to enable | ||
| 426 | * num_vfs = 0; disable all VFs | ||
| 427 | * | ||
| 428 | * Note: SRIOV spec doesn't allow partial VF | ||
| 429 | * disable, so it's all or none. | ||
| 430 | */ | ||
| 431 | static ssize_t sriov_numvfs_store(struct device *dev, | ||
| 432 | struct device_attribute *attr, | ||
| 433 | const char *buf, size_t count) | ||
| 434 | { | ||
| 435 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 436 | int ret; | ||
| 437 | u16 num_vfs; | ||
| 438 | |||
| 439 | ret = kstrtou16(buf, 0, &num_vfs); | ||
| 440 | if (ret < 0) | ||
| 441 | return ret; | ||
| 442 | |||
| 443 | if (num_vfs > pci_sriov_get_totalvfs(pdev)) | ||
| 444 | return -ERANGE; | ||
| 445 | |||
| 446 | if (num_vfs == pdev->sriov->num_VFs) | ||
| 447 | return count; /* no change */ | ||
| 448 | |||
| 449 | /* is PF driver loaded w/callback */ | ||
| 450 | if (!pdev->driver || !pdev->driver->sriov_configure) { | ||
| 451 | dev_info(&pdev->dev, "Driver doesn't support SRIOV configuration via sysfs\n"); | ||
| 452 | return -ENOSYS; | ||
| 453 | } | ||
| 454 | |||
| 455 | if (num_vfs == 0) { | ||
| 456 | /* disable VFs */ | ||
| 457 | ret = pdev->driver->sriov_configure(pdev, 0); | ||
| 458 | if (ret < 0) | ||
| 459 | return ret; | ||
| 460 | return count; | ||
| 461 | } | ||
| 462 | |||
| 463 | /* enable VFs */ | ||
| 464 | if (pdev->sriov->num_VFs) { | ||
| 465 | dev_warn(&pdev->dev, "%d VFs already enabled. Disable before enabling %d VFs\n", | ||
| 466 | pdev->sriov->num_VFs, num_vfs); | ||
| 467 | return -EBUSY; | ||
| 468 | } | ||
| 469 | |||
| 470 | ret = pdev->driver->sriov_configure(pdev, num_vfs); | ||
| 471 | if (ret < 0) | ||
| 472 | return ret; | ||
| 473 | |||
| 474 | if (ret != num_vfs) | ||
| 475 | dev_warn(&pdev->dev, "%d VFs requested; only %d enabled\n", | ||
| 476 | num_vfs, ret); | ||
| 477 | |||
| 478 | return count; | ||
| 479 | } | ||
| 480 | |||
| 481 | static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs); | ||
| 482 | static struct device_attribute sriov_numvfs_attr = | ||
| 483 | __ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP), | ||
| 484 | sriov_numvfs_show, sriov_numvfs_store); | ||
| 485 | #endif /* CONFIG_PCI_IOV */ | ||
| 486 | |||
| 407 | struct device_attribute pci_dev_attrs[] = { | 487 | struct device_attribute pci_dev_attrs[] = { |
| 408 | __ATTR_RO(resource), | 488 | __ATTR_RO(resource), |
| 409 | __ATTR_RO(vendor), | 489 | __ATTR_RO(vendor), |
| @@ -424,10 +504,8 @@ struct device_attribute pci_dev_attrs[] = { | |||
| 424 | __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR), | 504 | __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR), |
| 425 | broken_parity_status_show,broken_parity_status_store), | 505 | broken_parity_status_show,broken_parity_status_store), |
| 426 | __ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store), | 506 | __ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store), |
| 427 | #ifdef CONFIG_HOTPLUG | ||
| 428 | __ATTR(remove, (S_IWUSR|S_IWGRP), NULL, remove_store), | 507 | __ATTR(remove, (S_IWUSR|S_IWGRP), NULL, remove_store), |
| 429 | __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_rescan_store), | 508 | __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_rescan_store), |
| 430 | #endif | ||
| 431 | #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI) | 509 | #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI) |
| 432 | __ATTR(d3cold_allowed, 0644, d3cold_allowed_show, d3cold_allowed_store), | 510 | __ATTR(d3cold_allowed, 0644, d3cold_allowed_show, d3cold_allowed_store), |
| 433 | #endif | 511 | #endif |
| @@ -435,9 +513,7 @@ struct device_attribute pci_dev_attrs[] = { | |||
| 435 | }; | 513 | }; |
| 436 | 514 | ||
| 437 | struct device_attribute pcibus_dev_attrs[] = { | 515 | struct device_attribute pcibus_dev_attrs[] = { |
| 438 | #ifdef CONFIG_HOTPLUG | ||
| 439 | __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store), | 516 | __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store), |
| 440 | #endif | ||
| 441 | __ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpumaskaffinity, NULL), | 517 | __ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpumaskaffinity, NULL), |
| 442 | __ATTR(cpulistaffinity, S_IRUGO, pci_bus_show_cpulistaffinity, NULL), | 518 | __ATTR(cpulistaffinity, S_IRUGO, pci_bus_show_cpulistaffinity, NULL), |
| 443 | __ATTR_NULL, | 519 | __ATTR_NULL, |
| @@ -458,40 +534,6 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf) | |||
| 458 | } | 534 | } |
| 459 | struct device_attribute vga_attr = __ATTR_RO(boot_vga); | 535 | struct device_attribute vga_attr = __ATTR_RO(boot_vga); |
| 460 | 536 | ||
| 461 | static void | ||
| 462 | pci_config_pm_runtime_get(struct pci_dev *pdev) | ||
| 463 | { | ||
| 464 | struct device *dev = &pdev->dev; | ||
| 465 | struct device *parent = dev->parent; | ||
| 466 | |||
| 467 | if (parent) | ||
| 468 | pm_runtime_get_sync(parent); | ||
| 469 | pm_runtime_get_noresume(dev); | ||
| 470 | /* | ||
| 471 | * pdev->current_state is set to PCI_D3cold during suspending, | ||
| 472 | * so wait until suspending completes | ||
| 473 | */ | ||
| 474 | pm_runtime_barrier(dev); | ||
| 475 | /* | ||
| 476 | * Only need to resume devices in D3cold, because config | ||
| 477 | * registers are still accessible for devices suspended but | ||
| 478 | * not in D3cold. | ||
| 479 | */ | ||
| 480 | if (pdev->current_state == PCI_D3cold) | ||
| 481 | pm_runtime_resume(dev); | ||
| 482 | } | ||
| 483 | |||
| 484 | static void | ||
| 485 | pci_config_pm_runtime_put(struct pci_dev *pdev) | ||
| 486 | { | ||
| 487 | struct device *dev = &pdev->dev; | ||
| 488 | struct device *parent = dev->parent; | ||
| 489 | |||
| 490 | pm_runtime_put(dev); | ||
| 491 | if (parent) | ||
| 492 | pm_runtime_put_sync(parent); | ||
| 493 | } | ||
| 494 | |||
| 495 | static ssize_t | 537 | static ssize_t |
| 496 | pci_read_config(struct file *filp, struct kobject *kobj, | 538 | pci_read_config(struct file *filp, struct kobject *kobj, |
| 497 | struct bin_attribute *bin_attr, | 539 | struct bin_attribute *bin_attr, |
| @@ -1303,29 +1345,20 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) | |||
| 1303 | pdev->rom_attr = attr; | 1345 | pdev->rom_attr = attr; |
| 1304 | } | 1346 | } |
| 1305 | 1347 | ||
| 1306 | if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) { | ||
| 1307 | retval = device_create_file(&pdev->dev, &vga_attr); | ||
| 1308 | if (retval) | ||
| 1309 | goto err_rom_file; | ||
| 1310 | } | ||
| 1311 | |||
| 1312 | /* add platform-specific attributes */ | 1348 | /* add platform-specific attributes */ |
| 1313 | retval = pcibios_add_platform_entries(pdev); | 1349 | retval = pcibios_add_platform_entries(pdev); |
| 1314 | if (retval) | 1350 | if (retval) |
| 1315 | goto err_vga_file; | 1351 | goto err_rom_file; |
| 1316 | 1352 | ||
| 1317 | /* add sysfs entries for various capabilities */ | 1353 | /* add sysfs entries for various capabilities */ |
| 1318 | retval = pci_create_capabilities_sysfs(pdev); | 1354 | retval = pci_create_capabilities_sysfs(pdev); |
| 1319 | if (retval) | 1355 | if (retval) |
| 1320 | goto err_vga_file; | 1356 | goto err_rom_file; |
| 1321 | 1357 | ||
| 1322 | pci_create_firmware_label_files(pdev); | 1358 | pci_create_firmware_label_files(pdev); |
| 1323 | 1359 | ||
| 1324 | return 0; | 1360 | return 0; |
| 1325 | 1361 | ||
| 1326 | err_vga_file: | ||
| 1327 | if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) | ||
| 1328 | device_remove_file(&pdev->dev, &vga_attr); | ||
| 1329 | err_rom_file: | 1362 | err_rom_file: |
| 1330 | if (rom_size) { | 1363 | if (rom_size) { |
| 1331 | sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); | 1364 | sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); |
| @@ -1411,3 +1444,62 @@ static int __init pci_sysfs_init(void) | |||
| 1411 | } | 1444 | } |
| 1412 | 1445 | ||
| 1413 | late_initcall(pci_sysfs_init); | 1446 | late_initcall(pci_sysfs_init); |
| 1447 | |||
| 1448 | static struct attribute *pci_dev_dev_attrs[] = { | ||
| 1449 | &vga_attr.attr, | ||
| 1450 | NULL, | ||
| 1451 | }; | ||
| 1452 | |||
| 1453 | static umode_t pci_dev_attrs_are_visible(struct kobject *kobj, | ||
| 1454 | struct attribute *a, int n) | ||
| 1455 | { | ||
| 1456 | struct device *dev = container_of(kobj, struct device, kobj); | ||
| 1457 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 1458 | |||
| 1459 | if (a == &vga_attr.attr) | ||
| 1460 | if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) | ||
| 1461 | return 0; | ||
| 1462 | |||
| 1463 | return a->mode; | ||
| 1464 | } | ||
| 1465 | |||
| 1466 | #ifdef CONFIG_PCI_IOV | ||
| 1467 | static struct attribute *sriov_dev_attrs[] = { | ||
| 1468 | &sriov_totalvfs_attr.attr, | ||
| 1469 | &sriov_numvfs_attr.attr, | ||
| 1470 | NULL, | ||
| 1471 | }; | ||
| 1472 | |||
| 1473 | static umode_t sriov_attrs_are_visible(struct kobject *kobj, | ||
| 1474 | struct attribute *a, int n) | ||
| 1475 | { | ||
| 1476 | struct device *dev = container_of(kobj, struct device, kobj); | ||
| 1477 | |||
| 1478 | if (!dev_is_pf(dev)) | ||
| 1479 | return 0; | ||
| 1480 | |||
| 1481 | return a->mode; | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | static struct attribute_group sriov_dev_attr_group = { | ||
| 1485 | .attrs = sriov_dev_attrs, | ||
| 1486 | .is_visible = sriov_attrs_are_visible, | ||
| 1487 | }; | ||
| 1488 | #endif /* CONFIG_PCI_IOV */ | ||
| 1489 | |||
| 1490 | static struct attribute_group pci_dev_attr_group = { | ||
| 1491 | .attrs = pci_dev_dev_attrs, | ||
| 1492 | .is_visible = pci_dev_attrs_are_visible, | ||
| 1493 | }; | ||
| 1494 | |||
| 1495 | static const struct attribute_group *pci_dev_attr_groups[] = { | ||
| 1496 | &pci_dev_attr_group, | ||
| 1497 | #ifdef CONFIG_PCI_IOV | ||
| 1498 | &sriov_dev_attr_group, | ||
| 1499 | #endif | ||
| 1500 | NULL, | ||
| 1501 | }; | ||
| 1502 | |||
| 1503 | struct device_type pci_dev_type = { | ||
| 1504 | .groups = pci_dev_attr_groups, | ||
| 1505 | }; | ||
