3.2.84-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@xxxxxxxxxxx> commit 4fdef698383db07d829da567e0e405fc41ff3a89 upstream. This patch fixes an issue that the xfer_work() is possible to cause NULL pointer dereference if the usb cable is disconnected while data transfer is running. In such case, a gadget driver may call usb_ep_disable()) before xfer_work() is actually called. In this case, the usbhs_pkt_pop() will call usbhsf_fifo_unselect(), and then usbhs_pipe_to_fifo() in xfer_work() will return NULL. Fixes: e73a989 ("usb: renesas_usbhs: add DMAEngine support") Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@xxxxxxxxxxx> Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxxxxxxxx> [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx> --- drivers/usb/renesas_usbhs/fifo.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -760,15 +760,22 @@ static void usbhsf_dma_prepare_tasklet(u { struct usbhs_pkt *pkt = (struct usbhs_pkt *)data; struct usbhs_pipe *pipe = pkt->pipe; - struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe); + struct usbhs_fifo *fifo; struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); struct scatterlist sg; struct dma_async_tx_descriptor *desc; - struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt); + struct dma_chan *chan; struct device *dev = usbhs_priv_to_dev(priv); enum dma_data_direction dir; dma_cookie_t cookie; + unsigned long flags; + usbhs_lock(priv, flags); + fifo = usbhs_pipe_to_fifo(pipe); + if (!fifo) + goto xfer_work_end; + + chan = usbhsf_dma_chan_get(fifo, pkt); dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; sg_init_table(&sg, 1); @@ -781,7 +788,7 @@ static void usbhsf_dma_prepare_tasklet(u DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) - return; + goto xfer_work_end; desc->callback = usbhsf_dma_complete; desc->callback_param = pipe; @@ -789,7 +796,7 @@ static void usbhsf_dma_prepare_tasklet(u cookie = desc->tx_submit(desc); if (cookie < 0) { dev_err(dev, "Failed to submit dma descriptor\n"); - return; + goto xfer_work_end; } dev_dbg(dev, " %s %d (%d/ %d)\n", @@ -797,6 +804,9 @@ static void usbhsf_dma_prepare_tasklet(u usbhsf_dma_start(pipe, fifo); dma_async_issue_pending(chan); + +xfer_work_end: + usbhs_unlock(priv, flags); } /* -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html