dfl.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Driver for FPGA Device Feature List (DFL) Support
  4. *
  5. * Copyright (C) 2017-2018 Intel Corporation, Inc.
  6. *
  7. * Authors:
  8. * Kang Luwei <luwei.kang@intel.com>
  9. * Zhang Yi <yi.z.zhang@intel.com>
  10. * Wu Hao <hao.wu@intel.com>
  11. * Xiao Guangrong <guangrong.xiao@linux.intel.com>
  12. */
  13. #include <linux/module.h>
  14. #include "dfl.h"
  15. static DEFINE_MUTEX(dfl_id_mutex);
  16. /*
  17. * when adding a new feature dev support in DFL framework, it's required to
  18. * add a new item in enum dfl_id_type and provide related information in below
  19. * dfl_devs table which is indexed by dfl_id_type, e.g. name string used for
  20. * platform device creation (define name strings in dfl.h, as they could be
  21. * reused by platform device drivers).
  22. *
  23. * if the new feature dev needs chardev support, then it's required to add
  24. * a new item in dfl_chardevs table and configure dfl_devs[i].devt_type as
  25. * index to dfl_chardevs table. If no chardev support just set devt_type
  26. * as one invalid index (DFL_FPGA_DEVT_MAX).
  27. */
  28. enum dfl_id_type {
  29. FME_ID, /* fme id allocation and mapping */
  30. PORT_ID, /* port id allocation and mapping */
  31. DFL_ID_MAX,
  32. };
  33. enum dfl_fpga_devt_type {
  34. DFL_FPGA_DEVT_FME,
  35. DFL_FPGA_DEVT_PORT,
  36. DFL_FPGA_DEVT_MAX,
  37. };
  38. /**
  39. * dfl_dev_info - dfl feature device information.
  40. * @name: name string of the feature platform device.
  41. * @dfh_id: id value in Device Feature Header (DFH) register by DFL spec.
  42. * @id: idr id of the feature dev.
  43. * @devt_type: index to dfl_chrdevs[].
  44. */
  45. struct dfl_dev_info {
  46. const char *name;
  47. u32 dfh_id;
  48. struct idr id;
  49. enum dfl_fpga_devt_type devt_type;
  50. };
  51. /* it is indexed by dfl_id_type */
  52. static struct dfl_dev_info dfl_devs[] = {
  53. {.name = DFL_FPGA_FEATURE_DEV_FME, .dfh_id = DFH_ID_FIU_FME,
  54. .devt_type = DFL_FPGA_DEVT_FME},
  55. {.name = DFL_FPGA_FEATURE_DEV_PORT, .dfh_id = DFH_ID_FIU_PORT,
  56. .devt_type = DFL_FPGA_DEVT_PORT},
  57. };
  58. /**
  59. * dfl_chardev_info - chardev information of dfl feature device
  60. * @name: nmae string of the char device.
  61. * @devt: devt of the char device.
  62. */
  63. struct dfl_chardev_info {
  64. const char *name;
  65. dev_t devt;
  66. };
  67. /* indexed by enum dfl_fpga_devt_type */
  68. static struct dfl_chardev_info dfl_chrdevs[] = {
  69. {.name = DFL_FPGA_FEATURE_DEV_FME},
  70. {.name = DFL_FPGA_FEATURE_DEV_PORT},
  71. };
  72. static void dfl_ids_init(void)
  73. {
  74. int i;
  75. for (i = 0; i < ARRAY_SIZE(dfl_devs); i++)
  76. idr_init(&dfl_devs[i].id);
  77. }
  78. static void dfl_ids_destroy(void)
  79. {
  80. int i;
  81. for (i = 0; i < ARRAY_SIZE(dfl_devs); i++)
  82. idr_destroy(&dfl_devs[i].id);
  83. }
  84. static int dfl_id_alloc(enum dfl_id_type type, struct device *dev)
  85. {
  86. int id;
  87. WARN_ON(type >= DFL_ID_MAX);
  88. mutex_lock(&dfl_id_mutex);
  89. id = idr_alloc(&dfl_devs[type].id, dev, 0, 0, GFP_KERNEL);
  90. mutex_unlock(&dfl_id_mutex);
  91. return id;
  92. }
  93. static void dfl_id_free(enum dfl_id_type type, int id)
  94. {
  95. WARN_ON(type >= DFL_ID_MAX);
  96. mutex_lock(&dfl_id_mutex);
  97. idr_remove(&dfl_devs[type].id, id);
  98. mutex_unlock(&dfl_id_mutex);
  99. }
  100. static enum dfl_id_type feature_dev_id_type(struct platform_device *pdev)
  101. {
  102. int i;
  103. for (i = 0; i < ARRAY_SIZE(dfl_devs); i++)
  104. if (!strcmp(dfl_devs[i].name, pdev->name))
  105. return i;
  106. return DFL_ID_MAX;
  107. }
  108. static enum dfl_id_type dfh_id_to_type(u32 id)
  109. {
  110. int i;
  111. for (i = 0; i < ARRAY_SIZE(dfl_devs); i++)
  112. if (dfl_devs[i].dfh_id == id)
  113. return i;
  114. return DFL_ID_MAX;
  115. }
  116. static void dfl_chardev_uinit(void)
  117. {
  118. int i;
  119. for (i = 0; i < DFL_FPGA_DEVT_MAX; i++)
  120. if (MAJOR(dfl_chrdevs[i].devt)) {
  121. unregister_chrdev_region(dfl_chrdevs[i].devt,
  122. MINORMASK);
  123. dfl_chrdevs[i].devt = MKDEV(0, 0);
  124. }
  125. }
  126. static int dfl_chardev_init(void)
  127. {
  128. int i, ret;
  129. for (i = 0; i < DFL_FPGA_DEVT_MAX; i++) {
  130. ret = alloc_chrdev_region(&dfl_chrdevs[i].devt, 0, MINORMASK,
  131. dfl_chrdevs[i].name);
  132. if (ret)
  133. goto exit;
  134. }
  135. return 0;
  136. exit:
  137. dfl_chardev_uinit();
  138. return ret;
  139. }
  140. static dev_t dfl_get_devt(enum dfl_fpga_devt_type type, int id)
  141. {
  142. if (type >= DFL_FPGA_DEVT_MAX)
  143. return 0;
  144. return MKDEV(MAJOR(dfl_chrdevs[type].devt), id);
  145. }
  146. /**
  147. * dfl_fpga_dev_ops_register - register cdev ops for feature dev
  148. *
  149. * @pdev: feature dev.
  150. * @fops: file operations for feature dev's cdev.
  151. * @owner: owning module/driver.
  152. *
  153. * Return: 0 on success, negative error code otherwise.
  154. */
  155. int dfl_fpga_dev_ops_register(struct platform_device *pdev,
  156. const struct file_operations *fops,
  157. struct module *owner)
  158. {
  159. struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
  160. cdev_init(&pdata->cdev, fops);
  161. pdata->cdev.owner = owner;
  162. /*
  163. * set parent to the feature device so that its refcount is
  164. * decreased after the last refcount of cdev is gone, that
  165. * makes sure the feature device is valid during device
  166. * file's life-cycle.
  167. */
  168. pdata->cdev.kobj.parent = &pdev->dev.kobj;
  169. return cdev_add(&pdata->cdev, pdev->dev.devt, 1);
  170. }
  171. EXPORT_SYMBOL_GPL(dfl_fpga_dev_ops_register);
  172. /**
  173. * dfl_fpga_dev_ops_unregister - unregister cdev ops for feature dev
  174. * @pdev: feature dev.
  175. */
  176. void dfl_fpga_dev_ops_unregister(struct platform_device *pdev)
  177. {
  178. struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
  179. cdev_del(&pdata->cdev);
  180. }
  181. EXPORT_SYMBOL_GPL(dfl_fpga_dev_ops_unregister);
  182. /**
  183. * struct build_feature_devs_info - info collected during feature dev build.
  184. *
  185. * @dev: device to enumerate.
  186. * @cdev: the container device for all feature devices.
  187. * @feature_dev: current feature device.
  188. * @ioaddr: header register region address of feature device in enumeration.
  189. * @sub_features: a sub features linked list for feature device in enumeration.
  190. * @feature_num: number of sub features for feature device in enumeration.
  191. */
  192. struct build_feature_devs_info {
  193. struct device *dev;
  194. struct dfl_fpga_cdev *cdev;
  195. struct platform_device *feature_dev;
  196. void __iomem *ioaddr;
  197. struct list_head sub_features;
  198. int feature_num;
  199. };
  200. /**
  201. * struct dfl_feature_info - sub feature info collected during feature dev build
  202. *
  203. * @fid: id of this sub feature.
  204. * @mmio_res: mmio resource of this sub feature.
  205. * @ioaddr: mapped base address of mmio resource.
  206. * @node: node in sub_features linked list.
  207. */
  208. struct dfl_feature_info {
  209. u64 fid;
  210. struct resource mmio_res;
  211. void __iomem *ioaddr;
  212. struct list_head node;
  213. };
  214. static void dfl_fpga_cdev_add_port_dev(struct dfl_fpga_cdev *cdev,
  215. struct platform_device *port)
  216. {
  217. struct dfl_feature_platform_data *pdata = dev_get_platdata(&port->dev);
  218. mutex_lock(&cdev->lock);
  219. list_add(&pdata->node, &cdev->port_dev_list);
  220. get_device(&pdata->dev->dev);
  221. mutex_unlock(&cdev->lock);
  222. }
  223. /*
  224. * register current feature device, it is called when we need to switch to
  225. * another feature parsing or we have parsed all features on given device
  226. * feature list.
  227. */
  228. static int build_info_commit_dev(struct build_feature_devs_info *binfo)
  229. {
  230. struct platform_device *fdev = binfo->feature_dev;
  231. struct dfl_feature_platform_data *pdata;
  232. struct dfl_feature_info *finfo, *p;
  233. int ret, index = 0;
  234. if (!fdev)
  235. return 0;
  236. /*
  237. * we do not need to care for the memory which is associated with
  238. * the platform device. After calling platform_device_unregister(),
  239. * it will be automatically freed by device's release() callback,
  240. * platform_device_release().
  241. */
  242. pdata = kzalloc(dfl_feature_platform_data_size(binfo->feature_num),
  243. GFP_KERNEL);
  244. if (!pdata)
  245. return -ENOMEM;
  246. pdata->dev = fdev;
  247. pdata->num = binfo->feature_num;
  248. pdata->dfl_cdev = binfo->cdev;
  249. mutex_init(&pdata->lock);
  250. /*
  251. * the count should be initialized to 0 to make sure
  252. *__fpga_port_enable() following __fpga_port_disable()
  253. * works properly for port device.
  254. * and it should always be 0 for fme device.
  255. */
  256. WARN_ON(pdata->disable_count);
  257. fdev->dev.platform_data = pdata;
  258. /* each sub feature has one MMIO resource */
  259. fdev->num_resources = binfo->feature_num;
  260. fdev->resource = kcalloc(binfo->feature_num, sizeof(*fdev->resource),
  261. GFP_KERNEL);
  262. if (!fdev->resource)
  263. return -ENOMEM;
  264. /* fill features and resource information for feature dev */
  265. list_for_each_entry_safe(finfo, p, &binfo->sub_features, node) {
  266. struct dfl_feature *feature = &pdata->features[index];
  267. /* save resource information for each feature */
  268. feature->id = finfo->fid;
  269. feature->resource_index = index;
  270. feature->ioaddr = finfo->ioaddr;
  271. fdev->resource[index++] = finfo->mmio_res;
  272. list_del(&finfo->node);
  273. kfree(finfo);
  274. }
  275. ret = platform_device_add(binfo->feature_dev);
  276. if (!ret) {
  277. if (feature_dev_id_type(binfo->feature_dev) == PORT_ID)
  278. dfl_fpga_cdev_add_port_dev(binfo->cdev,
  279. binfo->feature_dev);
  280. else
  281. binfo->cdev->fme_dev =
  282. get_device(&binfo->feature_dev->dev);
  283. /*
  284. * reset it to avoid build_info_free() freeing their resource.
  285. *
  286. * The resource of successfully registered feature devices
  287. * will be freed by platform_device_unregister(). See the
  288. * comments in build_info_create_dev().
  289. */
  290. binfo->feature_dev = NULL;
  291. }
  292. return ret;
  293. }
  294. static int
  295. build_info_create_dev(struct build_feature_devs_info *binfo,
  296. enum dfl_id_type type, void __iomem *ioaddr)
  297. {
  298. struct platform_device *fdev;
  299. int ret;
  300. if (type >= DFL_ID_MAX)
  301. return -EINVAL;
  302. /* we will create a new device, commit current device first */
  303. ret = build_info_commit_dev(binfo);
  304. if (ret)
  305. return ret;
  306. /*
  307. * we use -ENODEV as the initialization indicator which indicates
  308. * whether the id need to be reclaimed
  309. */
  310. fdev = platform_device_alloc(dfl_devs[type].name, -ENODEV);
  311. if (!fdev)
  312. return -ENOMEM;
  313. binfo->feature_dev = fdev;
  314. binfo->feature_num = 0;
  315. binfo->ioaddr = ioaddr;
  316. INIT_LIST_HEAD(&binfo->sub_features);
  317. fdev->id = dfl_id_alloc(type, &fdev->dev);
  318. if (fdev->id < 0)
  319. return fdev->id;
  320. fdev->dev.parent = &binfo->cdev->region->dev;
  321. fdev->dev.devt = dfl_get_devt(dfl_devs[type].devt_type, fdev->id);
  322. return 0;
  323. }
  324. static void build_info_free(struct build_feature_devs_info *binfo)
  325. {
  326. struct dfl_feature_info *finfo, *p;
  327. /*
  328. * it is a valid id, free it. See comments in
  329. * build_info_create_dev()
  330. */
  331. if (binfo->feature_dev && binfo->feature_dev->id >= 0) {
  332. dfl_id_free(feature_dev_id_type(binfo->feature_dev),
  333. binfo->feature_dev->id);
  334. list_for_each_entry_safe(finfo, p, &binfo->sub_features, node) {
  335. list_del(&finfo->node);
  336. kfree(finfo);
  337. }
  338. }
  339. platform_device_put(binfo->feature_dev);
  340. devm_kfree(binfo->dev, binfo);
  341. }
  342. static inline u32 feature_size(void __iomem *start)
  343. {
  344. u64 v = readq(start + DFH);
  345. u32 ofst = FIELD_GET(DFH_NEXT_HDR_OFST, v);
  346. /* workaround for private features with invalid size, use 4K instead */
  347. return ofst ? ofst : 4096;
  348. }
  349. static u64 feature_id(void __iomem *start)
  350. {
  351. u64 v = readq(start + DFH);
  352. u16 id = FIELD_GET(DFH_ID, v);
  353. u8 type = FIELD_GET(DFH_TYPE, v);
  354. if (type == DFH_TYPE_FIU)
  355. return FEATURE_ID_FIU_HEADER;
  356. else if (type == DFH_TYPE_PRIVATE)
  357. return id;
  358. else if (type == DFH_TYPE_AFU)
  359. return FEATURE_ID_AFU;
  360. WARN_ON(1);
  361. return 0;
  362. }
  363. /*
  364. * when create sub feature instances, for private features, it doesn't need
  365. * to provide resource size and feature id as they could be read from DFH
  366. * register. For afu sub feature, its register region only contains user
  367. * defined registers, so never trust any information from it, just use the
  368. * resource size information provided by its parent FIU.
  369. */
  370. static int
  371. create_feature_instance(struct build_feature_devs_info *binfo,
  372. struct dfl_fpga_enum_dfl *dfl, resource_size_t ofst,
  373. resource_size_t size, u64 fid)
  374. {
  375. struct dfl_feature_info *finfo;
  376. /* read feature size and id if inputs are invalid */
  377. size = size ? size : feature_size(dfl->ioaddr + ofst);
  378. fid = fid ? fid : feature_id(dfl->ioaddr + ofst);
  379. if (dfl->len - ofst < size)
  380. return -EINVAL;
  381. finfo = kzalloc(sizeof(*finfo), GFP_KERNEL);
  382. if (!finfo)
  383. return -ENOMEM;
  384. finfo->fid = fid;
  385. finfo->mmio_res.start = dfl->start + ofst;
  386. finfo->mmio_res.end = finfo->mmio_res.start + size - 1;
  387. finfo->mmio_res.flags = IORESOURCE_MEM;
  388. finfo->ioaddr = dfl->ioaddr + ofst;
  389. list_add_tail(&finfo->node, &binfo->sub_features);
  390. binfo->feature_num++;
  391. return 0;
  392. }
  393. static int parse_feature_port_afu(struct build_feature_devs_info *binfo,
  394. struct dfl_fpga_enum_dfl *dfl,
  395. resource_size_t ofst)
  396. {
  397. u64 v = readq(binfo->ioaddr + PORT_HDR_CAP);
  398. u32 size = FIELD_GET(PORT_CAP_MMIO_SIZE, v) << 10;
  399. WARN_ON(!size);
  400. return create_feature_instance(binfo, dfl, ofst, size, FEATURE_ID_AFU);
  401. }
  402. static int parse_feature_afu(struct build_feature_devs_info *binfo,
  403. struct dfl_fpga_enum_dfl *dfl,
  404. resource_size_t ofst)
  405. {
  406. if (!binfo->feature_dev) {
  407. dev_err(binfo->dev, "this AFU does not belong to any FIU.\n");
  408. return -EINVAL;
  409. }
  410. switch (feature_dev_id_type(binfo->feature_dev)) {
  411. case PORT_ID:
  412. return parse_feature_port_afu(binfo, dfl, ofst);
  413. default:
  414. dev_info(binfo->dev, "AFU belonging to FIU %s is not supported yet.\n",
  415. binfo->feature_dev->name);
  416. }
  417. return 0;
  418. }
  419. static int parse_feature_fiu(struct build_feature_devs_info *binfo,
  420. struct dfl_fpga_enum_dfl *dfl,
  421. resource_size_t ofst)
  422. {
  423. u32 id, offset;
  424. u64 v;
  425. int ret = 0;
  426. v = readq(dfl->ioaddr + ofst + DFH);
  427. id = FIELD_GET(DFH_ID, v);
  428. /* create platform device for dfl feature dev */
  429. ret = build_info_create_dev(binfo, dfh_id_to_type(id),
  430. dfl->ioaddr + ofst);
  431. if (ret)
  432. return ret;
  433. ret = create_feature_instance(binfo, dfl, ofst, 0, 0);
  434. if (ret)
  435. return ret;
  436. /*
  437. * find and parse FIU's child AFU via its NEXT_AFU register.
  438. * please note that only Port has valid NEXT_AFU pointer per spec.
  439. */
  440. v = readq(dfl->ioaddr + ofst + NEXT_AFU);
  441. offset = FIELD_GET(NEXT_AFU_NEXT_DFH_OFST, v);
  442. if (offset)
  443. return parse_feature_afu(binfo, dfl, ofst + offset);
  444. dev_dbg(binfo->dev, "No AFUs detected on FIU %d\n", id);
  445. return ret;
  446. }
  447. static int parse_feature_private(struct build_feature_devs_info *binfo,
  448. struct dfl_fpga_enum_dfl *dfl,
  449. resource_size_t ofst)
  450. {
  451. if (!binfo->feature_dev) {
  452. dev_err(binfo->dev, "the private feature %llx does not belong to any AFU.\n",
  453. (unsigned long long)feature_id(dfl->ioaddr + ofst));
  454. return -EINVAL;
  455. }
  456. return create_feature_instance(binfo, dfl, ofst, 0, 0);
  457. }
  458. /**
  459. * parse_feature - parse a feature on given device feature list
  460. *
  461. * @binfo: build feature devices information.
  462. * @dfl: device feature list to parse
  463. * @ofst: offset to feature header on this device feature list
  464. */
  465. static int parse_feature(struct build_feature_devs_info *binfo,
  466. struct dfl_fpga_enum_dfl *dfl, resource_size_t ofst)
  467. {
  468. u64 v;
  469. u32 type;
  470. v = readq(dfl->ioaddr + ofst + DFH);
  471. type = FIELD_GET(DFH_TYPE, v);
  472. switch (type) {
  473. case DFH_TYPE_AFU:
  474. return parse_feature_afu(binfo, dfl, ofst);
  475. case DFH_TYPE_PRIVATE:
  476. return parse_feature_private(binfo, dfl, ofst);
  477. case DFH_TYPE_FIU:
  478. return parse_feature_fiu(binfo, dfl, ofst);
  479. default:
  480. dev_info(binfo->dev,
  481. "Feature Type %x is not supported.\n", type);
  482. }
  483. return 0;
  484. }
  485. static int parse_feature_list(struct build_feature_devs_info *binfo,
  486. struct dfl_fpga_enum_dfl *dfl)
  487. {
  488. void __iomem *start = dfl->ioaddr;
  489. void __iomem *end = dfl->ioaddr + dfl->len;
  490. int ret = 0;
  491. u32 ofst = 0;
  492. u64 v;
  493. /* walk through the device feature list via DFH's next DFH pointer. */
  494. for (; start < end; start += ofst) {
  495. if (end - start < DFH_SIZE) {
  496. dev_err(binfo->dev, "The region is too small to contain a feature.\n");
  497. return -EINVAL;
  498. }
  499. ret = parse_feature(binfo, dfl, start - dfl->ioaddr);
  500. if (ret)
  501. return ret;
  502. v = readq(start + DFH);
  503. ofst = FIELD_GET(DFH_NEXT_HDR_OFST, v);
  504. /* stop parsing if EOL(End of List) is set or offset is 0 */
  505. if ((v & DFH_EOL) || !ofst)
  506. break;
  507. }
  508. /* commit current feature device when reach the end of list */
  509. return build_info_commit_dev(binfo);
  510. }
  511. struct dfl_fpga_enum_info *dfl_fpga_enum_info_alloc(struct device *dev)
  512. {
  513. struct dfl_fpga_enum_info *info;
  514. get_device(dev);
  515. info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
  516. if (!info) {
  517. put_device(dev);
  518. return NULL;
  519. }
  520. info->dev = dev;
  521. INIT_LIST_HEAD(&info->dfls);
  522. return info;
  523. }
  524. EXPORT_SYMBOL_GPL(dfl_fpga_enum_info_alloc);
  525. void dfl_fpga_enum_info_free(struct dfl_fpga_enum_info *info)
  526. {
  527. struct dfl_fpga_enum_dfl *tmp, *dfl;
  528. struct device *dev;
  529. if (!info)
  530. return;
  531. dev = info->dev;
  532. /* remove all device feature lists in the list. */
  533. list_for_each_entry_safe(dfl, tmp, &info->dfls, node) {
  534. list_del(&dfl->node);
  535. devm_kfree(dev, dfl);
  536. }
  537. devm_kfree(dev, info);
  538. put_device(dev);
  539. }
  540. EXPORT_SYMBOL_GPL(dfl_fpga_enum_info_free);
  541. /**
  542. * dfl_fpga_enum_info_add_dfl - add info of a device feature list to enum info
  543. *
  544. * @info: ptr to dfl_fpga_enum_info
  545. * @start: mmio resource address of the device feature list.
  546. * @len: mmio resource length of the device feature list.
  547. * @ioaddr: mapped mmio resource address of the device feature list.
  548. *
  549. * One FPGA device may have one or more Device Feature Lists (DFLs), use this
  550. * function to add information of each DFL to common data structure for next
  551. * step enumeration.
  552. *
  553. * Return: 0 on success, negative error code otherwise.
  554. */
  555. int dfl_fpga_enum_info_add_dfl(struct dfl_fpga_enum_info *info,
  556. resource_size_t start, resource_size_t len,
  557. void __iomem *ioaddr)
  558. {
  559. struct dfl_fpga_enum_dfl *dfl;
  560. dfl = devm_kzalloc(info->dev, sizeof(*dfl), GFP_KERNEL);
  561. if (!dfl)
  562. return -ENOMEM;
  563. dfl->start = start;
  564. dfl->len = len;
  565. dfl->ioaddr = ioaddr;
  566. list_add_tail(&dfl->node, &info->dfls);
  567. return 0;
  568. }
  569. EXPORT_SYMBOL_GPL(dfl_fpga_enum_info_add_dfl);
  570. static int remove_feature_dev(struct device *dev, void *data)
  571. {
  572. struct platform_device *pdev = to_platform_device(dev);
  573. enum dfl_id_type type = feature_dev_id_type(pdev);
  574. int id = pdev->id;
  575. platform_device_unregister(pdev);
  576. dfl_id_free(type, id);
  577. return 0;
  578. }
  579. static void remove_feature_devs(struct dfl_fpga_cdev *cdev)
  580. {
  581. device_for_each_child(&cdev->region->dev, NULL, remove_feature_dev);
  582. }
  583. /**
  584. * dfl_fpga_feature_devs_enumerate - enumerate feature devices
  585. * @info: information for enumeration.
  586. *
  587. * This function creates a container device (base FPGA region), enumerates
  588. * feature devices based on the enumeration info and creates platform devices
  589. * under the container device.
  590. *
  591. * Return: dfl_fpga_cdev struct on success, -errno on failure
  592. */
  593. struct dfl_fpga_cdev *
  594. dfl_fpga_feature_devs_enumerate(struct dfl_fpga_enum_info *info)
  595. {
  596. struct build_feature_devs_info *binfo;
  597. struct dfl_fpga_enum_dfl *dfl;
  598. struct dfl_fpga_cdev *cdev;
  599. int ret = 0;
  600. if (!info->dev)
  601. return ERR_PTR(-ENODEV);
  602. cdev = devm_kzalloc(info->dev, sizeof(*cdev), GFP_KERNEL);
  603. if (!cdev)
  604. return ERR_PTR(-ENOMEM);
  605. cdev->region = fpga_region_create(info->dev, NULL, NULL);
  606. if (!cdev->region) {
  607. ret = -ENOMEM;
  608. goto free_cdev_exit;
  609. }
  610. cdev->parent = info->dev;
  611. mutex_init(&cdev->lock);
  612. INIT_LIST_HEAD(&cdev->port_dev_list);
  613. ret = fpga_region_register(cdev->region);
  614. if (ret)
  615. goto free_region_exit;
  616. /* create and init build info for enumeration */
  617. binfo = devm_kzalloc(info->dev, sizeof(*binfo), GFP_KERNEL);
  618. if (!binfo) {
  619. ret = -ENOMEM;
  620. goto unregister_region_exit;
  621. }
  622. binfo->dev = info->dev;
  623. binfo->cdev = cdev;
  624. /*
  625. * start enumeration for all feature devices based on Device Feature
  626. * Lists.
  627. */
  628. list_for_each_entry(dfl, &info->dfls, node) {
  629. ret = parse_feature_list(binfo, dfl);
  630. if (ret) {
  631. remove_feature_devs(cdev);
  632. build_info_free(binfo);
  633. goto unregister_region_exit;
  634. }
  635. }
  636. build_info_free(binfo);
  637. return cdev;
  638. unregister_region_exit:
  639. fpga_region_unregister(cdev->region);
  640. free_region_exit:
  641. fpga_region_free(cdev->region);
  642. free_cdev_exit:
  643. devm_kfree(info->dev, cdev);
  644. return ERR_PTR(ret);
  645. }
  646. EXPORT_SYMBOL_GPL(dfl_fpga_feature_devs_enumerate);
  647. /**
  648. * dfl_fpga_feature_devs_remove - remove all feature devices
  649. * @cdev: fpga container device.
  650. *
  651. * Remove the container device and all feature devices under given container
  652. * devices.
  653. */
  654. void dfl_fpga_feature_devs_remove(struct dfl_fpga_cdev *cdev)
  655. {
  656. struct dfl_feature_platform_data *pdata, *ptmp;
  657. remove_feature_devs(cdev);
  658. mutex_lock(&cdev->lock);
  659. if (cdev->fme_dev) {
  660. /* the fme should be unregistered. */
  661. WARN_ON(device_is_registered(cdev->fme_dev));
  662. put_device(cdev->fme_dev);
  663. }
  664. list_for_each_entry_safe(pdata, ptmp, &cdev->port_dev_list, node) {
  665. struct platform_device *port_dev = pdata->dev;
  666. /* the port should be unregistered. */
  667. WARN_ON(device_is_registered(&port_dev->dev));
  668. list_del(&pdata->node);
  669. put_device(&port_dev->dev);
  670. }
  671. mutex_unlock(&cdev->lock);
  672. fpga_region_unregister(cdev->region);
  673. devm_kfree(cdev->parent, cdev);
  674. }
  675. EXPORT_SYMBOL_GPL(dfl_fpga_feature_devs_remove);
  676. static int __init dfl_fpga_init(void)
  677. {
  678. int ret;
  679. dfl_ids_init();
  680. ret = dfl_chardev_init();
  681. if (ret)
  682. dfl_ids_destroy();
  683. return ret;
  684. }
  685. static void __exit dfl_fpga_exit(void)
  686. {
  687. dfl_chardev_uinit();
  688. dfl_ids_destroy();
  689. }
  690. module_init(dfl_fpga_init);
  691. module_exit(dfl_fpga_exit);
  692. MODULE_DESCRIPTION("FPGA Device Feature List (DFL) Support");
  693. MODULE_AUTHOR("Intel Corporation");
  694. MODULE_LICENSE("GPL v2");