This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MUSB driver crash on TI am335x

we are experiencing crashes in the TI MUSB driver (USB host) when we subject it to many small transfers.

This pattern occurs when running the rt28xx WiFi drivers, which issue a sequence of small USB vendor requests in occasional bursts.

I have attached the full kernel crash dump.

The function that blows up is musb_start_urb, which I understand is supposed to kick the hardware queue if necessary to start processing of previously added URBs (USB packets).

However, there appears to be a race condition and the URB is gone by the time the function is called. the next_urb(qh) function returns NULL and then blows up when it's dereferenced:

/*

 * Start the URB at the front of an endpoint's queue

 * end must be claimed from the caller.

 *

 * Context: controller locked, irqs blocked  */ static void musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) {

                u16                                         frame;

                u32                                         len;

                void __iomem                   *mbase =  musb->mregs;

                struct urb                            *urb = next_urb(qh);

                void                                       *buf = urb->transfer_buffer; <<<<Crash happens here, urb is NULL.

                u32                                         offset = 0;

                struct musb_hw_ep       *hw_ep = qh->hw_ep;

                unsigned                             pipe = urb->pipe;

                u8                                           address = usb_pipedevice(pipe);

                int                                           epnum = hw_ep->epnum;

 

                /* initialize software qh state */

                qh->offset = 0;

                qh->segsize = 0;

                hw_ep->xfer_type = qh->type;

...