18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Tegra host1x Command DMA
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2010-2013, NVIDIA Corporation.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/slab.h>
98c2ecf20Sopenharmony_ci#include <linux/scatterlist.h>
108c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include "../cdma.h"
138c2ecf20Sopenharmony_ci#include "../channel.h"
148c2ecf20Sopenharmony_ci#include "../dev.h"
158c2ecf20Sopenharmony_ci#include "../debug.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/*
188c2ecf20Sopenharmony_ci * Put the restart at the end of pushbuffer memory
198c2ecf20Sopenharmony_ci */
208c2ecf20Sopenharmony_cistatic void push_buffer_init(struct push_buffer *pb)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci	*(u32 *)(pb->mapped + pb->size) = host1x_opcode_restart(0);
238c2ecf20Sopenharmony_ci}
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci/*
268c2ecf20Sopenharmony_ci * Increment timedout buffer's syncpt via CPU.
278c2ecf20Sopenharmony_ci */
288c2ecf20Sopenharmony_cistatic void cdma_timeout_cpu_incr(struct host1x_cdma *cdma, u32 getptr,
298c2ecf20Sopenharmony_ci				u32 syncpt_incrs, u32 syncval, u32 nr_slots)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	unsigned int i;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	for (i = 0; i < syncpt_incrs; i++)
348c2ecf20Sopenharmony_ci		host1x_syncpt_incr(cdma->timeout.syncpt);
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	/* after CPU incr, ensure shadow is up to date */
378c2ecf20Sopenharmony_ci	host1x_syncpt_load(cdma->timeout.syncpt);
388c2ecf20Sopenharmony_ci}
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci/*
418c2ecf20Sopenharmony_ci * Start channel DMA
428c2ecf20Sopenharmony_ci */
438c2ecf20Sopenharmony_cistatic void cdma_start(struct host1x_cdma *cdma)
448c2ecf20Sopenharmony_ci{
458c2ecf20Sopenharmony_ci	struct host1x_channel *ch = cdma_to_channel(cdma);
468c2ecf20Sopenharmony_ci	u64 start, end;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	if (cdma->running)
498c2ecf20Sopenharmony_ci		return;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	cdma->last_pos = cdma->push_buffer.pos;
528c2ecf20Sopenharmony_ci	start = cdma->push_buffer.dma;
538c2ecf20Sopenharmony_ci	end = cdma->push_buffer.size + 4;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, HOST1X_CHANNEL_DMACTRL_DMASTOP,
568c2ecf20Sopenharmony_ci			 HOST1X_CHANNEL_DMACTRL);
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	/* set base, put and end pointer */
598c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, lower_32_bits(start), HOST1X_CHANNEL_DMASTART);
608c2ecf20Sopenharmony_ci#if HOST1X_HW >= 6
618c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, upper_32_bits(start), HOST1X_CHANNEL_DMASTART_HI);
628c2ecf20Sopenharmony_ci#endif
638c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, cdma->push_buffer.pos, HOST1X_CHANNEL_DMAPUT);
648c2ecf20Sopenharmony_ci#if HOST1X_HW >= 6
658c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, 0, HOST1X_CHANNEL_DMAPUT_HI);
668c2ecf20Sopenharmony_ci#endif
678c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, lower_32_bits(end), HOST1X_CHANNEL_DMAEND);
688c2ecf20Sopenharmony_ci#if HOST1X_HW >= 6
698c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, upper_32_bits(end), HOST1X_CHANNEL_DMAEND_HI);
708c2ecf20Sopenharmony_ci#endif
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	/* reset GET */
738c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, HOST1X_CHANNEL_DMACTRL_DMASTOP |
748c2ecf20Sopenharmony_ci			 HOST1X_CHANNEL_DMACTRL_DMAGETRST |
758c2ecf20Sopenharmony_ci			 HOST1X_CHANNEL_DMACTRL_DMAINITGET,
768c2ecf20Sopenharmony_ci			 HOST1X_CHANNEL_DMACTRL);
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	/* start the command DMA */
798c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, 0, HOST1X_CHANNEL_DMACTRL);
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	cdma->running = true;
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci/*
858c2ecf20Sopenharmony_ci * Similar to cdma_start(), but rather than starting from an idle
868c2ecf20Sopenharmony_ci * state (where DMA GET is set to DMA PUT), on a timeout we restore
878c2ecf20Sopenharmony_ci * DMA GET from an explicit value (so DMA may again be pending).
888c2ecf20Sopenharmony_ci */
898c2ecf20Sopenharmony_cistatic void cdma_timeout_restart(struct host1x_cdma *cdma, u32 getptr)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	struct host1x *host1x = cdma_to_host1x(cdma);
928c2ecf20Sopenharmony_ci	struct host1x_channel *ch = cdma_to_channel(cdma);
938c2ecf20Sopenharmony_ci	u64 start, end;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	if (cdma->running)
968c2ecf20Sopenharmony_ci		return;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	cdma->last_pos = cdma->push_buffer.pos;
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, HOST1X_CHANNEL_DMACTRL_DMASTOP,
1018c2ecf20Sopenharmony_ci			 HOST1X_CHANNEL_DMACTRL);
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	start = cdma->push_buffer.dma;
1048c2ecf20Sopenharmony_ci	end = cdma->push_buffer.size + 4;
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	/* set base, end pointer (all of memory) */
1078c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, lower_32_bits(start), HOST1X_CHANNEL_DMASTART);
1088c2ecf20Sopenharmony_ci#if HOST1X_HW >= 6
1098c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, upper_32_bits(start), HOST1X_CHANNEL_DMASTART_HI);
1108c2ecf20Sopenharmony_ci#endif
1118c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, lower_32_bits(end), HOST1X_CHANNEL_DMAEND);
1128c2ecf20Sopenharmony_ci#if HOST1X_HW >= 6
1138c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, upper_32_bits(end), HOST1X_CHANNEL_DMAEND_HI);
1148c2ecf20Sopenharmony_ci#endif
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	/* set GET, by loading the value in PUT (then reset GET) */
1178c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, getptr, HOST1X_CHANNEL_DMAPUT);
1188c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, HOST1X_CHANNEL_DMACTRL_DMASTOP |
1198c2ecf20Sopenharmony_ci			 HOST1X_CHANNEL_DMACTRL_DMAGETRST |
1208c2ecf20Sopenharmony_ci			 HOST1X_CHANNEL_DMACTRL_DMAINITGET,
1218c2ecf20Sopenharmony_ci			 HOST1X_CHANNEL_DMACTRL);
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	dev_dbg(host1x->dev,
1248c2ecf20Sopenharmony_ci		"%s: DMA GET 0x%x, PUT HW 0x%x / shadow 0x%x\n", __func__,
1258c2ecf20Sopenharmony_ci		host1x_ch_readl(ch, HOST1X_CHANNEL_DMAGET),
1268c2ecf20Sopenharmony_ci		host1x_ch_readl(ch, HOST1X_CHANNEL_DMAPUT),
1278c2ecf20Sopenharmony_ci		cdma->last_pos);
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	/* deassert GET reset and set PUT */
1308c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, HOST1X_CHANNEL_DMACTRL_DMASTOP,
1318c2ecf20Sopenharmony_ci			 HOST1X_CHANNEL_DMACTRL);
1328c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, cdma->push_buffer.pos, HOST1X_CHANNEL_DMAPUT);
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	/* start the command DMA */
1358c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, 0, HOST1X_CHANNEL_DMACTRL);
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	cdma->running = true;
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci/*
1418c2ecf20Sopenharmony_ci * Kick channel DMA into action by writing its PUT offset (if it has changed)
1428c2ecf20Sopenharmony_ci */
1438c2ecf20Sopenharmony_cistatic void cdma_flush(struct host1x_cdma *cdma)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	struct host1x_channel *ch = cdma_to_channel(cdma);
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	if (cdma->push_buffer.pos != cdma->last_pos) {
1488c2ecf20Sopenharmony_ci		host1x_ch_writel(ch, cdma->push_buffer.pos,
1498c2ecf20Sopenharmony_ci				 HOST1X_CHANNEL_DMAPUT);
1508c2ecf20Sopenharmony_ci		cdma->last_pos = cdma->push_buffer.pos;
1518c2ecf20Sopenharmony_ci	}
1528c2ecf20Sopenharmony_ci}
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_cistatic void cdma_stop(struct host1x_cdma *cdma)
1558c2ecf20Sopenharmony_ci{
1568c2ecf20Sopenharmony_ci	struct host1x_channel *ch = cdma_to_channel(cdma);
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	mutex_lock(&cdma->lock);
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	if (cdma->running) {
1618c2ecf20Sopenharmony_ci		host1x_cdma_wait_locked(cdma, CDMA_EVENT_SYNC_QUEUE_EMPTY);
1628c2ecf20Sopenharmony_ci		host1x_ch_writel(ch, HOST1X_CHANNEL_DMACTRL_DMASTOP,
1638c2ecf20Sopenharmony_ci				 HOST1X_CHANNEL_DMACTRL);
1648c2ecf20Sopenharmony_ci		cdma->running = false;
1658c2ecf20Sopenharmony_ci	}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	mutex_unlock(&cdma->lock);
1688c2ecf20Sopenharmony_ci}
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_cistatic void cdma_hw_cmdproc_stop(struct host1x *host, struct host1x_channel *ch,
1718c2ecf20Sopenharmony_ci				 bool stop)
1728c2ecf20Sopenharmony_ci{
1738c2ecf20Sopenharmony_ci#if HOST1X_HW >= 6
1748c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, stop ? 0x1 : 0x0, HOST1X_CHANNEL_CMDPROC_STOP);
1758c2ecf20Sopenharmony_ci#else
1768c2ecf20Sopenharmony_ci	u32 cmdproc_stop = host1x_sync_readl(host, HOST1X_SYNC_CMDPROC_STOP);
1778c2ecf20Sopenharmony_ci	if (stop)
1788c2ecf20Sopenharmony_ci		cmdproc_stop |= BIT(ch->id);
1798c2ecf20Sopenharmony_ci	else
1808c2ecf20Sopenharmony_ci		cmdproc_stop &= ~BIT(ch->id);
1818c2ecf20Sopenharmony_ci	host1x_sync_writel(host, cmdproc_stop, HOST1X_SYNC_CMDPROC_STOP);
1828c2ecf20Sopenharmony_ci#endif
1838c2ecf20Sopenharmony_ci}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_cistatic void cdma_hw_teardown(struct host1x *host, struct host1x_channel *ch)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci#if HOST1X_HW >= 6
1888c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, 0x1, HOST1X_CHANNEL_TEARDOWN);
1898c2ecf20Sopenharmony_ci#else
1908c2ecf20Sopenharmony_ci	host1x_sync_writel(host, BIT(ch->id), HOST1X_SYNC_CH_TEARDOWN);
1918c2ecf20Sopenharmony_ci#endif
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci/*
1958c2ecf20Sopenharmony_ci * Stops both channel's command processor and CDMA immediately.
1968c2ecf20Sopenharmony_ci * Also, tears down the channel and resets corresponding module.
1978c2ecf20Sopenharmony_ci */
1988c2ecf20Sopenharmony_cistatic void cdma_freeze(struct host1x_cdma *cdma)
1998c2ecf20Sopenharmony_ci{
2008c2ecf20Sopenharmony_ci	struct host1x *host = cdma_to_host1x(cdma);
2018c2ecf20Sopenharmony_ci	struct host1x_channel *ch = cdma_to_channel(cdma);
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	if (cdma->torndown && !cdma->running) {
2048c2ecf20Sopenharmony_ci		dev_warn(host->dev, "Already torn down\n");
2058c2ecf20Sopenharmony_ci		return;
2068c2ecf20Sopenharmony_ci	}
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	dev_dbg(host->dev, "freezing channel (id %d)\n", ch->id);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	cdma_hw_cmdproc_stop(host, ch, true);
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	dev_dbg(host->dev, "%s: DMA GET 0x%x, PUT HW 0x%x / shadow 0x%x\n",
2138c2ecf20Sopenharmony_ci		__func__, host1x_ch_readl(ch, HOST1X_CHANNEL_DMAGET),
2148c2ecf20Sopenharmony_ci		host1x_ch_readl(ch, HOST1X_CHANNEL_DMAPUT),
2158c2ecf20Sopenharmony_ci		cdma->last_pos);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	host1x_ch_writel(ch, HOST1X_CHANNEL_DMACTRL_DMASTOP,
2188c2ecf20Sopenharmony_ci			 HOST1X_CHANNEL_DMACTRL);
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	cdma_hw_teardown(host, ch);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	cdma->running = false;
2238c2ecf20Sopenharmony_ci	cdma->torndown = true;
2248c2ecf20Sopenharmony_ci}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_cistatic void cdma_resume(struct host1x_cdma *cdma, u32 getptr)
2278c2ecf20Sopenharmony_ci{
2288c2ecf20Sopenharmony_ci	struct host1x *host1x = cdma_to_host1x(cdma);
2298c2ecf20Sopenharmony_ci	struct host1x_channel *ch = cdma_to_channel(cdma);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	dev_dbg(host1x->dev,
2328c2ecf20Sopenharmony_ci		"resuming channel (id %u, DMAGET restart = 0x%x)\n",
2338c2ecf20Sopenharmony_ci		ch->id, getptr);
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	cdma_hw_cmdproc_stop(host1x, ch, false);
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	cdma->torndown = false;
2388c2ecf20Sopenharmony_ci	cdma_timeout_restart(cdma, getptr);
2398c2ecf20Sopenharmony_ci}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci/*
2428c2ecf20Sopenharmony_ci * If this timeout fires, it indicates the current sync_queue entry has
2438c2ecf20Sopenharmony_ci * exceeded its TTL and the userctx should be timed out and remaining
2448c2ecf20Sopenharmony_ci * submits already issued cleaned up (future submits return an error).
2458c2ecf20Sopenharmony_ci */
2468c2ecf20Sopenharmony_cistatic void cdma_timeout_handler(struct work_struct *work)
2478c2ecf20Sopenharmony_ci{
2488c2ecf20Sopenharmony_ci	u32 syncpt_val;
2498c2ecf20Sopenharmony_ci	struct host1x_cdma *cdma;
2508c2ecf20Sopenharmony_ci	struct host1x *host1x;
2518c2ecf20Sopenharmony_ci	struct host1x_channel *ch;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	cdma = container_of(to_delayed_work(work), struct host1x_cdma,
2548c2ecf20Sopenharmony_ci			    timeout.wq);
2558c2ecf20Sopenharmony_ci	host1x = cdma_to_host1x(cdma);
2568c2ecf20Sopenharmony_ci	ch = cdma_to_channel(cdma);
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	host1x_debug_dump(cdma_to_host1x(cdma));
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	mutex_lock(&cdma->lock);
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	if (!cdma->timeout.client) {
2638c2ecf20Sopenharmony_ci		dev_dbg(host1x->dev,
2648c2ecf20Sopenharmony_ci			"cdma_timeout: expired, but has no clientid\n");
2658c2ecf20Sopenharmony_ci		mutex_unlock(&cdma->lock);
2668c2ecf20Sopenharmony_ci		return;
2678c2ecf20Sopenharmony_ci	}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	/* stop processing to get a clean snapshot */
2708c2ecf20Sopenharmony_ci	cdma_hw_cmdproc_stop(host1x, ch, true);
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	syncpt_val = host1x_syncpt_load(cdma->timeout.syncpt);
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	/* has buffer actually completed? */
2758c2ecf20Sopenharmony_ci	if ((s32)(syncpt_val - cdma->timeout.syncpt_val) >= 0) {
2768c2ecf20Sopenharmony_ci		dev_dbg(host1x->dev,
2778c2ecf20Sopenharmony_ci			"cdma_timeout: expired, but buffer had completed\n");
2788c2ecf20Sopenharmony_ci		/* restore */
2798c2ecf20Sopenharmony_ci		cdma_hw_cmdproc_stop(host1x, ch, false);
2808c2ecf20Sopenharmony_ci		mutex_unlock(&cdma->lock);
2818c2ecf20Sopenharmony_ci		return;
2828c2ecf20Sopenharmony_ci	}
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	dev_warn(host1x->dev, "%s: timeout: %u (%s), HW thresh %d, done %d\n",
2858c2ecf20Sopenharmony_ci		 __func__, cdma->timeout.syncpt->id, cdma->timeout.syncpt->name,
2868c2ecf20Sopenharmony_ci		 syncpt_val, cdma->timeout.syncpt_val);
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	/* stop HW, resetting channel/module */
2898c2ecf20Sopenharmony_ci	host1x_hw_cdma_freeze(host1x, cdma);
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	host1x_cdma_update_sync_queue(cdma, ch->dev);
2928c2ecf20Sopenharmony_ci	mutex_unlock(&cdma->lock);
2938c2ecf20Sopenharmony_ci}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci/*
2968c2ecf20Sopenharmony_ci * Init timeout resources
2978c2ecf20Sopenharmony_ci */
2988c2ecf20Sopenharmony_cistatic int cdma_timeout_init(struct host1x_cdma *cdma, unsigned int syncpt)
2998c2ecf20Sopenharmony_ci{
3008c2ecf20Sopenharmony_ci	INIT_DELAYED_WORK(&cdma->timeout.wq, cdma_timeout_handler);
3018c2ecf20Sopenharmony_ci	cdma->timeout.initialized = true;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	return 0;
3048c2ecf20Sopenharmony_ci}
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci/*
3078c2ecf20Sopenharmony_ci * Clean up timeout resources
3088c2ecf20Sopenharmony_ci */
3098c2ecf20Sopenharmony_cistatic void cdma_timeout_destroy(struct host1x_cdma *cdma)
3108c2ecf20Sopenharmony_ci{
3118c2ecf20Sopenharmony_ci	if (cdma->timeout.initialized)
3128c2ecf20Sopenharmony_ci		cancel_delayed_work(&cdma->timeout.wq);
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	cdma->timeout.initialized = false;
3158c2ecf20Sopenharmony_ci}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_cistatic const struct host1x_cdma_ops host1x_cdma_ops = {
3188c2ecf20Sopenharmony_ci	.start = cdma_start,
3198c2ecf20Sopenharmony_ci	.stop = cdma_stop,
3208c2ecf20Sopenharmony_ci	.flush = cdma_flush,
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	.timeout_init = cdma_timeout_init,
3238c2ecf20Sopenharmony_ci	.timeout_destroy = cdma_timeout_destroy,
3248c2ecf20Sopenharmony_ci	.freeze = cdma_freeze,
3258c2ecf20Sopenharmony_ci	.resume = cdma_resume,
3268c2ecf20Sopenharmony_ci	.timeout_cpu_incr = cdma_timeout_cpu_incr,
3278c2ecf20Sopenharmony_ci};
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_cistatic const struct host1x_pushbuffer_ops host1x_pushbuffer_ops = {
3308c2ecf20Sopenharmony_ci	.init = push_buffer_init,
3318c2ecf20Sopenharmony_ci};
332