1
2
3
4
5
6
7
8#include <linux/kobject.h>
9#include <linux/slab.h>
10#include <linux/module.h>
11#include <linux/pci.h>
12#include <linux/err.h>
13#include "pci.h"
14
15struct kset *pci_slots_kset;
16EXPORT_SYMBOL_GPL(pci_slots_kset);
17
18static ssize_t pci_slot_attr_show(struct kobject *kobj,
19 struct attribute *attr, char *buf)
20{
21 struct pci_slot *slot = to_pci_slot(kobj);
22 struct pci_slot_attribute *attribute = to_pci_slot_attr(attr);
23 return attribute->show ? attribute->show(slot, buf) : -EIO;
24}
25
26static ssize_t pci_slot_attr_store(struct kobject *kobj,
27 struct attribute *attr, const char *buf, size_t len)
28{
29 struct pci_slot *slot = to_pci_slot(kobj);
30 struct pci_slot_attribute *attribute = to_pci_slot_attr(attr);
31 return attribute->store ? attribute->store(slot, buf, len) : -EIO;
32}
33
34static const struct sysfs_ops pci_slot_sysfs_ops = {
35 .show = pci_slot_attr_show,
36 .store = pci_slot_attr_store,
37};
38
39static ssize_t address_read_file(struct pci_slot *slot, char *buf)
40{
41 if (slot->number == 0xff)
42 return sprintf(buf, "%04x:%02x\n",
43 pci_domain_nr(slot->bus),
44 slot->bus->number);
45 else
46 return sprintf(buf, "%04x:%02x:%02x\n",
47 pci_domain_nr(slot->bus),
48 slot->bus->number,
49 slot->number);
50}
51
52
53static const char *pci_bus_speed_strings[] = {
54 "33 MHz PCI",
55 "66 MHz PCI",
56 "66 MHz PCI-X",
57 "100 MHz PCI-X",
58 "133 MHz PCI-X",
59 NULL,
60 NULL,
61 NULL,
62 NULL,
63 "66 MHz PCI-X 266",
64 "100 MHz PCI-X 266",
65 "133 MHz PCI-X 266",
66 "Unknown AGP",
67 "1x AGP",
68 "2x AGP",
69 "4x AGP",
70 "8x AGP",
71 "66 MHz PCI-X 533",
72 "100 MHz PCI-X 533",
73 "133 MHz PCI-X 533",
74 "2.5 GT/s PCIe",
75 "5.0 GT/s PCIe",
76 "8.0 GT/s PCIe",
77};
78
79static ssize_t bus_speed_read(enum pci_bus_speed speed, char *buf)
80{
81 const char *speed_string;
82
83 if (speed < ARRAY_SIZE(pci_bus_speed_strings))
84 speed_string = pci_bus_speed_strings[speed];
85 else
86 speed_string = "Unknown";
87
88 return sprintf(buf, "%s\n", speed_string);
89}
90
91static ssize_t max_speed_read_file(struct pci_slot *slot, char *buf)
92{
93 return bus_speed_read(slot->bus->max_bus_speed, buf);
94}
95
96static ssize_t cur_speed_read_file(struct pci_slot *slot, char *buf)
97{
98 return bus_speed_read(slot->bus->cur_bus_speed, buf);
99}
100
101static void pci_slot_release(struct kobject *kobj)
102{
103 struct pci_dev *dev;
104 struct pci_slot *slot = to_pci_slot(kobj);
105
106 dev_dbg(&slot->bus->dev, "dev %02x, released physical slot %s\n",
107 slot->number, pci_slot_name(slot));
108
109 list_for_each_entry(dev, &slot->bus->devices, bus_list)
110 if (PCI_SLOT(dev->devfn) == slot->number)
111 dev->slot = NULL;
112
113 list_del(&slot->list);
114
115 kfree(slot);
116}
117
118static struct pci_slot_attribute pci_slot_attr_address =
119 __ATTR(address, S_IRUGO, address_read_file, NULL);
120static struct pci_slot_attribute pci_slot_attr_max_speed =
121 __ATTR(max_bus_speed, S_IRUGO, max_speed_read_file, NULL);
122static struct pci_slot_attribute pci_slot_attr_cur_speed =
123 __ATTR(cur_bus_speed, S_IRUGO, cur_speed_read_file, NULL);
124
125static struct attribute *pci_slot_default_attrs[] = {
126 &pci_slot_attr_address.attr,
127 &pci_slot_attr_max_speed.attr,
128 &pci_slot_attr_cur_speed.attr,
129 NULL,
130};
131
132static struct kobj_type pci_slot_ktype = {
133 .sysfs_ops = &pci_slot_sysfs_ops,
134 .release = &pci_slot_release,
135 .default_attrs = pci_slot_default_attrs,
136};
137
138static char *make_slot_name(const char *name)
139{
140 char *new_name;
141 int len, max, dup;
142
143 new_name = kstrdup(name, GFP_KERNEL);
144 if (!new_name)
145 return NULL;
146
147
148
149
150
151
152 len = strlen(name) + 2;
153 max = 1;
154 dup = 1;
155
156 for (;;) {
157 struct kobject *dup_slot;
158 dup_slot = kset_find_obj(pci_slots_kset, new_name);
159 if (!dup_slot)
160 break;
161 kobject_put(dup_slot);
162 if (dup == max) {
163 len++;
164 max *= 10;
165 kfree(new_name);
166 new_name = kmalloc(len, GFP_KERNEL);
167 if (!new_name)
168 break;
169 }
170 sprintf(new_name, "%s-%d", name, dup++);
171 }
172
173 return new_name;
174}
175
176static int rename_slot(struct pci_slot *slot, const char *name)
177{
178 int result = 0;
179 char *slot_name;
180
181 if (strcmp(pci_slot_name(slot), name) == 0)
182 return result;
183
184 slot_name = make_slot_name(name);
185 if (!slot_name)
186 return -ENOMEM;
187
188 result = kobject_rename(&slot->kobj, slot_name);
189 kfree(slot_name);
190
191 return result;
192}
193
194static struct pci_slot *get_slot(struct pci_bus *parent, int slot_nr)
195{
196 struct pci_slot *slot;
197
198
199
200 list_for_each_entry(slot, &parent->slots, list)
201 if (slot->number == slot_nr) {
202 kobject_get(&slot->kobj);
203 return slot;
204 }
205
206 return NULL;
207}
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
248 const char *name,
249 struct hotplug_slot *hotplug)
250{
251 struct pci_dev *dev;
252 struct pci_slot *slot;
253 int err = 0;
254 char *slot_name = NULL;
255
256 down_write(&pci_bus_sem);
257
258 if (slot_nr == -1)
259 goto placeholder;
260
261
262
263
264
265 slot = get_slot(parent, slot_nr);
266 if (slot) {
267 if (hotplug) {
268 if ((err = slot->hotplug ? -EBUSY : 0)
269 || (err = rename_slot(slot, name))) {
270 kobject_put(&slot->kobj);
271 slot = NULL;
272 goto err;
273 }
274 }
275 goto out;
276 }
277
278placeholder:
279 slot = kzalloc(sizeof(*slot), GFP_KERNEL);
280 if (!slot) {
281 err = -ENOMEM;
282 goto err;
283 }
284
285 slot->bus = parent;
286 slot->number = slot_nr;
287
288 slot->kobj.kset = pci_slots_kset;
289
290 slot_name = make_slot_name(name);
291 if (!slot_name) {
292 err = -ENOMEM;
293 goto err;
294 }
295
296 err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL,
297 "%s", slot_name);
298 if (err)
299 goto err;
300
301 INIT_LIST_HEAD(&slot->list);
302 list_add(&slot->list, &parent->slots);
303
304 list_for_each_entry(dev, &parent->devices, bus_list)
305 if (PCI_SLOT(dev->devfn) == slot_nr)
306 dev->slot = slot;
307
308 dev_dbg(&parent->dev, "dev %02x, created physical slot %s\n",
309 slot_nr, pci_slot_name(slot));
310
311out:
312 kfree(slot_name);
313 up_write(&pci_bus_sem);
314 return slot;
315err:
316 kfree(slot);
317 slot = ERR_PTR(err);
318 goto out;
319}
320EXPORT_SYMBOL_GPL(pci_create_slot);
321
322
323
324
325
326
327
328
329
330void pci_destroy_slot(struct pci_slot *slot)
331{
332 dev_dbg(&slot->bus->dev, "dev %02x, dec refcount to %d\n",
333 slot->number, atomic_read(&slot->kobj.kref.refcount) - 1);
334
335 down_write(&pci_bus_sem);
336 kobject_put(&slot->kobj);
337 up_write(&pci_bus_sem);
338}
339EXPORT_SYMBOL_GPL(pci_destroy_slot);
340
341#if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
342#include <linux/pci_hotplug.h>
343
344
345
346
347
348
349
350void pci_hp_create_module_link(struct pci_slot *pci_slot)
351{
352 struct hotplug_slot *slot = pci_slot->hotplug;
353 struct kobject *kobj = NULL;
354 int ret;
355
356 if (!slot || !slot->ops)
357 return;
358 kobj = kset_find_obj(module_kset, slot->ops->mod_name);
359 if (!kobj)
360 return;
361 ret = sysfs_create_link(&pci_slot->kobj, kobj, "module");
362 if (ret)
363 dev_err(&pci_slot->bus->dev, "Error creating sysfs link (%d)\n",
364 ret);
365 kobject_put(kobj);
366}
367EXPORT_SYMBOL_GPL(pci_hp_create_module_link);
368
369
370
371
372
373
374
375
376void pci_hp_remove_module_link(struct pci_slot *pci_slot)
377{
378 sysfs_remove_link(&pci_slot->kobj, "module");
379}
380EXPORT_SYMBOL_GPL(pci_hp_remove_module_link);
381#endif
382
383static int pci_slot_init(void)
384{
385 struct kset *pci_bus_kset;
386
387 pci_bus_kset = bus_get_kset(&pci_bus_type);
388 pci_slots_kset = kset_create_and_add("slots", NULL,
389 &pci_bus_kset->kobj);
390 if (!pci_slots_kset) {
391 printk(KERN_ERR "PCI: Slot initialization failure\n");
392 return -ENOMEM;
393 }
394 return 0;
395}
396
397subsys_initcall(pci_slot_init);
398