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.c109
1 files changed, 95 insertions, 14 deletions
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index f5b0b622c189..ae9a7695be97 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -343,6 +343,58 @@ pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
343 return count; 343 return count;
344} 344}
345 345
346static ssize_t
347pci_read_vpd(struct kobject *kobj, struct bin_attribute *bin_attr,
348 char *buf, loff_t off, size_t count)
349{
350 struct pci_dev *dev =
351 to_pci_dev(container_of(kobj, struct device, kobj));
352 int end;
353 int ret;
354
355 if (off > bin_attr->size)
356 count = 0;
357 else if (count > bin_attr->size - off)
358 count = bin_attr->size - off;
359 end = off + count;
360
361 while (off < end) {
362 ret = dev->vpd->ops->read(dev, off, end - off, buf);
363 if (ret < 0)
364 return ret;
365 buf += ret;
366 off += ret;
367 }
368
369 return count;
370}
371
372static ssize_t
373pci_write_vpd(struct kobject *kobj, struct bin_attribute *bin_attr,
374 char *buf, loff_t off, size_t count)
375{
376 struct pci_dev *dev =
377 to_pci_dev(container_of(kobj, struct device, kobj));
378 int end;
379 int ret;
380
381 if (off > bin_attr->size)
382 count = 0;
383 else if (count > bin_attr->size - off)
384 count = bin_attr->size - off;
385 end = off + count;
386
387 while (off < end) {
388 ret = dev->vpd->ops->write(dev, off, end - off, buf);
389 if (ret < 0)
390 return ret;
391 buf += ret;
392 off += ret;
393 }
394
395 return count;
396}
397
346#ifdef HAVE_PCI_LEGACY 398#ifdef HAVE_PCI_LEGACY
347/** 399/**
348 * pci_read_legacy_io - read byte(s) from legacy I/O port space 400 * pci_read_legacy_io - read byte(s) from legacy I/O port space
@@ -611,7 +663,7 @@ int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev)
611 663
612int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) 664int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
613{ 665{
614 struct bin_attribute *rom_attr = NULL; 666 struct bin_attribute *attr = NULL;
615 int retval; 667 int retval;
616 668
617 if (!sysfs_initialized) 669 if (!sysfs_initialized)
@@ -624,22 +676,41 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
624 if (retval) 676 if (retval)
625 goto err; 677 goto err;
626 678
679 /* If the device has VPD, try to expose it in sysfs. */
680 if (pdev->vpd) {
681 attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
682 if (attr) {
683 pdev->vpd->attr = attr;
684 attr->size = pdev->vpd->ops->get_size(pdev);
685 attr->attr.name = "vpd";
686 attr->attr.mode = S_IRUGO | S_IWUSR;
687 attr->read = pci_read_vpd;
688 attr->write = pci_write_vpd;
689 retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
690 if (retval)
691 goto err_vpd;
692 } else {
693 retval = -ENOMEM;
694 goto err_config_file;
695 }
696 }
697
627 retval = pci_create_resource_files(pdev); 698 retval = pci_create_resource_files(pdev);
628 if (retval) 699 if (retval)
629 goto err_bin_file; 700 goto err_vpd_file;
630 701
631 /* If the device has a ROM, try to expose it in sysfs. */ 702 /* If the device has a ROM, try to expose it in sysfs. */
632 if (pci_resource_len(pdev, PCI_ROM_RESOURCE) || 703 if (pci_resource_len(pdev, PCI_ROM_RESOURCE) ||
633 (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)) { 704 (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)) {
634 rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC); 705 attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
635 if (rom_attr) { 706 if (attr) {
636 pdev->rom_attr = rom_attr; 707 pdev->rom_attr = attr;
637 rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE); 708 attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
638 rom_attr->attr.name = "rom"; 709 attr->attr.name = "rom";
639 rom_attr->attr.mode = S_IRUSR; 710 attr->attr.mode = S_IRUSR;
640 rom_attr->read = pci_read_rom; 711 attr->read = pci_read_rom;
641 rom_attr->write = pci_write_rom; 712 attr->write = pci_write_rom;
642 retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr); 713 retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
643 if (retval) 714 if (retval)
644 goto err_rom; 715 goto err_rom;
645 } else { 716 } else {
@@ -657,12 +728,18 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
657 728
658err_rom_file: 729err_rom_file:
659 if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) 730 if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
660 sysfs_remove_bin_file(&pdev->dev.kobj, rom_attr); 731 sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
661err_rom: 732err_rom:
662 kfree(rom_attr); 733 kfree(pdev->rom_attr);
663err_resource_files: 734err_resource_files:
664 pci_remove_resource_files(pdev); 735 pci_remove_resource_files(pdev);
665err_bin_file: 736err_vpd_file:
737 if (pdev->vpd) {
738 sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
739err_vpd:
740 kfree(pdev->vpd->attr);
741 }
742err_config_file:
666 if (pdev->cfg_size < 4096) 743 if (pdev->cfg_size < 4096)
667 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); 744 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
668 else 745 else
@@ -684,6 +761,10 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
684 761
685 pcie_aspm_remove_sysfs_dev_files(pdev); 762 pcie_aspm_remove_sysfs_dev_files(pdev);
686 763
764 if (pdev->vpd) {
765 sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
766 kfree(pdev->vpd->attr);
767 }
687 if (pdev->cfg_size < 4096) 768 if (pdev->cfg_size < 4096)
688 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); 769 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
689 else 770 else