diff options
author | Alan Tull <atull@kernel.org> | 2017-11-15 15:20:23 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-11-28 10:30:38 -0500 |
commit | 52a3a7ccce07e73323fc1bae9eb0b0b63375391c (patch) | |
tree | 6796ce652e7ad0c399ba3cd3cd1bb2f5034fa089 | |
parent | 3b49537f8084af15ccaac542eaf317e01c6869e6 (diff) |
fpga: region: add register/unregister functions
Another step in separating common code from device tree specific
code for FPGA regions.
* add FPGA region register/unregister functions.
* add the register/unregister functions to the header
* use devm_kzalloc to alloc the region.
* add a method for getting bridges to the region struct
* add priv to the region struct
* use region->info in of_fpga_region_get_bridges
Signed-off-by: Alan Tull <atull@kernel.org>
Acked-by: Moritz Fischer <mdf@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/fpga/fpga-region.c | 105 | ||||
-rw-r--r-- | include/linux/fpga/fpga-region.h | 7 |
2 files changed, 72 insertions, 40 deletions
diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 92ab21651aeb..76db81de2cc0 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c | |||
@@ -143,7 +143,6 @@ static struct fpga_manager *of_fpga_region_get_mgr(struct device_node *np) | |||
143 | /** | 143 | /** |
144 | * of_fpga_region_get_bridges - create a list of bridges | 144 | * of_fpga_region_get_bridges - create a list of bridges |
145 | * @region: FPGA region | 145 | * @region: FPGA region |
146 | * @info: FPGA image info | ||
147 | * | 146 | * |
148 | * Create a list of bridges including the parent bridge and the bridges | 147 | * Create a list of bridges including the parent bridge and the bridges |
149 | * specified by "fpga-bridges" property. Note that the | 148 | * specified by "fpga-bridges" property. Note that the |
@@ -156,11 +155,11 @@ static struct fpga_manager *of_fpga_region_get_mgr(struct device_node *np) | |||
156 | * Return 0 for success (even if there are no bridges specified) | 155 | * Return 0 for success (even if there are no bridges specified) |
157 | * or -EBUSY if any of the bridges are in use. | 156 | * or -EBUSY if any of the bridges are in use. |
158 | */ | 157 | */ |
159 | static int of_fpga_region_get_bridges(struct fpga_region *region, | 158 | static int of_fpga_region_get_bridges(struct fpga_region *region) |
160 | struct fpga_image_info *info) | ||
161 | { | 159 | { |
162 | struct device *dev = ®ion->dev; | 160 | struct device *dev = ®ion->dev; |
163 | struct device_node *region_np = dev->of_node; | 161 | struct device_node *region_np = dev->of_node; |
162 | struct fpga_image_info *info = region->info; | ||
164 | struct device_node *br, *np, *parent_br = NULL; | 163 | struct device_node *br, *np, *parent_br = NULL; |
165 | int i, ret; | 164 | int i, ret; |
166 | 165 | ||
@@ -192,7 +191,7 @@ static int of_fpga_region_get_bridges(struct fpga_region *region, | |||
192 | continue; | 191 | continue; |
193 | 192 | ||
194 | /* If node is a bridge, get it and add to list */ | 193 | /* If node is a bridge, get it and add to list */ |
195 | ret = of_fpga_bridge_get_to_list(br, region->info, | 194 | ret = of_fpga_bridge_get_to_list(br, info, |
196 | ®ion->bridge_list); | 195 | ®ion->bridge_list); |
197 | 196 | ||
198 | /* If any of the bridges are in use, give up */ | 197 | /* If any of the bridges are in use, give up */ |
@@ -229,10 +228,16 @@ int fpga_region_program_fpga(struct fpga_region *region) | |||
229 | goto err_put_region; | 228 | goto err_put_region; |
230 | } | 229 | } |
231 | 230 | ||
232 | ret = of_fpga_region_get_bridges(region, info); | 231 | /* |
233 | if (ret) { | 232 | * In some cases, we already have a list of bridges in the |
234 | dev_err(dev, "failed to get FPGA bridges\n"); | 233 | * fpga region struct. Or we don't have any bridges. |
235 | goto err_unlock_mgr; | 234 | */ |
235 | if (region->get_bridges) { | ||
236 | ret = region->get_bridges(region); | ||
237 | if (ret) { | ||
238 | dev_err(dev, "failed to get fpga region bridges\n"); | ||
239 | goto err_unlock_mgr; | ||
240 | } | ||
236 | } | 241 | } |
237 | 242 | ||
238 | ret = fpga_bridges_disable(®ion->bridge_list); | 243 | ret = fpga_bridges_disable(®ion->bridge_list); |
@@ -259,7 +264,8 @@ int fpga_region_program_fpga(struct fpga_region *region) | |||
259 | return 0; | 264 | return 0; |
260 | 265 | ||
261 | err_put_br: | 266 | err_put_br: |
262 | fpga_bridges_put(®ion->bridge_list); | 267 | if (region->get_bridges) |
268 | fpga_bridges_put(®ion->bridge_list); | ||
263 | err_unlock_mgr: | 269 | err_unlock_mgr: |
264 | fpga_mgr_unlock(region->mgr); | 270 | fpga_mgr_unlock(region->mgr); |
265 | err_put_region: | 271 | err_put_region: |
@@ -522,39 +528,20 @@ static struct notifier_block fpga_region_of_nb = { | |||
522 | .notifier_call = of_fpga_region_notify, | 528 | .notifier_call = of_fpga_region_notify, |
523 | }; | 529 | }; |
524 | 530 | ||
525 | static int of_fpga_region_probe(struct platform_device *pdev) | 531 | int fpga_region_register(struct device *dev, struct fpga_region *region) |
526 | { | 532 | { |
527 | struct device *dev = &pdev->dev; | ||
528 | struct device_node *np = dev->of_node; | ||
529 | struct fpga_region *region; | ||
530 | struct fpga_manager *mgr; | ||
531 | int id, ret = 0; | 533 | int id, ret = 0; |
532 | 534 | ||
533 | mgr = of_fpga_region_get_mgr(np); | ||
534 | if (IS_ERR(mgr)) | ||
535 | return -EPROBE_DEFER; | ||
536 | |||
537 | region = kzalloc(sizeof(*region), GFP_KERNEL); | ||
538 | if (!region) { | ||
539 | ret = -ENOMEM; | ||
540 | goto err_put_mgr; | ||
541 | } | ||
542 | |||
543 | region->mgr = mgr; | ||
544 | |||
545 | id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL); | 535 | id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL); |
546 | if (id < 0) { | 536 | if (id < 0) |
547 | ret = id; | 537 | return id; |
548 | goto err_kfree; | ||
549 | } | ||
550 | 538 | ||
551 | mutex_init(®ion->mutex); | 539 | mutex_init(®ion->mutex); |
552 | INIT_LIST_HEAD(®ion->bridge_list); | 540 | INIT_LIST_HEAD(®ion->bridge_list); |
553 | |||
554 | device_initialize(®ion->dev); | 541 | device_initialize(®ion->dev); |
555 | region->dev.class = fpga_region_class; | 542 | region->dev.class = fpga_region_class; |
556 | region->dev.parent = dev; | 543 | region->dev.parent = dev; |
557 | region->dev.of_node = np; | 544 | region->dev.of_node = dev->of_node; |
558 | region->dev.id = id; | 545 | region->dev.id = id; |
559 | dev_set_drvdata(dev, region); | 546 | dev_set_drvdata(dev, region); |
560 | 547 | ||
@@ -566,19 +553,58 @@ static int of_fpga_region_probe(struct platform_device *pdev) | |||
566 | if (ret) | 553 | if (ret) |
567 | goto err_remove; | 554 | goto err_remove; |
568 | 555 | ||
556 | return 0; | ||
557 | |||
558 | err_remove: | ||
559 | ida_simple_remove(&fpga_region_ida, id); | ||
560 | return ret; | ||
561 | } | ||
562 | EXPORT_SYMBOL_GPL(fpga_region_register); | ||
563 | |||
564 | int fpga_region_unregister(struct fpga_region *region) | ||
565 | { | ||
566 | device_unregister(®ion->dev); | ||
567 | |||
568 | return 0; | ||
569 | } | ||
570 | EXPORT_SYMBOL_GPL(fpga_region_unregister); | ||
571 | |||
572 | static int of_fpga_region_probe(struct platform_device *pdev) | ||
573 | { | ||
574 | struct device *dev = &pdev->dev; | ||
575 | struct device_node *np = dev->of_node; | ||
576 | struct fpga_region *region; | ||
577 | struct fpga_manager *mgr; | ||
578 | int ret; | ||
579 | |||
580 | /* Find the FPGA mgr specified by region or parent region. */ | ||
581 | mgr = of_fpga_region_get_mgr(np); | ||
582 | if (IS_ERR(mgr)) | ||
583 | return -EPROBE_DEFER; | ||
584 | |||
585 | region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL); | ||
586 | if (!region) { | ||
587 | ret = -ENOMEM; | ||
588 | goto eprobe_mgr_put; | ||
589 | } | ||
590 | |||
591 | region->mgr = mgr; | ||
592 | |||
593 | /* Specify how to get bridges for this type of region. */ | ||
594 | region->get_bridges = of_fpga_region_get_bridges; | ||
595 | |||
596 | ret = fpga_region_register(dev, region); | ||
597 | if (ret) | ||
598 | goto eprobe_mgr_put; | ||
599 | |||
569 | of_platform_populate(np, fpga_region_of_match, NULL, ®ion->dev); | 600 | of_platform_populate(np, fpga_region_of_match, NULL, ®ion->dev); |
570 | 601 | ||
571 | dev_info(dev, "FPGA Region probed\n"); | 602 | dev_info(dev, "FPGA Region probed\n"); |
572 | 603 | ||
573 | return 0; | 604 | return 0; |
574 | 605 | ||
575 | err_remove: | 606 | eprobe_mgr_put: |
576 | ida_simple_remove(&fpga_region_ida, id); | ||
577 | err_kfree: | ||
578 | kfree(region); | ||
579 | err_put_mgr: | ||
580 | fpga_mgr_put(mgr); | 607 | fpga_mgr_put(mgr); |
581 | |||
582 | return ret; | 608 | return ret; |
583 | } | 609 | } |
584 | 610 | ||
@@ -586,7 +612,7 @@ static int of_fpga_region_remove(struct platform_device *pdev) | |||
586 | { | 612 | { |
587 | struct fpga_region *region = platform_get_drvdata(pdev); | 613 | struct fpga_region *region = platform_get_drvdata(pdev); |
588 | 614 | ||
589 | device_unregister(®ion->dev); | 615 | fpga_region_unregister(region); |
590 | fpga_mgr_put(region->mgr); | 616 | fpga_mgr_put(region->mgr); |
591 | 617 | ||
592 | return 0; | 618 | return 0; |
@@ -606,7 +632,6 @@ static void fpga_region_dev_release(struct device *dev) | |||
606 | struct fpga_region *region = to_fpga_region(dev); | 632 | struct fpga_region *region = to_fpga_region(dev); |
607 | 633 | ||
608 | ida_simple_remove(&fpga_region_ida, region->dev.id); | 634 | ida_simple_remove(&fpga_region_ida, region->dev.id); |
609 | kfree(region); | ||
610 | } | 635 | } |
611 | 636 | ||
612 | /** | 637 | /** |
diff --git a/include/linux/fpga/fpga-region.h b/include/linux/fpga/fpga-region.h index 8a355171406b..8c8a3249f96c 100644 --- a/include/linux/fpga/fpga-region.h +++ b/include/linux/fpga/fpga-region.h | |||
@@ -12,6 +12,8 @@ | |||
12 | * @bridge_list: list of FPGA bridges specified in region | 12 | * @bridge_list: list of FPGA bridges specified in region |
13 | * @mgr: FPGA manager | 13 | * @mgr: FPGA manager |
14 | * @info: FPGA image info | 14 | * @info: FPGA image info |
15 | * @priv: private data | ||
16 | * @get_bridges: optional function to get bridges to a list | ||
15 | */ | 17 | */ |
16 | struct fpga_region { | 18 | struct fpga_region { |
17 | struct device dev; | 19 | struct device dev; |
@@ -19,10 +21,15 @@ struct fpga_region { | |||
19 | struct list_head bridge_list; | 21 | struct list_head bridge_list; |
20 | struct fpga_manager *mgr; | 22 | struct fpga_manager *mgr; |
21 | struct fpga_image_info *info; | 23 | struct fpga_image_info *info; |
24 | void *priv; | ||
25 | int (*get_bridges)(struct fpga_region *region); | ||
22 | }; | 26 | }; |
23 | 27 | ||
24 | #define to_fpga_region(d) container_of(d, struct fpga_region, dev) | 28 | #define to_fpga_region(d) container_of(d, struct fpga_region, dev) |
25 | 29 | ||
26 | int fpga_region_program_fpga(struct fpga_region *region); | 30 | int fpga_region_program_fpga(struct fpga_region *region); |
27 | 31 | ||
32 | int fpga_region_register(struct device *dev, struct fpga_region *region); | ||
33 | int fpga_region_unregister(struct fpga_region *region); | ||
34 | |||
28 | #endif /* _FPGA_REGION_H */ | 35 | #endif /* _FPGA_REGION_H */ |