summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-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)
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);
}
}