From c688419141ad6134d7973fcf182e3719e98d7491 Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Mon, 9 Jan 2012 13:14:56 +0100
Subject: [PATCH 01/53] usb: gadget: dummy_hcd: initialize max_streams early

While playing with uasp I noticed that it does not work with dummy_hcd.
The problem is that uasp requires a stream capable endpoint which it is
requesting at bind time like every other gadget. dummy_hcd however
initializes the max_stream value after connect once it knows if it runs
at SS or not.
I don't think that it is might be wrong to initialize the stream
capability even at HS speed. The gadget may not use this descriptor at
HS speed so it should not cause any damage.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/dummy_hcd.c | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index db815c2da7ed..5a21bf5c7650 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -800,17 +800,10 @@ static int dummy_set_selfpowered (struct usb_gadget *_gadget, int value)
 
 static void dummy_udc_udpate_ep0(struct dummy *dum)
 {
-	u32 i;
-
-	if (dum->gadget.speed == USB_SPEED_SUPER) {
-		for (i = 0; i < DUMMY_ENDPOINTS; i++)
-			dum->ep[i].ep.max_streams = 0x10;
+	if (dum->gadget.speed == USB_SPEED_SUPER)
 		dum->ep[0].ep.maxpacket = 9;
-	} else {
-		for (i = 0; i < DUMMY_ENDPOINTS; i++)
-			dum->ep[i].ep.max_streams = 0;
+	else
 		dum->ep[0].ep.maxpacket = 64;
-	}
 }
 
 static int dummy_pullup (struct usb_gadget *_gadget, int value)
@@ -954,6 +947,7 @@ static void init_dummy_udc_hw(struct dummy *dum)
 		ep->halted = ep->wedged = ep->already_seen =
 				ep->setup_stage = 0;
 		ep->ep.maxpacket = ~0;
+		ep->ep.max_streams = 16;
 		ep->last_io = jiffies;
 		ep->gadget = &dum->gadget;
 		ep->desc = NULL;

From a04ce20d9f5e9484ed3879e1290bd05933cbbe2a Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Mon, 9 Jan 2012 13:14:57 +0100
Subject: [PATCH 02/53] usb: gadget: dummy_hcd: move the transfer part into its
 own function

This patch moves the part of the code which does the bare transfer into
its function. It is a preparion for the implementation of sg support.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/dummy_hcd.c | 28 +++++++++++++++++++---------
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 5a21bf5c7650..61e893ac2545 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -1133,6 +1133,23 @@ static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 	return rc;
 }
 
+static int dummy_perform_transfer(struct urb *urb, struct dummy_request *req,
+		u32 len)
+{
+	void *ubuf, *rbuf;
+	int to_host;
+
+	to_host = usb_pipein(urb->pipe);
+	rbuf = req->req.buf + req->req.actual;
+	ubuf = urb->transfer_buffer + urb->actual_length;
+
+	if (to_host)
+		memcpy(ubuf, rbuf, len);
+	else
+		memcpy(rbuf, ubuf, len);
+	return len;
+}
+
 /* transfer up to a frame's worth; caller must own lock */
 static int
 transfer(struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit,
@@ -1164,8 +1181,6 @@ top:
 		if (unlikely (len == 0))
 			is_short = 1;
 		else {
-			char		*ubuf, *rbuf;
-
 			/* not enough bandwidth left? */
 			if (limit < ep->ep.maxpacket && limit < len)
 				break;
@@ -1180,13 +1195,8 @@ top:
 			}
 			is_short = (len % ep->ep.maxpacket) != 0;
 
-			/* else transfer packet(s) */
-			ubuf = urb->transfer_buffer + urb->actual_length;
-			rbuf = req->req.buf + req->req.actual;
-			if (to_host)
-				memcpy (ubuf, rbuf, len);
-			else
-				memcpy (rbuf, ubuf, len);
+			len = dummy_perform_transfer(urb, req, len);
+
 			ep->last_io = jiffies;
 
 			limit -= len;

From 14fce33a960afbcf91ef97135903092c33f6d076 Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Mon, 9 Jan 2012 19:30:50 +0100
Subject: [PATCH 03/53] usb: gadget: dummy_hcd: add sg support

This patch adds sg support to dummy_hcd. It seems that uas is not able
to work with a hcd which does not support sg only based transfers.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/dummy_hcd.c | 80 ++++++++++++++++++++++++++++------
 1 file changed, 67 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 61e893ac2545..4973778b7785 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -39,6 +39,7 @@
 #include <linux/usb.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/hcd.h>
+#include <linux/scatterlist.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -147,6 +148,8 @@ static const char *const ep_name [] = {
 struct urbp {
 	struct urb		*urb;
 	struct list_head	urbp_list;
+	struct sg_mapping_iter	miter;
+	u32			miter_started;
 };
 
 
@@ -1077,13 +1080,11 @@ static int dummy_urb_enqueue (
 	unsigned long	flags;
 	int		rc;
 
-	if (!urb->transfer_buffer && urb->transfer_buffer_length)
-		return -EINVAL;
-
 	urbp = kmalloc (sizeof *urbp, mem_flags);
 	if (!urbp)
 		return -ENOMEM;
 	urbp->urb = urb;
+	urbp->miter_started = 0;
 
 	dum_hcd = hcd_to_dummy_hcd(hcd);
 	spin_lock_irqsave(&dum_hcd->dum->lock, flags);
@@ -1137,17 +1138,66 @@ static int dummy_perform_transfer(struct urb *urb, struct dummy_request *req,
 		u32 len)
 {
 	void *ubuf, *rbuf;
+	struct urbp *urbp = urb->hcpriv;
 	int to_host;
+	struct sg_mapping_iter *miter = &urbp->miter;
+	u32 trans = 0;
+	u32 this_sg;
+	bool next_sg;
 
 	to_host = usb_pipein(urb->pipe);
 	rbuf = req->req.buf + req->req.actual;
-	ubuf = urb->transfer_buffer + urb->actual_length;
 
-	if (to_host)
-		memcpy(ubuf, rbuf, len);
-	else
-		memcpy(rbuf, ubuf, len);
-	return len;
+	if (!urb->num_sgs) {
+		ubuf = urb->transfer_buffer + urb->actual_length;
+		if (to_host)
+			memcpy(ubuf, rbuf, len);
+		else
+			memcpy(rbuf, ubuf, len);
+		return len;
+	}
+
+	if (!urbp->miter_started) {
+		u32 flags = SG_MITER_ATOMIC;
+
+		if (to_host)
+			flags |= SG_MITER_TO_SG;
+		else
+			flags |= SG_MITER_FROM_SG;
+
+		sg_miter_start(miter, urb->sg, urb->num_sgs, flags);
+		urbp->miter_started = 1;
+	}
+	next_sg = sg_miter_next(miter);
+	if (next_sg == false) {
+		WARN_ON_ONCE(1);
+		return -EINVAL;
+	}
+	do {
+		ubuf = miter->addr;
+		this_sg = min_t(u32, len, miter->length);
+		miter->consumed = this_sg;
+		trans += this_sg;
+
+		if (to_host)
+			memcpy(ubuf, rbuf, this_sg);
+		else
+			memcpy(rbuf, ubuf, this_sg);
+		len -= this_sg;
+
+		if (!len)
+			break;
+		next_sg = sg_miter_next(miter);
+		if (next_sg == false) {
+			WARN_ON_ONCE(1);
+			return -EINVAL;
+		}
+
+		rbuf += this_sg;
+	} while (1);
+
+	sg_miter_stop(miter);
+	return trans;
 }
 
 /* transfer up to a frame's worth; caller must own lock */
@@ -1198,10 +1248,13 @@ top:
 			len = dummy_perform_transfer(urb, req, len);
 
 			ep->last_io = jiffies;
-
-			limit -= len;
-			urb->actual_length += len;
-			req->req.actual += len;
+			if (len < 0) {
+				req->req.status = len;
+			} else {
+				limit -= len;
+				urb->actual_length += len;
+				req->req.actual += len;
+			}
 		}
 
 		/* short packets terminate, maybe with overflow/underflow.
@@ -2212,6 +2265,7 @@ static int dummy_h_get_frame (struct usb_hcd *hcd)
 
 static int dummy_setup(struct usb_hcd *hcd)
 {
+	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;

From d262127c330b852ce4b210a0b1b06e69d4d87704 Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Mon, 9 Jan 2012 13:14:59 +0100
Subject: [PATCH 04/53] usb: gadget: dummy_hcd: rename dummy_udc_udpate_ep0()
 to dummy_udc_update_ep0()

This renames a function so "update" is spelled properly.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/dummy_hcd.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 4973778b7785..a40dc6a4c9eb 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -801,7 +801,7 @@ static int dummy_set_selfpowered (struct usb_gadget *_gadget, int value)
 	return 0;
 }
 
-static void dummy_udc_udpate_ep0(struct dummy *dum)
+static void dummy_udc_update_ep0(struct dummy *dum)
 {
 	if (dum->gadget.speed == USB_SPEED_SUPER)
 		dum->ep[0].ep.maxpacket = 9;
@@ -825,7 +825,7 @@ static int dummy_pullup (struct usb_gadget *_gadget, int value)
 					dum->driver->max_speed);
 		else
 			dum->gadget.speed = USB_SPEED_FULL;
-		dummy_udc_udpate_ep0(dum);
+		dummy_udc_update_ep0(dum);
 
 		if (dum->gadget.speed < dum->driver->max_speed)
 			dev_dbg(udc_dev(dum), "This device can perform faster"

From d81f3e4f5792acab5929ef99aad6ca5e21a31a0e Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Mon, 9 Jan 2012 13:15:00 +0100
Subject: [PATCH 05/53] usb: gadget: dummy_hcd: make alloc/free streams static

There is no reason why dummy_alloc_streams() and dummy_free_streams()
are global. Make them static instead.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/dummy_hcd.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index a40dc6a4c9eb..626473238b3c 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -2286,7 +2286,7 @@ static int dummy_setup(struct usb_hcd *hcd)
 }
 
 /* Change a group of bulk endpoints to support multiple stream IDs */
-int dummy_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
+static int dummy_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
 	struct usb_host_endpoint **eps, unsigned int num_eps,
 	unsigned int num_streams, gfp_t mem_flags)
 {
@@ -2298,7 +2298,7 @@ int dummy_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
 }
 
 /* Reverts a group of bulk endpoints back to not using stream IDs. */
-int dummy_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
+static int dummy_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
 	struct usb_host_endpoint **eps, unsigned int num_eps,
 	gfp_t mem_flags)
 {

From 10800f2ca1a78e24cf92dc5e16a68a9b78f91bbe Mon Sep 17 00:00:00 2001
From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Wed, 4 Jan 2012 10:20:09 +0300
Subject: [PATCH 06/53] usb: gadget: mv_udc: remove unneeded NULL check

We've dereferenced req already, and we checked for bogus parameters at
the start of the function.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/mv_udc_core.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index f97e737d26f7..8dd398b99e2f 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -771,8 +771,7 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 		udc->ep0_state = DATA_STATE_XMIT;
 
 	/* irq handler advances the queue */
-	if (req != NULL)
-		list_add_tail(&req->queue, &ep->queue);
+	list_add_tail(&req->queue, &ep->queue);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 	return 0;

From 53069af3fa8ba2849cd4785160690873995d4f39 Mon Sep 17 00:00:00 2001
From: "Shimoda, Yoshihiro" <yoshihiro.shimoda.uh@renesas.com>
Date: Thu, 5 Jan 2012 15:37:18 +0900
Subject: [PATCH 07/53] usb: renesas_usbhs: add IRQ resource decoding for
 IRQF_SHARED

In case of the SH7757, the irq number of USB module and SUDMAC
are the same. So, we have to set the IRQF_SHARED in such a case.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/renesas_usbhs/common.c | 11 ++++++-----
 drivers/usb/renesas_usbhs/common.h |  1 +
 drivers/usb/renesas_usbhs/mod.c    |  2 +-
 3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index e9a5b1d2615e..a165490bae48 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -413,8 +413,7 @@ static int usbhs_probe(struct platform_device *pdev)
 	struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;
 	struct renesas_usbhs_driver_callback *dfunc;
 	struct usbhs_priv *priv;
-	struct resource *res;
-	unsigned int irq;
+	struct resource *res, *irq_res;
 	int ret;
 
 	/* check platform information */
@@ -426,8 +425,8 @@ static int usbhs_probe(struct platform_device *pdev)
 
 	/* platform data */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	irq = platform_get_irq(pdev, 0);
-	if (!res || (int)irq <= 0) {
+	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res || !irq_res) {
 		dev_err(&pdev->dev, "Not enough Renesas USB platform resources.\n");
 		return -ENODEV;
 	}
@@ -476,7 +475,9 @@ static int usbhs_probe(struct platform_device *pdev)
 	/*
 	 * priv settings
 	 */
-	priv->irq	= irq;
+	priv->irq	= irq_res->start;
+	if (irq_res->flags & IORESOURCE_IRQ_SHAREABLE)
+		priv->irqflags = IRQF_SHARED;
 	priv->pdev	= pdev;
 	INIT_DELAYED_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug);
 	spin_lock_init(usbhs_priv_to_lock(priv));
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h
index d79b3e27db95..3f3ccd358753 100644
--- a/drivers/usb/renesas_usbhs/common.h
+++ b/drivers/usb/renesas_usbhs/common.h
@@ -242,6 +242,7 @@ struct usbhs_priv {
 
 	void __iomem *base;
 	unsigned int irq;
+	unsigned long irqflags;
 
 	struct renesas_usbhs_platform_callback	pfunc;
 	struct renesas_usbhs_driver_param	dparam;
diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c
index 1b97fb12694b..0871e816df45 100644
--- a/drivers/usb/renesas_usbhs/mod.c
+++ b/drivers/usb/renesas_usbhs/mod.c
@@ -152,7 +152,7 @@ int usbhs_mod_probe(struct usbhs_priv *priv)
 
 	/* irq settings */
 	ret = request_irq(priv->irq, usbhs_interrupt,
-			  0, dev_name(dev), priv);
+			  priv->irqflags, dev_name(dev), priv);
 	if (ret) {
 		dev_err(dev, "irq request err\n");
 		goto mod_init_gadget_err;

From 5ea4399457f730b4614d0632ceefd3e8f53fb1e6 Mon Sep 17 00:00:00 2001
From: "Shimoda, Yoshihiro" <yoshihiro.shimoda.uh@renesas.com>
Date: Thu, 5 Jan 2012 15:37:22 +0900
Subject: [PATCH 08/53] usb: renesas_usbhs: add support for SUDMAC

The SUDMAC uses 8-bit width only. So, when the driver uses SUDMAC,
we have to clear the MBW_32.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/renesas_usbhs/fifo.c  | 6 +++++-
 include/linux/usb/renesas_usbhs.h | 1 +
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index 72339bd6fcab..03a9cc529c82 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -23,6 +23,7 @@
 #define usbhsf_get_cfifo(p)	(&((p)->fifo_info.cfifo))
 #define usbhsf_get_d0fifo(p)	(&((p)->fifo_info.d0fifo))
 #define usbhsf_get_d1fifo(p)	(&((p)->fifo_info.d1fifo))
+#define usbhsf_is_cfifo(p, f)	(usbhsf_get_cfifo(p) == f)
 
 #define usbhsf_fifo_is_busy(f)	((f)->pipe) /* see usbhs_pipe_select_fifo */
 
@@ -305,7 +306,10 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe,
 	}
 
 	/* "base" will be used below  */
-	usbhs_write(priv, fifo->sel, base | MBW_32);
+	if (usbhs_get_dparam(priv, has_sudmac) && !usbhsf_is_cfifo(priv, fifo))
+		usbhs_write(priv, fifo->sel, base);
+	else
+		usbhs_write(priv, fifo->sel, base | MBW_32);
 
 	/* check ISEL and CURPIPE value */
 	while (timeout--) {
diff --git a/include/linux/usb/renesas_usbhs.h b/include/linux/usb/renesas_usbhs.h
index 0d3f98879256..547e59cc00ea 100644
--- a/include/linux/usb/renesas_usbhs.h
+++ b/include/linux/usb/renesas_usbhs.h
@@ -149,6 +149,7 @@ struct renesas_usbhs_driver_param {
 	 * option:
 	 */
 	u32 has_otg:1; /* for controlling PWEN/EXTLP */
+	u32 has_sudmac:1; /* for SUDMAC */
 };
 
 /*

From 2d4172c938745cfa51c4a91406efb584549c1024 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Heiko=20St=C3=BCbner?= <heiko@sntech.de>
Date: Sun, 8 Jan 2012 21:57:55 +0100
Subject: [PATCH 09/53] usb: s3c-hsudc: Use helper functions instead of generic
 container_of

The helper functions were definied but never used until now.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/s3c-hsudc.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index df8661d266cb..41b3a583c1a7 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -759,7 +759,7 @@ static int s3c_hsudc_ep_enable(struct usb_ep *_ep,
 	unsigned long flags;
 	u32 ecr = 0;
 
-	hsep = container_of(_ep, struct s3c_hsudc_ep, ep);
+	hsep = our_ep(_ep);
 	if (!_ep || !desc || hsep->desc || _ep->name == ep0name
 		|| desc->bDescriptorType != USB_DT_ENDPOINT
 		|| hsep->bEndpointAddress != desc->bEndpointAddress
@@ -853,7 +853,7 @@ static void s3c_hsudc_free_request(struct usb_ep *ep, struct usb_request *_req)
 {
 	struct s3c_hsudc_req *hsreq;
 
-	hsreq = container_of(_req, struct s3c_hsudc_req, req);
+	hsreq = our_req(_req);
 	WARN_ON(!list_empty(&hsreq->queue));
 	kfree(hsreq);
 }
@@ -876,12 +876,12 @@ static int s3c_hsudc_queue(struct usb_ep *_ep, struct usb_request *_req,
 	u32 offset;
 	u32 csr;
 
-	hsreq = container_of(_req, struct s3c_hsudc_req, req);
+	hsreq = our_req(_req);
 	if ((!_req || !_req->complete || !_req->buf ||
 		!list_empty(&hsreq->queue)))
 		return -EINVAL;
 
-	hsep = container_of(_ep, struct s3c_hsudc_ep, ep);
+	hsep = our_ep(_ep);
 	hsudc = hsep->dev;
 	if (!hsudc->driver || hsudc->gadget.speed == USB_SPEED_UNKNOWN)
 		return -ESHUTDOWN;
@@ -935,7 +935,7 @@ static int s3c_hsudc_dequeue(struct usb_ep *_ep, struct usb_request *_req)
 	struct s3c_hsudc_req *hsreq;
 	unsigned long flags;
 
-	hsep = container_of(_ep, struct s3c_hsudc_ep, ep);
+	hsep = our_ep(_ep);
 	if (!_ep || hsep->ep.name == ep0name)
 		return -EINVAL;
 

From 294f78ec493e69b55bcba566d4fe264d041aba8d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Heiko=20St=C3=BCbner?= <heiko@sntech.de>
Date: Sun, 8 Jan 2012 21:58:28 +0100
Subject: [PATCH 10/53] usb: s3c-hsudc: add basic runtime_pm calls

This will enable the system to check for activity of the usb gadget
and also in a later patch to control the usbphy power-domain.
When handling the power domain there, it will be possible to remove
another reference to architecture code.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/s3c-hsudc.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index 41b3a583c1a7..5e8729374fba 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -30,6 +30,7 @@
 #include <linux/prefetch.h>
 #include <linux/platform_data/s3c-hsudc.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
 
 #include <mach/regs-s3c2443-clock.h>
 
@@ -1178,6 +1179,9 @@ static int s3c_hsudc_start(struct usb_gadget *gadget,
 	dev_info(hsudc->dev, "bound driver %s\n", driver->driver.name);
 
 	s3c_hsudc_reconfig(hsudc);
+
+	pm_runtime_get_sync(hsudc->dev);
+
 	s3c_hsudc_init_phy();
 	if (hsudc->pd->gpio_init)
 		hsudc->pd->gpio_init();
@@ -1208,6 +1212,9 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget,
 	hsudc->gadget.dev.driver = NULL;
 	hsudc->gadget.speed = USB_SPEED_UNKNOWN;
 	s3c_hsudc_uninit_phy();
+
+	pm_runtime_put(hsudc->dev);
+
 	if (hsudc->pd->gpio_uninit)
 		hsudc->pd->gpio_uninit();
 	s3c_hsudc_stop_activity(hsudc);
@@ -1362,6 +1369,8 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_add_udc;
 
+	pm_runtime_enable(dev);
+
 	return 0;
 err_add_udc:
 	device_unregister(&hsudc->gadget.dev);

From c50a3bff0edb0acd49d8033a12ea4668e09a31ad Mon Sep 17 00:00:00 2001
From: Tomoya MORINAGA <tomoya.rohm@gmail.com>
Date: Thu, 12 Jan 2012 11:27:05 +0900
Subject: [PATCH 11/53] usb: gadget: pch_udc: Fix disconnect issue

ISSUE:
When the driver notifies a gadget of a disconnect event, a system
rarely freezes.

CAUSE:
When the driver calls dev->driver->disconnect(), it is not calling
spin_unlock().

Signed-off-by: Tomoya MORINAGA <tomoya.rohm@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/pch_udc.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index a3fcaae4bc2a..6a44c921d13c 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -2335,8 +2335,11 @@ static void pch_udc_svc_ur_interrupt(struct pch_udc_dev *dev)
 		/* Complete request queue */
 		empty_req_queue(ep);
 	}
-	if (dev->driver && dev->driver->disconnect)
+	if (dev->driver && dev->driver->disconnect) {
+		spin_unlock(&dev->lock);
 		dev->driver->disconnect(&dev->gadget);
+		spin_lock(&dev->lock);
+	}
 }
 
 /**

From c802672cd36cd063bfd54d54c8c34825ab5b2357 Mon Sep 17 00:00:00 2001
From: Tomoya MORINAGA <tomoya.rohm@gmail.com>
Date: Thu, 12 Jan 2012 11:27:06 +0900
Subject: [PATCH 12/53] usb: gadget: pch_udc: Fix wrong return value

ISSUE:
If the return value of pch_udc_pcd_init() is False, the return value of
this function is unsettled.
Since pch_udc_pcd_init() always returns 0, there is not actually the issue.

CAUSE:
If pch_udc_pcd_init() is True, the variable, retval, is not set for an
appropriate value.

Signed-off-by: Tomoya MORINAGA <tomoya.rohm@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/pch_udc.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index 6a44c921d13c..96606b6cff45 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -2915,8 +2915,10 @@ static int pch_udc_probe(struct pci_dev *pdev,
 	}
 	pch_udc = dev;
 	/* initialize the hardware */
-	if (pch_udc_pcd_init(dev))
+	if (pch_udc_pcd_init(dev)) {
+		retval = -ENODEV;
 		goto finished;
+	}
 	if (request_irq(pdev->irq, pch_udc_isr, IRQF_SHARED, KBUILD_MODNAME,
 			dev)) {
 		dev_err(&pdev->dev, "%s: request_irq(%d) fail\n", __func__,

From 84566abba058b2aae8d603dfa90b5a3778a6714f Mon Sep 17 00:00:00 2001
From: Tomoya MORINAGA <tomoya.rohm@gmail.com>
Date: Thu, 12 Jan 2012 11:27:07 +0900
Subject: [PATCH 13/53] usb: gadget: pch_udc: Fix USB suspend issue

ISSUE:
After USB Suspend, a system rarely freezes.

CAUSE:
When USB Suspend occurred, the driver is not notifying
a gadget of the event.

Signed-off-by: Tomoya MORINAGA <tomoya.rohm@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/pch_udc.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index 96606b6cff45..842ca6349a90 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -2475,8 +2475,15 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
 	if (dev_intr & UDC_DEVINT_SC)
 		pch_udc_svc_cfg_interrupt(dev);
 	/* USB Suspend interrupt */
-	if (dev_intr & UDC_DEVINT_US)
+	if (dev_intr & UDC_DEVINT_US) {
+		if (dev->driver
+			&& dev->driver->suspend) {
+			spin_unlock(&dev->lock);
+			dev->driver->suspend(&dev->gadget);
+			spin_lock(&dev->lock);
+		}
 		dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n");
+	}
 	/* Clear the SOF interrupt, if enabled */
 	if (dev_intr & UDC_DEVINT_SOF)
 		dev_dbg(&dev->pdev->dev, "SOF\n");

From 1c575d2d2e3ff2a7cb3c2e2165064199cfd8ad32 Mon Sep 17 00:00:00 2001
From: Tomoya MORINAGA <tomoya.rohm@gmail.com>
Date: Thu, 12 Jan 2012 11:27:08 +0900
Subject: [PATCH 14/53] usb: gadget: pch_udc: Fix usb/gadget/pch_udc: Fix ether
 gadget connect/disconnect issue

ISSUE:
After a USB cable is connect/disconnected, the system rarely freezes.

CAUSE:
Since the USB device controller cannot know to disconnect the USB cable, when
it is used without detecting VBUS by GPIO, the UDC driver does not notify to
USB Gadget.

Since USB Gadget cannot know to disconnect, a false setting occurred when the
USB cable is connected/disconnect repeatedly.

Signed-off-by: Tomoya MORINAGA <tomoya.rohm@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/pch_udc.c | 70 +++++++++++++++++++++++++++++++++---
 1 file changed, 66 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index 842ca6349a90..c2f19752c074 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -311,6 +311,7 @@ struct pch_udc_ep {
  * @registered:		driver regsitered with system
  * @suspended:		driver in suspended state
  * @connected:		gadget driver associated
+ * @vbus_session:	required vbus_session state
  * @set_cfg_not_acked:	pending acknowledgement 4 setup
  * @waiting_zlp_ack:	pending acknowledgement 4 ZLP
  * @data_requests:	DMA pool for data requests
@@ -337,6 +338,7 @@ struct pch_udc_dev {
 			registered:1,
 			suspended:1,
 			connected:1,
+			vbus_session:1,
 			set_cfg_not_acked:1,
 			waiting_zlp_ack:1;
 	struct pci_pool		*data_requests;
@@ -553,6 +555,31 @@ static void pch_udc_clear_disconnect(struct pch_udc_dev *dev)
 	pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
 }
 
+/**
+ * pch_udc_reconnect() - This API initializes usb device controller,
+ *						and clear the disconnect status.
+ * @dev:		Reference to pch_udc_regs structure
+ */
+static void pch_udc_init(struct pch_udc_dev *dev);
+static void pch_udc_reconnect(struct pch_udc_dev *dev)
+{
+	pch_udc_init(dev);
+
+	/* enable device interrupts */
+	/* pch_udc_enable_interrupts() */
+	pch_udc_bit_clr(dev, UDC_DEVIRQMSK_ADDR,
+			UDC_DEVINT_UR | UDC_DEVINT_US |
+			UDC_DEVINT_ENUM |
+			UDC_DEVINT_SI | UDC_DEVINT_SC);
+
+	/* Clear the disconnect */
+	pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
+	pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_SD);
+	mdelay(1);
+	/* Resume USB signalling */
+	pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
+}
+
 /**
  * pch_udc_vbus_session() - set or clearr the disconnect status.
  * @dev:	Reference to pch_udc_regs structure
@@ -563,10 +590,18 @@ static void pch_udc_clear_disconnect(struct pch_udc_dev *dev)
 static inline void pch_udc_vbus_session(struct pch_udc_dev *dev,
 					  int is_active)
 {
-	if (is_active)
-		pch_udc_clear_disconnect(dev);
-	else
+	if (is_active) {
+		pch_udc_reconnect(dev);
+		dev->vbus_session = 1;
+	} else {
+		if (dev->driver && dev->driver->disconnect) {
+			spin_unlock(&dev->lock);
+			dev->driver->disconnect(&dev->gadget);
+			spin_lock(&dev->lock);
+		}
 		pch_udc_set_disconnect(dev);
+		dev->vbus_session = 0;
+	}
 }
 
 /**
@@ -1126,7 +1161,17 @@ static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on)
 	if (!gadget)
 		return -EINVAL;
 	dev = container_of(gadget, struct pch_udc_dev, gadget);
-	pch_udc_vbus_session(dev, is_on);
+	if (is_on) {
+		pch_udc_reconnect(dev);
+	} else {
+		if (dev->driver && dev->driver->disconnect) {
+			spin_unlock(&dev->lock);
+			dev->driver->disconnect(&dev->gadget);
+			spin_lock(&dev->lock);
+		}
+		pch_udc_set_disconnect(dev);
+	}
+
 	return 0;
 }
 
@@ -2482,6 +2527,15 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
 			dev->driver->suspend(&dev->gadget);
 			spin_lock(&dev->lock);
 		}
+
+		if (dev->vbus_session == 0) {
+			if (dev->driver && dev->driver->disconnect) {
+				spin_unlock(&dev->lock);
+				dev->driver->disconnect(&dev->gadget);
+				spin_lock(&dev->lock);
+			}
+			pch_udc_reconnect(dev);
+		}
 		dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n");
 	}
 	/* Clear the SOF interrupt, if enabled */
@@ -2509,6 +2563,14 @@ static irqreturn_t pch_udc_isr(int irq, void *pdev)
 	dev_intr = pch_udc_read_device_interrupts(dev);
 	ep_intr = pch_udc_read_ep_interrupts(dev);
 
+	/* For a hot plug, this find that the controller is hung up. */
+	if (dev_intr == ep_intr)
+		if (dev_intr == pch_udc_readl(dev, UDC_DEVCFG_ADDR)) {
+			dev_dbg(&dev->pdev->dev, "UDC: Hung up\n");
+			/* The controller is reset */
+			pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR);
+			return IRQ_HANDLED;
+		}
 	if (dev_intr)
 		/* Clear device interrupts */
 		pch_udc_write_device_interrupts(dev, dev_intr);

From 833310402c54ad9b676b465fc53ad276b13d36be Mon Sep 17 00:00:00 2001
From: Tomoya MORINAGA <tomoya.rohm@gmail.com>
Date: Thu, 12 Jan 2012 11:27:09 +0900
Subject: [PATCH 15/53] usb: gadget: pch_udc: Reduce redundant interrupt

ISSUE:
USB Suspend interrupts occur frequently.

CAUSE:
When it is called pch_udc_reconnect() in USB Suspend, it repeats reset and
Suspend.

SOLUTION:
pch_udc_reconnect() does not enable all interrupts.  When an enumeration event
occurred the driver enables all interrupts.

Signed-off-by: Tomoya MORINAGA <tomoya.rohm@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/pch_udc.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index c2f19752c074..4da98141e058 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -568,9 +568,7 @@ static void pch_udc_reconnect(struct pch_udc_dev *dev)
 	/* enable device interrupts */
 	/* pch_udc_enable_interrupts() */
 	pch_udc_bit_clr(dev, UDC_DEVIRQMSK_ADDR,
-			UDC_DEVINT_UR | UDC_DEVINT_US |
-			UDC_DEVINT_ENUM |
-			UDC_DEVINT_SI | UDC_DEVINT_SC);
+			UDC_DEVINT_UR | UDC_DEVINT_ENUM);
 
 	/* Clear the disconnect */
 	pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
