Commit ac810384 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'dmaengine-fix-4.8-rc5' of git://git.infradead.org/users/vkoul/slave-dma

Pull dmaengine fixes from Vinod Koul:
 "The fixes this time are all in drivers:

   - possible NULL dereference in img-mdc
   - correct device identity for free_irq in at_xdmac
   - missing of_node_put() in fsl probe
   - fix debug log and hotchain corner case for pxa-dma
   - fix checking hardware bits in isr in usb dmac"

* tag 'dmaengine-fix-4.8-rc5' of git://git.infradead.org/users/vkoul/slave-dma:
  dmaengine: img-mdc: fix a possible NULL dereference
  dmaengine: at_xdmac: fix to pass correct device identity to free_irq()
  dmaengine: fsl_raid: add missing of_node_put() in fsl_re_probe()
  dmaengine: pxa_dma: fix debug message
  dmaengine: pxa_dma: fix hotchain corner case
  dmaengine: usb-dmac: check CHCR.DE bit in usb_dmac_isr_channel()
parents b0be76bf 32e80820
...@@ -2067,7 +2067,7 @@ static int at_xdmac_probe(struct platform_device *pdev) ...@@ -2067,7 +2067,7 @@ static int at_xdmac_probe(struct platform_device *pdev)
err_clk_disable: err_clk_disable:
clk_disable_unprepare(atxdmac->clk); clk_disable_unprepare(atxdmac->clk);
err_free_irq: err_free_irq:
free_irq(atxdmac->irq, atxdmac->dma.dev); free_irq(atxdmac->irq, atxdmac);
return ret; return ret;
} }
...@@ -2081,7 +2081,7 @@ static int at_xdmac_remove(struct platform_device *pdev) ...@@ -2081,7 +2081,7 @@ static int at_xdmac_remove(struct platform_device *pdev)
dma_async_device_unregister(&atxdmac->dma); dma_async_device_unregister(&atxdmac->dma);
clk_disable_unprepare(atxdmac->clk); clk_disable_unprepare(atxdmac->clk);
free_irq(atxdmac->irq, atxdmac->dma.dev); free_irq(atxdmac->irq, atxdmac);
for (i = 0; i < atxdmac->dma.chancnt; i++) { for (i = 0; i < atxdmac->dma.chancnt; i++) {
struct at_xdmac_chan *atchan = &atxdmac->chan[i]; struct at_xdmac_chan *atchan = &atxdmac->chan[i];
......
...@@ -836,6 +836,7 @@ static int fsl_re_probe(struct platform_device *ofdev) ...@@ -836,6 +836,7 @@ static int fsl_re_probe(struct platform_device *ofdev)
rc = of_property_read_u32(np, "reg", &off); rc = of_property_read_u32(np, "reg", &off);
if (rc) { if (rc) {
dev_err(dev, "Reg property not found in JQ node\n"); dev_err(dev, "Reg property not found in JQ node\n");
of_node_put(np);
return -ENODEV; return -ENODEV;
} }
/* Find out the Job Rings present under each JQ */ /* Find out the Job Rings present under each JQ */
......
...@@ -861,7 +861,6 @@ static int mdc_dma_probe(struct platform_device *pdev) ...@@ -861,7 +861,6 @@ static int mdc_dma_probe(struct platform_device *pdev)
{ {
struct mdc_dma *mdma; struct mdc_dma *mdma;
struct resource *res; struct resource *res;
const struct of_device_id *match;
unsigned int i; unsigned int i;
u32 val; u32 val;
int ret; int ret;
...@@ -871,8 +870,7 @@ static int mdc_dma_probe(struct platform_device *pdev) ...@@ -871,8 +870,7 @@ static int mdc_dma_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(pdev, mdma); platform_set_drvdata(pdev, mdma);
match = of_match_device(mdc_dma_of_match, &pdev->dev); mdma->soc = of_device_get_match_data(&pdev->dev);
mdma->soc = match->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mdma->regs = devm_ioremap_resource(&pdev->dev, res); mdma->regs = devm_ioremap_resource(&pdev->dev, res);
......
...@@ -638,7 +638,7 @@ static bool pxad_try_hotchain(struct virt_dma_chan *vc, ...@@ -638,7 +638,7 @@ static bool pxad_try_hotchain(struct virt_dma_chan *vc,
vd_last_issued = list_entry(vc->desc_issued.prev, vd_last_issued = list_entry(vc->desc_issued.prev,
struct virt_dma_desc, node); struct virt_dma_desc, node);
pxad_desc_chain(vd_last_issued, vd); pxad_desc_chain(vd_last_issued, vd);
if (is_chan_running(chan) || is_desc_completed(vd_last_issued)) if (is_chan_running(chan) || is_desc_completed(vd))
return true; return true;
} }
...@@ -671,6 +671,7 @@ static irqreturn_t pxad_chan_handler(int irq, void *dev_id) ...@@ -671,6 +671,7 @@ static irqreturn_t pxad_chan_handler(int irq, void *dev_id)
struct virt_dma_desc *vd, *tmp; struct virt_dma_desc *vd, *tmp;
unsigned int dcsr; unsigned int dcsr;
unsigned long flags; unsigned long flags;
bool vd_completed;
dma_cookie_t last_started = 0; dma_cookie_t last_started = 0;
BUG_ON(!chan); BUG_ON(!chan);
...@@ -681,15 +682,17 @@ static irqreturn_t pxad_chan_handler(int irq, void *dev_id) ...@@ -681,15 +682,17 @@ static irqreturn_t pxad_chan_handler(int irq, void *dev_id)
spin_lock_irqsave(&chan->vc.lock, flags); spin_lock_irqsave(&chan->vc.lock, flags);
list_for_each_entry_safe(vd, tmp, &chan->vc.desc_issued, node) { list_for_each_entry_safe(vd, tmp, &chan->vc.desc_issued, node) {
vd_completed = is_desc_completed(vd);
dev_dbg(&chan->vc.chan.dev->device, dev_dbg(&chan->vc.chan.dev->device,
"%s(): checking txd %p[%x]: completed=%d\n", "%s(): checking txd %p[%x]: completed=%d dcsr=0x%x\n",
__func__, vd, vd->tx.cookie, is_desc_completed(vd)); __func__, vd, vd->tx.cookie, vd_completed,
dcsr);
last_started = vd->tx.cookie; last_started = vd->tx.cookie;
if (to_pxad_sw_desc(vd)->cyclic) { if (to_pxad_sw_desc(vd)->cyclic) {
vchan_cyclic_callback(vd); vchan_cyclic_callback(vd);
break; break;
} }
if (is_desc_completed(vd)) { if (vd_completed) {
list_del(&vd->node); list_del(&vd->node);
vchan_cookie_complete(vd); vchan_cookie_complete(vd);
} else { } else {
......
...@@ -600,27 +600,30 @@ static irqreturn_t usb_dmac_isr_channel(int irq, void *dev) ...@@ -600,27 +600,30 @@ static irqreturn_t usb_dmac_isr_channel(int irq, void *dev)
{ {
struct usb_dmac_chan *chan = dev; struct usb_dmac_chan *chan = dev;
irqreturn_t ret = IRQ_NONE; irqreturn_t ret = IRQ_NONE;
u32 mask = USB_DMACHCR_TE; u32 mask = 0;
u32 check_bits = USB_DMACHCR_TE | USB_DMACHCR_SP;
u32 chcr; u32 chcr;
bool xfer_end = false;
spin_lock(&chan->vc.lock); spin_lock(&chan->vc.lock);
chcr = usb_dmac_chan_read(chan, USB_DMACHCR); chcr = usb_dmac_chan_read(chan, USB_DMACHCR);
if (chcr & check_bits) if (chcr & (USB_DMACHCR_TE | USB_DMACHCR_SP)) {
mask |= USB_DMACHCR_DE | check_bits; mask |= USB_DMACHCR_DE | USB_DMACHCR_TE | USB_DMACHCR_SP;
if (chcr & USB_DMACHCR_DE)
xfer_end = true;
ret |= IRQ_HANDLED;
}
if (chcr & USB_DMACHCR_NULL) { if (chcr & USB_DMACHCR_NULL) {
/* An interruption of TE will happen after we set FTE */ /* An interruption of TE will happen after we set FTE */
mask |= USB_DMACHCR_NULL; mask |= USB_DMACHCR_NULL;
chcr |= USB_DMACHCR_FTE; chcr |= USB_DMACHCR_FTE;
ret |= IRQ_HANDLED; ret |= IRQ_HANDLED;
} }
usb_dmac_chan_write(chan, USB_DMACHCR, chcr & ~mask); if (mask)
usb_dmac_chan_write(chan, USB_DMACHCR, chcr & ~mask);
if (chcr & check_bits) { if (xfer_end)
usb_dmac_isr_transfer_end(chan); usb_dmac_isr_transfer_end(chan);
ret |= IRQ_HANDLED;
}
spin_unlock(&chan->vc.lock); spin_unlock(&chan->vc.lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment