PCI: centralize the capabilities code in pci-sysfs.c
[linux-2.6.git] / drivers / pci / pci-sysfs.c
index 00a9947..2cad6da 100644 (file)
@@ -735,10 +735,41 @@ int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev)
        return 0;
 }
 
+static int pci_create_capabilities_sysfs(struct pci_dev *dev)
+{
+       int retval;
+       struct bin_attribute *attr;
+
+       /* If the device has VPD, try to expose it in sysfs. */
+       if (dev->vpd) {
+               attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
+               if (!attr)
+                       return -ENOMEM;
+
+               attr->size = dev->vpd->len;
+               attr->attr.name = "vpd";
+               attr->attr.mode = S_IRUSR | S_IWUSR;
+               attr->read = pci_read_vpd;
+               attr->write = pci_write_vpd;
+               retval = sysfs_create_bin_file(&dev->dev.kobj, attr);
+               if (retval) {
+                       kfree(dev->vpd->attr);
+                       return retval;
+               }
+               dev->vpd->attr = attr;
+       }
+
+       /* Active State Power Management */
+       pcie_aspm_create_sysfs_dev_files(dev);
+
+       return 0;
+}
+
 int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
 {
-       struct bin_attribute *attr = NULL;
        int retval;
+       int rom_size = 0;
+       struct bin_attribute *attr;
 
        if (!sysfs_initialized)
                return -EACCES;
@@ -750,69 +781,55 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
        if (retval)
                goto err;
 
-       /* If the device has VPD, try to expose it in sysfs. */
-       if (pdev->vpd) {
-               attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
-               if (attr) {
-                       pdev->vpd->attr = attr;
-                       attr->size = pdev->vpd->len;
-                       attr->attr.name = "vpd";
-                       attr->attr.mode = S_IRUSR | S_IWUSR;
-                       attr->read = pci_read_vpd;
-                       attr->write = pci_write_vpd;
-                       retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
-                       if (retval)
-                               goto err_vpd;
-               } else {
-                       retval = -ENOMEM;
-                       goto err_config_file;
-               }
-       }
-
        retval = pci_create_resource_files(pdev);
        if (retval)
-               goto err_vpd_file;
+               goto err_config_file;
+
+       if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
+               rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
+       else if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
+               rom_size = 0x20000;
 
        /* If the device has a ROM, try to expose it in sysfs. */
-       if (pci_resource_len(pdev, PCI_ROM_RESOURCE) ||
-           (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)) {
+       if (rom_size) {
                attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
-               if (attr) {
-                       pdev->rom_attr = attr;
-                       attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
-                       attr->attr.name = "rom";
-                       attr->attr.mode = S_IRUSR;
-                       attr->read = pci_read_rom;
-                       attr->write = pci_write_rom;
-                       retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
-                       if (retval)
-                               goto err_rom;
-               } else {
+               if (!attr) {
                        retval = -ENOMEM;
                        goto err_resource_files;
                }
+               attr->size = rom_size;
+               attr->attr.name = "rom";
+               attr->attr.mode = S_IRUSR;
+               attr->read = pci_read_rom;
+               attr->write = pci_write_rom;
+               retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
+               if (retval) {
+                       kfree(attr);
+                       goto err_resource_files;
+               }
+               pdev->rom_attr = attr;
        }
+
        /* add platform-specific attributes */
-       if (pcibios_add_platform_entries(pdev))
+       retval = pcibios_add_platform_entries(pdev);
+       if (retval)
                goto err_rom_file;
 
-       pcie_aspm_create_sysfs_dev_files(pdev);
+       /* add sysfs entries for various capabilities */
+       retval = pci_create_capabilities_sysfs(pdev);
+       if (retval)
+               goto err_rom_file;
 
        return 0;
 
 err_rom_file:
-       if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
+       if (rom_size) {
                sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
-err_rom:
-       kfree(pdev->rom_attr);
+               kfree(pdev->rom_attr);
+               pdev->rom_attr = NULL;
+       }
 err_resource_files:
        pci_remove_resource_files(pdev);
-err_vpd_file:
-       if (pdev->vpd) {
-               sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
-err_vpd:
-               kfree(pdev->vpd->attr);
-       }
 err_config_file:
        if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
                sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
@@ -822,6 +839,16 @@ err:
        return retval;
 }
 
+static void pci_remove_capabilities_sysfs(struct pci_dev *dev)
+{
+       if (dev->vpd && dev->vpd->attr) {
+               sysfs_remove_bin_file(&dev->dev.kobj, dev->vpd->attr);
+               kfree(dev->vpd->attr);
+       }
+
+       pcie_aspm_remove_sysfs_dev_files(dev);
+}
+
 /**
  * pci_remove_sysfs_dev_files - cleanup PCI specific sysfs files
  * @pdev: device whose entries we should free
@@ -830,15 +857,13 @@ err:
  */
 void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
 {
+       int rom_size = 0;
+
        if (!sysfs_initialized)
                return;
 
-       pcie_aspm_remove_sysfs_dev_files(pdev);
+       pci_remove_capabilities_sysfs(pdev);
 
-       if (pdev->vpd) {
-               sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
-               kfree(pdev->vpd->attr);
-       }
        if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
                sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
        else
@@ -846,11 +871,14 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
 
        pci_remove_resource_files(pdev);
 
-       if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
-               if (pdev->rom_attr) {
-                       sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
-                       kfree(pdev->rom_attr);
-               }
+       if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
+               rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
+       else if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
+               rom_size = 0x20000;
+
+       if (rom_size && pdev->rom_attr) {
+               sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
+               kfree(pdev->rom_attr);
        }
 }