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>
This commit is contained in:
parent
b2113136a5
commit
c7a1db457b
@ -63,16 +63,20 @@ MODULE_LICENSE("GPL");
|
|||||||
struct dummy_hcd_module_parameters {
|
struct dummy_hcd_module_parameters {
|
||||||
bool is_super_speed;
|
bool is_super_speed;
|
||||||
bool is_high_speed;
|
bool is_high_speed;
|
||||||
|
unsigned int num;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dummy_hcd_module_parameters mod_data = {
|
static struct dummy_hcd_module_parameters mod_data = {
|
||||||
.is_super_speed = false,
|
.is_super_speed = false,
|
||||||
.is_high_speed = true,
|
.is_high_speed = true,
|
||||||
|
.num = 1,
|
||||||
};
|
};
|
||||||
module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO);
|
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_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_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_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 */
|
/* gadget side driver data structres */
|
||||||
@ -2634,6 +2638,7 @@ static struct platform_device *the_hcd_pdev[MAX_NUM_UDC];
|
|||||||
static int __init init(void)
|
static int __init init(void)
|
||||||
{
|
{
|
||||||
int retval = -ENOMEM;
|
int retval = -ENOMEM;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (usb_disabled())
|
if (usb_disabled())
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@ -2641,12 +2646,29 @@ static int __init init(void)
|
|||||||
if (!mod_data.is_high_speed && mod_data.is_super_speed)
|
if (!mod_data.is_high_speed && mod_data.is_super_speed)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
the_hcd_pdev[0] = platform_device_alloc(driver_name, 0);
|
if (mod_data.num < 1 || mod_data.num > MAX_NUM_UDC) {
|
||||||
if (!the_hcd_pdev[0])
|
pr_err("Number of emulated UDC must be in range of 1…%d\n",
|
||||||
return retval;
|
MAX_NUM_UDC);
|
||||||
the_udc_pdev[0] = platform_device_alloc(gadget_name, 0);
|
return -EINVAL;
|
||||||
if (!the_udc_pdev[0])
|
}
|
||||||
goto err_alloc_udc;
|
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);
|
retval = platform_driver_register(&dummy_hcd_driver);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
@ -2655,9 +2677,15 @@ static int __init init(void)
|
|||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
goto err_register_udc_driver;
|
goto err_register_udc_driver;
|
||||||
|
|
||||||
retval = platform_device_add(the_hcd_pdev[0]);
|
for (i = 0; i < mod_data.num; i++) {
|
||||||
if (retval < 0)
|
retval = platform_device_add(the_hcd_pdev[i]);
|
||||||
goto err_add_hcd;
|
if (retval < 0) {
|
||||||
|
i--;
|
||||||
|
while (i >= 0)
|
||||||
|
platform_device_del(the_hcd_pdev[i--]);
|
||||||
|
goto err_add_hcd;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!the_controller.hs_hcd ||
|
if (!the_controller.hs_hcd ||
|
||||||
(!the_controller.ss_hcd && mod_data.is_super_speed)) {
|
(!the_controller.ss_hcd && mod_data.is_super_speed)) {
|
||||||
/*
|
/*
|
||||||
@ -2667,39 +2695,58 @@ static int __init init(void)
|
|||||||
retval = -EINVAL;
|
retval = -EINVAL;
|
||||||
goto err_add_udc;
|
goto err_add_udc;
|
||||||
}
|
}
|
||||||
retval = platform_device_add(the_udc_pdev[0]);
|
|
||||||
if (retval < 0)
|
|
||||||
goto err_add_udc;
|
for (i = 0; i < mod_data.num; i++) {
|
||||||
if (!platform_get_drvdata(the_udc_pdev[0])) {
|
retval = platform_device_add(the_udc_pdev[i]);
|
||||||
/*
|
if (retval < 0) {
|
||||||
* The udc was added successfully but its probe function failed
|
i--;
|
||||||
* for some reason.
|
while (i >= 0)
|
||||||
*/
|
platform_device_del(the_udc_pdev[i]);
|
||||||
retval = -EINVAL;
|
goto err_add_udc;
|
||||||
goto err_probe_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;
|
return retval;
|
||||||
|
|
||||||
err_probe_udc:
|
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:
|
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:
|
err_add_hcd:
|
||||||
platform_driver_unregister(&dummy_udc_driver);
|
platform_driver_unregister(&dummy_udc_driver);
|
||||||
err_register_udc_driver:
|
err_register_udc_driver:
|
||||||
platform_driver_unregister(&dummy_hcd_driver);
|
platform_driver_unregister(&dummy_hcd_driver);
|
||||||
err_register_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:
|
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;
|
return retval;
|
||||||
}
|
}
|
||||||
module_init(init);
|
module_init(init);
|
||||||
|
|
||||||
static void __exit cleanup(void)
|
static void __exit cleanup(void)
|
||||||
{
|
{
|
||||||
platform_device_unregister(the_udc_pdev[0]);
|
int i;
|
||||||
platform_device_unregister(the_hcd_pdev[0]);
|
|
||||||
|
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_udc_driver);
|
||||||
platform_driver_unregister(&dummy_hcd_driver);
|
platform_driver_unregister(&dummy_hcd_driver);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user