diff options
-rw-r--r-- | drivers/usb/renesas_usbhs/mod_gadget.c | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index cc3ad634d4f..ba79dbf5adb 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c | |||
@@ -44,6 +44,7 @@ struct usbhsg_uep { | |||
44 | struct usbhsg_gpriv { | 44 | struct usbhsg_gpriv { |
45 | struct usb_gadget gadget; | 45 | struct usb_gadget gadget; |
46 | struct usbhs_mod mod; | 46 | struct usbhs_mod mod; |
47 | struct list_head link; | ||
47 | 48 | ||
48 | struct usbhsg_uep *uep; | 49 | struct usbhsg_uep *uep; |
49 | int uep_size; | 50 | int uep_size; |
@@ -113,6 +114,16 @@ struct usbhsg_recip_handle { | |||
113 | #define usbhsg_status_clr(gp, b) (gp->status &= ~b) | 114 | #define usbhsg_status_clr(gp, b) (gp->status &= ~b) |
114 | #define usbhsg_status_has(gp, b) (gp->status & b) | 115 | #define usbhsg_status_has(gp, b) (gp->status & b) |
115 | 116 | ||
117 | /* controller */ | ||
118 | LIST_HEAD(the_controller_link); | ||
119 | |||
120 | #define usbhsg_for_each_controller(gpriv)\ | ||
121 | list_for_each_entry(gpriv, &the_controller_link, link) | ||
122 | #define usbhsg_controller_register(gpriv)\ | ||
123 | list_add_tail(&(gpriv)->link, &the_controller_link) | ||
124 | #define usbhsg_controller_unregister(gpriv)\ | ||
125 | list_del_init(&(gpriv)->link) | ||
126 | |||
116 | /* | 127 | /* |
117 | * queue push/pop | 128 | * queue push/pop |
118 | */ | 129 | */ |
@@ -732,11 +743,10 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) | |||
732 | * linux usb function | 743 | * linux usb function |
733 | * | 744 | * |
734 | */ | 745 | */ |
735 | struct usbhsg_gpriv *the_controller; | ||
736 | static int usbhsg_gadget_start(struct usb_gadget_driver *driver, | 746 | static int usbhsg_gadget_start(struct usb_gadget_driver *driver, |
737 | int (*bind)(struct usb_gadget *)) | 747 | int (*bind)(struct usb_gadget *)) |
738 | { | 748 | { |
739 | struct usbhsg_gpriv *gpriv = the_controller; | 749 | struct usbhsg_gpriv *gpriv; |
740 | struct usbhs_priv *priv; | 750 | struct usbhs_priv *priv; |
741 | struct device *dev; | 751 | struct device *dev; |
742 | int ret; | 752 | int ret; |
@@ -746,10 +756,17 @@ static int usbhsg_gadget_start(struct usb_gadget_driver *driver, | |||
746 | !driver->setup || | 756 | !driver->setup || |
747 | driver->speed != USB_SPEED_HIGH) | 757 | driver->speed != USB_SPEED_HIGH) |
748 | return -EINVAL; | 758 | return -EINVAL; |
749 | if (!gpriv) | 759 | |
750 | return -ENODEV; | 760 | /* |
751 | if (gpriv->driver) | 761 | * find unused controller |
752 | return -EBUSY; | 762 | */ |
763 | usbhsg_for_each_controller(gpriv) { | ||
764 | if (!gpriv->driver) | ||
765 | goto find_unused_controller; | ||
766 | } | ||
767 | return -ENODEV; | ||
768 | |||
769 | find_unused_controller: | ||
753 | 770 | ||
754 | dev = usbhsg_gpriv_to_dev(gpriv); | 771 | dev = usbhsg_gpriv_to_dev(gpriv); |
755 | priv = usbhsg_gpriv_to_priv(gpriv); | 772 | priv = usbhsg_gpriv_to_priv(gpriv); |
@@ -786,18 +803,25 @@ add_fail: | |||
786 | 803 | ||
787 | static int usbhsg_gadget_stop(struct usb_gadget_driver *driver) | 804 | static int usbhsg_gadget_stop(struct usb_gadget_driver *driver) |
788 | { | 805 | { |
789 | struct usbhsg_gpriv *gpriv = the_controller; | 806 | struct usbhsg_gpriv *gpriv; |
790 | struct usbhs_priv *priv; | 807 | struct usbhs_priv *priv; |
791 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | 808 | struct device *dev; |
792 | |||
793 | if (!gpriv) | ||
794 | return -ENODEV; | ||
795 | 809 | ||
796 | if (!driver || | 810 | if (!driver || |
797 | !driver->unbind || | 811 | !driver->unbind) |
798 | driver != gpriv->driver) | ||
799 | return -EINVAL; | 812 | return -EINVAL; |
800 | 813 | ||
814 | /* | ||
815 | * find controller | ||
816 | */ | ||
817 | usbhsg_for_each_controller(gpriv) { | ||
818 | if (gpriv->driver == driver) | ||
819 | goto find_matching_controller; | ||
820 | } | ||
821 | return -ENODEV; | ||
822 | |||
823 | find_matching_controller: | ||
824 | |||
801 | dev = usbhsg_gpriv_to_dev(gpriv); | 825 | dev = usbhsg_gpriv_to_dev(gpriv); |
802 | priv = usbhsg_gpriv_to_priv(gpriv); | 826 | priv = usbhsg_gpriv_to_priv(gpriv); |
803 | 827 | ||
@@ -919,7 +943,7 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv) | |||
919 | } | 943 | } |
920 | } | 944 | } |
921 | 945 | ||
922 | the_controller = gpriv; | 946 | usbhsg_controller_register(gpriv); |
923 | 947 | ||
924 | ret = usb_add_gadget_udc(dev, &gpriv->gadget); | 948 | ret = usb_add_gadget_udc(dev, &gpriv->gadget); |
925 | if (ret) | 949 | if (ret) |
@@ -943,6 +967,9 @@ void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv) | |||
943 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | 967 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); |
944 | 968 | ||
945 | usb_del_gadget_udc(&gpriv->gadget); | 969 | usb_del_gadget_udc(&gpriv->gadget); |
970 | |||
971 | usbhsg_controller_unregister(gpriv); | ||
972 | |||
946 | kfree(gpriv->uep); | 973 | kfree(gpriv->uep); |
947 | kfree(gpriv); | 974 | kfree(gpriv); |
948 | } | 975 | } |