4.14-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Takashi Iwai <ti...@suse.de>

commit e901b9873876ca30a09253731bd3a6b00c44b5b0 upstream.

This patch adds a new helper function to perform a sanity check of the
given URB to see whether it contains a valid endpoint.  It's a light-
weight version of what usb_submit_urb() does, but without the kernel
warning followed by the stack trace, just returns an error code.

Especially for a driver that doesn't parse the descriptor but fills
the URB with the fixed endpoint (e.g. some quirks for non-compliant
devices), this kind of check is preferable at the probe phase before
actually submitting the urb.

Tested-by: Andrey Konovalov <andreyk...@google.com>
Acked-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
Signed-off-by: Takashi Iwai <ti...@suse.de>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 drivers/usb/core/urb.c |   30 ++++++++++++++++++++++++++----
 include/linux/usb.h    |    2 ++
 2 files changed, 28 insertions(+), 4 deletions(-)

--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -187,6 +187,31 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
 
 /*-------------------------------------------------------------------*/
 
+static const int pipetypes[4] = {
+       PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
+};
+
+/**
+ * usb_urb_ep_type_check - sanity check of endpoint in the given urb
+ * @urb: urb to be checked
+ *
+ * This performs a light-weight sanity check for the endpoint in the
+ * given urb.  It returns 0 if the urb contains a valid endpoint, otherwise
+ * a negative error code.
+ */
+int usb_urb_ep_type_check(const struct urb *urb)
+{
+       const struct usb_host_endpoint *ep;
+
+       ep = usb_pipe_endpoint(urb->dev, urb->pipe);
+       if (!ep)
+               return -EINVAL;
+       if (usb_pipetype(urb->pipe) != pipetypes[usb_endpoint_type(&ep->desc)])
+               return -EINVAL;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(usb_urb_ep_type_check);
+
 /**
  * usb_submit_urb - issue an asynchronous transfer request for an endpoint
  * @urb: pointer to the urb describing the request
@@ -326,9 +351,6 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
  */
 int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 {
-       static int                      pipetypes[4] = {
-               PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
-       };
        int                             xfertype, max;
        struct usb_device               *dev;
        struct usb_host_endpoint        *ep;
@@ -444,7 +466,7 @@ int usb_submit_urb(struct urb *urb, gfp_
         */
 
        /* Check that the pipe's type matches the endpoint's type */
-       if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
+       if (usb_urb_ep_type_check(urb))
                dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
                        usb_pipetype(urb->pipe), pipetypes[xfertype]);
 
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1729,6 +1729,8 @@ static inline int usb_urb_dir_out(struct
        return (urb->transfer_flags & URB_DIR_MASK) == URB_DIR_OUT;
 }
 
+int usb_urb_ep_type_check(const struct urb *urb);
+
 void *usb_alloc_coherent(struct usb_device *dev, size_t size,
        gfp_t mem_flags, dma_addr_t *dma);
 void usb_free_coherent(struct usb_device *dev, size_t size,


Reply via email to