aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/slot.c
diff options
context:
space:
mode:
authorAlex Chiang <achiang@hp.com>2010-03-08 12:24:29 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-05-11 15:01:07 -0400
commit75568f8094eb0333e9c2109b23cbc8b82d318a3c (patch)
treebdbd169b2220e067bc03f7445e2471aa2f8499a7 /drivers/pci/slot.c
parentfc2a093e7ad23e935aa29e349bc27173c92f1a95 (diff)
PCI: create function symlinks in /sys/bus/pci/slots/N/
Create convenience symlinks in sysfs, linking slots to device functions, and vice versa. These links make it easier for users to figure out which devices actually live in what slots. For example: sapphire:/sys/bus/pci/slots # ls 1 10 2 3 4 5 6 7 8 9 sapphire:/sys/bus/pci/slots # ls -l 3 total 0 -r--r--r-- 1 root root 65536 Aug 18 14:10 address lrwxrwxrwx 1 root root 0 Aug 18 14:10 function0 -> ../../../../devices/pci0000:23/0000:23:01.0 lrwxrwxrwx 1 root root 0 Aug 18 14:10 function1 -> ../../../../devices/pci0000:23/0000:23:01.1 sapphire:/sys/bus/pci/slots # ls -l 3/function0/slot lrwxrwxrwx 1 root root 0 Aug 18 14:13 3/function0/slot -> ../../../bus/pci/slots/3 The original form of this patch was written by Matthew Wilcox, and was enhanced to include links from the sysfs slots/ directory pointing back at the device functions. Cc: willy@linux.intel.com Signed-off-by: Alex Chiang <achiang@hp.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/slot.c')
-rw-r--r--drivers/pci/slot.c48
1 files changed, 48 insertions, 0 deletions
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;