mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-28 16:53:49 +00:00
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: ee17028009
("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>
This commit is contained in:
parent
362f1bf98a
commit
ebc008699f
@ -231,6 +231,7 @@ struct tegra_dma_channel {
|
|||||||
bool config_init;
|
bool config_init;
|
||||||
char name[30];
|
char name[30];
|
||||||
enum dma_transfer_direction sid_dir;
|
enum dma_transfer_direction sid_dir;
|
||||||
|
enum dma_status status;
|
||||||
int id;
|
int id;
|
||||||
int irq;
|
int irq;
|
||||||
int slave_id;
|
int slave_id;
|
||||||
@ -393,6 +394,8 @@ static int tegra_dma_pause(struct tegra_dma_channel *tdc)
|
|||||||
tegra_dma_dump_chan_regs(tdc);
|
tegra_dma_dump_chan_regs(tdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tdc->status = DMA_PAUSED;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,6 +422,8 @@ static void tegra_dma_resume(struct tegra_dma_channel *tdc)
|
|||||||
val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE);
|
val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE);
|
||||||
val &= ~TEGRA_GPCDMA_CHAN_CSRE_PAUSE;
|
val &= ~TEGRA_GPCDMA_CHAN_CSRE_PAUSE;
|
||||||
tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSRE, val);
|
tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSRE, val);
|
||||||
|
|
||||||
|
tdc->status = DMA_IN_PROGRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_dma_device_resume(struct dma_chan *dc)
|
static int tegra_dma_device_resume(struct dma_chan *dc)
|
||||||
@ -544,6 +549,7 @@ static void tegra_dma_xfer_complete(struct tegra_dma_channel *tdc)
|
|||||||
|
|
||||||
tegra_dma_sid_free(tdc);
|
tegra_dma_sid_free(tdc);
|
||||||
tdc->dma_desc = NULL;
|
tdc->dma_desc = NULL;
|
||||||
|
tdc->status = DMA_COMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra_dma_chan_decode_error(struct tegra_dma_channel *tdc,
|
static void tegra_dma_chan_decode_error(struct tegra_dma_channel *tdc,
|
||||||
@ -716,6 +722,7 @@ static int tegra_dma_terminate_all(struct dma_chan *dc)
|
|||||||
tdc->dma_desc = NULL;
|
tdc->dma_desc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tdc->status = DMA_COMPLETE;
|
||||||
tegra_dma_sid_free(tdc);
|
tegra_dma_sid_free(tdc);
|
||||||
vchan_get_all_descriptors(&tdc->vc, &head);
|
vchan_get_all_descriptors(&tdc->vc, &head);
|
||||||
spin_unlock_irqrestore(&tdc->vc.lock, flags);
|
spin_unlock_irqrestore(&tdc->vc.lock, flags);
|
||||||
@ -769,6 +776,9 @@ static enum dma_status tegra_dma_tx_status(struct dma_chan *dc,
|
|||||||
if (ret == DMA_COMPLETE)
|
if (ret == DMA_COMPLETE)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (tdc->status == DMA_PAUSED)
|
||||||
|
ret = DMA_PAUSED;
|
||||||
|
|
||||||
spin_lock_irqsave(&tdc->vc.lock, flags);
|
spin_lock_irqsave(&tdc->vc.lock, flags);
|
||||||
vd = vchan_find_desc(&tdc->vc, cookie);
|
vd = vchan_find_desc(&tdc->vc, cookie);
|
||||||
if (vd) {
|
if (vd) {
|
||||||
|
Loading…
Reference in New Issue
Block a user