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