[PATCH v2] usb: cdns3: Handle ZLP request allocation failure

Triet Hoang <[email protected]>
Newsgroups org.kernel.vger.linux-kernel,org.kernel.vger.linux-usb
Message-ID <[email protected]>
Check the return value of cdns3_gadget_ep_alloc_request() before
dereferencing the returned request.

Changes in v2:
- Allocate the ZLP request before queuing the primary request.
- Free the allocated ZLP request when the primary request queueing fails.

Signed-off-by: Triet Hoang <[email protected]>
---
 drivers/usb/cdns3/cdns3-gadget.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c
index 42311c1bfada..05d225f99012 100644
--- a/drivers/usb/cdns3/cdns3-gadget.c
+++ b/drivers/usb/cdns3/cdns3-gadget.c
@@ -2641,7 +2641,7 @@ static int __cdns3_gadget_ep_queue(struct usb_ep *ep,
 static int cdns3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
 				 gfp_t gfp_flags)
 {
-	struct usb_request *zlp_request;
+	struct usb_request *zlp_request = NULL;
 	struct cdns3_endpoint *priv_ep;
 	struct cdns3_device *priv_dev;
 	unsigned long flags;
@@ -2655,24 +2655,36 @@ static int cdns3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
 
 	spin_lock_irqsave(&priv_dev->lock, flags);
 
-	ret = __cdns3_gadget_ep_queue(ep, request, gfp_flags);
-
-	if (ret == 0 && request->zero && request->length &&
+	if (request->zero && request->length &&
 	    (request->length % ep->maxpacket == 0)) {
 		struct cdns3_request *priv_req;
 
 		zlp_request = cdns3_gadget_ep_alloc_request(ep, GFP_ATOMIC);
+		if (!zlp_request) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
 		zlp_request->buf = priv_dev->zlp_buf;
 		zlp_request->length = 0;
 
 		priv_req = to_cdns3_request(zlp_request);
 		priv_req->flags |= REQUEST_ZLP;
+	}
+
+	ret = __cdns3_gadget_ep_queue(ep, request, gfp_flags);
+	if (ret)
+		goto out;
 
+	if (zlp_request) {
 		dev_dbg(priv_dev->dev, "Queuing ZLP for endpoint: %s\n",
 			priv_ep->name);
 		ret = __cdns3_gadget_ep_queue(ep, zlp_request, gfp_flags);
 	}
 
+out:
+	if (ret && zlp_request)
+		cdns3_gadget_ep_free_request(ep, zlp_request);
 	spin_unlock_irqrestore(&priv_dev->lock, flags);
 	return ret;
 }
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.