1
2
3
4
5
6
7
8
9#include <linux/module.h>
10#include <linux/idr.h>
11#include <linux/slab.h>
12
13#include <linux/pci-epc.h>
14#include <linux/pci-epf.h>
15#include <linux/pci-ep-cfs.h>
16
17static DEFINE_IDR(functions_idr);
18static DEFINE_MUTEX(functions_mutex);
19static struct config_group *functions_group;
20static struct config_group *controllers_group;
21
22struct pci_epf_group {
23 struct config_group group;
24 struct pci_epf *epf;
25 int index;
26};
27
28struct pci_epc_group {
29 struct config_group group;
30 struct pci_epc *epc;
31 bool start;
32};
33
34static inline struct pci_epf_group *to_pci_epf_group(struct config_item *item)
35{
36 return container_of(to_config_group(item), struct pci_epf_group, group);
37}
38
39static inline struct pci_epc_group *to_pci_epc_group(struct config_item *item)
40{
41 return container_of(to_config_group(item), struct pci_epc_group, group);
42}
43
44static ssize_t pci_epc_start_store(struct config_item *item, const char *page,
45 size_t len)
46{
47 int ret;
48 bool start;
49 struct pci_epc *epc;
50 struct pci_epc_group *epc_group = to_pci_epc_group(item);
51
52 epc = epc_group->epc;
53
54 ret = kstrtobool(page, &start);
55 if (ret)
56 return ret;
57
58 if (!start) {
59 pci_epc_stop(epc);
60 epc_group->start = 0;
61 return len;
62 }
63
64 ret = pci_epc_start(epc);
65 if (ret) {
66 dev_err(&epc->dev, "failed to start endpoint controller\n");
67 return -EINVAL;
68 }
69
70 epc_group->start = start;
71
72 return len;
73}
74
75static ssize_t pci_epc_start_show(struct config_item *item, char *page)
76{
77 return sprintf(page, "%d\n",
78 to_pci_epc_group(item)->start);
79}
80
81CONFIGFS_ATTR(pci_epc_, start);
82
83static struct configfs_attribute *pci_epc_attrs[] = {
84 &pci_epc_attr_start,
85 NULL,
86};
87
88static int pci_epc_epf_link(struct config_item *epc_item,
89 struct config_item *epf_item)
90{
91 int ret;
92 struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
93 struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
94 struct pci_epc *epc = epc_group->epc;
95 struct pci_epf *epf = epf_group->epf;
96
97 ret = pci_epc_add_epf(epc, epf);
98 if (ret)
99 return ret;
100
101 ret = pci_epf_bind(epf);
102 if (ret) {
103 pci_epc_remove_epf(epc, epf);
104 return ret;
105 }
106
107 return 0;
108}
109
110static void pci_epc_epf_unlink(struct config_item *epc_item,
111 struct config_item *epf_item)
112{
113 struct pci_epc *epc;
114 struct pci_epf *epf;
115 struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
116 struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
117
118 WARN_ON_ONCE(epc_group->start);
119
120 epc = epc_group->epc;
121 epf = epf_group->epf;
122 pci_epf_unbind(epf);
123 pci_epc_remove_epf(epc, epf);
124}
125
126static struct configfs_item_operations pci_epc_item_ops = {
127 .allow_link = pci_epc_epf_link,
128 .drop_link = pci_epc_epf_unlink,
129};
130
131static const struct config_item_type pci_epc_type = {
132 .ct_item_ops = &pci_epc_item_ops,
133 .ct_attrs = pci_epc_attrs,
134 .ct_owner = THIS_MODULE,
135};
136
137struct config_group *pci_ep_cfs_add_epc_group(const char *name)
138{
139 int ret;
140 struct pci_epc *epc;
141 struct config_group *group;
142 struct pci_epc_group *epc_group;
143
144 epc_group = kzalloc(sizeof(*epc_group), GFP_KERNEL);
145 if (!epc_group) {
146 ret = -ENOMEM;
147 goto err;
148 }
149
150 group = &epc_group->group;
151
152 config_group_init_type_name(group, name, &pci_epc_type);
153 ret = configfs_register_group(controllers_group, group);
154 if (ret) {
155 pr_err("failed to register configfs group for %s\n", name);
156 goto err_register_group;
157 }
158
159 epc = pci_epc_get(name);
160 if (IS_ERR(epc)) {
161 ret = PTR_ERR(epc);
162 goto err_epc_get;
163 }
164
165 epc_group->epc = epc;
166
167 return group;
168
169err_epc_get:
170 configfs_unregister_group(group);
171
172err_register_group:
173 kfree(epc_group);
174
175err:
176 return ERR_PTR(ret);
177}
178EXPORT_SYMBOL(pci_ep_cfs_add_epc_group);
179
180void pci_ep_cfs_remove_epc_group(struct config_group *group)
181{
182 struct pci_epc_group *epc_group;
183
184 if (!group)
185 return;
186
187 epc_group = container_of(group, struct pci_epc_group, group);
188 pci_epc_put(epc_group->epc);
189 configfs_unregister_group(&epc_group->group);
190 kfree(epc_group);
191}
192EXPORT_SYMBOL(pci_ep_cfs_remove_epc_group);
193
194#define PCI_EPF_HEADER_R(_name) \
195static ssize_t pci_epf_##_name##_show(struct config_item *item, char *page) \
196{ \
197 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
198 if (WARN_ON_ONCE(!epf->header)) \
199 return -EINVAL; \
200 return sprintf(page, "0x%04x\n", epf->header->_name); \
201}
202
203#define PCI_EPF_HEADER_W_u32(_name) \
204static ssize_t pci_epf_##_name##_store(struct config_item *item, \
205 const char *page, size_t len) \
206{ \
207 u32 val; \
208 int ret; \
209 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
210 if (WARN_ON_ONCE(!epf->header)) \
211 return -EINVAL; \
212 ret = kstrtou32(page, 0, &val); \
213 if (ret) \
214 return ret; \
215 epf->header->_name = val; \
216 return len; \
217}
218
219#define PCI_EPF_HEADER_W_u16(_name) \
220static ssize_t pci_epf_##_name##_store(struct config_item *item, \
221 const char *page, size_t len) \
222{ \
223 u16 val; \
224 int ret; \
225 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
226 if (WARN_ON_ONCE(!epf->header)) \
227 return -EINVAL; \
228 ret = kstrtou16(page, 0, &val); \
229 if (ret) \
230 return ret; \
231 epf->header->_name = val; \
232 return len; \
233}
234
235#define PCI_EPF_HEADER_W_u8(_name) \
236static ssize_t pci_epf_##_name##_store(struct config_item *item, \
237 const char *page, size_t len) \
238{ \
239 u8 val; \
240 int ret; \
241 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
242 if (WARN_ON_ONCE(!epf->header)) \
243 return -EINVAL; \
244 ret = kstrtou8(page, 0, &val); \
245 if (ret) \
246 return ret; \
247 epf->header->_name = val; \
248 return len; \
249}
250
251static ssize_t pci_epf_msi_interrupts_store(struct config_item *item,
252 const char *page, size_t len)
253{
254 u8 val;
255 int ret;
256
257 ret = kstrtou8(page, 0, &val);
258 if (ret)
259 return ret;
260
261 to_pci_epf_group(item)->epf->msi_interrupts = val;
262
263 return len;
264}
265
266static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
267 char *page)
268{
269 return sprintf(page, "%d\n",
270 to_pci_epf_group(item)->epf->msi_interrupts);
271}
272
273static ssize_t pci_epf_msix_interrupts_store(struct config_item *item,
274 const char *page, size_t len)
275{
276 u16 val;
277 int ret;
278
279 ret = kstrtou16(page, 0, &val);
280 if (ret)
281 return ret;
282
283 to_pci_epf_group(item)->epf->msix_interrupts = val;
284
285 return len;
286}
287
288static ssize_t pci_epf_msix_interrupts_show(struct config_item *item,
289 char *page)
290{
291 return sprintf(page, "%d\n",
292 to_pci_epf_group(item)->epf->msix_interrupts);
293}
294
295PCI_EPF_HEADER_R(vendorid)
296PCI_EPF_HEADER_W_u16(vendorid)
297
298PCI_EPF_HEADER_R(deviceid)
299PCI_EPF_HEADER_W_u16(deviceid)
300
301PCI_EPF_HEADER_R(revid)
302PCI_EPF_HEADER_W_u8(revid)
303
304PCI_EPF_HEADER_R(progif_code)
305PCI_EPF_HEADER_W_u8(progif_code)
306
307PCI_EPF_HEADER_R(subclass_code)
308PCI_EPF_HEADER_W_u8(subclass_code)
309
310PCI_EPF_HEADER_R(baseclass_code)
311PCI_EPF_HEADER_W_u8(baseclass_code)
312
313PCI_EPF_HEADER_R(cache_line_size)
314PCI_EPF_HEADER_W_u8(cache_line_size)
315
316PCI_EPF_HEADER_R(subsys_vendor_id)
317PCI_EPF_HEADER_W_u16(subsys_vendor_id)
318
319PCI_EPF_HEADER_R(subsys_id)
320PCI_EPF_HEADER_W_u16(subsys_id)
321
322PCI_EPF_HEADER_R(interrupt_pin)
323PCI_EPF_HEADER_W_u8(interrupt_pin)
324
325CONFIGFS_ATTR(pci_epf_, vendorid);
326CONFIGFS_ATTR(pci_epf_, deviceid);
327CONFIGFS_ATTR(pci_epf_, revid);
328CONFIGFS_ATTR(pci_epf_, progif_code);
329CONFIGFS_ATTR(pci_epf_, subclass_code);
330CONFIGFS_ATTR(pci_epf_, baseclass_code);
331CONFIGFS_ATTR(pci_epf_, cache_line_size);
332CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
333CONFIGFS_ATTR(pci_epf_, subsys_id);
334CONFIGFS_ATTR(pci_epf_, interrupt_pin);
335CONFIGFS_ATTR(pci_epf_, msi_interrupts);
336CONFIGFS_ATTR(pci_epf_, msix_interrupts);
337
338static struct configfs_attribute *pci_epf_attrs[] = {
339 &pci_epf_attr_vendorid,
340 &pci_epf_attr_deviceid,
341 &pci_epf_attr_revid,
342 &pci_epf_attr_progif_code,
343 &pci_epf_attr_subclass_code,
344 &pci_epf_attr_baseclass_code,
345 &pci_epf_attr_cache_line_size,
346 &pci_epf_attr_subsys_vendor_id,
347 &pci_epf_attr_subsys_id,
348 &pci_epf_attr_interrupt_pin,
349 &pci_epf_attr_msi_interrupts,
350 &pci_epf_attr_msix_interrupts,
351 NULL,
352};
353
354static void pci_epf_release(struct config_item *item)
355{
356 struct pci_epf_group *epf_group = to_pci_epf_group(item);
357
358 mutex_lock(&functions_mutex);
359 idr_remove(&functions_idr, epf_group->index);
360 mutex_unlock(&functions_mutex);
361 pci_epf_destroy(epf_group->epf);
362 kfree(epf_group);
363}
364
365static struct configfs_item_operations pci_epf_ops = {
366 .release = pci_epf_release,
367};
368
369static const struct config_item_type pci_epf_type = {
370 .ct_item_ops = &pci_epf_ops,
371 .ct_attrs = pci_epf_attrs,
372 .ct_owner = THIS_MODULE,
373};
374
375static struct config_group *pci_epf_make(struct config_group *group,
376 const char *name)
377{
378 struct pci_epf_group *epf_group;
379 struct pci_epf *epf;
380 char *epf_name;
381 int index, err;
382
383 epf_group = kzalloc(sizeof(*epf_group), GFP_KERNEL);
384 if (!epf_group)
385 return ERR_PTR(-ENOMEM);
386
387 mutex_lock(&functions_mutex);
388 index = idr_alloc(&functions_idr, epf_group, 0, 0, GFP_KERNEL);
389 mutex_unlock(&functions_mutex);
390 if (index < 0) {
391 err = index;
392 goto free_group;
393 }
394
395 epf_group->index = index;
396
397 config_group_init_type_name(&epf_group->group, name, &pci_epf_type);
398
399 epf_name = kasprintf(GFP_KERNEL, "%s.%d",
400 group->cg_item.ci_name, epf_group->index);
401 if (!epf_name) {
402 err = -ENOMEM;
403 goto remove_idr;
404 }
405
406 epf = pci_epf_create(epf_name);
407 if (IS_ERR(epf)) {
408 pr_err("failed to create endpoint function device\n");
409 err = -EINVAL;
410 goto free_name;
411 }
412
413 epf_group->epf = epf;
414
415 kfree(epf_name);
416
417 return &epf_group->group;
418
419free_name:
420 kfree(epf_name);
421
422remove_idr:
423 mutex_lock(&functions_mutex);
424 idr_remove(&functions_idr, epf_group->index);
425 mutex_unlock(&functions_mutex);
426
427free_group:
428 kfree(epf_group);
429
430 return ERR_PTR(err);
431}
432
433static void pci_epf_drop(struct config_group *group, struct config_item *item)
434{
435 config_item_put(item);
436}
437
438static struct configfs_group_operations pci_epf_group_ops = {
439 .make_group = &pci_epf_make,
440 .drop_item = &pci_epf_drop,
441};
442
443static const struct config_item_type pci_epf_group_type = {
444 .ct_group_ops = &pci_epf_group_ops,
445 .ct_owner = THIS_MODULE,
446};
447
448struct config_group *pci_ep_cfs_add_epf_group(const char *name)
449{
450 struct config_group *group;
451
452 group = configfs_register_default_group(functions_group, name,
453 &pci_epf_group_type);
454 if (IS_ERR(group))
455 pr_err("failed to register configfs group for %s function\n",
456 name);
457
458 return group;
459}
460EXPORT_SYMBOL(pci_ep_cfs_add_epf_group);
461
462void pci_ep_cfs_remove_epf_group(struct config_group *group)
463{
464 if (IS_ERR_OR_NULL(group))
465 return;
466
467 configfs_unregister_default_group(group);
468}
469EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group);
470
471static const struct config_item_type pci_functions_type = {
472 .ct_owner = THIS_MODULE,
473};
474
475static const struct config_item_type pci_controllers_type = {
476 .ct_owner = THIS_MODULE,
477};
478
479static const struct config_item_type pci_ep_type = {
480 .ct_owner = THIS_MODULE,
481};
482
483static struct configfs_subsystem pci_ep_cfs_subsys = {
484 .su_group = {
485 .cg_item = {
486 .ci_namebuf = "pci_ep",
487 .ci_type = &pci_ep_type,
488 },
489 },
490 .su_mutex = __MUTEX_INITIALIZER(pci_ep_cfs_subsys.su_mutex),
491};
492
493static int __init pci_ep_cfs_init(void)
494{
495 int ret;
496 struct config_group *root = &pci_ep_cfs_subsys.su_group;
497
498 config_group_init(root);
499
500 ret = configfs_register_subsystem(&pci_ep_cfs_subsys);
501 if (ret) {
502 pr_err("Error %d while registering subsystem %s\n",
503 ret, root->cg_item.ci_namebuf);
504 goto err;
505 }
506
507 functions_group = configfs_register_default_group(root, "functions",
508 &pci_functions_type);
509 if (IS_ERR(functions_group)) {
510 ret = PTR_ERR(functions_group);
511 pr_err("Error %d while registering functions group\n",
512 ret);
513 goto err_functions_group;
514 }
515
516 controllers_group =
517 configfs_register_default_group(root, "controllers",
518 &pci_controllers_type);
519 if (IS_ERR(controllers_group)) {
520 ret = PTR_ERR(controllers_group);
521 pr_err("Error %d while registering controllers group\n",
522 ret);
523 goto err_controllers_group;
524 }
525
526 return 0;
527
528err_controllers_group:
529 configfs_unregister_default_group(functions_group);
530
531err_functions_group:
532 configfs_unregister_subsystem(&pci_ep_cfs_subsys);
533
534err:
535 return ret;
536}
537module_init(pci_ep_cfs_init);
538
539static void __exit pci_ep_cfs_exit(void)
540{
541 configfs_unregister_default_group(controllers_group);
542 configfs_unregister_default_group(functions_group);
543 configfs_unregister_subsystem(&pci_ep_cfs_subsys);
544}
545module_exit(pci_ep_cfs_exit);
546
547MODULE_DESCRIPTION("PCI EP CONFIGFS");
548MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
549MODULE_LICENSE("GPL v2");
550