usb: f_qdss: Fix watchdog bark issue on wait_for_completion

The coresight driver is freeing up d_req as part of notify
from write_complete. Accessing write_done form qdss_close,
wait_for_completion will be stuck there causing watchdog
bark.

Fix this by making f_qdss independent of coresight & bridge
driver from initializing complete. Initialization of
completion now occurs from alloc_req.

Change-Id: Ie6b1cd445ed6bb38c1a555f6c4c41068090e4fac
Signed-off-by: Udipto Goswami <ugoswami@codeaurora.org>
diff --git a/drivers/hwtracing/coresight/coresight-byte-cntr.c b/drivers/hwtracing/coresight/coresight-byte-cntr.c
index d0b7a89..6353106 100644
--- a/drivers/hwtracing/coresight/coresight-byte-cntr.c
+++ b/drivers/hwtracing/coresight/coresight-byte-cntr.c
@@ -340,8 +340,6 @@
 			goto out;
 		}
 
-		init_completion(&usb_req->write_done);
-
 		actual = tmc_etr_buf_get_data(etr_buf, drvdata->offset,
 					req_size, &usb_req->buf);
 		usb_req->length = actual;
@@ -425,7 +423,6 @@
 						sizeof(*usb_req), GFP_KERNEL);
 			if (!usb_req)
 				return;
-			init_completion(&usb_req->write_done);
 			usb_req->sg = devm_kzalloc(tmcdrvdata->dev,
 					sizeof(*(usb_req->sg)) * req_sg_num,
 					GFP_KERNEL);
diff --git a/drivers/soc/qcom/qdss_bridge.c b/drivers/soc/qcom/qdss_bridge.c
index d9e1422..4d15790 100644
--- a/drivers/soc/qcom/qdss_bridge.c
+++ b/drivers/soc/qcom/qdss_bridge.c
@@ -108,7 +108,6 @@
 
 		buf = kzalloc(drvdata->mtu, GFP_KERNEL);
 		usb_req = kzalloc(sizeof(*usb_req), GFP_KERNEL);
-		init_completion(&usb_req->write_done);
 
 		entry->buf = buf;
 		entry->usb_req = usb_req;
