Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * configfs to configure the PCI endpoint
4 *
5 * Copyright (C) 2017 Texas Instruments
6 * Author: Kishon Vijay Abraham I <kishon@ti.com>
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 config_group primary_epc_group;
25 struct config_group secondary_epc_group;
26 struct pci_epf *epf;
27 int index;
28};
29
30struct pci_epc_group {
31 struct config_group group;
32 struct pci_epc *epc;
33 bool start;
34};
35
36static inline struct pci_epf_group *to_pci_epf_group(struct config_item *item)
37{
38 return container_of(to_config_group(item), struct pci_epf_group, group);
39}
40
41static inline struct pci_epc_group *to_pci_epc_group(struct config_item *item)
42{
43 return container_of(to_config_group(item), struct pci_epc_group, group);
44}
45
46static int pci_secondary_epc_epf_link(struct config_item *epf_item,
47 struct config_item *epc_item)
48{
49 int ret;
50 struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent);
51 struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
52 struct pci_epc *epc = epc_group->epc;
53 struct pci_epf *epf = epf_group->epf;
54
55 ret = pci_epc_add_epf(epc, epf, SECONDARY_INTERFACE);
56 if (ret)
57 return ret;
58
59 ret = pci_epf_bind(epf);
60 if (ret) {
61 pci_epc_remove_epf(epc, epf, SECONDARY_INTERFACE);
62 return ret;
63 }
64
65 /* Send any pending EPC initialization complete to the EPF driver */
66 pci_epc_notify_pending_init(epc, epf);
67
68 return 0;
69}
70
71static void pci_secondary_epc_epf_unlink(struct config_item *epf_item,
72 struct config_item *epc_item)
73{
74 struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent);
75 struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
76 struct pci_epc *epc;
77 struct pci_epf *epf;
78
79 WARN_ON_ONCE(epc_group->start);
80
81 epc = epc_group->epc;
82 epf = epf_group->epf;
83 pci_epf_unbind(epf);
84 pci_epc_remove_epf(epc, epf, SECONDARY_INTERFACE);
85}
86
87static const struct configfs_item_operations pci_secondary_epc_item_ops = {
88 .allow_link = pci_secondary_epc_epf_link,
89 .drop_link = pci_secondary_epc_epf_unlink,
90};
91
92static const struct config_item_type pci_secondary_epc_type = {
93 .ct_item_ops = &pci_secondary_epc_item_ops,
94 .ct_owner = THIS_MODULE,
95};
96
97static struct config_group
98*pci_ep_cfs_add_secondary_group(struct pci_epf_group *epf_group)
99{
100 struct config_group *secondary_epc_group;
101
102 secondary_epc_group = &epf_group->secondary_epc_group;
103 config_group_init_type_name(secondary_epc_group, "secondary",
104 &pci_secondary_epc_type);
105 configfs_add_default_group(secondary_epc_group, &epf_group->group);
106
107 return secondary_epc_group;
108}
109
110static int pci_primary_epc_epf_link(struct config_item *epf_item,
111 struct config_item *epc_item)
112{
113 int ret;
114 struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent);
115 struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
116 struct pci_epc *epc = epc_group->epc;
117 struct pci_epf *epf = epf_group->epf;
118
119 ret = pci_epc_add_epf(epc, epf, PRIMARY_INTERFACE);
120 if (ret)
121 return ret;
122
123 ret = pci_epf_bind(epf);
124 if (ret) {
125 pci_epc_remove_epf(epc, epf, PRIMARY_INTERFACE);
126 return ret;
127 }
128
129 /* Send any pending EPC initialization complete to the EPF driver */
130 pci_epc_notify_pending_init(epc, epf);
131
132 return 0;
133}
134
135static void pci_primary_epc_epf_unlink(struct config_item *epf_item,
136 struct config_item *epc_item)
137{
138 struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent);
139 struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
140 struct pci_epc *epc;
141 struct pci_epf *epf;
142
143 WARN_ON_ONCE(epc_group->start);
144
145 epc = epc_group->epc;
146 epf = epf_group->epf;
147 pci_epf_unbind(epf);
148 pci_epc_remove_epf(epc, epf, PRIMARY_INTERFACE);
149}
150
151static const struct configfs_item_operations pci_primary_epc_item_ops = {
152 .allow_link = pci_primary_epc_epf_link,
153 .drop_link = pci_primary_epc_epf_unlink,
154};
155
156static const struct config_item_type pci_primary_epc_type = {
157 .ct_item_ops = &pci_primary_epc_item_ops,
158 .ct_owner = THIS_MODULE,
159};
160
161static struct config_group
162*pci_ep_cfs_add_primary_group(struct pci_epf_group *epf_group)
163{
164 struct config_group *primary_epc_group = &epf_group->primary_epc_group;
165
166 config_group_init_type_name(primary_epc_group, "primary",
167 &pci_primary_epc_type);
168 configfs_add_default_group(primary_epc_group, &epf_group->group);
169
170 return primary_epc_group;
171}
172
173static ssize_t pci_epc_start_store(struct config_item *item, const char *page,
174 size_t len)
175{
176 int ret;
177 bool start;
178 struct pci_epc *epc;
179 struct pci_epc_group *epc_group = to_pci_epc_group(item);
180
181 epc = epc_group->epc;
182
183 if (kstrtobool(page, &start) < 0)
184 return -EINVAL;
185
186 if (start == epc_group->start)
187 return -EALREADY;
188
189 if (!start) {
190 pci_epc_stop(epc);
191 epc_group->start = 0;
192 return len;
193 }
194
195 ret = pci_epc_start(epc);
196 if (ret) {
197 dev_err(&epc->dev, "failed to start endpoint controller\n");
198 return -EINVAL;
199 }
200
201 epc_group->start = start;
202
203 return len;
204}
205
206static ssize_t pci_epc_start_show(struct config_item *item, char *page)
207{
208 return sysfs_emit(page, "%d\n", to_pci_epc_group(item)->start);
209}
210
211CONFIGFS_ATTR(pci_epc_, start);
212
213static struct configfs_attribute *pci_epc_attrs[] = {
214 &pci_epc_attr_start,
215 NULL,
216};
217
218static int pci_epc_epf_link(struct config_item *epc_item,
219 struct config_item *epf_item)
220{
221 int ret;
222 struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
223 struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
224 struct pci_epc *epc = epc_group->epc;
225 struct pci_epf *epf = epf_group->epf;
226
227 ret = pci_epc_add_epf(epc, epf, PRIMARY_INTERFACE);
228 if (ret)
229 return ret;
230
231 ret = pci_epf_bind(epf);
232 if (ret) {
233 pci_epc_remove_epf(epc, epf, PRIMARY_INTERFACE);
234 return ret;
235 }
236
237 /* Send any pending EPC initialization complete to the EPF driver */
238 pci_epc_notify_pending_init(epc, epf);
239
240 return 0;
241}
242
243static void pci_epc_epf_unlink(struct config_item *epc_item,
244 struct config_item *epf_item)
245{
246 struct pci_epc *epc;
247 struct pci_epf *epf;
248 struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
249 struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
250
251 WARN_ON_ONCE(epc_group->start);
252
253 epc = epc_group->epc;
254 epf = epf_group->epf;
255 pci_epf_unbind(epf);
256 pci_epc_remove_epf(epc, epf, PRIMARY_INTERFACE);
257}
258
259static const struct configfs_item_operations pci_epc_item_ops = {
260 .allow_link = pci_epc_epf_link,
261 .drop_link = pci_epc_epf_unlink,
262};
263
264static const struct config_item_type pci_epc_type = {
265 .ct_item_ops = &pci_epc_item_ops,
266 .ct_attrs = pci_epc_attrs,
267 .ct_owner = THIS_MODULE,
268};
269
270struct config_group *pci_ep_cfs_add_epc_group(const char *name)
271{
272 int ret;
273 struct pci_epc *epc;
274 struct config_group *group;
275 struct pci_epc_group *epc_group;
276
277 epc_group = kzalloc_obj(*epc_group);
278 if (!epc_group) {
279 ret = -ENOMEM;
280 goto err;
281 }
282
283 group = &epc_group->group;
284
285 config_group_init_type_name(group, name, &pci_epc_type);
286 ret = configfs_register_group(controllers_group, group);
287 if (ret) {
288 pr_err("failed to register configfs group for %s\n", name);
289 goto err_register_group;
290 }
291
292 epc = pci_epc_get(name);
293 if (IS_ERR(epc)) {
294 ret = PTR_ERR(epc);
295 goto err_epc_get;
296 }
297
298 epc_group->epc = epc;
299
300 return group;
301
302err_epc_get:
303 configfs_unregister_group(group);
304
305err_register_group:
306 kfree(epc_group);
307
308err:
309 return ERR_PTR(ret);
310}
311EXPORT_SYMBOL(pci_ep_cfs_add_epc_group);
312
313void pci_ep_cfs_remove_epc_group(struct config_group *group)
314{
315 struct pci_epc_group *epc_group;
316
317 if (!group)
318 return;
319
320 epc_group = container_of(group, struct pci_epc_group, group);
321 pci_epc_put(epc_group->epc);
322 configfs_unregister_group(&epc_group->group);
323 kfree(epc_group);
324}
325EXPORT_SYMBOL(pci_ep_cfs_remove_epc_group);
326
327#define PCI_EPF_HEADER_R(_name) \
328static ssize_t pci_epf_##_name##_show(struct config_item *item, char *page) \
329{ \
330 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
331 if (WARN_ON_ONCE(!epf->header)) \
332 return -EINVAL; \
333 return sysfs_emit(page, "0x%04x\n", epf->header->_name); \
334}
335
336#define PCI_EPF_HEADER_W_u32(_name) \
337static ssize_t pci_epf_##_name##_store(struct config_item *item, \
338 const char *page, size_t len) \
339{ \
340 u32 val; \
341 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
342 if (WARN_ON_ONCE(!epf->header)) \
343 return -EINVAL; \
344 if (kstrtou32(page, 0, &val) < 0) \
345 return -EINVAL; \
346 epf->header->_name = val; \
347 return len; \
348}
349
350#define PCI_EPF_HEADER_W_u16(_name) \
351static ssize_t pci_epf_##_name##_store(struct config_item *item, \
352 const char *page, size_t len) \
353{ \
354 u16 val; \
355 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
356 if (WARN_ON_ONCE(!epf->header)) \
357 return -EINVAL; \
358 if (kstrtou16(page, 0, &val) < 0) \
359 return -EINVAL; \
360 epf->header->_name = val; \
361 return len; \
362}
363
364#define PCI_EPF_HEADER_W_u8(_name) \
365static ssize_t pci_epf_##_name##_store(struct config_item *item, \
366 const char *page, size_t len) \
367{ \
368 u8 val; \
369 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
370 if (WARN_ON_ONCE(!epf->header)) \
371 return -EINVAL; \
372 if (kstrtou8(page, 0, &val) < 0) \
373 return -EINVAL; \
374 epf->header->_name = val; \
375 return len; \
376}
377
378static ssize_t pci_epf_msi_interrupts_store(struct config_item *item,
379 const char *page, size_t len)
380{
381 u8 val;
382
383 if (kstrtou8(page, 0, &val) < 0)
384 return -EINVAL;
385
386 to_pci_epf_group(item)->epf->msi_interrupts = val;
387
388 return len;
389}
390
391static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
392 char *page)
393{
394 return sysfs_emit(page, "%d\n",
395 to_pci_epf_group(item)->epf->msi_interrupts);
396}
397
398static ssize_t pci_epf_msix_interrupts_store(struct config_item *item,
399 const char *page, size_t len)
400{
401 u16 val;
402
403 if (kstrtou16(page, 0, &val) < 0)
404 return -EINVAL;
405
406 to_pci_epf_group(item)->epf->msix_interrupts = val;
407
408 return len;
409}
410
411static ssize_t pci_epf_msix_interrupts_show(struct config_item *item,
412 char *page)
413{
414 return sysfs_emit(page, "%d\n",
415 to_pci_epf_group(item)->epf->msix_interrupts);
416}
417
418PCI_EPF_HEADER_R(vendorid)
419PCI_EPF_HEADER_W_u16(vendorid)
420
421PCI_EPF_HEADER_R(deviceid)
422PCI_EPF_HEADER_W_u16(deviceid)
423
424PCI_EPF_HEADER_R(revid)
425PCI_EPF_HEADER_W_u8(revid)
426
427PCI_EPF_HEADER_R(progif_code)
428PCI_EPF_HEADER_W_u8(progif_code)
429
430PCI_EPF_HEADER_R(subclass_code)
431PCI_EPF_HEADER_W_u8(subclass_code)
432
433PCI_EPF_HEADER_R(baseclass_code)
434PCI_EPF_HEADER_W_u8(baseclass_code)
435
436PCI_EPF_HEADER_R(cache_line_size)
437PCI_EPF_HEADER_W_u8(cache_line_size)
438
439PCI_EPF_HEADER_R(subsys_vendor_id)
440PCI_EPF_HEADER_W_u16(subsys_vendor_id)
441
442PCI_EPF_HEADER_R(subsys_id)
443PCI_EPF_HEADER_W_u16(subsys_id)
444
445PCI_EPF_HEADER_R(interrupt_pin)
446PCI_EPF_HEADER_W_u8(interrupt_pin)
447
448CONFIGFS_ATTR(pci_epf_, vendorid);
449CONFIGFS_ATTR(pci_epf_, deviceid);
450CONFIGFS_ATTR(pci_epf_, revid);
451CONFIGFS_ATTR(pci_epf_, progif_code);
452CONFIGFS_ATTR(pci_epf_, subclass_code);
453CONFIGFS_ATTR(pci_epf_, baseclass_code);
454CONFIGFS_ATTR(pci_epf_, cache_line_size);
455CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
456CONFIGFS_ATTR(pci_epf_, subsys_id);
457CONFIGFS_ATTR(pci_epf_, interrupt_pin);
458CONFIGFS_ATTR(pci_epf_, msi_interrupts);
459CONFIGFS_ATTR(pci_epf_, msix_interrupts);
460
461static struct configfs_attribute *pci_epf_attrs[] = {
462 &pci_epf_attr_vendorid,
463 &pci_epf_attr_deviceid,
464 &pci_epf_attr_revid,
465 &pci_epf_attr_progif_code,
466 &pci_epf_attr_subclass_code,
467 &pci_epf_attr_baseclass_code,
468 &pci_epf_attr_cache_line_size,
469 &pci_epf_attr_subsys_vendor_id,
470 &pci_epf_attr_subsys_id,
471 &pci_epf_attr_interrupt_pin,
472 &pci_epf_attr_msi_interrupts,
473 &pci_epf_attr_msix_interrupts,
474 NULL,
475};
476
477static int pci_epf_vepf_link(struct config_item *epf_pf_item,
478 struct config_item *epf_vf_item)
479{
480 struct pci_epf_group *epf_vf_group = to_pci_epf_group(epf_vf_item);
481 struct pci_epf_group *epf_pf_group = to_pci_epf_group(epf_pf_item);
482 struct pci_epf *epf_pf = epf_pf_group->epf;
483 struct pci_epf *epf_vf = epf_vf_group->epf;
484
485 return pci_epf_add_vepf(epf_pf, epf_vf);
486}
487
488static void pci_epf_vepf_unlink(struct config_item *epf_pf_item,
489 struct config_item *epf_vf_item)
490{
491 struct pci_epf_group *epf_vf_group = to_pci_epf_group(epf_vf_item);
492 struct pci_epf_group *epf_pf_group = to_pci_epf_group(epf_pf_item);
493 struct pci_epf *epf_pf = epf_pf_group->epf;
494 struct pci_epf *epf_vf = epf_vf_group->epf;
495
496 pci_epf_remove_vepf(epf_pf, epf_vf);
497}
498
499static void pci_epf_release(struct config_item *item)
500{
501 struct pci_epf_group *epf_group = to_pci_epf_group(item);
502
503 mutex_lock(&functions_mutex);
504 idr_remove(&functions_idr, epf_group->index);
505 mutex_unlock(&functions_mutex);
506 pci_epf_destroy(epf_group->epf);
507 kfree(epf_group);
508}
509
510static const struct configfs_item_operations pci_epf_ops = {
511 .allow_link = pci_epf_vepf_link,
512 .drop_link = pci_epf_vepf_unlink,
513 .release = pci_epf_release,
514};
515
516static const struct config_item_type pci_epf_type = {
517 .ct_item_ops = &pci_epf_ops,
518 .ct_attrs = pci_epf_attrs,
519 .ct_owner = THIS_MODULE,
520};
521
522/**
523 * pci_epf_type_add_cfs() - Help function drivers to expose function specific
524 * attributes in configfs
525 * @epf: the EPF device that has to be configured using configfs
526 * @group: the parent configfs group (corresponding to entries in
527 * pci_epf_device_id)
528 *
529 * Invoke to expose function specific attributes in configfs.
530 *
531 * Return: A pointer to a config_group structure or NULL if the function driver
532 * does not have anything to expose (attributes configured by user) or if
533 * the function driver does not implement the add_cfs() method.
534 *
535 * Returns an error pointer if this function is called for an unbound EPF device
536 * or if the EPF driver add_cfs() method fails.
537 */
538static struct config_group *pci_epf_type_add_cfs(struct pci_epf *epf,
539 struct config_group *group)
540{
541 struct config_group *epf_type_group;
542
543 if (!epf->driver) {
544 dev_err(&epf->dev, "epf device not bound to driver\n");
545 return ERR_PTR(-ENODEV);
546 }
547
548 if (!epf->driver->ops->add_cfs)
549 return NULL;
550
551 mutex_lock(&epf->lock);
552 epf_type_group = epf->driver->ops->add_cfs(epf, group);
553 mutex_unlock(&epf->lock);
554
555 return epf_type_group;
556}
557
558static void pci_ep_cfs_add_type_group(struct pci_epf_group *epf_group)
559{
560 struct config_group *group;
561
562 group = pci_epf_type_add_cfs(epf_group->epf, &epf_group->group);
563 if (!group)
564 return;
565
566 if (IS_ERR(group)) {
567 dev_err(&epf_group->epf->dev,
568 "failed to create epf type specific attributes: %pe\n",
569 group);
570 return;
571 }
572
573 configfs_add_default_group(group, &epf_group->group);
574}
575
576static void pci_epf_cfs_add_sub_groups(struct pci_epf_group *epf_group)
577{
578 struct config_group *group;
579
580 group = pci_ep_cfs_add_primary_group(epf_group);
581 if (IS_ERR(group)) {
582 dev_err(&epf_group->epf->dev,
583 "failed to create 'primary' EPC interface: %pe\n",
584 group);
585 return;
586 }
587
588 group = pci_ep_cfs_add_secondary_group(epf_group);
589 if (IS_ERR(group)) {
590 dev_err(&epf_group->epf->dev,
591 "failed to create 'secondary' EPC interface: %pe\n",
592 group);
593 return;
594 }
595
596 pci_ep_cfs_add_type_group(epf_group);
597}
598
599static struct config_group *pci_epf_make(struct config_group *group,
600 const char *name)
601{
602 struct pci_epf_group *epf_group;
603 struct pci_epf *epf;
604 char *epf_name;
605 int index, err;
606
607 epf_group = kzalloc_obj(*epf_group);
608 if (!epf_group)
609 return ERR_PTR(-ENOMEM);
610
611 mutex_lock(&functions_mutex);
612 index = idr_alloc(&functions_idr, epf_group, 0, 0, GFP_KERNEL);
613 mutex_unlock(&functions_mutex);
614 if (index < 0) {
615 err = index;
616 goto free_group;
617 }
618
619 epf_group->index = index;
620
621 config_group_init_type_name(&epf_group->group, name, &pci_epf_type);
622
623 epf_name = kasprintf(GFP_KERNEL, "%s.%d",
624 group->cg_item.ci_name, epf_group->index);
625 if (!epf_name) {
626 err = -ENOMEM;
627 goto remove_idr;
628 }
629
630 epf = pci_epf_create(epf_name);
631 if (IS_ERR(epf)) {
632 err = PTR_ERR(epf);
633 pr_err("failed to create endpoint function device (%s): %d\n",
634 epf_name, err);
635 goto free_name;
636 }
637
638 epf->group = &epf_group->group;
639 epf_group->epf = epf;
640
641 kfree(epf_name);
642
643 pci_epf_cfs_add_sub_groups(epf_group);
644
645 return &epf_group->group;
646
647free_name:
648 kfree(epf_name);
649
650remove_idr:
651 mutex_lock(&functions_mutex);
652 idr_remove(&functions_idr, epf_group->index);
653 mutex_unlock(&functions_mutex);
654
655free_group:
656 kfree(epf_group);
657
658 return ERR_PTR(err);
659}
660
661static void pci_epf_drop(struct config_group *group, struct config_item *item)
662{
663 config_item_put(item);
664}
665
666static const struct configfs_group_operations pci_epf_group_ops = {
667 .make_group = &pci_epf_make,
668 .drop_item = &pci_epf_drop,
669};
670
671static const struct config_item_type pci_epf_group_type = {
672 .ct_group_ops = &pci_epf_group_ops,
673 .ct_owner = THIS_MODULE,
674};
675
676struct config_group *pci_ep_cfs_add_epf_group(const char *name)
677{
678 struct config_group *group;
679
680 group = configfs_register_default_group(functions_group, name,
681 &pci_epf_group_type);
682 if (IS_ERR(group))
683 pr_err("failed to register configfs group for %s function: %pe\n",
684 name, group);
685
686 return group;
687}
688EXPORT_SYMBOL(pci_ep_cfs_add_epf_group);
689
690void pci_ep_cfs_remove_epf_group(struct config_group *group)
691{
692 if (IS_ERR_OR_NULL(group))
693 return;
694
695 list_del(&group->group_entry);
696 configfs_unregister_default_group(group);
697}
698EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group);
699
700static const struct config_item_type pci_functions_type = {
701 .ct_owner = THIS_MODULE,
702};
703
704static const struct config_item_type pci_controllers_type = {
705 .ct_owner = THIS_MODULE,
706};
707
708static const struct config_item_type pci_ep_type = {
709 .ct_owner = THIS_MODULE,
710};
711
712static struct configfs_subsystem pci_ep_cfs_subsys = {
713 .su_group = {
714 .cg_item = {
715 .ci_namebuf = "pci_ep",
716 .ci_type = &pci_ep_type,
717 },
718 },
719 .su_mutex = __MUTEX_INITIALIZER(pci_ep_cfs_subsys.su_mutex),
720};
721
722static int __init pci_ep_cfs_init(void)
723{
724 int ret;
725 struct config_group *root = &pci_ep_cfs_subsys.su_group;
726
727 config_group_init(root);
728
729 ret = configfs_register_subsystem(&pci_ep_cfs_subsys);
730 if (ret) {
731 pr_err("Error %d while registering subsystem %s\n",
732 ret, root->cg_item.ci_namebuf);
733 goto err;
734 }
735
736 functions_group = configfs_register_default_group(root, "functions",
737 &pci_functions_type);
738 if (IS_ERR(functions_group)) {
739 ret = PTR_ERR(functions_group);
740 pr_err("Error %d while registering functions group\n",
741 ret);
742 goto err_functions_group;
743 }
744
745 controllers_group =
746 configfs_register_default_group(root, "controllers",
747 &pci_controllers_type);
748 if (IS_ERR(controllers_group)) {
749 ret = PTR_ERR(controllers_group);
750 pr_err("Error %d while registering controllers group\n",
751 ret);
752 goto err_controllers_group;
753 }
754
755 return 0;
756
757err_controllers_group:
758 configfs_unregister_default_group(functions_group);
759
760err_functions_group:
761 configfs_unregister_subsystem(&pci_ep_cfs_subsys);
762
763err:
764 return ret;
765}
766module_init(pci_ep_cfs_init);
767
768static void __exit pci_ep_cfs_exit(void)
769{
770 configfs_unregister_default_group(controllers_group);
771 configfs_unregister_default_group(functions_group);
772 configfs_unregister_subsystem(&pci_ep_cfs_subsys);
773}
774module_exit(pci_ep_cfs_exit);
775
776MODULE_DESCRIPTION("PCI EP CONFIGFS");
777MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");