USB: u_bam: Copy data to host in work queue context

Currently data to host is being sent in interrupt context
instead of work queue context which might hit perforamce.
Hence move this processing to work queue context.

With standalone dataloopback test, increments in throughput numbers
are observed as follows(Mbps):
TCP uplink	29.7	53.1
TCP downlink	29.8	53.7
UDP uplink	16.7	22.7
UDP downlink	20.8	24.2

Change-Id: I72ae2ccb0aee43db5a69514a002eba78ae647573
Signed-off-by: Vijayavardhan Vennapusa <vvreddy@codeaurora.org>
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 4f380df..df0646f 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -96,6 +96,7 @@
 
 	struct gbam_port	*port;
 	struct work_struct	write_tobam_w;
+	struct work_struct	write_tohost_w;
 
 	struct usb_request	*rx_req;
 	struct usb_request	*tx_req;
@@ -176,15 +177,19 @@
 /*--------------------------------------------- */
 
 /*------------data_path----------------------------*/
-static void gbam_write_data_tohost(struct gbam_port *port)
+static void gbam_write_data_tohost(struct work_struct *w)
 {
 	unsigned long			flags;
-	struct bam_ch_info		*d = &port->data_ch;
+	struct bam_ch_info	*d;
+	struct gbam_port	*port;
 	struct sk_buff			*skb;
 	int				ret;
 	struct usb_request		*req;
 	struct usb_ep			*ep;
 
+	d = container_of(w, struct bam_ch_info, write_tohost_w);
+	port = d->port;
+
 	spin_lock_irqsave(&port->port_lock_dl, flags);
 	if (!port->port_usb) {
 		spin_unlock_irqrestore(&port->port_lock_dl, flags);
@@ -261,7 +266,7 @@
 	__skb_queue_tail(&d->tx_skb_q, skb);
 	spin_unlock_irqrestore(&port->port_lock_dl, flags);
 
-	gbam_write_data_tohost(port);
+	queue_work(gbam_wq, &d->write_tohost_w);
 }
 
 void gbam_data_write_done(void *p, struct sk_buff *skb)
@@ -370,7 +375,7 @@
 	list_add_tail(&req->list, &d->tx_idle);
 	spin_unlock(&port->port_lock_dl);
 
-	gbam_write_data_tohost(port);
+	queue_work(gbam_wq, &d->write_tohost_w);
 }
 
 static void
@@ -867,6 +872,7 @@
 	INIT_LIST_HEAD(&d->tx_idle);
 	INIT_LIST_HEAD(&d->rx_idle);
 	INIT_WORK(&d->write_tobam_w, gbam_data_write_tobam);
+	INIT_WORK(&d->write_tohost_w, gbam_write_data_tohost);
 	skb_queue_head_init(&d->tx_skb_q);
 	skb_queue_head_init(&d->rx_skb_q);
 	d->id = bam_ch_ids[portno];