diff options
-rw-r--r-- | drivers/pci/pci-sysfs.c | 138 |
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 | ||
738 | static 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 | |||
738 | int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) | 768 | int __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 | ||
803 | err_rom_file: | 825 | err_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); |
806 | err_rom: | 828 | kfree(pdev->rom_attr); |
807 | kfree(pdev->rom_attr); | 829 | pdev->rom_attr = NULL; |
830 | } | ||
808 | err_resource_files: | 831 | err_resource_files: |
809 | pci_remove_resource_files(pdev); | 832 | pci_remove_resource_files(pdev); |
810 | err_vpd_file: | ||
811 | if (pdev->vpd) { | ||
812 | sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr); | ||
813 | err_vpd: | ||
814 | kfree(pdev->vpd->attr); | ||
815 | } | ||
816 | err_config_file: | 833 | err_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 | ||
842 | static 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 | */ |
831 | void pci_remove_sysfs_dev_files(struct pci_dev *pdev) | 858 | void 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 | ||