brintos

brintos / linux-shallow public Read only

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