@@ -2419,6 +2417,11 @@ static void pch_udc_svc_enum_interrupt(struct pch_udc_dev *dev)
 	pch_udc_set_dma(dev, DMA_DIR_TX);
 	pch_udc_set_dma(dev, DMA_DIR_RX);
 	pch_udc_ep_set_rrdy(&(dev->ep[UDC_EP0OUT_IDX]));
+
+	/* enable device interrupts */
+	pch_udc_enable_interrupts(dev, UDC_DEVINT_UR | UDC_DEVINT_US |
+					UDC_DEVINT_ES | UDC_DEVINT_ENUM |
+					UDC_DEVINT_SI | UDC_DEVINT_SC);
 }
 
 /**

From 9645f7d3dab346a9d442dca1688740551b8c55f2 Mon Sep 17 00:00:00 2001
From: Tomoya MORINAGA <tomoya.rohm@gmail.com>
Date: Thu, 12 Jan 2012 11:27:10 +0900
Subject: [PATCH 16/53] usb: gadget: pch_udc: Add debug message

ISSUE:
Adding debugging messages.

CAUSE:
The debugging messages are added to make sure of that major interrupt events
are occurring.

Signed-off-by: Tomoya MORINAGA <tomoya.rohm@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/pch_udc.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index 4da98141e058..82416aae816f 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -2511,11 +2511,15 @@ static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev)
 static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
 {
 	/* USB Reset Interrupt */
-	if (dev_intr & UDC_DEVINT_UR)
+	if (dev_intr & UDC_DEVINT_UR) {
 		pch_udc_svc_ur_interrupt(dev);
+		dev_dbg(&dev->pdev->dev, "USB_RESET\n");
+	}
 	/* Enumeration Done Interrupt */
-	if (dev_intr & UDC_DEVINT_ENUM)
+	if (dev_intr & UDC_DEVINT_ENUM) {
 		pch_udc_svc_enum_interrupt(dev);
+		dev_dbg(&dev->pdev->dev, "USB_ENUM\n");
+	}
 	/* Set Interface Interrupt */
 	if (dev_intr & UDC_DEVINT_SI)
 		pch_udc_svc_intf_interrupt(dev);

From a54c979fed31b4230b2e63132f7167206e4e5d69 Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Fri, 13 Jan 2012 21:51:47 +0100
Subject: [PATCH 17/53] usb: gadget: dummy_hcd: complete stream support

dummy_hcd provides (alloc|free)_stream() callbacks but there are not
doing anything. The transfer side also lacks matching of streams. This
patch changes this and implements stream allocation / de-allocation
support and proper urb <=> req matching.
The UDC side exposes a limit of 16 streams. DWC3, the only USB3 UDC has
no limitations in this regard except that it _needs_ to know that
streams will be used at the ep_enable time. At the host side, there is
no real limit either: XHCI can allocate any number of streams as long as
it does not run out of memory. The UAS gadget currently requests 16
streams and the UAS host side fallbacks from the requested 256 down to
16 which is fine.
From the UASP point of view (the only specified user), the number of
used streams does not really matter. The only limitation is that the
host may not use a higher stream than the gadget requested and can deal
with.

The dummy stream support has been modelled after current UAS + XHCI +
DWC3 + UASP usage which helps me testing:
- the device announces that each ep supports 16 streams (even it could
  more than that).
- the device side looks into Companion descriptor at ep_enable time and
  enables them according to it.
- the host side tries to enable the requested number of streams but the
  upper limit is the Comanion descriptor. None (zero streams) is an
  error condition, less is okay.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/dummy_hcd.c | 197 ++++++++++++++++++++++++++++++---
 1 file changed, 181 insertions(+), 16 deletions(-)

diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 626473238b3c..e57989ccc0e5 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -88,6 +88,7 @@ struct dummy_ep {
 	unsigned			wedged : 1;
 	unsigned			already_seen : 1;
 	unsigned			setup_stage : 1;
+	unsigned			stream_en:1;
 };
 
 struct dummy_request {
@@ -169,6 +170,8 @@ struct dummy_hcd {
 
 	struct usb_device		*udev;
 	struct list_head		urbp_list;
+	u32				stream_en_ep;
+	u8				num_stream[30 / 2];
 
 	unsigned			active:1;
 	unsigned			old_active:1;
@@ -514,8 +517,16 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 
 	_ep->maxpacket = max;
 	ep->desc = desc;
+	if (usb_ss_max_streams(_ep->comp_desc)) {
+		if (!usb_endpoint_xfer_bulk(desc)) {
+			dev_err(udc_dev(dum), "Can't enable stream support on "
+					"non-bulk ep %s\n", _ep->name);
+			return -EINVAL;
+		}
+		ep->stream_en = 1;
+	}
 
-	dev_dbg (udc_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d\n",
+	dev_dbg(udc_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d stream %s\n",
 		_ep->name,
 		desc->bEndpointAddress & 0x0f,
 		(desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
@@ -534,7 +545,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 			 val = "ctrl";
 			 break;
 		 }; val; }),
-		max);
+		max, ep->stream_en ? "enabled" : "disabled");
 
 	/* at this point real hardware should be NAKing transfers
 	 * to that endpoint, until a buffer is queued to it.
@@ -559,6 +570,7 @@ static int dummy_disable (struct usb_ep *_ep)
 
 	spin_lock_irqsave (&dum->lock, flags);
 	ep->desc = NULL;
+	ep->stream_en = 0;
 	retval = 0;
 	nuke (dum, ep);
 	spin_unlock_irqrestore (&dum->lock, flags);
@@ -1058,6 +1070,16 @@ static struct platform_driver dummy_udc_driver = {
 
 /*-------------------------------------------------------------------------*/
 
+static unsigned int dummy_get_ep_idx(const struct usb_endpoint_descriptor *desc)
+{
+	unsigned int index;
+
+	index = usb_endpoint_num(desc) << 1;
+	if (usb_endpoint_dir_in(desc))
+		index |= 1;
+	return index;
+}
+
 /* MASTER/HOST SIDE DRIVER
  *
  * this uses the hcd framework to hook up to host side drivers.
@@ -1070,6 +1092,81 @@ static struct platform_driver dummy_udc_driver = {
  * usb 2.0 rules.
  */
 
