File Index
Files and directories
Sign in
FILE

pci-ep-cfs.c

File preview with syntax highlighting.

linux-6.19.14/drivers/pci/endpoint/pci-ep-cfs.c C
  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 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 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 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(sizeof(*epc_group), GFP_KERNEL);
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 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\n");
569		return;
570	}
571
572	configfs_add_default_group(group, &epf_group->group);
573}
574
575static void pci_epf_cfs_add_sub_groups(struct pci_epf_group *epf_group)
576{
577	struct config_group *group;
578
579	group = pci_ep_cfs_add_primary_group(epf_group);
580	if (IS_ERR(group)) {
581		pr_err("failed to create 'primary' EPC interface\n");
582		return;
583	}
584
585	group = pci_ep_cfs_add_secondary_group(epf_group);
586	if (IS_ERR(group)) {
587		pr_err("failed to create 'secondary' EPC interface\n");
588		return;
589	}
590
591	pci_ep_cfs_add_type_group(epf_group);
592}
593
594static struct config_group *pci_epf_make(struct config_group *group,
595					 const char *name)
596{
597	struct pci_epf_group *epf_group;
598	struct pci_epf *epf;
599	char *epf_name;
600	int index, err;
601
602	epf_group = kzalloc(sizeof(*epf_group), GFP_KERNEL);
603	if (!epf_group)
604		return ERR_PTR(-ENOMEM);
605
606	mutex_lock(&functions_mutex);
607	index = idr_alloc(&functions_idr, epf_group, 0, 0, GFP_KERNEL);
608	mutex_unlock(&functions_mutex);
609	if (index < 0) {
610		err = index;
611		goto free_group;
612	}
613
614	epf_group->index = index;
615
616	config_group_init_type_name(&epf_group->group, name, &pci_epf_type);
617
618	epf_name = kasprintf(GFP_KERNEL, "%s.%d",
619			     group->cg_item.ci_name, epf_group->index);
620	if (!epf_name) {
621		err = -ENOMEM;
622		goto remove_idr;
623	}
624
625	epf = pci_epf_create(epf_name);
626	if (IS_ERR(epf)) {
627		pr_err("failed to create endpoint function device\n");
628		err = -EINVAL;
629		goto free_name;
630	}
631
632	epf->group = &epf_group->group;
633	epf_group->epf = epf;
634
635	kfree(epf_name);
636
637	pci_epf_cfs_add_sub_groups(epf_group);
638
639	return &epf_group->group;
640
641free_name:
642	kfree(epf_name);
643
644remove_idr:
645	mutex_lock(&functions_mutex);
646	idr_remove(&functions_idr, epf_group->index);
647	mutex_unlock(&functions_mutex);
648
649free_group:
650	kfree(epf_group);
651
652	return ERR_PTR(err);
653}
654
655static void pci_epf_drop(struct config_group *group, struct config_item *item)
656{
657	config_item_put(item);
658}
659
660static struct configfs_group_operations pci_epf_group_ops = {
661	.make_group     = &pci_epf_make,
662	.drop_item      = &pci_epf_drop,
663};
664
665static const struct config_item_type pci_epf_group_type = {
666	.ct_group_ops	= &pci_epf_group_ops,
667	.ct_owner	= THIS_MODULE,
668};
669
670struct config_group *pci_ep_cfs_add_epf_group(const char *name)
671{
672	struct config_group *group;
673
674	group = configfs_register_default_group(functions_group, name,
675						&pci_epf_group_type);
676	if (IS_ERR(group))
677		pr_err("failed to register configfs group for %s function\n",
678		       name);
679
680	return group;
681}
682EXPORT_SYMBOL(pci_ep_cfs_add_epf_group);
683
684void pci_ep_cfs_remove_epf_group(struct config_group *group)
685{
686	if (IS_ERR_OR_NULL(group))
687		return;
688
689	list_del(&group->group_entry);
690	configfs_unregister_default_group(group);
691}
692EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group);
693
694static const struct config_item_type pci_functions_type = {
695	.ct_owner	= THIS_MODULE,
696};
697
698static const struct config_item_type pci_controllers_type = {
699	.ct_owner	= THIS_MODULE,
700};
701
702static const struct config_item_type pci_ep_type = {
703	.ct_owner	= THIS_MODULE,
704};
705
706static struct configfs_subsystem pci_ep_cfs_subsys = {
707	.su_group = {
708		.cg_item = {
709			.ci_namebuf = "pci_ep",
710			.ci_type = &pci_ep_type,
711		},
712	},
713	.su_mutex = __MUTEX_INITIALIZER(pci_ep_cfs_subsys.su_mutex),
714};
715
716static int __init pci_ep_cfs_init(void)
717{
718	int ret;
719	struct config_group *root = &pci_ep_cfs_subsys.su_group;
720
721	config_group_init(root);
722
723	ret = configfs_register_subsystem(&pci_ep_cfs_subsys);
724	if (ret) {
725		pr_err("Error %d while registering subsystem %s\n",
726		       ret, root->cg_item.ci_namebuf);
727		goto err;
728	}
729
730	functions_group = configfs_register_default_group(root, "functions",
731							  &pci_functions_type);
732	if (IS_ERR(functions_group)) {
733		ret = PTR_ERR(functions_group);
734		pr_err("Error %d while registering functions group\n",
735		       ret);
736		goto err_functions_group;
737	}
738
739	controllers_group =
740		configfs_register_default_group(root, "controllers",
741						&pci_controllers_type);
742	if (IS_ERR(controllers_group)) {
743		ret = PTR_ERR(controllers_group);
744		pr_err("Error %d while registering controllers group\n",
745		       ret);
746		goto err_controllers_group;
747	}
748
749	return 0;
750
751err_controllers_group:
752	configfs_unregister_default_group(functions_group);
753
754err_functions_group:
755	configfs_unregister_subsystem(&pci_ep_cfs_subsys);
756
757err:
758	return ret;
759}
760module_init(pci_ep_cfs_init);
761
762static void __exit pci_ep_cfs_exit(void)
763{
764	configfs_unregister_default_group(controllers_group);
765	configfs_unregister_default_group(functions_group);
766	configfs_unregister_subsystem(&pci_ep_cfs_subsys);
767}
768module_exit(pci_ep_cfs_exit);
769
770MODULE_DESCRIPTION("PCI EP CONFIGFS");
771MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
~/ Read-only file preview.