aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2012-10-29 13:09:55 -0400
committerFelipe Balbi <balbi@ti.com>2012-10-31 09:17:07 -0400
commitc7a1db457bfca045a0960f4eaaffd6539afbf8d7 (patch)
treeb2d00356f82a46724428b4d1527272249bfd6778
parentb2113136a5701a7aaffee96c0423e7a620124328 (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.c97
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");
63struct dummy_hcd_module_parameters { 63struct 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
68static struct dummy_hcd_module_parameters mod_data = { 69static 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};
72module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO); 74module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO);
73MODULE_PARM_DESC(is_super_speed, "true to simulate SuperSpeed connection"); 75MODULE_PARM_DESC(is_super_speed, "true to simulate SuperSpeed connection");
74module_param_named(is_high_speed, mod_data.is_high_speed, bool, S_IRUGO); 76module_param_named(is_high_speed, mod_data.is_high_speed, bool, S_IRUGO);
75MODULE_PARM_DESC(is_high_speed, "true to simulate HighSpeed connection"); 77MODULE_PARM_DESC(is_high_speed, "true to simulate HighSpeed connection");
78module_param_named(num, mod_data.num, uint, S_IRUGO);
79MODULE_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];
2634static int __init init(void) 2638static 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
2683err_probe_udc: 2722err_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]);
2685err_add_udc: 2725err_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]);
2687err_add_hcd: 2728err_add_hcd:
2688 platform_driver_unregister(&dummy_udc_driver); 2729 platform_driver_unregister(&dummy_udc_driver);
2689err_register_udc_driver: 2730err_register_udc_driver:
2690 platform_driver_unregister(&dummy_hcd_driver); 2731 platform_driver_unregister(&dummy_hcd_driver);
2691err_register_hcd_driver: 2732err_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]);
2693err_alloc_udc: 2735err_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}
2697module_init(init); 2740module_init(init);
2698 2741
2699static void __exit cleanup(void) 2742static 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}