+static int dummy_ep_stream_en(struct dummy_hcd *dum_hcd, struct urb *urb)
+{
+	const struct usb_endpoint_descriptor *desc = &urb->ep->desc;
+	u32 index;
+
+	if (!usb_endpoint_xfer_bulk(desc))
+		return 0;
+
+	index = dummy_get_ep_idx(desc);
+	return (1 << index) & dum_hcd->stream_en_ep;
+}
+
+/*
+ * The max stream number is saved as a nibble so for the 30 possible endpoints
+ * we only 15 bytes of memory. Therefore we are limited to max 16 streams (0
+ * means we use only 1 stream). The maximum according to the spec is 16bit so
+ * if the 16 stream limit is about to go, the array size should be incremented
+ * to 30 elements of type u16.
+ */
+static int get_max_streams_for_pipe(struct dummy_hcd *dum_hcd,
+		unsigned int pipe)
+{
+	int max_streams;
+
+	max_streams = dum_hcd->num_stream[usb_pipeendpoint(pipe)];
+	if (usb_pipeout(pipe))
+		max_streams >>= 4;
+	else
+		max_streams &= 0xf;
+	max_streams++;
+	return max_streams;
+}
+
+static void set_max_streams_for_pipe(struct dummy_hcd *dum_hcd,
+		unsigned int pipe, unsigned int streams)
+{
+	int max_streams;
+
+	streams--;
+	max_streams = dum_hcd->num_stream[usb_pipeendpoint(pipe)];
+	if (usb_pipeout(pipe)) {
+		streams <<= 4;
+		max_streams &= 0xf;
+	} else {
+		max_streams &= 0xf0;
+	}
+	max_streams |= streams;
+	dum_hcd->num_stream[usb_pipeendpoint(pipe)] = max_streams;
+}
+
+static int dummy_validate_stream(struct dummy_hcd *dum_hcd, struct urb *urb)
+{
+	unsigned int max_streams;
+	int enabled;
+
+	enabled = dummy_ep_stream_en(dum_hcd, urb);
+	if (!urb->stream_id) {
+		if (enabled)
+			return -EINVAL;
+		return 0;
+	}
+	if (!enabled)
+		return -EINVAL;
+
+	max_streams = get_max_streams_for_pipe(dum_hcd,
+			usb_pipeendpoint(urb->pipe));
+	if (urb->stream_id > max_streams) {
+		dev_err(dummy_dev(dum_hcd), "Stream id %d is out of range.\n",
+				urb->stream_id);
+		BUG();
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static int dummy_urb_enqueue (
 	struct usb_hcd			*hcd,
 	struct urb			*urb,
@@ -1088,6 +1185,13 @@ static int dummy_urb_enqueue (
 
 	dum_hcd = hcd_to_dummy_hcd(hcd);
 	spin_lock_irqsave(&dum_hcd->dum->lock, flags);
+
+	rc = dummy_validate_stream(dum_hcd, urb);
+	if (rc) {
+		kfree(urbp);
+		goto done;
+	}
+
 	rc = usb_hcd_link_urb_to_ep(hcd, urb);
 	if (rc) {
 		kfree(urbp);
@@ -1201,10 +1305,10 @@ static int dummy_perform_transfer(struct urb *urb, struct dummy_request *req,
 }
 
 /* transfer up to a frame's worth; caller must own lock */
-static int
-transfer(struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit,
-		int *status)
+static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
+		struct dummy_ep *ep, int limit, int *status)
 {
+	struct dummy		*dum = dum_hcd->dum;
 	struct dummy_request	*req;
 
 top:
@@ -1214,6 +1318,11 @@ top:
 		int		is_short, to_host;
 		int		rescan = 0;
 
+		if (dummy_ep_stream_en(dum_hcd, urb)) {
+			if ((urb->stream_id != req->req.stream_id))
+				continue;
+		}
+
 		/* 1..N packets of ep->ep.maxpacket each ... the last one
 		 * may be short (including zero length).
 		 *
@@ -1744,7 +1853,7 @@ restart:
 		default:
 		treat_control_like_bulk:
 			ep->last_io = jiffies;
-			total = transfer(dum, urb, ep, limit, &status);
+			total = transfer(dum_hcd, urb, ep, limit, &status);
 			break;
 		}
 
@@ -2201,6 +2310,7 @@ static int dummy_start_ss(struct dummy_hcd *dum_hcd)
 	dum_hcd->timer.function = dummy_timer;
 	dum_hcd->timer.data = (unsigned long)dum_hcd;
 	dum_hcd->rh_state = DUMMY_RH_RUNNING;
+	dum_hcd->stream_en_ep = 0;
 	INIT_LIST_HEAD(&dum_hcd->urbp_list);
 	dummy_hcd_to_hcd(dum_hcd)->power_budget = POWER_BUDGET;
 	dummy_hcd_to_hcd(dum_hcd)->state = HC_STATE_RUNNING;
@@ -2290,11 +2400,46 @@ static int dummy_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
 	struct usb_host_endpoint **eps, unsigned int num_eps,
 	unsigned int num_streams, gfp_t mem_flags)
 {
-	if (hcd->speed != HCD_USB3)
-		dev_dbg(dummy_dev(hcd_to_dummy_hcd(hcd)),
-			"%s() - ERROR! Not supported for USB2.0 roothub\n",
-			__func__);
-	return 0;
+	struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
+	unsigned long flags;
+	int max_stream;
+	int ret_streams = num_streams;
+	unsigned int index;
+	unsigned int i;
+
+	if (!num_eps)
+		return -EINVAL;
+
+	spin_lock_irqsave(&dum_hcd->dum->lock, flags);
+	for (i = 0; i < num_eps; i++) {
+		index = dummy_get_ep_idx(&eps[i]->desc);
+		if ((1 << index) & dum_hcd->stream_en_ep) {
+			ret_streams = -EINVAL;
+			goto out;
+		}
+		max_stream = usb_ss_max_streams(&eps[i]->ss_ep_comp);
+		if (!max_stream) {
+			ret_streams = -EINVAL;
+			goto out;
+		}
+		if (max_stream < ret_streams) {
+			dev_dbg(dummy_dev(dum_hcd), "Ep 0x%x only supports %u "
+					"stream IDs.\n",
+					eps[i]->desc.bEndpointAddress,
+					max_stream);
+			ret_streams = max_stream;
+		}
+	}
+
+	for (i = 0; i < num_eps; i++) {
+		index = dummy_get_ep_idx(&eps[i]->desc);
+		dum_hcd->stream_en_ep |= 1 << index;
+		set_max_streams_for_pipe(dum_hcd,
+				usb_endpoint_num(&eps[i]->desc), ret_streams);
+	}
+out:
+	spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
+	return ret_streams;
 }
 
 /* Reverts a group of bulk endpoints back to not using stream IDs. */
@@ -2302,11 +2447,31 @@ static int dummy_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
 	struct usb_host_endpoint **eps, unsigned int num_eps,
 	gfp_t mem_flags)
 {
-	if (hcd->speed != HCD_USB3)
-		dev_dbg(dummy_dev(hcd_to_dummy_hcd(hcd)),
-			"%s() - ERROR! Not supported for USB2.0 roothub\n",
-			__func__);
-	return 0;
+	struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
+	unsigned long flags;
+	int ret;
+	unsigned int index;
+	unsigned int i;
+
+	spin_lock_irqsave(&dum_hcd->dum->lock, flags);
+	for (i = 0; i < num_eps; i++) {
+		index = dummy_get_ep_idx(&eps[i]->desc);
+		if (!((1 << index) & dum_hcd->stream_en_ep)) {
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+
+	for (i = 0; i < num_eps; i++) {
+		index = dummy_get_ep_idx(&eps[i]->desc);
+		dum_hcd->stream_en_ep &= ~(1 << index);
+		set_max_streams_for_pipe(dum_hcd,
+				usb_endpoint_num(&eps[i]->desc), 0);
+	}
+	ret = 0;
+out:
+	spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
+	return ret;
 }
 
 static struct hc_driver dummy_hcd = {

From 59f08e6d2015a16fb4856f910ef0660d13a0c767 Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Thu, 12 Jan 2012 12:53:14 +0100
Subject: [PATCH 18/53] usb: dummy_hcd: use usb_endpoint_type()

This patch makes use of usb_endpoint_type() instead of the open coding.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/dummy_hcd.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index e57989ccc0e5..fd4d86a57142 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -447,7 +447,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 	 * especially for "ep9out" style fixed function ones.)
 	 */
 	retval = -EINVAL;
-	switch (desc->bmAttributes & 0x03) {
+	switch (usb_endpoint_type(desc)) {
 	case USB_ENDPOINT_XFER_BULK:
 		if (strstr (ep->ep.name, "-iso")
 				|| strstr (ep->ep.name, "-int")) {
@@ -531,7 +531,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 		desc->bEndpointAddress & 0x0f,
 		(desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
 		({ char *val;
-		 switch (desc->bmAttributes & 0x03) {
+		 switch (usb_endpoint_type(desc)) {
 		 case USB_ENDPOINT_XFER_BULK:
 			 val = "bulk";
 			 break;
@@ -1439,7 +1439,7 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep)
 		limit += limit * tmp;
 	}
 	if (dum->gadget.speed == USB_SPEED_SUPER) {
-		switch (ep->desc->bmAttributes & 0x03) {
+		switch (usb_endpoint_type(ep->desc)) {
 		case USB_ENDPOINT_XFER_ISOC:
 			/* Sec. 4.4.8.2 USB3.0 Spec */
 			limit = 3 * 16 * 1024 * 8;

From 18f2cbaa2b9617eed20789ce40878920a8ea6beb Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Thu, 12 Jan 2012 12:53:15 +0100
Subject: [PATCH 19/53] usb: gadget: dummy_hcd: clean up checkpatch

This patch converts checkpatch output of
|./scripts/checkpatch.pl drivers/usb/gadget/dummy_hcd.c -file

from
|total: 22 errors, 174 warnings, 2642 lines checked

to
|total: 0 errors, 0 warnings, 2632 lines checked

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/dummy_hcd.c | 432 ++++++++++++++++-----------------
 1 file changed, 211 insertions(+), 221 deletions(-)

diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index fd4d86a57142..67573e5f2a18 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -42,25 +42,24 @@
 #include <linux/scatterlist.h>
 
 #include <asm/byteorder.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
 
-
 #define DRIVER_DESC	"USB Host+Gadget Emulator"
 #define DRIVER_VERSION	"02 May 2005"
 
 #define POWER_BUDGET	500	/* in mA; use 8 for low-power port testing */
 
-static const char	driver_name [] = "dummy_hcd";
-static const char	driver_desc [] = "USB Host+Gadget Emulator";
+static const char	driver_name[] = "dummy_hcd";
+static const char	driver_desc[] = "USB Host+Gadget Emulator";
 
-static const char	gadget_name [] = "dummy_udc";
+static const char	gadget_name[] = "dummy_udc";
 
-MODULE_DESCRIPTION (DRIVER_DESC);
-MODULE_AUTHOR ("David Brownell");
-MODULE_LICENSE ("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("David Brownell");
+MODULE_LICENSE("GPL");
 
 struct dummy_hcd_module_parameters {
 	bool is_super_speed;
@@ -84,10 +83,10 @@ struct dummy_ep {
 	struct usb_gadget		*gadget;
 	const struct usb_endpoint_descriptor *desc;
 	struct usb_ep			ep;
-	unsigned			halted : 1;
-	unsigned			wedged : 1;
-	unsigned			already_seen : 1;
-	unsigned			setup_stage : 1;
+	unsigned			halted:1;
+	unsigned			wedged:1;
+	unsigned			already_seen:1;
+	unsigned			setup_stage:1;
 	unsigned			stream_en:1;
 };
 
@@ -96,15 +95,15 @@ struct dummy_request {
 	struct usb_request		req;
 };
 
-static inline struct dummy_ep *usb_ep_to_dummy_ep (struct usb_ep *_ep)
+static inline struct dummy_ep *usb_ep_to_dummy_ep(struct usb_ep *_ep)
 {
-	return container_of (_ep, struct dummy_ep, ep);
+	return container_of(_ep, struct dummy_ep, ep);
 }
 
 static inline struct dummy_request *usb_request_to_dummy_request
 		(struct usb_request *_req)
 {
-	return container_of (_req, struct dummy_request, req);
+	return container_of(_req, struct dummy_request, req);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -123,9 +122,9 @@ static inline struct dummy_request *usb_request_to_dummy_request
  * configurations, illegal or unsupported packet lengths, and so on.
  */
 
-static const char ep0name [] = "ep0";
+static const char ep0name[] = "ep0";
 
-static const char *const ep_name [] = {
+static const char *const ep_name[] = {
 	ep0name,				/* everyone has ep0 */
 
 	/* act like a net2280: high speed, six configurable endpoints */
@@ -184,12 +183,12 @@ struct dummy {
 	/*
 	 * SLAVE/GADGET side support
 	 */
-	struct dummy_ep			ep [DUMMY_ENDPOINTS];
+	struct dummy_ep			ep[DUMMY_ENDPOINTS];
 	int				address;
 	struct usb_gadget		gadget;
 	struct usb_gadget_driver	*driver;
 	struct dummy_request		fifo_req;
-	u8				fifo_buf [FIFO_SIZE];
+	u8				fifo_buf[FIFO_SIZE];
 	u16				devstatus;
 	unsigned			udc_suspended:1;
 	unsigned			pullup:1;
@@ -216,14 +215,14 @@ static inline struct device *dummy_dev(struct dummy_hcd *dum)
 	return dummy_hcd_to_hcd(dum)->self.controller;
 }
 
-static inline struct device *udc_dev (struct dummy *dum)
+static inline struct device *udc_dev(struct dummy *dum)
 {
 	return dum->gadget.dev.parent;
 }
 
-static inline struct dummy *ep_to_dummy (struct dummy_ep *ep)
+static inline struct dummy *ep_to_dummy(struct dummy_ep *ep)
 {
-	return container_of (ep->gadget, struct dummy, gadget);
+	return container_of(ep->gadget, struct dummy, gadget);
 }
 
 static inline struct dummy_hcd *gadget_to_dummy_hcd(struct usb_gadget *gadget)
@@ -235,9 +234,9 @@ static inline struct dummy_hcd *gadget_to_dummy_hcd(struct usb_gadget *gadget)
 		return dum->hs_hcd;
 }
 
-static inline struct dummy *gadget_dev_to_dummy (struct device *dev)
+static inline struct dummy *gadget_dev_to_dummy(struct device *dev)
 {
-	return container_of (dev, struct dummy, gadget.dev);
+	return container_of(dev, struct dummy, gadget.dev);
 }
 
 static struct dummy			the_controller;
@@ -247,24 +246,23 @@ static struct dummy			the_controller;
 /* SLAVE/GADGET SIDE UTILITY ROUTINES */
 
 /* called with spinlock held */
-static void nuke (struct dummy *dum, struct dummy_ep *ep)
+static void nuke(struct dummy *dum, struct dummy_ep *ep)
 {
-	while (!list_empty (&ep->queue)) {
+	while (!list_empty(&ep->queue)) {
 		struct dummy_request	*req;
 
-		req = list_entry (ep->queue.next, struct dummy_request, queue);
-		list_del_init (&req->queue);
+		req = list_entry(ep->queue.next, struct dummy_request, queue);
+		list_del_init(&req->queue);
 		req->req.status = -ESHUTDOWN;
 
-		spin_unlock (&dum->lock);
-		req->req.complete (&ep->ep, &req->req);
-		spin_lock (&dum->lock);
+		spin_unlock(&dum->lock);
+		req->req.complete(&ep->ep, &req->req);
+		spin_lock(&dum->lock);
 	}
 }
 
 /* caller must hold lock */
-static void
-stop_activity (struct dummy *dum)
+static void stop_activity(struct dummy *dum)
 {
 	struct dummy_ep	*ep;
 
@@ -274,8 +272,8 @@ stop_activity (struct dummy *dum)
 	/* The timer is left running so that outstanding URBs can fail */
 
 	/* nuke any pending requests first, so driver i/o is quiesced */
-	list_for_each_entry (ep, &dum->gadget.ep_list, ep.ep_list)
-		nuke (dum, ep);
+	list_for_each_entry(ep, &dum->gadget.ep_list, ep.ep_list)
+		nuke(dum, ep);
 
 	/* driver now does any non-usb quiescing necessary */
 }
@@ -410,8 +408,8 @@ static void set_link_state(struct dummy_hcd *dum_hcd)
 #define is_enabled(dum) \
 	(dum->port_status & USB_PORT_STAT_ENABLE)
 
-static int
-dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+static int dummy_enable(struct usb_ep *_ep,
+		const struct usb_endpoint_descriptor *desc)
 {
 	struct dummy		*dum;
 	struct dummy_hcd	*dum_hcd;
@@ -419,11 +417,11 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 	unsigned		max;
 	int			retval;
 
-	ep = usb_ep_to_dummy_ep (_ep);
+	ep = usb_ep_to_dummy_ep(_ep);
 	if (!_ep || !desc || ep->desc || _ep->name == ep0name
 			|| desc->bDescriptorType != USB_DT_ENDPOINT)
 		return -EINVAL;
-	dum = ep_to_dummy (ep);
+	dum = ep_to_dummy(ep);
 	if (!dum->driver)
 		return -ESHUTDOWN;
 
@@ -449,8 +447,8 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 	retval = -EINVAL;
 	switch (usb_endpoint_type(desc)) {
 	case USB_ENDPOINT_XFER_BULK:
-		if (strstr (ep->ep.name, "-iso")
-				|| strstr (ep->ep.name, "-int")) {
+		if (strstr(ep->ep.name, "-iso")
+				|| strstr(ep->ep.name, "-int")) {
 			goto done;
 		}
 		switch (dum->gadget.speed) {
@@ -472,7 +470,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 		}
 		break;
 	case USB_ENDPOINT_XFER_INT:
-		if (strstr (ep->ep.name, "-iso")) /* bulk is ok */
+		if (strstr(ep->ep.name, "-iso")) /* bulk is ok */
 			goto done;
 		/* real hardware might not handle all packet sizes */
 		switch (dum->gadget.speed) {
@@ -492,8 +490,8 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 		}
 		break;
 	case USB_ENDPOINT_XFER_ISOC:
-		if (strstr (ep->ep.name, "-bulk")
-				|| strstr (ep->ep.name, "-int"))
+		if (strstr(ep->ep.name, "-bulk")
+				|| strstr(ep->ep.name, "-int"))
 			goto done;
 		/* real hardware might not handle all packet sizes */
 		switch (dum->gadget.speed) {
@@ -556,68 +554,65 @@ done:
 	return retval;
 }
 
-static int dummy_disable (struct usb_ep *_ep)
+static int dummy_disable(struct usb_ep *_ep)
 {
 	struct dummy_ep		*ep;
 	struct dummy		*dum;
 	unsigned long		flags;
 	int			retval;
 
-	ep = usb_ep_to_dummy_ep (_ep);
+	ep = usb_ep_to_dummy_ep(_ep);
 	if (!_ep || !ep->desc || _ep->name == ep0name)
 		return -EINVAL;
-	dum = ep_to_dummy (ep);
+	dum = ep_to_dummy(ep);
 
-	spin_lock_irqsave (&dum->lock, flags);
+	spin_lock_irqsave(&dum->lock, flags);
 	ep->desc = NULL;
 	ep->stream_en = 0;
 	retval = 0;
-	nuke (dum, ep);
-	spin_unlock_irqrestore (&dum->lock, flags);
+	nuke(dum, ep);
+	spin_unlock_irqrestore(&dum->lock, flags);
 
-	dev_dbg (udc_dev(dum), "disabled %s\n", _ep->name);
+	dev_dbg(udc_dev(dum), "disabled %s\n", _ep->name);
 	return retval;
 }
 
-static struct usb_request *
-dummy_alloc_request (struct usb_ep *_ep, gfp_t mem_flags)
+static struct usb_request *dummy_alloc_request(struct usb_ep *_ep,
+		gfp_t mem_flags)
 {
 	struct dummy_ep		*ep;
 	struct dummy_request	*req;
 
 	if (!_ep)
 		return NULL;
-	ep = usb_ep_to_dummy_ep (_ep);
+	ep = usb_ep_to_dummy_ep(_ep);
 
 	req = kzalloc(sizeof(*req), mem_flags);
 	if (!req)
 		return NULL;
-	INIT_LIST_HEAD (&req->queue);
+	INIT_LIST_HEAD(&req->queue);
 	return &req->req;
 }
 
-static void
-dummy_free_request (struct usb_ep *_ep, struct usb_request *_req)
+static void dummy_free_request(struct usb_ep *_ep, struct usb_request *_req)
 {
 	struct dummy_ep		*ep;
 	struct dummy_request	*req;
 
-	ep = usb_ep_to_dummy_ep (_ep);
+	ep = usb_ep_to_dummy_ep(_ep);
 	if (!ep || !_req || (!ep->desc && _ep->name != ep0name))
 		return;
 
-	req = usb_request_to_dummy_request (_req);
-	WARN_ON (!list_empty (&req->queue));
-	kfree (req);
+	req = usb_request_to_dummy_request(_req);
+	WARN_ON(!list_empty(&req->queue));
+	kfree(req);
 }
 
-static void
-fifo_complete (struct usb_ep *ep, struct usb_request *req)
+static void fifo_complete(struct usb_ep *ep, struct usb_request *req)
 {
 }
 
-static int
-dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
+static int dummy_queue(struct usb_ep *_ep, struct usb_request *_req,
 		gfp_t mem_flags)
 {
 	struct dummy_ep		*ep;
@@ -626,49 +621,48 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
 	struct dummy_hcd	*dum_hcd;
 	unsigned long		flags;
 
-	req = usb_request_to_dummy_request (_req);
-	if (!_req || !list_empty (&req->queue) || !_req->complete)
+	req = usb_request_to_dummy_request(_req);
+	if (!_req || !list_empty(&req->queue) || !_req->complete)
 		return -EINVAL;
 
-	ep = usb_ep_to_dummy_ep (_ep);
+	ep = usb_ep_to_dummy_ep(_ep);
 	if (!_ep || (!ep->desc && _ep->name != ep0name))
 		return -EINVAL;
 
-	dum = ep_to_dummy (ep);
+	dum = ep_to_dummy(ep);
 	dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
 	if (!dum->driver || !is_enabled(dum_hcd))
 		return -ESHUTDOWN;
 
 #if 0
-	dev_dbg (udc_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n",
+	dev_dbg(udc_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n",
 			ep, _req, _ep->name, _req->length, _req->buf);
 #endif
-
 	_req->status = -EINPROGRESS;
 	_req->actual = 0;
-	spin_lock_irqsave (&dum->lock, flags);
+	spin_lock_irqsave(&dum->lock, flags);
 
 	/* implement an emulated single-request FIFO */
 	if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
-			list_empty (&dum->fifo_req.queue) &&
-			list_empty (&ep->queue) &&
+			list_empty(&dum->fifo_req.queue) &&
+			list_empty(&ep->queue) &&
 			_req->length <= FIFO_SIZE) {
 		req = &dum->fifo_req;
 		req->req = *_req;
 		req->req.buf = dum->fifo_buf;
-		memcpy (dum->fifo_buf, _req->buf, _req->length);
+		memcpy(dum->fifo_buf, _req->buf, _req->length);
 		req->req.context = dum;
 		req->req.complete = fifo_complete;
 
 		list_add_tail(&req->queue, &ep->queue);
-		spin_unlock (&dum->lock);
+		spin_unlock(&dum->lock);
 		_req->actual = _req->length;
 		_req->status = 0;
-		_req->complete (_ep, _req);
-		spin_lock (&dum->lock);
+		_req->complete(_ep, _req);
+		spin_lock(&dum->lock);
 	}  else
 		list_add_tail(&req->queue, &ep->queue);
-	spin_unlock_irqrestore (&dum->lock, flags);
+	spin_unlock_irqrestore(&dum->lock, flags);
 
 	/* real hardware would likely enable transfers here, in case
 	 * it'd been left NAKing.
@@ -676,7 +670,7 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
 	return 0;
 }
 
-static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req)
+static int dummy_dequeue(struct usb_ep *_ep, struct usb_request *_req)
 {
 	struct dummy_ep		*ep;
 	struct dummy		*dum;
@@ -686,31 +680,31 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req)
 
 	if (!_ep || !_req)
 		return retval;
-	ep = usb_ep_to_dummy_ep (_ep);
-	dum = ep_to_dummy (ep);
+	ep = usb_ep_to_dummy_ep(_ep);
+	dum = ep_to_dummy(ep);
 
 	if (!dum->driver)
 		return -ESHUTDOWN;
 
-	local_irq_save (flags);
-	spin_lock (&dum->lock);
-	list_for_each_entry (req, &ep->queue, queue) {
+	local_irq_save(flags);
+	spin_lock(&dum->lock);
+	list_for_each_entry(req, &ep->queue, queue) {
 		if (&req->req == _req) {
-			list_del_init (&req->queue);
+			list_del_init(&req->queue);
 			_req->status = -ECONNRESET;
 			retval = 0;
 			break;
 		}
 	}
-	spin_unlock (&dum->lock);
+	spin_unlock(&dum->lock);
 
 	if (retval == 0) {
-		dev_dbg (udc_dev(dum),
+		dev_dbg(udc_dev(dum),
 				"dequeued req %p from %s, len %d buf %p\n",
 				req, _ep->name, _req->length, _req->buf);
-		_req->complete (_ep, _req);
+		_req->complete(_ep, _req);
 	}
-	local_irq_restore (flags);
+	local_irq_restore(flags);
 	return retval;
 }
 
@@ -722,14 +716,14 @@ dummy_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
 
 	if (!_ep)
 		return -EINVAL;
-	ep = usb_ep_to_dummy_ep (_ep);
-	dum = ep_to_dummy (ep);
+	ep = usb_ep_to_dummy_ep(_ep);
+	dum = ep_to_dummy(ep);
 	if (!dum->driver)
 		return -ESHUTDOWN;
 	if (!value)
 		ep->halted = ep->wedged = 0;
 	else if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
-			!list_empty (&ep->queue))
+			!list_empty(&ep->queue))
 		return -EAGAIN;
 	else {
 		ep->halted = 1;
@@ -770,15 +764,15 @@ static const struct usb_ep_ops dummy_ep_ops = {
 /*-------------------------------------------------------------------------*/
 
 /* there are both host and device side versions of this call ... */
-static int dummy_g_get_frame (struct usb_gadget *_gadget)
+static int dummy_g_get_frame(struct usb_gadget *_gadget)
 {
 	struct timeval	tv;
 
-	do_gettimeofday (&tv);
+	do_gettimeofday(&tv);
 	return tv.tv_usec / 1000;
 }
 
-static int dummy_wakeup (struct usb_gadget *_gadget)
+static int dummy_wakeup(struct usb_gadget *_gadget)
 {
 	struct dummy_hcd *dum_hcd;
 
@@ -801,11 +795,11 @@ static int dummy_wakeup (struct usb_gadget *_gadget)
 	return 0;
 }
 
-static int dummy_set_selfpowered (struct usb_gadget *_gadget, int value)
+static int dummy_set_selfpowered(struct usb_gadget *_gadget, int value)
 {
 	struct dummy	*dum;
 
-	dum = (gadget_to_dummy_hcd(_gadget))->dum;
+	dum = gadget_to_dummy_hcd(_gadget)->dum;
 	if (value)
 		dum->devstatus |= (1 << USB_DEVICE_SELF_POWERED);
 	else
@@ -821,7 +815,7 @@ static void dummy_udc_update_ep0(struct dummy *dum)
 		dum->ep[0].ep.maxpacket = 64;
 }
 
-static int dummy_pullup (struct usb_gadget *_gadget, int value)
+static int dummy_pullup(struct usb_gadget *_gadget, int value)
 {
 	struct dummy_hcd *dum_hcd;
 	struct dummy	*dum;
@@ -846,10 +840,10 @@ static int dummy_pullup (struct usb_gadget *_gadget, int value)
 	}
 	dum_hcd = gadget_to_dummy_hcd(_gadget);
 
-	spin_lock_irqsave (&dum->lock, flags);
+	spin_lock_irqsave(&dum->lock, flags);
 	dum->pullup = (value != 0);
 	set_link_state(dum_hcd);
-	spin_unlock_irqrestore (&dum->lock, flags);
+	spin_unlock_irqrestore(&dum->lock, flags);
 
 	usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd));
 	return 0;
@@ -872,16 +866,16 @@ static const struct usb_gadget_ops dummy_ops = {
 /*-------------------------------------------------------------------------*/
 
 /* "function" sysfs attribute */
-static ssize_t
-show_function (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_function(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
-	struct dummy	*dum = gadget_dev_to_dummy (dev);
+	struct dummy	*dum = gadget_dev_to_dummy(dev);
 
 	if (!dum->driver || !dum->driver->function)
 		return 0;
-	return scnprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", dum->driver->function);
 }
-static DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
+static DEVICE_ATTR(function, S_IRUGO, show_function, NULL);
 
 /*-------------------------------------------------------------------------*/
 
@@ -916,7 +910,7 @@ static int dummy_udc_start(struct usb_gadget *g,
 	dum->devstatus = 0;
 
 	dum->driver = driver;
-	dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
+	dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n",
 			driver->driver.name);
 	return 0;
 }
@@ -927,7 +921,7 @@ static int dummy_udc_stop(struct usb_gadget *g,
 	struct dummy_hcd	*dum_hcd = gadget_to_dummy_hcd(g);
 	struct dummy		*dum = dum_hcd->dum;
 
-	dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n",
+	dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
 			driver->driver.name);
 
 	dum->driver = NULL;
@@ -940,8 +934,7 @@ static int dummy_udc_stop(struct usb_gadget *g,
 
 /* The gadget structure is stored inside the hcd structure and will be
  * released along with it. */
-static void
-dummy_gadget_release (struct device *dev)
+static void dummy_gadget_release(struct device *dev)
 {
 	return;
 }
@@ -978,7 +971,7 @@ static void init_dummy_udc_hw(struct dummy *dum)
 #endif
 }
 
-static int dummy_udc_probe (struct platform_device *pdev)
+static int dummy_udc_probe(struct platform_device *pdev)
 {
 	struct dummy	*dum = &the_controller;
 	int		rc;
@@ -990,7 +983,7 @@ static int dummy_udc_probe (struct platform_device *pdev)
 	dev_set_name(&dum->gadget.dev, "gadget");
 	dum->gadget.dev.parent = &pdev->dev;
 	dum->gadget.dev.release = dummy_gadget_release;
-	rc = device_register (&dum->gadget.dev);
+	rc = device_register(&dum->gadget.dev);
 	if (rc < 0) {
 		put_device(&dum->gadget.dev);
 		return rc;
@@ -1002,7 +995,7 @@ static int dummy_udc_probe (struct platform_device *pdev)
 	if (rc < 0)
 		goto err_udc;
 
-	rc = device_create_file (&dum->gadget.dev, &dev_attr_function);
+	rc = device_create_file(&dum->gadget.dev, &dev_attr_function);
 	if (rc < 0)
 		goto err_dev;
 	platform_set_drvdata(pdev, dum);
@@ -1015,14 +1008,14 @@ err_udc:
 	return rc;
 }
 
-static int dummy_udc_remove (struct platform_device *pdev)
+static int dummy_udc_remove(struct platform_device *pdev)
 {
-	struct dummy	*dum = platform_get_drvdata (pdev);
+	struct dummy	*dum = platform_get_drvdata(pdev);
 
 	usb_del_gadget_udc(&dum->gadget);
-	platform_set_drvdata (pdev, NULL);
-	device_remove_file (&dum->gadget.dev, &dev_attr_function);
-	device_unregister (&dum->gadget.dev);
+	platform_set_drvdata(pdev, NULL);
+	device_remove_file(&dum->gadget.dev, &dev_attr_function);
+	device_unregister(&dum->gadget.dev);
 	return 0;
 }
 
@@ -1167,7 +1160,7 @@ static int dummy_validate_stream(struct dummy_hcd *dum_hcd, struct urb *urb)
 	return 0;
 }
 
-static int dummy_urb_enqueue (
+static int dummy_urb_enqueue(
 	struct usb_hcd			*hcd,
 	struct urb			*urb,
 	gfp_t				mem_flags
@@ -1177,7 +1170,7 @@ static int dummy_urb_enqueue (
 	unsigned long	flags;
 	int		rc;
 
-	urbp = kmalloc (sizeof *urbp, mem_flags);
+	urbp = kmalloc(sizeof *urbp, mem_flags);
 	if (!urbp)
 		return -ENOMEM;
 	urbp->urb = urb;
@@ -1206,7 +1199,7 @@ static int dummy_urb_enqueue (
 
 	list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list);
 	urb->hcpriv = urbp;
-	if (usb_pipetype (urb->pipe) == PIPE_CONTROL)
+	if (usb_pipetype(urb->pipe) == PIPE_CONTROL)
 		urb->error_count = 1;		/* mark as a new urb */
 
 	/* kick the scheduler, it'll do the rest */
@@ -1313,7 +1306,7 @@ static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
 
 top:
 	/* if there's no request queued, the device is NAKing; return */
-	list_for_each_entry (req, &ep->queue, queue) {
+	list_for_each_entry(req, &ep->queue, queue) {
 		unsigned	host_len, dev_len, len;
 		int		is_short, to_host;
 		int		rescan = 0;
@@ -1332,18 +1325,18 @@ top:
 		 */
 		host_len = urb->transfer_buffer_length - urb->actual_length;
 		dev_len = req->req.length - req->req.actual;
-		len = min (host_len, dev_len);
+		len = min(host_len, dev_len);
 
 		/* FIXME update emulated data toggle too */
 
-		to_host = usb_pipein (urb->pipe);
-		if (unlikely (len == 0))
+		to_host = usb_pipein(urb->pipe);
+		if (unlikely(len == 0))
 			is_short = 1;
 		else {
 			/* not enough bandwidth left? */
 			if (limit < ep->ep.maxpacket && limit < len)
 				break;
-			len = min (len, (unsigned) limit);
+			len = min_t(unsigned, len, limit);
 			if (len == 0)
 				break;
 
@@ -1404,11 +1397,11 @@ top:
 
 		/* device side completion --> continuable */
 		if (req->req.status != -EINPROGRESS) {
-			list_del_init (&req->queue);
+			list_del_init(&req->queue);
 
-			spin_unlock (&dum->lock);
-			req->req.complete (&ep->ep, &req->req);
-			spin_lock (&dum->lock);
+			spin_unlock(&dum->lock);
+			req->req.complete(&ep->ep, &req->req);
+			spin_lock(&dum->lock);
 
 			/* requests might have been unlinked... */
 			rescan = 1;
@@ -1425,7 +1418,7 @@ top:
 	return limit;
 }
 
-static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep)
+static int periodic_bytes(struct dummy *dum, struct dummy_ep *ep)
 {
 	int	limit = ep->ep.maxpacket;
 
@@ -1461,7 +1454,7 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep)
 			USB_PORT_STAT_SUSPEND)) \
 		== (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE))
 
-static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
+static struct dummy_ep *find_endpoint(struct dummy *dum, u8 address)
 {
 	int		i;
 
@@ -1469,9 +1462,9 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
 			dum->ss_hcd : dum->hs_hcd)))
 		return NULL;
 	if ((address & ~USB_DIR_IN) == 0)
-		return &dum->ep [0];
+		return &dum->ep[0];
 	for (i = 1; i < DUMMY_ENDPOINTS; i++) {
-		struct dummy_ep	*ep = &dum->ep [i];
+		struct dummy_ep	*ep = &dum->ep[i];
 
 		if (!ep->desc)
 			continue;
@@ -1701,19 +1694,19 @@ static void dummy_timer(unsigned long _dum_hcd)
 	/* FIXME if HZ != 1000 this will probably misbehave ... */
 
 	/* look at each urb queued by the host side driver */
-	spin_lock_irqsave (&dum->lock, flags);
+	spin_lock_irqsave(&dum->lock, flags);
 
 	if (!dum_hcd->udev) {
 		dev_err(dummy_dev(dum_hcd),
 				"timer fired with no URBs pending?\n");
-		spin_unlock_irqrestore (&dum->lock, flags);
+		spin_unlock_irqrestore(&dum->lock, flags);
 		return;
 	}
 
 	for (i = 0; i < DUMMY_ENDPOINTS; i++) {
-		if (!ep_name [i])
+		if (!ep_name[i])
 			break;
-		dum->ep [i].already_seen = 0;
+		dum->ep[i].already_seen = 0;
 	}
 
 restart:
@@ -1730,7 +1723,7 @@ restart:
 			goto return_urb;
 		else if (dum_hcd->rh_state != DUMMY_RH_RUNNING)
 			continue;
-		type = usb_pipetype (urb->pipe);
+		type = usb_pipetype(urb->pipe);
 
 		/* used up this frame's non-periodic bandwidth?
 		 * FIXME there's infinite bandwidth for control and
@@ -1741,7 +1734,7 @@ restart:
 
 		/* find the gadget's ep for this request (if configured) */
 		address = usb_pipeendpoint (urb->pipe);
-		if (usb_pipein (urb->pipe))
+		if (usb_pipein(urb->pipe))
 			address |= USB_DIR_IN;
 		ep = find_endpoint(dum, address);
 		if (!ep) {
@@ -1756,7 +1749,7 @@ restart:
 		if (ep->already_seen)
 			continue;
 		ep->already_seen = 1;
-		if (ep == &dum->ep [0] && urb->error_count) {
+		if (ep == &dum->ep[0] && urb->error_count) {
 			ep->setup_stage = 1;	/* a new urb */
 			urb->error_count = 0;
 		}
@@ -1770,21 +1763,21 @@ restart:
 		/* FIXME make sure both ends agree on maxpacket */
 
 		/* handle control requests */
-		if (ep == &dum->ep [0] && ep->setup_stage) {
+		if (ep == &dum->ep[0] && ep->setup_stage) {
 			struct usb_ctrlrequest		setup;
 			int				value = 1;
 
-			setup = *(struct usb_ctrlrequest*) urb->setup_packet;
+			setup = *(struct usb_ctrlrequest *) urb->setup_packet;
 			/* paranoia, in case of stale queued data */
-			list_for_each_entry (req, &ep->queue, queue) {
-				list_del_init (&req->queue);
+			list_for_each_entry(req, &ep->queue, queue) {
+				list_del_init(&req->queue);
 				req->req.status = -EOVERFLOW;
-				dev_dbg (udc_dev(dum), "stale req = %p\n",
+				dev_dbg(udc_dev(dum), "stale req = %p\n",
 						req);
 
-				spin_unlock (&dum->lock);
-				req->req.complete (&ep->ep, &req->req);
-				spin_lock (&dum->lock);
+				spin_unlock(&dum->lock);
+				req->req.complete(&ep->ep, &req->req);
+				spin_lock(&dum->lock);
 				ep->already_seen = 0;
 				goto restart;
 			}
@@ -1804,10 +1797,10 @@ restart:
 			 * until setup() returns; no reentrancy issues etc.
 			 */
 			if (value > 0) {
-				spin_unlock (&dum->lock);
-				value = dum->driver->setup (&dum->gadget,
+				spin_unlock(&dum->lock);
+				value = dum->driver->setup(&dum->gadget,
 						&setup);
-				spin_lock (&dum->lock);
+				spin_lock(&dum->lock);
 
 				if (value >= 0) {
 					/* no delays (max 64KB data stage) */
@@ -1819,7 +1812,7 @@ restart:
 
 			if (value < 0) {
 				if (value != -EOPNOTSUPP)
-					dev_dbg (udc_dev(dum),
+					dev_dbg(udc_dev(dum),
 						"setup --> %d\n",
 						value);
 				status = -EPIPE;
@@ -1831,14 +1824,14 @@ restart:
 
 		/* non-control requests */
 		limit = total;
-		switch (usb_pipetype (urb->pipe)) {
+		switch (usb_pipetype(urb->pipe)) {
 		case PIPE_ISOCHRONOUS:
 			/* FIXME is it urb->interval since the last xfer?
 			 * use urb->iso_frame_desc[i].
 			 * complete whether or not ep has requests queued.
 			 * report random errors, to debug drivers.
 			 */
-			limit = max (limit, periodic_bytes (dum, ep));
+			limit = max(limit, periodic_bytes(dum, ep));
 			status = -ENOSYS;
 			break;
 
@@ -1846,12 +1839,11 @@ restart:
 			/* FIXME is it urb->interval since the last xfer?
 			 * this almost certainly polls too fast.
 			 */
-			limit = max (limit, periodic_bytes (dum, ep));
+			limit = max(limit, periodic_bytes(dum, ep));
 			/* FALLTHROUGH */
 
-		// case PIPE_BULK:  case PIPE_CONTROL:
 		default:
-		treat_control_like_bulk:
+treat_control_like_bulk:
 			ep->last_io = jiffies;
 			total = transfer(dum_hcd, urb, ep, limit, &status);
 			break;
@@ -1862,15 +1854,15 @@ restart:
 			continue;
 
 return_urb:
-		list_del (&urbp->urbp_list);
-		kfree (urbp);
+		list_del(&urbp->urbp_list);
+		kfree(urbp);
 		if (ep)
 			ep->already_seen = ep->setup_stage = 0;
 
 		usb_hcd_unlink_urb_from_ep(dummy_hcd_to_hcd(dum_hcd), urb);
-		spin_unlock (&dum->lock);
+		spin_unlock(&dum->lock);
 		usb_hcd_giveback_urb(dummy_hcd_to_hcd(dum_hcd), urb, status);
-		spin_lock (&dum->lock);
+		spin_lock(&dum->lock);
 
 		goto restart;
 	}
@@ -1883,7 +1875,7 @@ return_urb:
 		mod_timer(&dum_hcd->timer, jiffies + msecs_to_jiffies(1));
 	}
 
-	spin_unlock_irqrestore (&dum->lock, flags);
+	spin_unlock_irqrestore(&dum->lock, flags);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1895,7 +1887,7 @@ return_urb:
 	| USB_PORT_STAT_C_OVERCURRENT \
 	| USB_PORT_STAT_C_RESET) << 16)
 
-static int dummy_hub_status (struct usb_hcd *hcd, char *buf)
+static int dummy_hub_status(struct usb_hcd *hcd, char *buf)
 {
 	struct dummy_hcd	*dum_hcd;
 	unsigned long		flags;
@@ -1919,7 +1911,7 @@ static int dummy_hub_status (struct usb_hcd *hcd, char *buf)
 				dum_hcd->port_status);
 		retval = 1;
 		if (dum_hcd->rh_state == DUMMY_RH_SUSPENDED)
-			usb_hcd_resume_root_hub (hcd);
+			usb_hcd_resume_root_hub(hcd);
 	}
 done:
 	spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
@@ -1938,10 +1930,9 @@ ss_hub_descriptor(struct usb_hub_descriptor *desc)
 	desc->u.ss.DeviceRemovable = 0xffff;
 }
 
-static inline void
-hub_descriptor (struct usb_hub_descriptor *desc)
+static inline void hub_descriptor(struct usb_hub_descriptor *desc)
 {
-	memset (desc, 0, sizeof *desc);
+	memset(desc, 0, sizeof *desc);
 	desc->bDescriptorType = 0x29;
 	desc->bDescLength = 9;
 	desc->wHubCharacteristics = cpu_to_le16(0x0001);
@@ -1950,7 +1941,7 @@ hub_descriptor (struct usb_hub_descriptor *desc)
 	desc->u.hs.DeviceRemovable[1] = 0xff;
 }
 
-static int dummy_hub_control (
+static int dummy_hub_control(
 	struct usb_hcd	*hcd,
 	u16		typeReq,
 	u16		wValue,
@@ -2018,7 +2009,7 @@ static int dummy_hub_control (
 			hub_descriptor((struct usb_hub_descriptor *) buf);
 		break;
 	case GetHubStatus:
-		*(__le32 *) buf = cpu_to_le32 (0);
+		*(__le32 *) buf = cpu_to_le32(0);
 		break;
 	case GetPortStatus:
 		if (wIndex != 1)
@@ -2060,8 +2051,8 @@ static int dummy_hub_control (
 			}
 		}
 		set_link_state(dum_hcd);
-		((__le16 *) buf)[0] = cpu_to_le16 (dum_hcd->port_status);
-		((__le16 *) buf)[1] = cpu_to_le16 (dum_hcd->port_status >> 16);
+		((__le16 *) buf)[0] = cpu_to_le16(dum_hcd->port_status);
+		((__le16 *) buf)[1] = cpu_to_le16(dum_hcd->port_status >> 16);
 		break;
 	case SetHubFeature:
 		retval = -EPIPE;
@@ -2195,15 +2186,15 @@ error:
 	spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
 
 	if ((dum_hcd->port_status & PORT_C_MASK) != 0)
-		usb_hcd_poll_rh_status (hcd);
+		usb_hcd_poll_rh_status(hcd);
 	return retval;
 }
 
-static int dummy_bus_suspend (struct usb_hcd *hcd)
+static int dummy_bus_suspend(struct usb_hcd *hcd)
 {
 	struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
 
-	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
+	dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
 
 	spin_lock_irq(&dum_hcd->dum->lock);
 	dum_hcd->rh_state = DUMMY_RH_SUSPENDED;
@@ -2213,12 +2204,12 @@ static int dummy_bus_suspend (struct usb_hcd *hcd)
 	return 0;
 }
 
-static int dummy_bus_resume (struct usb_hcd *hcd)
+static int dummy_bus_resume(struct usb_hcd *hcd)
 {
 	struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
 	int rc = 0;
 
-	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
+	dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
 
 	spin_lock_irq(&dum_hcd->dum->lock);
 	if (!HCD_HW_ACCESSIBLE(hcd)) {
@@ -2236,55 +2227,54 @@ static int dummy_bus_resume (struct usb_hcd *hcd)
 
 /*-------------------------------------------------------------------------*/
 
-static inline ssize_t
-show_urb (char *buf, size_t size, struct urb *urb)
+static inline ssize_t show_urb(char *buf, size_t size, struct urb *urb)
 {
-	int ep = usb_pipeendpoint (urb->pipe);
+	int ep = usb_pipeendpoint(urb->pipe);
 
-	return snprintf (buf, size,
+	return snprintf(buf, size,
 		"urb/%p %s ep%d%s%s len %d/%d\n",
 		urb,
 		({ char *s;
-		 switch (urb->dev->speed) {
-		 case USB_SPEED_LOW:
+		switch (urb->dev->speed) {
+		case USB_SPEED_LOW:
 			s = "ls";
 			break;
-		 case USB_SPEED_FULL:
+		case USB_SPEED_FULL:
 			s = "fs";
 			break;
-		 case USB_SPEED_HIGH:
+		case USB_SPEED_HIGH:
 			s = "hs";
 			break;
-		 case USB_SPEED_SUPER:
+		case USB_SPEED_SUPER:
 			s = "ss";
 			break;
-		 default:
+		default:
 			s = "?";
 			break;
 		 }; s; }),
-		ep, ep ? (usb_pipein (urb->pipe) ? "in" : "out") : "",
+		ep, ep ? (usb_pipein(urb->pipe) ? "in" : "out") : "",
 		({ char *s; \
-		 switch (usb_pipetype (urb->pipe)) { \
-		 case PIPE_CONTROL: \
+		switch (usb_pipetype(urb->pipe)) { \
+		case PIPE_CONTROL: \
 			s = ""; \
 			break; \
-		 case PIPE_BULK: \
+		case PIPE_BULK: \
 			s = "-bulk"; \
 			break; \
-		 case PIPE_INTERRUPT: \
+		case PIPE_INTERRUPT: \
 			s = "-int"; \
 			break; \
-		 default: \
+		default: \
 			s = "-iso"; \
 			break; \
-		}; s;}),
+		}; s; }),
 		urb->actual_length, urb->transfer_buffer_length);
 }
 
-static ssize_t
-show_urbs (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_urbs(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
-	struct usb_hcd		*hcd = dev_get_drvdata (dev);
+	struct usb_hcd		*hcd = dev_get_drvdata(dev);
 	struct dummy_hcd	*dum_hcd = hcd_to_dummy_hcd(hcd);
 	struct urbp		*urbp;
 	size_t			size = 0;
@@ -2294,7 +2284,7 @@ show_urbs (struct device *dev, struct device_attribute *attr, char *buf)
 	list_for_each_entry(urbp, &dum_hcd->urbp_list, urbp_list) {
 		size_t		temp;
 
-		temp = show_urb (buf, PAGE_SIZE - size, urbp->urb);
+		temp = show_urb(buf, PAGE_SIZE - size, urbp->urb);
 		buf += temp;
 		size += temp;
 	}
@@ -2302,7 +2292,7 @@ show_urbs (struct device *dev, struct device_attribute *attr, char *buf)
 
 	return size;
 }
-static DEVICE_ATTR (urbs, S_IRUGO, show_urbs, NULL);
+static DEVICE_ATTR(urbs, S_IRUGO, show_urbs, NULL);
 
 static int dummy_start_ss(struct dummy_hcd *dum_hcd)
 {
@@ -2356,11 +2346,11 @@ static int dummy_start(struct usb_hcd *hcd)
 	return device_create_file(dummy_dev(dum_hcd), &dev_attr_urbs);
 }
 
-static void dummy_stop (struct usb_hcd *hcd)
+static void dummy_stop(struct usb_hcd *hcd)
 {
 	struct dummy		*dum;
 
-	dum = (hcd_to_dummy_hcd(hcd))->dum;
+	dum = hcd_to_dummy_hcd(hcd)->dum;
 	device_remove_file(dummy_dev(hcd_to_dummy_hcd(hcd)), &dev_attr_urbs);
 	usb_gadget_unregister_driver(dum->driver);
 	dev_info(dummy_dev(hcd_to_dummy_hcd(hcd)), "stopped\n");
@@ -2368,9 +2358,9 @@ static void dummy_stop (struct usb_hcd *hcd)
 
 /*-------------------------------------------------------------------------*/
 
-static int dummy_h_get_frame (struct usb_hcd *hcd)
+static int dummy_h_get_frame(struct usb_hcd *hcd)
 {
-	return dummy_g_get_frame (NULL);
+	return dummy_g_get_frame(NULL);
 }
 
 static int dummy_setup(struct usb_hcd *hcd)
@@ -2485,13 +2475,13 @@ static struct hc_driver dummy_hcd = {
 	.start =		dummy_start,
 	.stop =			dummy_stop,
 
-	.urb_enqueue = 		dummy_urb_enqueue,
-	.urb_dequeue = 		dummy_urb_dequeue,
+	.urb_enqueue =		dummy_urb_enqueue,
+	.urb_dequeue =		dummy_urb_dequeue,
 
-	.get_frame_number = 	dummy_h_get_frame,
+	.get_frame_number =	dummy_h_get_frame,
 
-	.hub_status_data = 	dummy_hub_status,
-	.hub_control = 		dummy_hub_control,
+	.hub_status_data =	dummy_hub_status,
+	.hub_control =		dummy_hub_control,
 	.bus_suspend =		dummy_bus_suspend,
 	.bus_resume =		dummy_bus_resume,
 
@@ -2546,7 +2536,7 @@ static int dummy_hcd_remove(struct platform_device *pdev)
 {
 	struct dummy		*dum;
 
-	dum = (hcd_to_dummy_hcd(platform_get_drvdata(pdev)))->dum;
+	dum = hcd_to_dummy_hcd(platform_get_drvdata(pdev))->dum;
 
 	if (dum->ss_hcd) {
 		usb_remove_hcd(dummy_hcd_to_hcd(dum->ss_hcd));
@@ -2562,15 +2552,15 @@ static int dummy_hcd_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state)
+static int dummy_hcd_suspend(struct platform_device *pdev, pm_message_t state)
 {
 	struct usb_hcd		*hcd;
 	struct dummy_hcd	*dum_hcd;
 	int			rc = 0;
 
-	dev_dbg (&pdev->dev, "%s\n", __func__);
+	dev_dbg(&pdev->dev, "%s\n", __func__);
 
-	hcd = platform_get_drvdata (pdev);
+	hcd = platform_get_drvdata(pdev);
 	dum_hcd = hcd_to_dummy_hcd(hcd);
 	if (dum_hcd->rh_state == DUMMY_RH_RUNNING) {
 		dev_warn(&pdev->dev, "Root hub isn't suspended!\n");
@@ -2580,15 +2570,15 @@ static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state)
 	return rc;
 }
 
-static int dummy_hcd_resume (struct platform_device *pdev)
+static int dummy_hcd_resume(struct platform_device *pdev)
 {
 	struct usb_hcd		*hcd;
 
-	dev_dbg (&pdev->dev, "%s\n", __func__);
+	dev_dbg(&pdev->dev, "%s\n", __func__);
 
-	hcd = platform_get_drvdata (pdev);
+	hcd = platform_get_drvdata(pdev);
 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-	usb_hcd_poll_rh_status (hcd);
+	usb_hcd_poll_rh_status(hcd);
 	return 0;
 }
 
@@ -2608,11 +2598,11 @@ static struct platform_driver dummy_hcd_driver = {
 static struct platform_device *the_udc_pdev;
 static struct platform_device *the_hcd_pdev;
 
-static int __init init (void)
+static int __init init(void)
 {
 	int	retval = -ENOMEM;
 
-	if (usb_disabled ())
+	if (usb_disabled())
 		return -ENODEV;
 
 	if (!mod_data.is_high_speed && mod_data.is_super_speed)
@@ -2671,13 +2661,13 @@ err_alloc_udc:
 	platform_device_put(the_hcd_pdev);
 	return retval;
 }
-module_init (init);
+module_init(init);
 
-static void __exit cleanup (void)
+static void __exit cleanup(void)
 {
 	platform_device_unregister(the_udc_pdev);
 	platform_device_unregister(the_hcd_pdev);
 	platform_driver_unregister(&dummy_udc_driver);
 	platform_driver_unregister(&dummy_hcd_driver);
 }
-module_exit (cleanup);
+module_exit(cleanup);

From 54b8360ffd4c8b2c128ca25233b8c6876fb92d30 Mon Sep 17 00:00:00 2001
From: Michal Nazarewicz <mina86@mina86.com>
Date: Fri, 13 Jan 2012 15:05:16 +0100
Subject: [PATCH 20/53] usb: gadget: update Michal Nazarewicz's email address

The m.nazarewicz@samsung.com email address is no longer valid,
so this commit replaces it with mina86@mina86.com which is
employer-agnostic and thus should be valid for foreseeable
feature.

Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/f_acm.c          | 2 +-
 drivers/usb/gadget/f_fs.c           | 2 +-
 drivers/usb/gadget/f_mass_storage.c | 2 +-
 drivers/usb/gadget/f_rndis.c        | 2 +-
 drivers/usb/gadget/g_ffs.c          | 2 +-
 drivers/usb/gadget/mass_storage.c   | 2 +-
 drivers/usb/gadget/multi.c          | 2 +-
 drivers/usb/gadget/storage_common.c | 2 +-
 tools/usb/ffs-test.c                | 2 +-
 tools/usb/testusb.c                 | 2 +-
 10 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 3f8849339ade..e48212195466 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -5,7 +5,7 @@
  * Copyright (C) 2008 by David Brownell
  * Copyright (C) 2008 by Nokia Corporation
  * Copyright (C) 2009 by Samsung Electronics
- * Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
+ * Author: Michal Nazarewicz (mina86@mina86.com)
  *
  * This software is distributed under the terms of the GNU General
  * Public License ("GPL") as published by the Free Software Foundation,
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index f63dc6c150d2..7e2216f1bbe6 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -2,7 +2,7 @@
  * f_fs.c -- user mode file system API for USB composite function controllers
  *
  * Copyright (C) 2010 Samsung Electronics
- * Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
+ * Author: Michal Nazarewicz <mina86@mina86.com>
  *
  * Based on inode.c (GadgetFS) which was:
  * Copyright (C) 2003-2004 David Brownell
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 6353eca1e852..6cde0217a8da 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2003-2008 Alan Stern
  * Copyright (C) 2009 Samsung Electronics
- *                    Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
+ *                    Author: Michal Nazarewicz <mina86@mina86.com>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 704d1d94f72a..7b1cf18df5e3 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -5,7 +5,7 @@
  * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
  * Copyright (C) 2008 Nokia Corporation
  * Copyright (C) 2009 Samsung Electronics
- *                    Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
+ *                    Author: Michal Nazarewicz (mina86@mina86.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index 0519d77915ec..331cd6729d3c 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -2,7 +2,7 @@
  * g_ffs.c -- user mode file system API for USB composite function controllers
  *
  * Copyright (C) 2010 Samsung Electronics
- * Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
+ * Author: Michal Nazarewicz <mina86@mina86.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c
index e24f72f82a47..1f376eba31f6 100644
--- a/drivers/usb/gadget/mass_storage.c
+++ b/drivers/usb/gadget/mass_storage.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2003-2008 Alan Stern
  * Copyright (C) 2009 Samsung Electronics
- *                    Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
+ *                    Author: Michal Nazarewicz <mina86@mina86.com>
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index 7e7f515b8b19..c37fb33a3d1b 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -4,7 +4,7 @@
  * Copyright (C) 2008 David Brownell
  * Copyright (C) 2008 Nokia Corporation
  * Copyright (C) 2009 Samsung Electronics
- * Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
+ * Author: Michal Nazarewicz (mina86@mina86.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index c7f291a331df..9d450feaaeab 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2003-2008 Alan Stern
  * Copyeight (C) 2009 Samsung Electronics
- * Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
+ * Author: Michal Nazarewicz (mina86@mina86.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/tools/usb/ffs-test.c b/tools/usb/ffs-test.c
index b9c798631699..53452c35d5e1 100644
--- a/tools/usb/ffs-test.c
+++ b/tools/usb/ffs-test.c
@@ -2,7 +2,7 @@
  * ffs-test.c.c -- user mode filesystem api for usb composite function
  *
  * Copyright (C) 2010 Samsung Electronics
- *                    Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
+ *                    Author: Michal Nazarewicz <mina86@mina86.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/tools/usb/testusb.c b/tools/usb/testusb.c
index f08e89463842..6e0f56701e44 100644
--- a/tools/usb/testusb.c
+++ b/tools/usb/testusb.c
@@ -3,7 +3,7 @@
 /*
  * Copyright (c) 2002 by David Brownell
  * Copyright (c) 2010 by Samsung Electronics
- * Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
+ * Author: Michal Nazarewicz <mina86@mina86.com>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the

From fcc0bb5ace11e6d0a27bdbdbf2e5e6d361a4e701 Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Fri, 13 Jan 2012 21:54:46 +0100
Subject: [PATCH 21/53] usb: gadget: f_mass_storage: remove one FSG_NO_INTR_EP

Remove one define of FSG_NO_INTR_EP and we still have that we can use.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Acked-by: Michal Nazarewicz <mina86@mina86.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/f_mass_storage.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 6cde0217a8da..82462714582d 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -304,7 +304,6 @@
 
 static const char fsg_string_interface[] = "Mass Storage";
 
-#define FSG_NO_INTR_EP 1
 #define FSG_NO_DEVICE_STRINGS    1
 #define FSG_NO_OTG               1
 #define FSG_NO_INTR_EP           1

From d11519adc214c243ec606f186316f2667b677694 Mon Sep 17 00:00:00 2001
From: Praveena Nadahally <praveen.nadahally@stericsson.com>
Date: Wed, 25 Jan 2012 11:02:03 +0100
Subject: [PATCH 22/53] usb: gadget: Add Interface Association Descriptor to
 ECM

Add IAD to bind the two interfaces of ECM so that it works properly
in composite gadget mode.

Signed-off-by: Thirupathi <thirupathi.chippakurthy@stericsson.com>
Signed-off-by: Praveena Nadahally <praveen.nadahally@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/f_ecm.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
index 11c07cb7d337..30b908f2a53d 100644
--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/f_ecm.c
@@ -97,6 +97,20 @@ static inline unsigned ecm_bitrate(struct usb_gadget *g)
 
 /* interface descriptor: */
 
+static struct usb_interface_assoc_descriptor
+ecm_iad_descriptor = {
+	.bLength =		sizeof ecm_iad_descriptor,
+	.bDescriptorType =	USB_DT_INTERFACE_ASSOCIATION,
+
+	/* .bFirstInterface =	DYNAMIC, */
+	.bInterfaceCount =	2,	/* control + data */
+	.bFunctionClass =	USB_CLASS_COMM,
+	.bFunctionSubClass =	USB_CDC_SUBCLASS_ETHERNET,
+	.bFunctionProtocol =	USB_CDC_PROTO_NONE,
+	/* .iFunction =		DYNAMIC */
+};
+
+
 static struct usb_interface_descriptor ecm_control_intf = {
 	.bLength =		sizeof ecm_control_intf,
 	.bDescriptorType =	USB_DT_INTERFACE,
@@ -199,6 +213,7 @@ static struct usb_endpoint_descriptor fs_ecm_out_desc = {
 
 static struct usb_descriptor_header *ecm_fs_function[] = {
 	/* CDC ECM control descriptors */
+	(struct usb_descriptor_header *) &ecm_iad_descriptor,
 	(struct usb_descriptor_header *) &ecm_control_intf,
 	(struct usb_descriptor_header *) &ecm_header_desc,
 	(struct usb_descriptor_header *) &ecm_union_desc,
@@ -247,6 +262,7 @@ static struct usb_endpoint_descriptor hs_ecm_out_desc = {
 
 static struct usb_descriptor_header *ecm_hs_function[] = {
 	/* CDC ECM control descriptors */
+	(struct usb_descriptor_header *) &ecm_iad_descriptor,
 	(struct usb_descriptor_header *) &ecm_control_intf,
 	(struct usb_descriptor_header *) &ecm_header_desc,
 	(struct usb_descriptor_header *) &ecm_union_desc,
@@ -339,6 +355,7 @@ static struct usb_string ecm_string_defs[] = {
 	[0].s = "CDC Ethernet Control Model (ECM)",
 	[1].s = NULL /* DYNAMIC */,
 	[2].s = "CDC Ethernet Data",
+	[3].s = "CDC ECM",
 	{  } /* end of list */
 };
 
@@ -674,6 +691,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
 	if (status < 0)
 		goto fail;
 	ecm->ctrl_id = status;
+	ecm_iad_descriptor.bFirstInterface = status;
 
 	ecm_control_intf.bInterfaceNumber = status;
 	ecm_union_desc.bMasterInterface0 = status;
@@ -864,6 +882,13 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 			return status;
 		ecm_string_defs[1].id = status;
 		ecm_desc.iMACAddress = status;
+
+		/* IAD label */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		ecm_string_defs[3].id = status;
+		ecm_iad_descriptor.iFunction = status;
 	}
 
 	/* allocate and initialize one new instance */

From 3cf0ad02e42a91e85ffe9bd67422dd266531d3ec Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Wed, 25 Jan 2012 11:51:19 +0100
Subject: [PATCH 23/53] usb: gadget: dummy_hcd: don't assign ->desc on error
 case

If the stream check fails then we leave ep->desc assigend but we return
with an error code. The caller assumes the endpoint is not enabled
(which is the case) but it can not enable it again due to this
assigment.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/dummy_hcd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 67573e5f2a18..9170a4c7ced4 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -514,7 +514,6 @@ static int dummy_enable(struct usb_ep *_ep,
 	}
 
 	_ep->maxpacket = max;
-	ep->desc = desc;
 	if (usb_ss_max_streams(_ep->comp_desc)) {
 		if (!usb_endpoint_xfer_bulk(desc)) {
 			dev_err(udc_dev(dum), "Can't enable stream support on "
@@ -523,6 +522,7 @@ static int dummy_enable(struct usb_ep *_ep,
 		}
 		ep->stream_en = 1;
 	}
+	ep->desc = desc;
 
 	dev_dbg(udc_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d stream %s\n",
 		_ep->name,

From 20edfbb6a17f3007c1905e9849d8d306e318883b Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Wed, 25 Jan 2012 15:18:58 +0100
Subject: [PATCH 24/53] usb: gadget: dummy_hcd: fix null-deref free req

_ep to ep is a pointer substraction so ep won't be zero unless _ep was
8. This was not intendent by the author, it was probably a typo while
checking for NULL of the argument.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/dummy_hcd.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 9170a4c7ced4..8cc1a88d21e7 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -599,8 +599,10 @@ static void dummy_free_request(struct usb_ep *_ep, struct usb_request *_req)
 	struct dummy_ep		*ep;
 	struct dummy_request	*req;
 
+	if (!_ep || !_req)
+		return;
 	ep = usb_ep_to_dummy_ep(_ep);
-	if (!ep || !_req || (!ep->desc && _ep->name != ep0name))
+	if (!ep->desc && _ep->name != ep0name)
 		return;
 
 	req = usb_request_to_dummy_request(_req);

From dd63180b758d5972fc90621af0741d5bfae1a684 Mon Sep 17 00:00:00 2001
From: Tomoya MORINAGA <tomoya.rohm@gmail.com>
Date: Fri, 3 Feb 2012 16:35:26 +0900
Subject: [PATCH 25/53] usb: gadget: pch_udc: Detecting VBUS through GPIO

Problem:
 In USB Suspend, pch_udc handles 'disconnect'.

Root cause:
 The current pch_udc is not monitoring VBUS.
 When USB cable is disconnected, USB Device Controller generates
 an interrupt of USB Suspend.
 pch_udc cannot distinguish it is USB Suspend or disconnect.
 Therefore, pch_udc handles 'disconnect' after an interrupt of
 USB Suspend happend.

Solution:
 VBUS is detected through GPIO.
 After an interrupt produced USB Suspend, if VBUS is Low,
 pch_udc handles 'disconnect'.
 If VBUS is High, pch_udc handles 'suspend'.

Signed-off-by: Tomoya MORINAGA <tomoya.rohm@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/pch_udc.c | 145 ++++++++++++++++++++++++++++++++++-
 1 file changed, 142 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index 82416aae816f..9c5ae2c10147 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -15,6 +15,13 @@
 #include <linux/interrupt.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/gpio.h>
+
+/* GPIO port for VBUS detecting */
+static int vbus_gpio_port = -1;		/* GPIO port number (-1:Not used) */
+
+#define PCH_VBUS_PERIOD		3000	/* VBUS polling period (msec) */
+#define PCH_VBUS_INTERVAL	10	/* VBUS polling interval (msec) */
 
 /* Address offset of Registers */
 #define UDC_EP_REG_SHIFT	0x20	/* Offset to next EP */
@@ -295,6 +302,17 @@ struct pch_udc_ep {
 	unsigned long			epsts;
 };
 
+/**
+ * struct pch_vbus_gpio_data - Structure holding GPIO informaton
+ *					for detecting VBUS
+ * @port:		gpio port number
+ * @irq_work_fall	Structure for WorkQueue
+ */
+struct pch_vbus_gpio_data {
+	int			port;
+	struct work_struct	irq_work_fall;
+};
+
 /**
  * struct pch_udc_dev - Structure holding complete information
  *			of the PCH USB device
@@ -323,6 +341,7 @@ struct pch_udc_ep {
  * @base_addr:		for mapped device memory
  * @irq:		IRQ line for the device
  * @cfg_data:		current cfg, intf, and alt in use
+ * @vbus_gpio:		GPIO informaton for detecting VBUS
  */
 struct pch_udc_dev {
 	struct usb_gadget		gadget;
@@ -349,7 +368,8 @@ struct pch_udc_dev {
 	unsigned long			phys_addr;
 	void __iomem			*base_addr;
 	unsigned			irq;
-	struct pch_udc_cfg_data	cfg_data;
+	struct pch_udc_cfg_data		cfg_data;
+	struct pch_vbus_gpio_data	vbus_gpio;
 };
 
 #define PCH_UDC_PCI_BAR			1
@@ -1225,6 +1245,115 @@ static const struct usb_gadget_ops pch_udc_ops = {
 	.stop	= pch_udc_stop,
 };
 
+/**
+ * pch_vbus_gpio_get_value() - This API gets value of GPIO port as VBUS status.
+ * @dev:	Reference to the driver structure
+ *
+ * Return value:
+ *	1: VBUS is high
+ *	0: VBUS is low
+ *     -1: It is not enable to detect VBUS using GPIO
+ */
+static int pch_vbus_gpio_get_value(struct pch_udc_dev *dev)
+{
+	int vbus = 0;
+
+	if (dev->vbus_gpio.port)
+		vbus = gpio_get_value(dev->vbus_gpio.port) ? 1 : 0;
+	else
+		vbus = -1;
+
+	return vbus;
+}
+
+/**
+ * pch_vbus_gpio_work_fall() - This API keeps watch on VBUS becoming Low.
+ *                             If VBUS is Low, disconnect is processed
+ * @irq_work:	Structure for WorkQueue
+ *
+ */
+static void pch_vbus_gpio_work_fall(struct work_struct *irq_work)
+{
+	struct pch_vbus_gpio_data *vbus_gpio = container_of(irq_work,
+		struct pch_vbus_gpio_data, irq_work_fall);
+	struct pch_udc_dev *dev =
+		container_of(vbus_gpio, struct pch_udc_dev, vbus_gpio);
+	int vbus_saved = -1;
+	int vbus;
+	int count;
+
+	if (!dev->vbus_gpio.port)
+		return;
+
+	for (count = 0; count < (PCH_VBUS_PERIOD / PCH_VBUS_INTERVAL);
+		count++) {
+		vbus = pch_vbus_gpio_get_value(dev);
+
+		if ((vbus_saved == vbus) && (vbus == 0)) {
+			dev_dbg(&dev->pdev->dev, "VBUS fell");
+			if (dev->driver
+				&& dev->driver->disconnect) {
+				dev->driver->disconnect(
+					&dev->gadget);
+			}
+			pch_udc_reconnect(dev);
+			dev_dbg(&dev->pdev->dev, "VBUS fell");
+			return;
+		}
+		vbus_saved = vbus;
+		mdelay(PCH_VBUS_INTERVAL);
+	}
+}
+
+/**
+ * pch_vbus_gpio_init() - This API initializes GPIO port detecting VBUS.
+ * @dev:	Reference to the driver structure
+ * @vbus_gpio	Number of GPIO port to detect gpio
+ *
+ * Return codes:
+ *	0: Success
+ *	-EINVAL: GPIO port is invalid or can't be initialized.
+ */
+static int pch_vbus_gpio_init(struct pch_udc_dev *dev, int vbus_gpio_port)
+{
+	int err;
+
+	dev->vbus_gpio.port = 0;
+
+	if (vbus_gpio_port <= -1)
+		return -EINVAL;
+
+	err = gpio_is_valid(vbus_gpio_port);
+	if (!err) {
+		pr_err("%s: gpio port %d is invalid\n",
+			__func__, vbus_gpio_port);
+		return -EINVAL;
+	}
+
+	err = gpio_request(vbus_gpio_port, "pch_vbus");
+	if (err) {
+		pr_err("%s: can't request gpio port %d, err: %d\n",
+			__func__, vbus_gpio_port, err);
+		return -EINVAL;
+	}
+
+	dev->vbus_gpio.port = vbus_gpio_port;
+	gpio_direction_input(vbus_gpio_port);
+	INIT_WORK(&dev->vbus_gpio.irq_work_fall, pch_vbus_gpio_work_fall);
+
+	return 0;
+}
+
+/**
+ * pch_vbus_gpio_free() - This API frees resources of GPIO port
+ * @dev:	Reference to the driver structure
+ */
+static void pch_vbus_gpio_free(struct pch_udc_dev *dev)
+{
+	if (dev->vbus_gpio.port)
+		gpio_free(dev->vbus_gpio.port);
+}
+
 /**
  * complete_req() - This API is invoked from the driver when processing
  *			of a request is complete
@@ -2510,6 +2639,8 @@ static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev)
  */
 static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
 {
+	int vbus;
+
 	/* USB Reset Interrupt */
 	if (dev_intr & UDC_DEVINT_UR) {
 		pch_udc_svc_ur_interrupt(dev);
@@ -2535,14 +2666,19 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
 			spin_lock(&dev->lock);
 		}
 
-		if (dev->vbus_session == 0) {
+		vbus = pch_vbus_gpio_get_value(dev);
+		if ((dev->vbus_session == 0)
+			&& (vbus != 1)) {
 			if (dev->driver && dev->driver->disconnect) {
 				spin_unlock(&dev->lock);
 				dev->driver->disconnect(&dev->gadget);
 				spin_lock(&dev->lock);
 			}
 			pch_udc_reconnect(dev);
-		}
+		} else if ((dev->vbus_session == 0)
+			&& (vbus == 1))
+			schedule_work(&dev->vbus_gpio.irq_work_fall);
+
 		dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n");
 	}
 	/* Clear the SOF interrupt, if enabled */
@@ -2704,6 +2840,7 @@ static int pch_udc_pcd_init(struct pch_udc_dev *dev)
 {
 	pch_udc_init(dev);
 	pch_udc_pcd_reinit(dev);
+	pch_vbus_gpio_init(dev, vbus_gpio_port);
 	return 0;
 }
 
@@ -2882,6 +3019,8 @@ static void pch_udc_remove(struct pci_dev *pdev)
 				 UDC_EP0OUT_BUFF_SIZE * 4, DMA_FROM_DEVICE);
 	kfree(dev->ep0out_buf);
 
+	pch_vbus_gpio_free(dev);
+
 	pch_udc_exit(dev);
 
 	if (dev->irq_registered)

From 637b78eb31e0b167ed913f1750bb645dfeda38f0 Mon Sep 17 00:00:00 2001
From: Tomoya MORINAGA <tomoya.rohm@gmail.com>
Date: Fri, 3 Feb 2012 16:14:18 +0900
Subject: [PATCH 26/53] usb: gadget: pch_udc: Detecting VBUS through GPIO with
 interrupt

Problem:
 pch_udc continues operation even if VBUS becomes Low.
 pch_udc performs D+ pulling up before VBUS becomes High.
 USB device should be controlled according to VBUS state.

Root cause:
 The current pch_udc is not always monitoring VBUS.

Solution:
 The change of VBUS is detected using an interrupt of GPIO.
 If VBUS became Low, pch_udc handles 'disconnect'.
 After VBUS became High, a pull improves D+, and pch_udc
 handles 'connect'.

[ balbi@ti.com : make it actually compile ]

Signed-off-by: Tomoya MORINAGA <tomoya.rohm@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/pch_udc.c | 87 ++++++++++++++++++++++++++++++++++--
 1 file changed, 83 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index 9c5ae2c10147..a992084d3890 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -306,11 +306,15 @@ struct pch_udc_ep {
  * struct pch_vbus_gpio_data - Structure holding GPIO informaton
  *					for detecting VBUS
  * @port:		gpio port number
+ * @intr:		gpio interrupt number
  * @irq_work_fall	Structure for WorkQueue
+ * @irq_work_rise	Structure for WorkQueue
  */
 struct pch_vbus_gpio_data {
 	int			port;
+	int			intr;
 	struct work_struct	irq_work_fall;
+	struct work_struct	irq_work_rise;
 };
 
 /**
@@ -1296,8 +1300,10 @@ static void pch_vbus_gpio_work_fall(struct work_struct *irq_work)
 				dev->driver->disconnect(
 					&dev->gadget);
 			}
-			pch_udc_reconnect(dev);
-			dev_dbg(&dev->pdev->dev, "VBUS fell");
+			if (dev->vbus_gpio.intr)
+				pch_udc_init(dev);
+			else
+				pch_udc_reconnect(dev);
 			return;
 		}
 		vbus_saved = vbus;
@@ -1305,6 +1311,57 @@ static void pch_vbus_gpio_work_fall(struct work_struct *irq_work)
 	}
 }
 
+/**
+ * pch_vbus_gpio_work_rise() - This API checks VBUS is High.
+ *                             If VBUS is High, connect is processed
+ * @irq_work:	Structure for WorkQueue
+ *
+ */
+static void pch_vbus_gpio_work_rise(struct work_struct *irq_work)
+{
+	struct pch_vbus_gpio_data *vbus_gpio = container_of(irq_work,
+		struct pch_vbus_gpio_data, irq_work_rise);
+	struct pch_udc_dev *dev =
+		container_of(vbus_gpio, struct pch_udc_dev, vbus_gpio);
+	int vbus;
+
+	if (!dev->vbus_gpio.port)
+		return;
+
+	mdelay(PCH_VBUS_INTERVAL);
+	vbus = pch_vbus_gpio_get_value(dev);
+
+	if (vbus == 1) {
+		dev_dbg(&dev->pdev->dev, "VBUS rose");
+		pch_udc_reconnect(dev);
+		return;
+	}
+}
+
+/**
+ * pch_vbus_gpio_irq() - IRQ handler for GPIO intrerrupt for changing VBUS
+ * @irq:	Interrupt request number
+ * @dev:	Reference to the device structure
+ *
+ * Return codes:
+ *	0: Success
+ *	-EINVAL: GPIO port is invalid or can't be initialized.
+ */
+static irqreturn_t pch_vbus_gpio_irq(int irq, void *data)
+{
+	struct pch_udc_dev *dev = (struct pch_udc_dev *)data;
+
+	if (!dev->vbus_gpio.port || !dev->vbus_gpio.intr)
+		return IRQ_NONE;
+
+	if (pch_vbus_gpio_get_value(dev))
+		schedule_work(&dev->vbus_gpio.irq_work_rise);
+	else
+		schedule_work(&dev->vbus_gpio.irq_work_fall);
+
+	return IRQ_HANDLED;
+}
+
 /**
  * pch_vbus_gpio_init() - This API initializes GPIO port detecting VBUS.
  * @dev:	Reference to the driver structure
@@ -1317,8 +1374,10 @@ static void pch_vbus_gpio_work_fall(struct work_struct *irq_work)
 static int pch_vbus_gpio_init(struct pch_udc_dev *dev, int vbus_gpio_port)
 {
 	int err;
+	int irq_num = 0;
 
 	dev->vbus_gpio.port = 0;
+	dev->vbus_gpio.intr = 0;
 
 	if (vbus_gpio_port <= -1)
 		return -EINVAL;
@@ -1341,6 +1400,21 @@ static int pch_vbus_gpio_init(struct pch_udc_dev *dev, int vbus_gpio_port)
 	gpio_direction_input(vbus_gpio_port);
 	INIT_WORK(&dev->vbus_gpio.irq_work_fall, pch_vbus_gpio_work_fall);
 
+	irq_num = gpio_to_irq(vbus_gpio_port);
+	if (irq_num > 0) {
+		irq_set_irq_type(irq_num, IRQ_TYPE_EDGE_BOTH);
+		err = request_irq(irq_num, pch_vbus_gpio_irq, 0,
+			"vbus_detect", dev);
+		if (!err) {
+			dev->vbus_gpio.intr = irq_num;
+			INIT_WORK(&dev->vbus_gpio.irq_work_rise,
+				pch_vbus_gpio_work_rise);
+		} else {
+			pr_err("%s: can't request irq %d, err: %d\n",
+				__func__, irq_num, err);
+		}
+	}
+
 	return 0;
 }
 
@@ -1350,6 +1424,9 @@ static int pch_vbus_gpio_init(struct pch_udc_dev *dev, int vbus_gpio_port)
  */
 static void pch_vbus_gpio_free(struct pch_udc_dev *dev)
 {
+	if (dev->vbus_gpio.intr)
+		free_irq(dev->vbus_gpio.intr, dev);
+
 	if (dev->vbus_gpio.port)
 		gpio_free(dev->vbus_gpio.port);
 }
@@ -2676,7 +2753,8 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
 			}
 			pch_udc_reconnect(dev);
 		} else if ((dev->vbus_session == 0)
-			&& (vbus == 1))
+			&& (vbus == 1)
+			&& !dev->vbus_gpio.intr)
 			schedule_work(&dev->vbus_gpio.irq_work_fall);
 
 		dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n");
@@ -2941,7 +3019,8 @@ static int pch_udc_start(struct usb_gadget_driver *driver,
 	pch_udc_setup_ep0(dev);
 
 	/* clear SD */
-	pch_udc_clear_disconnect(dev);
+	if ((pch_vbus_gpio_get_value(dev) != 0) || !dev->vbus_gpio.intr)
+		pch_udc_clear_disconnect(dev);
 
 	dev->connected = 1;
 	return 0;

From 609ca228073ae06c5513474d2cdf0af7ee5766ec Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Mon, 6 Feb 2012 18:46:35 +0100
Subject: [PATCH 27/53] usb: gadget: clean the ep in autoconf before returning
 it.

Since commit 72c973dd aka ("usb: gadget: add usb_endpoint_descriptor to
struct usb_ep) the descriptor is part of the ep. Most gadgets like
g_zero or masstorage call config_ep_by_speed() to grab an available
endpoint which may be used for FS/HS/SS bulk/iso/intr and in a second
they assign the proper descriptor by calling config_ep_by_speed(). This
is good so far. A few of them like ncm call config_ep_by_speed() only if
ep->desc not assigned earlier. That means ep->desc is never assigned if
the endpoint was used by another gadget before it was removed.

Some of those gadgets also assign ep->driver_data to NULL on reset or
ep_disable part _but_ keep a reference to this endpoint. At ep_enable
time they assign driver_data to their private data. This probably needs
a clean up of its own.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/epautoconf.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 753aa0683ac1..f59f7e367b5a 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -275,24 +275,24 @@ struct usb_ep *usb_ep_autoconfig_ss(
 		/* ep-e, ep-f are PIO with only 64 byte fifos */
 		ep = find_ep (gadget, "ep-e");
 		if (ep && ep_matches(gadget, ep, desc, ep_comp))
-			return ep;
+			goto found_ep;
 		ep = find_ep (gadget, "ep-f");
 		if (ep && ep_matches(gadget, ep, desc, ep_comp))
-			return ep;
+			goto found_ep;
 
 	} else if (gadget_is_goku (gadget)) {
 		if (USB_ENDPOINT_XFER_INT == type) {
 			/* single buffering is enough */
 			ep = find_ep(gadget, "ep3-bulk");
 			if (ep && ep_matches(gadget, ep, desc, ep_comp))
-				return ep;
+				goto found_ep;
 		} else if (USB_ENDPOINT_XFER_BULK == type
 				&& (USB_DIR_IN & desc->bEndpointAddress)) {
 			/* DMA may be available */
 			ep = find_ep(gadget, "ep2-bulk");
 			if (ep && ep_matches(gadget, ep, desc,
 					      ep_comp))
-				return ep;
+				goto found_ep;
 		}
 
 #ifdef CONFIG_BLACKFIN
@@ -311,18 +311,22 @@ struct usb_ep *usb_ep_autoconfig_ss(
 		} else
 			ep = NULL;
 		if (ep && ep_matches(gadget, ep, desc, ep_comp))
-			return ep;
+			goto found_ep;
 #endif
 	}
 
 	/* Second, look at endpoints until an unclaimed one looks usable */
 	list_for_each_entry (ep, &gadget->ep_list, ep_list) {
 		if (ep_matches(gadget, ep, desc, ep_comp))
-			return ep;
+			goto found_ep;
 	}
 
 	/* Fail */
 	return NULL;
+found_ep:
+	ep->desc = NULL;
+	ep->comp_desc = NULL;
+	return ep;
 }
 
 /**

From 6fecfb05c077586ba85aa6f52f10abf30a4bfb40 Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Mon, 6 Feb 2012 18:46:36 +0100
Subject: [PATCH 28/53] usb: gadget: add usb3.0 descriptors to serial gadgets

This patch adds SS descriptors to the ACM & generic serial gadget. The
ACM part was tested with minicom + dummy + send / receive files over
ttyACM <=> ttyGS0.
The generic serial part (f_serial) was not tested (haven't found a
driver on the host side).
The nokia & multi gadget use HS at most.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/f_acm.c    | 50 +++++++++++++++++++++++++++++++++++
 drivers/usb/gadget/f_serial.c | 42 +++++++++++++++++++++++++++++
 drivers/usb/gadget/serial.c   |  2 +-
 3 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index e48212195466..d672250a61fa 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -237,6 +237,42 @@ static struct usb_descriptor_header *acm_hs_function[] = {
 	NULL,
 };
 
+static struct usb_endpoint_descriptor acm_ss_in_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+static struct usb_endpoint_descriptor acm_ss_out_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor acm_ss_bulk_comp_desc = {
+	.bLength =              sizeof acm_ss_bulk_comp_desc,
+	.bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
+};
+
+static struct usb_descriptor_header *acm_ss_function[] = {
+	(struct usb_descriptor_header *) &acm_iad_descriptor,
+	(struct usb_descriptor_header *) &acm_control_interface_desc,
+	(struct usb_descriptor_header *) &acm_header_desc,
+	(struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
+	(struct usb_descriptor_header *) &acm_descriptor,
+	(struct usb_descriptor_header *) &acm_union_desc,
+	(struct usb_descriptor_header *) &acm_hs_notify_desc,
+	(struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
+	(struct usb_descriptor_header *) &acm_data_interface_desc,
+	(struct usb_descriptor_header *) &acm_ss_in_desc,
+	(struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
+	(struct usb_descriptor_header *) &acm_ss_out_desc,
+	(struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
+	NULL,
+};
+
 /* string descriptors: */
 
 #define ACM_CTRL_IDX	0
@@ -643,9 +679,21 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
 		/* copy descriptors */
 		f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
 	}
+	if (gadget_is_superspeed(c->cdev->gadget)) {
+		acm_ss_in_desc.bEndpointAddress =
+			acm_fs_in_desc.bEndpointAddress;
+		acm_ss_out_desc.bEndpointAddress =
+			acm_fs_out_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->ss_descriptors = usb_copy_descriptors(acm_ss_function);
+		if (!f->ss_descriptors)
+			goto fail;
+	}
 
 	DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
 			acm->port_num,
+			gadget_is_superspeed(c->cdev->gadget) ? "super" :
 			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
 			acm->port.in->name, acm->port.out->name,
 			acm->notify->name);
@@ -675,6 +723,8 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f)
 
 	if (gadget_is_dualspeed(c->cdev->gadget))
 		usb_free_descriptors(f->hs_descriptors);
+	if (gadget_is_superspeed(c->cdev->gadget))
+		usb_free_descriptors(f->ss_descriptors);
 	usb_free_descriptors(f->descriptors);
 	gs_free_req(acm->notify, acm->notify_req);
 	kfree(acm);
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
index cf33a8d0fd5d..07197d63d9b1 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -99,6 +99,34 @@ static struct usb_descriptor_header *gser_hs_function[] __initdata = {
 	NULL,
 };
 
+static struct usb_endpoint_descriptor gser_ss_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+static struct usb_endpoint_descriptor gser_ss_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc __initdata = {
+	.bLength =              sizeof gser_ss_bulk_comp_desc,
+	.bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
+};
+
+static struct usb_descriptor_header *gser_ss_function[] __initdata = {
+	(struct usb_descriptor_header *) &gser_interface_desc,
+	(struct usb_descriptor_header *) &gser_ss_in_desc,
+	(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
+	(struct usb_descriptor_header *) &gser_ss_out_desc,
+	(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
+	NULL,
+};
+
 /* string descriptors: */
 
 static struct usb_string gser_string_defs[] = {
@@ -201,9 +229,21 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)
 		/* copy descriptors, and track endpoint copies */
 		f->hs_descriptors = usb_copy_descriptors(gser_hs_function);
 	}
+	if (gadget_is_superspeed(c->cdev->gadget)) {
+		gser_ss_in_desc.bEndpointAddress =
+			gser_fs_in_desc.bEndpointAddress;
+		gser_ss_out_desc.bEndpointAddress =
+			gser_fs_out_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->ss_descriptors = usb_copy_descriptors(gser_ss_function);
+		if (!f->ss_descriptors)
+			goto fail;
+	}
 
 	DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
 			gser->port_num,
+			gadget_is_superspeed(c->cdev->gadget) ? "super" :
 			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
 			gser->port.in->name, gser->port.out->name);
 	return 0;
@@ -225,6 +265,8 @@ gser_unbind(struct usb_configuration *c, struct usb_function *f)
 {
 	if (gadget_is_dualspeed(c->cdev->gadget))
 		usb_free_descriptors(f->hs_descriptors);
+	if (gadget_is_superspeed(c->cdev->gadget))
+		usb_free_descriptors(f->ss_descriptors);
 	usb_free_descriptors(f->descriptors);
 	kfree(func_to_gser(f));
 }
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index ad9e5b2df642..665c07422c26 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -242,7 +242,7 @@ static struct usb_composite_driver gserial_driver = {
 	.name		= "g_serial",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
-	.max_speed	= USB_SPEED_HIGH,
+	.max_speed	= USB_SPEED_SUPER,
 };
 
 static int __init init(void)

From d5261286949fc9ada701c7e30bf89e08a6dbf4de Mon Sep 17 00:00:00 2001
From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Date: Tue, 14 Feb 2012 11:37:17 +0100
Subject: [PATCH 29/53] usb: renesas_usbhs: (cosmetic) simplify list operations

list.h already provide helpers to find the first entry and to move list
nodes to the tail of another list. This patch simply uses those helpers,
no functional changes.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/renesas_usbhs/fifo.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index 03a9cc529c82..fb2a88c5c210 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -76,8 +76,7 @@ void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
 		pipe->handler = &usbhsf_null_handler;
 	}
 
-	list_del_init(&pkt->node);
-	list_add_tail(&pkt->node, &pipe->list);
+	list_move_tail(&pkt->node, &pipe->list);
 
 	/*
 	 * each pkt must hold own handler.
@@ -107,7 +106,7 @@ static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe)
 	if (list_empty(&pipe->list))
 		return NULL;
 
-	return list_entry(pipe->list.next, struct usbhs_pkt, node);
+	return list_first_entry(&pipe->list, struct usbhs_pkt, node);
 }
 
 struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt)

From 6e4b74e4690dd03b5664fa4895c3db0607d64742 Mon Sep 17 00:00:00 2001
From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Date: Tue, 14 Feb 2012 11:37:21 +0100
Subject: [PATCH 30/53] usb: renesas: fix scheduling in atomic context bug

The current renesas_usbhs driver triggers

BUG: scheduling while atomic: ksoftirqd/0/3/0x00000102

with enabled CONFIG_DEBUG_ATOMIC_SLEEP, by submitting DMA transfers from
an atomic (tasklet) context, which is not supported by the shdma dmaengine
driver. Fix it by switching to a work.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/renesas_usbhs/fifo.c | 18 ++++++------------
 drivers/usb/renesas_usbhs/fifo.h |  3 ++-
 2 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index fb2a88c5c210..3648c82a17fe 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -765,9 +765,9 @@ static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
 }
 
 static void usbhsf_dma_complete(void *arg);
-static void usbhsf_dma_prepare_tasklet(unsigned long data)
+static void xfer_work(struct work_struct *work)
 {
-	struct usbhs_pkt *pkt = (struct usbhs_pkt *)data;
+	struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work);
 	struct usbhs_pipe *pipe = pkt->pipe;
 	struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe);
 	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
@@ -847,11 +847,8 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
 
 	pkt->trans = len;
 
-	tasklet_init(&fifo->tasklet,
-		     usbhsf_dma_prepare_tasklet,
-		     (unsigned long)pkt);
-
-	tasklet_schedule(&fifo->tasklet);
+	INIT_WORK(&pkt->work, xfer_work);
+	schedule_work(&pkt->work);
 
 	return 0;
 
@@ -941,11 +938,8 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done)
 
 	pkt->trans = len;
 
-	tasklet_init(&fifo->tasklet,
-		     usbhsf_dma_prepare_tasklet,
-		     (unsigned long)pkt);
-
-	tasklet_schedule(&fifo->tasklet);
+	INIT_WORK(&pkt->work, xfer_work);
+	schedule_work(&pkt->work);
 
 	return 0;
 
diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h
index f68609c0f489..c31731a843d1 100644
--- a/drivers/usb/renesas_usbhs/fifo.h
+++ b/drivers/usb/renesas_usbhs/fifo.h
@@ -19,6 +19,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/sh_dma.h>
+#include <linux/workqueue.h>
 #include <asm/dma.h>
 #include "pipe.h"
 
@@ -31,7 +32,6 @@ struct usbhs_fifo {
 	u32 ctr;	/* xFIFOCTR */
 
 	struct usbhs_pipe	*pipe;
-	struct tasklet_struct	tasklet;
 
 	struct dma_chan		*tx_chan;
 	struct dma_chan		*rx_chan;
@@ -53,6 +53,7 @@ struct usbhs_pkt {
 	struct usbhs_pkt_handle *handler;
 	void (*done)(struct usbhs_priv *priv,
 		     struct usbhs_pkt *pkt);
+	struct work_struct work;
 	dma_addr_t dma;
 	void *buf;
 	int length;

From 18b5b3b55f44c28a0380f3559d1db3c467f94b4a Mon Sep 17 00:00:00 2001
From: Jassi Brar <jaswinder.singh@linaro.org>
Date: Thu, 2 Feb 2012 21:59:53 +0530
Subject: [PATCH 31/53] usb: gadget: Rename audio function to uac1

The extant USB-Audio function driver complies to UAC_1 spec.
So name the files accordingly, paving way for inclusion of
a new UAC_2 specified driver.

Signed-off-by: Yadi Brar <yadi.brar01@gmail.com>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/audio.c                 | 6 +++---
 drivers/usb/gadget/{f_audio.c => f_uac1.c} | 2 +-
 drivers/usb/gadget/{u_audio.c => u_uac1.c} | 4 ++--
 drivers/usb/gadget/{u_audio.h => u_uac1.h} | 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)
 rename drivers/usb/gadget/{f_audio.c => f_uac1.c} (99%)
 rename drivers/usb/gadget/{u_audio.c => u_uac1.c} (99%)
 rename drivers/usb/gadget/{u_audio.h => u_uac1.h} (94%)

diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c
index 9d89ae4765a9..056a2d936d7f 100644
--- a/drivers/usb/gadget/audio.c
+++ b/drivers/usb/gadget/audio.c
@@ -14,7 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/utsname.h>
 
-#include "u_audio.h"
+#include "u_uac1.h"
 
 #define DRIVER_DESC		"Linux USB Audio Gadget"
 #define DRIVER_VERSION		"Dec 18, 2008"
@@ -33,8 +33,8 @@
 #include "config.c"
 #include "epautoconf.c"
 
-#include "u_audio.c"
-#include "f_audio.c"
+#include "u_uac1.c"
+#include "f_uac1.c"
 
 /*-------------------------------------------------------------------------*/
 
diff --git a/drivers/usb/gadget/f_audio.c b/drivers/usb/gadget/f_uac1.c
similarity index 99%
rename from drivers/usb/gadget/f_audio.c
rename to drivers/usb/gadget/f_uac1.c
index ec7ffcd0d0cd..e4c060fd81e4 100644
--- a/drivers/usb/gadget/f_audio.c
+++ b/drivers/usb/gadget/f_uac1.c
@@ -14,7 +14,7 @@
 #include <linux/device.h>
 #include <linux/atomic.h>
 
-#include "u_audio.h"
+#include "u_uac1.h"
 
 #define OUT_EP_MAX_PACKET_SIZE	200
 static int req_buf_size = OUT_EP_MAX_PACKET_SIZE;
diff --git a/drivers/usb/gadget/u_audio.c b/drivers/usb/gadget/u_uac1.c
similarity index 99%
rename from drivers/usb/gadget/u_audio.c
rename to drivers/usb/gadget/u_uac1.c
index 59ffe1ecf1c9..af9898982059 100644
--- a/drivers/usb/gadget/u_audio.c
+++ b/drivers/usb/gadget/u_uac1.c
@@ -1,5 +1,5 @@
 /*
- * u_audio.c -- ALSA audio utilities for Gadget stack
+ * u_uac1.c -- ALSA audio utilities for Gadget stack
  *
  * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
  * Copyright (C) 2008 Analog Devices, Inc
@@ -17,7 +17,7 @@
 #include <linux/random.h>
 #include <linux/syscalls.h>
 
-#include "u_audio.h"
+#include "u_uac1.h"
 
 /*
  * This component encapsulates the ALSA devices for USB audio gadget
diff --git a/drivers/usb/gadget/u_audio.h b/drivers/usb/gadget/u_uac1.h
similarity index 94%
rename from drivers/usb/gadget/u_audio.h
rename to drivers/usb/gadget/u_uac1.h
index 08ffce3298e6..18c2e729faf6 100644
--- a/drivers/usb/gadget/u_audio.h
+++ b/drivers/usb/gadget/u_uac1.h
@@ -1,5 +1,5 @@
 /*
- * u_audio.h -- interface to USB gadget "ALSA AUDIO" utilities
+ * u_uac1.h -- interface to USB gadget "ALSA AUDIO" utilities
  *
  * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
  * Copyright (C) 2008 Analog Devices, Inc

From 0d4e1b2a7eb7f4db8b3dc1c7ef4b507040f87ded Mon Sep 17 00:00:00 2001
From: Jassi Brar <jaswinder.singh@linaro.org>
Date: Thu, 2 Feb 2012 22:00:48 +0530
Subject: [PATCH 32/53] usb: uac2: Add ACHeader and FormatType descriptor

Add missing, but needed, ACHeader and FormatType descriptor definitions.

Signed-off-by: Yadi Brar <yadi.brar01@gmail.com>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 include/linux/usb/audio-v2.h | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/include/linux/usb/audio-v2.h b/include/linux/usb/audio-v2.h
index 964cb603f7c7..ed13053153f4 100644
--- a/include/linux/usb/audio-v2.h
+++ b/include/linux/usb/audio-v2.h
@@ -43,6 +43,27 @@ static inline bool uac2_control_is_writeable(u32 bmControls, u8 control)
 	return (bmControls >> (control * 2)) & 0x2;
 }
 
+/* 4.7.2 Class-Specific AC Interface Descriptor */
+struct uac2_ac_header_descriptor {
+	__u8  bLength;			/* 9 */
+	__u8  bDescriptorType;		/* USB_DT_CS_INTERFACE */
+	__u8  bDescriptorSubtype;	/* UAC_MS_HEADER */
+	__le16 bcdADC;			/* 0x0200 */
+	__u8  bCategory;
+	__le16 wTotalLength;		/* includes Unit and Terminal desc. */
+	__u8  bmControls;
+} __packed;
+
+/* 2.3.1.6 Type I Format Type Descriptor (Frmts20 final.pdf)*/
+struct uac2_format_type_i_descriptor {
+	__u8  bLength;			/* in bytes: 6 */
+	__u8  bDescriptorType;		/* USB_DT_CS_INTERFACE */
+	__u8  bDescriptorSubtype;	/* FORMAT_TYPE */
+	__u8  bFormatType;		/* FORMAT_TYPE_1 */
+	__u8  bSubslotSize;		/* {1,2,3,4} */
+	__u8  bBitResolution;
+} __packed;
+
 /* 4.7.2.1 Clock Source Descriptor */
 
 struct uac_clock_source_descriptor {

From d747a916872241daef68c864ef09f8bef0c35bf8 Mon Sep 17 00:00:00 2001
From: Jassi Brar <jaswinder.singh@linaro.org>
Date: Thu, 2 Feb 2012 22:01:12 +0530
Subject: [PATCH 33/53] usb: gadget: audio: Move string IDs to audio.c

Move manufacturer and product string ids into audio.c so
as to be reusable by the new uac2 version of gadget driver.

Signed-off-by: Yadi Brar <yadi.brar01@gmail.com>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/audio.c  | 23 +++++++++++++++++++++++
 drivers/usb/gadget/f_uac1.c | 23 -----------------------
 2 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c
index 056a2d936d7f..33e9327d6639 100644
--- a/drivers/usb/gadget/audio.c
+++ b/drivers/usb/gadget/audio.c
@@ -33,6 +33,29 @@
 #include "config.c"
 #include "epautoconf.c"
 
+/* string IDs are assigned dynamically */
+
+#define STRING_MANUFACTURER_IDX		0
+#define STRING_PRODUCT_IDX		1
+
+static char manufacturer[50];
+
+static struct usb_string strings_dev[] = {
+	[STRING_MANUFACTURER_IDX].s = manufacturer,
+	[STRING_PRODUCT_IDX].s = DRIVER_DESC,
+	{  } /* end of list */
+};
+
+static struct usb_gadget_strings stringtab_dev = {
+	.language = 0x0409,	/* en-us */
+	.strings = strings_dev,
+};
+
+static struct usb_gadget_strings *audio_strings[] = {
+	&stringtab_dev,
+	NULL,
+};
+
 #include "u_uac1.c"
 #include "f_uac1.c"
 
diff --git a/drivers/usb/gadget/f_uac1.c b/drivers/usb/gadget/f_uac1.c
index e4c060fd81e4..1a5dcd5565e3 100644
--- a/drivers/usb/gadget/f_uac1.c
+++ b/drivers/usb/gadget/f_uac1.c
@@ -216,29 +216,6 @@ static struct usb_descriptor_header *f_audio_desc[] __initdata = {
 	NULL,
 };
 
-/* string IDs are assigned dynamically */
-
-#define STRING_MANUFACTURER_IDX		0
-#define STRING_PRODUCT_IDX		1
-
-static char manufacturer[50];
-
-static struct usb_string strings_dev[] = {
-	[STRING_MANUFACTURER_IDX].s = manufacturer,
-	[STRING_PRODUCT_IDX].s = DRIVER_DESC,
-	{  } /* end of list */
-};
-
-static struct usb_gadget_strings stringtab_dev = {
-	.language	= 0x0409,	/* en-us */
-	.strings	= strings_dev,
-};
-
-static struct usb_gadget_strings *audio_strings[] = {
-	&stringtab_dev,
-	NULL,
-};
-
 /*
  * This function is an ALSA sound card following USB Audio Class Spec 1.0.
  */

From 132fcb460839a876f5bc8b71bede60f8d0875757 Mon Sep 17 00:00:00 2001
From: Jassi Brar <jaswinder.singh@linaro.org>
Date: Thu, 2 Feb 2012 22:01:34 +0530
Subject: [PATCH 34/53] usb: gadget: Add Audio Class 2.0 Driver

This is a flexible USB Audio Class 2.0 compliant gadget driver that
implements a simple topology with a virtual sound card exposed at
the function side.

The driver doesn't expect any real audio codec to be present on the
function - the audio streams are simply sinked to and sourced from a
virtual ALSA sound card created. The user-space application may choose
to do whatever it wants with the data received from the USB Host and
choose to provide whatever it wants as audio data to the USB Host.

Capture(USB-Out) and Playback(USB-In) can be run at independent
configurations specified via module parameters while loading the driver.

Make this new version as the default selection by a new Kconfig choice.

Signed-off-by: Yadi Brar <yadi.brar01@gmail.com>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/Kconfig  |   25 +-
 drivers/usb/gadget/audio.c  |   20 +-
 drivers/usb/gadget/f_uac2.c | 1449 +++++++++++++++++++++++++++++++++++
 3 files changed, 1485 insertions(+), 9 deletions(-)
 create mode 100644 drivers/usb/gadget/f_uac2.c

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 7ecb68a67411..1623b5204da4 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -599,16 +599,29 @@ config USB_AUDIO
 	depends on SND
 	select SND_PCM
 	help
-	  Gadget Audio is compatible with USB Audio Class specification 1.0.
-	  It will include at least one AudioControl interface, zero or more
-	  AudioStream interface and zero or more MIDIStream interface.
-
-	  Gadget Audio will use on-board ALSA (CONFIG_SND) audio card to
-	  playback or capture audio stream.
+	  This Gadget Audio driver is compatible with USB Audio Class
+	  specification 2.0. It implements 1 AudioControl interface,
+	  1 AudioStreaming Interface each for USB-OUT and USB-IN.
+	  Number of channels, sample rate and sample size can be
+	  specified as module parameters.
+	  This driver doesn't expect any real Audio codec to be present
+	  on the device - the audio streams are simply sinked to and
+	  sourced from a virtual ALSA sound card created. The user-space
+	  application may choose to do whatever it wants with the data
+	  received from the USB Host and choose to provide whatever it
+	  wants as audio data to the USB Host.
 
 	  Say "y" to link the driver statically, or "m" to build a
 	  dynamically linked module called "g_audio".
 
+config GADGET_UAC1
+	bool "UAC 1.0 (Legacy)"
+	depends on USB_AUDIO
+	help
+	  If you instead want older UAC Spec-1.0 driver that also has audio
+	  paths hardwired to the Audio codec chip on-board and doesn't work
+	  without one.
+
 config USB_ETH
 	tristate "Ethernet Gadget (with CDC Ethernet support)"
 	depends on NET
diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c
index 33e9327d6639..98899244860e 100644
--- a/drivers/usb/gadget/audio.c
+++ b/drivers/usb/gadget/audio.c
@@ -14,10 +14,8 @@
 #include <linux/kernel.h>
 #include <linux/utsname.h>
 
-#include "u_uac1.h"
-
 #define DRIVER_DESC		"Linux USB Audio Gadget"
-#define DRIVER_VERSION		"Dec 18, 2008"
+#define DRIVER_VERSION		"Feb 2, 2012"
 
 /*-------------------------------------------------------------------------*/
 
@@ -56,8 +54,13 @@ static struct usb_gadget_strings *audio_strings[] = {
 	NULL,
 };
 
+#ifdef CONFIG_GADGET_UAC1
+#include "u_uac1.h"
 #include "u_uac1.c"
 #include "f_uac1.c"
+#else
+#include "f_uac2.c"
+#endif
 
 /*-------------------------------------------------------------------------*/
 
@@ -77,9 +80,15 @@ static struct usb_device_descriptor device_desc = {
 
 	.bcdUSB =		__constant_cpu_to_le16(0x200),
 
+#ifdef CONFIG_GADGET_UAC1
 	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
 	.bDeviceSubClass =	0,
 	.bDeviceProtocol =	0,
+#else
+	.bDeviceClass =		USB_CLASS_MISC,
+	.bDeviceSubClass =	0x02,
+	.bDeviceProtocol =	0x01,
+#endif
 	/* .bMaxPacketSize0 = f(hardware) */
 
 	/* Vendor and product id defaults change according to what configs
@@ -131,6 +140,9 @@ static struct usb_configuration audio_config_driver = {
 	.bConfigurationValue	= 1,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
+#ifndef CONFIG_GADGET_UAC1
+	.unbind			= uac2_unbind_config,
+#endif
 };
 
 /*-------------------------------------------------------------------------*/
@@ -180,7 +192,9 @@ fail:
 
 static int __exit audio_unbind(struct usb_composite_dev *cdev)
 {
+#ifdef CONFIG_GADGET_UAC1
 	gaudio_cleanup();
+#endif
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/f_uac2.c
new file mode 100644
index 000000000000..e7cc4de93e33
--- /dev/null
+++ b/drivers/usb/gadget/f_uac2.c
@@ -0,0 +1,1449 @@
+/*
+ * f_uac2.c -- USB Audio Class 2.0 Function
+ *
+ * Copyright (C) 2011
+ *    Yadwinder Singh (yadi.brar01@gmail.com)
+ *    Jaswinder Singh (jaswinder.singh@linaro.org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/usb/audio.h>
+#include <linux/usb/audio-v2.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+/* Playback(USB-IN) Default Stereo - Fl/Fr */
+static int p_chmask = 0x3;
+module_param(p_chmask, uint, S_IRUGO);
+MODULE_PARM_DESC(p_chmask, "Playback Channel Mask");
+
+/* Playback Default 48 KHz */
+static int p_srate = 48000;
+module_param(p_srate, uint, S_IRUGO);
+MODULE_PARM_DESC(p_srate, "Playback Sampling Rate");
+
+/* Playback Default 16bits/sample */
+static int p_ssize = 2;
+module_param(p_ssize, uint, S_IRUGO);
+MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)");
+
+/* Capture(USB-OUT) Default Stereo - Fl/Fr */
+static int c_chmask = 0x3;
+module_param(c_chmask, uint, S_IRUGO);
+MODULE_PARM_DESC(c_chmask, "Capture Channel Mask");
+
+/* Capture Default 64 KHz */
+static int c_srate = 64000;
+module_param(c_srate, uint, S_IRUGO);
+MODULE_PARM_DESC(c_srate, "Capture Sampling Rate");
+
+/* Capture Default 16bits/sample */
+static int c_ssize = 2;
+module_param(c_ssize, uint, S_IRUGO);
+MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
+
+#define DMA_ADDR_INVALID	(~(dma_addr_t)0)
+
+#define ALT_SET(x, a)	do {(x) &= ~0xff; (x) |= (a); } while (0)
+#define ALT_GET(x)	((x) & 0xff)
+#define INTF_SET(x, i)	do {(x) &= 0xff; (x) |= ((i) << 8); } while (0)
+#define INTF_GET(x)	((x >> 8) & 0xff)
+
+/* Keep everyone on toes */
+#define USB_XFERS	2
+
+/*
+ * The driver implements a simple UAC_2 topology.
+ * USB-OUT -> IT_1 -> OT_3 -> ALSA_Capture
+ * ALSA_Playback -> IT_2 -> OT_4 -> USB-IN
+ * Capture and Playback sampling rates are independently
+ *  controlled by two clock sources :
+ *    CLK_5 := c_srate, and CLK_6 := p_srate
+ */
+#define USB_OUT_IT_ID	1
+#define IO_IN_IT_ID	2
+#define IO_OUT_OT_ID	3
+#define USB_IN_OT_ID	4
+#define USB_OUT_CLK_ID	5
+#define USB_IN_CLK_ID	6
+
+#define CONTROL_ABSENT	0
+#define CONTROL_RDONLY	1
+#define CONTROL_RDWR	3
+
+#define CLK_FREQ_CTRL	0
+#define CLK_VLD_CTRL	2
+
+#define COPY_CTRL	0
+#define CONN_CTRL	2
+#define OVRLD_CTRL	4
+#define CLSTR_CTRL	6
+#define UNFLW_CTRL	8
+#define OVFLW_CTRL	10
+
+const char *uac2_name = "snd_uac2";
+
+struct uac2_req {
+	struct uac2_rtd_params *pp; /* parent param */
+	struct usb_request *req;
+};
+
+struct uac2_rtd_params {
+	bool ep_enabled; /* if the ep is enabled */
+	/* Size of the ring buffer */
+	size_t dma_bytes;
+	unsigned char *dma_area;
+
+	struct snd_pcm_substream *ss;
+
+	/* Ring buffer */
+	ssize_t hw_ptr;
+
+	void *rbuf;
+
+	size_t period_size;
+
+	unsigned max_psize;
+	struct uac2_req ureq[USB_XFERS];
+
+	spinlock_t lock;
+};
+
+struct snd_uac2_chip {
+	struct platform_device pdev;
+	struct platform_driver pdrv;
+
+	struct uac2_rtd_params p_prm;
+	struct uac2_rtd_params c_prm;
+
+	struct snd_card *card;
+	struct snd_pcm *pcm;
+};
+
+#define BUFF_SIZE_MAX	(PAGE_SIZE * 16)
+#define PRD_SIZE_MAX	PAGE_SIZE
+#define MIN_PERIODS	4
+
+static struct snd_pcm_hardware uac2_pcm_hardware = {
+	.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER
+		 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
+		 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+	.rates = SNDRV_PCM_RATE_CONTINUOUS,
+	.periods_max = BUFF_SIZE_MAX / PRD_SIZE_MAX,
+	.buffer_bytes_max = BUFF_SIZE_MAX,
+	.period_bytes_max = PRD_SIZE_MAX,
+	.periods_min = MIN_PERIODS,
+};
+
+struct audio_dev {
+	/* Currently active {Interface[15:8] | AltSettings[7:0]} */
+	__u16 ac_alt, as_out_alt, as_in_alt;
+
+	struct usb_ep *in_ep, *out_ep;
+	struct usb_function func;
+
+	/* The ALSA Sound Card it represents on the USB-Client side */
+	struct snd_uac2_chip uac2;
+};
+
+static struct audio_dev *agdev_g;
+
+static inline
+struct audio_dev *func_to_agdev(struct usb_function *f)
+{
+	return container_of(f, struct audio_dev, func);
+}
+
+static inline
+struct audio_dev *uac2_to_agdev(struct snd_uac2_chip *u)
+{
+	return container_of(u, struct audio_dev, uac2);
+}
+
+static inline
+struct snd_uac2_chip *pdev_to_uac2(struct platform_device *p)
+{
+	return container_of(p, struct snd_uac2_chip, pdev);
+}
+
+static inline
+struct snd_uac2_chip *prm_to_uac2(struct uac2_rtd_params *r)
+{
+	struct snd_uac2_chip *uac2 = container_of(r,
+					struct snd_uac2_chip, c_prm);
+
+	if (&uac2->c_prm != r)
+		uac2 = container_of(r, struct snd_uac2_chip, p_prm);
+
+	return uac2;
+}
+
+static inline
+uint num_channels(uint chanmask)
+{
+	uint num = 0;
+
+	while (chanmask) {
+		num += (chanmask & 1);
+		chanmask >>= 1;
+	}
+
+	return num;
+}
+
+static void
+agdev_iso_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	unsigned pending;
+	unsigned long flags;
+	bool update_alsa = false;
+	unsigned char *src, *dst;
+	int status = req->status;
+	struct uac2_req *ur = req->context;
+	struct snd_pcm_substream *substream;
+	struct uac2_rtd_params *prm = ur->pp;
+	struct snd_uac2_chip *uac2 = prm_to_uac2(prm);
+
+	/* i/f shutting down */
+	if (!prm->ep_enabled)
+		return;
+
+	/*
+	 * We can't really do much about bad xfers.
+	 * Afterall, the ISOCH xfers could fail legitimately.
+	 */
+	if (status)
+		pr_debug("%s: iso_complete status(%d) %d/%d\n",
+			__func__, status, req->actual, req->length);
+
+	substream = prm->ss;
+
+	/* Do nothing if ALSA isn't active */
+	if (!substream)
+		goto exit;
+
+	spin_lock_irqsave(&prm->lock, flags);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		src = prm->dma_area + prm->hw_ptr;
+		req->actual = req->length;
+		dst = req->buf;
+	} else {
+		dst = prm->dma_area + prm->hw_ptr;
+		src = req->buf;
+	}
+
+	pending = prm->hw_ptr % prm->period_size;
+	pending += req->actual;
+	if (pending >= prm->period_size)
+		update_alsa = true;
+
+	prm->hw_ptr = (prm->hw_ptr + req->actual) % prm->dma_bytes;
+
+	spin_unlock_irqrestore(&prm->lock, flags);
+
+	/* Pack USB load in ALSA ring buffer */
+	memcpy(dst, src, req->actual);
+exit:
+	if (usb_ep_queue(ep, req, GFP_ATOMIC))
+		dev_err(&uac2->pdev.dev, "%d Error!\n", __LINE__);
+
+	if (update_alsa)
+		snd_pcm_period_elapsed(substream);
+
+	return;
+}
+
+static int
+uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
+	struct audio_dev *agdev = uac2_to_agdev(uac2);
+	struct uac2_rtd_params *prm;
+	unsigned long flags;
+	struct usb_ep *ep;
+	int err = 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		ep = agdev->in_ep;
+		prm = &uac2->p_prm;
+	} else {
+		ep = agdev->out_ep;
+		prm = &uac2->c_prm;
+	}
+
+	spin_lock_irqsave(&prm->lock, flags);
+
+	/* Reset */
+	prm->hw_ptr = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		prm->ss = substream;
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		prm->ss = NULL;
+		break;
+	default:
+		err = -EINVAL;
+	}
+
+	spin_unlock_irqrestore(&prm->lock, flags);
+
+	/* Clear buffer after Play stops */
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !prm->ss)
+		memset(prm->rbuf, 0, prm->max_psize * USB_XFERS);
+
+	return err;
+}
+
+static snd_pcm_uframes_t uac2_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
+	struct uac2_rtd_params *prm;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		prm = &uac2->p_prm;
+	else
+		prm = &uac2->c_prm;
+
+	return bytes_to_frames(substream->runtime, prm->hw_ptr);
+}
+
+static int uac2_pcm_hw_params(struct snd_pcm_substream *substream,
+			       struct snd_pcm_hw_params *hw_params)
+{
+	struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
+	struct uac2_rtd_params *prm;
+	int err;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		prm = &uac2->p_prm;
+	else
+		prm = &uac2->c_prm;
+
+	err = snd_pcm_lib_malloc_pages(substream,
+					params_buffer_bytes(hw_params));
+	if (err >= 0) {
+		prm->dma_bytes = substream->runtime->dma_bytes;
+		prm->dma_area = substream->runtime->dma_area;
+		prm->period_size = params_period_bytes(hw_params);
+	}
+
+	return err;
+}
+
+static int uac2_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
+	struct uac2_rtd_params *prm;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		prm = &uac2->p_prm;
+	else
+		prm = &uac2->c_prm;
+
+	prm->dma_area = NULL;
+	prm->dma_bytes = 0;
+	prm->period_size = 0;
+
+	return snd_pcm_lib_free_pages(substream);
+}
+
+static int uac2_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	runtime->hw = uac2_pcm_hardware;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		spin_lock_init(&uac2->p_prm.lock);
+		runtime->hw.rate_min = p_srate;
+		runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; /* ! p_ssize ! */
+		runtime->hw.channels_min = num_channels(p_chmask);
+		runtime->hw.period_bytes_min = 2 * uac2->p_prm.max_psize
+						/ runtime->hw.periods_min;
+	} else {
+		spin_lock_init(&uac2->c_prm.lock);
+		runtime->hw.rate_min = c_srate;
+		runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; /* ! c_ssize ! */
+		runtime->hw.channels_min = num_channels(c_chmask);
+		runtime->hw.period_bytes_min = 2 * uac2->c_prm.max_psize
+						/ runtime->hw.periods_min;
+	}
+
+	runtime->hw.rate_max = runtime->hw.rate_min;
+	runtime->hw.channels_max = runtime->hw.channels_min;
+
+	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+
+	return 0;
+}
+
+/* ALSA cries without these function pointers */
+static int uac2_pcm_null(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+static struct snd_pcm_ops uac2_pcm_ops = {
+	.open = uac2_pcm_open,
+	.close = uac2_pcm_null,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = uac2_pcm_hw_params,
+	.hw_free = uac2_pcm_hw_free,
+	.trigger = uac2_pcm_trigger,
+	.pointer = uac2_pcm_pointer,
+	.prepare = uac2_pcm_null,
+};
+
+static int __devinit snd_uac2_probe(struct platform_device *pdev)
+{
+	struct snd_uac2_chip *uac2 = pdev_to_uac2(pdev);
+	struct snd_card *card;
+	struct snd_pcm *pcm;
+	int err;
+
+	/* Choose any slot, with no id */
+	err = snd_card_create(-1, NULL, THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
+
+	uac2->card = card;
+
+	/*
+	 * Create first PCM device
+	 * Create a substream only for non-zero channel streams
+	 */
+	err = snd_pcm_new(uac2->card, "UAC2 PCM", 0,
+			       p_chmask ? 1 : 0, c_chmask ? 1 : 0, &pcm);
+	if (err < 0)
+		goto snd_fail;
+
+	strcpy(pcm->name, "UAC2 PCM");
+	pcm->private_data = uac2;
+
+	uac2->pcm = pcm;
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac2_pcm_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac2_pcm_ops);
+
+	strcpy(card->driver, "UAC2_Gadget");
+	strcpy(card->shortname, "UAC2_Gadget");
+	sprintf(card->longname, "UAC2_Gadget %i", pdev->id);
+
+	snd_card_set_dev(card, &pdev->dev);
+
+	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+		snd_dma_continuous_data(GFP_KERNEL), 0, BUFF_SIZE_MAX);
+
+	err = snd_card_register(card);
+	if (!err) {
+		platform_set_drvdata(pdev, card);
+		return 0;
+	}
+
+snd_fail:
+	snd_card_free(card);
+
+	uac2->pcm = NULL;
+	uac2->card = NULL;
+
+	return err;
+}
+
+static int __devexit snd_uac2_remove(struct platform_device *pdev)
+{
+	struct snd_card *card = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (card)
+		return snd_card_free(card);
+
+	return 0;
+}
+
+static int alsa_uac2_init(struct audio_dev *agdev)
+{
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+	int err;
+
+	uac2->pdrv.probe = snd_uac2_probe;
+	uac2->pdrv.remove = snd_uac2_remove;
+	uac2->pdrv.driver.name = uac2_name;
+
+	uac2->pdev.id = 0;
+	uac2->pdev.name = uac2_name;
+
+	/* Register snd_uac2 driver */
+	err = platform_driver_register(&uac2->pdrv);
+	if (err)
+		return err;
+
+	/* Register snd_uac2 device */
+	err = platform_device_register(&uac2->pdev);
+	if (err)
+		platform_driver_unregister(&uac2->pdrv);
+
+	return err;
+}
+
+static void alsa_uac2_exit(struct audio_dev *agdev)
+{
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+
+	platform_driver_unregister(&uac2->pdrv);
+	platform_device_unregister(&uac2->pdev);
+}
+
+
+/* --------- USB Function Interface ------------- */
+
+enum {
+	STR_ASSOC,
+	STR_IF_CTRL,
+	STR_CLKSRC_IN,
+	STR_CLKSRC_OUT,
+	STR_USB_IT,
+	STR_IO_IT,
+	STR_USB_OT,
+	STR_IO_OT,
+	STR_AS_OUT_ALT0,
+	STR_AS_OUT_ALT1,
+	STR_AS_IN_ALT0,
+	STR_AS_IN_ALT1,
+};
+
+static const char ifassoc[] = "Source/Sink";
+static const char ifctrl[] = "Topology Control";
+static char clksrc_in[8];
+static char clksrc_out[8];
+static const char usb_it[] = "USBH Out";
+static const char io_it[] = "USBD Out";
+static const char usb_ot[] = "USBH In";
+static const char io_ot[] = "USBD In";
+static const char out_alt0[] = "Playback Inactive";
+static const char out_alt1[] = "Playback Active";
+static const char in_alt0[] = "Capture Inactive";
+static const char in_alt1[] = "Capture Active";
+
+static struct usb_string strings_fn[] = {
+	[STR_ASSOC].s = ifassoc,
+	[STR_IF_CTRL].s = ifctrl,
+	[STR_CLKSRC_IN].s = clksrc_in,
+	[STR_CLKSRC_OUT].s = clksrc_out,
+	[STR_USB_IT].s = usb_it,
+	[STR_IO_IT].s = io_it,
+	[STR_USB_OT].s = usb_ot,
+	[STR_IO_OT].s = io_ot,
+	[STR_AS_OUT_ALT0].s = out_alt0,
+	[STR_AS_OUT_ALT1].s = out_alt1,
+	[STR_AS_IN_ALT0].s = in_alt0,
+	[STR_AS_IN_ALT1].s = in_alt1,
+	{ },
+};
+
+static struct usb_gadget_strings str_fn = {
+	.language = 0x0409,	/* en-us */
+	.strings = strings_fn,
+};
+
+static struct usb_gadget_strings *fn_strings[] = {
+	&str_fn,
+	NULL,
+};
+
+static struct usb_qualifier_descriptor devqual_desc = {
+	.bLength = sizeof devqual_desc,
+	.bDescriptorType = USB_DT_DEVICE_QUALIFIER,
+
+	.bcdUSB = cpu_to_le16(0x200),
+	.bDeviceClass = USB_CLASS_MISC,
+	.bDeviceSubClass = 0x02,
+	.bDeviceProtocol = 0x01,
+	.bNumConfigurations = 1,
+	.bRESERVED = 0,
+};
+
+static struct usb_interface_assoc_descriptor iad_desc = {
+	.bLength = sizeof iad_desc,
+	.bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
+
+	.bFirstInterface = 0,
+	.bInterfaceCount = 3,
+	.bFunctionClass = USB_CLASS_AUDIO,
+	.bFunctionSubClass = UAC2_FUNCTION_SUBCLASS_UNDEFINED,
+	.bFunctionProtocol = UAC_VERSION_2,
+};
+
+/* Audio Control Interface */
+static struct usb_interface_descriptor std_ac_if_desc = {
+	.bLength = sizeof std_ac_if_desc,
+	.bDescriptorType = USB_DT_INTERFACE,
+
+	.bAlternateSetting = 0,
+	.bNumEndpoints = 0,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+	.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
+	.bInterfaceProtocol = UAC_VERSION_2,
+};
+
+/* Clock source for IN traffic */
+struct uac_clock_source_descriptor in_clk_src_desc = {
+	.bLength = sizeof in_clk_src_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC2_CLOCK_SOURCE,
+	.bClockID = USB_IN_CLK_ID,
+	.bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED,
+	.bmControls = (CONTROL_RDONLY << CLK_FREQ_CTRL),
+	.bAssocTerminal = 0,
+};
+
+/* Clock source for OUT traffic */
+struct uac_clock_source_descriptor out_clk_src_desc = {
+	.bLength = sizeof out_clk_src_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC2_CLOCK_SOURCE,
+	.bClockID = USB_OUT_CLK_ID,
+	.bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED,
+	.bmControls = (CONTROL_RDONLY << CLK_FREQ_CTRL),
+	.bAssocTerminal = 0,
+};
+
+/* Input Terminal for USB_OUT */
+struct uac2_input_terminal_descriptor usb_out_it_desc = {
+	.bLength = sizeof usb_out_it_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC_INPUT_TERMINAL,
+	.bTerminalID = USB_OUT_IT_ID,
+	.wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING),
+	.bAssocTerminal = 0,
+	.bCSourceID = USB_OUT_CLK_ID,
+	.iChannelNames = 0,
+	.bmControls = (CONTROL_RDWR << COPY_CTRL),
+};
+
+/* Input Terminal for I/O-In */
+struct uac2_input_terminal_descriptor io_in_it_desc = {
+	.bLength = sizeof io_in_it_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC_INPUT_TERMINAL,
+	.bTerminalID = IO_IN_IT_ID,
+	.wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_UNDEFINED),
+	.bAssocTerminal = 0,
+	.bCSourceID = USB_IN_CLK_ID,
+	.iChannelNames = 0,
+	.bmControls = (CONTROL_RDWR << COPY_CTRL),
+};
+
+/* Ouput Terminal for USB_IN */
+struct uac2_output_terminal_descriptor usb_in_ot_desc = {
+	.bLength = sizeof usb_in_ot_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
+	.bTerminalID = USB_IN_OT_ID,
+	.wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING),
+	.bAssocTerminal = 0,
+	.bSourceID = IO_IN_IT_ID,
+	.bCSourceID = USB_IN_CLK_ID,
+	.bmControls = (CONTROL_RDWR << COPY_CTRL),
+};
+
+/* Ouput Terminal for I/O-Out */
+struct uac2_output_terminal_descriptor io_out_ot_desc = {
+	.bLength = sizeof io_out_ot_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
+	.bTerminalID = IO_OUT_OT_ID,
+	.wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_UNDEFINED),
+	.bAssocTerminal = 0,
+	.bSourceID = USB_OUT_IT_ID,
+	.bCSourceID = USB_OUT_CLK_ID,
+	.bmControls = (CONTROL_RDWR << COPY_CTRL),
+};
+
+struct uac2_ac_header_descriptor ac_hdr_desc = {
+	.bLength = sizeof ac_hdr_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC_MS_HEADER,
+	.bcdADC = cpu_to_le16(0x200),
+	.bCategory = UAC2_FUNCTION_IO_BOX,
+	.wTotalLength = sizeof in_clk_src_desc + sizeof out_clk_src_desc
+			 + sizeof usb_out_it_desc + sizeof io_in_it_desc
+			+ sizeof usb_in_ot_desc + sizeof io_out_ot_desc,
+	.bmControls = 0,
+};
+
+/* Audio Streaming OUT Interface - Alt0 */
+static struct usb_interface_descriptor std_as_out_if0_desc = {
+	.bLength = sizeof std_as_out_if0_desc,
+	.bDescriptorType = USB_DT_INTERFACE,
+
+	.bAlternateSetting = 0,
+	.bNumEndpoints = 0,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+	.bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+	.bInterfaceProtocol = UAC_VERSION_2,
+};
+
+/* Audio Streaming OUT Interface - Alt1 */
+static struct usb_interface_descriptor std_as_out_if1_desc = {
+	.bLength = sizeof std_as_out_if1_desc,
+	.bDescriptorType = USB_DT_INTERFACE,
+
+	.bAlternateSetting = 1,
+	.bNumEndpoints = 1,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+	.bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+	.bInterfaceProtocol = UAC_VERSION_2,
+};
+
+/* Audio Stream OUT Intface Desc */
+struct uac2_as_header_descriptor as_out_hdr_desc = {
+	.bLength = sizeof as_out_hdr_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC_AS_GENERAL,
+	.bTerminalLink = USB_OUT_IT_ID,
+	.bmControls = 0,
+	.bFormatType = UAC_FORMAT_TYPE_I,
+	.bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM),
+	.iChannelNames = 0,
+};
+
+/* Audio USB_OUT Format */
+struct uac2_format_type_i_descriptor as_out_fmt1_desc = {
+	.bLength = sizeof as_out_fmt1_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+	.bDescriptorSubtype = UAC_FORMAT_TYPE,
+	.bFormatType = UAC_FORMAT_TYPE_I,
+};
+
+/* STD AS ISO OUT Endpoint */
+struct usb_endpoint_descriptor fs_epout_desc = {
+	.bLength = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType = USB_DT_ENDPOINT,
+
+	.bEndpointAddress = USB_DIR_OUT,
+	.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
+	.bInterval = 1,
+};
+
+struct usb_endpoint_descriptor hs_epout_desc = {
+	.bLength = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType = USB_DT_ENDPOINT,
+
+	.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
+	.bInterval = 4,
+};
+
+/* CS AS ISO OUT Endpoint */
+static struct uac2_iso_endpoint_descriptor as_iso_out_desc = {
+	.bLength = sizeof as_iso_out_desc,
+	.bDescriptorType = USB_DT_CS_ENDPOINT,
+
+	.bDescriptorSubtype = UAC_EP_GENERAL,
+	.bmAttributes = 0,
+	.bmControls = 0,
+	.bLockDelayUnits = 0,
+	.wLockDelay = 0,
+};
+
+/* Audio Streaming IN Interface - Alt0 */
+static struct usb_interface_descriptor std_as_in_if0_desc = {
+	.bLength = sizeof std_as_in_if0_desc,
+	.bDescriptorType = USB_DT_INTERFACE,
+
+	.bAlternateSetting = 0,
+	.bNumEndpoints = 0,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+	.bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+	.bInterfaceProtocol = UAC_VERSION_2,
+};
+
+/* Audio Streaming IN Interface - Alt1 */
+static struct usb_interface_descriptor std_as_in_if1_desc = {
+	.bLength = sizeof std_as_in_if1_desc,
+	.bDescriptorType = USB_DT_INTERFACE,
+
+	.bAlternateSetting = 1,
+	.bNumEndpoints = 1,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+	.bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+	.bInterfaceProtocol = UAC_VERSION_2,
+};
+
+/* Audio Stream IN Intface Desc */
+struct uac2_as_header_descriptor as_in_hdr_desc = {
+	.bLength = sizeof as_in_hdr_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC_AS_GENERAL,
+	.bTerminalLink = USB_IN_OT_ID,
+	.bmControls = 0,
+	.bFormatType = UAC_FORMAT_TYPE_I,
+	.bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM),
+	.iChannelNames = 0,
+};
+
+/* Audio USB_IN Format */
+struct uac2_format_type_i_descriptor as_in_fmt1_desc = {
+	.bLength = sizeof as_in_fmt1_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+	.bDescriptorSubtype = UAC_FORMAT_TYPE,
+	.bFormatType = UAC_FORMAT_TYPE_I,
+};
+
+/* STD AS ISO IN Endpoint */
+struct usb_endpoint_descriptor fs_epin_desc = {
+	.bLength = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType = USB_DT_ENDPOINT,
+
+	.bEndpointAddress = USB_DIR_IN,
+	.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
+	.bInterval = 1,
+};
+
+struct usb_endpoint_descriptor hs_epin_desc = {
+	.bLength = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType = USB_DT_ENDPOINT,
+
+	.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
+	.bInterval = 4,
+};
+
+/* CS AS ISO IN Endpoint */
+static struct uac2_iso_endpoint_descriptor as_iso_in_desc = {
+	.bLength = sizeof as_iso_in_desc,
+	.bDescriptorType = USB_DT_CS_ENDPOINT,
+
+	.bDescriptorSubtype = UAC_EP_GENERAL,
+	.bmAttributes = 0,
+	.bmControls = 0,
+	.bLockDelayUnits = 0,
+	.wLockDelay = 0,
+};
+
+static struct usb_descriptor_header *fs_audio_desc[] = {
+	(struct usb_descriptor_header *)&iad_desc,
+	(struct usb_descriptor_header *)&std_ac_if_desc,
+
+	(struct usb_descriptor_header *)&ac_hdr_desc,
+	(struct usb_descriptor_header *)&in_clk_src_desc,
+	(struct usb_descriptor_header *)&out_clk_src_desc,
+	(struct usb_descriptor_header *)&usb_out_it_desc,
+	(struct usb_descriptor_header *)&io_in_it_desc,
+	(struct usb_descriptor_header *)&usb_in_ot_desc,
+	(struct usb_descriptor_header *)&io_out_ot_desc,
+
+	(struct usb_descriptor_header *)&std_as_out_if0_desc,
+	(struct usb_descriptor_header *)&std_as_out_if1_desc,
+
+	(struct usb_descriptor_header *)&as_out_hdr_desc,
+	(struct usb_descriptor_header *)&as_out_fmt1_desc,
+	(struct usb_descriptor_header *)&fs_epout_desc,
+	(struct usb_descriptor_header *)&as_iso_out_desc,
+
+	(struct usb_descriptor_header *)&std_as_in_if0_desc,
+	(struct usb_descriptor_header *)&std_as_in_if1_desc,
+
+	(struct usb_descriptor_header *)&as_in_hdr_desc,
+	(struct usb_descriptor_header *)&as_in_fmt1_desc,
+	(struct usb_descriptor_header *)&fs_epin_desc,
+	(struct usb_descriptor_header *)&as_iso_in_desc,
+	NULL,
+};
+
+static struct usb_descriptor_header *hs_audio_desc[] = {
+	(struct usb_descriptor_header *)&iad_desc,
+	(struct usb_descriptor_header *)&std_ac_if_desc,
+
+	(struct usb_descriptor_header *)&ac_hdr_desc,
+	(struct usb_descriptor_header *)&in_clk_src_desc,
+	(struct usb_descriptor_header *)&out_clk_src_desc,
+	(struct usb_descriptor_header *)&usb_out_it_desc,
+	(struct usb_descriptor_header *)&io_in_it_desc,
+	(struct usb_descriptor_header *)&usb_in_ot_desc,
+	(struct usb_descriptor_header *)&io_out_ot_desc,
+
+	(struct usb_descriptor_header *)&std_as_out_if0_desc,
+	(struct usb_descriptor_header *)&std_as_out_if1_desc,
+
+	(struct usb_descriptor_header *)&as_out_hdr_desc,
+	(struct usb_descriptor_header *)&as_out_fmt1_desc,
+	(struct usb_descriptor_header *)&hs_epout_desc,
+	(struct usb_descriptor_header *)&as_iso_out_desc,
+
+	(struct usb_descriptor_header *)&std_as_in_if0_desc,
+	(struct usb_descriptor_header *)&std_as_in_if1_desc,
+
+	(struct usb_descriptor_header *)&as_in_hdr_desc,
+	(struct usb_descriptor_header *)&as_in_fmt1_desc,
+	(struct usb_descriptor_header *)&hs_epin_desc,
+	(struct usb_descriptor_header *)&as_iso_in_desc,
+	NULL,
+};
+
+struct cntrl_cur_lay3 {
+	__u32	dCUR;
+};
+
+struct cntrl_range_lay3 {
+	__u16	wNumSubRanges;
+	__u32	dMIN;
+	__u32	dMAX;
+	__u32	dRES;
+} __packed;
+
+static inline void
+free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep)
+{
+	struct snd_uac2_chip *uac2 = prm_to_uac2(prm);
+	int i;
+
+	prm->ep_enabled = false;
+
+	for (i = 0; i < USB_XFERS; i++) {
+		if (prm->ureq[i].req) {
+			usb_ep_dequeue(ep, prm->ureq[i].req);
+			usb_ep_free_request(ep, prm->ureq[i].req);
+			prm->ureq[i].req = NULL;
+		}
+	}
+
+	if (usb_ep_disable(ep))
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+}
+
+static int __init
+afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
+{
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+	struct usb_composite_dev *cdev = cfg->cdev;
+	struct usb_gadget *gadget = cdev->gadget;
+	struct uac2_rtd_params *prm;
+	int ret;
+
+	ret = usb_interface_id(cfg, fn);
+	if (ret < 0) {
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+		return ret;
+	}
+	std_ac_if_desc.bInterfaceNumber = ret;
+	ALT_SET(agdev->ac_alt, 0);
+	INTF_SET(agdev->ac_alt, ret);
+
+	ret = usb_interface_id(cfg, fn);
+	if (ret < 0) {
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+		return ret;
+	}
+	std_as_out_if0_desc.bInterfaceNumber = ret;
+	std_as_out_if1_desc.bInterfaceNumber = ret;
+	ALT_SET(agdev->as_out_alt, 0);
+	INTF_SET(agdev->as_out_alt, ret);
+
+	ret = usb_interface_id(cfg, fn);
+	if (ret < 0) {
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+		return ret;
+	}
+	std_as_in_if0_desc.bInterfaceNumber = ret;
+	std_as_in_if1_desc.bInterfaceNumber = ret;
+	ALT_SET(agdev->as_in_alt, 0);
+	INTF_SET(agdev->as_in_alt, ret);
+
+	agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
+	if (!agdev->out_ep)
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+	agdev->out_ep->driver_data = agdev;
+
+	agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc);
+	if (!agdev->in_ep)
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+	agdev->in_ep->driver_data = agdev;
+
+	hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
+	hs_epout_desc.wMaxPacketSize = fs_epout_desc.wMaxPacketSize;
+	hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
+	hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize;
+
+	fn->descriptors = usb_copy_descriptors(fs_audio_desc);
+	if (gadget_is_dualspeed(gadget))
+		fn->hs_descriptors = usb_copy_descriptors(hs_audio_desc);
+
+	prm = &agdev->uac2.c_prm;
+	prm->max_psize = hs_epout_desc.wMaxPacketSize;
+	prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
+	if (!prm->rbuf) {
+		prm->max_psize = 0;
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+	}
+
+	prm = &agdev->uac2.p_prm;
+	prm->max_psize = hs_epin_desc.wMaxPacketSize;
+	prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
+	if (!prm->rbuf) {
+		prm->max_psize = 0;
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+	}
+
+	return alsa_uac2_init(agdev);
+}
+
+static void
+afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn)
+{
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct usb_composite_dev *cdev = cfg->cdev;
+	struct usb_gadget *gadget = cdev->gadget;
+	struct uac2_rtd_params *prm;
+
+	alsa_uac2_exit(agdev);
+
+	prm = &agdev->uac2.p_prm;
+	kfree(prm->rbuf);
+
+	prm = &agdev->uac2.c_prm;
+	kfree(prm->rbuf);
+
+	if (gadget_is_dualspeed(gadget))
+		usb_free_descriptors(fn->hs_descriptors);
+	usb_free_descriptors(fn->descriptors);
+
+	if (agdev->in_ep)
+		agdev->in_ep->driver_data = NULL;
+	if (agdev->out_ep)
+		agdev->out_ep->driver_data = NULL;
+}
+
+static int
+afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
+{
+	struct usb_composite_dev *cdev = fn->config->cdev;
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+	struct usb_gadget *gadget = cdev->gadget;
+	struct usb_request *req;
+	struct usb_ep *ep;
+	struct uac2_rtd_params *prm;
+	int i;
+
+	/* No i/f has more than 2 alt settings */
+	if (alt > 1) {
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	if (intf == INTF_GET(agdev->ac_alt)) {
+		/* Control I/f has only 1 AltSetting - 0 */
+		if (alt) {
+			dev_err(&uac2->pdev.dev,
+				"%s:%d Error!\n", __func__, __LINE__);
+			return -EINVAL;
+		}
+		return 0;
+	}
+
+	if (intf == INTF_GET(agdev->as_out_alt)) {
+		ep = agdev->out_ep;
+		prm = &uac2->c_prm;
+		config_ep_by_speed(gadget, fn, ep);
+		ALT_SET(agdev->as_out_alt, alt);
+	} else if (intf == INTF_GET(agdev->as_in_alt)) {
+		ep = agdev->in_ep;
+		prm = &uac2->p_prm;
+		config_ep_by_speed(gadget, fn, ep);
+		ALT_SET(agdev->as_in_alt, alt);
+	} else {
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	if (alt == 0) {
+		free_ep(prm, ep);
+		return 0;
+	}
+
+	prm->ep_enabled = true;
+	usb_ep_enable(ep);
+
+	for (i = 0; i < USB_XFERS; i++) {
+		if (prm->ureq[i].req) {
+			if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC))
+				dev_err(&uac2->pdev.dev, "%d Error!\n",
+					__LINE__);
+			continue;
+		}
+
+		req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+		if (req == NULL) {
+			dev_err(&uac2->pdev.dev,
+				"%s:%d Error!\n", __func__, __LINE__);
+			return -EINVAL;
+		}
+
+		prm->ureq[i].req = req;
+		prm->ureq[i].pp = prm;
+
+		req->zero = 0;
+		req->dma = DMA_ADDR_INVALID;
+		req->context = &prm->ureq[i];
+		req->length = prm->max_psize;
+		req->complete =	agdev_iso_complete;
+		req->buf = prm->rbuf + i * req->length;
+
+		if (usb_ep_queue(ep, req, GFP_ATOMIC))
+			dev_err(&uac2->pdev.dev, "%d Error!\n", __LINE__);
+	}
+
+	return 0;
+}
+
+static int
+afunc_get_alt(struct usb_function *fn, unsigned intf)
+{
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+
+	if (intf == INTF_GET(agdev->ac_alt))
+		return ALT_GET(agdev->ac_alt);
+	else if (intf == INTF_GET(agdev->as_out_alt))
+		return ALT_GET(agdev->as_out_alt);
+	else if (intf == INTF_GET(agdev->as_in_alt))
+		return ALT_GET(agdev->as_in_alt);
+	else
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Invalid Interface %d!\n",
+			__func__, __LINE__, intf);
+
+	return -EINVAL;
+}
+
+static void
+afunc_disable(struct usb_function *fn)
+{
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+
+	free_ep(&uac2->p_prm, agdev->in_ep);
+	ALT_SET(agdev->as_in_alt, 0);
+
+	free_ep(&uac2->c_prm, agdev->out_ep);
+	ALT_SET(agdev->as_out_alt, 0);
+}
+
+static int
+in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+	struct usb_request *req = fn->config->cdev->req;
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+	u16 w_length = le16_to_cpu(cr->wLength);
+	u16 w_index = le16_to_cpu(cr->wIndex);
+	u16 w_value = le16_to_cpu(cr->wValue);
+	u8 entity_id = (w_index >> 8) & 0xff;
+	u8 control_selector = w_value >> 8;
+	int value = -EOPNOTSUPP;
+
+	if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) {
+		struct cntrl_cur_lay3 c;
+
+		if (entity_id == USB_IN_CLK_ID)
+			c.dCUR = p_srate;
+		else if (entity_id == USB_OUT_CLK_ID)
+			c.dCUR = c_srate;
+
+		value = min_t(unsigned, w_length, sizeof c);
+		memcpy(req->buf, &c, value);
+	} else if (control_selector == UAC2_CS_CONTROL_CLOCK_VALID) {
+		*(u8 *)req->buf = 1;
+		value = min_t(unsigned, w_length, 1);
+	} else {
+		dev_err(&uac2->pdev.dev,
+			"%s:%d control_selector=%d TODO!\n",
+			__func__, __LINE__, control_selector);
+	}
+
+	return value;
+}
+
+static int
+in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+	struct usb_request *req = fn->config->cdev->req;
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+	u16 w_length = le16_to_cpu(cr->wLength);
+	u16 w_index = le16_to_cpu(cr->wIndex);
+	u16 w_value = le16_to_cpu(cr->wValue);
+	u8 entity_id = (w_index >> 8) & 0xff;
+	u8 control_selector = w_value >> 8;
+	struct cntrl_range_lay3 r;
+	int value = -EOPNOTSUPP;
+
+	if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) {
+		if (entity_id == USB_IN_CLK_ID)
+			r.dMIN = p_srate;
+		else if (entity_id == USB_OUT_CLK_ID)
+			r.dMIN = c_srate;
+		else
+			return -EOPNOTSUPP;
+
+		r.dMAX = r.dMIN;
+		r.dRES = 0;
+		r.wNumSubRanges = 1;
+
+		value = min_t(unsigned, w_length, sizeof r);
+		memcpy(req->buf, &r, value);
+	} else {
+		dev_err(&uac2->pdev.dev,
+			"%s:%d control_selector=%d TODO!\n",
+			__func__, __LINE__, control_selector);
+	}
+
+	return value;
+}
+
+static int
+ac_rq_in(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+	if (cr->bRequest == UAC2_CS_CUR)
+		return in_rq_cur(fn, cr);
+	else if (cr->bRequest == UAC2_CS_RANGE)
+		return in_rq_range(fn, cr);
+	else
+		return -EOPNOTSUPP;
+}
+
+static int
+out_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+	u16 w_length = le16_to_cpu(cr->wLength);
+	u16 w_value = le16_to_cpu(cr->wValue);
+	u8 control_selector = w_value >> 8;
+
+	if (control_selector == UAC2_CS_CONTROL_SAM_FREQ)
+		return w_length;
+
+	return -EOPNOTSUPP;
+}
+
+static int
+setup_rq_inf(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+	u16 w_index = le16_to_cpu(cr->wIndex);
+	u8 intf = w_index & 0xff;
+
+	if (intf != INTF_GET(agdev->ac_alt)) {
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+		return -EOPNOTSUPP;
+	}
+
+	if (cr->bRequestType & USB_DIR_IN)
+		return ac_rq_in(fn, cr);
+	else if (cr->bRequest == UAC2_CS_CUR)
+		return out_rq_cur(fn, cr);
+
+	return -EOPNOTSUPP;
+}
+
+static int
+afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+	struct usb_composite_dev *cdev = fn->config->cdev;
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+	struct usb_request *req = cdev->req;
+	u16 w_length = le16_to_cpu(cr->wLength);
+	int value = -EOPNOTSUPP;
+
+	/* Only Class specific requests are supposed to reach here */
+	if ((cr->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS)
+		return -EOPNOTSUPP;
+
+	if ((cr->bRequestType & USB_RECIP_MASK) == USB_RECIP_INTERFACE)
+		value = setup_rq_inf(fn, cr);
+	else
+		dev_err(&uac2->pdev.dev, "%s:%d Error!\n", __func__, __LINE__);
+
+	if (value >= 0) {
+		req->length = value;
+		req->zero = value < w_length;
+		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0) {
+			dev_err(&uac2->pdev.dev,
+				"%s:%d Error!\n", __func__, __LINE__);
+			req->status = 0;
+		}
+	}
+
+	return value;
+}
+
+static int audio_bind_config(struct usb_configuration *cfg)
+{
+	int id, res;
+
+	agdev_g = kzalloc(sizeof *agdev_g, GFP_KERNEL);
+	if (agdev_g == NULL) {
+		printk(KERN_ERR "Unable to allocate audio gadget\n");
+		return -ENOMEM;
+	}
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_ASSOC].id = id;
+	iad_desc.iFunction = id,
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_IF_CTRL].id = id;
+	std_ac_if_desc.iInterface = id,
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_CLKSRC_IN].id = id;
+	in_clk_src_desc.iClockSource = id,
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_CLKSRC_OUT].id = id;
+	out_clk_src_desc.iClockSource = id,
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_USB_IT].id = id;
+	usb_out_it_desc.iTerminal = id,
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_IO_IT].id = id;
+	io_in_it_desc.iTerminal = id;
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_USB_OT].id = id;
+	usb_in_ot_desc.iTerminal = id;
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_IO_OT].id = id;
+	io_out_ot_desc.iTerminal = id;
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_AS_OUT_ALT0].id = id;
+	std_as_out_if0_desc.iInterface = id;
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_AS_OUT_ALT1].id = id;
+	std_as_out_if1_desc.iInterface = id;
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_AS_IN_ALT0].id = id;
+	std_as_in_if0_desc.iInterface = id;
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_AS_IN_ALT1].id = id;
+	std_as_in_if1_desc.iInterface = id;
+
+	agdev_g->func.name = "uac2_func";
+	agdev_g->func.strings = fn_strings;
+	agdev_g->func.bind = afunc_bind;
+	agdev_g->func.unbind = afunc_unbind;
+	agdev_g->func.set_alt = afunc_set_alt;
+	agdev_g->func.get_alt = afunc_get_alt;
+	agdev_g->func.disable = afunc_disable;
+	agdev_g->func.setup = afunc_setup;
+
+	/* Initialize the configurable parameters */
+	usb_out_it_desc.bNrChannels = num_channels(c_chmask);
+	usb_out_it_desc.bmChannelConfig = cpu_to_le32(c_chmask);
+	io_in_it_desc.bNrChannels = num_channels(p_chmask);
+	io_in_it_desc.bmChannelConfig = cpu_to_le32(p_chmask);
+	as_out_hdr_desc.bNrChannels = num_channels(c_chmask);
+	as_out_hdr_desc.bmChannelConfig = cpu_to_le32(c_chmask);
+	as_in_hdr_desc.bNrChannels = num_channels(p_chmask);
+	as_in_hdr_desc.bmChannelConfig = cpu_to_le32(p_chmask);
+	as_out_fmt1_desc.bSubslotSize = c_ssize;
+	as_out_fmt1_desc.bBitResolution = c_ssize * 8;
+	as_in_fmt1_desc.bSubslotSize = p_ssize;
+	as_in_fmt1_desc.bBitResolution = p_ssize * 8;
+
+	snprintf(clksrc_in, sizeof(clksrc_in), "%uHz", p_srate);
+	snprintf(clksrc_out, sizeof(clksrc_out), "%uHz", c_srate);
+
+	res = usb_add_function(cfg, &agdev_g->func);
+	if (res < 0)
+		kfree(agdev_g);
+
+	return res;
+}
+
+static void
+uac2_unbind_config(struct usb_configuration *cfg)
+{
+	kfree(agdev_g);
+	agdev_g = NULL;
+}

From a003c187cac7a88101fe7f254bde6582865f7908 Mon Sep 17 00:00:00 2001
From: Danny Kukawka <danny.kukawka@bisect.de>
Date: Wed, 15 Feb 2012 18:56:07 +0100
Subject: [PATCH 35/53] usb: at91_udc: linux/prefetch.h included twice

drivers/usb/gadget/at91_udc.c included 'linux/prefetch.h' twice,
remove the duplicate.

Signed-off-by: Danny Kukawka <danny.kukawka@bisect.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/at91_udc.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 143a7256b598..d8dee225bf8e 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -29,7 +29,6 @@
 #include <linux/clk.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
-#include <linux/prefetch.h>
 
 #include <asm/byteorder.h>
 #include <mach/hardware.h>

From f9c56cdd3905c96c600456203637bd7ec8ec6383 Mon Sep 17 00:00:00 2001
From: Ido Shayevitz <idos@codeaurora.org>
Date: Wed, 8 Feb 2012 13:56:48 +0200
Subject: [PATCH 36/53] usb: gadget: Clear usb_endpoint_descriptor inside the
 struct usb_ep on disable

This fix a bug in f_serial, which expect the ep->desc to be NULL after
disabling an endpoint.

Cc: stable@vger.kernel.org
Signed-off-by: Ido Shayevitz <idos@codeaurora.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/dwc3/gadget.c           | 1 +
 drivers/usb/gadget/amd5536udc.c     | 1 +
 drivers/usb/gadget/at91_udc.c       | 1 +
 drivers/usb/gadget/atmel_usba_udc.c | 1 +
 drivers/usb/gadget/ci13xxx_udc.c    | 1 +
 drivers/usb/gadget/fsl_qe_udc.c     | 1 +
 drivers/usb/gadget/fsl_udc_core.c   | 1 +
 drivers/usb/gadget/goku_udc.c       | 1 +
 drivers/usb/gadget/langwell_udc.c   | 1 +
 drivers/usb/gadget/mv_udc_core.c    | 1 +
 drivers/usb/gadget/omap_udc.c       | 1 +
 drivers/usb/gadget/pch_udc.c        | 1 +
 drivers/usb/gadget/pxa25x_udc.c     | 2 ++
 drivers/usb/gadget/s3c-hsudc.c      | 2 ++
 drivers/usb/gadget/s3c2410_udc.c    | 2 ++
 15 files changed, 18 insertions(+)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index a696bde53222..a1a04d00a9e4 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -440,6 +440,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
 
 	dep->stream_capable = false;
 	dep->desc = NULL;
+	dep->endpoint.desc = NULL;
 	dep->comp_desc = NULL;
 	dep->type = 0;
 	dep->flags = 0;
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index c16ff55a74e8..18883bd0f162 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -445,6 +445,7 @@ static void ep_init(struct udc_regs __iomem *regs, struct udc_ep *ep)
 
 	VDBG(ep->dev, "ep-%d reset\n", ep->num);
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->ep.ops = &udc_ep_ops;
 	INIT_LIST_HEAD(&ep->queue);
 
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index d8dee225bf8e..15a8cdb2ded5 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -557,6 +557,7 @@ static int at91_ep_disable (struct usb_ep * _ep)
 
 	/* restore the endpoint's pristine config */
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->ep.maxpacket = ep->maxpacket;
 
 	/* reset fifos and endpoint */
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index e2fb6d583bd9..5e10f651ad63 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -659,6 +659,7 @@ static int usba_ep_disable(struct usb_ep *_ep)
 		return -EINVAL;
 	}
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 
 	list_splice_init(&ep->queue, &req_list);
 	if (ep->can_dma) {
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 27e313718422..9e892890e08a 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2181,6 +2181,7 @@ static int ep_disable(struct usb_ep *ep)
 	} while (mEp->dir != direction);
 
 	mEp->desc = NULL;
+	mEp->ep.desc = NULL;
 
 	spin_unlock_irqrestore(mEp->lock, flags);
 	return retval;
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index b95697c03d07..877a2c46672b 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -1638,6 +1638,7 @@ static int qe_ep_disable(struct usb_ep *_ep)
 	/* Nuke all pending requests (does flush) */
 	nuke(ep, -ESHUTDOWN);
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 	ep->tx_req = NULL;
 	qe_ep_reset(udc, ep->epnum);
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index d7ea6c076ce9..b54357350422 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -659,6 +659,7 @@ static int fsl_ep_disable(struct usb_ep *_ep)
 	nuke(ep, -ESHUTDOWN);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 	spin_unlock_irqrestore(&udc->lock, flags);
 
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 5af70fcce139..59777490a19a 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -235,6 +235,7 @@ static void ep_reset(struct goku_udc_regs __iomem *regs, struct goku_ep *ep)
 
 	ep->ep.maxpacket = MAX_FIFO_SIZE;
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 	ep->irqs = 0;
 	ep->dma = 0;
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c
index fa0fcc11263f..a2bb5e476f54 100644
--- a/drivers/usb/gadget/langwell_udc.c
+++ b/drivers/usb/gadget/langwell_udc.c
@@ -492,6 +492,7 @@ static int langwell_ep_disable(struct usb_ep *_ep)
 	nuke(ep, -ESHUTDOWN);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 
 	spin_unlock_irqrestore(&dev->lock, flags);
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index 8dd398b99e2f..ec6009fc050f 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -608,6 +608,7 @@ static int  mv_ep_disable(struct usb_ep *_ep)
 	nuke(ep, -ESHUTDOWN);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 
 	spin_unlock_irqrestore(&udc->lock, flags);
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 576cd8578b45..7d0835e4bb92 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -251,6 +251,7 @@ static int omap_ep_disable(struct usb_ep *_ep)
 
 	spin_lock_irqsave(&ep->udc->lock, flags);
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	nuke (ep, -ESHUTDOWN);
 	ep->ep.maxpacket = ep->maxpacket;
 	ep->has_dma = 0;
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index a992084d3890..350dbcd90681 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -1742,6 +1742,7 @@ static int pch_udc_pcd_ep_disable(struct usb_ep *usbep)
 	pch_udc_ep_disable(ep);
 	pch_udc_disable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num));
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	INIT_LIST_HEAD(&ep->queue);
 	spin_unlock_irqrestore(&ep->dev->lock, iflags);
 	return 0;
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index dd470635f4f7..33adf3884275 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -283,6 +283,7 @@ static int pxa25x_ep_disable (struct usb_ep *_ep)
 	pxa25x_ep_fifo_flush (_ep);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 
 	local_irq_restore(flags);
@@ -1192,6 +1193,7 @@ static void udc_reinit(struct pxa25x_udc *dev)
 			list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
 
 		ep->desc = NULL;
+		ep->ep.desc = NULL;
 		ep->stopped = 0;
 		INIT_LIST_HEAD (&ep->queue);
 		ep->pio_irqs = 0;
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index 5e8729374fba..ace95f933689 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -817,6 +817,7 @@ static int s3c_hsudc_ep_disable(struct usb_ep *_ep)
 	s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN);
 
 	hsep->desc = 0;
+	hsep->ep.desc = NULL;
 	hsep->stopped = 1;
 
 	spin_unlock_irqrestore(&hsudc->lock, flags);
@@ -1006,6 +1007,7 @@ static void s3c_hsudc_initep(struct s3c_hsudc *hsudc,
 	hsep->ep.ops = &s3c_hsudc_ep_ops;
 	hsep->fifo = hsudc->regs + S3C_BR(epnum);
 	hsep->desc = 0;
+	hsep->ep.desc = NULL;
 	hsep->stopped = 0;
 	hsep->wedge = 0;
 
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index 3f87cb9344bb..ab9c65e2c1d5 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1148,6 +1148,7 @@ static int s3c2410_udc_ep_disable(struct usb_ep *_ep)
 	dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->halted = 1;
 
 	s3c2410_udc_nuke (ep->dev, ep, -ESHUTDOWN);
@@ -1630,6 +1631,7 @@ static void s3c2410_udc_reinit(struct s3c2410_udc *dev)
 
 		ep->dev = dev;
 		ep->desc = NULL;
+		ep->ep.desc = NULL;
 		ep->halted = 0;
 		INIT_LIST_HEAD (&ep->queue);
 	}

From 3b2a2e47174cd978258bbb0fdf2e2b1b5ec2144c Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Mon, 20 Feb 2012 17:35:50 -0800
Subject: [PATCH 37/53] usb: renesas_usbhs: bugfix: add .release function to
 gpriv->gadget.dev

This patch fixup below warning on device_unregister()

renesas_usbhs renesas_usbhs.1: host probed
renesas_usbhs renesas_usbhs.1: gadget probed
renesas_usbhs renesas_usbhs.1: irq request err
------------[ cut here ]------------
WARNING: at ${LINUX}/drivers/base/core.c:1)
Device 'gadget' does not have a release() function, it is broken and must be fi.
Modules linked in:
[<c000e25c>] (unwind_backtrace+0x0/0xe4) from [<c0016960>] (warn_slowpath_commo)
[<c0016960>] (warn_slowpath_common+0x4c/0x64) from [<c00169f8>] (warn_slowpath_)
[<c00169f8>] (warn_slowpath_fmt+0x2c/0x3c) from [<c0185b80>] (device_release+0x)
[<c0185b80>] (device_release+0x70/0x84) from [<c013e300>] (kobject_cleanup+0x58)
[<c013e300>] (kobject_cleanup+0x58/0x6c) from [<c01cba14>] (usbhs_mod_gadget_re)
[<c01cba14>] (usbhs_mod_gadget_remove+0x3c/0x6c) from [<c01c8384>] (usbhs_mod_p)
[<c01c8384>] (usbhs_mod_probe+0x68/0x80) from [<c01c7f84>] (usbhs_probe+0x1cc/0)
...

Cc: stable@vger.kernel.org
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/renesas_usbhs/mod_gadget.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 528691d5f3e2..f37b20c82c80 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -941,6 +941,11 @@ static int usbhsg_stop(struct usbhs_priv *priv)
 	return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED);
 }
 
