| From e09e6cd7d4514003abfa1fed4e993f6a7de58d93 Mon Sep 17 00:00:00 2001 |
| From: Krzysztof Kozlowski <krzk@kernel.org> |
| Date: Thu, 11 Jun 2020 15:21:05 +0200 |
| Subject: [PATCH] dmaengine: mcf-edma: Fix NULL pointer exception in |
| mcf_edma_tx_handler |
| |
| commit 8995aa3d164ddd9200e6abcf25c449cf5298c858 upstream. |
| |
| On Toradex Colibri VF50 (Vybrid VF5xx) with fsl-edma driver NULL pointer |
| exception happens occasionally on serial output initiated by login |
| timeout. |
| |
| This was reproduced only if kernel was built with significant debugging |
| options and EDMA driver is used with serial console. |
| |
| Issue looks like a race condition between interrupt handler |
| fsl_edma_tx_handler() (called as a result of fsl_edma_xfer_desc()) and |
| terminating the transfer with fsl_edma_terminate_all(). |
| |
| The fsl_edma_tx_handler() handles interrupt for a transfer with already |
| freed edesc and idle==true. |
| |
| The mcf-edma driver shares design and lot of code with fsl-edma. It |
| looks like being affected by same problem. Fix this pattern the same |
| way as fix for fsl-edma driver. |
| |
| Fixes: e7a3ff92eaf1 ("dmaengine: fsl-edma: add ColdFire mcf5441x edma support") |
| Cc: <stable@vger.kernel.org> |
| Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org> |
| Reviewed-by: Robin Gong <yibin.gong@nxp.com> |
| Link: https://lore.kernel.org/r/1591881665-25592-1-git-send-email-krzk@kernel.org |
| Signed-off-by: Vinod Koul <vkoul@kernel.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/dma/mcf-edma.c b/drivers/dma/mcf-edma.c |
| index 7de54b2fafdb..6e3d4ab34321 100644 |
| --- a/drivers/dma/mcf-edma.c |
| +++ b/drivers/dma/mcf-edma.c |
| @@ -35,6 +35,13 @@ static irqreturn_t mcf_edma_tx_handler(int irq, void *dev_id) |
| mcf_chan = &mcf_edma->chans[ch]; |
| |
| spin_lock(&mcf_chan->vchan.lock); |
| + |
| + if (!mcf_chan->edesc) { |
| + /* terminate_all called before */ |
| + spin_unlock(&mcf_chan->vchan.lock); |
| + continue; |
| + } |
| + |
| if (!mcf_chan->edesc->iscyclic) { |
| list_del(&mcf_chan->edesc->vdesc.node); |
| vchan_cookie_complete(&mcf_chan->edesc->vdesc); |
| -- |
| 2.27.0 |
| |