diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2012-10-29 18:09:55 +0100 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2012-10-31 15:17:07 +0200 |
commit | c7a1db457bfca045a0960f4eaaffd6539afbf8d7 (patch) | |
tree | b2d00356f82a46724428b4d1527272249bfd6778 /drivers/usb/gadget | |
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>
Diffstat (limited to 'drivers/usb/gadget')
-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 dffcf34d18d..70f70ea133d 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -63,16 +63,20 @@ MODULE_LICENSE("GPL"); struct dummy_hcd_module_parameters { bool is_super_speed; bool is_high_speed; + unsigned int num; }; static struct dummy_hcd_module_parameters mod_data = { .is_super_speed = false, .is_high_speed = true, + .num = 1, }; module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO); MODULE_PARM_DESC(is_super_speed, "true to simulate SuperSpeed connection"); module_param_named(is_high_speed, mod_data.is_high_speed, bool, S_IRUGO); MODULE_PARM_DESC(is_high_speed, "true to simulate HighSpeed connection"); +module_param_named(num, mod_data.num, uint, S_IRUGO); +MODULE_PARM_DESC(num, "number of emulated controllers"); /*-------------------------------------------------------------------------*/ /* gadget side driver data structres */ @@ -2634,6 +2638,7 @@ static struct platform_device *the_hcd_pdev[MAX_NUM_UDC]; static int __init init(void) { int retval = -ENOMEM; + int i; if (usb_disabled()) return -ENODEV; @@ -2641,12 +2646,29 @@ static int __init init(void) if (!mod_data.is_high_speed && mod_data.is_super_speed) return -EINVAL; - the_hcd_pdev[0] = platform_device_alloc(driver_name, 0); - if (!the_hcd_pdev[0]) - return retval; - the_udc_pdev[0] = platform_device_alloc(gadget_name, 0); - if (!the_udc_pdev[0]) - goto err_alloc_udc; + if (mod_data.num < 1 || mod_data.num > MAX_NUM_UDC) { + pr_err("Number of emulated UDC must be in range of 1…%d\n", + MAX_NUM_UDC); + return -EINVAL; + } + for (i = 0; i < mod_data.num; i++) { + the_hcd_pdev[i] = platform_device_alloc(driver_name, i); + if (!the_hcd_pdev[i]) { + i--; + while (i >= 0) + platform_device_put(the_hcd_pdev[i--]); + return retval; + } + } + for (i = 0; i < mod_data.num; i++) { + the_udc_pdev[i] = platform_device_alloc(gadget_name, i); + if (!the_udc_pdev[i]) { + i--; + while (i >= 0) + platform_device_put(the_udc_pdev[i--]); + goto err_alloc_udc; + } + } retval = platform_driver_register(&dummy_hcd_driver); if (retval < 0) @@ -2655,9 +2677,15 @@ static int __init init(void) if (retval < 0) goto err_register_udc_driver; - retval = platform_device_add(the_hcd_pdev[0]); - if (retval < 0) - goto err_add_hcd; + for (i = 0; i < mod_data.num; i++) { + retval = platform_device_add(the_hcd_pdev[i]); + if (retval < 0) { + i--; + while (i >= 0) + platform_device_del(the_hcd_pdev[i--]); + goto err_add_hcd; + } + } if (!the_controller.hs_hcd || (!the_controller.ss_hcd && mod_data.is_super_speed)) { /* @@ -2667,39 +2695,58 @@ static int __init init(void) retval = -EINVAL; goto err_add_udc; } - retval = platform_device_add(the_udc_pdev[0]); - if (retval < 0) - goto err_add_udc; - if (!platform_get_drvdata(the_udc_pdev[0])) { - /* - * The udc was added successfully but its probe function failed - * for some reason. - */ - retval = -EINVAL; - goto err_probe_udc; + + + for (i = 0; i < mod_data.num; i++) { + retval = platform_device_add(the_udc_pdev[i]); + if (retval < 0) { + i--; + while (i >= 0) + platform_device_del(the_udc_pdev[i]); + goto err_add_udc; + } + } + + for (i = 0; i < mod_data.num; i++) { + if (!platform_get_drvdata(the_udc_pdev[i])) { + /* + * The udc was added successfully but its probe + * function failed for some reason. + */ + retval = -EINVAL; + goto err_probe_udc; + } } return retval; err_probe_udc: - platform_device_del(the_udc_pdev[0]); + for (i = 0; i < mod_data.num; i++) + platform_device_del(the_udc_pdev[i]); err_add_udc: - platform_device_del(the_hcd_pdev[0]); + for (i = 0; i < mod_data.num; i++) + platform_device_del(the_hcd_pdev[i]); err_add_hcd: platform_driver_unregister(&dummy_udc_driver); err_register_udc_driver: platform_driver_unregister(&dummy_hcd_driver); err_register_hcd_driver: - platform_device_put(the_udc_pdev[0]); + for (i = 0; i < mod_data.num; i++) + platform_device_put(the_udc_pdev[i]); err_alloc_udc: - platform_device_put(the_hcd_pdev[0]); + for (i = 0; i < mod_data.num; i++) + platform_device_put(the_hcd_pdev[i]); return retval; } module_init(init); static void __exit cleanup(void) { - platform_device_unregister(the_udc_pdev[0]); - platform_device_unregister(the_hcd_pdev[0]); + int i; + + for (i = 0; i < mod_data.num; i++) { + platform_device_unregister(the_udc_pdev[i]); + platform_device_unregister(the_hcd_pdev[i]); + } platform_driver_unregister(&dummy_udc_driver); platform_driver_unregister(&dummy_hcd_driver); } |