+static void usbhs_mod_gadget_release(struct device *pdev)
+{
+	/* do nothing */
+}
+
 int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 {
 	struct usbhsg_gpriv *gpriv;
@@ -989,6 +994,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 	 */
 	dev_set_name(&gpriv->gadget.dev, "gadget");
 	gpriv->gadget.dev.parent	= dev;
+	gpriv->gadget.dev.release	= usbhs_mod_gadget_release;
 	gpriv->gadget.name		= "renesas_usbhs_udc";
 	gpriv->gadget.ops		= &usbhsg_gadget_ops;
 	gpriv->gadget.max_speed		= USB_SPEED_HIGH;

From c5cc5ed86667d4ae74fe40ee4ed893f4b46aba05 Mon Sep 17 00:00:00 2001
From: Peter Chen <peter.chen@freescale.com>
Date: Thu, 16 Feb 2012 09:36:25 +0800
Subject: [PATCH 38/53] usb: fsl_udc_core: Fix scheduling while atomic dump
 message

When loading g_ether gadget, there is below message:

Backtrace:
[<80012248>] (dump_backtrace+0x0/0x10c) from [<803cb42c>] (dump_stack+0x18/0x1c)
r7:00000000 r6:80512000 r5:8052bef8 r4:80513f30
[<803cb414>] (dump_stack+0x0/0x1c) from [<8000feb4>] (show_regs+0x44/0x50)
[<8000fe70>] (show_regs+0x0/0x50) from [<8004c840>] (__schedule_bug+0x68/0x84)
r5:8052bef8 r4:80513f30
[<8004c7d8>] (__schedule_bug+0x0/0x84) from [<803cd0e4>] (__schedule+0x4b0/0x528)
r5:8052bef8 r4:809aad00
[<803ccc34>] (__schedule+0x0/0x528) from [<803cd214>] (_cond_resched+0x44/0x58)
[<803cd1d0>] (_cond_resched+0x0/0x58) from [<800a9488>] (dma_pool_alloc+0x184/0x250)
 r5:9f9b4000 r4:9fb4fb80
 [<800a9304>] (dma_pool_alloc+0x0/0x250) from [<802a8ad8>] (fsl_req_to_dtd+0xac/0x180)
[<802a8a2c>] (fsl_req_to_dtd+0x0/0x180) from [<802a8ce4>] (fsl_ep_queue+0x138/0x274)
[<802a8bac>] (fsl_ep_queue+0x0/0x274) from [<7f004328>] (composite_setup+0x2d4/0xfac [g_ether])
[<7f004054>] (composite_setup+0x0/0xfac [g_ether]) from [<802a9bb4>] (fsl_udc_irq+0x8dc/0xd38)
[<802a92d8>] (fsl_udc_irq+0x0/0xd38) from [<800704f8>] (handle_irq_event_percpu+0x54/0x188)
[<800704a4>] (handle_irq_event_percpu+0x0/0x188) from [<80070674>] (handle_irq_event+0x48/0x68)
[<8007062c>] (handle_irq_event+0x0/0x68) from [<800738ec>] (handle_level_irq+0xb4/0x138)
 r5:80514f94 r4:80514f40
 [<80073838>] (handle_level_irq+0x0/0x138) from [<8006ffa4>] (generic_handle_irq+0x38/0x44)
 r7:00000012 r6:80510b1c r5:80529860 r4:80512000
 [<8006ff6c>] (generic_handle_irq+0x0/0x44) from [<8000f4c4>] (handle_IRQ+0x54/0xb4)
[<8000f470>] (handle_IRQ+0x0/0xb4) from [<800085b8>] (tzic_handle_irq+0x64/0x94)
 r9:412fc085 r8:00000000 r7:80513f30 r6:00000001 r5:00000000
 r4:00000000
 [<80008554>] (tzic_handle_irq+0x0/0x94) from [<8000e680>] (__irq_svc+0x40/0x60)

The reason of above dump message is calling dma_poll_alloc with can-schedule
mem_flags at atomic context.

To fix this problem, below changes are made:
- fsl_req_to_dtd doesn't need to be protected by spin_lock_irqsave,
as struct usb_request can be access at process context. Move lock
to beginning of hardware visit (fsl_queue_td).
- Change the memory flag which using to allocate dTD descriptor buffer,
the memory flag can be from gadget layer.

It is tested at i.mx51 bbg board with g_mass_storage, g_ether, g_serial.

Cc: stable@vger.kernel.org
Signed-off-by: Peter Chen <peter.chen@freescale.com>
Acked-by: Li Yang <leoli@freescale.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/fsl_udc_core.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index b54357350422..8db5a666e2ab 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -769,7 +769,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
  * @is_last: return flag if it is the last dTD of the request
  * return: pointer to the built dTD */
 static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
-		dma_addr_t *dma, int *is_last)
+		dma_addr_t *dma, int *is_last, gfp_t gfp_flags)
 {
 	u32 swap_temp;
 	struct ep_td_struct *dtd;
@@ -778,7 +778,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
 	*length = min(req->req.length - req->req.actual,
 			(unsigned)EP_MAX_LENGTH_TRANSFER);
 
-	dtd = dma_pool_alloc(udc_controller->td_pool, GFP_KERNEL, dma);
+	dtd = dma_pool_alloc(udc_controller->td_pool, gfp_flags, dma);
 	if (dtd == NULL)
 		return dtd;
 
@@ -828,7 +828,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
 }
 
 /* Generate dtd chain for a request */
