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_IFREG | S_IRUGO), address_read_file, NULL);
120static struct pci_slot_attribute pci_slot_attr_max_speed =
121 __ATTR(max_bus_speed, (S_IFREG | S_IRUGO), max_speed_read_file, NULL);
122static struct pci_slot_attribute pci_slot_attr_cur_speed =
123 __ATTR(cur_bus_speed, (S_IFREG | 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
330
331void pci_renumber_slot(struct pci_slot *slot, int slot_nr)
332{
333 struct pci_slot *tmp;
334
335 down_write(&pci_bus_sem);
336
337 list_for_each_entry(tmp, &slot->bus->slots, list) {
338 WARN_ON(tmp->number == slot_nr);
339 goto out;
340 }
341
342 slot->number = slot_nr;
343out:
344 up_write(&pci_bus_sem);
345}
346EXPORT_SYMBOL_GPL(pci_renumber_slot);
347
348
349
350
351
352
353
354
355
356void pci_destroy_slot(struct pci_slot *slot)
357{
358 dev_dbg(&slot->bus->dev, "dev %02x, dec refcount to %d\n",
359 slot->number, atomic_read(&slot->kobj.kref.refcount) - 1);
360
361 down_write(&pci_bus_sem);
362 kobject_put(&slot->kobj);
363 up_write(&pci_bus_sem);
364}
365EXPORT_SYMBOL_GPL(pci_destroy_slot);
366
367#if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
368#include <linux/pci_hotplug.h>
369
370
371
372
373
374
375
376void pci_hp_create_module_link(struct pci_slot *pci_slot)
377{
378 struct hotplug_slot *slot = pci_slot->hotplug;
379 struct kobject *kobj = NULL;
380 int no_warn;
381
382 if (!slot || !slot->ops)
383 return;
384 kobj = kset_find_obj(module_kset, slot->ops->mod_name);
385 if (!kobj)
386 return;
387 no_warn = sysfs_create_link(&pci_slot->kobj, kobj, "module");
388 kobject_put(kobj);
389}
390EXPORT_SYMBOL_GPL(pci_hp_create_module_link);
391
392
393
394
395
396
397
398
399void pci_hp_remove_module_link(struct pci_slot *pci_slot)
400{
401 sysfs_remove_link(&pci_slot->kobj, "module");
402}
403EXPORT_SYMBOL_GPL(pci_hp_remove_module_link);
404#endif
405
406static int pci_slot_init(void)
407{
408 struct kset *pci_bus_kset;
409
410 pci_bus_kset = bus_get_kset(&pci_bus_type);
411 pci_slots_kset = kset_create_and_add("slots", NULL,
412 &pci_bus_kset->kobj);
413 if (!pci_slots_kset) {
414 printk(KERN_ERR "PCI: Slot initialization failure\n");
415 return -ENOMEM;
416 }
417 return 0;
418}
419
420subsys_initcall(pci_slot_init);
421