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.
13 #include <linux/fpga-dfl.h>
25 * platform device creation (define name strings in dfl.h, as they could be
26 * reused by platform device drivers).
42 "dfl-fme-pdata",
43 "dfl-port-pdata",
47 * dfl_dev_info - dfl feature device information.
48 * @name: name string of the feature platform device.
49 * @dfh_id: id value in Device Feature Header (DFH) register by DFL spec.
50 * @id: idr id of the feature dev.
56 struct idr id; member
69 * dfl_chardev_info - chardev information of dfl feature device
70 * @name: nmae string of the char device.
71 * @devt: devt of the char device.
89 idr_init(&dfl_devs[i].id); in dfl_ids_init()
97 idr_destroy(&dfl_devs[i].id); in dfl_ids_destroy()
100 static int dfl_id_alloc(enum dfl_id_type type, struct device *dev) in dfl_id_alloc()
102 int id; in dfl_id_alloc() local
106 id = idr_alloc(&dfl_devs[type].id, dev, 0, 0, GFP_KERNEL); in dfl_id_alloc()
109 return id; in dfl_id_alloc()
112 static void dfl_id_free(enum dfl_id_type type, int id) in dfl_id_free() argument
116 idr_remove(&dfl_devs[type].id, id); in dfl_id_free()
125 if (!strcmp(dfl_devs[i].name, pdev->name)) in feature_dev_id_type()
131 static enum dfl_id_type dfh_id_to_type(u16 id) in dfh_id_to_type() argument
136 if (dfl_devs[i].dfh_id == id) in dfh_id_to_type()
145 * functions even related port platform device is hidden. Below is one example,
146 * in virtualization case of PCIe-based FPGA DFL device, when SRIOV is
147 * enabled, port (and it's AFU) is turned into VF and port platform device
156 * dfl_fpga_port_ops_get - get matched port ops from the global list
157 * @pdev: platform device to match with associated port ops.
171 /* match port_ops using the name of platform device */ in dfl_fpga_port_ops_get()
172 if (!strcmp(pdev->name, ops->name)) { in dfl_fpga_port_ops_get()
173 if (!try_module_get(ops->owner)) in dfl_fpga_port_ops_get()
187 * dfl_fpga_port_ops_put - put port ops
192 if (ops && ops->owner) in dfl_fpga_port_ops_put()
193 module_put(ops->owner); in dfl_fpga_port_ops_put()
198 * dfl_fpga_port_ops_add - add port_ops to global list
204 list_add_tail(&ops->node, &dfl_port_ops_list); in dfl_fpga_port_ops_add()
210 * dfl_fpga_port_ops_del - remove port_ops from global list
216 list_del(&ops->node); in dfl_fpga_port_ops_del()
222 * dfl_fpga_check_port_id - check the port id
223 * @pdev: port platform device.
224 * @pport_id: port id to compare.
226 * Return: 1 if port device matches with given port id, otherwise 0.
230 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); in dfl_fpga_check_port_id()
233 if (pdata->id != FEATURE_DEV_ID_UNUSED) in dfl_fpga_check_port_id()
234 return pdata->id == *(int *)pport_id; in dfl_fpga_check_port_id()
237 if (!port_ops || !port_ops->get_id) in dfl_fpga_check_port_id()
240 pdata->id = port_ops->get_id(pdev); in dfl_fpga_check_port_id()
243 return pdata->id == *(int *)pport_id; in dfl_fpga_check_port_id()
250 dfl_match_one_device(const struct dfl_device_id *id, struct dfl_device *ddev) in dfl_match_one_device() argument
252 if (id->type == ddev->type && id->feature_id == ddev->feature_id) in dfl_match_one_device()
253 return id; in dfl_match_one_device()
258 static int dfl_bus_match(struct device *dev, struct device_driver *drv) in dfl_bus_match()
264 id_entry = ddrv->id_table; in dfl_bus_match()
266 while (id_entry->feature_id) { in dfl_bus_match()
268 ddev->id_entry = id_entry; in dfl_bus_match()
278 static int dfl_bus_probe(struct device *dev) in dfl_bus_probe()
280 struct dfl_driver *ddrv = to_dfl_drv(dev->driver); in dfl_bus_probe()
283 return ddrv->probe(ddev); in dfl_bus_probe()
286 static int dfl_bus_remove(struct device *dev) in dfl_bus_remove()
288 struct dfl_driver *ddrv = to_dfl_drv(dev->driver); in dfl_bus_remove()
291 if (ddrv->remove) in dfl_bus_remove()
292 ddrv->remove(ddev); in dfl_bus_remove()
297 static int dfl_bus_uevent(struct device *dev, struct kobj_uevent_env *env) in dfl_bus_uevent()
303 ddev->type, ddev->feature_id); in dfl_bus_uevent()
307 type_show(struct device *dev, struct device_attribute *attr, char *buf) in type_show()
311 return sprintf(buf, "0x%x\n", ddev->type); in type_show()
316 feature_id_show(struct device *dev, struct device_attribute *attr, char *buf) in feature_id_show()
320 return sprintf(buf, "0x%x\n", ddev->feature_id); in feature_id_show()
340 static void release_dfl_dev(struct device *dev) in release_dfl_dev()
344 if (ddev->mmio_res.parent) in release_dfl_dev()
345 release_resource(&ddev->mmio_res); in release_dfl_dev()
347 ida_simple_remove(&dfl_device_ida, ddev->id); in release_dfl_dev()
348 kfree(ddev->irqs); in release_dfl_dev()
356 struct platform_device *pdev = pdata->dev; in dfl_dev_add()
359 int id, i, ret; in dfl_dev_add() local
363 return ERR_PTR(-ENOMEM); in dfl_dev_add()
365 id = ida_simple_get(&dfl_device_ida, 0, 0, GFP_KERNEL); in dfl_dev_add()
366 if (id < 0) { in dfl_dev_add()
367 dev_err(&pdev->dev, "unable to get id\n"); in dfl_dev_add()
369 return ERR_PTR(id); in dfl_dev_add()
373 device_initialize(&ddev->dev); in dfl_dev_add()
374 ddev->dev.parent = &pdev->dev; in dfl_dev_add()
375 ddev->dev.bus = &dfl_bus_type; in dfl_dev_add()
376 ddev->dev.release = release_dfl_dev; in dfl_dev_add()
377 ddev->id = id; in dfl_dev_add()
378 ret = dev_set_name(&ddev->dev, "dfl_dev.%d", id); in dfl_dev_add()
382 ddev->type = feature_dev_id_type(pdev); in dfl_dev_add()
383 ddev->feature_id = feature->id; in dfl_dev_add()
384 ddev->cdev = pdata->dfl_cdev; in dfl_dev_add()
387 parent_res = &pdev->resource[feature->resource_index]; in dfl_dev_add()
388 ddev->mmio_res.flags = IORESOURCE_MEM; in dfl_dev_add()
389 ddev->mmio_res.start = parent_res->start; in dfl_dev_add()
390 ddev->mmio_res.end = parent_res->end; in dfl_dev_add()
391 ddev->mmio_res.name = dev_name(&ddev->dev); in dfl_dev_add()
392 ret = insert_resource(parent_res, &ddev->mmio_res); in dfl_dev_add()
394 dev_err(&pdev->dev, "%s failed to claim resource: %pR\n", in dfl_dev_add()
395 dev_name(&ddev->dev), &ddev->mmio_res); in dfl_dev_add()
400 if (feature->nr_irqs) { in dfl_dev_add()
401 ddev->irqs = kcalloc(feature->nr_irqs, in dfl_dev_add()
402 sizeof(*ddev->irqs), GFP_KERNEL); in dfl_dev_add()
403 if (!ddev->irqs) { in dfl_dev_add()
404 ret = -ENOMEM; in dfl_dev_add()
408 for (i = 0; i < feature->nr_irqs; i++) in dfl_dev_add()
409 ddev->irqs[i] = feature->irq_ctx[i].irq; in dfl_dev_add()
411 ddev->num_irqs = feature->nr_irqs; in dfl_dev_add()
414 ret = device_add(&ddev->dev); in dfl_dev_add()
418 dev_dbg(&pdev->dev, "add dfl_dev: %s\n", dev_name(&ddev->dev)); in dfl_dev_add()
423 put_device(&ddev->dev); in dfl_dev_add()
432 if (feature->ddev) { in dfl_devs_remove()
433 device_unregister(&feature->ddev->dev); in dfl_devs_remove()
434 feature->ddev = NULL; in dfl_devs_remove()
446 if (feature->ioaddr) in dfl_devs_add()
449 if (feature->ddev) { in dfl_devs_add()
450 ret = -EEXIST; in dfl_devs_add()
460 feature->ddev = ddev; in dfl_devs_add()
472 if (!dfl_drv || !dfl_drv->probe || !dfl_drv->id_table) in __dfl_driver_register()
473 return -EINVAL; in __dfl_driver_register()
475 dfl_drv->drv.owner = owner; in __dfl_driver_register()
476 dfl_drv->drv.bus = &dfl_bus_type; in __dfl_driver_register()
478 return driver_register(&dfl_drv->drv); in __dfl_driver_register()
484 driver_unregister(&dfl_drv->drv); in dfl_driver_unregister()
488 #define is_header_feature(feature) ((feature)->id == FEATURE_ID_FIU_HEADER)
491 * dfl_fpga_dev_feature_uinit - uinit for sub features of dfl feature device
492 * @pdev: feature device.
496 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); in dfl_fpga_dev_feature_uinit()
502 if (feature->ops) { in dfl_fpga_dev_feature_uinit()
503 if (feature->ops->uinit) in dfl_fpga_dev_feature_uinit()
504 feature->ops->uinit(pdev, feature); in dfl_fpga_dev_feature_uinit()
505 feature->ops = NULL; in dfl_fpga_dev_feature_uinit()
521 feature->resource_index); in dfl_feature_instance_init()
523 dev_err(&pdev->dev, in dfl_feature_instance_init()
525 feature->id); in dfl_feature_instance_init()
529 feature->ioaddr = base; in dfl_feature_instance_init()
532 if (drv->ops->init) { in dfl_feature_instance_init()
533 ret = drv->ops->init(pdev, feature); in dfl_feature_instance_init()
538 feature->ops = drv->ops; in dfl_feature_instance_init()
546 const struct dfl_feature_id *ids = driver->id_table; in dfl_feature_drv_match()
549 while (ids->id) { in dfl_feature_drv_match()
550 if (ids->id == feature->id) in dfl_feature_drv_match()
559 * dfl_fpga_dev_feature_init - init for sub features of dfl feature device
560 * @pdev: feature device.
571 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); in dfl_fpga_dev_feature_init()
576 while (drv->ops) { in dfl_fpga_dev_feature_init()
629 static dev_t dfl_get_devt(enum dfl_fpga_devt_type type, int id) in dfl_get_devt() argument
634 return MKDEV(MAJOR(dfl_chrdevs[type].devt), id); in dfl_get_devt()
638 * dfl_fpga_dev_ops_register - register cdev ops for feature dev
650 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); in dfl_fpga_dev_ops_register()
652 cdev_init(&pdata->cdev, fops); in dfl_fpga_dev_ops_register()
653 pdata->cdev.owner = owner; in dfl_fpga_dev_ops_register()
656 * set parent to the feature device so that its refcount is in dfl_fpga_dev_ops_register()
658 * makes sure the feature device is valid during device in dfl_fpga_dev_ops_register()
659 * file's life-cycle. in dfl_fpga_dev_ops_register()
661 pdata->cdev.kobj.parent = &pdev->dev.kobj; in dfl_fpga_dev_ops_register()
663 return cdev_add(&pdata->cdev, pdev->dev.devt, 1); in dfl_fpga_dev_ops_register()
668 * dfl_fpga_dev_ops_unregister - unregister cdev ops for feature dev
673 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); in dfl_fpga_dev_ops_unregister()
675 cdev_del(&pdata->cdev); in dfl_fpga_dev_ops_unregister()
680 * struct build_feature_devs_info - info collected during feature dev build.
682 * @dev: device to enumerate.
683 * @cdev: the container device for all feature devices.
686 * this device.
687 * @feature_dev: current feature device.
691 * @sub_features: a sub features linked list for feature device in enumeration.
692 * @feature_num: number of sub features for feature device in enumeration.
695 struct device *dev;
709 * struct dfl_feature_info - sub feature info collected during feature dev build
711 * @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()
802 * set, port enable/disable) needed for the dfl bus device and in build_info_commit_dev()
804 * DFL bus device. And we should not assign it to feature in build_info_commit_dev()
805 * devices (dfl-fme/afu) again. in build_info_commit_dev()
808 feature->resource_index = -1; in build_info_commit_dev()
809 feature->ioaddr = in build_info_commit_dev()
810 devm_ioremap_resource(binfo->dev, in build_info_commit_dev()
811 &finfo->mmio_res); in build_info_commit_dev()
812 if (IS_ERR(feature->ioaddr)) in build_info_commit_dev()
813 return PTR_ERR(feature->ioaddr); in build_info_commit_dev()
815 feature->resource_index = res_idx; in build_info_commit_dev()
816 fdev->resource[res_idx++] = finfo->mmio_res; in build_info_commit_dev()
819 if (finfo->nr_irqs) { in build_info_commit_dev()
820 ctx = devm_kcalloc(binfo->dev, finfo->nr_irqs, in build_info_commit_dev()
823 return -ENOMEM; in build_info_commit_dev()
825 for (i = 0; i < finfo->nr_irqs; i++) in build_info_commit_dev()
827 binfo->irq_table[finfo->irq_base + i]; in build_info_commit_dev()
829 feature->irq_ctx = ctx; in build_info_commit_dev()
830 feature->nr_irqs = finfo->nr_irqs; in build_info_commit_dev()
833 list_del(&finfo->node); in build_info_commit_dev()
837 ret = platform_device_add(binfo->feature_dev); in build_info_commit_dev()
840 dfl_fpga_cdev_add_port_dev(binfo->cdev, in build_info_commit_dev()
841 binfo->feature_dev); in build_info_commit_dev()
843 binfo->cdev->fme_dev = in build_info_commit_dev()
844 get_device(&binfo->feature_dev->dev); in build_info_commit_dev()
852 binfo->feature_dev = NULL; in build_info_commit_dev()
865 return -EINVAL; in build_info_create_dev()
868 * we use -ENODEV as the initialization indicator which indicates in build_info_create_dev()
869 * whether the id need to be reclaimed in build_info_create_dev()
871 fdev = platform_device_alloc(dfl_devs[type].name, -ENODEV); in build_info_create_dev()
873 return -ENOMEM; in build_info_create_dev()
875 binfo->feature_dev = fdev; in build_info_create_dev()
876 binfo->feature_num = 0; in build_info_create_dev()
878 INIT_LIST_HEAD(&binfo->sub_features); in build_info_create_dev()
880 fdev->id = dfl_id_alloc(type, &fdev->dev); in build_info_create_dev()
881 if (fdev->id < 0) in build_info_create_dev()
882 return fdev->id; in build_info_create_dev()
884 fdev->dev.parent = &binfo->cdev->region->dev; in build_info_create_dev()
885 fdev->dev.devt = dfl_get_devt(dfl_devs[type].devt_type, fdev->id); in build_info_create_dev()
895 * it is a valid id, free it. See comments in in build_info_free()
898 if (binfo->feature_dev && binfo->feature_dev->id >= 0) { in build_info_free()
899 dfl_id_free(feature_dev_id_type(binfo->feature_dev), in build_info_free()
900 binfo->feature_dev->id); in build_info_free()
902 list_for_each_entry_safe(finfo, p, &binfo->sub_features, node) { in build_info_free()
903 list_del(&finfo->node); in build_info_free()
908 platform_device_put(binfo->feature_dev); in build_info_free()
910 devm_kfree(binfo->dev, binfo); in build_info_free()
924 u16 id = FIELD_GET(DFH_ID, v); in feature_id() local
930 return id; in feature_id()
942 void __iomem *base = binfo->ioaddr + ofst; in parse_feature_irqs()
985 dev_dbg(binfo->dev, "feature: 0x%x, irq_base: %u, nr_irqs: %u\n", in parse_feature_irqs()
988 if (ibase + inr > binfo->nr_irqs) { in parse_feature_irqs()
989 dev_err(binfo->dev, in parse_feature_irqs()
991 return -EINVAL; in parse_feature_irqs()
995 virq = binfo->irq_table[ibase + i]; in parse_feature_irqs()
997 dev_err(binfo->dev, in parse_feature_irqs()
1000 return -EINVAL; in parse_feature_irqs()
1012 * to provide resource size and feature id as they could be read from DFH
1025 /* read feature size and id if inputs are invalid */ in create_feature_instance()
1026 size = size ? size : feature_size(binfo->ioaddr + ofst); in create_feature_instance()
1027 fid = fid ? fid : feature_id(binfo->ioaddr + ofst); in create_feature_instance()
1029 if (binfo->len - ofst < size) in create_feature_instance()
1030 return -EINVAL; in create_feature_instance()
1038 return -ENOMEM; in create_feature_instance()
1040 finfo->fid = fid; in create_feature_instance()
1041 finfo->mmio_res.start = binfo->start + ofst; in create_feature_instance()
1042 finfo->mmio_res.end = finfo->mmio_res.start + size - 1; in create_feature_instance()
1043 finfo->mmio_res.flags = IORESOURCE_MEM; in create_feature_instance()
1044 finfo->irq_base = irq_base; in create_feature_instance()
1045 finfo->nr_irqs = nr_irqs; in create_feature_instance()
1047 list_add_tail(&finfo->node, &binfo->sub_features); in create_feature_instance()
1048 binfo->feature_num++; in create_feature_instance()
1056 u64 v = readq(binfo->ioaddr + PORT_HDR_CAP); in parse_feature_port_afu()
1064 #define is_feature_dev_detected(binfo) (!!(binfo)->feature_dev)
1070 dev_err(binfo->dev, "this AFU does not belong to any FIU.\n"); in parse_feature_afu()
1071 return -EINVAL; in parse_feature_afu()
1074 switch (feature_dev_id_type(binfo->feature_dev)) { in parse_feature_afu()
1078 dev_info(binfo->dev, "AFU belonging to FIU %s is not supported yet.\n", in parse_feature_afu()
1079 binfo->feature_dev->name); in parse_feature_afu()
1088 struct device *dev = binfo->dev; in build_info_prepare()
1094 return -EBUSY; in build_info_prepare()
1101 return -ENOMEM; in build_info_prepare()
1104 binfo->start = start; in build_info_prepare()
1105 binfo->len = len; in build_info_prepare()
1106 binfo->ioaddr = ioaddr; in build_info_prepare()
1113 devm_iounmap(binfo->dev, binfo->ioaddr); in build_info_complete()
1114 devm_release_mem_region(binfo->dev, binfo->start, binfo->len); in build_info_complete()
1122 u16 id; in parse_feature_fiu() local
1132 ret = build_info_prepare(binfo, binfo->start + ofst, in parse_feature_fiu()
1133 binfo->len - ofst); in parse_feature_fiu()
1138 v = readq(binfo->ioaddr + DFH); in parse_feature_fiu()
1139 id = FIELD_GET(DFH_ID, v); in parse_feature_fiu()
1141 /* create platform device for dfl feature dev */ in parse_feature_fiu()
1142 ret = build_info_create_dev(binfo, dfh_id_to_type(id)); in parse_feature_fiu()
1153 v = readq(binfo->ioaddr + NEXT_AFU); in parse_feature_fiu()
1159 dev_dbg(binfo->dev, "No AFUs detected on FIU %d\n", id); in parse_feature_fiu()
1168 dev_err(binfo->dev, "the private feature 0x%x does not belong to any AFU.\n", in parse_feature_private()
1169 feature_id(binfo->ioaddr + ofst)); in parse_feature_private()
1170 return -EINVAL; in parse_feature_private()
1177 * parse_feature - parse a feature on given device feature list
1188 v = readq(binfo->ioaddr + ofst + DFH); in parse_feature()
1199 dev_info(binfo->dev, in parse_feature()
1218 /* walk through the device feature list via DFH's next DFH pointer. */ in parse_feature_list()
1220 if (end - start < DFH_SIZE) { in parse_feature_list()
1221 dev_err(binfo->dev, "The region is too small to contain a feature.\n"); in parse_feature_list()
1222 return -EINVAL; in parse_feature_list()
1225 ret = parse_feature(binfo, start - binfo->start); in parse_feature_list()
1229 v = readq(binfo->ioaddr + start - binfo->start + DFH); in parse_feature_list()
1237 /* commit current feature device when reach the end of list */ in parse_feature_list()
1246 struct dfl_fpga_enum_info *dfl_fpga_enum_info_alloc(struct device *dev) in dfl_fpga_enum_info_alloc()
1258 info->dev = dev; in dfl_fpga_enum_info_alloc()
1259 INIT_LIST_HEAD(&info->dfls); in dfl_fpga_enum_info_alloc()
1268 struct device *dev; in dfl_fpga_enum_info_free()
1273 dev = info->dev; in dfl_fpga_enum_info_free()
1275 /* remove all device feature lists in the list. */ in dfl_fpga_enum_info_free()
1276 list_for_each_entry_safe(dfl, tmp, &info->dfls, node) { in dfl_fpga_enum_info_free()
1277 list_del(&dfl->node); in dfl_fpga_enum_info_free()
1282 if (info->irq_table) in dfl_fpga_enum_info_free()
1283 devm_kfree(dev, info->irq_table); in dfl_fpga_enum_info_free()
1291 * dfl_fpga_enum_info_add_dfl - add info of a device feature list to enum info
1294 * @start: mmio resource address of the device feature list.
1295 * @len: mmio resource length of the device feature list.
1297 * One FPGA device may have one or more Device Feature Lists (DFLs), use this
1308 dfl = devm_kzalloc(info->dev, sizeof(*dfl), GFP_KERNEL); in dfl_fpga_enum_info_add_dfl()
1310 return -ENOMEM; in dfl_fpga_enum_info_add_dfl()
1312 dfl->start = start; in dfl_fpga_enum_info_add_dfl()
1313 dfl->len = len; in dfl_fpga_enum_info_add_dfl()
1315 list_add_tail(&dfl->node, &info->dfls); in dfl_fpga_enum_info_add_dfl()
1322 * dfl_fpga_enum_info_add_irq - add irq table to enum info
1325 * @nr_irqs: number of irqs of the DFL fpga device to be enumerated.
1327 * this device.
1329 * One FPGA device may have several interrupts. This function adds irq
1330 * information of the DFL fpga device to enum info for next step enumeration.
1344 return -EINVAL; in dfl_fpga_enum_info_add_irq()
1346 if (info->irq_table) in dfl_fpga_enum_info_add_irq()
1347 return -EEXIST; in dfl_fpga_enum_info_add_irq()
1349 info->irq_table = devm_kmemdup(info->dev, irq_table, in dfl_fpga_enum_info_add_irq()
1351 if (!info->irq_table) in dfl_fpga_enum_info_add_irq()
1352 return -ENOMEM; in dfl_fpga_enum_info_add_irq()
1354 info->nr_irqs = nr_irqs; in dfl_fpga_enum_info_add_irq()
1360 static int remove_feature_dev(struct device *dev, void *data) in remove_feature_dev()
1364 int id = pdev->id; in remove_feature_dev() local
1368 dfl_id_free(type, id); in remove_feature_dev()
1375 device_for_each_child(&cdev->region->dev, NULL, remove_feature_dev); in remove_feature_devs()
1379 * dfl_fpga_feature_devs_enumerate - enumerate feature devices
1382 * This function creates a container device (base FPGA region), enumerates
1384 * under the container device.
1386 * Return: dfl_fpga_cdev struct on success, -errno on failure
1396 if (!info->dev) in dfl_fpga_feature_devs_enumerate()
1397 return ERR_PTR(-ENODEV); in dfl_fpga_feature_devs_enumerate()
1399 cdev = devm_kzalloc(info->dev, sizeof(*cdev), GFP_KERNEL); in dfl_fpga_feature_devs_enumerate()
1401 return ERR_PTR(-ENOMEM); in dfl_fpga_feature_devs_enumerate()
1403 cdev->region = devm_fpga_region_create(info->dev, NULL, NULL); in dfl_fpga_feature_devs_enumerate()
1404 if (!cdev->region) { in dfl_fpga_feature_devs_enumerate()
1405 ret = -ENOMEM; in dfl_fpga_feature_devs_enumerate()
1409 cdev->parent = info->dev; in dfl_fpga_feature_devs_enumerate()
1410 mutex_init(&cdev->lock); in dfl_fpga_feature_devs_enumerate()
1411 INIT_LIST_HEAD(&cdev->port_dev_list); in dfl_fpga_feature_devs_enumerate()
1413 ret = fpga_region_register(cdev->region); in dfl_fpga_feature_devs_enumerate()
1418 binfo = devm_kzalloc(info->dev, sizeof(*binfo), GFP_KERNEL); in dfl_fpga_feature_devs_enumerate()
1420 ret = -ENOMEM; in dfl_fpga_feature_devs_enumerate()
1424 binfo->dev = info->dev; in dfl_fpga_feature_devs_enumerate()
1425 binfo->cdev = cdev; in dfl_fpga_feature_devs_enumerate()
1427 binfo->nr_irqs = info->nr_irqs; in dfl_fpga_feature_devs_enumerate()
1428 if (info->nr_irqs) in dfl_fpga_feature_devs_enumerate()
1429 binfo->irq_table = info->irq_table; in dfl_fpga_feature_devs_enumerate()
1432 * start enumeration for all feature devices based on Device Feature in dfl_fpga_feature_devs_enumerate()
1435 list_for_each_entry(dfl, &info->dfls, node) { in dfl_fpga_feature_devs_enumerate()
1436 ret = parse_feature_list(binfo, dfl->start, dfl->len); in dfl_fpga_feature_devs_enumerate()
1449 fpga_region_unregister(cdev->region); in dfl_fpga_feature_devs_enumerate()
1451 devm_kfree(info->dev, cdev); in dfl_fpga_feature_devs_enumerate()
1457 * dfl_fpga_feature_devs_remove - remove all feature devices
1458 * @cdev: fpga container device.
1460 * Remove the container device and all feature devices under given container
1467 mutex_lock(&cdev->lock); in dfl_fpga_feature_devs_remove()
1468 if (cdev->fme_dev) in dfl_fpga_feature_devs_remove()
1469 put_device(cdev->fme_dev); in dfl_fpga_feature_devs_remove()
1471 list_for_each_entry_safe(pdata, ptmp, &cdev->port_dev_list, node) { in dfl_fpga_feature_devs_remove()
1472 struct platform_device *port_dev = pdata->dev; in dfl_fpga_feature_devs_remove()
1475 if (!device_is_registered(&port_dev->dev)) { in dfl_fpga_feature_devs_remove()
1477 port_dev->id); in dfl_fpga_feature_devs_remove()
1481 list_del(&pdata->node); in dfl_fpga_feature_devs_remove()
1482 put_device(&port_dev->dev); in dfl_fpga_feature_devs_remove()
1484 mutex_unlock(&cdev->lock); in dfl_fpga_feature_devs_remove()
1488 fpga_region_unregister(cdev->region); in dfl_fpga_feature_devs_remove()
1489 devm_kfree(cdev->parent, cdev); in dfl_fpga_feature_devs_remove()
1494 * __dfl_fpga_cdev_find_port - find a port under given container device
1496 * @cdev: container device
1498 * @match: match function used to find specific port from the port device list
1500 * Find a port device under container device. This function needs to be
1503 * Return: pointer to port's platform device if successful, NULL otherwise.
1505 * NOTE: you will need to drop the device reference with put_device() after use.
1514 list_for_each_entry(pdata, &cdev->port_dev_list, node) { in __dfl_fpga_cdev_find_port()
1515 port_dev = pdata->dev; in __dfl_fpga_cdev_find_port()
1517 if (match(port_dev, data) && get_device(&port_dev->dev)) in __dfl_fpga_cdev_find_port()
1545 * dfl_fpga_cdev_release_port - release a port platform device
1547 * @cdev: parent container device.
1548 * @port_id: id of the port platform device.
1550 * This function allows user to release a port platform device. This is a
1559 int ret = -ENODEV; in dfl_fpga_cdev_release_port()
1561 mutex_lock(&cdev->lock); in dfl_fpga_cdev_release_port()
1567 if (!device_is_registered(&port_pdev->dev)) { in dfl_fpga_cdev_release_port()
1568 ret = -EBUSY; in dfl_fpga_cdev_release_port()
1572 pdata = dev_get_platdata(&port_pdev->dev); in dfl_fpga_cdev_release_port()
1574 mutex_lock(&pdata->lock); in dfl_fpga_cdev_release_port()
1576 mutex_unlock(&pdata->lock); in dfl_fpga_cdev_release_port()
1581 cdev->released_port_num++; in dfl_fpga_cdev_release_port()
1583 put_device(&port_pdev->dev); in dfl_fpga_cdev_release_port()
1585 mutex_unlock(&cdev->lock); in dfl_fpga_cdev_release_port()
1591 * dfl_fpga_cdev_assign_port - assign a port platform device back
1593 * @cdev: parent container device.
1594 * @port_id: id of the port platform device.
1596 * This function allows user to assign a port platform device back. This is
1605 int ret = -ENODEV; in dfl_fpga_cdev_assign_port()
1607 mutex_lock(&cdev->lock); in dfl_fpga_cdev_assign_port()
1613 if (device_is_registered(&port_pdev->dev)) { in dfl_fpga_cdev_assign_port()
1614 ret = -EBUSY; in dfl_fpga_cdev_assign_port()
1622 pdata = dev_get_platdata(&port_pdev->dev); in dfl_fpga_cdev_assign_port()
1624 mutex_lock(&pdata->lock); in dfl_fpga_cdev_assign_port()
1626 mutex_unlock(&pdata->lock); in dfl_fpga_cdev_assign_port()
1628 cdev->released_port_num--; in dfl_fpga_cdev_assign_port()
1630 put_device(&port_pdev->dev); in dfl_fpga_cdev_assign_port()
1632 mutex_unlock(&cdev->lock); in dfl_fpga_cdev_assign_port()
1637 static void config_port_access_mode(struct device *fme_dev, int port_id, in config_port_access_mode()
1654 #define config_port_vf_mode(dev, id) config_port_access_mode(dev, id, true) argument
1655 #define config_port_pf_mode(dev, id) config_port_access_mode(dev, id, false) argument
1658 * dfl_fpga_cdev_config_ports_pf - configure ports to PF access mode
1660 * @cdev: parent container device.
1669 mutex_lock(&cdev->lock); in dfl_fpga_cdev_config_ports_pf()
1670 list_for_each_entry(pdata, &cdev->port_dev_list, node) { in dfl_fpga_cdev_config_ports_pf()
1671 if (device_is_registered(&pdata->dev->dev)) in dfl_fpga_cdev_config_ports_pf()
1674 config_port_pf_mode(cdev->fme_dev, pdata->id); in dfl_fpga_cdev_config_ports_pf()
1676 mutex_unlock(&cdev->lock); in dfl_fpga_cdev_config_ports_pf()
1681 * dfl_fpga_cdev_config_ports_vf - configure ports to VF access mode
1683 * @cdev: parent container device.
1684 * @num_vfs: VF device number.
1696 mutex_lock(&cdev->lock); in dfl_fpga_cdev_config_ports_vf()
1698 * can't turn multiple ports into 1 VF device, only 1 port for 1 VF in dfl_fpga_cdev_config_ports_vf()
1699 * device, so if released port number doesn't match VF device number, in dfl_fpga_cdev_config_ports_vf()
1700 * then reject the request with -EINVAL error code. in dfl_fpga_cdev_config_ports_vf()
1702 if (cdev->released_port_num != num_vfs) { in dfl_fpga_cdev_config_ports_vf()
1703 ret = -EINVAL; in dfl_fpga_cdev_config_ports_vf()
1707 list_for_each_entry(pdata, &cdev->port_dev_list, node) { in dfl_fpga_cdev_config_ports_vf()
1708 if (device_is_registered(&pdata->dev->dev)) in dfl_fpga_cdev_config_ports_vf()
1711 config_port_vf_mode(cdev->fme_dev, pdata->id); in dfl_fpga_cdev_config_ports_vf()
1714 mutex_unlock(&cdev->lock); in dfl_fpga_cdev_config_ports_vf()
1730 struct platform_device *pdev = feature->dev; in do_set_irq_trigger()
1734 irq = feature->irq_ctx[idx].irq; in do_set_irq_trigger()
1736 if (feature->irq_ctx[idx].trigger) { in do_set_irq_trigger()
1737 free_irq(irq, feature->irq_ctx[idx].trigger); in do_set_irq_trigger()
1738 kfree(feature->irq_ctx[idx].name); in do_set_irq_trigger()
1739 eventfd_ctx_put(feature->irq_ctx[idx].trigger); in do_set_irq_trigger()
1740 feature->irq_ctx[idx].trigger = NULL; in do_set_irq_trigger()
1746 feature->irq_ctx[idx].name = in do_set_irq_trigger()
1747 kasprintf(GFP_KERNEL, "fpga-irq[%u](%s-%x)", idx, in do_set_irq_trigger()
1748 dev_name(&pdev->dev), feature->id); in do_set_irq_trigger()
1749 if (!feature->irq_ctx[idx].name) in do_set_irq_trigger()
1750 return -ENOMEM; in do_set_irq_trigger()
1759 feature->irq_ctx[idx].name, trigger); in do_set_irq_trigger()
1761 feature->irq_ctx[idx].trigger = trigger; in do_set_irq_trigger()
1767 kfree(feature->irq_ctx[idx].name); in do_set_irq_trigger()
1773 * dfl_fpga_set_irq_triggers - set eventfd triggers for dfl feature interrupts
1795 return -EINVAL; in dfl_fpga_set_irq_triggers()
1798 if (start + count > feature->nr_irqs) in dfl_fpga_set_irq_triggers()
1799 return -EINVAL; in dfl_fpga_set_irq_triggers()
1802 int fd = fds ? fds[i] : -1; in dfl_fpga_set_irq_triggers()
1806 while (i--) in dfl_fpga_set_irq_triggers()
1807 do_set_irq_trigger(feature, start + i, -1); in dfl_fpga_set_irq_triggers()
1817 * dfl_feature_ioctl_get_num_irqs - dfl feature _GET_IRQ_NUM ioctl interface.
1818 * @pdev: the feature device which has the sub feature
1828 return put_user(feature->nr_irqs, (__u32 __user *)arg); in dfl_feature_ioctl_get_num_irqs()
1833 * dfl_feature_ioctl_set_irq - dfl feature _SET_IRQ ioctl interface.
1834 * @pdev: the feature device which has the sub feature
1844 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); in dfl_feature_ioctl_set_irq()
1849 if (!feature->nr_irqs) in dfl_feature_ioctl_set_irq()
1850 return -ENOENT; in dfl_feature_ioctl_set_irq()
1853 return -EFAULT; in dfl_feature_ioctl_set_irq()
1855 if (!hdr.count || (hdr.start + hdr.count > feature->nr_irqs) || in dfl_feature_ioctl_set_irq()
1857 return -EINVAL; in dfl_feature_ioctl_set_irq()
1864 mutex_lock(&pdata->lock); in dfl_feature_ioctl_set_irq()
1866 mutex_unlock(&pdata->lock); in dfl_feature_ioctl_set_irq()
1883 MODULE_DESCRIPTION("FPGA Device Feature List (DFL) Support");