-static int fsl_req_to_dtd(struct fsl_req *req)
+static int fsl_req_to_dtd(struct fsl_req *req, gfp_t gfp_flags)
 {
 	unsigned	count;
 	int		is_last;
@@ -837,7 +837,7 @@ static int fsl_req_to_dtd(struct fsl_req *req)
 	dma_addr_t dma;
 
 	do {
-		dtd = fsl_build_dtd(req, &count, &dma, &is_last);
+		dtd = fsl_build_dtd(req, &count, &dma, &is_last, gfp_flags);
 		if (dtd == NULL)
 			return -ENOMEM;
 
@@ -911,13 +911,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	req->req.actual = 0;
 	req->dtd_count = 0;
 
-	spin_lock_irqsave(&udc->lock, flags);
-
 	/* build dtds and push them to device queue */
-	if (!fsl_req_to_dtd(req)) {
+	if (!fsl_req_to_dtd(req, gfp_flags)) {
+		spin_lock_irqsave(&udc->lock, flags);
 		fsl_queue_td(ep, req);
 	} else {
-		spin_unlock_irqrestore(&udc->lock, flags);
 		return -ENOMEM;
 	}
 
@@ -1296,7 +1294,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
 			ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 	req->mapped = 1;
 
-	if (fsl_req_to_dtd(req) == 0)
+	if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
 		fsl_queue_td(ep, req);
 	else
 		return -ENOMEM;
@@ -1380,7 +1378,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
 	req->mapped = 1;
 
 	/* prime the data phase */
-	if ((fsl_req_to_dtd(req) == 0))
+	if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
 		fsl_queue_td(ep, req);
 	else			/* no mem */
 		goto stall;

From 170b778ffbfca8619b6971e8a5e8b864712b72e2 Mon Sep 17 00:00:00 2001
From: Cyril Roelandt <tipecaml@gmail.com>
Date: Sat, 25 Feb 2012 02:14:57 +0100
Subject: [PATCH 39/53] usb: amd5536udc: Fix brace coding style issues.

Remove a bunch of unneeded braces.

Signed-off-by: Cyril Roelandt <tipecaml@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/amd5536udc.c | 93 +++++++++++++--------------------
 1 file changed, 36 insertions(+), 57 deletions(-)

diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 18883bd0f162..7df2f7082908 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -204,9 +204,8 @@ static void print_regs(struct udc *dev)
 		DBG(dev, "DMA mode       = BF (buffer fill mode)\n");
 		dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "BF");
 	}
-	if (!use_dma) {
+	if (!use_dma)
 		dev_info(&dev->pdev->dev, "FIFO mode\n");
-	}
 	DBG(dev, "-------------------------------------------------------\n");
 }
 
