cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pci-ep-cfs.c (18402B)


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