diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2012-10-29 13:09:56 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2012-10-31 09:18:01 -0400 |
commit | b100a2f34dc160502bf7d3006cd8294303bbfacb (patch) | |
tree | 6e75fa7d7831c50a3c7886077cbb96389e41f13a /drivers/usb | |
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')
-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 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 | ||
245 | static 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 | ||
978 | static int dummy_udc_probe(struct platform_device *pdev) | 976 | static 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 | ||
2403 | static int dummy_setup(struct usb_hcd *hcd) | 2402 | static 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 | ||
2529 | static int dummy_hcd_probe(struct platform_device *pdev) | 2531 | static 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); |
2566 | put_usb2_hcd: | 2570 | put_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 |
2635 | static struct platform_device *the_udc_pdev[MAX_NUM_UDC]; | 2639 | static struct platform_device *the_udc_pdev[MAX_NUM_UDC]; |
2636 | static struct platform_device *the_hcd_pdev[MAX_NUM_UDC]; | 2640 | static 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); |
2730 | err_register_udc_driver: | 2750 | err_register_udc_driver: |
2731 | platform_driver_unregister(&dummy_hcd_driver); | 2751 | platform_driver_unregister(&dummy_hcd_driver); |
2732 | err_register_hcd_driver: | 2752 | err_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]); |
2735 | err_alloc_udc: | 2757 | err_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); |