@@ -570,9 +569,8 @@ udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq)
 		VDBG(ep->dev, "req->td_data=%p\n", req->td_data);
 
 		/* free dma chain if created */
-		if (req->chain_len > 1) {
+		if (req->chain_len > 1)
 			udc_free_dma_chain(ep->dev, req);
-		}
 
 		pci_pool_free(ep->dev->data_requests, req->td_data,
 							req->td_phys);
@@ -640,9 +638,8 @@ udc_txfifo_write(struct udc_ep *ep, struct usb_request *req)
 		bytes = remaining;
 
 	/* dwords first */
-	for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) {
+	for (i = 0; i < bytes / UDC_DWORD_BYTES; i++)
 		writel(*(buf + i), ep->txfifo);
-	}
 
 	/* remaining bytes must be written by byte access */
 	for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) {
@@ -661,9 +658,8 @@ static int udc_rxfifo_read_dwords(struct udc *dev, u32 *buf, int dwords)
 
 	VDBG(dev, "udc_read_dwords(): %d dwords\n", dwords);
 
-	for (i = 0; i < dwords; i++) {
+	for (i = 0; i < dwords; i++)
 		*(buf + i) = readl(dev->rxfifo);
-	}
 	return 0;
 }
 
@@ -676,9 +672,8 @@ static int udc_rxfifo_read_bytes(struct udc *dev, u8 *buf, int bytes)
 	VDBG(dev, "udc_read_bytes(): %d bytes\n", bytes);
 
 	/* dwords first */
