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.c114
1 files changed, 100 insertions, 14 deletions
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 8d9d648daeba..271d41cc05ab 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -21,6 +21,7 @@
21#include <linux/topology.h> 21#include <linux/topology.h>
22#include <linux/mm.h> 22#include <linux/mm.h>
23#include <linux/capability.h> 23#include <linux/capability.h>
24#include <linux/pci-aspm.h>
24#include "pci.h" 25#include "pci.h"
25 26
26static int sysfs_initialized; /* = 0 */ 27static int sysfs_initialized; /* = 0 */
@@ -358,6 +359,58 @@ pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
358 return count; 359 return count;
359} 360}
360 361
362static ssize_t
363pci_read_vpd(struct kobject *kobj, struct bin_attribute *bin_attr,
364 char *buf, loff_t off, size_t count)
365{
366 struct pci_dev *dev =
367 to_pci_dev(container_of(kobj, struct device, kobj));
368 int end;
369 int ret;
370
371 if (off > bin_attr->size)
372 count = 0;
373 else if (count > bin_attr->size - off)
374 count = bin_attr->size - off;
375 end = off + count;
376
377 while (off < end) {
378 ret = dev->vpd->ops->read(dev, off, end - off, buf);
379 if (ret < 0)
380 return ret;
381 buf += ret;
382 off += ret;
383 }
384
385 return count;
386}
387
388static ssize_t
389pci_write_vpd(struct kobject *kobj, struct bin_attribute *bin_attr,
390 char *buf, loff_t off, size_t count)
391{
392 struct pci_dev *dev =
393 to_pci_dev(container_of(kobj, struct device, kobj));
394 int end;
395 int ret;
396
397 if (off > bin_attr->size)
398 count = 0;
399 else if (count > bin_attr->size - off)
400 count = bin_attr->size - off;
401 end = off + count;
402
403 while (off < end) {
404 ret = dev->vpd->ops->write(dev, off, end - off, buf);
405 if (ret < 0)
406 return ret;
407 buf += ret;
408 off += ret;
409 }
410
411 return count;
412}
413
361#ifdef HAVE_PCI_LEGACY 414#ifdef HAVE_PCI_LEGACY
362/** 415/**
363 * pci_read_legacy_io - read byte(s) from legacy I/O port space 416 * pci_read_legacy_io - read byte(s) from legacy I/O port space
@@ -626,7 +679,7 @@ int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev)
626 679
627int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) 680int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
628{ 681{
629 struct bin_attribute *rom_attr = NULL; 682 struct bin_attribute *attr = NULL;
630 int retval; 683 int retval;
631 684
632 if (!sysfs_initialized) 685 if (!sysfs_initialized)
@@ -639,22 +692,41 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
639 if (retval) 692 if (retval)
640 goto err; 693 goto err;
641 694
695 /* If the device has VPD, try to expose it in sysfs. */
696 if (pdev->vpd) {
697 attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
698 if (attr) {
699 pdev->vpd->attr = attr;
700 attr->size = pdev->vpd->ops->get_size(pdev);
701 attr->attr.name = "vpd";
702 attr->attr.mode = S_IRUGO | S_IWUSR;
703 attr->read = pci_read_vpd;
704 attr->write = pci_write_vpd;
705 retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
706 if (retval)
707 goto err_vpd;
708 } else {
709 retval = -ENOMEM;
710 goto err_config_file;
711 }
712 }
713
642 retval = pci_create_resource_files(pdev); 714 retval = pci_create_resource_files(pdev);
643 if (retval) 715 if (retval)
644 goto err_bin_file; 716 goto err_vpd_file;
645 717
646 /* If the device has a ROM, try to expose it in sysfs. */ 718 /* If the device has a ROM, try to expose it in sysfs. */
647 if (pci_resource_len(pdev, PCI_ROM_RESOURCE) || 719 if (pci_resource_len(pdev, PCI_ROM_RESOURCE) ||
648 (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)) { 720 (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)) {
649 rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC); 721 attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
650 if (rom_attr) { 722 if (attr) {
651 pdev->rom_attr = rom_attr; 723 pdev->rom_attr = attr;
652 rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE); 724 attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
653 rom_attr->attr.name = "rom"; 725 attr->attr.name = "rom";
654 rom_attr->attr.mode = S_IRUSR; 726 attr->attr.mode = S_IRUSR;
655 rom_attr->read = pci_read_rom; 727 attr->read = pci_read_rom;
656 rom_attr->write = pci_write_rom; 728 attr->write = pci_write_rom;
657 retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr); 729 retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
658 if (retval) 730 if (retval)
659 goto err_rom; 731 goto err_rom;
660 } else { 732 } else {
@@ -666,16 +738,24 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
666 if (pcibios_add_platform_entries(pdev)) 738 if (pcibios_add_platform_entries(pdev))
667 goto err_rom_file; 739 goto err_rom_file;
668 740
741 pcie_aspm_create_sysfs_dev_files(pdev);
742
669 return 0; 743 return 0;
670 744
671err_rom_file: 745err_rom_file:
672 if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) 746 if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
673 sysfs_remove_bin_file(&pdev->dev.kobj, rom_attr); 747 sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
674err_rom: 748err_rom:
675 kfree(rom_attr); 749 kfree(pdev->rom_attr);
676err_resource_files: 750err_resource_files:
677 pci_remove_resource_files(pdev); 751 pci_remove_resource_files(pdev);
678err_bin_file: 752err_vpd_file:
753 if (pdev->vpd) {
754 sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
755err_vpd:
756 kfree(pdev->vpd->attr);
757 }
758err_config_file:
679 if (pdev->cfg_size < 4096) 759 if (pdev->cfg_size < 4096)
680 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); 760 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
681 else 761 else
@@ -695,6 +775,12 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
695 if (!sysfs_initialized) 775 if (!sysfs_initialized)
696 return; 776 return;
697 777
778 pcie_aspm_remove_sysfs_dev_files(pdev);
779
780 if (pdev->vpd) {
781 sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
782 kfree(pdev->vpd->attr);
783 }
698 if (pdev->cfg_size < 4096) 784 if (pdev->cfg_size < 4096)
699 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); 785 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
700 else 786 else