Skip to content

Commit

Permalink
dmaengine: tegra: Add terminate() for Tegra234
Browse files Browse the repository at this point in the history
[ Upstream commit 36834c6 ]

In certain cases where the DMA client bus gets corrupted or if the
end device ceases to send/receive data, DMA can wait indefinitely
for the data to be received/sent. Attempting to terminate the transfer
will put the DMA in pause flush mode and it remains there.

The channel is irrecoverable once this pause times out in Tegra194 and
earlier chips. Whereas, from Tegra234, it can be recovered by disabling
the channel and reprograming it.

Hence add a new terminate() function that ignores the outcome of
dma_pause() so that terminate_all() can proceed to disable the channel.

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Link: https://lore.kernel.org/r/20220720104045.16099-3-akhilrajeev@nvidia.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Akhil R authored and gregkh committed Aug 25, 2022
1 parent 59e6595 commit 32a9798
Showing 1 changed file with 24 additions and 2 deletions.
26 changes: 24 additions & 2 deletions drivers/dma/tegra186-gpc-dma.c
Expand Up @@ -157,8 +157,8 @@
* If any burst is in flight and DMA paused then this is the time to complete
* on-flight burst and update DMA status register.
*/
#define TEGRA_GPCDMA_BURST_COMPLETE_TIME 20
#define TEGRA_GPCDMA_BURST_COMPLETION_TIMEOUT 100
#define TEGRA_GPCDMA_BURST_COMPLETE_TIME 10
#define TEGRA_GPCDMA_BURST_COMPLETION_TIMEOUT 5000 /* 5 msec */

/* Channel base address offset from GPCDMA base address */
#define TEGRA_GPCDMA_CHANNEL_BASE_ADD_OFFSET 0x20000
Expand Down Expand Up @@ -432,6 +432,17 @@ static int tegra_dma_device_resume(struct dma_chan *dc)
return 0;
}

static inline int tegra_dma_pause_noerr(struct tegra_dma_channel *tdc)
{
/* Return 0 irrespective of PAUSE status.
* This is useful to recover channels that can exit out of flush
* state when the channel is disabled.
*/

tegra_dma_pause(tdc);
return 0;
}

static void tegra_dma_disable(struct tegra_dma_channel *tdc)
{
u32 csr, status;
Expand Down Expand Up @@ -1292,13 +1303,24 @@ static const struct tegra_dma_chip_data tegra194_dma_chip_data = {
.terminate = tegra_dma_pause,
};

static const struct tegra_dma_chip_data tegra234_dma_chip_data = {
.nr_channels = 31,
.channel_reg_size = SZ_64K,
.max_dma_count = SZ_1G,
.hw_support_pause = true,
.terminate = tegra_dma_pause_noerr,
};

static const struct of_device_id tegra_dma_of_match[] = {
{
.compatible = "nvidia,tegra186-gpcdma",
.data = &tegra186_dma_chip_data,
}, {
.compatible = "nvidia,tegra194-gpcdma",
.data = &tegra194_dma_chip_data,
}, {
.compatible = "nvidia,tegra234-gpcdma",
.data = &tegra234_dma_chip_data,
}, {
},
};
Expand Down

0 comments on commit 32a9798

Please sign in to comment.