aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci-sysfs.c')
-rw-r--r--drivers/pci/pci-sysfs.c112
1 files changed, 73 insertions, 39 deletions
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 010e01c4bd43..a1d2e979b17f 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -117,6 +117,7 @@ is_enabled_store(struct device *dev, struct device_attribute *attr,
117 const char *buf, size_t count) 117 const char *buf, size_t count)
118{ 118{
119 struct pci_dev *pdev = to_pci_dev(dev); 119 struct pci_dev *pdev = to_pci_dev(dev);
120 int retval = 0;
120 121
121 /* this can crash the machine when done on the "wrong" device */ 122 /* this can crash the machine when done on the "wrong" device */
122 if (!capable(CAP_SYS_ADMIN)) 123 if (!capable(CAP_SYS_ADMIN))
@@ -126,8 +127,10 @@ is_enabled_store(struct device *dev, struct device_attribute *attr,
126 pci_disable_device(pdev); 127 pci_disable_device(pdev);
127 128
128 if (*buf == '1') 129 if (*buf == '1')
129 pci_enable_device(pdev); 130 retval = pci_enable_device(pdev);
130 131
132 if (retval)
133 return retval;
131 return count; 134 return count;
132} 135}
133 136
@@ -426,15 +429,38 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
426} 429}
427 430
428/** 431/**
432 * pci_remove_resource_files - cleanup resource files
433 * @dev: dev to cleanup
434 *
435 * If we created resource files for @dev, remove them from sysfs and
436 * free their resources.
437 */
438static void
439pci_remove_resource_files(struct pci_dev *pdev)
440{
441 int i;
442
443 for (i = 0; i < PCI_ROM_RESOURCE; i++) {
444 struct bin_attribute *res_attr;
445
446 res_attr = pdev->res_attr[i];
447 if (res_attr) {
448 sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
449 kfree(res_attr);
450 }
451 }
452}
453
454/**
429 * pci_create_resource_files - create resource files in sysfs for @dev 455 * pci_create_resource_files - create resource files in sysfs for @dev
430 * @dev: dev in question 456 * @dev: dev in question
431 * 457 *
432 * Walk the resources in @dev creating files for each resource available. 458 * Walk the resources in @dev creating files for each resource available.
433 */ 459 */
434static void 460static int pci_create_resource_files(struct pci_dev *pdev)
435pci_create_resource_files(struct pci_dev *pdev)
436{ 461{
437 int i; 462 int i;
463 int retval;
438 464
439 /* Expose the PCI resources from this device as files */ 465 /* Expose the PCI resources from this device as files */
440 for (i = 0; i < PCI_ROM_RESOURCE; i++) { 466 for (i = 0; i < PCI_ROM_RESOURCE; i++) {
@@ -457,35 +483,19 @@ pci_create_resource_files(struct pci_dev *pdev)
457 res_attr->size = pci_resource_len(pdev, i); 483 res_attr->size = pci_resource_len(pdev, i);
458 res_attr->mmap = pci_mmap_resource; 484 res_attr->mmap = pci_mmap_resource;
459 res_attr->private = &pdev->resource[i]; 485 res_attr->private = &pdev->resource[i];
460 sysfs_create_bin_file(&pdev->dev.kobj, res_attr); 486 retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
461 } 487 if (retval) {
462 } 488 pci_remove_resource_files(pdev);
463} 489 return retval;
464 490 }
465/** 491 } else {
466 * pci_remove_resource_files - cleanup resource files 492 return -ENOMEM;
467 * @dev: dev to cleanup
468 *
469 * If we created resource files for @dev, remove them from sysfs and
470 * free their resources.
471 */
472static void
473pci_remove_resource_files(struct pci_dev *pdev)
474{
475 int i;
476
477 for (i = 0; i < PCI_ROM_RESOURCE; i++) {
478 struct bin_attribute *res_attr;
479
480 res_attr = pdev->res_attr[i];
481 if (res_attr) {
482 sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
483 kfree(res_attr);
484 } 493 }
485 } 494 }
495 return 0;
486} 496}
487#else /* !HAVE_PCI_MMAP */ 497#else /* !HAVE_PCI_MMAP */
488static inline void pci_create_resource_files(struct pci_dev *dev) { return; } 498static inline int pci_create_resource_files(struct pci_dev *dev) { return 0; }
489static inline void pci_remove_resource_files(struct pci_dev *dev) { return; } 499static inline void pci_remove_resource_files(struct pci_dev *dev) { return; }
490#endif /* HAVE_PCI_MMAP */ 500#endif /* HAVE_PCI_MMAP */
491 501
@@ -570,22 +580,27 @@ static struct bin_attribute pcie_config_attr = {
570 .write = pci_write_config, 580 .write = pci_write_config,
571}; 581};
572 582
573int pci_create_sysfs_dev_files (struct pci_dev *pdev) 583int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
574{ 584{
585 struct bin_attribute *rom_attr = NULL;
586 int retval;
587
575 if (!sysfs_initialized) 588 if (!sysfs_initialized)
576 return -EACCES; 589 return -EACCES;
577 590
578 if (pdev->cfg_size < 4096) 591 if (pdev->cfg_size < 4096)
579 sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr); 592 retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
580 else 593 else
581 sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr); 594 retval = sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
595 if (retval)
596 goto err;
582 597
583 pci_create_resource_files(pdev); 598 retval = pci_create_resource_files(pdev);
599 if (retval)
600 goto err_bin_file;
584 601
585 /* If the device has a ROM, try to expose it in sysfs. */ 602 /* If the device has a ROM, try to expose it in sysfs. */
586 if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) { 603 if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
587 struct bin_attribute *rom_attr;
588
589 rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC); 604 rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC);
590 if (rom_attr) { 605 if (rom_attr) {
591 pdev->rom_attr = rom_attr; 606 pdev->rom_attr = rom_attr;
@@ -595,13 +610,28 @@ int pci_create_sysfs_dev_files (struct pci_dev *pdev)
595 rom_attr->attr.owner = THIS_MODULE; 610 rom_attr->attr.owner = THIS_MODULE;
596 rom_attr->read = pci_read_rom; 611 rom_attr->read = pci_read_rom;
597 rom_attr->write = pci_write_rom; 612 rom_attr->write = pci_write_rom;
598 sysfs_create_bin_file(&pdev->dev.kobj, rom_attr); 613 retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
614 if (retval)
615 goto err_rom;
616 } else {
617 retval = -ENOMEM;
618 goto err_bin_file;
599 } 619 }
600 } 620 }
601 /* add platform-specific attributes */ 621 /* add platform-specific attributes */
602 pcibios_add_platform_entries(pdev); 622 pcibios_add_platform_entries(pdev);
603 623
604 return 0; 624 return 0;
625
626err_rom:
627 kfree(rom_attr);
628err_bin_file:
629 if (pdev->cfg_size < 4096)
630 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
631 else
632 sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
633err:
634 return retval;
605} 635}
606 636
607/** 637/**
@@ -630,10 +660,14 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
630static int __init pci_sysfs_init(void) 660static int __init pci_sysfs_init(void)
631{ 661{
632 struct pci_dev *pdev = NULL; 662 struct pci_dev *pdev = NULL;
633 663 int retval;
664
634 sysfs_initialized = 1; 665 sysfs_initialized = 1;
635 for_each_pci_dev(pdev) 666 for_each_pci_dev(pdev) {
636 pci_create_sysfs_dev_files(pdev); 667 retval = pci_create_sysfs_dev_files(pdev);
668 if (retval)
669 return retval;
670 }
637 671
638 return 0; 672 return 0;
639} 673}