]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/fpga/dfl.c
Merge tag 'extcon-next-for-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / drivers / fpga / dfl.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Driver for FPGA Device Feature List (DFL) Support
4  *
5  * Copyright (C) 2017-2018 Intel Corporation, Inc.
6  *
7  * Authors:
8  *   Kang Luwei <luwei.kang@intel.com>
9  *   Zhang Yi <yi.z.zhang@intel.com>
10  *   Wu Hao <hao.wu@intel.com>
11  *   Xiao Guangrong <guangrong.xiao@linux.intel.com>
12  */
13 #include <linux/module.h>
14
15 #include "dfl.h"
16
17 static DEFINE_MUTEX(dfl_id_mutex);
18
19 /*
20  * when adding a new feature dev support in DFL framework, it's required to
21  * add a new item in enum dfl_id_type and provide related information in below
22  * dfl_devs table which is indexed by dfl_id_type, e.g. name string used for
23  * platform device creation (define name strings in dfl.h, as they could be
24  * reused by platform device drivers).
25  *
26  * if the new feature dev needs chardev support, then it's required to add
27  * a new item in dfl_chardevs table and configure dfl_devs[i].devt_type as
28  * index to dfl_chardevs table. If no chardev support just set devt_type
29  * as one invalid index (DFL_FPGA_DEVT_MAX).
30  */
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
37 enum dfl_fpga_devt_type {
38         DFL_FPGA_DEVT_FME,
39         DFL_FPGA_DEVT_PORT,
40         DFL_FPGA_DEVT_MAX,
41 };
42
43 static struct lock_class_key dfl_pdata_keys[DFL_ID_MAX];
44
45 static const char *dfl_pdata_key_strings[DFL_ID_MAX] = {
46         "dfl-fme-pdata",
47         "dfl-port-pdata",
48 };
49
50 /**
51  * dfl_dev_info - dfl feature device information.
52  * @name: name string of the feature platform device.
53  * @dfh_id: id value in Device Feature Header (DFH) register by DFL spec.
54  * @id: idr id of the feature dev.
55  * @devt_type: index to dfl_chrdevs[].
56  */
57 struct dfl_dev_info {
58         const char *name;
59         u32 dfh_id;
60         struct idr id;
61         enum dfl_fpga_devt_type devt_type;
62 };
63
64 /* it is indexed by dfl_id_type */
65 static struct dfl_dev_info dfl_devs[] = {
66         {.name = DFL_FPGA_FEATURE_DEV_FME, .dfh_id = DFH_ID_FIU_FME,
67          .devt_type = DFL_FPGA_DEVT_FME},
68         {.name = DFL_FPGA_FEATURE_DEV_PORT, .dfh_id = DFH_ID_FIU_PORT,
69          .devt_type = DFL_FPGA_DEVT_PORT},
70 };
71
72 /**
73  * dfl_chardev_info - chardev information of dfl feature device
74  * @name: nmae string of the char device.
75  * @devt: devt of the char device.
76  */
77 struct dfl_chardev_info {
78         const char *name;
79         dev_t devt;
80 };
81
82 /* indexed by enum dfl_fpga_devt_type */
83 static struct dfl_chardev_info dfl_chrdevs[] = {
84         {.name = DFL_FPGA_FEATURE_DEV_FME},
85         {.name = DFL_FPGA_FEATURE_DEV_PORT},
86 };
87
88 static void dfl_ids_init(void)
89 {
90         int i;
91
92         for (i = 0; i < ARRAY_SIZE(dfl_devs); i++)
93                 idr_init(&dfl_devs[i].id);
94 }
95
96 static void dfl_ids_destroy(void)
97 {
98         int i;
99
100         for (i = 0; i < ARRAY_SIZE(dfl_devs); i++)
101                 idr_destroy(&dfl_devs[i].id);
102 }
103
104 static int dfl_id_alloc(enum dfl_id_type type, struct device *dev)
105 {
106         int id;
107
108         WARN_ON(type >= DFL_ID_MAX);
109         mutex_lock(&dfl_id_mutex);
110         id = idr_alloc(&dfl_devs[type].id, dev, 0, 0, GFP_KERNEL);
111         mutex_unlock(&dfl_id_mutex);
112
113         return id;
114 }
115
116 static void dfl_id_free(enum dfl_id_type type, int id)
117 {
118         WARN_ON(type >= DFL_ID_MAX);
119         mutex_lock(&dfl_id_mutex);
120         idr_remove(&dfl_devs[type].id, id);
121         mutex_unlock(&dfl_id_mutex);
122 }
123
124 static enum dfl_id_type feature_dev_id_type(struct platform_device *pdev)
125 {
126         int i;
127
128         for (i = 0; i < ARRAY_SIZE(dfl_devs); i++)
129                 if (!strcmp(dfl_devs[i].name, pdev->name))
130                         return i;
131
132         return DFL_ID_MAX;
133 }
134
135 static enum dfl_id_type dfh_id_to_type(u32 id)
136 {
137         int i;
138
139         for (i = 0; i < ARRAY_SIZE(dfl_devs); i++)
140                 if (dfl_devs[i].dfh_id == id)
141                         return i;
142
143         return DFL_ID_MAX;
144 }
145
146 /*
147  * introduce a global port_ops list, it allows port drivers to register ops
148  * in such list, then other feature devices (e.g. FME), could use the port
149  * functions even related port platform device is hidden. Below is one example,
150  * in virtualization case of PCIe-based FPGA DFL device, when SRIOV is
151  * enabled, port (and it's AFU) is turned into VF and port platform device
152  * is hidden from system but it's still required to access port to finish FPGA
153  * reconfiguration function in FME.
154  */
155
156 static DEFINE_MUTEX(dfl_port_ops_mutex);
157 static LIST_HEAD(dfl_port_ops_list);
158
159 /**
160  * dfl_fpga_port_ops_get - get matched port ops from the global list
161  * @pdev: platform device to match with associated port ops.
162  * Return: matched port ops on success, NULL otherwise.
163  *
164  * Please note that must dfl_fpga_port_ops_put after use the port_ops.
165  */
166 struct dfl_fpga_port_ops *dfl_fpga_port_ops_get(struct platform_device *pdev)
167 {
168         struct dfl_fpga_port_ops *ops = NULL;
169
170         mutex_lock(&dfl_port_ops_mutex);
171         if (list_empty(&dfl_port_ops_list))
172                 goto done;
173
174         list_for_each_entry(ops, &dfl_port_ops_list, node) {
175                 /* match port_ops using the name of platform device */
176                 if (!strcmp(pdev->name, ops->name)) {
177                         if (!try_module_get(ops->owner))
178                                 ops = NULL;
179                         goto done;
180                 }
181         }
182
183         ops = NULL;
184 done:
185         mutex_unlock(&dfl_port_ops_mutex);
186         return ops;
187 }
188 EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_get);
189
190 /**
191  * dfl_fpga_port_ops_put - put port ops
192  * @ops: port ops.
193  */
194 void dfl_fpga_port_ops_put(struct dfl_fpga_port_ops *ops)
195 {
196         if (ops && ops->owner)
197                 module_put(ops->owner);
198 }
199 EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_put);
200
201 /**
202  * dfl_fpga_port_ops_add - add port_ops to global list
203  * @ops: port ops to add.
204  */
205 void dfl_fpga_port_ops_add(struct dfl_fpga_port_ops *ops)
206 {
207         mutex_lock(&dfl_port_ops_mutex);
208         list_add_tail(&ops->node, &dfl_port_ops_list);
209         mutex_unlock(&dfl_port_ops_mutex);
210 }
211 EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_add);
212
213 /**
214  * dfl_fpga_port_ops_del - remove port_ops from global list
215  * @ops: port ops to del.
216  */
217 void dfl_fpga_port_ops_del(struct dfl_fpga_port_ops *ops)
218 {
219         mutex_lock(&dfl_port_ops_mutex);
220         list_del(&ops->node);
221         mutex_unlock(&dfl_port_ops_mutex);
222 }
223 EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_del);
224
225 /**
226  * dfl_fpga_check_port_id - check the port id
227  * @pdev: port platform device.
228  * @pport_id: port id to compare.
229  *
230  * Return: 1 if port device matches with given port id, otherwise 0.
231  */
232 int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id)
233 {
234         struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
235         struct dfl_fpga_port_ops *port_ops;
236
237         if (pdata->id != FEATURE_DEV_ID_UNUSED)
238                 return pdata->id == *(int *)pport_id;
239
240         port_ops = dfl_fpga_port_ops_get(pdev);
241         if (!port_ops || !port_ops->get_id)
242                 return 0;
243
244         pdata->id = port_ops->get_id(pdev);
245         dfl_fpga_port_ops_put(port_ops);
246
247         return pdata->id == *(int *)pport_id;
248 }
249 EXPORT_SYMBOL_GPL(dfl_fpga_check_port_id);
250
251 /**
252  * dfl_fpga_dev_feature_uinit - uinit for sub features of dfl feature device
253  * @pdev: feature device.
254  */
255 void dfl_fpga_dev_feature_uinit(struct platform_device *pdev)
256 {
257         struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
258         struct dfl_feature *feature;
259
260         dfl_fpga_dev_for_each_feature(pdata, feature)
261                 if (feature->ops) {
262                         if (feature->ops->uinit)
263                                 feature->ops->uinit(pdev, feature);
264                         feature->ops = NULL;
265                 }
266 }
267 EXPORT_SYMBOL_GPL(dfl_fpga_dev_feature_uinit);
268
269 static int dfl_feature_instance_init(struct platform_device *pdev,
270                                      struct dfl_feature_platform_data *pdata,
271                                      struct dfl_feature *feature,
272                                      struct dfl_feature_driver *drv)
273 {
274         int ret;
275
276         ret = drv->ops->init(pdev, feature);
277         if (ret)
278                 return ret;
279
280         feature->ops = drv->ops;
281
282         return ret;
283 }
284
285 static bool dfl_feature_drv_match(struct dfl_feature *feature,
286                                   struct dfl_feature_driver *driver)
287 {
288         const struct dfl_feature_id *ids = driver->id_table;
289
290         if (ids) {
291                 while (ids->id) {
292                         if (ids->id == feature->id)
293                                 return true;
294                         ids++;
295                 }
296         }
297         return false;
298 }
299
300 /**
301  * dfl_fpga_dev_feature_init - init for sub features of dfl feature device
302  * @pdev: feature device.
303  * @feature_drvs: drvs for sub features.
304  *
305  * This function will match sub features with given feature drvs list and
306  * use matched drv to init related sub feature.
307  *
308  * Return: 0 on success, negative error code otherwise.
309  */
310 int dfl_fpga_dev_feature_init(struct platform_device *pdev,
311                               struct dfl_feature_driver *feature_drvs)
312 {
313         struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
314         struct dfl_feature_driver *drv = feature_drvs;
315         struct dfl_feature *feature;
316         int ret;
317
318         while (drv->ops) {
319                 dfl_fpga_dev_for_each_feature(pdata, feature) {
320                         if (dfl_feature_drv_match(feature, drv)) {
321                                 ret = dfl_feature_instance_init(pdev, pdata,
322                                                                 feature, drv);
323                                 if (ret)
324                                         goto exit;
325                         }
326                 }
327                 drv++;
328         }
329
330         return 0;
331 exit:
332         dfl_fpga_dev_feature_uinit(pdev);
333         return ret;
334 }
335 EXPORT_SYMBOL_GPL(dfl_fpga_dev_feature_init);
336
337 static void dfl_chardev_uinit(void)
338 {
339         int i;
340
341         for (i = 0; i < DFL_FPGA_DEVT_MAX; i++)
342                 if (MAJOR(dfl_chrdevs[i].devt)) {
343                         unregister_chrdev_region(dfl_chrdevs[i].devt,
344                                                  MINORMASK + 1);
345                         dfl_chrdevs[i].devt = MKDEV(0, 0);
346                 }
347 }
348
349 static int dfl_chardev_init(void)
350 {
351         int i, ret;
352
353         for (i = 0; i < DFL_FPGA_DEVT_MAX; i++) {
354                 ret = alloc_chrdev_region(&dfl_chrdevs[i].devt, 0,
355                                           MINORMASK + 1, dfl_chrdevs[i].name);
356                 if (ret)
357                         goto exit;
358         }
359
360         return 0;
361
362 exit:
363         dfl_chardev_uinit();
364         return ret;
365 }
366
367 static dev_t dfl_get_devt(enum dfl_fpga_devt_type type, int id)
368 {
369         if (type >= DFL_FPGA_DEVT_MAX)
370                 return 0;
371
372         return MKDEV(MAJOR(dfl_chrdevs[type].devt), id);
373 }
374
375 /**
376  * dfl_fpga_dev_ops_register - register cdev ops for feature dev
377  *
378  * @pdev: feature dev.
379  * @fops: file operations for feature dev's cdev.
380  * @owner: owning module/driver.
381  *
382  * Return: 0 on success, negative error code otherwise.
383  */
384 int dfl_fpga_dev_ops_register(struct platform_device *pdev,
385                               const struct file_operations *fops,
386                               struct module *owner)
387 {
388         struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
389
390         cdev_init(&pdata->cdev, fops);
391         pdata->cdev.owner = owner;
392
393         /*
394          * set parent to the feature device so that its refcount is
395          * decreased after the last refcount of cdev is gone, that
396          * makes sure the feature device is valid during device
397          * file's life-cycle.
398          */
399         pdata->cdev.kobj.parent = &pdev->dev.kobj;
400
401         return cdev_add(&pdata->cdev, pdev->dev.devt, 1);
402 }
403 EXPORT_SYMBOL_GPL(dfl_fpga_dev_ops_register);
404
405 /**
406  * dfl_fpga_dev_ops_unregister - unregister cdev ops for feature dev
407  * @pdev: feature dev.
408  */
409 void dfl_fpga_dev_ops_unregister(struct platform_device *pdev)
410 {
411         struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
412
413         cdev_del(&pdata->cdev);
414 }
415 EXPORT_SYMBOL_GPL(dfl_fpga_dev_ops_unregister);
416
417 /**
418  * struct build_feature_devs_info - info collected during feature dev build.
419  *
420  * @dev: device to enumerate.
421  * @cdev: the container device for all feature devices.
422  * @feature_dev: current feature device.
423  * @ioaddr: header register region address of feature device in enumeration.
424  * @sub_features: a sub features linked list for feature device in enumeration.
425  * @feature_num: number of sub features for feature device in enumeration.
426  */
427 struct build_feature_devs_info {
428         struct device *dev;
429         struct dfl_fpga_cdev *cdev;
430         struct platform_device *feature_dev;
431         void __iomem *ioaddr;
432         struct list_head sub_features;
433         int feature_num;
434 };
435
436 /**
437  * struct dfl_feature_info - sub feature info collected during feature dev build
438  *
439  * @fid: id of this sub feature.
440  * @mmio_res: mmio resource of this sub feature.
441  * @ioaddr: mapped base address of mmio resource.
442  * @node: node in sub_features linked list.
443  */
444 struct dfl_feature_info {
445         u64 fid;
446         struct resource mmio_res;
447         void __iomem *ioaddr;
448         struct list_head node;
449 };
450
451 static void dfl_fpga_cdev_add_port_dev(struct dfl_fpga_cdev *cdev,
452                                        struct platform_device *port)
453 {
454         struct dfl_feature_platform_data *pdata = dev_get_platdata(&port->dev);
455
456         mutex_lock(&cdev->lock);
457         list_add(&pdata->node, &cdev->port_dev_list);
458         get_device(&pdata->dev->dev);
459         mutex_unlock(&cdev->lock);
460 }
461
462 /*
463  * register current feature device, it is called when we need to switch to
464  * another feature parsing or we have parsed all features on given device
465  * feature list.
466  */
467 static int build_info_commit_dev(struct build_feature_devs_info *binfo)
468 {
469         struct platform_device *fdev = binfo->feature_dev;
470         struct dfl_feature_platform_data *pdata;
471         struct dfl_feature_info *finfo, *p;
472         enum dfl_id_type type;
473         int ret, index = 0;
474
475         if (!fdev)
476                 return 0;
477
478         type = feature_dev_id_type(fdev);
479         if (WARN_ON_ONCE(type >= DFL_ID_MAX))
480                 return -EINVAL;
481
482         /*
483          * we do not need to care for the memory which is associated with
484          * the platform device. After calling platform_device_unregister(),
485          * it will be automatically freed by device's release() callback,
486          * platform_device_release().
487          */
488         pdata = kzalloc(dfl_feature_platform_data_size(binfo->feature_num),
489                         GFP_KERNEL);
490         if (!pdata)
491                 return -ENOMEM;
492
493         pdata->dev = fdev;
494         pdata->num = binfo->feature_num;
495         pdata->dfl_cdev = binfo->cdev;
496         pdata->id = FEATURE_DEV_ID_UNUSED;
497         mutex_init(&pdata->lock);
498         lockdep_set_class_and_name(&pdata->lock, &dfl_pdata_keys[type],
499                                    dfl_pdata_key_strings[type]);
500
501         /*
502          * the count should be initialized to 0 to make sure
503          *__fpga_port_enable() following __fpga_port_disable()
504          * works properly for port device.
505          * and it should always be 0 for fme device.
506          */
507         WARN_ON(pdata->disable_count);
508
509         fdev->dev.platform_data = pdata;
510
511         /* each sub feature has one MMIO resource */
512         fdev->num_resources = binfo->feature_num;
513         fdev->resource = kcalloc(binfo->feature_num, sizeof(*fdev->resource),
514                                  GFP_KERNEL);
515         if (!fdev->resource)
516                 return -ENOMEM;
517
518         /* fill features and resource information for feature dev */
519         list_for_each_entry_safe(finfo, p, &binfo->sub_features, node) {
520                 struct dfl_feature *feature = &pdata->features[index];
521
522                 /* save resource information for each feature */
523                 feature->id = finfo->fid;
524                 feature->resource_index = index;
525                 feature->ioaddr = finfo->ioaddr;
526                 fdev->resource[index++] = finfo->mmio_res;
527
528                 list_del(&finfo->node);
529                 kfree(finfo);
530         }
531
532         ret = platform_device_add(binfo->feature_dev);
533         if (!ret) {
534                 if (type == PORT_ID)
535                         dfl_fpga_cdev_add_port_dev(binfo->cdev,
536                                                    binfo->feature_dev);
537                 else
538                         binfo->cdev->fme_dev =
539                                         get_device(&binfo->feature_dev->dev);
540                 /*
541                  * reset it to avoid build_info_free() freeing their resource.
542                  *
543                  * The resource of successfully registered feature devices
544                  * will be freed by platform_device_unregister(). See the
545                  * comments in build_info_create_dev().
546                  */
547                 binfo->feature_dev = NULL;
548         }
549
550         return ret;
551 }
552
553 static int
554 build_info_create_dev(struct build_feature_devs_info *binfo,
555                       enum dfl_id_type type, void __iomem *ioaddr)
556 {
557         struct platform_device *fdev;
558         int ret;
559
560         if (type >= DFL_ID_MAX)
561                 return -EINVAL;
562
563         /* we will create a new device, commit current device first */
564         ret = build_info_commit_dev(binfo);
565         if (ret)
566                 return ret;
567
568         /*
569          * we use -ENODEV as the initialization indicator which indicates
570          * whether the id need to be reclaimed
571          */
572         fdev = platform_device_alloc(dfl_devs[type].name, -ENODEV);
573         if (!fdev)
574                 return -ENOMEM;
575
576         binfo->feature_dev = fdev;
577         binfo->feature_num = 0;
578         binfo->ioaddr = ioaddr;
579         INIT_LIST_HEAD(&binfo->sub_features);
580
581         fdev->id = dfl_id_alloc(type, &fdev->dev);
582         if (fdev->id < 0)
583                 return fdev->id;
584
585         fdev->dev.parent = &binfo->cdev->region->dev;
586         fdev->dev.devt = dfl_get_devt(dfl_devs[type].devt_type, fdev->id);
587
588         return 0;
589 }
590
591 static void build_info_free(struct build_feature_devs_info *binfo)
592 {
593         struct dfl_feature_info *finfo, *p;
594
595         /*
596          * it is a valid id, free it. See comments in
597          * build_info_create_dev()
598          */
599         if (binfo->feature_dev && binfo->feature_dev->id >= 0) {
600                 dfl_id_free(feature_dev_id_type(binfo->feature_dev),
601                             binfo->feature_dev->id);
602
603                 list_for_each_entry_safe(finfo, p, &binfo->sub_features, node) {
604                         list_del(&finfo->node);
605                         kfree(finfo);
606                 }
607         }
608
609         platform_device_put(binfo->feature_dev);
610
611         devm_kfree(binfo->dev, binfo);
612 }
613
614 static inline u32 feature_size(void __iomem *start)
615 {
616         u64 v = readq(start + DFH);
617         u32 ofst = FIELD_GET(DFH_NEXT_HDR_OFST, v);
618         /* workaround for private features with invalid size, use 4K instead */
619         return ofst ? ofst : 4096;
620 }
621
622 static u64 feature_id(void __iomem *start)
623 {
624         u64 v = readq(start + DFH);
625         u16 id = FIELD_GET(DFH_ID, v);
626         u8 type = FIELD_GET(DFH_TYPE, v);
627
628         if (type == DFH_TYPE_FIU)
629                 return FEATURE_ID_FIU_HEADER;
630         else if (type == DFH_TYPE_PRIVATE)
631                 return id;
632         else if (type == DFH_TYPE_AFU)
633                 return FEATURE_ID_AFU;
634
635         WARN_ON(1);
636         return 0;
637 }
638
639 /*
640  * when create sub feature instances, for private features, it doesn't need
641  * to provide resource size and feature id as they could be read from DFH
642  * register. For afu sub feature, its register region only contains user
643  * defined registers, so never trust any information from it, just use the
644  * resource size information provided by its parent FIU.
645  */
646 static int
647 create_feature_instance(struct build_feature_devs_info *binfo,
648                         struct dfl_fpga_enum_dfl *dfl, resource_size_t ofst,
649                         resource_size_t size, u64 fid)
650 {
651         struct dfl_feature_info *finfo;
652
653         /* read feature size and id if inputs are invalid */
654         size = size ? size : feature_size(dfl->ioaddr + ofst);
655         fid = fid ? fid : feature_id(dfl->ioaddr + ofst);
656
657         if (dfl->len - ofst < size)
658                 return -EINVAL;
659
660         finfo = kzalloc(sizeof(*finfo), GFP_KERNEL);
661         if (!finfo)
662                 return -ENOMEM;
663
664         finfo->fid = fid;
665         finfo->mmio_res.start = dfl->start + ofst;
666         finfo->mmio_res.end = finfo->mmio_res.start + size - 1;
667         finfo->mmio_res.flags = IORESOURCE_MEM;
668         finfo->ioaddr = dfl->ioaddr + ofst;
669
670         list_add_tail(&finfo->node, &binfo->sub_features);
671         binfo->feature_num++;
672
673         return 0;
674 }
675
676 static int parse_feature_port_afu(struct build_feature_devs_info *binfo,
677                                   struct dfl_fpga_enum_dfl *dfl,
678                                   resource_size_t ofst)
679 {
680         u64 v = readq(binfo->ioaddr + PORT_HDR_CAP);
681         u32 size = FIELD_GET(PORT_CAP_MMIO_SIZE, v) << 10;
682
683         WARN_ON(!size);
684
685         return create_feature_instance(binfo, dfl, ofst, size, FEATURE_ID_AFU);
686 }
687
688 static int parse_feature_afu(struct build_feature_devs_info *binfo,
689                              struct dfl_fpga_enum_dfl *dfl,
690                              resource_size_t ofst)
691 {
692         if (!binfo->feature_dev) {
693                 dev_err(binfo->dev, "this AFU does not belong to any FIU.\n");
694                 return -EINVAL;
695         }
696
697         switch (feature_dev_id_type(binfo->feature_dev)) {
698         case PORT_ID:
699                 return parse_feature_port_afu(binfo, dfl, ofst);
700         default:
701                 dev_info(binfo->dev, "AFU belonging to FIU %s is not supported yet.\n",
702                          binfo->feature_dev->name);
703         }
704
705         return 0;
706 }
707
708 static int parse_feature_fiu(struct build_feature_devs_info *binfo,
709                              struct dfl_fpga_enum_dfl *dfl,
710                              resource_size_t ofst)
711 {
712         u32 id, offset;
713         u64 v;
714         int ret = 0;
715
716         v = readq(dfl->ioaddr + ofst + DFH);
717         id = FIELD_GET(DFH_ID, v);
718
719         /* create platform device for dfl feature dev */
720         ret = build_info_create_dev(binfo, dfh_id_to_type(id),
721                                     dfl->ioaddr + ofst);
722         if (ret)
723                 return ret;
724
725         ret = create_feature_instance(binfo, dfl, ofst, 0, 0);
726         if (ret)
727                 return ret;
728         /*
729          * find and parse FIU's child AFU via its NEXT_AFU register.
730          * please note that only Port has valid NEXT_AFU pointer per spec.
731          */
732         v = readq(dfl->ioaddr + ofst + NEXT_AFU);
733
734         offset = FIELD_GET(NEXT_AFU_NEXT_DFH_OFST, v);
735         if (offset)
736                 return parse_feature_afu(binfo, dfl, ofst + offset);
737
738         dev_dbg(binfo->dev, "No AFUs detected on FIU %d\n", id);
739
740         return ret;
741 }
742
743 static int parse_feature_private(struct build_feature_devs_info *binfo,
744                                  struct dfl_fpga_enum_dfl *dfl,
745                                  resource_size_t ofst)
746 {
747         if (!binfo->feature_dev) {
748                 dev_err(binfo->dev, "the private feature %llx does not belong to any AFU.\n",
749                         (unsigned long long)feature_id(dfl->ioaddr + ofst));
750                 return -EINVAL;
751         }
752
753         return create_feature_instance(binfo, dfl, ofst, 0, 0);
754 }
755
756 /**
757  * parse_feature - parse a feature on given device feature list
758  *
759  * @binfo: build feature devices information.
760  * @dfl: device feature list to parse
761  * @ofst: offset to feature header on this device feature list
762  */
763 static int parse_feature(struct build_feature_devs_info *binfo,
764                          struct dfl_fpga_enum_dfl *dfl, resource_size_t ofst)
765 {
766         u64 v;
767         u32 type;
768
769         v = readq(dfl->ioaddr + ofst + DFH);
770         type = FIELD_GET(DFH_TYPE, v);
771
772         switch (type) {
773         case DFH_TYPE_AFU:
774                 return parse_feature_afu(binfo, dfl, ofst);
775         case DFH_TYPE_PRIVATE:
776                 return parse_feature_private(binfo, dfl, ofst);
777         case DFH_TYPE_FIU:
778                 return parse_feature_fiu(binfo, dfl, ofst);
779         default:
780                 dev_info(binfo->dev,
781                          "Feature Type %x is not supported.\n", type);
782         }
783
784         return 0;
785 }
786
787 static int parse_feature_list(struct build_feature_devs_info *binfo,
788                               struct dfl_fpga_enum_dfl *dfl)
789 {
790         void __iomem *start = dfl->ioaddr;
791         void __iomem *end = dfl->ioaddr + dfl->len;
792         int ret = 0;
793         u32 ofst = 0;
794         u64 v;
795
796         /* walk through the device feature list via DFH's next DFH pointer. */
797         for (; start < end; start += ofst) {
798                 if (end - start < DFH_SIZE) {
799                         dev_err(binfo->dev, "The region is too small to contain a feature.\n");
800                         return -EINVAL;
801                 }
802
803                 ret = parse_feature(binfo, dfl, start - dfl->ioaddr);
804                 if (ret)
805                         return ret;
806
807                 v = readq(start + DFH);
808                 ofst = FIELD_GET(DFH_NEXT_HDR_OFST, v);
809
810                 /* stop parsing if EOL(End of List) is set or offset is 0 */
811                 if ((v & DFH_EOL) || !ofst)
812                         break;
813         }
814
815         /* commit current feature device when reach the end of list */
816         return build_info_commit_dev(binfo);
817 }
818
819 struct dfl_fpga_enum_info *dfl_fpga_enum_info_alloc(struct device *dev)
820 {
821         struct dfl_fpga_enum_info *info;
822
823         get_device(dev);
824
825         info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
826         if (!info) {
827                 put_device(dev);
828                 return NULL;
829         }
830
831         info->dev = dev;
832         INIT_LIST_HEAD(&info->dfls);
833
834         return info;
835 }
836 EXPORT_SYMBOL_GPL(dfl_fpga_enum_info_alloc);
837
838 void dfl_fpga_enum_info_free(struct dfl_fpga_enum_info *info)
839 {
840         struct dfl_fpga_enum_dfl *tmp, *dfl;
841         struct device *dev;
842
843         if (!info)
844                 return;
845
846         dev = info->dev;
847
848         /* remove all device feature lists in the list. */
849         list_for_each_entry_safe(dfl, tmp, &info->dfls, node) {
850                 list_del(&dfl->node);
851                 devm_kfree(dev, dfl);
852         }
853
854         devm_kfree(dev, info);
855         put_device(dev);
856 }
857 EXPORT_SYMBOL_GPL(dfl_fpga_enum_info_free);
858
859 /**
860  * dfl_fpga_enum_info_add_dfl - add info of a device feature list to enum info
861  *
862  * @info: ptr to dfl_fpga_enum_info
863  * @start: mmio resource address of the device feature list.
864  * @len: mmio resource length of the device feature list.
865  * @ioaddr: mapped mmio resource address of the device feature list.
866  *
867  * One FPGA device may have one or more Device Feature Lists (DFLs), use this
868  * function to add information of each DFL to common data structure for next
869  * step enumeration.
870  *
871  * Return: 0 on success, negative error code otherwise.
872  */
873 int dfl_fpga_enum_info_add_dfl(struct dfl_fpga_enum_info *info,
874                                resource_size_t start, resource_size_t len,
875                                void __iomem *ioaddr)
876 {
877         struct dfl_fpga_enum_dfl *dfl;
878
879         dfl = devm_kzalloc(info->dev, sizeof(*dfl), GFP_KERNEL);
880         if (!dfl)
881                 return -ENOMEM;
882
883         dfl->start = start;
884         dfl->len = len;
885         dfl->ioaddr = ioaddr;
886
887         list_add_tail(&dfl->node, &info->dfls);
888
889         return 0;
890 }
891 EXPORT_SYMBOL_GPL(dfl_fpga_enum_info_add_dfl);
892
893 static int remove_feature_dev(struct device *dev, void *data)
894 {
895         struct platform_device *pdev = to_platform_device(dev);
896         enum dfl_id_type type = feature_dev_id_type(pdev);
897         int id = pdev->id;
898
899         platform_device_unregister(pdev);
900
901         dfl_id_free(type, id);
902
903         return 0;
904 }
905
906 static void remove_feature_devs(struct dfl_fpga_cdev *cdev)
907 {
908         device_for_each_child(&cdev->region->dev, NULL, remove_feature_dev);
909 }
910
911 /**
912  * dfl_fpga_feature_devs_enumerate - enumerate feature devices
913  * @info: information for enumeration.
914  *
915  * This function creates a container device (base FPGA region), enumerates
916  * feature devices based on the enumeration info and creates platform devices
917  * under the container device.
918  *
919  * Return: dfl_fpga_cdev struct on success, -errno on failure
920  */
921 struct dfl_fpga_cdev *
922 dfl_fpga_feature_devs_enumerate(struct dfl_fpga_enum_info *info)
923 {
924         struct build_feature_devs_info *binfo;
925         struct dfl_fpga_enum_dfl *dfl;
926         struct dfl_fpga_cdev *cdev;
927         int ret = 0;
928
929         if (!info->dev)
930                 return ERR_PTR(-ENODEV);
931
932         cdev = devm_kzalloc(info->dev, sizeof(*cdev), GFP_KERNEL);
933         if (!cdev)
934                 return ERR_PTR(-ENOMEM);
935
936         cdev->region = devm_fpga_region_create(info->dev, NULL, NULL);
937         if (!cdev->region) {
938                 ret = -ENOMEM;
939                 goto free_cdev_exit;
940         }
941
942         cdev->parent = info->dev;
943         mutex_init(&cdev->lock);
944         INIT_LIST_HEAD(&cdev->port_dev_list);
945
946         ret = fpga_region_register(cdev->region);
947         if (ret)
948                 goto free_cdev_exit;
949
950         /* create and init build info for enumeration */
951         binfo = devm_kzalloc(info->dev, sizeof(*binfo), GFP_KERNEL);
952         if (!binfo) {
953                 ret = -ENOMEM;
954                 goto unregister_region_exit;
955         }
956
957         binfo->dev = info->dev;
958         binfo->cdev = cdev;
959
960         /*
961          * start enumeration for all feature devices based on Device Feature
962          * Lists.
963          */
964         list_for_each_entry(dfl, &info->dfls, node) {
965                 ret = parse_feature_list(binfo, dfl);
966                 if (ret) {
967                         remove_feature_devs(cdev);
968                         build_info_free(binfo);
969                         goto unregister_region_exit;
970                 }
971         }
972
973         build_info_free(binfo);
974
975         return cdev;
976
977 unregister_region_exit:
978         fpga_region_unregister(cdev->region);
979 free_cdev_exit:
980         devm_kfree(info->dev, cdev);
981         return ERR_PTR(ret);
982 }
983 EXPORT_SYMBOL_GPL(dfl_fpga_feature_devs_enumerate);
984
985 /**
986  * dfl_fpga_feature_devs_remove - remove all feature devices
987  * @cdev: fpga container device.
988  *
989  * Remove the container device and all feature devices under given container
990  * devices.
991  */
992 void dfl_fpga_feature_devs_remove(struct dfl_fpga_cdev *cdev)
993 {
994         struct dfl_feature_platform_data *pdata, *ptmp;
995
996         mutex_lock(&cdev->lock);
997         if (cdev->fme_dev)
998                 put_device(cdev->fme_dev);
999
1000         list_for_each_entry_safe(pdata, ptmp, &cdev->port_dev_list, node) {
1001                 struct platform_device *port_dev = pdata->dev;
1002
1003                 /* remove released ports */
1004                 if (!device_is_registered(&port_dev->dev)) {
1005                         dfl_id_free(feature_dev_id_type(port_dev),
1006                                     port_dev->id);
1007                         platform_device_put(port_dev);
1008                 }
1009
1010                 list_del(&pdata->node);
1011                 put_device(&port_dev->dev);
1012         }
1013         mutex_unlock(&cdev->lock);
1014
1015         remove_feature_devs(cdev);
1016
1017         fpga_region_unregister(cdev->region);
1018         devm_kfree(cdev->parent, cdev);
1019 }
1020 EXPORT_SYMBOL_GPL(dfl_fpga_feature_devs_remove);
1021
1022 /**
1023  * __dfl_fpga_cdev_find_port - find a port under given container device
1024  *
1025  * @cdev: container device
1026  * @data: data passed to match function
1027  * @match: match function used to find specific port from the port device list
1028  *
1029  * Find a port device under container device. This function needs to be
1030  * invoked with lock held.
1031  *
1032  * Return: pointer to port's platform device if successful, NULL otherwise.
1033  *
1034  * NOTE: you will need to drop the device reference with put_device() after use.
1035  */
1036 struct platform_device *
1037 __dfl_fpga_cdev_find_port(struct dfl_fpga_cdev *cdev, void *data,
1038                           int (*match)(struct platform_device *, void *))
1039 {
1040         struct dfl_feature_platform_data *pdata;
1041         struct platform_device *port_dev;
1042
1043         list_for_each_entry(pdata, &cdev->port_dev_list, node) {
1044                 port_dev = pdata->dev;
1045
1046                 if (match(port_dev, data) && get_device(&port_dev->dev))
1047                         return port_dev;
1048         }
1049
1050         return NULL;
1051 }
1052 EXPORT_SYMBOL_GPL(__dfl_fpga_cdev_find_port);
1053
1054 static int __init dfl_fpga_init(void)
1055 {
1056         int ret;
1057
1058         dfl_ids_init();
1059
1060         ret = dfl_chardev_init();
1061         if (ret)
1062                 dfl_ids_destroy();
1063
1064         return ret;
1065 }
1066
1067 /**
1068  * dfl_fpga_cdev_release_port - release a port platform device
1069  *
1070  * @cdev: parent container device.
1071  * @port_id: id of the port platform device.
1072  *
1073  * This function allows user to release a port platform device. This is a
1074  * mandatory step before turn a port from PF into VF for SRIOV support.
1075  *
1076  * Return: 0 on success, negative error code otherwise.
1077  */
1078 int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id)
1079 {
1080         struct platform_device *port_pdev;
1081         int ret = -ENODEV;
1082
1083         mutex_lock(&cdev->lock);
1084         port_pdev = __dfl_fpga_cdev_find_port(cdev, &port_id,
1085                                               dfl_fpga_check_port_id);
1086         if (!port_pdev)
1087                 goto unlock_exit;
1088
1089         if (!device_is_registered(&port_pdev->dev)) {
1090                 ret = -EBUSY;
1091                 goto put_dev_exit;
1092         }
1093
1094         ret = dfl_feature_dev_use_begin(dev_get_platdata(&port_pdev->dev));
1095         if (ret)
1096                 goto put_dev_exit;
1097
1098         platform_device_del(port_pdev);
1099         cdev->released_port_num++;
1100 put_dev_exit:
1101         put_device(&port_pdev->dev);
1102 unlock_exit:
1103         mutex_unlock(&cdev->lock);
1104         return ret;
1105 }
1106 EXPORT_SYMBOL_GPL(dfl_fpga_cdev_release_port);
1107
1108 /**
1109  * dfl_fpga_cdev_assign_port - assign a port platform device back
1110  *
1111  * @cdev: parent container device.
1112  * @port_id: id of the port platform device.
1113  *
1114  * This function allows user to assign a port platform device back. This is
1115  * a mandatory step after disable SRIOV support.
1116  *
1117  * Return: 0 on success, negative error code otherwise.
1118  */
1119 int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id)
1120 {
1121         struct platform_device *port_pdev;
1122         int ret = -ENODEV;
1123
1124         mutex_lock(&cdev->lock);
1125         port_pdev = __dfl_fpga_cdev_find_port(cdev, &port_id,
1126                                               dfl_fpga_check_port_id);
1127         if (!port_pdev)
1128                 goto unlock_exit;
1129
1130         if (device_is_registered(&port_pdev->dev)) {
1131                 ret = -EBUSY;
1132                 goto put_dev_exit;
1133         }
1134
1135         ret = platform_device_add(port_pdev);
1136         if (ret)
1137                 goto put_dev_exit;
1138
1139         dfl_feature_dev_use_end(dev_get_platdata(&port_pdev->dev));
1140         cdev->released_port_num--;
1141 put_dev_exit:
1142         put_device(&port_pdev->dev);
1143 unlock_exit:
1144         mutex_unlock(&cdev->lock);
1145         return ret;
1146 }
1147 EXPORT_SYMBOL_GPL(dfl_fpga_cdev_assign_port);
1148
1149 static void config_port_access_mode(struct device *fme_dev, int port_id,
1150                                     bool is_vf)
1151 {
1152         void __iomem *base;
1153         u64 v;
1154
1155         base = dfl_get_feature_ioaddr_by_id(fme_dev, FME_FEATURE_ID_HEADER);
1156
1157         v = readq(base + FME_HDR_PORT_OFST(port_id));
1158
1159         v &= ~FME_PORT_OFST_ACC_CTRL;
1160         v |= FIELD_PREP(FME_PORT_OFST_ACC_CTRL,
1161                         is_vf ? FME_PORT_OFST_ACC_VF : FME_PORT_OFST_ACC_PF);
1162
1163         writeq(v, base + FME_HDR_PORT_OFST(port_id));
1164 }
1165
1166 #define config_port_vf_mode(dev, id) config_port_access_mode(dev, id, true)
1167 #define config_port_pf_mode(dev, id) config_port_access_mode(dev, id, false)
1168
1169 /**
1170  * dfl_fpga_cdev_config_ports_pf - configure ports to PF access mode
1171  *
1172  * @cdev: parent container device.
1173  *
1174  * This function is needed in sriov configuration routine. It could be used to
1175  * configure the all released ports from VF access mode to PF.
1176  */
1177 void dfl_fpga_cdev_config_ports_pf(struct dfl_fpga_cdev *cdev)
1178 {
1179         struct dfl_feature_platform_data *pdata;
1180
1181         mutex_lock(&cdev->lock);
1182         list_for_each_entry(pdata, &cdev->port_dev_list, node) {
1183                 if (device_is_registered(&pdata->dev->dev))
1184                         continue;
1185
1186                 config_port_pf_mode(cdev->fme_dev, pdata->id);
1187         }
1188         mutex_unlock(&cdev->lock);
1189 }
1190 EXPORT_SYMBOL_GPL(dfl_fpga_cdev_config_ports_pf);
1191
1192 /**
1193  * dfl_fpga_cdev_config_ports_vf - configure ports to VF access mode
1194  *
1195  * @cdev: parent container device.
1196  * @num_vfs: VF device number.
1197  *
1198  * This function is needed in sriov configuration routine. It could be used to
1199  * configure the released ports from PF access mode to VF.
1200  *
1201  * Return: 0 on success, negative error code otherwise.
1202  */
1203 int dfl_fpga_cdev_config_ports_vf(struct dfl_fpga_cdev *cdev, int num_vfs)
1204 {
1205         struct dfl_feature_platform_data *pdata;
1206         int ret = 0;
1207
1208         mutex_lock(&cdev->lock);
1209         /*
1210          * can't turn multiple ports into 1 VF device, only 1 port for 1 VF
1211          * device, so if released port number doesn't match VF device number,
1212          * then reject the request with -EINVAL error code.
1213          */
1214         if (cdev->released_port_num != num_vfs) {
1215                 ret = -EINVAL;
1216                 goto done;
1217         }
1218
1219         list_for_each_entry(pdata, &cdev->port_dev_list, node) {
1220                 if (device_is_registered(&pdata->dev->dev))
1221                         continue;
1222
1223                 config_port_vf_mode(cdev->fme_dev, pdata->id);
1224         }
1225 done:
1226         mutex_unlock(&cdev->lock);
1227         return ret;
1228 }
1229 EXPORT_SYMBOL_GPL(dfl_fpga_cdev_config_ports_vf);
1230
1231 static void __exit dfl_fpga_exit(void)
1232 {
1233         dfl_chardev_uinit();
1234         dfl_ids_destroy();
1235 }
1236
1237 module_init(dfl_fpga_init);
1238 module_exit(dfl_fpga_exit);
1239
1240 MODULE_DESCRIPTION("FPGA Device Feature List (DFL) Support");
1241 MODULE_AUTHOR("Intel Corporation");
1242 MODULE_LICENSE("GPL v2");