dfl.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042
  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. /*
  117. * introduce a global port_ops list, it allows port drivers to register ops
  118. * in such list, then other feature devices (e.g. FME), could use the port
  119. * functions even related port platform device is hidden. Below is one example,
  120. * in virtualization case of PCIe-based FPGA DFL device, when SRIOV is
  121. * enabled, port (and it's AFU) is turned into VF and port platform device
  122. * is hidden from system but it's still required to access port to finish FPGA
  123. * reconfiguration function in FME.
  124. */
  125. static DEFINE_MUTEX(dfl_port_ops_mutex);
  126. static LIST_HEAD(dfl_port_ops_list);
  127. /**
  128. * dfl_fpga_port_ops_get - get matched port ops from the global list
  129. * @pdev: platform device to match with associated port ops.
  130. * Return: matched port ops on success, NULL otherwise.
  131. *
  132. * Please note that must dfl_fpga_port_ops_put after use the port_ops.
  133. */
  134. struct dfl_fpga_port_ops *dfl_fpga_port_ops_get(struct platform_device *pdev)
  135. {
  136. struct dfl_fpga_port_ops *ops = NULL;
  137. mutex_lock(&dfl_port_ops_mutex);
  138. if (list_empty(&dfl_port_ops_list))
  139. goto done;
  140. list_for_each_entry(ops, &dfl_port_ops_list, node) {
  141. /* match port_ops using the name of platform device */
  142. if (!strcmp(pdev->name, ops->name)) {
  143. if (!try_module_get(ops->owner))
  144. ops = NULL;
  145. goto done;
  146. }
  147. }
  148. ops = NULL;
  149. done:
  150. mutex_unlock(&dfl_port_ops_mutex);
  151. return ops;
  152. }
  153. EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_get);
  154. /**
  155. * dfl_fpga_port_ops_put - put port ops
  156. * @ops: port ops.
  157. */
  158. void dfl_fpga_port_ops_put(struct dfl_fpga_port_ops *ops)
  159. {
  160. if (ops && ops->owner)
  161. module_put(ops->owner);
  162. }
  163. EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_put);
  164. /**
  165. * dfl_fpga_port_ops_add - add port_ops to global list
  166. * @ops: port ops to add.
  167. */
  168. void dfl_fpga_port_ops_add(struct dfl_fpga_port_ops *ops)
  169. {
  170. mutex_lock(&dfl_port_ops_mutex);
  171. list_add_tail(&ops->node, &dfl_port_ops_list);
  172. mutex_unlock(&dfl_port_ops_mutex);
  173. }
  174. EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_add);
  175. /**
  176. * dfl_fpga_port_ops_del - remove port_ops from global list
  177. * @ops: port ops to del.
  178. */
  179. void dfl_fpga_port_ops_del(struct dfl_fpga_port_ops *ops)
  180. {
  181. mutex_lock(&dfl_port_ops_mutex);
  182. list_del(&ops->node);
  183. mutex_unlock(&dfl_port_ops_mutex);
  184. }
  185. EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_del);
  186. /**
  187. * dfl_fpga_check_port_id - check the port id
  188. * @pdev: port platform device.
  189. * @pport_id: port id to compare.
  190. *
  191. * Return: 1 if port device matches with given port id, otherwise 0.
  192. */
  193. int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id)
  194. {
  195. struct dfl_fpga_port_ops *port_ops = dfl_fpga_port_ops_get(pdev);
  196. int port_id;
  197. if (!port_ops || !port_ops->get_id)
  198. return 0;
  199. port_id = port_ops->get_id(pdev);
  200. dfl_fpga_port_ops_put(port_ops);
  201. return port_id == *(int *)pport_id;
  202. }
  203. EXPORT_SYMBOL_GPL(dfl_fpga_check_port_id);
  204. /**
  205. * dfl_fpga_dev_feature_uinit - uinit for sub features of dfl feature device
  206. * @pdev: feature device.
  207. */
  208. void dfl_fpga_dev_feature_uinit(struct platform_device *pdev)
  209. {
  210. struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
  211. struct dfl_feature *feature;
  212. dfl_fpga_dev_for_each_feature(pdata, feature)
  213. if (feature->ops) {
  214. feature->ops->uinit(pdev, feature);
  215. feature->ops = NULL;
  216. }
  217. }
  218. EXPORT_SYMBOL_GPL(dfl_fpga_dev_feature_uinit);
  219. static int dfl_feature_instance_init(struct platform_device *pdev,
  220. struct dfl_feature_platform_data *pdata,
  221. struct dfl_feature *feature,
  222. struct dfl_feature_driver *drv)
  223. {
  224. int ret;
  225. ret = drv->ops->init(pdev, feature);
  226. if (ret)
  227. return ret;
  228. feature->ops = drv->ops;
  229. return ret;
  230. }
  231. /**
  232. * dfl_fpga_dev_feature_init - init for sub features of dfl feature device
  233. * @pdev: feature device.
  234. * @feature_drvs: drvs for sub features.
  235. *
  236. * This function will match sub features with given feature drvs list and
  237. * use matched drv to init related sub feature.
  238. *
  239. * Return: 0 on success, negative error code otherwise.
  240. */
  241. int dfl_fpga_dev_feature_init(struct platform_device *pdev,
  242. struct dfl_feature_driver *feature_drvs)
  243. {
  244. struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
  245. struct dfl_feature_driver *drv = feature_drvs;
  246. struct dfl_feature *feature;
  247. int ret;
  248. while (drv->ops) {
  249. dfl_fpga_dev_for_each_feature(pdata, feature) {
  250. /* match feature and drv using id */
  251. if (feature->id == drv->id) {
  252. ret = dfl_feature_instance_init(pdev, pdata,
  253. feature, drv);
  254. if (ret)
  255. goto exit;
  256. }
  257. }
  258. drv++;
  259. }
  260. return 0;
  261. exit:
  262. dfl_fpga_dev_feature_uinit(pdev);
  263. return ret;
  264. }
  265. EXPORT_SYMBOL_GPL(dfl_fpga_dev_feature_init);
  266. static void dfl_chardev_uinit(void)
  267. {
  268. int i;
  269. for (i = 0; i < DFL_FPGA_DEVT_MAX; i++)
  270. if (MAJOR(dfl_chrdevs[i].devt)) {
  271. unregister_chrdev_region(dfl_chrdevs[i].devt,
  272. MINORMASK);
  273. dfl_chrdevs[i].devt = MKDEV(0, 0);
  274. }
  275. }
  276. static int dfl_chardev_init(void)
  277. {
  278. int i, ret;
  279. for (i = 0; i < DFL_FPGA_DEVT_MAX; i++) {
  280. ret = alloc_chrdev_region(&dfl_chrdevs[i].devt, 0, MINORMASK,
  281. dfl_chrdevs[i].name);
  282. if (ret)
  283. goto exit;
  284. }
  285. return 0;
  286. exit:
  287. dfl_chardev_uinit();
  288. return ret;
  289. }
  290. static dev_t dfl_get_devt(enum dfl_fpga_devt_type type, int id)
  291. {
  292. if (type >= DFL_FPGA_DEVT_MAX)
  293. return 0;
  294. return MKDEV(MAJOR(dfl_chrdevs[type].devt), id);
  295. }
  296. /**
  297. * dfl_fpga_dev_ops_register - register cdev ops for feature dev
  298. *
  299. * @pdev: feature dev.
  300. * @fops: file operations for feature dev's cdev.
  301. * @owner: owning module/driver.
  302. *
  303. * Return: 0 on success, negative error code otherwise.
  304. */
  305. int dfl_fpga_dev_ops_register(struct platform_device *pdev,
  306. const struct file_operations *fops,
  307. struct module *owner)
  308. {
  309. struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
  310. cdev_init(&pdata->cdev, fops);
  311. pdata->cdev.owner = owner;
  312. /*
  313. * set parent to the feature device so that its refcount is
  314. * decreased after the last refcount of cdev is gone, that
  315. * makes sure the feature device is valid during device
  316. * file's life-cycle.
  317. */
  318. pdata->cdev.kobj.parent = &pdev->dev.kobj;
  319. return cdev_add(&pdata->cdev, pdev->dev.devt, 1);
  320. }
  321. EXPORT_SYMBOL_GPL(dfl_fpga_dev_ops_register);
  322. /**
  323. * dfl_fpga_dev_ops_unregister - unregister cdev ops for feature dev
  324. * @pdev: feature dev.
  325. */
  326. void dfl_fpga_dev_ops_unregister(struct platform_device *pdev)
  327. {
  328. struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
  329. cdev_del(&pdata->cdev);
  330. }
  331. EXPORT_SYMBOL_GPL(dfl_fpga_dev_ops_unregister);
  332. /**
  333. * struct build_feature_devs_info - info collected during feature dev build.
  334. *
  335. * @dev: device to enumerate.
  336. * @cdev: the container device for all feature devices.
  337. * @feature_dev: current feature device.
  338. * @ioaddr: header register region address of feature device in enumeration.
  339. * @sub_features: a sub features linked list for feature device in enumeration.
  340. * @feature_num: number of sub features for feature device in enumeration.
  341. */
  342. struct build_feature_devs_info {
  343. struct device *dev;
  344. struct dfl_fpga_cdev *cdev;
  345. struct platform_device *feature_dev;
  346. void __iomem *ioaddr;
  347. struct list_head sub_features;
  348. int feature_num;
  349. };
  350. /**
  351. * struct dfl_feature_info - sub feature info collected during feature dev build
  352. *
  353. * @fid: id of this sub feature.
  354. * @mmio_res: mmio resource of this sub feature.
  355. * @ioaddr: mapped base address of mmio resource.
  356. * @node: node in sub_features linked list.
  357. */
  358. struct dfl_feature_info {
  359. u64 fid;
  360. struct resource mmio_res;
  361. void __iomem *ioaddr;
  362. struct list_head node;
  363. };
  364. static void dfl_fpga_cdev_add_port_dev(struct dfl_fpga_cdev *cdev,
  365. struct platform_device *port)
  366. {
  367. struct dfl_feature_platform_data *pdata = dev_get_platdata(&port->dev);
  368. mutex_lock(&cdev->lock);
  369. list_add(&pdata->node, &cdev->port_dev_list);
  370. get_device(&pdata->dev->dev);
  371. mutex_unlock(&cdev->lock);
  372. }
  373. /*
  374. * register current feature device, it is called when we need to switch to
  375. * another feature parsing or we have parsed all features on given device
  376. * feature list.
  377. */
  378. static int build_info_commit_dev(struct build_feature_devs_info *binfo)
  379. {
  380. struct platform_device *fdev = binfo->feature_dev;
  381. struct dfl_feature_platform_data *pdata;
  382. struct dfl_feature_info *finfo, *p;
  383. int ret, index = 0;
  384. if (!fdev)
  385. return 0;
  386. /*
  387. * we do not need to care for the memory which is associated with
  388. * the platform device. After calling platform_device_unregister(),
  389. * it will be automatically freed by device's release() callback,
  390. * platform_device_release().
  391. */
  392. pdata = kzalloc(dfl_feature_platform_data_size(binfo->feature_num),
  393. GFP_KERNEL);
  394. if (!pdata)
  395. return -ENOMEM;
  396. pdata->dev = fdev;
  397. pdata->num = binfo->feature_num;
  398. pdata->dfl_cdev = binfo->cdev;
  399. mutex_init(&pdata->lock);
  400. /*
  401. * the count should be initialized to 0 to make sure
  402. *__fpga_port_enable() following __fpga_port_disable()
  403. * works properly for port device.
  404. * and it should always be 0 for fme device.
  405. */
  406. WARN_ON(pdata->disable_count);
  407. fdev->dev.platform_data = pdata;
  408. /* each sub feature has one MMIO resource */
  409. fdev->num_resources = binfo->feature_num;
  410. fdev->resource = kcalloc(binfo->feature_num, sizeof(*fdev->resource),
  411. GFP_KERNEL);
  412. if (!fdev->resource)
  413. return -ENOMEM;
  414. /* fill features and resource information for feature dev */
  415. list_for_each_entry_safe(finfo, p, &binfo->sub_features, node) {
  416. struct dfl_feature *feature = &pdata->features[index];
  417. /* save resource information for each feature */
  418. feature->id = finfo->fid;
  419. feature->resource_index = index;
  420. feature->ioaddr = finfo->ioaddr;
  421. fdev->resource[index++] = finfo->mmio_res;
  422. list_del(&finfo->node);
  423. kfree(finfo);
  424. }
  425. ret = platform_device_add(binfo->feature_dev);
  426. if (!ret) {
  427. if (feature_dev_id_type(binfo->feature_dev) == PORT_ID)
  428. dfl_fpga_cdev_add_port_dev(binfo->cdev,
  429. binfo->feature_dev);
  430. else
  431. binfo->cdev->fme_dev =
  432. get_device(&binfo->feature_dev->dev);
  433. /*
  434. * reset it to avoid build_info_free() freeing their resource.
  435. *
  436. * The resource of successfully registered feature devices
  437. * will be freed by platform_device_unregister(). See the
  438. * comments in build_info_create_dev().
  439. */
  440. binfo->feature_dev = NULL;
  441. }
  442. return ret;
  443. }
  444. static int
  445. build_info_create_dev(struct build_feature_devs_info *binfo,
  446. enum dfl_id_type type, void __iomem *ioaddr)
  447. {
  448. struct platform_device *fdev;
  449. int ret;
  450. if (type >= DFL_ID_MAX)
  451. return -EINVAL;
  452. /* we will create a new device, commit current device first */
  453. ret = build_info_commit_dev(binfo);
  454. if (ret)
  455. return ret;
  456. /*
  457. * we use -ENODEV as the initialization indicator which indicates
  458. * whether the id need to be reclaimed
  459. */
  460. fdev = platform_device_alloc(dfl_devs[type].name, -ENODEV);
  461. if (!fdev)
  462. return -ENOMEM;
  463. binfo->feature_dev = fdev;
  464. binfo->feature_num = 0;
  465. binfo->ioaddr = ioaddr;
  466. INIT_LIST_HEAD(&binfo->sub_features);
  467. fdev->id = dfl_id_alloc(type, &fdev->dev);
  468. if (fdev->id < 0)
  469. return fdev->id;
  470. fdev->dev.parent = &binfo->cdev->region->dev;
  471. fdev->dev.devt = dfl_get_devt(dfl_devs[type].devt_type, fdev->id);
  472. return 0;
  473. }
  474. static void build_info_free(struct build_feature_devs_info *binfo)
  475. {
  476. struct dfl_feature_info *finfo, *p;
  477. /*
  478. * it is a valid id, free it. See comments in
  479. * build_info_create_dev()
  480. */
  481. if (binfo->feature_dev && binfo->feature_dev->id >= 0) {
  482. dfl_id_free(feature_dev_id_type(binfo->feature_dev),
  483. binfo->feature_dev->id);
  484. list_for_each_entry_safe(finfo, p, &binfo->sub_features, node) {
  485. list_del(&finfo->node);
  486. kfree(finfo);
  487. }
  488. }
  489. platform_device_put(binfo->feature_dev);
  490. devm_kfree(binfo->dev, binfo);
  491. }
  492. static inline u32 feature_size(void __iomem *start)
  493. {
  494. u64 v = readq(start + DFH);
  495. u32 ofst = FIELD_GET(DFH_NEXT_HDR_OFST, v);
  496. /* workaround for private features with invalid size, use 4K instead */
  497. return ofst ? ofst : 4096;
  498. }
  499. static u64 feature_id(void __iomem *start)
  500. {
  501. u64 v = readq(start + DFH);
  502. u16 id = FIELD_GET(DFH_ID, v);
  503. u8 type = FIELD_GET(DFH_TYPE, v);
  504. if (type == DFH_TYPE_FIU)
  505. return FEATURE_ID_FIU_HEADER;
  506. else if (type == DFH_TYPE_PRIVATE)
  507. return id;
  508. else if (type == DFH_TYPE_AFU)
  509. return FEATURE_ID_AFU;
  510. WARN_ON(1);
  511. return 0;
  512. }
  513. /*
  514. * when create sub feature instances, for private features, it doesn't need
  515. * to provide resource size and feature id as they could be read from DFH
  516. * register. For afu sub feature, its register region only contains user
  517. * defined registers, so never trust any information from it, just use the
  518. * resource size information provided by its parent FIU.
  519. */
  520. static int
  521. create_feature_instance(struct build_feature_devs_info *binfo,
  522. struct dfl_fpga_enum_dfl *dfl, resource_size_t ofst,
  523. resource_size_t size, u64 fid)
  524. {
  525. struct dfl_feature_info *finfo;
  526. /* read feature size and id if inputs are invalid */
  527. size = size ? size : feature_size(dfl->ioaddr + ofst);
  528. fid = fid ? fid : feature_id(dfl->ioaddr + ofst);
  529. if (dfl->len - ofst < size)
  530. return -EINVAL;
  531. finfo = kzalloc(sizeof(*finfo), GFP_KERNEL);
  532. if (!finfo)
  533. return -ENOMEM;
  534. finfo->fid = fid;
  535. finfo->mmio_res.start = dfl->start + ofst;
  536. finfo->mmio_res.end = finfo->mmio_res.start + size - 1;
  537. finfo->mmio_res.flags = IORESOURCE_MEM;
  538. finfo->ioaddr = dfl->ioaddr + ofst;
  539. list_add_tail(&finfo->node, &binfo->sub_features);
  540. binfo->feature_num++;
  541. return 0;
  542. }
  543. static int parse_feature_port_afu(struct build_feature_devs_info *binfo,
  544. struct dfl_fpga_enum_dfl *dfl,
  545. resource_size_t ofst)
  546. {
  547. u64 v = readq(binfo->ioaddr + PORT_HDR_CAP);
  548. u32 size = FIELD_GET(PORT_CAP_MMIO_SIZE, v) << 10;
  549. WARN_ON(!size);
  550. return create_feature_instance(binfo, dfl, ofst, size, FEATURE_ID_AFU);
  551. }
  552. static int parse_feature_afu(struct build_feature_devs_info *binfo,
  553. struct dfl_fpga_enum_dfl *dfl,
  554. resource_size_t ofst)
  555. {
  556. if (!binfo->feature_dev) {
  557. dev_err(binfo->dev, "this AFU does not belong to any FIU.\n");
  558. return -EINVAL;
  559. }
  560. switch (feature_dev_id_type(binfo->feature_dev)) {
  561. case PORT_ID:
  562. return parse_feature_port_afu(binfo, dfl, ofst);
  563. default:
  564. dev_info(binfo->dev, "AFU belonging to FIU %s is not supported yet.\n",
  565. binfo->feature_dev->name);
  566. }
  567. return 0;
  568. }
  569. static int parse_feature_fiu(struct build_feature_devs_info *binfo,
  570. struct dfl_fpga_enum_dfl *dfl,
  571. resource_size_t ofst)
  572. {
  573. u32 id, offset;
  574. u64 v;
  575. int ret = 0;
  576. v = readq(dfl->ioaddr + ofst + DFH);
  577. id = FIELD_GET(DFH_ID, v);
  578. /* create platform device for dfl feature dev */
  579. ret = build_info_create_dev(binfo, dfh_id_to_type(id),
  580. dfl->ioaddr + ofst);
  581. if (ret)
  582. return ret;
  583. ret = create_feature_instance(binfo, dfl, ofst, 0, 0);
  584. if (ret)
  585. return ret;
  586. /*
  587. * find and parse FIU's child AFU via its NEXT_AFU register.
  588. * please note that only Port has valid NEXT_AFU pointer per spec.
  589. */
  590. v = readq(dfl->ioaddr + ofst + NEXT_AFU);
  591. offset = FIELD_GET(NEXT_AFU_NEXT_DFH_OFST, v);
  592. if (offset)
  593. return parse_feature_afu(binfo, dfl, ofst + offset);
  594. dev_dbg(binfo->dev, "No AFUs detected on FIU %d\n", id);
  595. return ret;
  596. }
  597. static int parse_feature_private(struct build_feature_devs_info *binfo,
  598. struct dfl_fpga_enum_dfl *dfl,
  599. resource_size_t ofst)
  600. {
  601. if (!binfo->feature_dev) {
  602. dev_err(binfo->dev, "the private feature %llx does not belong to any AFU.\n",
  603. (unsigned long long)feature_id(dfl->ioaddr + ofst));
  604. return -EINVAL;
  605. }
  606. return create_feature_instance(binfo, dfl, ofst, 0, 0);
  607. }
  608. /**
  609. * parse_feature - parse a feature on given device feature list
  610. *
  611. * @binfo: build feature devices information.
  612. * @dfl: device feature list to parse
  613. * @ofst: offset to feature header on this device feature list
  614. */
  615. static int parse_feature(struct build_feature_devs_info *binfo,
  616. struct dfl_fpga_enum_dfl *dfl, resource_size_t ofst)
  617. {
  618. u64 v;
  619. u32 type;
  620. v = readq(dfl->ioaddr + ofst + DFH);
  621. type = FIELD_GET(DFH_TYPE, v);
  622. switch (type) {
  623. case DFH_TYPE_AFU:
  624. return parse_feature_afu(binfo, dfl, ofst);
  625. case DFH_TYPE_PRIVATE:
  626. return parse_feature_private(binfo, dfl, ofst);
  627. case DFH_TYPE_FIU:
  628. return parse_feature_fiu(binfo, dfl, ofst);
  629. default:
  630. dev_info(binfo->dev,
  631. "Feature Type %x is not supported.\n", type);
  632. }
  633. return 0;
  634. }
  635. static int parse_feature_list(struct build_feature_devs_info *binfo,
  636. struct dfl_fpga_enum_dfl *dfl)
  637. {
  638. void __iomem *start = dfl->ioaddr;
  639. void __iomem *end = dfl->ioaddr + dfl->len;
  640. int ret = 0;
  641. u32 ofst = 0;
  642. u64 v;
  643. /* walk through the device feature list via DFH's next DFH pointer. */
  644. for (; start < end; start += ofst) {
  645. if (end - start < DFH_SIZE) {
  646. dev_err(binfo->dev, "The region is too small to contain a feature.\n");
  647. return -EINVAL;
  648. }
  649. ret = parse_feature(binfo, dfl, start - dfl->ioaddr);
  650. if (ret)
  651. return ret;
  652. v = readq(start + DFH);
  653. ofst = FIELD_GET(DFH_NEXT_HDR_OFST, v);
  654. /* stop parsing if EOL(End of List) is set or offset is 0 */
  655. if ((v & DFH_EOL) || !ofst)
  656. break;
  657. }
  658. /* commit current feature device when reach the end of list */
  659. return build_info_commit_dev(binfo);
  660. }
  661. struct dfl_fpga_enum_info *dfl_fpga_enum_info_alloc(struct device *dev)
  662. {
  663. struct dfl_fpga_enum_info *info;
  664. get_device(dev);
  665. info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
  666. if (!info) {
  667. put_device(dev);
  668. return NULL;
  669. }
  670. info->dev = dev;
  671. INIT_LIST_HEAD(&info->dfls);
  672. return info;
  673. }
  674. EXPORT_SYMBOL_GPL(dfl_fpga_enum_info_alloc);
  675. void dfl_fpga_enum_info_free(struct dfl_fpga_enum_info *info)
  676. {
  677. struct dfl_fpga_enum_dfl *tmp, *dfl;
  678. struct device *dev;
  679. if (!info)
  680. return;
  681. dev = info->dev;
  682. /* remove all device feature lists in the list. */
  683. list_for_each_entry_safe(dfl, tmp, &info->dfls, node) {
  684. list_del(&dfl->node);
  685. devm_kfree(dev, dfl);
  686. }
  687. devm_kfree(dev, info);
  688. put_device(dev);
  689. }
  690. EXPORT_SYMBOL_GPL(dfl_fpga_enum_info_free);
  691. /**
  692. * dfl_fpga_enum_info_add_dfl - add info of a device feature list to enum info
  693. *
  694. * @info: ptr to dfl_fpga_enum_info
  695. * @start: mmio resource address of the device feature list.
  696. * @len: mmio resource length of the device feature list.
  697. * @ioaddr: mapped mmio resource address of the device feature list.
  698. *
  699. * One FPGA device may have one or more Device Feature Lists (DFLs), use this
  700. * function to add information of each DFL to common data structure for next
  701. * step enumeration.
  702. *
  703. * Return: 0 on success, negative error code otherwise.
  704. */
  705. int dfl_fpga_enum_info_add_dfl(struct dfl_fpga_enum_info *info,
  706. resource_size_t start, resource_size_t len,
  707. void __iomem *ioaddr)
  708. {
  709. struct dfl_fpga_enum_dfl *dfl;
  710. dfl = devm_kzalloc(info->dev, sizeof(*dfl), GFP_KERNEL);
  711. if (!dfl)
  712. return -ENOMEM;
  713. dfl->start = start;
  714. dfl->len = len;
  715. dfl->ioaddr = ioaddr;
  716. list_add_tail(&dfl->node, &info->dfls);
  717. return 0;
  718. }
  719. EXPORT_SYMBOL_GPL(dfl_fpga_enum_info_add_dfl);
  720. static int remove_feature_dev(struct device *dev, void *data)
  721. {
  722. struct platform_device *pdev = to_platform_device(dev);
  723. enum dfl_id_type type = feature_dev_id_type(pdev);
  724. int id = pdev->id;
  725. platform_device_unregister(pdev);
  726. dfl_id_free(type, id);
  727. return 0;
  728. }
  729. static void remove_feature_devs(struct dfl_fpga_cdev *cdev)
  730. {
  731. device_for_each_child(&cdev->region->dev, NULL, remove_feature_dev);
  732. }
  733. /**
  734. * dfl_fpga_feature_devs_enumerate - enumerate feature devices
  735. * @info: information for enumeration.
  736. *
  737. * This function creates a container device (base FPGA region), enumerates
  738. * feature devices based on the enumeration info and creates platform devices
  739. * under the container device.
  740. *
  741. * Return: dfl_fpga_cdev struct on success, -errno on failure
  742. */
  743. struct dfl_fpga_cdev *
  744. dfl_fpga_feature_devs_enumerate(struct dfl_fpga_enum_info *info)
  745. {
  746. struct build_feature_devs_info *binfo;
  747. struct dfl_fpga_enum_dfl *dfl;
  748. struct dfl_fpga_cdev *cdev;
  749. int ret = 0;
  750. if (!info->dev)
  751. return ERR_PTR(-ENODEV);
  752. cdev = devm_kzalloc(info->dev, sizeof(*cdev), GFP_KERNEL);
  753. if (!cdev)
  754. return ERR_PTR(-ENOMEM);
  755. cdev->region = devm_fpga_region_create(info->dev, NULL, NULL);
  756. if (!cdev->region) {
  757. ret = -ENOMEM;
  758. goto free_cdev_exit;
  759. }
  760. cdev->parent = info->dev;
  761. mutex_init(&cdev->lock);
  762. INIT_LIST_HEAD(&cdev->port_dev_list);
  763. ret = fpga_region_register(cdev->region);
  764. if (ret)
  765. goto free_cdev_exit;
  766. /* create and init build info for enumeration */
  767. binfo = devm_kzalloc(info->dev, sizeof(*binfo), GFP_KERNEL);
  768. if (!binfo) {
  769. ret = -ENOMEM;
  770. goto unregister_region_exit;
  771. }
  772. binfo->dev = info->dev;
  773. binfo->cdev = cdev;
  774. /*
  775. * start enumeration for all feature devices based on Device Feature
  776. * Lists.
  777. */
  778. list_for_each_entry(dfl, &info->dfls, node) {
  779. ret = parse_feature_list(binfo, dfl);
  780. if (ret) {
  781. remove_feature_devs(cdev);
  782. build_info_free(binfo);
  783. goto unregister_region_exit;
  784. }
  785. }
  786. build_info_free(binfo);
  787. return cdev;
  788. unregister_region_exit:
  789. fpga_region_unregister(cdev->region);
  790. free_cdev_exit:
  791. devm_kfree(info->dev, cdev);
  792. return ERR_PTR(ret);
  793. }
  794. EXPORT_SYMBOL_GPL(dfl_fpga_feature_devs_enumerate);
  795. /**
  796. * dfl_fpga_feature_devs_remove - remove all feature devices
  797. * @cdev: fpga container device.
  798. *
  799. * Remove the container device and all feature devices under given container
  800. * devices.
  801. */
  802. void dfl_fpga_feature_devs_remove(struct dfl_fpga_cdev *cdev)
  803. {
  804. struct dfl_feature_platform_data *pdata, *ptmp;
  805. remove_feature_devs(cdev);
  806. mutex_lock(&cdev->lock);
  807. if (cdev->fme_dev) {
  808. /* the fme should be unregistered. */
  809. WARN_ON(device_is_registered(cdev->fme_dev));
  810. put_device(cdev->fme_dev);
  811. }
  812. list_for_each_entry_safe(pdata, ptmp, &cdev->port_dev_list, node) {
  813. struct platform_device *port_dev = pdata->dev;
  814. /* the port should be unregistered. */
  815. WARN_ON(device_is_registered(&port_dev->dev));
  816. list_del(&pdata->node);
  817. put_device(&port_dev->dev);
  818. }
  819. mutex_unlock(&cdev->lock);
  820. fpga_region_unregister(cdev->region);
  821. devm_kfree(cdev->parent, cdev);
  822. }
  823. EXPORT_SYMBOL_GPL(dfl_fpga_feature_devs_remove);
  824. /**
  825. * __dfl_fpga_cdev_find_port - find a port under given container device
  826. *
  827. * @cdev: container device
  828. * @data: data passed to match function
  829. * @match: match function used to find specific port from the port device list
  830. *
  831. * Find a port device under container device. This function needs to be
  832. * invoked with lock held.
  833. *
  834. * Return: pointer to port's platform device if successful, NULL otherwise.
  835. *
  836. * NOTE: you will need to drop the device reference with put_device() after use.
  837. */
  838. struct platform_device *
  839. __dfl_fpga_cdev_find_port(struct dfl_fpga_cdev *cdev, void *data,
  840. int (*match)(struct platform_device *, void *))
  841. {
  842. struct dfl_feature_platform_data *pdata;
  843. struct platform_device *port_dev;
  844. list_for_each_entry(pdata, &cdev->port_dev_list, node) {
  845. port_dev = pdata->dev;
  846. if (match(port_dev, data) && get_device(&port_dev->dev))
  847. return port_dev;
  848. }
  849. return NULL;
  850. }
  851. EXPORT_SYMBOL_GPL(__dfl_fpga_cdev_find_port);
  852. static int __init dfl_fpga_init(void)
  853. {
  854. int ret;
  855. dfl_ids_init();
  856. ret = dfl_chardev_init();
  857. if (ret)
  858. dfl_ids_destroy();
  859. return ret;
  860. }
  861. static void __exit dfl_fpga_exit(void)
  862. {
  863. dfl_chardev_uinit();
  864. dfl_ids_destroy();
  865. }
  866. module_init(dfl_fpga_init);
  867. module_exit(dfl_fpga_exit);
  868. MODULE_DESCRIPTION("FPGA Device Feature List (DFL) Support");
  869. MODULE_AUTHOR("Intel Corporation");
  870. MODULE_LICENSE("GPL v2");