-	for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) {
+	for (i = 0; i < bytes / UDC_DWORD_BYTES; i++)
 		*((u32 *)(buf + (i<<2))) = readl(dev->rxfifo);
-	}
 
 	/* remaining bytes must be read by byte access */
 	if (bytes % UDC_DWORD_BYTES) {
@@ -898,9 +893,8 @@ static struct udc_data_dma *udc_get_last_dma_desc(struct udc_request *req)
 	struct udc_data_dma	*td;
 
 	td = req->td_data;
-	while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) {
+	while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L)))
 		td = phys_to_virt(td->next);
-	}
 
 	return td;
 
@@ -950,21 +944,18 @@ static int udc_create_dma_chain(
 	dma_addr = DMA_DONT_USE;
 
 	/* unset L bit in first desc for OUT */
-	if (!ep->in) {
+	if (!ep->in)
 		req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);
-	}
 
 	/* alloc only new desc's if not already available */
 	len = req->req.length / ep->ep.maxpacket;
-	if (req->req.length % ep->ep.maxpacket) {
+	if (req->req.length % ep->ep.maxpacket)
 		len++;
-	}
 
 	if (len > req->chain_len) {
 		/* shorter chain already allocated before */
-		if (req->chain_len > 1) {
+		if (req->chain_len > 1)
 			udc_free_dma_chain(ep->dev, req);
-		}
 		req->chain_len = len;
 		create_new_chain = 1;
 	}
@@ -1007,11 +998,12 @@ static int udc_create_dma_chain(
 
 		/* link td and assign tx bytes */
 		if (i == buf_len) {
-			if (create_new_chain) {
+			if (create_new_chain)
 				req->td_data->next = dma_addr;
-			} else {
-				/* req->td_data->next = virt_to_phys(td); */
-			}
+			/*
+			else
+				req->td_data->next = virt_to_phys(td);
+			*/
 			/* write tx bytes */
 			if (ep->in) {
 				/* first desc */
@@ -1025,11 +1017,12 @@ static int udc_create_dma_chain(
 							UDC_DMA_IN_STS_TXBYTES);
 			}
 		} else {
-			if (create_new_chain) {
+			if (create_new_chain)
 				last->next = dma_addr;
-			} else {
-				/* last->next = virt_to_phys(td); */
-			}
+			/*
+			else
+				last->next = virt_to_phys(td);
+			*/
 			if (ep->in) {
 				/* write tx bytes */
 				td->status = AMD_ADDBITS(td->status,
@@ -1480,11 +1473,10 @@ static int startup_registers(struct udc *dev)
 
 	/* program speed */
 	tmp = readl(&dev->regs->cfg);
-	if (use_fullspeed) {
+	if (use_fullspeed)
 		tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
-	} else {
+	else
 		tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD);
-	}
 	writel(tmp, &dev->regs->cfg);
 
 	return 0;
@@ -1505,9 +1497,8 @@ static void udc_basic_init(struct udc *dev)
 		mod_timer(&udc_timer, jiffies - 1);
 	}
 	/* stop poll stall timer */
-	if (timer_pending(&udc_pollstall_timer)) {
+	if (timer_pending(&udc_pollstall_timer))
 		mod_timer(&udc_pollstall_timer, jiffies - 1);
-	}
 	/* disable DMA */
 	tmp = readl(&dev->regs->ctl);
 	tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_RDE);
@@ -1541,11 +1532,10 @@ static void udc_setup_endpoints(struct udc *dev)
 	/* read enum speed */
 	tmp = readl(&dev->regs->sts);
 	tmp = AMD_GETBITS(tmp, UDC_DEVSTS_ENUM_SPEED);
-	if (tmp == UDC_DEVSTS_ENUM_SPEED_HIGH) {
+	if (tmp == UDC_DEVSTS_ENUM_SPEED_HIGH)
 		dev->gadget.speed = USB_SPEED_HIGH;
-	} else if (tmp == UDC_DEVSTS_ENUM_SPEED_FULL) {
+	else if (tmp == UDC_DEVSTS_ENUM_SPEED_FULL)
 		dev->gadget.speed = USB_SPEED_FULL;
-	}
 
 	/* set basic ep parameters */
 	for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
@@ -1571,9 +1561,8 @@ static void udc_setup_endpoints(struct udc *dev)
 		 * disabling ep interrupts when ENUM interrupt occurs but ep is
 		 * not enabled by gadget driver
 		 */
-		if (!ep->desc) {
+		if (!ep->desc)
 			ep_init(dev->regs, ep);
-		}
 
 		if (use_dma) {
 			/*
@@ -1671,9 +1660,8 @@ static void udc_tasklet_disconnect(unsigned long par)
 		spin_lock(&dev->lock);
 
 		/* empty queues */
-		for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
+		for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
 			empty_req_queue(&dev->ep[tmp]);
-		}
 
 	}
 
@@ -1747,9 +1735,8 @@ static void udc_timer_function(unsigned long v)
 			 * open the fifo
 			 */
 			udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV;
-			if (!stop_timer) {
+			if (!stop_timer)
 				add_timer(&udc_timer);
-			}
 		} else {
 			/*
 			 * fifo contains data now, setup timer for opening
@@ -1761,9 +1748,8 @@ static void udc_timer_function(unsigned long v)
 			set_rde++;
 			/* debug: lhadmot_timer_start = 221070 */
 			udc_timer.expires = jiffies + HZ*UDC_RDE_TIMER_SECONDS;
-			if (!stop_timer) {
+			if (!stop_timer)
 				add_timer(&udc_timer);
-			}
 		}
 
 	} else
@@ -1908,19 +1894,17 @@ static void activate_control_endpoints(struct udc *dev)
 			mod_timer(&udc_timer, jiffies - 1);
 		}
 		/* stop pollstall timer */
-		if (timer_pending(&udc_pollstall_timer)) {
+		if (timer_pending(&udc_pollstall_timer))
 			mod_timer(&udc_pollstall_timer, jiffies - 1);
-		}
 		/* enable DMA */
 		tmp = readl(&dev->regs->ctl);
 		tmp |= AMD_BIT(UDC_DEVCTL_MODE)
 				| AMD_BIT(UDC_DEVCTL_RDE)
 				| AMD_BIT(UDC_DEVCTL_TDE);
-		if (use_dma_bufferfill_mode) {
+		if (use_dma_bufferfill_mode)
 			tmp |= AMD_BIT(UDC_DEVCTL_BF);
-		} else if (use_dma_ppb_du) {
+		else if (use_dma_ppb_du)
 			tmp |= AMD_BIT(UDC_DEVCTL_DU);
-		}
 		writel(tmp, &dev->regs->ctl);
 	}
 
@@ -2105,9 +2089,8 @@ static void udc_ep0_set_rde(struct udc *dev)
 				udc_timer.expires =
 					jiffies + HZ/UDC_RDE_TIMER_DIV;
 				set_rde = 1;
-				if (!stop_timer) {
+				if (!stop_timer)
 					add_timer(&udc_timer);
-				}
 			}
 		}
 	}
@@ -2295,9 +2278,8 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
 						jiffies
 						+ HZ*UDC_RDE_TIMER_SECONDS;
 					set_rde = 1;
-					if (!stop_timer) {
+					if (!stop_timer)
 						add_timer(&udc_timer);
-					}
 				}
 				if (ep->num != UDC_EP0OUT_IX)
 					dev->data_ep_queued = 0;
@@ -2319,9 +2301,8 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
 	/* check pending CNAKS */
 	if (cnak_pending) {
 		/* CNAk processing when rxfifo empty only */
-		if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) {
+		if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY))
 			udc_process_cnak_queue(dev);
-		}
 	}
 
 	/* clear OUT bits in ep status */
@@ -2582,9 +2563,8 @@ __acquires(dev->lock)
 			if (!timer_pending(&udc_timer)) {
 				udc_timer.expires = jiffies +
 							HZ/UDC_RDE_TIMER_DIV;
-				if (!stop_timer) {
+				if (!stop_timer)
 					add_timer(&udc_timer);
-				}
 			}
 		}
 
@@ -2698,9 +2678,8 @@ __acquires(dev->lock)
 	/* check pending CNAKS */
 	if (cnak_pending) {
 		/* CNAk processing when rxfifo empty only */
-		if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) {
+		if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY))
 			udc_process_cnak_queue(dev);
-		}
 	}
 
 finished:

From 5647a149e2b9260530a11c8494b529de56e226ab Mon Sep 17 00:00:00 2001
From: Cyril Roelandt <tipecaml@gmail.com>
Date: Sat, 25 Feb 2012 02:14:58 +0100
Subject: [PATCH 40/53] usb: amd5536udc: Fix coding style issues.

Remove unnecessary whitespaces.

