diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2012-10-29 13:09:55 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2012-10-31 09:17:07 -0400 |
commit | c7a1db457bfca045a0960f4eaaffd6539afbf8d7 (patch) | |
tree | b2d00356f82a46724428b4d1527272249bfd6778 | |
parent | b2113136a5701a7aaffee96c0423e7a620124328 (diff) |
usb: gadget: dummy_hcd: add setup / cleanup of multiple HW intances
This patch creates & adds multiple instances of the HCD and UDC. We have
a new module option "num" which says how many emulated UDCs + HCDs we
want. The default value is one and currently the maximum is one as well.
This will change soon.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r-- | drivers/usb/gadget/dummy_hcd.c | 97 |
1 files changed, 72 insertions, 25 deletions
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index dffcf34d18d1..70f70ea133dd 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c | |||
@@ -63,16 +63,20 @@ MODULE_LICENSE("GPL"); | |||
63 | struct dummy_hcd_module_parameters { | 63 | struct dummy_hcd_module_parameters { |
64 | bool is_super_speed; | 64 | bool is_super_speed; |
65 | bool is_high_speed; | 65 | bool is_high_speed; |
66 | unsigned int num; | ||
66 | }; | 67 | }; |
67 | 68 | ||
68 | static struct dummy_hcd_module_parameters mod_data = { | 69 | static struct dummy_hcd_module_parameters mod_data = { |
69 | .is_super_speed = false, | 70 | .is_super_speed = false, |
70 | .is_high_speed = true, | 71 | .is_high_speed = true, |
72 | .num = 1, | ||
71 | }; | 73 | }; |
72 | module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO); | 74 | module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO); |
73 | MODULE_PARM_DESC(is_super_speed, "true to simulate SuperSpeed connection"); | 75 | MODULE_PARM_DESC(is_super_speed, "true to simulate SuperSpeed connection"); |
74 | module_param_named(is_high_speed, mod_data.is_high_speed, bool, S_IRUGO); | 76 | module_param_named(is_high_speed, mod_data.is_high_speed, bool, S_IRUGO); |
75 | MODULE_PARM_DESC(is_high_speed, "true to simulate HighSpeed connection"); | 77 | MODULE_PARM_DESC(is_high_speed, "true to simulate HighSpeed connection"); |
78 | module_param_named(num, mod_data.num, uint, S_IRUGO); | ||
79 | MODULE_PARM_DESC(num, "number of emulated controllers"); | ||
76 | /*-------------------------------------------------------------------------*/ | 80 | /*-------------------------------------------------------------------------*/ |
77 | 81 | ||
78 | /* gadget side driver data structres */ | 82 | /* gadget side driver data structres */ |
@@ -2634,6 +2638,7 @@ static struct platform_device *the_hcd_pdev[MAX_NUM_UDC]; | |||
2634 | static int __init init(void) | 2638 | static int __init init(void) |
2635 | { | 2639 | { |
2636 | int retval = -ENOMEM; | 2640 | int retval = -ENOMEM; |
2641 | int i; | ||
2637 | 2642 | ||
2638 | if (usb_disabled()) | 2643 | if (usb_disabled()) |
2639 | return -ENODEV; | 2644 | return -ENODEV; |
@@ -2641,12 +2646,29 @@ static int __init init(void) | |||
2641 | if (!mod_data.is_high_speed && mod_data.is_super_speed) | 2646 | if (!mod_data.is_high_speed && mod_data.is_super_speed) |
2642 | return -EINVAL; | 2647 | return -EINVAL; |
2643 | 2648 | ||
2644 | the_hcd_pdev[0] = platform_device_alloc(driver_name, 0); | 2649 | if (mod_data.num < 1 || mod_data.num > MAX_NUM_UDC) { |
2645 | if (!the_hcd_pdev[0]) | 2650 | pr_err("Number of emulated UDC must be in range of 1…%d\n", |
2646 | return retval; | 2651 | MAX_NUM_UDC); |
2647 | the_udc_pdev[0] = platform_device_alloc(gadget_name, 0); | 2652 | return -EINVAL; |
2648 | if (!the_udc_pdev[0]) | 2653 | } |
2649 | goto err_alloc_udc; | 2654 | for (i = 0; i < mod_data.num; i++) { |
2655 | the_hcd_pdev[i] = platform_device_alloc(driver_name, i); | ||
2656 | if (!the_hcd_pdev[i]) { | ||
2657 | i--; | ||
2658 | while (i >= 0) | ||
2659 | platform_device_put(the_hcd_pdev[i--]); | ||
2660 | return retval; | ||
2661 | } | ||
2662 | } | ||
2663 | for (i = 0; i < mod_data.num; i++) { | ||
2664 | the_udc_pdev[i] = platform_device_alloc(gadget_name, i); | ||
2665 | if (!the_udc_pdev[i]) { | ||
2666 | i--; | ||
2667 | while (i >= 0) | ||
2668 | platform_device_put(the_udc_pdev[i--]); | ||
2669 | goto err_alloc_udc; | ||
2670 | } | ||
2671 | } | ||
2650 | 2672 | ||
2651 | retval = platform_driver_register(&dummy_hcd_driver); | 2673 | retval = platform_driver_register(&dummy_hcd_driver); |
2652 | if (retval < 0) | 2674 | if (retval < 0) |
@@ -2655,9 +2677,15 @@ static int __init init(void) | |||
2655 | if (retval < 0) | 2677 | if (retval < 0) |
2656 | goto err_register_udc_driver; | 2678 | goto err_register_udc_driver; |
2657 | 2679 | ||
2658 | retval = platform_device_add(the_hcd_pdev[0]); | 2680 | for (i = 0; i < mod_data.num; i++) { |
2659 | if (retval < 0) | 2681 | retval = platform_device_add(the_hcd_pdev[i]); |
2660 | goto err_add_hcd; | 2682 | if (retval < 0) { |
2683 | i--; | ||
2684 | while (i >= 0) | ||
2685 | platform_device_del(the_hcd_pdev[i--]); | ||
2686 | goto err_add_hcd; | ||
2687 | } | ||
2688 | } | ||
2661 | if (!the_controller.hs_hcd || | 2689 | if (!the_controller.hs_hcd || |
2662 | (!the_controller.ss_hcd && mod_data.is_super_speed)) { | 2690 | (!the_controller.ss_hcd && mod_data.is_super_speed)) { |
2663 | /* | 2691 | /* |
@@ -2667,39 +2695,58 @@ static int __init init(void) | |||
2667 | retval = -EINVAL; | 2695 | retval = -EINVAL; |
2668 | goto err_add_udc; | 2696 | goto err_add_udc; |
2669 | } | 2697 | } |
2670 | retval = platform_device_add(the_udc_pdev[0]); | 2698 | |
2671 | if (retval < 0) | 2699 | |
2672 | goto err_add_udc; | 2700 | for (i = 0; i < mod_data.num; i++) { |
2673 | if (!platform_get_drvdata(the_udc_pdev[0])) { | 2701 | retval = platform_device_add(the_udc_pdev[i]); |
2674 | /* | 2702 | if (retval < 0) { |
2675 | * The udc was added successfully but its probe function failed | 2703 | i--; |
2676 | * for some reason. | 2704 | while (i >= 0) |
2677 | */ | 2705 | platform_device_del(the_udc_pdev[i]); |
2678 | retval = -EINVAL; | 2706 | goto err_add_udc; |
2679 | goto err_probe_udc; | 2707 | } |
2708 | } | ||
2709 | |||
2710 | for (i = 0; i < mod_data.num; i++) { | ||
2711 | if (!platform_get_drvdata(the_udc_pdev[i])) { | ||
2712 | /* | ||
2713 | * The udc was added successfully but its probe | ||
2714 | * function failed for some reason. | ||
2715 | */ | ||
2716 | retval = -EINVAL; | ||
2717 | goto err_probe_udc; | ||
2718 | } | ||
2680 | } | 2719 | } |
2681 | return retval; | 2720 | return retval; |
2682 | 2721 | ||
2683 | err_probe_udc: | 2722 | err_probe_udc: |
2684 | platform_device_del(the_udc_pdev[0]); | 2723 | for (i = 0; i < mod_data.num; i++) |
2724 | platform_device_del(the_udc_pdev[i]); | ||
2685 | err_add_udc: | 2725 | err_add_udc: |
2686 | platform_device_del(the_hcd_pdev[0]); | 2726 | for (i = 0; i < mod_data.num; i++) |
2727 | platform_device_del(the_hcd_pdev[i]); | ||
2687 | err_add_hcd: | 2728 | err_add_hcd: |
2688 | platform_driver_unregister(&dummy_udc_driver); | 2729 | platform_driver_unregister(&dummy_udc_driver); |
2689 | err_register_udc_driver: | 2730 | err_register_udc_driver: |
2690 | platform_driver_unregister(&dummy_hcd_driver); | 2731 | platform_driver_unregister(&dummy_hcd_driver); |
2691 | err_register_hcd_driver: | 2732 | err_register_hcd_driver: |
2692 | platform_device_put(the_udc_pdev[0]); | 2733 | for (i = 0; i < mod_data.num; i++) |
2734 | platform_device_put(the_udc_pdev[i]); | ||
2693 | err_alloc_udc: | 2735 | err_alloc_udc: |
2694 | platform_device_put(the_hcd_pdev[0]); | 2736 | for (i = 0; i < mod_data.num; i++) |
2737 | platform_device_put(the_hcd_pdev[i]); | ||
2695 | return retval; | 2738 | return retval; |
2696 | } | 2739 | } |
2697 | module_init(init); | 2740 | module_init(init); |
2698 | 2741 | ||
2699 | static void __exit cleanup(void) | 2742 | static void __exit cleanup(void) |
2700 | { | 2743 | { |
2701 | platform_device_unregister(the_udc_pdev[0]); | 2744 | int i; |
2702 | platform_device_unregister(the_hcd_pdev[0]); | 2745 | |
2746 | for (i = 0; i < mod_data.num; i++) { | ||
2747 | platform_device_unregister(the_udc_pdev[i]); | ||
2748 | platform_device_unregister(the_hcd_pdev[i]); | ||
2749 | } | ||
2703 | platform_driver_unregister(&dummy_udc_driver); | 2750 | platform_driver_unregister(&dummy_udc_driver); |
2704 | platform_driver_unregister(&dummy_hcd_driver); | 2751 | platform_driver_unregister(&dummy_hcd_driver); |
2705 | } | 2752 | } |