aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/pci-sysfs.c138
1 files changed, 83 insertions, 55 deletions
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 00a9947cb7cc..2cad6da2e4aa 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -735,10 +735,41 @@ int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev)
735 return 0; 735 return 0;
736} 736}
737 737
738static int pci_create_capabilities_sysfs(struct pci_dev *dev)
739{
740 int retval;
741 struct bin_attribute *attr;
742
743 /* If the device has VPD, try to expose it in sysfs. */
744 if (dev->vpd) {
745 attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
746 if (!attr)
747 return -ENOMEM;
748
749 attr->size = dev->vpd->len;
750 attr->attr.name = "vpd";
751 attr->attr.mode = S_IRUSR | S_IWUSR;
752 attr->read = pci_read_vpd;
753 attr->write = pci_write_vpd;
754 retval = sysfs_create_bin_file(&dev->dev.kobj, attr);
755 if (retval) {
756 kfree(dev->vpd->attr);
757 return retval;
758 }
759 dev->vpd->attr = attr;
760 }
761
762 /* Active State Power Management */
763 pcie_aspm_create_sysfs_dev_files(dev);
764
765 return 0;
766}
767
738int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) 768int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
739{ 769{
740 struct bin_attribute *attr = NULL;
741 int retval; 770 int retval;
771 int rom_size = 0;
772 struct bin_attribute *attr;
742 773
743 if (!sysfs_initialized) 774 if (!sysfs_initialized)
744 return -EACCES; 775 return -EACCES;
@@ -750,69 +781,55 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
750 if (retval) 781 if (retval)
751 goto err; 782 goto err;
752 783
753 /* If the device has VPD, try to expose it in sysfs. */
754 if (pdev->vpd) {
755 attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
756 if (attr) {
757 pdev->vpd->attr = attr;
758 attr->size = pdev->vpd->len;
759 attr->attr.name = "vpd";
760 attr->attr.mode = S_IRUSR | S_IWUSR;
761 attr->read = pci_read_vpd;
762 attr->write = pci_write_vpd;
763 retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
764 if (retval)
765 goto err_vpd;
766 } else {
767 retval = -ENOMEM;
768 goto err_config_file;
769 }
770 }
771
772 retval = pci_create_resource_files(pdev); 784 retval = pci_create_resource_files(pdev);
773 if (retval) 785 if (retval)
774 goto err_vpd_file; 786 goto err_config_file;
787
788 if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
789 rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
790 else if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
791 rom_size = 0x20000;
775 792
776 /* If the device has a ROM, try to expose it in sysfs. */ 793 /* If the device has a ROM, try to expose it in sysfs. */
777 if (pci_resource_len(pdev, PCI_ROM_RESOURCE) || 794 if (rom_size) {
778 (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)) {
779 attr = kzalloc(sizeof(*attr), GFP_ATOMIC); 795 attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
780 if (attr) { 796 if (!attr) {
781 pdev->rom_attr = attr;
782 attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
783 attr->attr.name = "rom";
784 attr->attr.mode = S_IRUSR;
785 attr->read = pci_read_rom;
786 attr->write = pci_write_rom;
787 retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
788 if (retval)
789 goto err_rom;
790 } else {
791 retval = -ENOMEM; 797 retval = -ENOMEM;
792 goto err_resource_files; 798 goto err_resource_files;
793 } 799 }
800 attr->size = rom_size;
801 attr->attr.name = "rom";
802 attr->attr.mode = S_IRUSR;
803 attr->read = pci_read_rom;
804 attr->write = pci_write_rom;
805 retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
806 if (retval) {
807 kfree(attr);
808 goto err_resource_files;
809 }
810 pdev->rom_attr = attr;
794 } 811 }
812
795 /* add platform-specific attributes */ 813 /* add platform-specific attributes */
796 if (pcibios_add_platform_entries(pdev)) 814 retval = pcibios_add_platform_entries(pdev);
815 if (retval)
797 goto err_rom_file; 816 goto err_rom_file;
798 817
799 pcie_aspm_create_sysfs_dev_files(pdev); 818 /* add sysfs entries for various capabilities */
819 retval = pci_create_capabilities_sysfs(pdev);
820 if (retval)
821 goto err_rom_file;
800 822
801 return 0; 823 return 0;
802 824
803err_rom_file: 825err_rom_file:
804 if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) 826 if (rom_size) {
805 sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); 827 sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
806err_rom: 828 kfree(pdev->rom_attr);
807 kfree(pdev->rom_attr); 829 pdev->rom_attr = NULL;
830 }
808err_resource_files: 831err_resource_files:
809 pci_remove_resource_files(pdev); 832 pci_remove_resource_files(pdev);
810err_vpd_file:
811 if (pdev->vpd) {
812 sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
813err_vpd:
814 kfree(pdev->vpd->attr);
815 }
816err_config_file: 833err_config_file:
817 if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE) 834 if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
818 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); 835 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
@@ -822,6 +839,16 @@ err:
822 return retval; 839 return retval;
823} 840}
824 841
842static void pci_remove_capabilities_sysfs(struct pci_dev *dev)
843{
844 if (dev->vpd && dev->vpd->attr) {
845 sysfs_remove_bin_file(&dev->dev.kobj, dev->vpd->attr);
846 kfree(dev->vpd->attr);
847 }
848
849 pcie_aspm_remove_sysfs_dev_files(dev);
850}
851
825/** 852/**
826 * pci_remove_sysfs_dev_files - cleanup PCI specific sysfs files 853 * pci_remove_sysfs_dev_files - cleanup PCI specific sysfs files
827 * @pdev: device whose entries we should free 854 * @pdev: device whose entries we should free
@@ -830,15 +857,13 @@ err:
830 */ 857 */
831void pci_remove_sysfs_dev_files(struct pci_dev *pdev) 858void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
832{ 859{
860 int rom_size = 0;
861
833 if (!sysfs_initialized) 862 if (!sysfs_initialized)
834 return; 863 return;
835 864
836 pcie_aspm_remove_sysfs_dev_files(pdev); 865 pci_remove_capabilities_sysfs(pdev);
837 866
838 if (pdev->vpd) {
839 sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
840 kfree(pdev->vpd->attr);
841 }
842 if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE) 867 if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
843 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); 868 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
844 else 869 else
@@ -846,11 +871,14 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
846 871
847 pci_remove_resource_files(pdev); 872 pci_remove_resource_files(pdev);
848 873
849 if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) { 874 if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
850 if (pdev->rom_attr) { 875 rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
851 sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); 876 else if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
852 kfree(pdev->rom_attr); 877 rom_size = 0x20000;
853 } 878
879 if (rom_size && pdev->rom_attr) {
880 sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
881 kfree(pdev->rom_attr);
854 } 882 }
855} 883}
856 884