pci-ep-cfs.c 18 KB

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