aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>2016-08-04 06:59:41 -0400
committerVinod Koul <vinod.koul@intel.com>2016-08-08 04:12:06 -0400
commit626d2f07de89bf6be3d7301524d0ab3375b81b9c (patch)
treea6295aa86917d7a92f066098183b66f8b809c43b
parent29b4817d4018df78086157ea3a55c1d9424a7cfc (diff)
dmaengine: usb-dmac: check CHCR.DE bit in usb_dmac_isr_channel()
The USB-DMAC's interruption happens even if the CHCR.DE is not set to 1 because CHCR.NULLE is set to 1. So, this driver should call usb_dmac_isr_transfer_end() if the DE bit is set to 1 only. Otherwise, the desc is possible to be NULL in the usb_dmac_isr_transfer_end(). Fixes: 0c1c8ff32fa2 ("dmaengine: usb-dmac: Add Renesas USB DMA Controller (USB-DMAC) driver) Cc: <stable@vger.kernel.org> # v4.1+ Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r--drivers/dma/sh/usb-dmac.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/drivers/dma/sh/usb-dmac.c b/drivers/dma/sh/usb-dmac.c
index 749f1bd5d65d..06ecdc38cee0 100644
--- a/drivers/dma/sh/usb-dmac.c
+++ b/drivers/dma/sh/usb-dmac.c
@@ -600,27 +600,30 @@ static irqreturn_t usb_dmac_isr_channel(int irq, void *dev)
600{ 600{
601 struct usb_dmac_chan *chan = dev; 601 struct usb_dmac_chan *chan = dev;
602 irqreturn_t ret = IRQ_NONE; 602 irqreturn_t ret = IRQ_NONE;
603 u32 mask = USB_DMACHCR_TE; 603 u32 mask = 0;
604 u32 check_bits = USB_DMACHCR_TE | USB_DMACHCR_SP;
605 u32 chcr; 604 u32 chcr;
605 bool xfer_end = false;
606 606
607 spin_lock(&chan->vc.lock); 607 spin_lock(&chan->vc.lock);
608 608
609 chcr = usb_dmac_chan_read(chan, USB_DMACHCR); 609 chcr = usb_dmac_chan_read(chan, USB_DMACHCR);
610 if (chcr & check_bits) 610 if (chcr & (USB_DMACHCR_TE | USB_DMACHCR_SP)) {
611 mask |= USB_DMACHCR_DE | check_bits; 611 mask |= USB_DMACHCR_DE | USB_DMACHCR_TE | USB_DMACHCR_SP;
612 if (chcr & USB_DMACHCR_DE)
613 xfer_end = true;
614 ret |= IRQ_HANDLED;
615 }
612 if (chcr & USB_DMACHCR_NULL) { 616 if (chcr & USB_DMACHCR_NULL) {
613 /* An interruption of TE will happen after we set FTE */ 617 /* An interruption of TE will happen after we set FTE */
614 mask |= USB_DMACHCR_NULL; 618 mask |= USB_DMACHCR_NULL;
615 chcr |= USB_DMACHCR_FTE; 619 chcr |= USB_DMACHCR_FTE;
616 ret |= IRQ_HANDLED; 620 ret |= IRQ_HANDLED;
617 } 621 }
618 usb_dmac_chan_write(chan, USB_DMACHCR, chcr & ~mask); 622 if (mask)
623 usb_dmac_chan_write(chan, USB_DMACHCR, chcr & ~mask);
619 624
620 if (chcr & check_bits) { 625 if (xfer_end)
621 usb_dmac_isr_transfer_end(chan); 626 usb_dmac_isr_transfer_end(chan);
622 ret |= IRQ_HANDLED;
623 }
624 627
625 spin_unlock(&chan->vc.lock); 628 spin_unlock(&chan->vc.lock);
626 629