aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2012-10-29 13:09:56 -0400
committerFelipe Balbi <balbi@ti.com>2012-10-31 09:18:01 -0400
commitb100a2f34dc160502bf7d3006cd8294303bbfacb (patch)
tree6e75fa7d7831c50a3c7886077cbb96389e41f13a /drivers
parentc7a1db457bfca045a0960f4eaaffd6539afbf8d7 (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')
-rw-r--r--drivers/usb/gadget/dummy_hcd.c71
1 files changed, 49 insertions, 22 deletions
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 70f70ea133dd..95d584dbed13 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)
242 return container_of(dev, struct dummy, gadget.dev); 242 return container_of(dev, struct dummy, gadget.dev);
243} 243}
244 244
245static struct dummy the_controller;
246
247/*-------------------------------------------------------------------------*/ 245/*-------------------------------------------------------------------------*/
248 246
249/* SLAVE/GADGET SIDE UTILITY ROUTINES */ 247/* SLAVE/GADGET SIDE UTILITY ROUTINES */
@@ -977,9 +975,10 @@ static void init_dummy_udc_hw(struct dummy *dum)
977 975
978static int dummy_udc_probe(struct platform_device *pdev) 976static int dummy_udc_probe(struct platform_device *pdev)
979{ 977{
980 struct dummy *dum = &the_controller; 978 struct dummy *dum;
981 int rc; 979 int rc;
982 980
981 dum = *((void **)dev_get_platdata(&pdev->dev));
983 dum->gadget.name = gadget_name; 982 dum->gadget.name = gadget_name;
984 dum->gadget.ops = &dummy_ops; 983 dum->gadget.ops = &dummy_ops;
985 dum->gadget.max_speed = USB_SPEED_SUPER; 984 dum->gadget.max_speed = USB_SPEED_SUPER;
@@ -2402,10 +2401,13 @@ static int dummy_h_get_frame(struct usb_hcd *hcd)
2402 2401
2403static int dummy_setup(struct usb_hcd *hcd) 2402static int dummy_setup(struct usb_hcd *hcd)
2404{ 2403{
2404 struct dummy *dum;
2405
2406 dum = *((void **)dev_get_platdata(hcd->self.controller));
2405 hcd->self.sg_tablesize = ~0; 2407 hcd->self.sg_tablesize = ~0;
2406 if (usb_hcd_is_primary_hcd(hcd)) { 2408 if (usb_hcd_is_primary_hcd(hcd)) {
2407 the_controller.hs_hcd = hcd_to_dummy_hcd(hcd); 2409 dum->hs_hcd = hcd_to_dummy_hcd(hcd);
2408 the_controller.hs_hcd->dum = &the_controller; 2410 dum->hs_hcd->dum = dum;
2409 /* 2411 /*
2410 * Mark the first roothub as being USB 2.0. 2412 * Mark the first roothub as being USB 2.0.
2411 * The USB 3.0 roothub will be registered later by 2413 * The USB 3.0 roothub will be registered later by
@@ -2414,8 +2416,8 @@ static int dummy_setup(struct usb_hcd *hcd)
2414 hcd->speed = HCD_USB2; 2416 hcd->speed = HCD_USB2;
2415 hcd->self.root_hub->speed = USB_SPEED_HIGH; 2417 hcd->self.root_hub->speed = USB_SPEED_HIGH;
2416 } else { 2418 } else {
2417 the_controller.ss_hcd = hcd_to_dummy_hcd(hcd); 2419 dum->ss_hcd = hcd_to_dummy_hcd(hcd);
2418 the_controller.ss_hcd->dum = &the_controller; 2420 dum->ss_hcd->dum = dum;
2419 hcd->speed = HCD_USB3; 2421 hcd->speed = HCD_USB3;
2420 hcd->self.root_hub->speed = USB_SPEED_SUPER; 2422 hcd->self.root_hub->speed = USB_SPEED_SUPER;
2421 } 2423 }
@@ -2528,11 +2530,13 @@ static struct hc_driver dummy_hcd = {
2528 2530
2529static int dummy_hcd_probe(struct platform_device *pdev) 2531static int dummy_hcd_probe(struct platform_device *pdev)
2530{ 2532{
2533 struct dummy *dum;
2531 struct usb_hcd *hs_hcd; 2534 struct usb_hcd *hs_hcd;
2532 struct usb_hcd *ss_hcd; 2535 struct usb_hcd *ss_hcd;
2533 int retval; 2536 int retval;
2534 2537
2535 dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); 2538 dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
2539 dum = *((void **)dev_get_platdata(&pdev->dev));
2536 2540
2537 if (!mod_data.is_super_speed) 2541 if (!mod_data.is_super_speed)
2538 dummy_hcd.flags = HCD_USB2; 2542 dummy_hcd.flags = HCD_USB2;
@@ -2565,7 +2569,7 @@ dealloc_usb2_hcd:
2565 usb_remove_hcd(hs_hcd); 2569 usb_remove_hcd(hs_hcd);
2566put_usb2_hcd: 2570put_usb2_hcd:
2567 usb_put_hcd(hs_hcd); 2571 usb_put_hcd(hs_hcd);
2568 the_controller.hs_hcd = the_controller.ss_hcd = NULL; 2572 dum->hs_hcd = dum->ss_hcd = NULL;
2569 return retval; 2573 return retval;
2570} 2574}
2571 2575
@@ -2583,8 +2587,8 @@ static int dummy_hcd_remove(struct platform_device *pdev)
2583 usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd)); 2587 usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
2584 usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd)); 2588 usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
2585 2589
2586 the_controller.hs_hcd = NULL; 2590 dum->hs_hcd = NULL;
2587 the_controller.ss_hcd = NULL; 2591 dum->ss_hcd = NULL;
2588 2592
2589 return 0; 2593 return 0;
2590} 2594}
@@ -2631,7 +2635,7 @@ static struct platform_driver dummy_hcd_driver = {
2631}; 2635};
2632 2636
2633/*-------------------------------------------------------------------------*/ 2637/*-------------------------------------------------------------------------*/
2634#define MAX_NUM_UDC 1 2638#define MAX_NUM_UDC 2
2635static struct platform_device *the_udc_pdev[MAX_NUM_UDC]; 2639static struct platform_device *the_udc_pdev[MAX_NUM_UDC];
2636static struct platform_device *the_hcd_pdev[MAX_NUM_UDC]; 2640static struct platform_device *the_hcd_pdev[MAX_NUM_UDC];
2637 2641
@@ -2639,6 +2643,7 @@ static int __init init(void)
2639{ 2643{
2640 int retval = -ENOMEM; 2644 int retval = -ENOMEM;
2641 int i; 2645 int i;
2646 struct dummy *dum[MAX_NUM_UDC];
2642 2647
2643 if (usb_disabled()) 2648 if (usb_disabled())
2644 return -ENODEV; 2649 return -ENODEV;
@@ -2651,6 +2656,7 @@ static int __init init(void)
2651 MAX_NUM_UDC); 2656 MAX_NUM_UDC);
2652 return -EINVAL; 2657 return -EINVAL;
2653 } 2658 }
2659
2654 for (i = 0; i < mod_data.num; i++) { 2660 for (i = 0; i < mod_data.num; i++) {
2655 the_hcd_pdev[i] = platform_device_alloc(driver_name, i); 2661 the_hcd_pdev[i] = platform_device_alloc(driver_name, i);
2656 if (!the_hcd_pdev[i]) { 2662 if (!the_hcd_pdev[i]) {
@@ -2669,10 +2675,23 @@ static int __init init(void)
2669 goto err_alloc_udc; 2675 goto err_alloc_udc;
2670 } 2676 }
2671 } 2677 }
2678 for (i = 0; i < mod_data.num; i++) {
2679 dum[i] = kzalloc(sizeof(struct dummy), GFP_KERNEL);
2680 if (!dum[i])
2681 goto err_add_pdata;
2682 retval = platform_device_add_data(the_hcd_pdev[i], &dum[i],
2683 sizeof(void *));
2684 if (retval)
2685 goto err_add_pdata;
2686 retval = platform_device_add_data(the_udc_pdev[i], &dum[i],
2687 sizeof(void *));
2688 if (retval)
2689 goto err_add_pdata;
2690 }
2672 2691
2673 retval = platform_driver_register(&dummy_hcd_driver); 2692 retval = platform_driver_register(&dummy_hcd_driver);
2674 if (retval < 0) 2693 if (retval < 0)
2675 goto err_register_hcd_driver; 2694 goto err_add_pdata;
2676 retval = platform_driver_register(&dummy_udc_driver); 2695 retval = platform_driver_register(&dummy_udc_driver);
2677 if (retval < 0) 2696 if (retval < 0)
2678 goto err_register_udc_driver; 2697 goto err_register_udc_driver;
@@ -2686,17 +2705,18 @@ static int __init init(void)
2686 goto err_add_hcd; 2705 goto err_add_hcd;
2687 } 2706 }
2688 } 2707 }
2689 if (!the_controller.hs_hcd || 2708 for (i = 0; i < mod_data.num; i++) {
2690 (!the_controller.ss_hcd && mod_data.is_super_speed)) { 2709 if (!dum[i]->hs_hcd ||
2691 /* 2710 (!dum[i]->ss_hcd && mod_data.is_super_speed)) {
2692 * The hcd was added successfully but its probe function failed 2711 /*
2693 * for some reason. 2712 * The hcd was added successfully but its probe
2694 */ 2713 * function failed for some reason.
2695 retval = -EINVAL; 2714 */
2696 goto err_add_udc; 2715 retval = -EINVAL;
2716 goto err_add_udc;
2717 }
2697 } 2718 }
2698 2719
2699
2700 for (i = 0; i < mod_data.num; i++) { 2720 for (i = 0; i < mod_data.num; i++) {
2701 retval = platform_device_add(the_udc_pdev[i]); 2721 retval = platform_device_add(the_udc_pdev[i]);
2702 if (retval < 0) { 2722 if (retval < 0) {
@@ -2729,7 +2749,9 @@ err_add_hcd:
2729 platform_driver_unregister(&dummy_udc_driver); 2749 platform_driver_unregister(&dummy_udc_driver);
2730err_register_udc_driver: 2750err_register_udc_driver:
2731 platform_driver_unregister(&dummy_hcd_driver); 2751 platform_driver_unregister(&dummy_hcd_driver);
2732err_register_hcd_driver: 2752err_add_pdata:
2753 for (i = 0; i < mod_data.num; i++)
2754 kfree(dum[i]);
2733 for (i = 0; i < mod_data.num; i++) 2755 for (i = 0; i < mod_data.num; i++)
2734 platform_device_put(the_udc_pdev[i]); 2756 platform_device_put(the_udc_pdev[i]);
2735err_alloc_udc: 2757err_alloc_udc:
@@ -2744,8 +2766,13 @@ static void __exit cleanup(void)
2744 int i; 2766 int i;
2745 2767
2746 for (i = 0; i < mod_data.num; i++) { 2768 for (i = 0; i < mod_data.num; i++) {
2769 struct dummy *dum;
2770
2771 dum = *((void **)dev_get_platdata(&the_udc_pdev[i]->dev));
2772
2747 platform_device_unregister(the_udc_pdev[i]); 2773 platform_device_unregister(the_udc_pdev[i]);
2748 platform_device_unregister(the_hcd_pdev[i]); 2774 platform_device_unregister(the_hcd_pdev[i]);
2775 kfree(dum);
2749 } 2776 }
2750 platform_driver_unregister(&dummy_udc_driver); 2777 platform_driver_unregister(&dummy_udc_driver);
2751 platform_driver_unregister(&dummy_hcd_driver); 2778 platform_driver_unregister(&dummy_hcd_driver);