Upgrade to 4.4.50-rt62
[kvmfornfv.git] / kernel / drivers / usb / renesas_usbhs / fifo.c
index c0f5c65..36e5b5c 100644 (file)
@@ -190,7 +190,8 @@ static int usbhsf_pkt_handler(struct usbhs_pipe *pipe, int type)
                goto __usbhs_pkt_handler_end;
        }
 
-       ret = func(pkt, &is_done);
+       if (likely(func))
+               ret = func(pkt, &is_done);
 
        if (is_done)
                __usbhsf_pkt_del(pkt);
@@ -807,20 +808,27 @@ static void xfer_work(struct work_struct *work)
 {
        struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work);
        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 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_transfer_direction dir;
+       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_DEV_TO_MEM : DMA_MEM_TO_DEV;
 
        desc = dmaengine_prep_slave_single(chan, pkt->dma + pkt->actual,
                                        pkt->trans, dir,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc)
-               return;
+               goto xfer_work_end;
 
        desc->callback          = usbhsf_dma_complete;
        desc->callback_param    = pipe;
@@ -828,7 +836,7 @@ static void xfer_work(struct work_struct *work)
        pkt->cookie = dmaengine_submit(desc);
        if (pkt->cookie < 0) {
                dev_err(dev, "Failed to submit dma descriptor\n");
-               return;
+               goto xfer_work_end;
        }
 
        dev_dbg(dev, "  %s %d (%d/ %d)\n",
@@ -839,6 +847,9 @@ static void xfer_work(struct work_struct *work)
        usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);
        dma_async_issue_pending(chan);
        usbhs_pipe_enable(pipe);
+
+xfer_work_end:
+       usbhs_unlock(priv, flags);
 }
 
 /*
@@ -858,7 +869,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
 
        /* use PIO if packet is less than pio_dma_border or pipe is DCP */
        if ((len < usbhs_get_dparam(priv, pio_dma_border)) ||
-           usbhs_pipe_is_dcp(pipe))
+           usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC))
                goto usbhsf_pio_prepare_push;
 
        /* check data length if this driver don't use USB-DMAC */
@@ -889,6 +900,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
 
        pkt->trans = len;
 
+       usbhsf_tx_irq_ctrl(pipe, 0);
        INIT_WORK(&pkt->work, xfer_work);
        schedule_work(&pkt->work);
 
@@ -962,7 +974,7 @@ static int usbhsf_dma_prepare_pop_with_usb_dmac(struct usbhs_pkt *pkt,
 
        /* use PIO if packet is less than pio_dma_border or pipe is DCP */
        if ((pkt->length < usbhs_get_dparam(priv, pio_dma_border)) ||
-           usbhs_pipe_is_dcp(pipe))
+           usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC))
                goto usbhsf_pio_prepare_pop;
 
        fifo = usbhsf_get_dma_fifo(priv, pkt);