hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/fpga/dfl.c
....@@ -10,7 +10,9 @@
1010 * Wu Hao <hao.wu@intel.com>
1111 * Xiao Guangrong <guangrong.xiao@linux.intel.com>
1212 */
13
+#include <linux/fpga-dfl.h>
1314 #include <linux/module.h>
15
+#include <linux/uaccess.h>
1416
1517 #include "dfl.h"
1618
....@@ -28,12 +30,6 @@
2830 * index to dfl_chardevs table. If no chardev support just set devt_type
2931 * as one invalid index (DFL_FPGA_DEVT_MAX).
3032 */
31
-enum dfl_id_type {
32
- FME_ID, /* fme id allocation and mapping */
33
- PORT_ID, /* port id allocation and mapping */
34
- DFL_ID_MAX,
35
-};
36
-
3733 enum dfl_fpga_devt_type {
3834 DFL_FPGA_DEVT_FME,
3935 DFL_FPGA_DEVT_PORT,
....@@ -56,7 +52,7 @@
5652 */
5753 struct dfl_dev_info {
5854 const char *name;
59
- u32 dfh_id;
55
+ u16 dfh_id;
6056 struct idr id;
6157 enum dfl_fpga_devt_type devt_type;
6258 };
....@@ -132,7 +128,7 @@
132128 return DFL_ID_MAX;
133129 }
134130
135
-static enum dfl_id_type dfh_id_to_type(u32 id)
131
+static enum dfl_id_type dfh_id_to_type(u16 id)
136132 {
137133 int i;
138134
....@@ -231,18 +227,265 @@
231227 */
232228 int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id)
233229 {
234
- struct dfl_fpga_port_ops *port_ops = dfl_fpga_port_ops_get(pdev);
235
- int port_id;
230
+ struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
231
+ struct dfl_fpga_port_ops *port_ops;
236232
233
+ if (pdata->id != FEATURE_DEV_ID_UNUSED)
234
+ return pdata->id == *(int *)pport_id;
235
+
236
+ port_ops = dfl_fpga_port_ops_get(pdev);
237237 if (!port_ops || !port_ops->get_id)
238238 return 0;
239239
240
- port_id = port_ops->get_id(pdev);
240
+ pdata->id = port_ops->get_id(pdev);
241241 dfl_fpga_port_ops_put(port_ops);
242242
243
- return port_id == *(int *)pport_id;
243
+ return pdata->id == *(int *)pport_id;
244244 }
245245 EXPORT_SYMBOL_GPL(dfl_fpga_check_port_id);
246
+
247
+static DEFINE_IDA(dfl_device_ida);
248
+
249
+static const struct dfl_device_id *
250
+dfl_match_one_device(const struct dfl_device_id *id, struct dfl_device *ddev)
251
+{
252
+ if (id->type == ddev->type && id->feature_id == ddev->feature_id)
253
+ return id;
254
+
255
+ return NULL;
256
+}
257
+
258
+static int dfl_bus_match(struct device *dev, struct device_driver *drv)
259
+{
260
+ struct dfl_device *ddev = to_dfl_dev(dev);
261
+ struct dfl_driver *ddrv = to_dfl_drv(drv);
262
+ const struct dfl_device_id *id_entry;
263
+
264
+ id_entry = ddrv->id_table;
265
+ if (id_entry) {
266
+ while (id_entry->feature_id) {
267
+ if (dfl_match_one_device(id_entry, ddev)) {
268
+ ddev->id_entry = id_entry;
269
+ return 1;
270
+ }
271
+ id_entry++;
272
+ }
273
+ }
274
+
275
+ return 0;
276
+}
277
+
278
+static int dfl_bus_probe(struct device *dev)
279
+{
280
+ struct dfl_driver *ddrv = to_dfl_drv(dev->driver);
281
+ struct dfl_device *ddev = to_dfl_dev(dev);
282
+
283
+ return ddrv->probe(ddev);
284
+}
285
+
286
+static int dfl_bus_remove(struct device *dev)
287
+{
288
+ struct dfl_driver *ddrv = to_dfl_drv(dev->driver);
289
+ struct dfl_device *ddev = to_dfl_dev(dev);
290
+
291
+ if (ddrv->remove)
292
+ ddrv->remove(ddev);
293
+
294
+ return 0;
295
+}
296
+
297
+static int dfl_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
298
+{
299
+ struct dfl_device *ddev = to_dfl_dev(dev);
300
+
301
+ /* The type has 4 valid bits and feature_id has 12 valid bits */
302
+ return add_uevent_var(env, "MODALIAS=dfl:t%01Xf%03X",
303
+ ddev->type, ddev->feature_id);
304
+}
305
+
306
+static ssize_t
307
+type_show(struct device *dev, struct device_attribute *attr, char *buf)
308
+{
309
+ struct dfl_device *ddev = to_dfl_dev(dev);
310
+
311
+ return sprintf(buf, "0x%x\n", ddev->type);
312
+}
313
+static DEVICE_ATTR_RO(type);
314
+
315
+static ssize_t
316
+feature_id_show(struct device *dev, struct device_attribute *attr, char *buf)
317
+{
318
+ struct dfl_device *ddev = to_dfl_dev(dev);
319
+
320
+ return sprintf(buf, "0x%x\n", ddev->feature_id);
321
+}
322
+static DEVICE_ATTR_RO(feature_id);
323
+
324
+static struct attribute *dfl_dev_attrs[] = {
325
+ &dev_attr_type.attr,
326
+ &dev_attr_feature_id.attr,
327
+ NULL,
328
+};
329
+ATTRIBUTE_GROUPS(dfl_dev);
330
+
331
+static struct bus_type dfl_bus_type = {
332
+ .name = "dfl",
333
+ .match = dfl_bus_match,
334
+ .probe = dfl_bus_probe,
335
+ .remove = dfl_bus_remove,
336
+ .uevent = dfl_bus_uevent,
337
+ .dev_groups = dfl_dev_groups,
338
+};
339
+
340
+static void release_dfl_dev(struct device *dev)
341
+{
342
+ struct dfl_device *ddev = to_dfl_dev(dev);
343
+
344
+ if (ddev->mmio_res.parent)
345
+ release_resource(&ddev->mmio_res);
346
+
347
+ ida_simple_remove(&dfl_device_ida, ddev->id);
348
+ kfree(ddev->irqs);
349
+ kfree(ddev);
350
+}
351
+
352
+static struct dfl_device *
353
+dfl_dev_add(struct dfl_feature_platform_data *pdata,
354
+ struct dfl_feature *feature)
355
+{
356
+ struct platform_device *pdev = pdata->dev;
357
+ struct resource *parent_res;
358
+ struct dfl_device *ddev;
359
+ int id, i, ret;
360
+
361
+ ddev = kzalloc(sizeof(*ddev), GFP_KERNEL);
362
+ if (!ddev)
363
+ return ERR_PTR(-ENOMEM);
364
+
365
+ id = ida_simple_get(&dfl_device_ida, 0, 0, GFP_KERNEL);
366
+ if (id < 0) {
367
+ dev_err(&pdev->dev, "unable to get id\n");
368
+ kfree(ddev);
369
+ return ERR_PTR(id);
370
+ }
371
+
372
+ /* freeing resources by put_device() after device_initialize() */
373
+ device_initialize(&ddev->dev);
374
+ ddev->dev.parent = &pdev->dev;
375
+ ddev->dev.bus = &dfl_bus_type;
376
+ ddev->dev.release = release_dfl_dev;
377
+ ddev->id = id;
378
+ ret = dev_set_name(&ddev->dev, "dfl_dev.%d", id);
379
+ if (ret)
380
+ goto put_dev;
381
+
382
+ ddev->type = feature_dev_id_type(pdev);
383
+ ddev->feature_id = feature->id;
384
+ ddev->cdev = pdata->dfl_cdev;
385
+
386
+ /* add mmio resource */
387
+ parent_res = &pdev->resource[feature->resource_index];
388
+ ddev->mmio_res.flags = IORESOURCE_MEM;
389
+ ddev->mmio_res.start = parent_res->start;
390
+ ddev->mmio_res.end = parent_res->end;
391
+ ddev->mmio_res.name = dev_name(&ddev->dev);
392
+ ret = insert_resource(parent_res, &ddev->mmio_res);
393
+ if (ret) {
394
+ dev_err(&pdev->dev, "%s failed to claim resource: %pR\n",
395
+ dev_name(&ddev->dev), &ddev->mmio_res);
396
+ goto put_dev;
397
+ }
398
+
399
+ /* then add irq resource */
400
+ if (feature->nr_irqs) {
401
+ ddev->irqs = kcalloc(feature->nr_irqs,
402
+ sizeof(*ddev->irqs), GFP_KERNEL);
403
+ if (!ddev->irqs) {
404
+ ret = -ENOMEM;
405
+ goto put_dev;
406
+ }
407
+
408
+ for (i = 0; i < feature->nr_irqs; i++)
409
+ ddev->irqs[i] = feature->irq_ctx[i].irq;
410
+
411
+ ddev->num_irqs = feature->nr_irqs;
412
+ }
413
+
414
+ ret = device_add(&ddev->dev);
415
+ if (ret)
416
+ goto put_dev;
417
+
418
+ dev_dbg(&pdev->dev, "add dfl_dev: %s\n", dev_name(&ddev->dev));
419
+ return ddev;
420
+
421
+put_dev:
422
+ /* calls release_dfl_dev() which does the clean up */
423
+ put_device(&ddev->dev);
424
+ return ERR_PTR(ret);
425
+}
426
+
427
+static void dfl_devs_remove(struct dfl_feature_platform_data *pdata)
428
+{
429
+ struct dfl_feature *feature;
430
+
431
+ dfl_fpga_dev_for_each_feature(pdata, feature) {
432
+ if (feature->ddev) {
433
+ device_unregister(&feature->ddev->dev);
434
+ feature->ddev = NULL;
435
+ }
436
+ }
437
+}
438
+
439
+static int dfl_devs_add(struct dfl_feature_platform_data *pdata)
440
+{
441
+ struct dfl_feature *feature;
442
+ struct dfl_device *ddev;
443
+ int ret;
444
+
445
+ dfl_fpga_dev_for_each_feature(pdata, feature) {
446
+ if (feature->ioaddr)
447
+ continue;
448
+
449
+ if (feature->ddev) {
450
+ ret = -EEXIST;
451
+ goto err;
452
+ }
453
+
454
+ ddev = dfl_dev_add(pdata, feature);
455
+ if (IS_ERR(ddev)) {
456
+ ret = PTR_ERR(ddev);
457
+ goto err;
458
+ }
459
+
460
+ feature->ddev = ddev;
461
+ }
462
+
463
+ return 0;
464
+
465
+err:
466
+ dfl_devs_remove(pdata);
467
+ return ret;
468
+}
469
+
470
+int __dfl_driver_register(struct dfl_driver *dfl_drv, struct module *owner)
471
+{
472
+ if (!dfl_drv || !dfl_drv->probe || !dfl_drv->id_table)
473
+ return -EINVAL;
474
+
475
+ dfl_drv->drv.owner = owner;
476
+ dfl_drv->drv.bus = &dfl_bus_type;
477
+
478
+ return driver_register(&dfl_drv->drv);
479
+}
480
+EXPORT_SYMBOL(__dfl_driver_register);
481
+
482
+void dfl_driver_unregister(struct dfl_driver *dfl_drv)
483
+{
484
+ driver_unregister(&dfl_drv->drv);
485
+}
486
+EXPORT_SYMBOL(dfl_driver_unregister);
487
+
488
+#define is_header_feature(feature) ((feature)->id == FEATURE_ID_FIU_HEADER)
246489
247490 /**
248491 * dfl_fpga_dev_feature_uinit - uinit for sub features of dfl feature device
....@@ -253,11 +496,15 @@
253496 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
254497 struct dfl_feature *feature;
255498
256
- dfl_fpga_dev_for_each_feature(pdata, feature)
499
+ dfl_devs_remove(pdata);
500
+
501
+ dfl_fpga_dev_for_each_feature(pdata, feature) {
257502 if (feature->ops) {
258
- feature->ops->uinit(pdev, feature);
503
+ if (feature->ops->uinit)
504
+ feature->ops->uinit(pdev, feature);
259505 feature->ops = NULL;
260506 }
507
+ }
261508 }
262509 EXPORT_SYMBOL_GPL(dfl_fpga_dev_feature_uinit);
263510
....@@ -266,15 +513,46 @@
266513 struct dfl_feature *feature,
267514 struct dfl_feature_driver *drv)
268515 {
269
- int ret;
516
+ void __iomem *base;
517
+ int ret = 0;
270518
271
- ret = drv->ops->init(pdev, feature);
272
- if (ret)
273
- return ret;
519
+ if (!is_header_feature(feature)) {
520
+ base = devm_platform_ioremap_resource(pdev,
521
+ feature->resource_index);
522
+ if (IS_ERR(base)) {
523
+ dev_err(&pdev->dev,
524
+ "ioremap failed for feature 0x%x!\n",
525
+ feature->id);
526
+ return PTR_ERR(base);
527
+ }
528
+
529
+ feature->ioaddr = base;
530
+ }
531
+
532
+ if (drv->ops->init) {
533
+ ret = drv->ops->init(pdev, feature);
534
+ if (ret)
535
+ return ret;
536
+ }
274537
275538 feature->ops = drv->ops;
276539
277540 return ret;
541
+}
542
+
543
+static bool dfl_feature_drv_match(struct dfl_feature *feature,
544
+ struct dfl_feature_driver *driver)
545
+{
546
+ const struct dfl_feature_id *ids = driver->id_table;
547
+
548
+ if (ids) {
549
+ while (ids->id) {
550
+ if (ids->id == feature->id)
551
+ return true;
552
+ ids++;
553
+ }
554
+ }
555
+ return false;
278556 }
279557
280558 /**
....@@ -297,8 +575,7 @@
297575
298576 while (drv->ops) {
299577 dfl_fpga_dev_for_each_feature(pdata, feature) {
300
- /* match feature and drv using id */
301
- if (feature->id == drv->id) {
578
+ if (dfl_feature_drv_match(feature, drv)) {
302579 ret = dfl_feature_instance_init(pdev, pdata,
303580 feature, drv);
304581 if (ret)
....@@ -307,6 +584,10 @@
307584 }
308585 drv++;
309586 }
587
+
588
+ ret = dfl_devs_add(pdata);
589
+ if (ret)
590
+ goto exit;
310591
311592 return 0;
312593 exit:
....@@ -322,7 +603,7 @@
322603 for (i = 0; i < DFL_FPGA_DEVT_MAX; i++)
323604 if (MAJOR(dfl_chrdevs[i].devt)) {
324605 unregister_chrdev_region(dfl_chrdevs[i].devt,
325
- MINORMASK);
606
+ MINORMASK + 1);
326607 dfl_chrdevs[i].devt = MKDEV(0, 0);
327608 }
328609 }
....@@ -332,8 +613,8 @@
332613 int i, ret;
333614
334615 for (i = 0; i < DFL_FPGA_DEVT_MAX; i++) {
335
- ret = alloc_chrdev_region(&dfl_chrdevs[i].devt, 0, MINORMASK,
336
- dfl_chrdevs[i].name);
616
+ ret = alloc_chrdev_region(&dfl_chrdevs[i].devt, 0,
617
+ MINORMASK + 1, dfl_chrdevs[i].name);
337618 if (ret)
338619 goto exit;
339620 }
....@@ -400,16 +681,26 @@
400681 *
401682 * @dev: device to enumerate.
402683 * @cdev: the container device for all feature devices.
684
+ * @nr_irqs: number of irqs for all feature devices.
685
+ * @irq_table: Linux IRQ numbers for all irqs, indexed by local irq index of
686
+ * this device.
403687 * @feature_dev: current feature device.
404
- * @ioaddr: header register region address of feature device in enumeration.
688
+ * @ioaddr: header register region address of current FIU in enumeration.
689
+ * @start: register resource start of current FIU.
690
+ * @len: max register resource length of current FIU.
405691 * @sub_features: a sub features linked list for feature device in enumeration.
406692 * @feature_num: number of sub features for feature device in enumeration.
407693 */
408694 struct build_feature_devs_info {
409695 struct device *dev;
410696 struct dfl_fpga_cdev *cdev;
697
+ unsigned int nr_irqs;
698
+ int *irq_table;
699
+
411700 struct platform_device *feature_dev;
412701 void __iomem *ioaddr;
702
+ resource_size_t start;
703
+ resource_size_t len;
413704 struct list_head sub_features;
414705 int feature_num;
415706 };
....@@ -421,12 +712,16 @@
421712 * @mmio_res: mmio resource of this sub feature.
422713 * @ioaddr: mapped base address of mmio resource.
423714 * @node: node in sub_features linked list.
715
+ * @irq_base: start of irq index in this sub feature.
716
+ * @nr_irqs: number of irqs of this sub feature.
424717 */
425718 struct dfl_feature_info {
426
- u64 fid;
719
+ u16 fid;
427720 struct resource mmio_res;
428721 void __iomem *ioaddr;
429722 struct list_head node;
723
+ unsigned int irq_base;
724
+ unsigned int nr_irqs;
430725 };
431726
432727 static void dfl_fpga_cdev_add_port_dev(struct dfl_fpga_cdev *cdev,
....@@ -451,10 +746,7 @@
451746 struct dfl_feature_platform_data *pdata;
452747 struct dfl_feature_info *finfo, *p;
453748 enum dfl_id_type type;
454
- int ret, index = 0;
455
-
456
- if (!fdev)
457
- return 0;
749
+ int ret, index = 0, res_idx = 0;
458750
459751 type = feature_dev_id_type(fdev);
460752 if (WARN_ON_ONCE(type >= DFL_ID_MAX))
....@@ -466,14 +758,14 @@
466758 * it will be automatically freed by device's release() callback,
467759 * platform_device_release().
468760 */
469
- pdata = kzalloc(dfl_feature_platform_data_size(binfo->feature_num),
470
- GFP_KERNEL);
761
+ pdata = kzalloc(struct_size(pdata, features, binfo->feature_num), GFP_KERNEL);
471762 if (!pdata)
472763 return -ENOMEM;
473764
474765 pdata->dev = fdev;
475766 pdata->num = binfo->feature_num;
476767 pdata->dfl_cdev = binfo->cdev;
768
+ pdata->id = FEATURE_DEV_ID_UNUSED;
477769 mutex_init(&pdata->lock);
478770 lockdep_set_class_and_name(&pdata->lock, &dfl_pdata_keys[type],
479771 dfl_pdata_key_strings[type]);
....@@ -497,13 +789,46 @@
497789
498790 /* fill features and resource information for feature dev */
499791 list_for_each_entry_safe(finfo, p, &binfo->sub_features, node) {
500
- struct dfl_feature *feature = &pdata->features[index];
792
+ struct dfl_feature *feature = &pdata->features[index++];
793
+ struct dfl_feature_irq_ctx *ctx;
794
+ unsigned int i;
501795
502796 /* save resource information for each feature */
797
+ feature->dev = fdev;
503798 feature->id = finfo->fid;
504
- feature->resource_index = index;
505
- feature->ioaddr = finfo->ioaddr;
506
- fdev->resource[index++] = finfo->mmio_res;
799
+
800
+ /*
801
+ * the FIU header feature has some fundamental functions (sriov
802
+ * set, port enable/disable) needed for the dfl bus device and
803
+ * other sub features. So its mmio resource should be mapped by
804
+ * DFL bus device. And we should not assign it to feature
805
+ * devices (dfl-fme/afu) again.
806
+ */
807
+ if (is_header_feature(feature)) {
808
+ feature->resource_index = -1;
809
+ feature->ioaddr =
810
+ devm_ioremap_resource(binfo->dev,
811
+ &finfo->mmio_res);
812
+ if (IS_ERR(feature->ioaddr))
813
+ return PTR_ERR(feature->ioaddr);
814
+ } else {
815
+ feature->resource_index = res_idx;
816
+ fdev->resource[res_idx++] = finfo->mmio_res;
817
+ }
818
+
819
+ if (finfo->nr_irqs) {
820
+ ctx = devm_kcalloc(binfo->dev, finfo->nr_irqs,
821
+ sizeof(*ctx), GFP_KERNEL);
822
+ if (!ctx)
823
+ return -ENOMEM;
824
+
825
+ for (i = 0; i < finfo->nr_irqs; i++)
826
+ ctx[i].irq =
827
+ binfo->irq_table[finfo->irq_base + i];
828
+
829
+ feature->irq_ctx = ctx;
830
+ feature->nr_irqs = finfo->nr_irqs;
831
+ }
507832
508833 list_del(&finfo->node);
509834 kfree(finfo);
....@@ -532,18 +857,12 @@
532857
533858 static int
534859 build_info_create_dev(struct build_feature_devs_info *binfo,
535
- enum dfl_id_type type, void __iomem *ioaddr)
860
+ enum dfl_id_type type)
536861 {
537862 struct platform_device *fdev;
538
- int ret;
539863
540864 if (type >= DFL_ID_MAX)
541865 return -EINVAL;
542
-
543
- /* we will create a new device, commit current device first */
544
- ret = build_info_commit_dev(binfo);
545
- if (ret)
546
- return ret;
547866
548867 /*
549868 * we use -ENODEV as the initialization indicator which indicates
....@@ -555,7 +874,7 @@
555874
556875 binfo->feature_dev = fdev;
557876 binfo->feature_num = 0;
558
- binfo->ioaddr = ioaddr;
877
+
559878 INIT_LIST_HEAD(&binfo->sub_features);
560879
561880 fdev->id = dfl_id_alloc(type, &fdev->dev);
....@@ -599,7 +918,7 @@
599918 return ofst ? ofst : 4096;
600919 }
601920
602
-static u64 feature_id(void __iomem *start)
921
+static u16 feature_id(void __iomem *start)
603922 {
604923 u64 v = readq(start + DFH);
605924 u16 id = FIELD_GET(DFH_ID, v);
....@@ -616,6 +935,78 @@
616935 return 0;
617936 }
618937
938
+static int parse_feature_irqs(struct build_feature_devs_info *binfo,
939
+ resource_size_t ofst, u16 fid,
940
+ unsigned int *irq_base, unsigned int *nr_irqs)
941
+{
942
+ void __iomem *base = binfo->ioaddr + ofst;
943
+ unsigned int i, ibase, inr = 0;
944
+ int virq;
945
+ u64 v;
946
+
947
+ /*
948
+ * Ideally DFL framework should only read info from DFL header, but
949
+ * current version DFL only provides mmio resources information for
950
+ * each feature in DFL Header, no field for interrupt resources.
951
+ * Interrupt resource information is provided by specific mmio
952
+ * registers of each private feature which supports interrupt. So in
953
+ * order to parse and assign irq resources, DFL framework has to look
954
+ * into specific capability registers of these private features.
955
+ *
956
+ * Once future DFL version supports generic interrupt resource
957
+ * information in common DFL headers, the generic interrupt parsing
958
+ * code will be added. But in order to be compatible to old version
959
+ * DFL, the driver may still fall back to these quirks.
960
+ */
961
+ switch (fid) {
962
+ case PORT_FEATURE_ID_UINT:
963
+ v = readq(base + PORT_UINT_CAP);
964
+ ibase = FIELD_GET(PORT_UINT_CAP_FST_VECT, v);
965
+ inr = FIELD_GET(PORT_UINT_CAP_INT_NUM, v);
966
+ break;
967
+ case PORT_FEATURE_ID_ERROR:
968
+ v = readq(base + PORT_ERROR_CAP);
969
+ ibase = FIELD_GET(PORT_ERROR_CAP_INT_VECT, v);
970
+ inr = FIELD_GET(PORT_ERROR_CAP_SUPP_INT, v);
971
+ break;
972
+ case FME_FEATURE_ID_GLOBAL_ERR:
973
+ v = readq(base + FME_ERROR_CAP);
974
+ ibase = FIELD_GET(FME_ERROR_CAP_INT_VECT, v);
975
+ inr = FIELD_GET(FME_ERROR_CAP_SUPP_INT, v);
976
+ break;
977
+ }
978
+
979
+ if (!inr) {
980
+ *irq_base = 0;
981
+ *nr_irqs = 0;
982
+ return 0;
983
+ }
984
+
985
+ dev_dbg(binfo->dev, "feature: 0x%x, irq_base: %u, nr_irqs: %u\n",
986
+ fid, ibase, inr);
987
+
988
+ if (ibase + inr > binfo->nr_irqs) {
989
+ dev_err(binfo->dev,
990
+ "Invalid interrupt number in feature 0x%x\n", fid);
991
+ return -EINVAL;
992
+ }
993
+
994
+ for (i = 0; i < inr; i++) {
995
+ virq = binfo->irq_table[ibase + i];
996
+ if (virq < 0 || virq > NR_IRQS) {
997
+ dev_err(binfo->dev,
998
+ "Invalid irq table entry for feature 0x%x\n",
999
+ fid);
1000
+ return -EINVAL;
1001
+ }
1002
+ }
1003
+
1004
+ *irq_base = ibase;
1005
+ *nr_irqs = inr;
1006
+
1007
+ return 0;
1008
+}
1009
+
6191010 /*
6201011 * when create sub feature instances, for private features, it doesn't need
6211012 * to provide resource size and feature id as they could be read from DFH
....@@ -625,27 +1016,33 @@
6251016 */
6261017 static int
6271018 create_feature_instance(struct build_feature_devs_info *binfo,
628
- struct dfl_fpga_enum_dfl *dfl, resource_size_t ofst,
629
- resource_size_t size, u64 fid)
1019
+ resource_size_t ofst, resource_size_t size, u16 fid)
6301020 {
1021
+ unsigned int irq_base, nr_irqs;
6311022 struct dfl_feature_info *finfo;
1023
+ int ret;
6321024
6331025 /* read feature size and id if inputs are invalid */
634
- size = size ? size : feature_size(dfl->ioaddr + ofst);
635
- fid = fid ? fid : feature_id(dfl->ioaddr + ofst);
1026
+ size = size ? size : feature_size(binfo->ioaddr + ofst);
1027
+ fid = fid ? fid : feature_id(binfo->ioaddr + ofst);
6361028
637
- if (dfl->len - ofst < size)
1029
+ if (binfo->len - ofst < size)
6381030 return -EINVAL;
1031
+
1032
+ ret = parse_feature_irqs(binfo, ofst, fid, &irq_base, &nr_irqs);
1033
+ if (ret)
1034
+ return ret;
6391035
6401036 finfo = kzalloc(sizeof(*finfo), GFP_KERNEL);
6411037 if (!finfo)
6421038 return -ENOMEM;
6431039
6441040 finfo->fid = fid;
645
- finfo->mmio_res.start = dfl->start + ofst;
1041
+ finfo->mmio_res.start = binfo->start + ofst;
6461042 finfo->mmio_res.end = finfo->mmio_res.start + size - 1;
6471043 finfo->mmio_res.flags = IORESOURCE_MEM;
648
- finfo->ioaddr = dfl->ioaddr + ofst;
1044
+ finfo->irq_base = irq_base;
1045
+ finfo->nr_irqs = nr_irqs;
6491046
6501047 list_add_tail(&finfo->node, &binfo->sub_features);
6511048 binfo->feature_num++;
....@@ -654,7 +1051,6 @@
6541051 }
6551052
6561053 static int parse_feature_port_afu(struct build_feature_devs_info *binfo,
657
- struct dfl_fpga_enum_dfl *dfl,
6581054 resource_size_t ofst)
6591055 {
6601056 u64 v = readq(binfo->ioaddr + PORT_HDR_CAP);
....@@ -662,21 +1058,22 @@
6621058
6631059 WARN_ON(!size);
6641060
665
- return create_feature_instance(binfo, dfl, ofst, size, FEATURE_ID_AFU);
1061
+ return create_feature_instance(binfo, ofst, size, FEATURE_ID_AFU);
6661062 }
6671063
1064
+#define is_feature_dev_detected(binfo) (!!(binfo)->feature_dev)
1065
+
6681066 static int parse_feature_afu(struct build_feature_devs_info *binfo,
669
- struct dfl_fpga_enum_dfl *dfl,
6701067 resource_size_t ofst)
6711068 {
672
- if (!binfo->feature_dev) {
1069
+ if (!is_feature_dev_detected(binfo)) {
6731070 dev_err(binfo->dev, "this AFU does not belong to any FIU.\n");
6741071 return -EINVAL;
6751072 }
6761073
6771074 switch (feature_dev_id_type(binfo->feature_dev)) {
6781075 case PORT_ID:
679
- return parse_feature_port_afu(binfo, dfl, ofst);
1076
+ return parse_feature_port_afu(binfo, ofst);
6801077 default:
6811078 dev_info(binfo->dev, "AFU belonging to FIU %s is not supported yet.\n",
6821079 binfo->feature_dev->name);
....@@ -685,35 +1082,79 @@
6851082 return 0;
6861083 }
6871084
1085
+static int build_info_prepare(struct build_feature_devs_info *binfo,
1086
+ resource_size_t start, resource_size_t len)
1087
+{
1088
+ struct device *dev = binfo->dev;
1089
+ void __iomem *ioaddr;
1090
+
1091
+ if (!devm_request_mem_region(dev, start, len, dev_name(dev))) {
1092
+ dev_err(dev, "request region fail, start:%pa, len:%pa\n",
1093
+ &start, &len);
1094
+ return -EBUSY;
1095
+ }
1096
+
1097
+ ioaddr = devm_ioremap(dev, start, len);
1098
+ if (!ioaddr) {
1099
+ dev_err(dev, "ioremap region fail, start:%pa, len:%pa\n",
1100
+ &start, &len);
1101
+ return -ENOMEM;
1102
+ }
1103
+
1104
+ binfo->start = start;
1105
+ binfo->len = len;
1106
+ binfo->ioaddr = ioaddr;
1107
+
1108
+ return 0;
1109
+}
1110
+
1111
+static void build_info_complete(struct build_feature_devs_info *binfo)
1112
+{
1113
+ devm_iounmap(binfo->dev, binfo->ioaddr);
1114
+ devm_release_mem_region(binfo->dev, binfo->start, binfo->len);
1115
+}
1116
+
6881117 static int parse_feature_fiu(struct build_feature_devs_info *binfo,
689
- struct dfl_fpga_enum_dfl *dfl,
6901118 resource_size_t ofst)
6911119 {
692
- u32 id, offset;
693
- u64 v;
6941120 int ret = 0;
1121
+ u32 offset;
1122
+ u16 id;
1123
+ u64 v;
6951124
696
- v = readq(dfl->ioaddr + ofst + DFH);
1125
+ if (is_feature_dev_detected(binfo)) {
1126
+ build_info_complete(binfo);
1127
+
1128
+ ret = build_info_commit_dev(binfo);
1129
+ if (ret)
1130
+ return ret;
1131
+
1132
+ ret = build_info_prepare(binfo, binfo->start + ofst,
1133
+ binfo->len - ofst);
1134
+ if (ret)
1135
+ return ret;
1136
+ }
1137
+
1138
+ v = readq(binfo->ioaddr + DFH);
6971139 id = FIELD_GET(DFH_ID, v);
6981140
6991141 /* create platform device for dfl feature dev */
700
- ret = build_info_create_dev(binfo, dfh_id_to_type(id),
701
- dfl->ioaddr + ofst);
1142
+ ret = build_info_create_dev(binfo, dfh_id_to_type(id));
7021143 if (ret)
7031144 return ret;
7041145
705
- ret = create_feature_instance(binfo, dfl, ofst, 0, 0);
1146
+ ret = create_feature_instance(binfo, 0, 0, 0);
7061147 if (ret)
7071148 return ret;
7081149 /*
7091150 * find and parse FIU's child AFU via its NEXT_AFU register.
7101151 * please note that only Port has valid NEXT_AFU pointer per spec.
7111152 */
712
- v = readq(dfl->ioaddr + ofst + NEXT_AFU);
1153
+ v = readq(binfo->ioaddr + NEXT_AFU);
7131154
7141155 offset = FIELD_GET(NEXT_AFU_NEXT_DFH_OFST, v);
7151156 if (offset)
716
- return parse_feature_afu(binfo, dfl, ofst + offset);
1157
+ return parse_feature_afu(binfo, offset);
7171158
7181159 dev_dbg(binfo->dev, "No AFUs detected on FIU %d\n", id);
7191160
....@@ -721,41 +1162,39 @@
7211162 }
7221163
7231164 static int parse_feature_private(struct build_feature_devs_info *binfo,
724
- struct dfl_fpga_enum_dfl *dfl,
7251165 resource_size_t ofst)
7261166 {
727
- if (!binfo->feature_dev) {
728
- dev_err(binfo->dev, "the private feature %llx does not belong to any AFU.\n",
729
- (unsigned long long)feature_id(dfl->ioaddr + ofst));
1167
+ if (!is_feature_dev_detected(binfo)) {
1168
+ dev_err(binfo->dev, "the private feature 0x%x does not belong to any AFU.\n",
1169
+ feature_id(binfo->ioaddr + ofst));
7301170 return -EINVAL;
7311171 }
7321172
733
- return create_feature_instance(binfo, dfl, ofst, 0, 0);
1173
+ return create_feature_instance(binfo, ofst, 0, 0);
7341174 }
7351175
7361176 /**
7371177 * parse_feature - parse a feature on given device feature list
7381178 *
7391179 * @binfo: build feature devices information.
740
- * @dfl: device feature list to parse
741
- * @ofst: offset to feature header on this device feature list
1180
+ * @ofst: offset to current FIU header
7421181 */
7431182 static int parse_feature(struct build_feature_devs_info *binfo,
744
- struct dfl_fpga_enum_dfl *dfl, resource_size_t ofst)
1183
+ resource_size_t ofst)
7451184 {
7461185 u64 v;
7471186 u32 type;
7481187
749
- v = readq(dfl->ioaddr + ofst + DFH);
1188
+ v = readq(binfo->ioaddr + ofst + DFH);
7501189 type = FIELD_GET(DFH_TYPE, v);
7511190
7521191 switch (type) {
7531192 case DFH_TYPE_AFU:
754
- return parse_feature_afu(binfo, dfl, ofst);
1193
+ return parse_feature_afu(binfo, ofst);
7551194 case DFH_TYPE_PRIVATE:
756
- return parse_feature_private(binfo, dfl, ofst);
1195
+ return parse_feature_private(binfo, ofst);
7571196 case DFH_TYPE_FIU:
758
- return parse_feature_fiu(binfo, dfl, ofst);
1197
+ return parse_feature_fiu(binfo, ofst);
7591198 default:
7601199 dev_info(binfo->dev,
7611200 "Feature Type %x is not supported.\n", type);
....@@ -765,13 +1204,16 @@
7651204 }
7661205
7671206 static int parse_feature_list(struct build_feature_devs_info *binfo,
768
- struct dfl_fpga_enum_dfl *dfl)
1207
+ resource_size_t start, resource_size_t len)
7691208 {
770
- void __iomem *start = dfl->ioaddr;
771
- void __iomem *end = dfl->ioaddr + dfl->len;
1209
+ resource_size_t end = start + len;
7721210 int ret = 0;
7731211 u32 ofst = 0;
7741212 u64 v;
1213
+
1214
+ ret = build_info_prepare(binfo, start, len);
1215
+ if (ret)
1216
+ return ret;
7751217
7761218 /* walk through the device feature list via DFH's next DFH pointer. */
7771219 for (; start < end; start += ofst) {
....@@ -780,11 +1222,11 @@
7801222 return -EINVAL;
7811223 }
7821224
783
- ret = parse_feature(binfo, dfl, start - dfl->ioaddr);
1225
+ ret = parse_feature(binfo, start - binfo->start);
7841226 if (ret)
7851227 return ret;
7861228
787
- v = readq(start + DFH);
1229
+ v = readq(binfo->ioaddr + start - binfo->start + DFH);
7881230 ofst = FIELD_GET(DFH_NEXT_HDR_OFST, v);
7891231
7901232 /* stop parsing if EOL(End of List) is set or offset is 0 */
....@@ -793,7 +1235,12 @@
7931235 }
7941236
7951237 /* commit current feature device when reach the end of list */
796
- return build_info_commit_dev(binfo);
1238
+ build_info_complete(binfo);
1239
+
1240
+ if (is_feature_dev_detected(binfo))
1241
+ ret = build_info_commit_dev(binfo);
1242
+
1243
+ return ret;
7971244 }
7981245
7991246 struct dfl_fpga_enum_info *dfl_fpga_enum_info_alloc(struct device *dev)
....@@ -831,6 +1278,10 @@
8311278 devm_kfree(dev, dfl);
8321279 }
8331280
1281
+ /* remove irq table */
1282
+ if (info->irq_table)
1283
+ devm_kfree(dev, info->irq_table);
1284
+
8341285 devm_kfree(dev, info);
8351286 put_device(dev);
8361287 }
....@@ -842,7 +1293,6 @@
8421293 * @info: ptr to dfl_fpga_enum_info
8431294 * @start: mmio resource address of the device feature list.
8441295 * @len: mmio resource length of the device feature list.
845
- * @ioaddr: mapped mmio resource address of the device feature list.
8461296 *
8471297 * One FPGA device may have one or more Device Feature Lists (DFLs), use this
8481298 * function to add information of each DFL to common data structure for next
....@@ -851,8 +1301,7 @@
8511301 * Return: 0 on success, negative error code otherwise.
8521302 */
8531303 int dfl_fpga_enum_info_add_dfl(struct dfl_fpga_enum_info *info,
854
- resource_size_t start, resource_size_t len,
855
- void __iomem *ioaddr)
1304
+ resource_size_t start, resource_size_t len)
8561305 {
8571306 struct dfl_fpga_enum_dfl *dfl;
8581307
....@@ -862,13 +1311,51 @@
8621311
8631312 dfl->start = start;
8641313 dfl->len = len;
865
- dfl->ioaddr = ioaddr;
8661314
8671315 list_add_tail(&dfl->node, &info->dfls);
8681316
8691317 return 0;
8701318 }
8711319 EXPORT_SYMBOL_GPL(dfl_fpga_enum_info_add_dfl);
1320
+
1321
+/**
1322
+ * dfl_fpga_enum_info_add_irq - add irq table to enum info
1323
+ *
1324
+ * @info: ptr to dfl_fpga_enum_info
1325
+ * @nr_irqs: number of irqs of the DFL fpga device to be enumerated.
1326
+ * @irq_table: Linux IRQ numbers for all irqs, indexed by local irq index of
1327
+ * this device.
1328
+ *
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.
1331
+ * This function should be called before dfl_fpga_feature_devs_enumerate().
1332
+ * As we only support one irq domain for all DFLs in the same enum info, adding
1333
+ * irq table a second time for the same enum info will return error.
1334
+ *
1335
+ * If we need to enumerate DFLs which belong to different irq domains, we
1336
+ * should fill more enum info and enumerate them one by one.
1337
+ *
1338
+ * Return: 0 on success, negative error code otherwise.
1339
+ */
1340
+int dfl_fpga_enum_info_add_irq(struct dfl_fpga_enum_info *info,
1341
+ unsigned int nr_irqs, int *irq_table)
1342
+{
1343
+ if (!nr_irqs || !irq_table)
1344
+ return -EINVAL;
1345
+
1346
+ if (info->irq_table)
1347
+ return -EEXIST;
1348
+
1349
+ info->irq_table = devm_kmemdup(info->dev, irq_table,
1350
+ sizeof(int) * nr_irqs, GFP_KERNEL);
1351
+ if (!info->irq_table)
1352
+ return -ENOMEM;
1353
+
1354
+ info->nr_irqs = nr_irqs;
1355
+
1356
+ return 0;
1357
+}
1358
+EXPORT_SYMBOL_GPL(dfl_fpga_enum_info_add_irq);
8721359
8731360 static int remove_feature_dev(struct device *dev, void *data)
8741361 {
....@@ -913,7 +1400,7 @@
9131400 if (!cdev)
9141401 return ERR_PTR(-ENOMEM);
9151402
916
- cdev->region = fpga_region_create(info->dev, NULL, NULL);
1403
+ cdev->region = devm_fpga_region_create(info->dev, NULL, NULL);
9171404 if (!cdev->region) {
9181405 ret = -ENOMEM;
9191406 goto free_cdev_exit;
....@@ -925,7 +1412,7 @@
9251412
9261413 ret = fpga_region_register(cdev->region);
9271414 if (ret)
928
- goto free_region_exit;
1415
+ goto free_cdev_exit;
9291416
9301417 /* create and init build info for enumeration */
9311418 binfo = devm_kzalloc(info->dev, sizeof(*binfo), GFP_KERNEL);
....@@ -937,12 +1424,16 @@
9371424 binfo->dev = info->dev;
9381425 binfo->cdev = cdev;
9391426
1427
+ binfo->nr_irqs = info->nr_irqs;
1428
+ if (info->nr_irqs)
1429
+ binfo->irq_table = info->irq_table;
1430
+
9401431 /*
9411432 * start enumeration for all feature devices based on Device Feature
9421433 * Lists.
9431434 */
9441435 list_for_each_entry(dfl, &info->dfls, node) {
945
- ret = parse_feature_list(binfo, dfl);
1436
+ ret = parse_feature_list(binfo, dfl->start, dfl->len);
9461437 if (ret) {
9471438 remove_feature_devs(cdev);
9481439 build_info_free(binfo);
....@@ -956,8 +1447,6 @@
9561447
9571448 unregister_region_exit:
9581449 fpga_region_unregister(cdev->region);
959
-free_region_exit:
960
- fpga_region_free(cdev->region);
9611450 free_cdev_exit:
9621451 devm_kfree(info->dev, cdev);
9631452 return ERR_PTR(ret);
....@@ -975,24 +1464,26 @@
9751464 {
9761465 struct dfl_feature_platform_data *pdata, *ptmp;
9771466
978
- remove_feature_devs(cdev);
979
-
9801467 mutex_lock(&cdev->lock);
981
- if (cdev->fme_dev) {
982
- /* the fme should be unregistered. */
983
- WARN_ON(device_is_registered(cdev->fme_dev));
1468
+ if (cdev->fme_dev)
9841469 put_device(cdev->fme_dev);
985
- }
9861470
9871471 list_for_each_entry_safe(pdata, ptmp, &cdev->port_dev_list, node) {
9881472 struct platform_device *port_dev = pdata->dev;
9891473
990
- /* the port should be unregistered. */
991
- WARN_ON(device_is_registered(&port_dev->dev));
1474
+ /* remove released ports */
1475
+ if (!device_is_registered(&port_dev->dev)) {
1476
+ dfl_id_free(feature_dev_id_type(port_dev),
1477
+ port_dev->id);
1478
+ platform_device_put(port_dev);
1479
+ }
1480
+
9921481 list_del(&pdata->node);
9931482 put_device(&port_dev->dev);
9941483 }
9951484 mutex_unlock(&cdev->lock);
1485
+
1486
+ remove_feature_devs(cdev);
9961487
9971488 fpga_region_unregister(cdev->region);
9981489 devm_kfree(cdev->parent, cdev);
....@@ -1035,19 +1526,355 @@
10351526 {
10361527 int ret;
10371528
1529
+ ret = bus_register(&dfl_bus_type);
1530
+ if (ret)
1531
+ return ret;
1532
+
10381533 dfl_ids_init();
10391534
10401535 ret = dfl_chardev_init();
1041
- if (ret)
1536
+ if (ret) {
10421537 dfl_ids_destroy();
1538
+ bus_unregister(&dfl_bus_type);
1539
+ }
10431540
10441541 return ret;
10451542 }
1543
+
1544
+/**
1545
+ * dfl_fpga_cdev_release_port - release a port platform device
1546
+ *
1547
+ * @cdev: parent container device.
1548
+ * @port_id: id of the port platform device.
1549
+ *
1550
+ * This function allows user to release a port platform device. This is a
1551
+ * mandatory step before turn a port from PF into VF for SRIOV support.
1552
+ *
1553
+ * Return: 0 on success, negative error code otherwise.
1554
+ */
1555
+int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id)
1556
+{
1557
+ struct dfl_feature_platform_data *pdata;
1558
+ struct platform_device *port_pdev;
1559
+ int ret = -ENODEV;
1560
+
1561
+ mutex_lock(&cdev->lock);
1562
+ port_pdev = __dfl_fpga_cdev_find_port(cdev, &port_id,
1563
+ dfl_fpga_check_port_id);
1564
+ if (!port_pdev)
1565
+ goto unlock_exit;
1566
+
1567
+ if (!device_is_registered(&port_pdev->dev)) {
1568
+ ret = -EBUSY;
1569
+ goto put_dev_exit;
1570
+ }
1571
+
1572
+ pdata = dev_get_platdata(&port_pdev->dev);
1573
+
1574
+ mutex_lock(&pdata->lock);
1575
+ ret = dfl_feature_dev_use_begin(pdata, true);
1576
+ mutex_unlock(&pdata->lock);
1577
+ if (ret)
1578
+ goto put_dev_exit;
1579
+
1580
+ platform_device_del(port_pdev);
1581
+ cdev->released_port_num++;
1582
+put_dev_exit:
1583
+ put_device(&port_pdev->dev);
1584
+unlock_exit:
1585
+ mutex_unlock(&cdev->lock);
1586
+ return ret;
1587
+}
1588
+EXPORT_SYMBOL_GPL(dfl_fpga_cdev_release_port);
1589
+
1590
+/**
1591
+ * dfl_fpga_cdev_assign_port - assign a port platform device back
1592
+ *
1593
+ * @cdev: parent container device.
1594
+ * @port_id: id of the port platform device.
1595
+ *
1596
+ * This function allows user to assign a port platform device back. This is
1597
+ * a mandatory step after disable SRIOV support.
1598
+ *
1599
+ * Return: 0 on success, negative error code otherwise.
1600
+ */
1601
+int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id)
1602
+{
1603
+ struct dfl_feature_platform_data *pdata;
1604
+ struct platform_device *port_pdev;
1605
+ int ret = -ENODEV;
1606
+
1607
+ mutex_lock(&cdev->lock);
1608
+ port_pdev = __dfl_fpga_cdev_find_port(cdev, &port_id,
1609
+ dfl_fpga_check_port_id);
1610
+ if (!port_pdev)
1611
+ goto unlock_exit;
1612
+
1613
+ if (device_is_registered(&port_pdev->dev)) {
1614
+ ret = -EBUSY;
1615
+ goto put_dev_exit;
1616
+ }
1617
+
1618
+ ret = platform_device_add(port_pdev);
1619
+ if (ret)
1620
+ goto put_dev_exit;
1621
+
1622
+ pdata = dev_get_platdata(&port_pdev->dev);
1623
+
1624
+ mutex_lock(&pdata->lock);
1625
+ dfl_feature_dev_use_end(pdata);
1626
+ mutex_unlock(&pdata->lock);
1627
+
1628
+ cdev->released_port_num--;
1629
+put_dev_exit:
1630
+ put_device(&port_pdev->dev);
1631
+unlock_exit:
1632
+ mutex_unlock(&cdev->lock);
1633
+ return ret;
1634
+}
1635
+EXPORT_SYMBOL_GPL(dfl_fpga_cdev_assign_port);
1636
+
1637
+static void config_port_access_mode(struct device *fme_dev, int port_id,
1638
+ bool is_vf)
1639
+{
1640
+ void __iomem *base;
1641
+ u64 v;
1642
+
1643
+ base = dfl_get_feature_ioaddr_by_id(fme_dev, FME_FEATURE_ID_HEADER);
1644
+
1645
+ v = readq(base + FME_HDR_PORT_OFST(port_id));
1646
+
1647
+ v &= ~FME_PORT_OFST_ACC_CTRL;
1648
+ v |= FIELD_PREP(FME_PORT_OFST_ACC_CTRL,
1649
+ is_vf ? FME_PORT_OFST_ACC_VF : FME_PORT_OFST_ACC_PF);
1650
+
1651
+ writeq(v, base + FME_HDR_PORT_OFST(port_id));
1652
+}
1653
+
1654
+#define config_port_vf_mode(dev, id) config_port_access_mode(dev, id, true)
1655
+#define config_port_pf_mode(dev, id) config_port_access_mode(dev, id, false)
1656
+
1657
+/**
1658
+ * dfl_fpga_cdev_config_ports_pf - configure ports to PF access mode
1659
+ *
1660
+ * @cdev: parent container device.
1661
+ *
1662
+ * This function is needed in sriov configuration routine. It could be used to
1663
+ * configure the all released ports from VF access mode to PF.
1664
+ */
1665
+void dfl_fpga_cdev_config_ports_pf(struct dfl_fpga_cdev *cdev)
1666
+{
1667
+ struct dfl_feature_platform_data *pdata;
1668
+
1669
+ mutex_lock(&cdev->lock);
1670
+ list_for_each_entry(pdata, &cdev->port_dev_list, node) {
1671
+ if (device_is_registered(&pdata->dev->dev))
1672
+ continue;
1673
+
1674
+ config_port_pf_mode(cdev->fme_dev, pdata->id);
1675
+ }
1676
+ mutex_unlock(&cdev->lock);
1677
+}
1678
+EXPORT_SYMBOL_GPL(dfl_fpga_cdev_config_ports_pf);
1679
+
1680
+/**
1681
+ * dfl_fpga_cdev_config_ports_vf - configure ports to VF access mode
1682
+ *
1683
+ * @cdev: parent container device.
1684
+ * @num_vfs: VF device number.
1685
+ *
1686
+ * This function is needed in sriov configuration routine. It could be used to
1687
+ * configure the released ports from PF access mode to VF.
1688
+ *
1689
+ * Return: 0 on success, negative error code otherwise.
1690
+ */
1691
+int dfl_fpga_cdev_config_ports_vf(struct dfl_fpga_cdev *cdev, int num_vfs)
1692
+{
1693
+ struct dfl_feature_platform_data *pdata;
1694
+ int ret = 0;
1695
+
1696
+ mutex_lock(&cdev->lock);
1697
+ /*
1698
+ * can't turn multiple ports into 1 VF device, only 1 port for 1 VF
1699
+ * device, so if released port number doesn't match VF device number,
1700
+ * then reject the request with -EINVAL error code.
1701
+ */
1702
+ if (cdev->released_port_num != num_vfs) {
1703
+ ret = -EINVAL;
1704
+ goto done;
1705
+ }
1706
+
1707
+ list_for_each_entry(pdata, &cdev->port_dev_list, node) {
1708
+ if (device_is_registered(&pdata->dev->dev))
1709
+ continue;
1710
+
1711
+ config_port_vf_mode(cdev->fme_dev, pdata->id);
1712
+ }
1713
+done:
1714
+ mutex_unlock(&cdev->lock);
1715
+ return ret;
1716
+}
1717
+EXPORT_SYMBOL_GPL(dfl_fpga_cdev_config_ports_vf);
1718
+
1719
+static irqreturn_t dfl_irq_handler(int irq, void *arg)
1720
+{
1721
+ struct eventfd_ctx *trigger = arg;
1722
+
1723
+ eventfd_signal(trigger, 1);
1724
+ return IRQ_HANDLED;
1725
+}
1726
+
1727
+static int do_set_irq_trigger(struct dfl_feature *feature, unsigned int idx,
1728
+ int fd)
1729
+{
1730
+ struct platform_device *pdev = feature->dev;
1731
+ struct eventfd_ctx *trigger;
1732
+ int irq, ret;
1733
+
1734
+ irq = feature->irq_ctx[idx].irq;
1735
+
1736
+ if (feature->irq_ctx[idx].trigger) {
1737
+ free_irq(irq, feature->irq_ctx[idx].trigger);
1738
+ kfree(feature->irq_ctx[idx].name);
1739
+ eventfd_ctx_put(feature->irq_ctx[idx].trigger);
1740
+ feature->irq_ctx[idx].trigger = NULL;
1741
+ }
1742
+
1743
+ if (fd < 0)
1744
+ return 0;
1745
+
1746
+ feature->irq_ctx[idx].name =
1747
+ kasprintf(GFP_KERNEL, "fpga-irq[%u](%s-%x)", idx,
1748
+ dev_name(&pdev->dev), feature->id);
1749
+ if (!feature->irq_ctx[idx].name)
1750
+ return -ENOMEM;
1751
+
1752
+ trigger = eventfd_ctx_fdget(fd);
1753
+ if (IS_ERR(trigger)) {
1754
+ ret = PTR_ERR(trigger);
1755
+ goto free_name;
1756
+ }
1757
+
1758
+ ret = request_irq(irq, dfl_irq_handler, 0,
1759
+ feature->irq_ctx[idx].name, trigger);
1760
+ if (!ret) {
1761
+ feature->irq_ctx[idx].trigger = trigger;
1762
+ return ret;
1763
+ }
1764
+
1765
+ eventfd_ctx_put(trigger);
1766
+free_name:
1767
+ kfree(feature->irq_ctx[idx].name);
1768
+
1769
+ return ret;
1770
+}
1771
+
1772
+/**
1773
+ * dfl_fpga_set_irq_triggers - set eventfd triggers for dfl feature interrupts
1774
+ *
1775
+ * @feature: dfl sub feature.
1776
+ * @start: start of irq index in this dfl sub feature.
1777
+ * @count: number of irqs.
1778
+ * @fds: eventfds to bind with irqs. unbind related irq if fds[n] is negative.
1779
+ * unbind "count" specified number of irqs if fds ptr is NULL.
1780
+ *
1781
+ * Bind given eventfds with irqs in this dfl sub feature. Unbind related irq if
1782
+ * fds[n] is negative. Unbind "count" specified number of irqs if fds ptr is
1783
+ * NULL.
1784
+ *
1785
+ * Return: 0 on success, negative error code otherwise.
1786
+ */
1787
+int dfl_fpga_set_irq_triggers(struct dfl_feature *feature, unsigned int start,
1788
+ unsigned int count, int32_t *fds)
1789
+{
1790
+ unsigned int i;
1791
+ int ret = 0;
1792
+
1793
+ /* overflow */
1794
+ if (unlikely(start + count < start))
1795
+ return -EINVAL;
1796
+
1797
+ /* exceeds nr_irqs */
1798
+ if (start + count > feature->nr_irqs)
1799
+ return -EINVAL;
1800
+
1801
+ for (i = 0; i < count; i++) {
1802
+ int fd = fds ? fds[i] : -1;
1803
+
1804
+ ret = do_set_irq_trigger(feature, start + i, fd);
1805
+ if (ret) {
1806
+ while (i--)
1807
+ do_set_irq_trigger(feature, start + i, -1);
1808
+ break;
1809
+ }
1810
+ }
1811
+
1812
+ return ret;
1813
+}
1814
+EXPORT_SYMBOL_GPL(dfl_fpga_set_irq_triggers);
1815
+
1816
+/**
1817
+ * dfl_feature_ioctl_get_num_irqs - dfl feature _GET_IRQ_NUM ioctl interface.
1818
+ * @pdev: the feature device which has the sub feature
1819
+ * @feature: the dfl sub feature
1820
+ * @arg: ioctl argument
1821
+ *
1822
+ * Return: 0 on success, negative error code otherwise.
1823
+ */
1824
+long dfl_feature_ioctl_get_num_irqs(struct platform_device *pdev,
1825
+ struct dfl_feature *feature,
1826
+ unsigned long arg)
1827
+{
1828
+ return put_user(feature->nr_irqs, (__u32 __user *)arg);
1829
+}
1830
+EXPORT_SYMBOL_GPL(dfl_feature_ioctl_get_num_irqs);
1831
+
1832
+/**
1833
+ * dfl_feature_ioctl_set_irq - dfl feature _SET_IRQ ioctl interface.
1834
+ * @pdev: the feature device which has the sub feature
1835
+ * @feature: the dfl sub feature
1836
+ * @arg: ioctl argument
1837
+ *
1838
+ * Return: 0 on success, negative error code otherwise.
1839
+ */
1840
+long dfl_feature_ioctl_set_irq(struct platform_device *pdev,
1841
+ struct dfl_feature *feature,
1842
+ unsigned long arg)
1843
+{
1844
+ struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
1845
+ struct dfl_fpga_irq_set hdr;
1846
+ s32 *fds;
1847
+ long ret;
1848
+
1849
+ if (!feature->nr_irqs)
1850
+ return -ENOENT;
1851
+
1852
+ if (copy_from_user(&hdr, (void __user *)arg, sizeof(hdr)))
1853
+ return -EFAULT;
1854
+
1855
+ if (!hdr.count || (hdr.start + hdr.count > feature->nr_irqs) ||
1856
+ (hdr.start + hdr.count < hdr.start))
1857
+ return -EINVAL;
1858
+
1859
+ fds = memdup_user((void __user *)(arg + sizeof(hdr)),
1860
+ array_size(hdr.count, sizeof(s32)));
1861
+ if (IS_ERR(fds))
1862
+ return PTR_ERR(fds);
1863
+
1864
+ mutex_lock(&pdata->lock);
1865
+ ret = dfl_fpga_set_irq_triggers(feature, hdr.start, hdr.count, fds);
1866
+ mutex_unlock(&pdata->lock);
1867
+
1868
+ kfree(fds);
1869
+ return ret;
1870
+}
1871
+EXPORT_SYMBOL_GPL(dfl_feature_ioctl_set_irq);
10461872
10471873 static void __exit dfl_fpga_exit(void)
10481874 {
10491875 dfl_chardev_uinit();
10501876 dfl_ids_destroy();
1877
+ bus_unregister(&dfl_bus_type);
10511878 }
10521879
10531880 module_init(dfl_fpga_init);