diff --git a/drivers/usb/gadget/function/f_qdss.c b/drivers/usb/gadget/function/f_qdss.c
index 4742b9b..329bee7 100644
--- a/drivers/usb/gadget/function/f_qdss.c
+++ b/drivers/usb/gadget/function/f_qdss.c
@@ -219,7 +219,8 @@
 	struct usb_request *req)
 {
 	struct f_qdss *qdss = ep->driver_data;
-	struct qdss_request *d_req = req->context;
+	struct qdss_req *qreq = req->context;
+	struct qdss_request *d_req = qreq->qdss_req;
 	struct usb_ep *in;
 	struct list_head *list_pool;
 	enum qdss_state state;
@@ -239,9 +240,9 @@
 
 	spin_lock_irqsave(&qdss->lock, flags);
 	if (!qdss->debug_inface_enabled)
-		list_del(&req->list);
-	list_add_tail(&req->list, list_pool);
-	complete(&d_req->write_done);
+		list_del(&qreq->list);
+	list_add_tail(&qreq->list, list_pool);
+	complete(&qreq->write_done);
 	if (req->length != 0) {
 		d_req->actual = req->actual;
 		d_req->status = req->status;
@@ -255,8 +256,8 @@
 void usb_qdss_free_req(struct usb_qdss_ch *ch)
 {
 	struct f_qdss *qdss;
-	struct usb_request *req;
 	struct list_head *act, *tmp;
+	struct qdss_req *qreq;
 
 	qdss = ch->priv_usb;
 	if (!qdss) {
@@ -267,15 +268,19 @@
 	qdss_log("%s: channel name = %s\n", __func__, qdss->ch.name);
 
 	list_for_each_safe(act, tmp, &qdss->data_write_pool) {
-		req = list_entry(act, struct usb_request, list);
-		list_del(&req->list);
-		usb_ep_free_request(qdss->port.data, req);
+		qreq = list_entry(act, struct qdss_req, list);
+		list_del(&qreq->list);
+		usb_ep_free_request(qdss->port.data, qreq->usb_req);
+		kfree(qreq);
+
 	}
 
 	list_for_each_safe(act, tmp, &qdss->ctrl_write_pool) {
-		req = list_entry(act, struct usb_request, list);
-		list_del(&req->list);
-		usb_ep_free_request(qdss->port.ctrl_in, req);
+		qreq = list_entry(act, struct qdss_req, list);
+		list_del(&qreq->list);
+		usb_ep_free_request(qdss->port.ctrl_in, qreq->usb_req);
+		kfree(qreq);
+
 	}
 }
 EXPORT_SYMBOL(usb_qdss_free_req);
@@ -287,6 +292,7 @@
 	struct usb_ep *in;
 	struct list_head *list_pool;
 	int i;
+	struct qdss_req *qreq;
 
 	qdss_log("%s\n", __func__);
 
@@ -310,13 +316,17 @@
 	}
 
 	for (i = 0; i < no_write_buf; i++) {
+		qreq = kzalloc(sizeof(struct qdss_req), GFP_KERNEL);
 		req = usb_ep_alloc_request(in, GFP_ATOMIC);
 		if (!req) {
 			pr_err("%s: ctrl_in allocation err\n", __func__);
 			goto fail;
 		}
+		qreq->usb_req = req;
+		req->context = qreq;
 		req->complete = qdss_write_complete;
-		list_add_tail(&req->list, list_pool);
+		list_add_tail(&qreq->list, list_pool);
+		init_completion(&qreq->write_done);
 	}
 
 	return 0;
@@ -784,6 +794,7 @@
 	struct f_qdss *qdss = ch->priv_usb;
 	unsigned long flags;
 	struct usb_request *req = NULL;
+	struct qdss_req *qreq;
 
 	qdss_log("%s\n", __func__);
 
@@ -803,17 +814,18 @@
 		return -EAGAIN;
 	}
 
-	req = list_first_entry(&qdss->ctrl_write_pool, struct usb_request,
+	qreq = list_first_entry(&qdss->ctrl_write_pool, struct qdss_req,
 		list);
-	list_del(&req->list);
+	list_del(&qreq->list);
 	spin_unlock_irqrestore(&qdss->lock, flags);
 
+	qreq->qdss_req = d_req;
+	req = qreq->usb_req;
 	req->buf = d_req->buf;
 	req->length = d_req->length;
-	req->context = d_req;
 	if (usb_ep_queue(qdss->port.ctrl_in, req, GFP_ATOMIC)) {
 		spin_lock_irqsave(&qdss->lock, flags);
-		list_add_tail(&req->list, &qdss->ctrl_write_pool);
+		list_add_tail(&qreq->list, &qdss->ctrl_write_pool);
 		spin_unlock_irqrestore(&qdss->lock, flags);
 		pr_err("%s usb_ep_queue failed\n", __func__);
 		return -EIO;
@@ -828,6 +840,7 @@
 	struct f_qdss *qdss = ch->priv_usb;
 	unsigned long flags;
 	struct usb_request *req = NULL;
+	struct qdss_req *qreq;
 
 	qdss_log("usb_qdss_data_write\n");
 
@@ -847,23 +860,24 @@
 		return -EAGAIN;
 	}
 
-	req = list_first_entry(&qdss->data_write_pool, struct usb_request,
+	qreq = list_first_entry(&qdss->data_write_pool, struct qdss_req,
 		list);
-	list_move_tail(&req->list, &qdss->queued_data_pool);
+	list_move_tail(&qreq->list, &qdss->queued_data_pool);
 	spin_unlock_irqrestore(&qdss->lock, flags);
 
+	qreq->qdss_req = d_req;
+	req = qreq->usb_req;
 	req->buf = d_req->buf;
 	req->length = d_req->length;
-	req->context = d_req;
 	req->sg = d_req->sg;
 	req->num_sgs = d_req->num_sgs;
 	req->num_mapped_sgs = d_req->num_mapped_sgs;
-	reinit_completion(&d_req->write_done);
+	reinit_completion(&qreq->write_done);
 	if (usb_ep_queue(qdss->port.data, req, GFP_ATOMIC)) {
 		spin_lock_irqsave(&qdss->lock, flags);
 		/* Remove from queued pool and add back to data pool */
-		list_move_tail(&req->list, &qdss->data_write_pool);
-		complete(&d_req->write_done);
+		list_move_tail(&qreq->list, &qdss->data_write_pool);
+		complete(&qreq->write_done);
 		spin_unlock_irqrestore(&qdss->lock, flags);
 		pr_err("qdss usb_ep_queue failed\n");
 		return -EIO;
@@ -927,8 +941,7 @@
 	struct usb_gadget *gadget;
 	unsigned long flags;
 	int status;
-	struct usb_request *req;
-	struct qdss_request *d_req;
+	struct qdss_req *qreq;
 
 	qdss_log("%s\n", __func__);
 
@@ -937,12 +950,11 @@
 		goto close;
 	qdss->qdss_close = true;
 	while (!list_empty(&qdss->queued_data_pool)) {
-		req = list_first_entry(&qdss->queued_data_pool,
-				struct usb_request, list);
-		d_req = req->context;
+		qreq = list_first_entry(&qdss->queued_data_pool,
+				struct qdss_req, list);
 		spin_unlock_irqrestore(&qdss_lock, flags);
-		usb_ep_dequeue(qdss->port.data, req);
-		wait_for_completion(&d_req->write_done);
+		usb_ep_dequeue(qdss->port.data, qreq->usb_req);
+		wait_for_completion(&qreq->write_done);
 		spin_lock_irqsave(&qdss_lock, flags);
 	}
 	usb_qdss_free_req(ch);
diff --git a/include/linux/usb/usb_qdss.h b/include/linux/usb/usb_qdss.h
index 8af6f6e..645d6f6 100644
--- a/include/linux/usb/usb_qdss.h
+++ b/include/linux/usb/usb_qdss.h
@@ -20,7 +20,6 @@
 	struct scatterlist *sg;
 	unsigned int num_sgs;
 	unsigned int num_mapped_sgs;
-	struct completion write_done;
 };
 
 struct usb_qdss_ch {
@@ -41,6 +40,13 @@
 	USB_QDSS_CTRL_WRITE_DONE,
 };
 
+struct qdss_req {
+	struct usb_request *usb_req;
+	struct completion write_done;
+	struct qdss_request *qdss_req;
+	struct list_head list;
+};
+
 #if IS_ENABLED(CONFIG_USB_F_QDSS)
 struct usb_qdss_ch *usb_qdss_open(const char *name, void *priv,
 	void (*notify)(void *priv, unsigned int event,