[PATCH 109/115] usb: renesas_usbhs: support multi driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Kuninori Morimoto <kuninori.morimoto.gx@xxxxxxxxxxx>

Some SuperH/board has multi USBHS on it.
This patch supports multi register for renesas_usbhs

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@xxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>
---
 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 cc3ad63..ba79dbf 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -44,6 +44,7 @@ struct usbhsg_uep {
 struct usbhsg_gpriv {
 	struct usb_gadget	 gadget;
 	struct usbhs_mod	 mod;
+	struct list_head	 link;
 
 	struct usbhsg_uep	*uep;
 	int			 uep_size;
@@ -113,6 +114,16 @@ struct usbhsg_recip_handle {
 #define usbhsg_status_clr(gp, b) (gp->status &= ~b)
 #define usbhsg_status_has(gp, b) (gp->status &   b)
 
+/* controller */
+LIST_HEAD(the_controller_link);
+
+#define usbhsg_for_each_controller(gpriv)\
+	list_for_each_entry(gpriv, &the_controller_link, link)
+#define usbhsg_controller_register(gpriv)\
+	list_add_tail(&(gpriv)->link, &the_controller_link)
+#define usbhsg_controller_unregister(gpriv)\
+	list_del_init(&(gpriv)->link)
+
 /*
  *		queue push/pop
  */
@@ -732,11 +743,10 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status)
  *		linux usb function
  *
  */
-struct usbhsg_gpriv *the_controller;
 static int usbhsg_gadget_start(struct usb_gadget_driver *driver,
 			    int (*bind)(struct usb_gadget *))
 {
-	struct usbhsg_gpriv *gpriv = the_controller;
+	struct usbhsg_gpriv *gpriv;
 	struct usbhs_priv *priv;
 	struct device *dev;
 	int ret;
@@ -746,10 +756,17 @@ static int usbhsg_gadget_start(struct usb_gadget_driver *driver,
 	    !driver->setup	||
 	    driver->speed != USB_SPEED_HIGH)
 		return -EINVAL;
-	if (!gpriv)
-		return -ENODEV;
-	if (gpriv->driver)
-		return -EBUSY;
+
+	/*
+	 * find unused controller
+	 */
+	usbhsg_for_each_controller(gpriv) {
+		if (!gpriv->driver)
+			goto find_unused_controller;
+	}
+	return -ENODEV;
+
+find_unused_controller:
 
 	dev  = usbhsg_gpriv_to_dev(gpriv);
 	priv = usbhsg_gpriv_to_priv(gpriv);
@@ -786,18 +803,25 @@ add_fail:
 
 static int usbhsg_gadget_stop(struct usb_gadget_driver *driver)
 {
-	struct usbhsg_gpriv *gpriv = the_controller;
+	struct usbhsg_gpriv *gpriv;
 	struct usbhs_priv *priv;
-	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
-
-	if (!gpriv)
-		return -ENODEV;
+	struct device *dev;
 
 	if (!driver		||
-	    !driver->unbind	||
-	    driver != gpriv->driver)
+	    !driver->unbind)
 		return -EINVAL;
 
+	/*
+	 * find controller
+	 */
+	usbhsg_for_each_controller(gpriv) {
+		if (gpriv->driver == driver)
+			goto find_matching_controller;
+	}
+	return -ENODEV;
+
+find_matching_controller:
+
 	dev  = usbhsg_gpriv_to_dev(gpriv);
 	priv = usbhsg_gpriv_to_priv(gpriv);
 
@@ -919,7 +943,7 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 		}
 	}
 
-	the_controller = gpriv;
+	usbhsg_controller_register(gpriv);
 
 	ret = usb_add_gadget_udc(dev, &gpriv->gadget);
 	if (ret)
@@ -943,6 +967,9 @@ void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv)
 	struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
 
 	usb_del_gadget_udc(&gpriv->gadget);
+
+	usbhsg_controller_unregister(gpriv);
+
 	kfree(gpriv->uep);
 	kfree(gpriv);
 }
-- 
1.7.6

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux