Lines Matching +full:device +full:- +full:id
1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for FPGA Device Feature List (DFL) Support
5 * Copyright (C) 2017-2018 Intel Corporation, Inc.
14 #include <linux/fpga-dfl.h>
26 * platform device creation (define name strings in dfl.h, as they could be
27 * reused by platform device drivers).
43 "dfl-fme-pdata",
44 "dfl-port-pdata",
48 * dfl_dev_info - dfl feature device information.
49 * @name: name string of the feature platform device.
50 * @dfh_id: id value in Device Feature Header (DFH) register by DFL spec.
51 * @id: idr id of the feature dev.
57 struct idr id; member
70 * dfl_chardev_info - chardev information of dfl feature device
71 * @name: nmae string of the char device.
72 * @devt: devt of the char device.
90 idr_init(&dfl_devs[i].id); in dfl_ids_init()
98 idr_destroy(&dfl_devs[i].id); in dfl_ids_destroy()
101 static int dfl_id_alloc(enum dfl_id_type type, struct device *dev) in dfl_id_alloc()
103 int id; in dfl_id_alloc() local
107 id = idr_alloc(&dfl_devs[type].id, dev, 0, 0, GFP_KERNEL); in dfl_id_alloc()
110 return id; in dfl_id_alloc()
113 static void dfl_id_free(enum dfl_id_type type, int id) in dfl_id_free() argument
117 idr_remove(&dfl_devs[type].id, id); in dfl_id_free()
126 if (!strcmp(dfl_devs[i].name, pdev->name)) in feature_dev_id_type()
132 static enum dfl_id_type dfh_id_to_type(u16 id) in dfh_id_to_type() argument
137 if (dfl_devs[i].dfh_id == id) in dfh_id_to_type()
146 * functions even related port platform device is hidden. Below is one example,
147 * in virtualization case of PCIe-based FPGA DFL device, when SRIOV is
148 * enabled, port (and it's AFU) is turned into VF and port platform device
157 * dfl_fpga_port_ops_get - get matched port ops from the global list
158 * @pdev: platform device to match with associated port ops.
172 /* match port_ops using the name of platform device */ in dfl_fpga_port_ops_get()
173 if (!strcmp(pdev->name, ops->name)) { in dfl_fpga_port_ops_get()
174 if (!try_module_get(ops->owner)) in dfl_fpga_port_ops_get()
188 * dfl_fpga_port_ops_put - put port ops
193 if (ops && ops->owner) in dfl_fpga_port_ops_put()
194 module_put(ops->owner); in dfl_fpga_port_ops_put()
199 * dfl_fpga_port_ops_add - add port_ops to global list
205 list_add_tail(&ops->node, &dfl_port_ops_list); in dfl_fpga_port_ops_add()
211 * dfl_fpga_port_ops_del - remove port_ops from global list
217 list_del(&ops->node); in dfl_fpga_port_ops_del()
223 * dfl_fpga_check_port_id - check the port id
224 * @pdev: port platform device.
225 * @pport_id: port id to compare.
227 * Return: 1 if port device matches with given port id, otherwise 0.
231 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); in dfl_fpga_check_port_id()
234 if (pdata->id != FEATURE_DEV_ID_UNUSED) in dfl_fpga_check_port_id()
235 return pdata->id == *(int *)pport_id; in dfl_fpga_check_port_id()
238 if (!port_ops || !port_ops->get_id) in dfl_fpga_check_port_id()
241 pdata->id = port_ops->get_id(pdev); in dfl_fpga_check_port_id()
244 return pdata->id == *(int *)pport_id; in dfl_fpga_check_port_id()
251 dfl_match_one_device(const struct dfl_device_id *id, struct dfl_device *ddev) in dfl_match_one_device() argument
253 if (id->type == ddev->type && id->feature_id == ddev->feature_id) in dfl_match_one_device()
254 return id; in dfl_match_one_device()
259 static int dfl_bus_match(struct device *dev, struct device_driver *drv) in dfl_bus_match()
265 id_entry = ddrv->id_table; in dfl_bus_match()
267 while (id_entry->feature_id) { in dfl_bus_match()
269 ddev->id_entry = id_entry; in dfl_bus_match()
279 static int dfl_bus_probe(struct device *dev) in dfl_bus_probe()
281 struct dfl_driver *ddrv = to_dfl_drv(dev->driver); in dfl_bus_probe()
284 return ddrv->probe(ddev); in dfl_bus_probe()
287 static void dfl_bus_remove(struct device *dev) in dfl_bus_remove()
289 struct dfl_driver *ddrv = to_dfl_drv(dev->driver); in dfl_bus_remove()
292 if (ddrv->remove) in dfl_bus_remove()
293 ddrv->remove(ddev); in dfl_bus_remove()
296 static int dfl_bus_uevent(struct device *dev, struct kobj_uevent_env *env) in dfl_bus_uevent()
301 ddev->type, ddev->feature_id); in dfl_bus_uevent()
305 type_show(struct device *dev, struct device_attribute *attr, char *buf) in type_show()
309 return sprintf(buf, "0x%x\n", ddev->type); in type_show()
314 feature_id_show(struct device *dev, struct device_attribute *attr, char *buf) in feature_id_show()
318 return sprintf(buf, "0x%x\n", ddev->feature_id); in feature_id_show()
338 static void release_dfl_dev(struct device *dev) in release_dfl_dev()
342 if (ddev->mmio_res.parent) in release_dfl_dev()
343 release_resource(&ddev->mmio_res); in release_dfl_dev()
345 ida_free(&dfl_device_ida, ddev->id); in release_dfl_dev()
346 kfree(ddev->irqs); in release_dfl_dev()
354 struct platform_device *pdev = pdata->dev; in dfl_dev_add()
357 int id, i, ret; in dfl_dev_add() local
361 return ERR_PTR(-ENOMEM); in dfl_dev_add()
363 id = ida_alloc(&dfl_device_ida, GFP_KERNEL); in dfl_dev_add()
364 if (id < 0) { in dfl_dev_add()
365 dev_err(&pdev->dev, "unable to get id\n"); in dfl_dev_add()
367 return ERR_PTR(id); in dfl_dev_add()
371 device_initialize(&ddev->dev); in dfl_dev_add()
372 ddev->dev.parent = &pdev->dev; in dfl_dev_add()
373 ddev->dev.bus = &dfl_bus_type; in dfl_dev_add()
374 ddev->dev.release = release_dfl_dev; in dfl_dev_add()
375 ddev->id = id; in dfl_dev_add()
376 ret = dev_set_name(&ddev->dev, "dfl_dev.%d", id); in dfl_dev_add()
380 ddev->type = feature_dev_id_type(pdev); in dfl_dev_add()
381 ddev->feature_id = feature->id; in dfl_dev_add()
382 ddev->revision = feature->revision; in dfl_dev_add()
383 ddev->cdev = pdata->dfl_cdev; in dfl_dev_add()
386 parent_res = &pdev->resource[feature->resource_index]; in dfl_dev_add()
387 ddev->mmio_res.flags = IORESOURCE_MEM; in dfl_dev_add()
388 ddev->mmio_res.start = parent_res->start; in dfl_dev_add()
389 ddev->mmio_res.end = parent_res->end; in dfl_dev_add()
390 ddev->mmio_res.name = dev_name(&ddev->dev); in dfl_dev_add()
391 ret = insert_resource(parent_res, &ddev->mmio_res); in dfl_dev_add()
393 dev_err(&pdev->dev, "%s failed to claim resource: %pR\n", in dfl_dev_add()
394 dev_name(&ddev->dev), &ddev->mmio_res); in dfl_dev_add()
399 if (feature->nr_irqs) { in dfl_dev_add()
400 ddev->irqs = kcalloc(feature->nr_irqs, in dfl_dev_add()
401 sizeof(*ddev->irqs), GFP_KERNEL); in dfl_dev_add()
402 if (!ddev->irqs) { in dfl_dev_add()
403 ret = -ENOMEM; in dfl_dev_add()
407 for (i = 0; i < feature->nr_irqs; i++) in dfl_dev_add()
408 ddev->irqs[i] = feature->irq_ctx[i].irq; in dfl_dev_add()
410 ddev->num_irqs = feature->nr_irqs; in dfl_dev_add()
413 ret = device_add(&ddev->dev); in dfl_dev_add()
417 dev_dbg(&pdev->dev, "add dfl_dev: %s\n", dev_name(&ddev->dev)); in dfl_dev_add()
422 put_device(&ddev->dev); in dfl_dev_add()
431 if (feature->ddev) { in dfl_devs_remove()
432 device_unregister(&feature->ddev->dev); in dfl_devs_remove()
433 feature->ddev = NULL; in dfl_devs_remove()
445 if (feature->ioaddr) in dfl_devs_add()
448 if (feature->ddev) { in dfl_devs_add()
449 ret = -EEXIST; in dfl_devs_add()
459 feature->ddev = ddev; in dfl_devs_add()
471 if (!dfl_drv || !dfl_drv->probe || !dfl_drv->id_table) in __dfl_driver_register()
472 return -EINVAL; in __dfl_driver_register()
474 dfl_drv->drv.owner = owner; in __dfl_driver_register()
475 dfl_drv->drv.bus = &dfl_bus_type; in __dfl_driver_register()
477 return driver_register(&dfl_drv->drv); in __dfl_driver_register()
483 driver_unregister(&dfl_drv->drv); in dfl_driver_unregister()
487 #define is_header_feature(feature) ((feature)->id == FEATURE_ID_FIU_HEADER)
490 * dfl_fpga_dev_feature_uinit - uinit for sub features of dfl feature device
491 * @pdev: feature device.
495 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); in dfl_fpga_dev_feature_uinit()
501 if (feature->ops) { in dfl_fpga_dev_feature_uinit()
502 if (feature->ops->uinit) in dfl_fpga_dev_feature_uinit()
503 feature->ops->uinit(pdev, feature); in dfl_fpga_dev_feature_uinit()
504 feature->ops = NULL; in dfl_fpga_dev_feature_uinit()
520 feature->resource_index); in dfl_feature_instance_init()
522 dev_err(&pdev->dev, in dfl_feature_instance_init()
524 feature->id); in dfl_feature_instance_init()
528 feature->ioaddr = base; in dfl_feature_instance_init()
531 if (drv->ops->init) { in dfl_feature_instance_init()
532 ret = drv->ops->init(pdev, feature); in dfl_feature_instance_init()
537 feature->ops = drv->ops; in dfl_feature_instance_init()
545 const struct dfl_feature_id *ids = driver->id_table; in dfl_feature_drv_match()
548 while (ids->id) { in dfl_feature_drv_match()
549 if (ids->id == feature->id) in dfl_feature_drv_match()
558 * dfl_fpga_dev_feature_init - init for sub features of dfl feature device
559 * @pdev: feature device.
570 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); in dfl_fpga_dev_feature_init()
575 while (drv->ops) { in dfl_fpga_dev_feature_init()
628 static dev_t dfl_get_devt(enum dfl_fpga_devt_type type, int id) in dfl_get_devt() argument
633 return MKDEV(MAJOR(dfl_chrdevs[type].devt), id); in dfl_get_devt()
637 * dfl_fpga_dev_ops_register - register cdev ops for feature dev
649 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); in dfl_fpga_dev_ops_register()
651 cdev_init(&pdata->cdev, fops); in dfl_fpga_dev_ops_register()
652 pdata->cdev.owner = owner; in dfl_fpga_dev_ops_register()
655 * set parent to the feature device so that its refcount is in dfl_fpga_dev_ops_register()
657 * makes sure the feature device is valid during device in dfl_fpga_dev_ops_register()
658 * file's life-cycle. in dfl_fpga_dev_ops_register()
660 pdata->cdev.kobj.parent = &pdev->dev.kobj; in dfl_fpga_dev_ops_register()
662 return cdev_add(&pdata->cdev, pdev->dev.devt, 1); in dfl_fpga_dev_ops_register()
667 * dfl_fpga_dev_ops_unregister - unregister cdev ops for feature dev
672 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); in dfl_fpga_dev_ops_unregister()
674 cdev_del(&pdata->cdev); in dfl_fpga_dev_ops_unregister()
679 * struct build_feature_devs_info - info collected during feature dev build.
681 * @dev: device to enumerate.
682 * @cdev: the container device for all feature devices.
685 * this device.
686 * @feature_dev: current feature device.
690 * @sub_features: a sub features linked list for feature device in enumeration.
691 * @feature_num: number of sub features for feature device in enumeration.
694 struct device *dev;
708 * struct dfl_feature_info - sub feature info collected during feature dev build
710 * @fid: id of this sub feature.
730 struct dfl_feature_platform_data *pdata = dev_get_platdata(&port->dev); in dfl_fpga_cdev_add_port_dev()
732 mutex_lock(&cdev->lock); in dfl_fpga_cdev_add_port_dev()
733 list_add(&pdata->node, &cdev->port_dev_list); in dfl_fpga_cdev_add_port_dev()
734 get_device(&pdata->dev->dev); in dfl_fpga_cdev_add_port_dev()
735 mutex_unlock(&cdev->lock); in dfl_fpga_cdev_add_port_dev()
739 * register current feature device, it is called when we need to switch to
740 * another feature parsing or we have parsed all features on given device
745 struct platform_device *fdev = binfo->feature_dev; in build_info_commit_dev()
753 return -EINVAL; in build_info_commit_dev()
757 * the platform device. After calling platform_device_unregister(), in build_info_commit_dev()
758 * it will be automatically freed by device's release() callback, in build_info_commit_dev()
761 pdata = kzalloc(struct_size(pdata, features, binfo->feature_num), GFP_KERNEL); in build_info_commit_dev()
763 return -ENOMEM; in build_info_commit_dev()
765 pdata->dev = fdev; in build_info_commit_dev()
766 pdata->num = binfo->feature_num; in build_info_commit_dev()
767 pdata->dfl_cdev = binfo->cdev; in build_info_commit_dev()
768 pdata->id = FEATURE_DEV_ID_UNUSED; in build_info_commit_dev()
769 mutex_init(&pdata->lock); in build_info_commit_dev()
770 lockdep_set_class_and_name(&pdata->lock, &dfl_pdata_keys[type], in build_info_commit_dev()
776 * works properly for port device. in build_info_commit_dev()
777 * and it should always be 0 for fme device. in build_info_commit_dev()
779 WARN_ON(pdata->disable_count); in build_info_commit_dev()
781 fdev->dev.platform_data = pdata; in build_info_commit_dev()
784 fdev->num_resources = binfo->feature_num; in build_info_commit_dev()
785 fdev->resource = kcalloc(binfo->feature_num, sizeof(*fdev->resource), in build_info_commit_dev()
787 if (!fdev->resource) in build_info_commit_dev()
788 return -ENOMEM; in build_info_commit_dev()
791 list_for_each_entry_safe(finfo, p, &binfo->sub_features, node) { in build_info_commit_dev()
792 struct dfl_feature *feature = &pdata->features[index++]; in build_info_commit_dev()
797 feature->dev = fdev; in build_info_commit_dev()
798 feature->id = finfo->fid; in build_info_commit_dev()
799 feature->revision = finfo->revision; in build_info_commit_dev()
803 * set, port enable/disable) needed for the dfl bus device and in build_info_commit_dev()
805 * DFL bus device. And we should not assign it to feature in build_info_commit_dev()
806 * devices (dfl-fme/afu) again. in build_info_commit_dev()
809 feature->resource_index = -1; in build_info_commit_dev()
810 feature->ioaddr = in build_info_commit_dev()
811 devm_ioremap_resource(binfo->dev, in build_info_commit_dev()
812 &finfo->mmio_res); in build_info_commit_dev()
813 if (IS_ERR(feature->ioaddr)) in build_info_commit_dev()
814 return PTR_ERR(feature->ioaddr); in build_info_commit_dev()
816 feature->resource_index = res_idx; in build_info_commit_dev()
817 fdev->resource[res_idx++] = finfo->mmio_res; in build_info_commit_dev()
820 if (finfo->nr_irqs) { in build_info_commit_dev()
821 ctx = devm_kcalloc(binfo->dev, finfo->nr_irqs, in build_info_commit_dev()
824 return -ENOMEM; in build_info_commit_dev()
826 for (i = 0; i < finfo->nr_irqs; i++) in build_info_commit_dev()
828 binfo->irq_table[finfo->irq_base + i]; in build_info_commit_dev()
830 feature->irq_ctx = ctx; in build_info_commit_dev()
831 feature->nr_irqs = finfo->nr_irqs; in build_info_commit_dev()
834 list_del(&finfo->node); in build_info_commit_dev()
838 ret = platform_device_add(binfo->feature_dev); in build_info_commit_dev()
841 dfl_fpga_cdev_add_port_dev(binfo->cdev, in build_info_commit_dev()
842 binfo->feature_dev); in build_info_commit_dev()
844 binfo->cdev->fme_dev = in build_info_commit_dev()
845 get_device(&binfo->feature_dev->dev); in build_info_commit_dev()
853 binfo->feature_dev = NULL; in build_info_commit_dev()
866 return -EINVAL; in build_info_create_dev()
869 * we use -ENODEV as the initialization indicator which indicates in build_info_create_dev()
870 * whether the id need to be reclaimed in build_info_create_dev()
872 fdev = platform_device_alloc(dfl_devs[type].name, -ENODEV); in build_info_create_dev()
874 return -ENOMEM; in build_info_create_dev()
876 binfo->feature_dev = fdev; in build_info_create_dev()
877 binfo->feature_num = 0; in build_info_create_dev()
879 INIT_LIST_HEAD(&binfo->sub_features); in build_info_create_dev()
881 fdev->id = dfl_id_alloc(type, &fdev->dev); in build_info_create_dev()
882 if (fdev->id < 0) in build_info_create_dev()
883 return fdev->id; in build_info_create_dev()
885 fdev->dev.parent = &binfo->cdev->region->dev; in build_info_create_dev()
886 fdev->dev.devt = dfl_get_devt(dfl_devs[type].devt_type, fdev->id); in build_info_create_dev()
896 * it is a valid id, free it. See comments in in build_info_free()
899 if (binfo->feature_dev && binfo->feature_dev->id >= 0) { in build_info_free()
900 dfl_id_free(feature_dev_id_type(binfo->feature_dev), in build_info_free()
901 binfo->feature_dev->id); in build_info_free()
903 list_for_each_entry_safe(finfo, p, &binfo->sub_features, node) { in build_info_free()
904 list_del(&finfo->node); in build_info_free()
909 platform_device_put(binfo->feature_dev); in build_info_free()
911 devm_kfree(binfo->dev, binfo); in build_info_free()
923 u16 id = FIELD_GET(DFH_ID, value); in feature_id() local
929 return id; in feature_id()
941 void __iomem *base = binfo->ioaddr + ofst; in parse_feature_irqs()
947 type = feature_dev_id_type(binfo->feature_dev); in parse_feature_irqs()
990 dev_dbg(binfo->dev, "feature: 0x%x, irq_base: %u, nr_irqs: %u\n", in parse_feature_irqs()
993 if (ibase + inr > binfo->nr_irqs) { in parse_feature_irqs()
994 dev_err(binfo->dev, in parse_feature_irqs()
996 return -EINVAL; in parse_feature_irqs()
1000 virq = binfo->irq_table[ibase + i]; in parse_feature_irqs()
1002 dev_err(binfo->dev, in parse_feature_irqs()
1005 return -EINVAL; in parse_feature_irqs()
1017 * to provide resource size and feature id as they could be read from DFH
1033 v = readq(binfo->ioaddr + ofst); in create_feature_instance()
1036 /* read feature size and id if inputs are invalid */ in create_feature_instance()
1041 if (binfo->len - ofst < size) in create_feature_instance()
1042 return -EINVAL; in create_feature_instance()
1050 return -ENOMEM; in create_feature_instance()
1052 finfo->fid = fid; in create_feature_instance()
1053 finfo->revision = revision; in create_feature_instance()
1054 finfo->mmio_res.start = binfo->start + ofst; in create_feature_instance()
1055 finfo->mmio_res.end = finfo->mmio_res.start + size - 1; in create_feature_instance()
1056 finfo->mmio_res.flags = IORESOURCE_MEM; in create_feature_instance()
1057 finfo->irq_base = irq_base; in create_feature_instance()
1058 finfo->nr_irqs = nr_irqs; in create_feature_instance()
1060 list_add_tail(&finfo->node, &binfo->sub_features); in create_feature_instance()
1061 binfo->feature_num++; in create_feature_instance()
1069 u64 v = readq(binfo->ioaddr + PORT_HDR_CAP); in parse_feature_port_afu()
1077 #define is_feature_dev_detected(binfo) (!!(binfo)->feature_dev)
1083 dev_err(binfo->dev, "this AFU does not belong to any FIU.\n"); in parse_feature_afu()
1084 return -EINVAL; in parse_feature_afu()
1087 switch (feature_dev_id_type(binfo->feature_dev)) { in parse_feature_afu()
1091 dev_info(binfo->dev, "AFU belonging to FIU %s is not supported yet.\n", in parse_feature_afu()
1092 binfo->feature_dev->name); in parse_feature_afu()
1101 struct device *dev = binfo->dev; in build_info_prepare()
1107 return -EBUSY; in build_info_prepare()
1114 return -ENOMEM; in build_info_prepare()
1117 binfo->start = start; in build_info_prepare()
1118 binfo->len = len; in build_info_prepare()
1119 binfo->ioaddr = ioaddr; in build_info_prepare()
1126 devm_iounmap(binfo->dev, binfo->ioaddr); in build_info_complete()
1127 devm_release_mem_region(binfo->dev, binfo->start, binfo->len); in build_info_complete()
1135 u16 id; in parse_feature_fiu() local
1145 ret = build_info_prepare(binfo, binfo->start + ofst, in parse_feature_fiu()
1146 binfo->len - ofst); in parse_feature_fiu()
1151 v = readq(binfo->ioaddr + DFH); in parse_feature_fiu()
1152 id = FIELD_GET(DFH_ID, v); in parse_feature_fiu()
1154 /* create platform device for dfl feature dev */ in parse_feature_fiu()
1155 ret = build_info_create_dev(binfo, dfh_id_to_type(id)); in parse_feature_fiu()
1166 v = readq(binfo->ioaddr + NEXT_AFU); in parse_feature_fiu()
1172 dev_dbg(binfo->dev, "No AFUs detected on FIU %d\n", id); in parse_feature_fiu()
1181 dev_err(binfo->dev, "the private feature 0x%x does not belong to any AFU.\n", in parse_feature_private()
1182 feature_id(readq(binfo->ioaddr + ofst))); in parse_feature_private()
1183 return -EINVAL; in parse_feature_private()
1190 * parse_feature - parse a feature on given device feature list
1201 v = readq(binfo->ioaddr + ofst + DFH); in parse_feature()
1212 dev_info(binfo->dev, in parse_feature()
1231 /* walk through the device feature list via DFH's next DFH pointer. */ in parse_feature_list()
1233 if (end - start < DFH_SIZE) { in parse_feature_list()
1234 dev_err(binfo->dev, "The region is too small to contain a feature.\n"); in parse_feature_list()
1235 return -EINVAL; in parse_feature_list()
1238 ret = parse_feature(binfo, start - binfo->start); in parse_feature_list()
1242 v = readq(binfo->ioaddr + start - binfo->start + DFH); in parse_feature_list()
1250 /* commit current feature device when reach the end of list */ in parse_feature_list()
1259 struct dfl_fpga_enum_info *dfl_fpga_enum_info_alloc(struct device *dev) in dfl_fpga_enum_info_alloc()
1271 info->dev = dev; in dfl_fpga_enum_info_alloc()
1272 INIT_LIST_HEAD(&info->dfls); in dfl_fpga_enum_info_alloc()
1281 struct device *dev; in dfl_fpga_enum_info_free()
1286 dev = info->dev; in dfl_fpga_enum_info_free()
1288 /* remove all device feature lists in the list. */ in dfl_fpga_enum_info_free()
1289 list_for_each_entry_safe(dfl, tmp, &info->dfls, node) { in dfl_fpga_enum_info_free()
1290 list_del(&dfl->node); in dfl_fpga_enum_info_free()
1295 if (info->irq_table) in dfl_fpga_enum_info_free()
1296 devm_kfree(dev, info->irq_table); in dfl_fpga_enum_info_free()
1304 * dfl_fpga_enum_info_add_dfl - add info of a device feature list to enum info
1307 * @start: mmio resource address of the device feature list.
1308 * @len: mmio resource length of the device feature list.
1310 * One FPGA device may have one or more Device Feature Lists (DFLs), use this
1321 dfl = devm_kzalloc(info->dev, sizeof(*dfl), GFP_KERNEL); in dfl_fpga_enum_info_add_dfl()
1323 return -ENOMEM; in dfl_fpga_enum_info_add_dfl()
1325 dfl->start = start; in dfl_fpga_enum_info_add_dfl()
1326 dfl->len = len; in dfl_fpga_enum_info_add_dfl()
1328 list_add_tail(&dfl->node, &info->dfls); in dfl_fpga_enum_info_add_dfl()
1335 * dfl_fpga_enum_info_add_irq - add irq table to enum info
1338 * @nr_irqs: number of irqs of the DFL fpga device to be enumerated.
1340 * this device.
1342 * One FPGA device may have several interrupts. This function adds irq
1343 * information of the DFL fpga device to enum info for next step enumeration.
1357 return -EINVAL; in dfl_fpga_enum_info_add_irq()
1359 if (info->irq_table) in dfl_fpga_enum_info_add_irq()
1360 return -EEXIST; in dfl_fpga_enum_info_add_irq()
1362 info->irq_table = devm_kmemdup(info->dev, irq_table, in dfl_fpga_enum_info_add_irq()
1364 if (!info->irq_table) in dfl_fpga_enum_info_add_irq()
1365 return -ENOMEM; in dfl_fpga_enum_info_add_irq()
1367 info->nr_irqs = nr_irqs; in dfl_fpga_enum_info_add_irq()
1373 static int remove_feature_dev(struct device *dev, void *data) in remove_feature_dev()
1377 int id = pdev->id; in remove_feature_dev() local
1381 dfl_id_free(type, id); in remove_feature_dev()
1388 device_for_each_child(&cdev->region->dev, NULL, remove_feature_dev); in remove_feature_devs()
1392 * dfl_fpga_feature_devs_enumerate - enumerate feature devices
1395 * This function creates a container device (base FPGA region), enumerates
1397 * under the container device.
1399 * Return: dfl_fpga_cdev struct on success, -errno on failure
1409 if (!info->dev) in dfl_fpga_feature_devs_enumerate()
1410 return ERR_PTR(-ENODEV); in dfl_fpga_feature_devs_enumerate()
1412 cdev = devm_kzalloc(info->dev, sizeof(*cdev), GFP_KERNEL); in dfl_fpga_feature_devs_enumerate()
1414 return ERR_PTR(-ENOMEM); in dfl_fpga_feature_devs_enumerate()
1416 cdev->parent = info->dev; in dfl_fpga_feature_devs_enumerate()
1417 mutex_init(&cdev->lock); in dfl_fpga_feature_devs_enumerate()
1418 INIT_LIST_HEAD(&cdev->port_dev_list); in dfl_fpga_feature_devs_enumerate()
1420 cdev->region = fpga_region_register(info->dev, NULL, NULL); in dfl_fpga_feature_devs_enumerate()
1421 if (IS_ERR(cdev->region)) { in dfl_fpga_feature_devs_enumerate()
1422 ret = PTR_ERR(cdev->region); in dfl_fpga_feature_devs_enumerate()
1427 binfo = devm_kzalloc(info->dev, sizeof(*binfo), GFP_KERNEL); in dfl_fpga_feature_devs_enumerate()
1429 ret = -ENOMEM; in dfl_fpga_feature_devs_enumerate()
1433 binfo->dev = info->dev; in dfl_fpga_feature_devs_enumerate()
1434 binfo->cdev = cdev; in dfl_fpga_feature_devs_enumerate()
1436 binfo->nr_irqs = info->nr_irqs; in dfl_fpga_feature_devs_enumerate()
1437 if (info->nr_irqs) in dfl_fpga_feature_devs_enumerate()
1438 binfo->irq_table = info->irq_table; in dfl_fpga_feature_devs_enumerate()
1441 * start enumeration for all feature devices based on Device Feature in dfl_fpga_feature_devs_enumerate()
1444 list_for_each_entry(dfl, &info->dfls, node) { in dfl_fpga_feature_devs_enumerate()
1445 ret = parse_feature_list(binfo, dfl->start, dfl->len); in dfl_fpga_feature_devs_enumerate()
1458 fpga_region_unregister(cdev->region); in dfl_fpga_feature_devs_enumerate()
1460 devm_kfree(info->dev, cdev); in dfl_fpga_feature_devs_enumerate()
1466 * dfl_fpga_feature_devs_remove - remove all feature devices
1467 * @cdev: fpga container device.
1469 * Remove the container device and all feature devices under given container
1476 mutex_lock(&cdev->lock); in dfl_fpga_feature_devs_remove()
1477 if (cdev->fme_dev) in dfl_fpga_feature_devs_remove()
1478 put_device(cdev->fme_dev); in dfl_fpga_feature_devs_remove()
1480 list_for_each_entry_safe(pdata, ptmp, &cdev->port_dev_list, node) { in dfl_fpga_feature_devs_remove()
1481 struct platform_device *port_dev = pdata->dev; in dfl_fpga_feature_devs_remove()
1484 if (!device_is_registered(&port_dev->dev)) { in dfl_fpga_feature_devs_remove()
1486 port_dev->id); in dfl_fpga_feature_devs_remove()
1490 list_del(&pdata->node); in dfl_fpga_feature_devs_remove()
1491 put_device(&port_dev->dev); in dfl_fpga_feature_devs_remove()
1493 mutex_unlock(&cdev->lock); in dfl_fpga_feature_devs_remove()
1497 fpga_region_unregister(cdev->region); in dfl_fpga_feature_devs_remove()
1498 devm_kfree(cdev->parent, cdev); in dfl_fpga_feature_devs_remove()
1503 * __dfl_fpga_cdev_find_port - find a port under given container device
1505 * @cdev: container device
1507 * @match: match function used to find specific port from the port device list
1509 * Find a port device under container device. This function needs to be
1512 * Return: pointer to port's platform device if successful, NULL otherwise.
1514 * NOTE: you will need to drop the device reference with put_device() after use.
1523 list_for_each_entry(pdata, &cdev->port_dev_list, node) { in __dfl_fpga_cdev_find_port()
1524 port_dev = pdata->dev; in __dfl_fpga_cdev_find_port()
1526 if (match(port_dev, data) && get_device(&port_dev->dev)) in __dfl_fpga_cdev_find_port()
1554 * dfl_fpga_cdev_release_port - release a port platform device
1556 * @cdev: parent container device.
1557 * @port_id: id of the port platform device.
1559 * This function allows user to release a port platform device. This is a
1568 int ret = -ENODEV; in dfl_fpga_cdev_release_port()
1570 mutex_lock(&cdev->lock); in dfl_fpga_cdev_release_port()
1576 if (!device_is_registered(&port_pdev->dev)) { in dfl_fpga_cdev_release_port()
1577 ret = -EBUSY; in dfl_fpga_cdev_release_port()
1581 pdata = dev_get_platdata(&port_pdev->dev); in dfl_fpga_cdev_release_port()
1583 mutex_lock(&pdata->lock); in dfl_fpga_cdev_release_port()
1585 mutex_unlock(&pdata->lock); in dfl_fpga_cdev_release_port()
1590 cdev->released_port_num++; in dfl_fpga_cdev_release_port()
1592 put_device(&port_pdev->dev); in dfl_fpga_cdev_release_port()
1594 mutex_unlock(&cdev->lock); in dfl_fpga_cdev_release_port()
1600 * dfl_fpga_cdev_assign_port - assign a port platform device back
1602 * @cdev: parent container device.
1603 * @port_id: id of the port platform device.
1605 * This function allows user to assign a port platform device back. This is
1614 int ret = -ENODEV; in dfl_fpga_cdev_assign_port()
1616 mutex_lock(&cdev->lock); in dfl_fpga_cdev_assign_port()
1622 if (device_is_registered(&port_pdev->dev)) { in dfl_fpga_cdev_assign_port()
1623 ret = -EBUSY; in dfl_fpga_cdev_assign_port()
1631 pdata = dev_get_platdata(&port_pdev->dev); in dfl_fpga_cdev_assign_port()
1633 mutex_lock(&pdata->lock); in dfl_fpga_cdev_assign_port()
1635 mutex_unlock(&pdata->lock); in dfl_fpga_cdev_assign_port()
1637 cdev->released_port_num--; in dfl_fpga_cdev_assign_port()
1639 put_device(&port_pdev->dev); in dfl_fpga_cdev_assign_port()
1641 mutex_unlock(&cdev->lock); in dfl_fpga_cdev_assign_port()
1646 static void config_port_access_mode(struct device *fme_dev, int port_id, in config_port_access_mode()
1663 #define config_port_vf_mode(dev, id) config_port_access_mode(dev, id, true) argument
1664 #define config_port_pf_mode(dev, id) config_port_access_mode(dev, id, false) argument
1667 * dfl_fpga_cdev_config_ports_pf - configure ports to PF access mode
1669 * @cdev: parent container device.
1678 mutex_lock(&cdev->lock); in dfl_fpga_cdev_config_ports_pf()
1679 list_for_each_entry(pdata, &cdev->port_dev_list, node) { in dfl_fpga_cdev_config_ports_pf()
1680 if (device_is_registered(&pdata->dev->dev)) in dfl_fpga_cdev_config_ports_pf()
1683 config_port_pf_mode(cdev->fme_dev, pdata->id); in dfl_fpga_cdev_config_ports_pf()
1685 mutex_unlock(&cdev->lock); in dfl_fpga_cdev_config_ports_pf()
1690 * dfl_fpga_cdev_config_ports_vf - configure ports to VF access mode
1692 * @cdev: parent container device.
1693 * @num_vfs: VF device number.
1705 mutex_lock(&cdev->lock); in dfl_fpga_cdev_config_ports_vf()
1707 * can't turn multiple ports into 1 VF device, only 1 port for 1 VF in dfl_fpga_cdev_config_ports_vf()
1708 * device, so if released port number doesn't match VF device number, in dfl_fpga_cdev_config_ports_vf()
1709 * then reject the request with -EINVAL error code. in dfl_fpga_cdev_config_ports_vf()
1711 if (cdev->released_port_num != num_vfs) { in dfl_fpga_cdev_config_ports_vf()
1712 ret = -EINVAL; in dfl_fpga_cdev_config_ports_vf()
1716 list_for_each_entry(pdata, &cdev->port_dev_list, node) { in dfl_fpga_cdev_config_ports_vf()
1717 if (device_is_registered(&pdata->dev->dev)) in dfl_fpga_cdev_config_ports_vf()
1720 config_port_vf_mode(cdev->fme_dev, pdata->id); in dfl_fpga_cdev_config_ports_vf()
1723 mutex_unlock(&cdev->lock); in dfl_fpga_cdev_config_ports_vf()
1739 struct platform_device *pdev = feature->dev; in do_set_irq_trigger()
1743 irq = feature->irq_ctx[idx].irq; in do_set_irq_trigger()
1745 if (feature->irq_ctx[idx].trigger) { in do_set_irq_trigger()
1746 free_irq(irq, feature->irq_ctx[idx].trigger); in do_set_irq_trigger()
1747 kfree(feature->irq_ctx[idx].name); in do_set_irq_trigger()
1748 eventfd_ctx_put(feature->irq_ctx[idx].trigger); in do_set_irq_trigger()
1749 feature->irq_ctx[idx].trigger = NULL; in do_set_irq_trigger()
1755 feature->irq_ctx[idx].name = in do_set_irq_trigger()
1756 kasprintf(GFP_KERNEL, "fpga-irq[%u](%s-%x)", idx, in do_set_irq_trigger()
1757 dev_name(&pdev->dev), feature->id); in do_set_irq_trigger()
1758 if (!feature->irq_ctx[idx].name) in do_set_irq_trigger()
1759 return -ENOMEM; in do_set_irq_trigger()
1768 feature->irq_ctx[idx].name, trigger); in do_set_irq_trigger()
1770 feature->irq_ctx[idx].trigger = trigger; in do_set_irq_trigger()
1776 kfree(feature->irq_ctx[idx].name); in do_set_irq_trigger()
1782 * dfl_fpga_set_irq_triggers - set eventfd triggers for dfl feature interrupts
1804 return -EINVAL; in dfl_fpga_set_irq_triggers()
1807 if (start + count > feature->nr_irqs) in dfl_fpga_set_irq_triggers()
1808 return -EINVAL; in dfl_fpga_set_irq_triggers()
1811 int fd = fds ? fds[i] : -1; in dfl_fpga_set_irq_triggers()
1815 while (i--) in dfl_fpga_set_irq_triggers()
1816 do_set_irq_trigger(feature, start + i, -1); in dfl_fpga_set_irq_triggers()
1826 * dfl_feature_ioctl_get_num_irqs - dfl feature _GET_IRQ_NUM ioctl interface.
1827 * @pdev: the feature device which has the sub feature
1837 return put_user(feature->nr_irqs, (__u32 __user *)arg); in dfl_feature_ioctl_get_num_irqs()
1842 * dfl_feature_ioctl_set_irq - dfl feature _SET_IRQ ioctl interface.
1843 * @pdev: the feature device which has the sub feature
1853 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); in dfl_feature_ioctl_set_irq()
1858 if (!feature->nr_irqs) in dfl_feature_ioctl_set_irq()
1859 return -ENOENT; in dfl_feature_ioctl_set_irq()
1862 return -EFAULT; in dfl_feature_ioctl_set_irq()
1864 if (!hdr.count || (hdr.start + hdr.count > feature->nr_irqs) || in dfl_feature_ioctl_set_irq()
1866 return -EINVAL; in dfl_feature_ioctl_set_irq()
1873 mutex_lock(&pdata->lock); in dfl_feature_ioctl_set_irq()
1875 mutex_unlock(&pdata->lock); in dfl_feature_ioctl_set_irq()
1892 MODULE_DESCRIPTION("FPGA Device Feature List (DFL) Support");