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 | } |