Signed-off-by: Cyril Roelandt <tipecaml@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/amd5536udc.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 7df2f7082908..5e2cc0addb85 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -2115,7 +2115,7 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
 	if (use_dma) {
 		/* BNA event ? */
 		if (tmp & AMD_BIT(UDC_EPSTS_BNA)) {
-			DBG(dev, "BNA ep%dout occurred - DESPTR = %x \n",
+			DBG(dev, "BNA ep%dout occurred - DESPTR = %x\n",
 					ep->num, readl(&ep->regs->desptr));
 			/* clear BNA */
 			writel(tmp | AMD_BIT(UDC_EPSTS_BNA), &ep->regs->sts);
@@ -2330,7 +2330,7 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
 		/* BNA ? */
 		if (epsts & AMD_BIT(UDC_EPSTS_BNA)) {
 			dev_err(&dev->pdev->dev,
-				"BNA ep%din occurred - DESPTR = %08lx \n",
+				"BNA ep%din occurred - DESPTR = %08lx\n",
 				ep->num,
 				(unsigned long) readl(&ep->regs->desptr));
 
@@ -2343,7 +2343,7 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
 	/* HE event ? */
 	if (epsts & AMD_BIT(UDC_EPSTS_HE)) {
 		dev_err(&dev->pdev->dev,
-			"HE ep%dn occurred - DESPTR = %08lx \n",
+			"HE ep%dn occurred - DESPTR = %08lx\n",
 			ep->num, (unsigned long) readl(&ep->regs->desptr));
 
 		/* clear HE */
@@ -2703,7 +2703,7 @@ static irqreturn_t udc_control_in_isr(struct udc *dev)
 	tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->sts);
 	/* DMA completion */
 	if (tmp & AMD_BIT(UDC_EPSTS_TDC)) {
-		VDBG(dev, "isr: TDC clear \n");
+		VDBG(dev, "isr: TDC clear\n");
 		ret_val = IRQ_HANDLED;
 
 		/* clear TDC bit */

From 1435db486c131b4b76d8e2a261ae6292ffc3f7ca Mon Sep 17 00:00:00 2001
From: Cyril Roelandt <tipecaml@gmail.com>
Date: Sat, 25 Feb 2012 02:14:59 +0100
Subject: [PATCH 41/53] usb: amd5536udc: Fix indentation

Remove an unnecessary level of indentation.

Signed-off-by: Cyril Roelandt <tipecaml@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/amd5536udc.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 5e2cc0addb85..ad72ab72f041 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -2409,9 +2409,9 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
 				/* write fifo */
 				udc_txfifo_write(ep, &req->req);
 				len = req->req.length - req->req.actual;
-						if (len > ep->ep.maxpacket)
-							len = ep->ep.maxpacket;
-						req->req.actual += len;
+				if (len > ep->ep.maxpacket)
+					len = ep->ep.maxpacket;
+				req->req.actual += len;
 				if (req->req.actual == req->req.length
 					|| (len != ep->ep.maxpacket)) {
 					/* complete req */

From 1b8860df38963218a30e9f1f39d649c992cb9efa Mon Sep 17 00:00:00 2001
From: Cyril Roelandt <tipecaml@gmail.com>
Date: Sat, 25 Feb 2012 02:15:00 +0100
Subject: [PATCH 42/53] usb: amd5536udc: use the DEFINE_PCI_DEVICE_TABLE macro

Use DEFINE_PCI_DEVICE_TABLE instead of "const struct pci_device_id".

Signed-off-by: Cyril Roelandt <tipecaml@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/amd5536udc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index ad72ab72f041..d28bc245ad52 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -3406,7 +3406,7 @@ static int udc_remote_wakeup(struct udc *dev)
 }
 
 /* PCI device parameters */
-static const struct pci_device_id pci_id[] = {
+static DEFINE_PCI_DEVICE_TABLE(pci_id) = {
 	{
 		PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096),
 		.class =	(PCI_CLASS_SERIAL_USB << 8) | 0xfe,

From 34af373865b91aa4108134b5a4748d40a100111c Mon Sep 17 00:00:00 2001
From: Cyril Roelandt <tipecaml@gmail.com>
Date: Sun, 26 Feb 2012 16:00:25 +0100
Subject: [PATCH 43/53] usb: amd5536udc: Fix the type of ep_string

Use "static const char *const" instead of "static const char *".

Signed-off-by: Cyril Roelandt <tipecaml@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/amd5536udc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index d28bc245ad52..9349c4eb688d 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -140,7 +140,7 @@ static DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect,
 
 /* endpoint names used for print */
 static const char ep0_string[] = "ep0in";
-static const char *ep_string[] = {
+static const char *const ep_string[] = {
 	ep0_string,
 	"ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk",
 	"ep6in-bulk", "ep7in-bulk", "ep8in-bulk", "ep9in-bulk", "ep10in-bulk",

From c15e03e1553d8fb334de26727b0edadd582a46e7 Mon Sep 17 00:00:00 2001
From: Cyril Roelandt <tipecaml@gmail.com>
Date: Sat, 25 Feb 2012 02:15:02 +0100
Subject: [PATCH 44/53] usb: amd5536udc: Remove old CVS markers

Git does not care about CVS markers.

Signed-off-by: Cyril Roelandt <tipecaml@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/amd5536udc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 9349c4eb688d..1355a2f5e685 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -29,7 +29,7 @@
 
 /* Driver strings */
 #define UDC_MOD_DESCRIPTION		"AMD 5536 UDC - USB Device Controller"
-#define UDC_DRIVER_VERSION_STRING	"01.00.0206 - $Revision: #3 $"
+#define UDC_DRIVER_VERSION_STRING	"01.00.0206"
 
 /* system */
 #include <linux/module.h>

From a698908d3b3be915ac20cd37faeff1216f6b4fe8 Mon Sep 17 00:00:00 2001
From: Felipe Balbi <balbi@ti.com>
Date: Thu, 15 Dec 2011 13:31:48 +0200
Subject: [PATCH 45/53] usb: gadget: add generic map/unmap request utilities

such utilities are currently duplicated on all UDC
drivers basically with the same structure. Let's group
all implementations into one generic implementation
and get rid of that duplication.

Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/udc-core.c | 52 +++++++++++++++++++++++++++++++++++
 include/linux/usb/gadget.h    | 10 +++++++
 2 files changed, 62 insertions(+)

diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index 0b0d12ccc487..56da49f31d6c 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -22,6 +22,7 @@
 #include <linux/device.h>
 #include <linux/list.h>
 #include <linux/err.h>
+#include <linux/dma-mapping.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
@@ -49,6 +50,57 @@ static DEFINE_MUTEX(udc_lock);
 
 /* ------------------------------------------------------------------------- */
 
+int usb_gadget_map_request(struct usb_gadget *gadget,
+		struct usb_request *req, int is_in)
+{
+	if (req->length == 0)
+		return 0;
+
+	if (req->num_sgs) {
+		int     mapped;
+
+		mapped = dma_map_sg(&gadget->dev, req->sg, req->num_sgs,
+				is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+		if (mapped == 0) {
+			dev_err(&gadget->dev, "failed to map SGs\n");
+			return -EFAULT;
+		}
+
+		req->num_mapped_sgs = mapped;
+	} else {
+		req->dma = dma_map_single(&gadget->dev, req->buf, req->length,
+				is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+
+		if (dma_mapping_error(&gadget->dev, req->dma)) {
+			dev_err(&gadget->dev, "failed to map buffer\n");
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_map_request);
+
+void usb_gadget_unmap_request(struct usb_gadget *gadget,
+		struct usb_request *req, int is_in)
+{
+	if (req->length == 0)
+		return;
+
+	if (req->num_mapped_sgs) {
+		dma_unmap_sg(&gadget->dev, req->sg, req->num_mapped_sgs,
+				is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+
+		req->num_mapped_sgs = 0;
+	} else {
+		dma_unmap_single(&gadget->dev, req->dma, req->length,
+				is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	}
+}
+EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
+
+/* ------------------------------------------------------------------------- */
+
 /**
  * usb_gadget_start - tells usb device controller to start up
  * @gadget: The gadget we want to get started
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index da653b5c7134..9517466ababb 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -950,6 +950,16 @@ static inline void usb_free_descriptors(struct usb_descriptor_header **v)
 
 /*-------------------------------------------------------------------------*/
 
+/* utility to simplify map/unmap of usb_requests to/from DMA */
+
+extern int usb_gadget_map_request(struct usb_gadget *gadget,
+		struct usb_request *req, int is_in);
+
+extern void usb_gadget_unmap_request(struct usb_gadget *gadget,
+		struct usb_request *req, int is_in);
+
+/*-------------------------------------------------------------------------*/
+
 /* utility wrapping a simple endpoint selection policy */
 
 extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *,

From 0fc9a1be09d9f8b19bcf64ab96836cb92beb0970 Mon Sep 17 00:00:00 2001
From: Felipe Balbi <balbi@ti.com>
Date: Mon, 19 Dec 2011 11:32:34 +0200
Subject: [PATCH 46/53] usb: dwc3: gadget: use generic map/unmap routines

those routines have everything we need to map/unmap
USB requests and it's better to use them.

In order to achieve that, we had to add a simple
change on how we allocate and use our setup buffer;
we cannot allocate it from coherent anymore otherwise
the generic map/unmap routines won't be able to easily
know that the GetStatus request already has a DMA
address.

Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/dwc3/core.h   |  2 -
 drivers/usb/dwc3/ep0.c    | 16 +++++--
 drivers/usb/dwc3/gadget.c | 93 +++++++--------------------------------
 drivers/usb/dwc3/gadget.h |  2 -
 4 files changed, 30 insertions(+), 83 deletions(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 9e57f8e9bf17..a72f42ffbbee 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -572,7 +572,6 @@ struct dwc3_request {
  * @ctrl_req_addr: dma address of ctrl_req
  * @ep0_trb: dma address of ep0_trb
  * @ep0_usb_req: dummy req used while handling STD USB requests
- * @setup_buf_addr: dma address of setup_buf
  * @ep0_bounce_addr: dma address of ep0_bounce
  * @lock: for synchronizing
  * @dev: pointer to our struct device
@@ -609,7 +608,6 @@ struct dwc3 {
 	u8			*setup_buf;
 	dma_addr_t		ctrl_req_addr;
 	dma_addr_t		ep0_trb_addr;
-	dma_addr_t		setup_buf_addr;
 	dma_addr_t		ep0_bounce_addr;
 	struct dwc3_request	ep0_usb_req;
 	/* device lock */
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 2f51de57593a..24137d8563c9 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -309,7 +309,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
 	dep = dwc->eps[0];
 	dwc->ep0_usb_req.dep = dep;
 	dwc->ep0_usb_req.request.length = sizeof(*response_pkt);
-	dwc->ep0_usb_req.request.dma = dwc->setup_buf_addr;
+	dwc->ep0_usb_req.request.buf = dwc->setup_buf;
 	dwc->ep0_usb_req.request.complete = dwc3_ep0_status_cmpl;
 
 	return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
@@ -686,7 +686,12 @@ static void dwc3_ep0_do_control_data(struct dwc3 *dwc,
 				DWC3_TRBCTL_CONTROL_DATA);
 	} else if ((req->request.length % dep->endpoint.maxpacket)
 			&& (event->endpoint_number == 0)) {
-		dwc3_map_buffer_to_dma(req);
+		ret = usb_gadget_map_request(&dwc->gadget, &req->request,
+				event->endpoint_number);
+		if (ret) {
+			dev_dbg(dwc->dev, "failed to map request\n");
+			return;
+		}
 
 		WARN_ON(req->request.length > dep->endpoint.maxpacket);
 
@@ -701,7 +706,12 @@ static void dwc3_ep0_do_control_data(struct dwc3 *dwc,
 				dwc->ep0_bounce_addr, dep->endpoint.maxpacket,
 				DWC3_TRBCTL_CONTROL_DATA);
 	} else {
-		dwc3_map_buffer_to_dma(req);
+		ret = usb_gadget_map_request(&dwc->gadget, &req->request,
+				event->endpoint_number);
+		if (ret) {
+			dev_dbg(dwc->dev, "failed to map request\n");
+			return;
+		}
 
 		ret = dwc3_ep0_start_trans(dwc, event->endpoint_number,
 				req->request.dma, req->request.length,
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index a1a04d00a9e4..1009e7e47a24 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -54,70 +54,6 @@
 #include "gadget.h"
 #include "io.h"
 
-#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
-
-void dwc3_map_buffer_to_dma(struct dwc3_request *req)
-{
-	struct dwc3			*dwc = req->dep->dwc;
-
-	if (req->request.length == 0) {
-		/* req->request.dma = dwc->setup_buf_addr; */
-		return;
-	}
-
-	if (req->request.num_sgs) {
-		int	mapped;
-
-		mapped = dma_map_sg(dwc->dev, req->request.sg,
-				req->request.num_sgs,
-				req->direction ? DMA_TO_DEVICE
-				: DMA_FROM_DEVICE);
-		if (mapped < 0) {
-			dev_err(dwc->dev, "failed to map SGs\n");
-			return;
-		}
-
-		req->request.num_mapped_sgs = mapped;
-		return;
-	}
-
-	if (req->request.dma == DMA_ADDR_INVALID) {
-		req->request.dma = dma_map_single(dwc->dev, req->request.buf,
-				req->request.length, req->direction
-				? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		req->mapped = true;
-	}
-}
-
-void dwc3_unmap_buffer_from_dma(struct dwc3_request *req)
-{
-	struct dwc3			*dwc = req->dep->dwc;
-
-	if (req->request.length == 0) {
-		req->request.dma = DMA_ADDR_INVALID;
-		return;
-	}
-
-	if (req->request.num_mapped_sgs) {
-		req->request.dma = DMA_ADDR_INVALID;
-		dma_unmap_sg(dwc->dev, req->request.sg,
-				req->request.num_sgs,
-				req->direction ? DMA_TO_DEVICE
-				: DMA_FROM_DEVICE);
-
-		req->request.num_mapped_sgs = 0;
-		return;
-	}
-
-	if (req->mapped) {
-		dma_unmap_single(dwc->dev, req->request.dma,
-				req->request.length, req->direction
-				? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		req->mapped = 0;
-		req->request.dma = DMA_ADDR_INVALID;
-	}
-}
-
 void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
 		int status)
 {
@@ -144,14 +80,15 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
 	if (req->request.status == -EINPROGRESS)
 		req->request.status = status;
 
-	dwc3_unmap_buffer_from_dma(req);
+	usb_gadget_unmap_request(&dwc->gadget, &req->request,
+			req->direction);
 
 	dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n",
 			req, dep->name, req->request.actual,
 			req->request.length, status);
 
 	spin_unlock(&dwc->lock);
-	req->request.complete(&req->dep->endpoint, &req->request);
+	req->request.complete(&dep->endpoint, &req->request);
 	spin_lock(&dwc->lock);
 }
 
@@ -563,7 +500,6 @@ static struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep,
 
 	req->epnum	= dep->number;
 	req->dep	= dep;
-	req->request.dma = DMA_ADDR_INVALID;
 
 	return &req->request;
 }
@@ -822,7 +758,8 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
 		 * here and stop, unmap, free and del each of the linked
 		 * requests instead of we do now.
 		 */
-		dwc3_unmap_buffer_from_dma(req);
+		usb_gadget_unmap_request(&dwc->gadget, &req->request,
+				req->direction);
 		list_del(&req->list);
 		return ret;
 	}
@@ -838,6 +775,9 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
 
 static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 {
+	struct dwc3		*dwc = dep->dwc;
+	int			ret;
+
 	req->request.actual	= 0;
 	req->request.status	= -EINPROGRESS;
 	req->direction		= dep->direction;
@@ -855,7 +795,11 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 	 * This will also avoid Host cancelling URBs due to too
 	 * many NACKs.
 	 */
-	dwc3_map_buffer_to_dma(req);
+	ret = usb_gadget_map_request(&dwc->gadget, &req->request,
+			dep->direction);
+	if (ret)
+		return ret;
+
 	list_add_tail(&req->list, &dep->request_list);
 
 	/*
@@ -2150,9 +2094,8 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
 		goto err1;
 	}
 
-	dwc->setup_buf = dma_alloc_coherent(dwc->dev,
-			sizeof(*dwc->setup_buf) * 2,
-			&dwc->setup_buf_addr, GFP_KERNEL);
+	dwc->setup_buf = kzalloc(sizeof(*dwc->setup_buf) * 2,
+			GFP_KERNEL);
 	if (!dwc->setup_buf) {
 		dev_err(dwc->dev, "failed to allocate setup buffer\n");
 		ret = -ENOMEM;
@@ -2243,8 +2186,7 @@ err4:
 			dwc->ep0_bounce_addr);
 
 err3:
-	dma_free_coherent(dwc->dev, sizeof(*dwc->setup_buf) * 2,
-			dwc->setup_buf, dwc->setup_buf_addr);
+	kfree(dwc->setup_buf);
 
 err2:
 	dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
@@ -2273,8 +2215,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
 	dma_free_coherent(dwc->dev, 512, dwc->ep0_bounce,
 			dwc->ep0_bounce_addr);
 
-	dma_free_coherent(dwc->dev, sizeof(*dwc->setup_buf) * 2,
-			dwc->setup_buf, dwc->setup_buf_addr);
+	kfree(dwc->setup_buf);
 
 	dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
 			dwc->ep0_trb, dwc->ep0_trb_addr);
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
index d97f467d41cc..12f1e104977f 100644
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -108,8 +108,6 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
 int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value);
 int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
 		unsigned cmd, struct dwc3_gadget_ep_cmd_params *params);
-void dwc3_map_buffer_to_dma(struct dwc3_request *req);
-void dwc3_unmap_buffer_from_dma(struct dwc3_request *req);
 
 /**
  * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW

From ac8a138cb61d641e1522f3470f1a85f2df21b8bf Mon Sep 17 00:00:00 2001
From: Felipe Balbi <balbi@ti.com>
Date: Mon, 19 Dec 2011 11:48:24 +0200
Subject: [PATCH 47/53] usb: gadget: langwell: use generic map/unmap functions

those routines have everything we need to map/unmap
USB requests and it's better to use them.

Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/langwell_udc.c | 45 +++++--------------------------
 1 file changed, 7 insertions(+), 38 deletions(-)

diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c
index a2bb5e476f54..e91f11a8e2b1 100644
--- a/drivers/usb/gadget/langwell_udc.c
+++ b/drivers/usb/gadget/langwell_udc.c
@@ -406,16 +406,7 @@ static void done(struct langwell_ep *ep, struct langwell_request *req,
 		dma_pool_free(dev->dtd_pool, curr_dtd, curr_dtd->dtd_dma);
 	}
 
-	if (req->mapped) {
-		dma_unmap_single(&dev->pdev->dev,
-			req->req.dma, req->req.length,
-			is_in(ep) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	} else
-		dma_sync_single_for_cpu(&dev->pdev->dev, req->req.dma,
-				req->req.length,
-				is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	usb_gadget_unmap_request(&dev->gadget, &req->req, is_in(ep));
 
 	if (status != -ESHUTDOWN)
 		dev_dbg(&dev->pdev->dev,
@@ -755,7 +746,8 @@ static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
 	struct langwell_ep	*ep;
 	struct langwell_udc	*dev;
 	unsigned long		flags;
-	int			is_iso = 0, zlflag = 0;
+	int			is_iso = 0;
+	int			ret;
 
 	/* always require a cpu-view buffer */
 	req = container_of(_req, struct langwell_request, req);
@@ -782,33 +774,10 @@ static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
 	if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN))
 		return -ESHUTDOWN;
 
-	/* set up dma mapping in case the caller didn't */
-	if (_req->dma == DMA_ADDR_INVALID) {
-		/* WORKAROUND: WARN_ON(size == 0) */
-		if (_req->length == 0) {
-			dev_vdbg(&dev->pdev->dev, "req->length: 0->1\n");
-			zlflag = 1;
-			_req->length++;
-		}
-
-		_req->dma = dma_map_single(&dev->pdev->dev,
-				_req->buf, _req->length,
-				is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		if (zlflag && (_req->length == 1)) {
-			dev_vdbg(&dev->pdev->dev, "req->length: 1->0\n");
-			zlflag = 0;
-			_req->length = 0;
-		}
-
-		req->mapped = 1;
-		dev_vdbg(&dev->pdev->dev, "req->mapped = 1\n");
-	} else {
-		dma_sync_single_for_device(&dev->pdev->dev,
-				_req->dma, _req->length,
-				is_in(ep) ?  DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		req->mapped = 0;
-		dev_vdbg(&dev->pdev->dev, "req->mapped = 0\n");
-	}
+	/* set up dma mapping */
+	ret = usb_gadget_map_request(&dev->gadget, &req->req, is_in(ep));
+	if (ret)
+		return ret;
 
 	dev_dbg(&dev->pdev->dev,
 			"%s queue req %p, len %u, buf %p, dma 0x%08x\n",

From ade78f9feb2ee3e03460ef3730d7656c4903d999 Mon Sep 17 00:00:00 2001
From: Felipe Balbi <balbi@ti.com>
Date: Mon, 19 Dec 2011 11:57:16 +0200
Subject: [PATCH 48/53] usb: renesas: gadget: use generic map/unmap routines

those routines have everything we need to map/unmap
USB requests and it's better to use them.

Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/renesas_usbhs/mod_gadget.c | 75 +++++++-------------------
 1 file changed, 18 insertions(+), 57 deletions(-)

diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index f37b20c82c80..937f2d40c747 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -165,69 +165,32 @@ static void usbhsg_queue_push(struct usbhsg_uep *uep,
 /*
  *		dma map/unmap
  */
-static int usbhsg_dma_map(struct device *dev,
-			  struct usbhs_pkt *pkt,
-			  enum dma_data_direction dir)
-{
-	struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
-	struct usb_request *req = &ureq->req;
-
-	if (pkt->dma != DMA_ADDR_INVALID) {
-		dev_err(dev, "dma is already mapped\n");
-		return -EIO;
-	}
-
-	if (req->dma == DMA_ADDR_INVALID) {
-		pkt->dma = dma_map_single(dev, pkt->buf, pkt->length, dir);
-	} else {
-		dma_sync_single_for_device(dev, req->dma, req->length, dir);
-		pkt->dma = req->dma;
-	}
-
-	if (dma_mapping_error(dev, pkt->dma)) {
-		dev_err(dev, "dma mapping error %llx\n", (u64)pkt->dma);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int usbhsg_dma_unmap(struct device *dev,
-			    struct usbhs_pkt *pkt,
-			    enum dma_data_direction dir)
-{
-	struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
-	struct usb_request *req = &ureq->req;
-
-	if (pkt->dma == DMA_ADDR_INVALID) {
-		dev_err(dev, "dma is not mapped\n");
-		return -EIO;
-	}
-
-	if (req->dma == DMA_ADDR_INVALID)
-		dma_unmap_single(dev, pkt->dma, pkt->length, dir);
-	else
-		dma_sync_single_for_cpu(dev, req->dma, req->length, dir);
-
-	pkt->dma = DMA_ADDR_INVALID;
-
-	return 0;
-}
-
 static int usbhsg_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
 {
+	struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
+	struct usb_request *req = &ureq->req;
 	struct usbhs_pipe *pipe = pkt->pipe;
 	struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe);
 	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
-	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
 	enum dma_data_direction dir;
+	int ret = 0;
 
-	dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	dir = usbhs_pipe_is_dir_host(pipe);
 
-	if (map)
-		return usbhsg_dma_map(dev, pkt, dir);
-	else
-		return usbhsg_dma_unmap(dev, pkt, dir);
+	if (map) {
+		/* it can not use scatter/gather */
+		WARN_ON(req->num_sgs);
+
+		ret = usb_gadget_map_request(&gpriv->gadget, req, dir);
+		if (ret < 0)
+			return ret;
+
+		pkt->dma = req->dma;
+	} else {
+		usb_gadget_unmap_request(&gpriv->gadget, req, dir);
+	}
+
+	return ret;
 }
 
 /*
@@ -657,8 +620,6 @@ static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep,
 
 	usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq));
 
-	ureq->req.dma = DMA_ADDR_INVALID;
-
 	return &ureq->req;
 }
 

From 220e860009ff4091b75f614eb0d09a7a8486bbe6 Mon Sep 17 00:00:00 2001
From: Felipe Balbi <balbi@ti.com>
Date: Mon, 19 Dec 2011 12:01:28 +0200
Subject: [PATCH 49/53] usb: gadget: amd5536: use generic map/unmap routines

those routines have everything we need to map/unmap
USB requests and it's better to use them.

Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/amd5536udc.c | 33 ++++++---------------------------
 1 file changed, 6 insertions(+), 27 deletions(-)

diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 1355a2f5e685..2204a4c68d85 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -827,20 +827,8 @@ __acquires(ep->dev->lock)
 
 	dev = ep->dev;
 	/* unmap DMA */
-	if (req->dma_mapping) {
-		if (ep->in)
-			pci_unmap_single(dev->pdev,
-					req->req.dma,
-					req->req.length,
-					PCI_DMA_TODEVICE);
-		else
-			pci_unmap_single(dev->pdev,
-					req->req.dma,
-					req->req.length,
-					PCI_DMA_FROMDEVICE);
-		req->dma_mapping = 0;
-		req->req.dma = DMA_DONT_USE;
-	}
+	if (ep->dma)
+		usb_gadget_unmap_request(&dev->gadget, &req->req, ep->in);
 
 	halted = ep->halted;
 	ep->halted = 1;
@@ -1089,20 +1077,11 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
 		return -ESHUTDOWN;
 
 	/* map dma (usually done before) */
-	if (ep->dma && usbreq->length != 0
-			&& (usbreq->dma == DMA_DONT_USE || usbreq->dma == 0)) {
+	if (ep->dma) {
 		VDBG(dev, "DMA map req %p\n", req);
-		if (ep->in)
-			usbreq->dma = pci_map_single(dev->pdev,
-						usbreq->buf,
-						usbreq->length,
-						PCI_DMA_TODEVICE);
-		else
-			usbreq->dma = pci_map_single(dev->pdev,
-						usbreq->buf,
-						usbreq->length,
-						PCI_DMA_FROMDEVICE);
-		req->dma_mapping = 1;
+		retval = usb_gadget_map_request(&udc->gadget, usbreq, ep->in);
+		if (retval)
+			return retval;
 	}
 
 	VDBG(dev, "%s queue req %p, len %d req->td_data=%p buf %p\n",

From 05d00fbe87f185d55edf7461d4f714a3909bc908 Mon Sep 17 00:00:00 2001
From: Felipe Balbi <balbi@ti.com>
Date: Mon, 19 Dec 2011 12:03:57 +0200
Subject: [PATCH 50/53] usb: gadget: r8a66597: use generic map/unmap routines

those routines have everything we need to map/unmap
USB requests and it's better to use them.

Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/r8a66597-udc.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
index f5b8d215e1d5..c4401e7dd3a6 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/r8a66597-udc.c
@@ -663,11 +663,7 @@ static int sudmac_alloc_channel(struct r8a66597 *r8a66597,
 	ep->fifoctr = D0FIFOCTR;
 
 	/* dma mapping */
-	req->req.dma = dma_map_single(r8a66597_to_dev(ep->r8a66597),
-				req->req.buf, req->req.length,
-				dma->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-
-	return 0;
+	return usb_gadget_map_request(&r8a66597->gadget, &req->req, dma->dir);
 }
 
 static void sudmac_free_channel(struct r8a66597 *r8a66597,
@@ -677,9 +673,7 @@ static void sudmac_free_channel(struct r8a66597 *r8a66597,
 	if (!r8a66597_is_sudmac(r8a66597))
 		return;
 
-	dma_unmap_single(r8a66597_to_dev(ep->r8a66597),
-			 req->req.dma, req->req.length,
-			 ep->dma->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	usb_gadget_unmap_request(&r8a66597->gadget, &req->req, ep->dma->dir);
 
 	r8a66597_bclr(r8a66597, DREQE, ep->fifosel);
 	r8a66597_change_curpipe(r8a66597, 0, 0, ep->fifosel);

From af93f2c77ac79e2f0bed542b5890f618d9d0cdb3 Mon Sep 17 00:00:00 2001
From: Felipe Balbi <balbi@ti.com>
Date: Mon, 19 Dec 2011 12:07:40 +0200
Subject: [PATCH 51/53] usb: gadget: net2272: use generic map/umap routines

those routines have everything we need to map/unmap
USB requests and it's better to use them.

Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/net2272.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c
index 7322d293213e..01ae56f47174 100644
--- a/drivers/usb/gadget/net2272.c
+++ b/drivers/usb/gadget/net2272.c
@@ -385,12 +385,9 @@ net2272_done(struct net2272_ep *ep, struct net2272_request *req, int status)
 		status = req->req.status;
 
 	dev = ep->dev;
-	if (use_dma && req->mapped) {
-		dma_unmap_single(dev->dev, req->req.dma, req->req.length,
-			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	}
+	if (use_dma && ep->dma)
+		usb_gadget_unmap_request(&dev->gadget, &req->req,
+				ep->is_in);
 
 	if (status && status != -ESHUTDOWN)
 		dev_vdbg(dev->dev, "complete %s req %p stat %d len %u/%u buf %p\n",
@@ -850,10 +847,11 @@ net2272_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 		return -ESHUTDOWN;
 
 	/* set up dma mapping in case the caller didn't */
-	if (use_dma && ep->dma && _req->dma == DMA_ADDR_INVALID) {
-		_req->dma = dma_map_single(dev->dev, _req->buf, _req->length,
-			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		req->mapped = 1;
+	if (use_dma && ep->dma) {
+		status = usb_gadget_map_request(&dev->gadget, _req,
+				ep->is_in);
+		if (status)
+			return status;
 	}
 
 	dev_vdbg(dev->dev, "%s queue req %p, len %d buf %p dma %08llx %s\n",

From ae4d7933344e8bc5702cdc56e9498d3852cf3b2a Mon Sep 17 00:00:00 2001
From: Felipe Balbi <balbi@ti.com>
Date: Mon, 19 Dec 2011 12:09:56 +0200
Subject: [PATCH 52/53] usb: gadget: net2280: use generic map/unmap routines

those routines have everything we need to map/unmap
USB requests and it's better to use them.

Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/net2280.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index cdedd1336745..a5ccabc37f30 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -806,12 +806,8 @@ done (struct net2280_ep *ep, struct net2280_request *req, int status)
 		status = req->req.status;
 
 	dev = ep->dev;
-	if (req->mapped) {
-		pci_unmap_single (dev->pdev, req->req.dma, req->req.length,
-			ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	}
+	if (ep->dma)
+		usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
 
 	if (status && status != -ESHUTDOWN)
 		VDEBUG (dev, "complete %s req %p stat %d len %u/%u\n",
@@ -857,10 +853,13 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 		return -EOPNOTSUPP;
 
 	/* set up dma mapping in case the caller didn't */
-	if (ep->dma && _req->dma == DMA_ADDR_INVALID) {
-		_req->dma = pci_map_single (dev->pdev, _req->buf, _req->length,
-			ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-		req->mapped = 1;
+	if (ep->dma) {
+		int ret;
+
+		ret = usb_gadget_map_request(&dev->gadget, _req,
+				ep->is_in);
+		if (ret)
+			return ret;
 	}
 
 #if 0

From 6440093f5eae9842feb06e40d41c3bd569b6b461 Mon Sep 17 00:00:00 2001
From: Felipe Balbi <balbi@ti.com>
Date: Mon, 19 Dec 2011 12:11:44 +0200
Subject: [PATCH 53/53] usb: gadget: goku: use generic map/unmap routines

those routines have everything we need to map/unmap
USB requests and it's better to use them.

Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/usb/gadget/goku_udc.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 59777490a19a..e1dfd32dc805 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -311,12 +311,9 @@ done(struct goku_ep *ep, struct goku_request *req, int status)
 		status = req->req.status;
 
 	dev = ep->dev;
-	if (req->mapped) {
-		pci_unmap_single(dev->pdev, req->req.dma, req->req.length,
-			ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	}
+
+	if (ep->dma)
+		usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
 
 #ifndef USB_TRACE
 	if (status && status != -ESHUTDOWN)
@@ -737,10 +734,11 @@ goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 		return -EBUSY;
 
 	/* set up dma mapping in case the caller didn't */
-	if (ep->dma && _req->dma == DMA_ADDR_INVALID) {
-		_req->dma = pci_map_single(dev->pdev, _req->buf, _req->length,
-			ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-		req->mapped = 1;
+	if (ep->dma) {
+		status = usb_gadget_map_request(&dev->gadget, &req->req,
+				ep->is_in);
+		if (status)
+			return status;
 	}
 
 #ifdef USB_TRACE