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