162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR MIT
262306a36Sopenharmony_ci/**************************************************************************
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
762306a36Sopenharmony_ci * copy of this software and associated documentation files (the
862306a36Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
962306a36Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
1062306a36Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
1162306a36Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
1262306a36Sopenharmony_ci * the following conditions:
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * The above copyright notice and this permission notice (including the
1562306a36Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
1662306a36Sopenharmony_ci * of the Software.
1762306a36Sopenharmony_ci *
1862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1962306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2062306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
2162306a36Sopenharmony_ci * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
2262306a36Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
2362306a36Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
2462306a36Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci **************************************************************************/
2762306a36Sopenharmony_ci#include "vmwgfx_bo.h"
2862306a36Sopenharmony_ci#include "vmwgfx_drv.h"
2962306a36Sopenharmony_ci#include "vmwgfx_devcaps.h"
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#include <drm/ttm/ttm_placement.h>
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#include <linux/sched/signal.h>
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cibool vmw_supports_3d(struct vmw_private *dev_priv)
3662306a36Sopenharmony_ci{
3762306a36Sopenharmony_ci	uint32_t fifo_min, hwversion;
3862306a36Sopenharmony_ci	const struct vmw_fifo_state *fifo = dev_priv->fifo;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	if (!(dev_priv->capabilities & SVGA_CAP_3D))
4162306a36Sopenharmony_ci		return false;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) {
4462306a36Sopenharmony_ci		uint32_t result;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci		if (!dev_priv->has_mob)
4762306a36Sopenharmony_ci			return false;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci		result = vmw_devcap_get(dev_priv, SVGA3D_DEVCAP_3D);
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci		return (result != 0);
5262306a36Sopenharmony_ci	}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
5562306a36Sopenharmony_ci		return false;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	BUG_ON(vmw_is_svga_v3(dev_priv));
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	fifo_min = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_MIN);
6062306a36Sopenharmony_ci	if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
6162306a36Sopenharmony_ci		return false;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	hwversion = vmw_fifo_mem_read(dev_priv,
6462306a36Sopenharmony_ci				      ((fifo->capabilities &
6562306a36Sopenharmony_ci					SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ?
6662306a36Sopenharmony_ci					       SVGA_FIFO_3D_HWVERSION_REVISED :
6762306a36Sopenharmony_ci					       SVGA_FIFO_3D_HWVERSION));
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	if (hwversion == 0)
7062306a36Sopenharmony_ci		return false;
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	if (hwversion < SVGA3D_HWVERSION_WS8_B1)
7362306a36Sopenharmony_ci		return false;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	/* Legacy Display Unit does not support surfaces */
7662306a36Sopenharmony_ci	if (dev_priv->active_display_unit == vmw_du_legacy)
7762306a36Sopenharmony_ci		return false;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	return true;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cibool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	uint32_t caps;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
8762306a36Sopenharmony_ci		return false;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	caps = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_CAPABILITIES);
9062306a36Sopenharmony_ci	if (caps & SVGA_FIFO_CAP_PITCHLOCK)
9162306a36Sopenharmony_ci		return true;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	return false;
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_cistruct vmw_fifo_state *vmw_fifo_create(struct vmw_private *dev_priv)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	struct vmw_fifo_state *fifo;
9962306a36Sopenharmony_ci	uint32_t max;
10062306a36Sopenharmony_ci	uint32_t min;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	if (!dev_priv->fifo_mem)
10362306a36Sopenharmony_ci		return NULL;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	fifo = kzalloc(sizeof(*fifo), GFP_KERNEL);
10662306a36Sopenharmony_ci	if (!fifo)
10762306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
10862306a36Sopenharmony_ci	fifo->static_buffer_size = VMWGFX_FIFO_STATIC_SIZE;
10962306a36Sopenharmony_ci	fifo->static_buffer = vmalloc(fifo->static_buffer_size);
11062306a36Sopenharmony_ci	if (unlikely(fifo->static_buffer == NULL)) {
11162306a36Sopenharmony_ci		kfree(fifo);
11262306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
11362306a36Sopenharmony_ci	}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	fifo->dynamic_buffer = NULL;
11662306a36Sopenharmony_ci	fifo->reserved_size = 0;
11762306a36Sopenharmony_ci	fifo->using_bounce_buffer = false;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	mutex_init(&fifo->fifo_mutex);
12062306a36Sopenharmony_ci	init_rwsem(&fifo->rwsem);
12162306a36Sopenharmony_ci	min = 4;
12262306a36Sopenharmony_ci	if (dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO)
12362306a36Sopenharmony_ci		min = vmw_read(dev_priv, SVGA_REG_MEM_REGS);
12462306a36Sopenharmony_ci	min <<= 2;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	if (min < PAGE_SIZE)
12762306a36Sopenharmony_ci		min = PAGE_SIZE;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	vmw_fifo_mem_write(dev_priv, SVGA_FIFO_MIN, min);
13062306a36Sopenharmony_ci	vmw_fifo_mem_write(dev_priv, SVGA_FIFO_MAX, dev_priv->fifo_mem_size);
13162306a36Sopenharmony_ci	wmb();
13262306a36Sopenharmony_ci	vmw_fifo_mem_write(dev_priv, SVGA_FIFO_NEXT_CMD, min);
13362306a36Sopenharmony_ci	vmw_fifo_mem_write(dev_priv, SVGA_FIFO_STOP, min);
13462306a36Sopenharmony_ci	vmw_fifo_mem_write(dev_priv, SVGA_FIFO_BUSY, 0);
13562306a36Sopenharmony_ci	mb();
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	vmw_write(dev_priv, SVGA_REG_CONFIG_DONE, 1);
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	max = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_MAX);
14062306a36Sopenharmony_ci	min = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_MIN);
14162306a36Sopenharmony_ci	fifo->capabilities = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_CAPABILITIES);
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	drm_info(&dev_priv->drm,
14462306a36Sopenharmony_ci		 "Fifo max 0x%08x min 0x%08x cap 0x%08x\n",
14562306a36Sopenharmony_ci		 (unsigned int) max,
14662306a36Sopenharmony_ci		 (unsigned int) min,
14762306a36Sopenharmony_ci		 (unsigned int) fifo->capabilities);
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	if (unlikely(min >= max)) {
15062306a36Sopenharmony_ci		drm_warn(&dev_priv->drm,
15162306a36Sopenharmony_ci			 "FIFO memory is not usable. Driver failed to initialize.");
15262306a36Sopenharmony_ci		return ERR_PTR(-ENXIO);
15362306a36Sopenharmony_ci	}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	return fifo;
15662306a36Sopenharmony_ci}
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_civoid vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	u32 *fifo_mem = dev_priv->fifo_mem;
16162306a36Sopenharmony_ci	if (fifo_mem && cmpxchg(fifo_mem + SVGA_FIFO_BUSY, 0, 1) == 0)
16262306a36Sopenharmony_ci		vmw_write(dev_priv, SVGA_REG_SYNC, reason);
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci}
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_civoid vmw_fifo_destroy(struct vmw_private *dev_priv)
16762306a36Sopenharmony_ci{
16862306a36Sopenharmony_ci	struct vmw_fifo_state *fifo = dev_priv->fifo;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	if (!fifo)
17162306a36Sopenharmony_ci		return;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	if (likely(fifo->static_buffer != NULL)) {
17462306a36Sopenharmony_ci		vfree(fifo->static_buffer);
17562306a36Sopenharmony_ci		fifo->static_buffer = NULL;
17662306a36Sopenharmony_ci	}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	if (likely(fifo->dynamic_buffer != NULL)) {
17962306a36Sopenharmony_ci		vfree(fifo->dynamic_buffer);
18062306a36Sopenharmony_ci		fifo->dynamic_buffer = NULL;
18162306a36Sopenharmony_ci	}
18262306a36Sopenharmony_ci	kfree(fifo);
18362306a36Sopenharmony_ci	dev_priv->fifo = NULL;
18462306a36Sopenharmony_ci}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_cistatic bool vmw_fifo_is_full(struct vmw_private *dev_priv, uint32_t bytes)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	uint32_t max = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_MAX);
18962306a36Sopenharmony_ci	uint32_t next_cmd = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_NEXT_CMD);
19062306a36Sopenharmony_ci	uint32_t min = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_MIN);
19162306a36Sopenharmony_ci	uint32_t stop = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_STOP);
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	return ((max - next_cmd) + (stop - min) <= bytes);
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_cistatic int vmw_fifo_wait_noirq(struct vmw_private *dev_priv,
19762306a36Sopenharmony_ci			       uint32_t bytes, bool interruptible,
19862306a36Sopenharmony_ci			       unsigned long timeout)
19962306a36Sopenharmony_ci{
20062306a36Sopenharmony_ci	int ret = 0;
20162306a36Sopenharmony_ci	unsigned long end_jiffies = jiffies + timeout;
20262306a36Sopenharmony_ci	DEFINE_WAIT(__wait);
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	DRM_INFO("Fifo wait noirq.\n");
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	for (;;) {
20762306a36Sopenharmony_ci		prepare_to_wait(&dev_priv->fifo_queue, &__wait,
20862306a36Sopenharmony_ci				(interruptible) ?
20962306a36Sopenharmony_ci				TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
21062306a36Sopenharmony_ci		if (!vmw_fifo_is_full(dev_priv, bytes))
21162306a36Sopenharmony_ci			break;
21262306a36Sopenharmony_ci		if (time_after_eq(jiffies, end_jiffies)) {
21362306a36Sopenharmony_ci			ret = -EBUSY;
21462306a36Sopenharmony_ci			DRM_ERROR("SVGA device lockup.\n");
21562306a36Sopenharmony_ci			break;
21662306a36Sopenharmony_ci		}
21762306a36Sopenharmony_ci		schedule_timeout(1);
21862306a36Sopenharmony_ci		if (interruptible && signal_pending(current)) {
21962306a36Sopenharmony_ci			ret = -ERESTARTSYS;
22062306a36Sopenharmony_ci			break;
22162306a36Sopenharmony_ci		}
22262306a36Sopenharmony_ci	}
22362306a36Sopenharmony_ci	finish_wait(&dev_priv->fifo_queue, &__wait);
22462306a36Sopenharmony_ci	wake_up_all(&dev_priv->fifo_queue);
22562306a36Sopenharmony_ci	DRM_INFO("Fifo noirq exit.\n");
22662306a36Sopenharmony_ci	return ret;
22762306a36Sopenharmony_ci}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_cistatic int vmw_fifo_wait(struct vmw_private *dev_priv,
23062306a36Sopenharmony_ci			 uint32_t bytes, bool interruptible,
23162306a36Sopenharmony_ci			 unsigned long timeout)
23262306a36Sopenharmony_ci{
23362306a36Sopenharmony_ci	long ret = 1L;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	if (likely(!vmw_fifo_is_full(dev_priv, bytes)))
23662306a36Sopenharmony_ci		return 0;
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_FIFOFULL);
23962306a36Sopenharmony_ci	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
24062306a36Sopenharmony_ci		return vmw_fifo_wait_noirq(dev_priv, bytes,
24162306a36Sopenharmony_ci					   interruptible, timeout);
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_FIFO_PROGRESS,
24462306a36Sopenharmony_ci			       &dev_priv->fifo_queue_waiters);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	if (interruptible)
24762306a36Sopenharmony_ci		ret = wait_event_interruptible_timeout
24862306a36Sopenharmony_ci		    (dev_priv->fifo_queue,
24962306a36Sopenharmony_ci		     !vmw_fifo_is_full(dev_priv, bytes), timeout);
25062306a36Sopenharmony_ci	else
25162306a36Sopenharmony_ci		ret = wait_event_timeout
25262306a36Sopenharmony_ci		    (dev_priv->fifo_queue,
25362306a36Sopenharmony_ci		     !vmw_fifo_is_full(dev_priv, bytes), timeout);
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	if (unlikely(ret == 0))
25662306a36Sopenharmony_ci		ret = -EBUSY;
25762306a36Sopenharmony_ci	else if (likely(ret > 0))
25862306a36Sopenharmony_ci		ret = 0;
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_FIFO_PROGRESS,
26162306a36Sopenharmony_ci				  &dev_priv->fifo_queue_waiters);
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	return ret;
26462306a36Sopenharmony_ci}
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci/*
26762306a36Sopenharmony_ci * Reserve @bytes number of bytes in the fifo.
26862306a36Sopenharmony_ci *
26962306a36Sopenharmony_ci * This function will return NULL (error) on two conditions:
27062306a36Sopenharmony_ci *  If it timeouts waiting for fifo space, or if @bytes is larger than the
27162306a36Sopenharmony_ci *   available fifo space.
27262306a36Sopenharmony_ci *
27362306a36Sopenharmony_ci * Returns:
27462306a36Sopenharmony_ci *   Pointer to the fifo, or null on error (possible hardware hang).
27562306a36Sopenharmony_ci */
27662306a36Sopenharmony_cistatic void *vmw_local_fifo_reserve(struct vmw_private *dev_priv,
27762306a36Sopenharmony_ci				    uint32_t bytes)
27862306a36Sopenharmony_ci{
27962306a36Sopenharmony_ci	struct vmw_fifo_state *fifo_state = dev_priv->fifo;
28062306a36Sopenharmony_ci	u32  *fifo_mem = dev_priv->fifo_mem;
28162306a36Sopenharmony_ci	uint32_t max;
28262306a36Sopenharmony_ci	uint32_t min;
28362306a36Sopenharmony_ci	uint32_t next_cmd;
28462306a36Sopenharmony_ci	uint32_t reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE;
28562306a36Sopenharmony_ci	int ret;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	mutex_lock(&fifo_state->fifo_mutex);
28862306a36Sopenharmony_ci	max = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_MAX);
28962306a36Sopenharmony_ci	min = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_MIN);
29062306a36Sopenharmony_ci	next_cmd = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_NEXT_CMD);
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	if (unlikely(bytes >= (max - min)))
29362306a36Sopenharmony_ci		goto out_err;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	BUG_ON(fifo_state->reserved_size != 0);
29662306a36Sopenharmony_ci	BUG_ON(fifo_state->dynamic_buffer != NULL);
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	fifo_state->reserved_size = bytes;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	while (1) {
30162306a36Sopenharmony_ci		uint32_t stop = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_STOP);
30262306a36Sopenharmony_ci		bool need_bounce = false;
30362306a36Sopenharmony_ci		bool reserve_in_place = false;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci		if (next_cmd >= stop) {
30662306a36Sopenharmony_ci			if (likely((next_cmd + bytes < max ||
30762306a36Sopenharmony_ci				    (next_cmd + bytes == max && stop > min))))
30862306a36Sopenharmony_ci				reserve_in_place = true;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci			else if (vmw_fifo_is_full(dev_priv, bytes)) {
31162306a36Sopenharmony_ci				ret = vmw_fifo_wait(dev_priv, bytes,
31262306a36Sopenharmony_ci						    false, 3 * HZ);
31362306a36Sopenharmony_ci				if (unlikely(ret != 0))
31462306a36Sopenharmony_ci					goto out_err;
31562306a36Sopenharmony_ci			} else
31662306a36Sopenharmony_ci				need_bounce = true;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci		} else {
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci			if (likely((next_cmd + bytes < stop)))
32162306a36Sopenharmony_ci				reserve_in_place = true;
32262306a36Sopenharmony_ci			else {
32362306a36Sopenharmony_ci				ret = vmw_fifo_wait(dev_priv, bytes,
32462306a36Sopenharmony_ci						    false, 3 * HZ);
32562306a36Sopenharmony_ci				if (unlikely(ret != 0))
32662306a36Sopenharmony_ci					goto out_err;
32762306a36Sopenharmony_ci			}
32862306a36Sopenharmony_ci		}
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci		if (reserve_in_place) {
33162306a36Sopenharmony_ci			if (reserveable || bytes <= sizeof(uint32_t)) {
33262306a36Sopenharmony_ci				fifo_state->using_bounce_buffer = false;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci				if (reserveable)
33562306a36Sopenharmony_ci					vmw_fifo_mem_write(dev_priv,
33662306a36Sopenharmony_ci							   SVGA_FIFO_RESERVED,
33762306a36Sopenharmony_ci							   bytes);
33862306a36Sopenharmony_ci				return (void __force *) (fifo_mem +
33962306a36Sopenharmony_ci							 (next_cmd >> 2));
34062306a36Sopenharmony_ci			} else {
34162306a36Sopenharmony_ci				need_bounce = true;
34262306a36Sopenharmony_ci			}
34362306a36Sopenharmony_ci		}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci		if (need_bounce) {
34662306a36Sopenharmony_ci			fifo_state->using_bounce_buffer = true;
34762306a36Sopenharmony_ci			if (bytes < fifo_state->static_buffer_size)
34862306a36Sopenharmony_ci				return fifo_state->static_buffer;
34962306a36Sopenharmony_ci			else {
35062306a36Sopenharmony_ci				fifo_state->dynamic_buffer = vmalloc(bytes);
35162306a36Sopenharmony_ci				if (!fifo_state->dynamic_buffer)
35262306a36Sopenharmony_ci					goto out_err;
35362306a36Sopenharmony_ci				return fifo_state->dynamic_buffer;
35462306a36Sopenharmony_ci			}
35562306a36Sopenharmony_ci		}
35662306a36Sopenharmony_ci	}
35762306a36Sopenharmony_ciout_err:
35862306a36Sopenharmony_ci	fifo_state->reserved_size = 0;
35962306a36Sopenharmony_ci	mutex_unlock(&fifo_state->fifo_mutex);
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	return NULL;
36262306a36Sopenharmony_ci}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_civoid *vmw_cmd_ctx_reserve(struct vmw_private *dev_priv, uint32_t bytes,
36562306a36Sopenharmony_ci			  int ctx_id)
36662306a36Sopenharmony_ci{
36762306a36Sopenharmony_ci	void *ret;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	if (dev_priv->cman)
37062306a36Sopenharmony_ci		ret = vmw_cmdbuf_reserve(dev_priv->cman, bytes,
37162306a36Sopenharmony_ci					 ctx_id, false, NULL);
37262306a36Sopenharmony_ci	else if (ctx_id == SVGA3D_INVALID_ID)
37362306a36Sopenharmony_ci		ret = vmw_local_fifo_reserve(dev_priv, bytes);
37462306a36Sopenharmony_ci	else {
37562306a36Sopenharmony_ci		WARN(1, "Command buffer has not been allocated.\n");
37662306a36Sopenharmony_ci		ret = NULL;
37762306a36Sopenharmony_ci	}
37862306a36Sopenharmony_ci	if (IS_ERR_OR_NULL(ret))
37962306a36Sopenharmony_ci		return NULL;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	return ret;
38262306a36Sopenharmony_ci}
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_cistatic void vmw_fifo_res_copy(struct vmw_fifo_state *fifo_state,
38562306a36Sopenharmony_ci			      struct vmw_private *vmw,
38662306a36Sopenharmony_ci			      uint32_t next_cmd,
38762306a36Sopenharmony_ci			      uint32_t max, uint32_t min, uint32_t bytes)
38862306a36Sopenharmony_ci{
38962306a36Sopenharmony_ci	u32 *fifo_mem = vmw->fifo_mem;
39062306a36Sopenharmony_ci	uint32_t chunk_size = max - next_cmd;
39162306a36Sopenharmony_ci	uint32_t rest;
39262306a36Sopenharmony_ci	uint32_t *buffer = (fifo_state->dynamic_buffer != NULL) ?
39362306a36Sopenharmony_ci	    fifo_state->dynamic_buffer : fifo_state->static_buffer;
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci	if (bytes < chunk_size)
39662306a36Sopenharmony_ci		chunk_size = bytes;
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	vmw_fifo_mem_write(vmw, SVGA_FIFO_RESERVED, bytes);
39962306a36Sopenharmony_ci	mb();
40062306a36Sopenharmony_ci	memcpy(fifo_mem + (next_cmd >> 2), buffer, chunk_size);
40162306a36Sopenharmony_ci	rest = bytes - chunk_size;
40262306a36Sopenharmony_ci	if (rest)
40362306a36Sopenharmony_ci		memcpy(fifo_mem + (min >> 2), buffer + (chunk_size >> 2), rest);
40462306a36Sopenharmony_ci}
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_cistatic void vmw_fifo_slow_copy(struct vmw_fifo_state *fifo_state,
40762306a36Sopenharmony_ci			       struct vmw_private *vmw,
40862306a36Sopenharmony_ci			       uint32_t next_cmd,
40962306a36Sopenharmony_ci			       uint32_t max, uint32_t min, uint32_t bytes)
41062306a36Sopenharmony_ci{
41162306a36Sopenharmony_ci	uint32_t *buffer = (fifo_state->dynamic_buffer != NULL) ?
41262306a36Sopenharmony_ci	    fifo_state->dynamic_buffer : fifo_state->static_buffer;
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	while (bytes > 0) {
41562306a36Sopenharmony_ci		vmw_fifo_mem_write(vmw, (next_cmd >> 2), *buffer++);
41662306a36Sopenharmony_ci		next_cmd += sizeof(uint32_t);
41762306a36Sopenharmony_ci		if (unlikely(next_cmd == max))
41862306a36Sopenharmony_ci			next_cmd = min;
41962306a36Sopenharmony_ci		mb();
42062306a36Sopenharmony_ci		vmw_fifo_mem_write(vmw, SVGA_FIFO_NEXT_CMD, next_cmd);
42162306a36Sopenharmony_ci		mb();
42262306a36Sopenharmony_ci		bytes -= sizeof(uint32_t);
42362306a36Sopenharmony_ci	}
42462306a36Sopenharmony_ci}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_cistatic void vmw_local_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes)
42762306a36Sopenharmony_ci{
42862306a36Sopenharmony_ci	struct vmw_fifo_state *fifo_state = dev_priv->fifo;
42962306a36Sopenharmony_ci	uint32_t next_cmd = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_NEXT_CMD);
43062306a36Sopenharmony_ci	uint32_t max = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_MAX);
43162306a36Sopenharmony_ci	uint32_t min = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_MIN);
43262306a36Sopenharmony_ci	bool reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE;
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	BUG_ON((bytes & 3) != 0);
43562306a36Sopenharmony_ci	BUG_ON(bytes > fifo_state->reserved_size);
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	fifo_state->reserved_size = 0;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	if (fifo_state->using_bounce_buffer) {
44062306a36Sopenharmony_ci		if (reserveable)
44162306a36Sopenharmony_ci			vmw_fifo_res_copy(fifo_state, dev_priv,
44262306a36Sopenharmony_ci					  next_cmd, max, min, bytes);
44362306a36Sopenharmony_ci		else
44462306a36Sopenharmony_ci			vmw_fifo_slow_copy(fifo_state, dev_priv,
44562306a36Sopenharmony_ci					   next_cmd, max, min, bytes);
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci		if (fifo_state->dynamic_buffer) {
44862306a36Sopenharmony_ci			vfree(fifo_state->dynamic_buffer);
44962306a36Sopenharmony_ci			fifo_state->dynamic_buffer = NULL;
45062306a36Sopenharmony_ci		}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	}
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	down_write(&fifo_state->rwsem);
45562306a36Sopenharmony_ci	if (fifo_state->using_bounce_buffer || reserveable) {
45662306a36Sopenharmony_ci		next_cmd += bytes;
45762306a36Sopenharmony_ci		if (next_cmd >= max)
45862306a36Sopenharmony_ci			next_cmd -= max - min;
45962306a36Sopenharmony_ci		mb();
46062306a36Sopenharmony_ci		vmw_fifo_mem_write(dev_priv, SVGA_FIFO_NEXT_CMD, next_cmd);
46162306a36Sopenharmony_ci	}
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci	if (reserveable)
46462306a36Sopenharmony_ci		vmw_fifo_mem_write(dev_priv, SVGA_FIFO_RESERVED, 0);
46562306a36Sopenharmony_ci	mb();
46662306a36Sopenharmony_ci	up_write(&fifo_state->rwsem);
46762306a36Sopenharmony_ci	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
46862306a36Sopenharmony_ci	mutex_unlock(&fifo_state->fifo_mutex);
46962306a36Sopenharmony_ci}
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_civoid vmw_cmd_commit(struct vmw_private *dev_priv, uint32_t bytes)
47262306a36Sopenharmony_ci{
47362306a36Sopenharmony_ci	if (dev_priv->cman)
47462306a36Sopenharmony_ci		vmw_cmdbuf_commit(dev_priv->cman, bytes, NULL, false);
47562306a36Sopenharmony_ci	else
47662306a36Sopenharmony_ci		vmw_local_fifo_commit(dev_priv, bytes);
47762306a36Sopenharmony_ci}
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci/**
48162306a36Sopenharmony_ci * vmw_cmd_commit_flush - Commit fifo space and flush any buffered commands.
48262306a36Sopenharmony_ci *
48362306a36Sopenharmony_ci * @dev_priv: Pointer to device private structure.
48462306a36Sopenharmony_ci * @bytes: Number of bytes to commit.
48562306a36Sopenharmony_ci */
48662306a36Sopenharmony_civoid vmw_cmd_commit_flush(struct vmw_private *dev_priv, uint32_t bytes)
48762306a36Sopenharmony_ci{
48862306a36Sopenharmony_ci	if (dev_priv->cman)
48962306a36Sopenharmony_ci		vmw_cmdbuf_commit(dev_priv->cman, bytes, NULL, true);
49062306a36Sopenharmony_ci	else
49162306a36Sopenharmony_ci		vmw_local_fifo_commit(dev_priv, bytes);
49262306a36Sopenharmony_ci}
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci/**
49562306a36Sopenharmony_ci * vmw_cmd_flush - Flush any buffered commands and make sure command processing
49662306a36Sopenharmony_ci * starts.
49762306a36Sopenharmony_ci *
49862306a36Sopenharmony_ci * @dev_priv: Pointer to device private structure.
49962306a36Sopenharmony_ci * @interruptible: Whether to wait interruptible if function needs to sleep.
50062306a36Sopenharmony_ci */
50162306a36Sopenharmony_ciint vmw_cmd_flush(struct vmw_private *dev_priv, bool interruptible)
50262306a36Sopenharmony_ci{
50362306a36Sopenharmony_ci	might_sleep();
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	if (dev_priv->cman)
50662306a36Sopenharmony_ci		return vmw_cmdbuf_cur_flush(dev_priv->cman, interruptible);
50762306a36Sopenharmony_ci	else
50862306a36Sopenharmony_ci		return 0;
50962306a36Sopenharmony_ci}
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ciint vmw_cmd_send_fence(struct vmw_private *dev_priv, uint32_t *seqno)
51262306a36Sopenharmony_ci{
51362306a36Sopenharmony_ci	struct svga_fifo_cmd_fence *cmd_fence;
51462306a36Sopenharmony_ci	u32 *fm;
51562306a36Sopenharmony_ci	int ret = 0;
51662306a36Sopenharmony_ci	uint32_t bytes = sizeof(u32) + sizeof(*cmd_fence);
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	fm = VMW_CMD_RESERVE(dev_priv, bytes);
51962306a36Sopenharmony_ci	if (unlikely(fm == NULL)) {
52062306a36Sopenharmony_ci		*seqno = atomic_read(&dev_priv->marker_seq);
52162306a36Sopenharmony_ci		ret = -ENOMEM;
52262306a36Sopenharmony_ci		(void)vmw_fallback_wait(dev_priv, false, true, *seqno,
52362306a36Sopenharmony_ci					false, 3*HZ);
52462306a36Sopenharmony_ci		goto out_err;
52562306a36Sopenharmony_ci	}
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	do {
52862306a36Sopenharmony_ci		*seqno = atomic_add_return(1, &dev_priv->marker_seq);
52962306a36Sopenharmony_ci	} while (*seqno == 0);
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	if (!vmw_has_fences(dev_priv)) {
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci		/*
53462306a36Sopenharmony_ci		 * Don't request hardware to send a fence. The
53562306a36Sopenharmony_ci		 * waiting code in vmwgfx_irq.c will emulate this.
53662306a36Sopenharmony_ci		 */
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci		vmw_cmd_commit(dev_priv, 0);
53962306a36Sopenharmony_ci		return 0;
54062306a36Sopenharmony_ci	}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	*fm++ = SVGA_CMD_FENCE;
54362306a36Sopenharmony_ci	cmd_fence = (struct svga_fifo_cmd_fence *) fm;
54462306a36Sopenharmony_ci	cmd_fence->fence = *seqno;
54562306a36Sopenharmony_ci	vmw_cmd_commit_flush(dev_priv, bytes);
54662306a36Sopenharmony_ci	vmw_update_seqno(dev_priv);
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ciout_err:
54962306a36Sopenharmony_ci	return ret;
55062306a36Sopenharmony_ci}
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci/**
55362306a36Sopenharmony_ci * vmw_cmd_emit_dummy_legacy_query - emits a dummy query to the fifo using
55462306a36Sopenharmony_ci * legacy query commands.
55562306a36Sopenharmony_ci *
55662306a36Sopenharmony_ci * @dev_priv: The device private structure.
55762306a36Sopenharmony_ci * @cid: The hardware context id used for the query.
55862306a36Sopenharmony_ci *
55962306a36Sopenharmony_ci * See the vmw_cmd_emit_dummy_query documentation.
56062306a36Sopenharmony_ci */
56162306a36Sopenharmony_cistatic int vmw_cmd_emit_dummy_legacy_query(struct vmw_private *dev_priv,
56262306a36Sopenharmony_ci					    uint32_t cid)
56362306a36Sopenharmony_ci{
56462306a36Sopenharmony_ci	/*
56562306a36Sopenharmony_ci	 * A query wait without a preceding query end will
56662306a36Sopenharmony_ci	 * actually finish all queries for this cid
56762306a36Sopenharmony_ci	 * without writing to the query result structure.
56862306a36Sopenharmony_ci	 */
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	struct ttm_buffer_object *bo = &dev_priv->dummy_query_bo->tbo;
57162306a36Sopenharmony_ci	struct {
57262306a36Sopenharmony_ci		SVGA3dCmdHeader header;
57362306a36Sopenharmony_ci		SVGA3dCmdWaitForQuery body;
57462306a36Sopenharmony_ci	} *cmd;
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
57762306a36Sopenharmony_ci	if (unlikely(cmd == NULL))
57862306a36Sopenharmony_ci		return -ENOMEM;
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	cmd->header.id = SVGA_3D_CMD_WAIT_FOR_QUERY;
58162306a36Sopenharmony_ci	cmd->header.size = sizeof(cmd->body);
58262306a36Sopenharmony_ci	cmd->body.cid = cid;
58362306a36Sopenharmony_ci	cmd->body.type = SVGA3D_QUERYTYPE_OCCLUSION;
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci	if (bo->resource->mem_type == TTM_PL_VRAM) {
58662306a36Sopenharmony_ci		cmd->body.guestResult.gmrId = SVGA_GMR_FRAMEBUFFER;
58762306a36Sopenharmony_ci		cmd->body.guestResult.offset = bo->resource->start << PAGE_SHIFT;
58862306a36Sopenharmony_ci	} else {
58962306a36Sopenharmony_ci		cmd->body.guestResult.gmrId = bo->resource->start;
59062306a36Sopenharmony_ci		cmd->body.guestResult.offset = 0;
59162306a36Sopenharmony_ci	}
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci	vmw_cmd_commit(dev_priv, sizeof(*cmd));
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	return 0;
59662306a36Sopenharmony_ci}
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci/**
59962306a36Sopenharmony_ci * vmw_cmd_emit_dummy_gb_query - emits a dummy query to the fifo using
60062306a36Sopenharmony_ci * guest-backed resource query commands.
60162306a36Sopenharmony_ci *
60262306a36Sopenharmony_ci * @dev_priv: The device private structure.
60362306a36Sopenharmony_ci * @cid: The hardware context id used for the query.
60462306a36Sopenharmony_ci *
60562306a36Sopenharmony_ci * See the vmw_cmd_emit_dummy_query documentation.
60662306a36Sopenharmony_ci */
60762306a36Sopenharmony_cistatic int vmw_cmd_emit_dummy_gb_query(struct vmw_private *dev_priv,
60862306a36Sopenharmony_ci				       uint32_t cid)
60962306a36Sopenharmony_ci{
61062306a36Sopenharmony_ci	/*
61162306a36Sopenharmony_ci	 * A query wait without a preceding query end will
61262306a36Sopenharmony_ci	 * actually finish all queries for this cid
61362306a36Sopenharmony_ci	 * without writing to the query result structure.
61462306a36Sopenharmony_ci	 */
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	struct ttm_buffer_object *bo = &dev_priv->dummy_query_bo->tbo;
61762306a36Sopenharmony_ci	struct {
61862306a36Sopenharmony_ci		SVGA3dCmdHeader header;
61962306a36Sopenharmony_ci		SVGA3dCmdWaitForGBQuery body;
62062306a36Sopenharmony_ci	} *cmd;
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
62362306a36Sopenharmony_ci	if (unlikely(cmd == NULL))
62462306a36Sopenharmony_ci		return -ENOMEM;
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	cmd->header.id = SVGA_3D_CMD_WAIT_FOR_GB_QUERY;
62762306a36Sopenharmony_ci	cmd->header.size = sizeof(cmd->body);
62862306a36Sopenharmony_ci	cmd->body.cid = cid;
62962306a36Sopenharmony_ci	cmd->body.type = SVGA3D_QUERYTYPE_OCCLUSION;
63062306a36Sopenharmony_ci	BUG_ON(bo->resource->mem_type != VMW_PL_MOB);
63162306a36Sopenharmony_ci	cmd->body.mobid = bo->resource->start;
63262306a36Sopenharmony_ci	cmd->body.offset = 0;
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	vmw_cmd_commit(dev_priv, sizeof(*cmd));
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	return 0;
63762306a36Sopenharmony_ci}
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci/**
64162306a36Sopenharmony_ci * vmw_cmd_emit_dummy_query - emits a dummy query to the fifo using
64262306a36Sopenharmony_ci * appropriate resource query commands.
64362306a36Sopenharmony_ci *
64462306a36Sopenharmony_ci * @dev_priv: The device private structure.
64562306a36Sopenharmony_ci * @cid: The hardware context id used for the query.
64662306a36Sopenharmony_ci *
64762306a36Sopenharmony_ci * This function is used to emit a dummy occlusion query with
64862306a36Sopenharmony_ci * no primitives rendered between query begin and query end.
64962306a36Sopenharmony_ci * It's used to provide a query barrier, in order to know that when
65062306a36Sopenharmony_ci * this query is finished, all preceding queries are also finished.
65162306a36Sopenharmony_ci *
65262306a36Sopenharmony_ci * A Query results structure should have been initialized at the start
65362306a36Sopenharmony_ci * of the dev_priv->dummy_query_bo buffer object. And that buffer object
65462306a36Sopenharmony_ci * must also be either reserved or pinned when this function is called.
65562306a36Sopenharmony_ci *
65662306a36Sopenharmony_ci * Returns -ENOMEM on failure to reserve fifo space.
65762306a36Sopenharmony_ci */
65862306a36Sopenharmony_ciint vmw_cmd_emit_dummy_query(struct vmw_private *dev_priv,
65962306a36Sopenharmony_ci			      uint32_t cid)
66062306a36Sopenharmony_ci{
66162306a36Sopenharmony_ci	if (dev_priv->has_mob)
66262306a36Sopenharmony_ci		return vmw_cmd_emit_dummy_gb_query(dev_priv, cid);
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	return vmw_cmd_emit_dummy_legacy_query(dev_priv, cid);
66562306a36Sopenharmony_ci}
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci/**
66962306a36Sopenharmony_ci * vmw_cmd_supported - returns true if the given device supports
67062306a36Sopenharmony_ci * command queues.
67162306a36Sopenharmony_ci *
67262306a36Sopenharmony_ci * @vmw: The device private structure.
67362306a36Sopenharmony_ci *
67462306a36Sopenharmony_ci * Returns true if we can issue commands.
67562306a36Sopenharmony_ci */
67662306a36Sopenharmony_cibool vmw_cmd_supported(struct vmw_private *vmw)
67762306a36Sopenharmony_ci{
67862306a36Sopenharmony_ci	bool has_cmdbufs =
67962306a36Sopenharmony_ci		(vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS |
68062306a36Sopenharmony_ci				      SVGA_CAP_CMD_BUFFERS_2)) != 0;
68162306a36Sopenharmony_ci	if (vmw_is_svga_v3(vmw))
68262306a36Sopenharmony_ci		return (has_cmdbufs &&
68362306a36Sopenharmony_ci			(vmw->capabilities & SVGA_CAP_GBOBJECTS) != 0);
68462306a36Sopenharmony_ci	/*
68562306a36Sopenharmony_ci	 * We have FIFO cmd's
68662306a36Sopenharmony_ci	 */
68762306a36Sopenharmony_ci	return has_cmdbufs || vmw->fifo_mem != NULL;
68862306a36Sopenharmony_ci}
689