Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dmaengine: tegra: Return correct DMA status when paused

Currently, the driver does not return the correct DMA status when a DMA
pause is issued by the client drivers. This causes GPCDMA users to
assume that DMA is still running, while in reality, the DMA is paused.

Return DMA_PAUSED for tx_status() if the channel is paused in the middle
of a transfer.

Fixes: ee17028009d4 ("dmaengine: tegra: Add tegra gpcdma driver")
Cc: stable@vger.kernel.org
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Signed-off-by: Kartik Rajput <kkartik@nvidia.com>
Link: https://lore.kernel.org/r/20241212124412.5650-1-kkartik@nvidia.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Akhil R and committed by
Vinod Koul
ebc00869 362f1bf9

+10
+10
drivers/dma/tegra186-gpc-dma.c
··· 231 231 bool config_init; 232 232 char name[30]; 233 233 enum dma_transfer_direction sid_dir; 234 + enum dma_status status; 234 235 int id; 235 236 int irq; 236 237 int slave_id; ··· 394 393 tegra_dma_dump_chan_regs(tdc); 395 394 } 396 395 396 + tdc->status = DMA_PAUSED; 397 + 397 398 return ret; 398 399 } 399 400 ··· 422 419 val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE); 423 420 val &= ~TEGRA_GPCDMA_CHAN_CSRE_PAUSE; 424 421 tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSRE, val); 422 + 423 + tdc->status = DMA_IN_PROGRESS; 425 424 } 426 425 427 426 static int tegra_dma_device_resume(struct dma_chan *dc) ··· 549 544 550 545 tegra_dma_sid_free(tdc); 551 546 tdc->dma_desc = NULL; 547 + tdc->status = DMA_COMPLETE; 552 548 } 553 549 554 550 static void tegra_dma_chan_decode_error(struct tegra_dma_channel *tdc, ··· 722 716 tdc->dma_desc = NULL; 723 717 } 724 718 719 + tdc->status = DMA_COMPLETE; 725 720 tegra_dma_sid_free(tdc); 726 721 vchan_get_all_descriptors(&tdc->vc, &head); 727 722 spin_unlock_irqrestore(&tdc->vc.lock, flags); ··· 775 768 ret = dma_cookie_status(dc, cookie, txstate); 776 769 if (ret == DMA_COMPLETE) 777 770 return ret; 771 + 772 + if (tdc->status == DMA_PAUSED) 773 + ret = DMA_PAUSED; 778 774 779 775 spin_lock_irqsave(&tdc->vc.lock, flags); 780 776 vd = vchan_find_desc(&tdc->vc, cookie);