[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