diff options
Diffstat (limited to 'drivers/pci/pci-sysfs.c')
-rw-r--r-- | drivers/pci/pci-sysfs.c | 172 |
1 files changed, 161 insertions, 11 deletions
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index f39378d9da15..5d883a152789 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -404,6 +404,106 @@ static ssize_t d3cold_allowed_show(struct device *dev, | |||
404 | } | 404 | } |
405 | #endif | 405 | #endif |
406 | 406 | ||
407 | #ifdef CONFIG_PCI_IOV | ||
408 | static ssize_t sriov_totalvfs_show(struct device *dev, | ||
409 | struct device_attribute *attr, | ||
410 | char *buf) | ||
411 | { | ||
412 | struct pci_dev *pdev = to_pci_dev(dev); | ||
413 | |||
414 | return sprintf(buf, "%u\n", pci_sriov_get_totalvfs(pdev)); | ||
415 | } | ||
416 | |||
417 | |||
418 | static ssize_t sriov_numvfs_show(struct device *dev, | ||
419 | struct device_attribute *attr, | ||
420 | char *buf) | ||
421 | { | ||
422 | struct pci_dev *pdev = to_pci_dev(dev); | ||
423 | |||
424 | return sprintf(buf, "%u\n", pdev->sriov->num_VFs); | ||
425 | } | ||
426 | |||
427 | /* | ||
428 | * num_vfs > 0; number of vfs to enable | ||
429 | * num_vfs = 0; disable all vfs | ||
430 | * | ||
431 | * Note: SRIOV spec doesn't allow partial VF | ||
432 | * disable, so its all or none. | ||
433 | */ | ||
434 | static ssize_t sriov_numvfs_store(struct device *dev, | ||
435 | struct device_attribute *attr, | ||
436 | const char *buf, size_t count) | ||
437 | { | ||
438 | struct pci_dev *pdev = to_pci_dev(dev); | ||
439 | int num_vfs_enabled = 0; | ||
440 | int num_vfs; | ||
441 | int ret = 0; | ||
442 | u16 total; | ||
443 | |||
444 | if (kstrtoint(buf, 0, &num_vfs) < 0) | ||
445 | return -EINVAL; | ||
446 | |||
447 | /* is PF driver loaded w/callback */ | ||
448 | if (!pdev->driver || !pdev->driver->sriov_configure) { | ||
449 | dev_info(&pdev->dev, | ||
450 | "Driver doesn't support SRIOV configuration via sysfs\n"); | ||
451 | return -ENOSYS; | ||
452 | } | ||
453 | |||
454 | /* if enabling vf's ... */ | ||
455 | total = pci_sriov_get_totalvfs(pdev); | ||
456 | /* Requested VFs to enable < totalvfs and none enabled already */ | ||
457 | if ((num_vfs > 0) && (num_vfs <= total)) { | ||
458 | if (pdev->sriov->num_VFs == 0) { | ||
459 | num_vfs_enabled = | ||
460 | pdev->driver->sriov_configure(pdev, num_vfs); | ||
461 | if ((num_vfs_enabled >= 0) && | ||
462 | (num_vfs_enabled != num_vfs)) { | ||
463 | dev_warn(&pdev->dev, | ||
464 | "Only %d VFs enabled\n", | ||
465 | num_vfs_enabled); | ||
466 | return count; | ||
467 | } else if (num_vfs_enabled < 0) | ||
468 | /* error code from driver callback */ | ||
469 | return num_vfs_enabled; | ||
470 | } else if (num_vfs == pdev->sriov->num_VFs) { | ||
471 | dev_warn(&pdev->dev, | ||
472 | "%d VFs already enabled; no enable action taken\n", | ||
473 | num_vfs); | ||
474 | return count; | ||
475 | } else { | ||
476 | dev_warn(&pdev->dev, | ||
477 | "%d VFs already enabled. Disable before enabling %d VFs\n", | ||
478 | pdev->sriov->num_VFs, num_vfs); | ||
479 | return -EINVAL; | ||
480 | } | ||
481 | } | ||
482 | |||
483 | /* disable vfs */ | ||
484 | if (num_vfs == 0) { | ||
485 | if (pdev->sriov->num_VFs != 0) { | ||
486 | ret = pdev->driver->sriov_configure(pdev, 0); | ||
487 | return ret ? ret : count; | ||
488 | } else { | ||
489 | dev_warn(&pdev->dev, | ||
490 | "All VFs disabled; no disable action taken\n"); | ||
491 | return count; | ||
492 | } | ||
493 | } | ||
494 | |||
495 | dev_err(&pdev->dev, | ||
496 | "Invalid value for number of VFs to enable: %d\n", num_vfs); | ||
497 | |||
498 | return -EINVAL; | ||
499 | } | ||
500 | |||
501 | static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs); | ||
502 | static struct device_attribute sriov_numvfs_attr = | ||
503 | __ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP), | ||
504 | sriov_numvfs_show, sriov_numvfs_store); | ||
505 | #endif /* CONFIG_PCI_IOV */ | ||
506 | |||
407 | struct device_attribute pci_dev_attrs[] = { | 507 | struct device_attribute pci_dev_attrs[] = { |
408 | __ATTR_RO(resource), | 508 | __ATTR_RO(resource), |
409 | __ATTR_RO(vendor), | 509 | __ATTR_RO(vendor), |
@@ -1269,29 +1369,20 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) | |||
1269 | pdev->rom_attr = attr; | 1369 | pdev->rom_attr = attr; |
1270 | } | 1370 | } |
1271 | 1371 | ||
1272 | if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) { | ||
1273 | retval = device_create_file(&pdev->dev, &vga_attr); | ||
1274 | if (retval) | ||
1275 | goto err_rom_file; | ||
1276 | } | ||
1277 | |||
1278 | /* add platform-specific attributes */ | 1372 | /* add platform-specific attributes */ |
1279 | retval = pcibios_add_platform_entries(pdev); | 1373 | retval = pcibios_add_platform_entries(pdev); |
1280 | if (retval) | 1374 | if (retval) |
1281 | goto err_vga_file; | 1375 | goto err_rom_file; |
1282 | 1376 | ||
1283 | /* add sysfs entries for various capabilities */ | 1377 | /* add sysfs entries for various capabilities */ |
1284 | retval = pci_create_capabilities_sysfs(pdev); | 1378 | retval = pci_create_capabilities_sysfs(pdev); |
1285 | if (retval) | 1379 | if (retval) |
1286 | goto err_vga_file; | 1380 | goto err_rom_file; |
1287 | 1381 | ||
1288 | pci_create_firmware_label_files(pdev); | 1382 | pci_create_firmware_label_files(pdev); |
1289 | 1383 | ||
1290 | return 0; | 1384 | return 0; |
1291 | 1385 | ||
1292 | err_vga_file: | ||
1293 | if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) | ||
1294 | device_remove_file(&pdev->dev, &vga_attr); | ||
1295 | err_rom_file: | 1386 | err_rom_file: |
1296 | if (rom_size) { | 1387 | if (rom_size) { |
1297 | sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); | 1388 | sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); |
@@ -1377,3 +1468,62 @@ static int __init pci_sysfs_init(void) | |||
1377 | } | 1468 | } |
1378 | 1469 | ||
1379 | late_initcall(pci_sysfs_init); | 1470 | late_initcall(pci_sysfs_init); |
1471 | |||
1472 | static struct attribute *pci_dev_dev_attrs[] = { | ||
1473 | &vga_attr.attr, | ||
1474 | NULL, | ||
1475 | }; | ||
1476 | |||
1477 | static umode_t pci_dev_attrs_are_visible(struct kobject *kobj, | ||
1478 | struct attribute *a, int n) | ||
1479 | { | ||
1480 | struct device *dev = container_of(kobj, struct device, kobj); | ||
1481 | struct pci_dev *pdev = to_pci_dev(dev); | ||
1482 | |||
1483 | if (a == &vga_attr.attr) | ||
1484 | if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) | ||
1485 | return 0; | ||
1486 | |||
1487 | return a->mode; | ||
1488 | } | ||
1489 | |||
1490 | #ifdef CONFIG_PCI_IOV | ||
1491 | static struct attribute *sriov_dev_attrs[] = { | ||
1492 | &sriov_totalvfs_attr.attr, | ||
1493 | &sriov_numvfs_attr.attr, | ||
1494 | NULL, | ||
1495 | }; | ||
1496 | |||
1497 | static umode_t sriov_attrs_are_visible(struct kobject *kobj, | ||
1498 | struct attribute *a, int n) | ||
1499 | { | ||
1500 | struct device *dev = container_of(kobj, struct device, kobj); | ||
1501 | |||
1502 | if (!dev_is_pf(dev)) | ||
1503 | return 0; | ||
1504 | |||
1505 | return a->mode; | ||
1506 | } | ||
1507 | |||
1508 | static struct attribute_group sriov_dev_attr_group = { | ||
1509 | .attrs = sriov_dev_attrs, | ||
1510 | .is_visible = sriov_attrs_are_visible, | ||
1511 | }; | ||
1512 | #endif /* CONFIG_PCI_IOV */ | ||
1513 | |||
1514 | static struct attribute_group pci_dev_attr_group = { | ||
1515 | .attrs = pci_dev_dev_attrs, | ||
1516 | .is_visible = pci_dev_attrs_are_visible, | ||
1517 | }; | ||
1518 | |||
1519 | static const struct attribute_group *pci_dev_attr_groups[] = { | ||
1520 | &pci_dev_attr_group, | ||
1521 | #ifdef CONFIG_PCI_IOV | ||
1522 | &sriov_dev_attr_group, | ||
1523 | #endif | ||
1524 | NULL, | ||
1525 | }; | ||
1526 | |||
1527 | struct device_type pci_dev_type = { | ||
1528 | .groups = pci_dev_attr_groups, | ||
1529 | }; | ||