diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2012-10-29 18:09:56 +0100 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2012-10-31 15:18:01 +0200 |
commit | b100a2f34dc160502bf7d3006cd8294303bbfacb (patch) | |
tree | 6e75fa7d7831c50a3c7886077cbb96389e41f13a /drivers/usb/gadget/dummy_hcd.c | |
parent | c7a1db457bfca045a0960f4eaaffd6539afbf8d7 (diff) |
usb: gadget: dummy_hcd: remove global the_controller variable
The one thing that makes two UDCs+HCDs impossible is the global
the_controller variable. This patch changes this. After device
allocation we allocate the "the_controller" variable and pass it as
platform_data to the UDC and its companion.
We can have now multiple instances dummy hcd and therefore I change the
limit from one to two. I was able to test this with g_ncm adn g_zero:
|# lsusb
|Bus 001 Device 002: ID 0525:a4a0 Netchip Technology, Inc. Linux-USB "Gadget Zero"
|Bus 002 Device 002: ID 0525:a4a1 Netchip Technology, Inc. Linux-USB Ethernet Gadget
|Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
|Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
I was able to start testusb -a and ifconfig usb[01] up with no complains.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/dummy_hcd.c')
-rw-r--r-- | drivers/usb/gadget/dummy_hcd.c | 71 |
1 files changed, 49 insertions, 22 deletions
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 70f70ea133d..95d584dbed1 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -242,8 +242,6 @@ static inline struct dummy *gadget_dev_to_dummy(struct device *dev) return container_of(dev, struct dummy, gadget.dev); } -static struct dummy the_controller; - /*-------------------------------------------------------------------------*/ /* SLAVE/GADGET SIDE UTILITY ROUTINES */ @@ -977,9 +975,10 @@ static void init_dummy_udc_hw(struct dummy *dum) static int dummy_udc_probe(struct platform_device *pdev) { - struct dummy *dum = &the_controller; + struct dummy *dum; int rc; + dum = *((void **)dev_get_platdata(&pdev->dev)); dum->gadget.name = gadget_name; dum->gadget.ops = &dummy_ops; dum->gadget.max_speed = USB_SPEED_SUPER; @@ -2402,10 +2401,13 @@ static int dummy_h_get_frame(struct usb_hcd *hcd) static int dummy_setup(struct usb_hcd *hcd) { + struct dummy *dum; + + dum = *((void **)dev_get_platdata(hcd->self.controller)); hcd->self.sg_tablesize = ~0; if (usb_hcd_is_primary_hcd(hcd)) { - the_controller.hs_hcd = hcd_to_dummy_hcd(hcd); - the_controller.hs_hcd->dum = &the_controller; + dum->hs_hcd = hcd_to_dummy_hcd(hcd); + dum->hs_hcd->dum = dum; /* * Mark the first roothub as being USB 2.0. * The USB 3.0 roothub will be registered later by @@ -2414,8 +2416,8 @@ static int dummy_setup(struct usb_hcd *hcd) hcd->speed = HCD_USB2; hcd->self.root_hub->speed = USB_SPEED_HIGH; } else { - the_controller.ss_hcd = hcd_to_dummy_hcd(hcd); - the_controller.ss_hcd->dum = &the_controller; + dum->ss_hcd = hcd_to_dummy_hcd(hcd); + dum->ss_hcd->dum = dum; hcd->speed = HCD_USB3; hcd->self.root_hub->speed = USB_SPEED_SUPER; } @@ -2528,11 +2530,13 @@ static struct hc_driver dummy_hcd = { static int dummy_hcd_probe(struct platform_device *pdev) { + struct dummy *dum; struct usb_hcd *hs_hcd; struct usb_hcd *ss_hcd; int retval; dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); + dum = *((void **)dev_get_platdata(&pdev->dev)); if (!mod_data.is_super_speed) dummy_hcd.flags = HCD_USB2; @@ -2565,7 +2569,7 @@ dealloc_usb2_hcd: usb_remove_hcd(hs_hcd); put_usb2_hcd: usb_put_hcd(hs_hcd); - the_controller.hs_hcd = the_controller.ss_hcd = NULL; + dum->hs_hcd = dum->ss_hcd = NULL; return retval; } @@ -2583,8 +2587,8 @@ static int dummy_hcd_remove(struct platform_device *pdev) usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd)); usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd)); - the_controller.hs_hcd = NULL; - the_controller.ss_hcd = NULL; + dum->hs_hcd = NULL; + dum->ss_hcd = NULL; return 0; } @@ -2631,7 +2635,7 @@ static struct platform_driver dummy_hcd_driver = { }; /*-------------------------------------------------------------------------*/ -#define MAX_NUM_UDC 1 +#define MAX_NUM_UDC 2 static struct platform_device *the_udc_pdev[MAX_NUM_UDC]; static struct platform_device *the_hcd_pdev[MAX_NUM_UDC]; @@ -2639,6 +2643,7 @@ static int __init init(void) { int retval = -ENOMEM; int i; + struct dummy *dum[MAX_NUM_UDC]; if (usb_disabled()) return -ENODEV; @@ -2651,6 +2656,7 @@ static int __init init(void) 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]) { @@ -2669,10 +2675,23 @@ static int __init init(void) goto err_alloc_udc; } } + for (i = 0; i < mod_data.num; i++) { + dum[i] = kzalloc(sizeof(struct dummy), GFP_KERNEL); + if (!dum[i]) + goto err_add_pdata; + retval = platform_device_add_data(the_hcd_pdev[i], &dum[i], + sizeof(void *)); + if (retval) + goto err_add_pdata; + retval = platform_device_add_data(the_udc_pdev[i], &dum[i], + sizeof(void *)); + if (retval) + goto err_add_pdata; + } retval = platform_driver_register(&dummy_hcd_driver); if (retval < 0) - goto err_register_hcd_driver; + goto err_add_pdata; retval = platform_driver_register(&dummy_udc_driver); if (retval < 0) goto err_register_udc_driver; @@ -2686,17 +2705,18 @@ static int __init init(void) goto err_add_hcd; } } - if (!the_controller.hs_hcd || - (!the_controller.ss_hcd && mod_data.is_super_speed)) { - /* - * The hcd was added successfully but its probe function failed - * for some reason. - */ - retval = -EINVAL; - goto err_add_udc; + for (i = 0; i < mod_data.num; i++) { + if (!dum[i]->hs_hcd || + (!dum[i]->ss_hcd && mod_data.is_super_speed)) { + /* + * The hcd was added successfully but its probe + * function failed for some reason. + */ + retval = -EINVAL; + goto err_add_udc; + } } - for (i = 0; i < mod_data.num; i++) { retval = platform_device_add(the_udc_pdev[i]); if (retval < 0) { @@ -2729,7 +2749,9 @@ err_add_hcd: platform_driver_unregister(&dummy_udc_driver); err_register_udc_driver: platform_driver_unregister(&dummy_hcd_driver); -err_register_hcd_driver: +err_add_pdata: + for (i = 0; i < mod_data.num; i++) + kfree(dum[i]); for (i = 0; i < mod_data.num; i++) platform_device_put(the_udc_pdev[i]); err_alloc_udc: @@ -2744,8 +2766,13 @@ static void __exit cleanup(void) int i; for (i = 0; i < mod_data.num; i++) { + struct dummy *dum; + + dum = *((void **)dev_get_platdata(&the_udc_pdev[i]->dev)); + platform_device_unregister(the_udc_pdev[i]); platform_device_unregister(the_hcd_pdev[i]); + kfree(dum); } platform_driver_unregister(&dummy_udc_driver); platform_driver_unregister(&dummy_hcd_driver); |