aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-bus-pci40
-rw-r--r--drivers/pci/pci-sysfs.c37
-rw-r--r--drivers/pci/slot.c48
3 files changed, 125 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index 25be3250f7d6..428676cfa61e 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -133,6 +133,46 @@ Description:
133 The symbolic link points to the PCI device sysfs entry of the 133 The symbolic link points to the PCI device sysfs entry of the
134 Physical Function this device associates with. 134 Physical Function this device associates with.
135 135
136
137What: /sys/bus/pci/slots/...
138Date: April 2005 (possibly older)
139KernelVersion: 2.6.12 (possibly older)
140Contact: linux-pci@vger.kernel.org
141Description:
142 When the appropriate driver is loaded, it will create a
143 directory per claimed physical PCI slot in
144 /sys/bus/pci/slots/. The names of these directories are
145 specific to the driver, which in turn, are specific to the
146 platform, but in general, should match the label on the
147 machine's physical chassis.
148
149 The drivers that can create slot directories include the
150 PCI hotplug drivers, and as of 2.6.27, the pci_slot driver.
151
152 The slot directories contain, at a minimum, a file named
153 'address' which contains the PCI bus:device:function tuple.
154 Other files may appear as well, but are specific to the
155 driver.
156
157What: /sys/bus/pci/slots/.../function[0-7]
158Date: March 2010
159KernelVersion: 2.6.35
160Contact: linux-pci@vger.kernel.org
161Description:
162 If PCI slot directories (as described above) are created,
163 and the physical slot is actually populated with a device,
164 symbolic links in the slot directory pointing to the
165 device's PCI functions are created as well.
166
167What: /sys/bus/pci/devices/.../slot
168Date: March 2010
169KernelVersion: 2.6.35
170Contact: linux-pci@vger.kernel.org
171Description:
172 If PCI slot directories (as described above) are created,
173 a symbolic link pointing to the slot directory will be
174 created as well.
175
136What: /sys/bus/pci/slots/.../module 176What: /sys/bus/pci/slots/.../module
137Date: June 2009 177Date: June 2009
138Contact: linux-pci@vger.kernel.org 178Contact: linux-pci@vger.kernel.org
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index fad93983bfed..941e939d1da9 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1011,6 +1011,39 @@ error:
1011 return retval; 1011 return retval;
1012} 1012}
1013 1013
1014static void pci_remove_slot_links(struct pci_dev *dev)
1015{
1016 char func[10];
1017 struct pci_slot *slot;
1018
1019 sysfs_remove_link(&dev->dev.kobj, "slot");
1020 list_for_each_entry(slot, &dev->bus->slots, list) {
1021 if (slot->number != PCI_SLOT(dev->devfn))
1022 continue;
1023 snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
1024 sysfs_remove_link(&slot->kobj, func);
1025 }
1026}
1027
1028static int pci_create_slot_links(struct pci_dev *dev)
1029{
1030 int result = 0;
1031 char func[10];
1032 struct pci_slot *slot;
1033
1034 list_for_each_entry(slot, &dev->bus->slots, list) {
1035 if (slot->number != PCI_SLOT(dev->devfn))
1036 continue;
1037 result = sysfs_create_link(&dev->dev.kobj, &slot->kobj, "slot");
1038 if (result)
1039 goto out;
1040 snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
1041 result = sysfs_create_link(&slot->kobj, &dev->dev.kobj, func);
1042 }
1043out:
1044 return result;
1045}
1046
1014int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) 1047int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
1015{ 1048{
1016 int retval; 1049 int retval;
@@ -1073,6 +1106,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
1073 if (retval) 1106 if (retval)
1074 goto err_vga_file; 1107 goto err_vga_file;
1075 1108
1109 pci_create_slot_links(pdev);
1110
1076 return 0; 1111 return 0;
1077 1112
1078err_vga_file: 1113err_vga_file:
@@ -1122,6 +1157,8 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
1122 if (!sysfs_initialized) 1157 if (!sysfs_initialized)
1123 return; 1158 return;
1124 1159
1160 pci_remove_slot_links(pdev);
1161
1125 pci_remove_capabilities_sysfs(pdev); 1162 pci_remove_capabilities_sysfs(pdev);
1126 1163
1127 if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE) 1164 if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
index 659eaa0fc48f..e0189cf7c558 100644
--- a/drivers/pci/slot.c
+++ b/drivers/pci/slot.c
@@ -97,6 +97,50 @@ static ssize_t cur_speed_read_file(struct pci_slot *slot, char *buf)
97 return bus_speed_read(slot->bus->cur_bus_speed, buf); 97 return bus_speed_read(slot->bus->cur_bus_speed, buf);
98} 98}
99 99
100static void remove_sysfs_files(struct pci_slot *slot)
101{
102 char func[10];
103 struct list_head *tmp;
104
105 list_for_each(tmp, &slot->bus->devices) {
106 struct pci_dev *dev = pci_dev_b(tmp);
107 if (PCI_SLOT(dev->devfn) != slot->number)
108 continue;
109 sysfs_remove_link(&dev->dev.kobj, "slot");
110
111 snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
112 sysfs_remove_link(&slot->kobj, func);
113 }
114}
115
116static int create_sysfs_files(struct pci_slot *slot)
117{
118 int result;
119 char func[10];
120 struct list_head *tmp;
121
122 list_for_each(tmp, &slot->bus->devices) {
123 struct pci_dev *dev = pci_dev_b(tmp);
124 if (PCI_SLOT(dev->devfn) != slot->number)
125 continue;
126
127 result = sysfs_create_link(&dev->dev.kobj, &slot->kobj, "slot");
128 if (result)
129 goto fail;
130
131 snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
132 result = sysfs_create_link(&slot->kobj, &dev->dev.kobj, func);
133 if (result)
134 goto fail;
135 }
136
137 return 0;
138
139fail:
140 remove_sysfs_files(slot);
141 return result;
142}
143
100static void pci_slot_release(struct kobject *kobj) 144static void pci_slot_release(struct kobject *kobj)
101{ 145{
102 struct pci_dev *dev; 146 struct pci_dev *dev;
@@ -109,6 +153,8 @@ static void pci_slot_release(struct kobject *kobj)
109 if (PCI_SLOT(dev->devfn) == slot->number) 153 if (PCI_SLOT(dev->devfn) == slot->number)
110 dev->slot = NULL; 154 dev->slot = NULL;
111 155
156 remove_sysfs_files(slot);
157
112 list_del(&slot->list); 158 list_del(&slot->list);
113 159
114 kfree(slot); 160 kfree(slot);
@@ -300,6 +346,8 @@ placeholder:
300 INIT_LIST_HEAD(&slot->list); 346 INIT_LIST_HEAD(&slot->list);
301 list_add(&slot->list, &parent->slots); 347 list_add(&slot->list, &parent->slots);
302 348
349 create_sysfs_files(slot);
350
303 list_for_each_entry(dev, &parent->devices, bus_list) 351 list_for_each_entry(dev, &parent->devices, bus_list)
304 if (PCI_SLOT(dev->devfn) == slot_nr) 352 if (PCI_SLOT(dev->devfn) == slot_nr)
305 dev->slot = slot; 353 dev->slot = slot;