1fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/**************************************************************************
2fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *
3fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
4fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * All Rights Reserved.
5fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *
6fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Permission is hereby granted, free of charge, to any person obtaining a
7fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * copy of this software and associated documentation files (the
8fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * "Software"), to deal in the Software without restriction, including
9fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * without limitation the rights to use, copy, modify, merge, publish,
10fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * distribute, sub license, and/or sell copies of the Software, and to
11fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * permit persons to whom the Software is furnished to do so, subject to
12fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * the following conditions:
13fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *
14fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * The above copyright notice and this permission notice (including the
15fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * next paragraph) shall be included in all copies or substantial portions
16fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * of the Software.
17fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *
18fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * USE OR OTHER DEALINGS IN THE SOFTWARE.
25fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *
26fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz **************************************************************************/
27fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
28fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#include "vmwgfx_drv.h"
29fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#include "drmP.h"
30fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#include "ttm/ttm_placement.h"
31fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
328e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantzbool vmw_fifo_have_3d(struct vmw_private *dev_priv)
338e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantz{
348e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantz	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
358e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantz	uint32_t fifo_min, hwversion;
36ebd4c6f6261c96d1cf9f004965384d57c4202fd6Thomas Hellstrom	const struct vmw_fifo_state *fifo = &dev_priv->fifo;
378e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantz
38d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz	if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
39d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz		return false;
40d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz
418e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantz	fifo_min = ioread32(fifo_mem  + SVGA_FIFO_MIN);
428e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantz	if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
438e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantz		return false;
448e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantz
45ebd4c6f6261c96d1cf9f004965384d57c4202fd6Thomas Hellstrom	hwversion = ioread32(fifo_mem +
46ebd4c6f6261c96d1cf9f004965384d57c4202fd6Thomas Hellstrom			     ((fifo->capabilities &
47ebd4c6f6261c96d1cf9f004965384d57c4202fd6Thomas Hellstrom			       SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ?
48ebd4c6f6261c96d1cf9f004965384d57c4202fd6Thomas Hellstrom			      SVGA_FIFO_3D_HWVERSION_REVISED :
49ebd4c6f6261c96d1cf9f004965384d57c4202fd6Thomas Hellstrom			      SVGA_FIFO_3D_HWVERSION));
50ebd4c6f6261c96d1cf9f004965384d57c4202fd6Thomas Hellstrom
518e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantz	if (hwversion == 0)
528e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantz		return false;
538e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantz
54b7b70024d94184991201ea788ab6fa3c20e1ce70Thomas Hellstrom	if (hwversion < SVGA3D_HWVERSION_WS8_B1)
558e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantz		return false;
568e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantz
5701e81419ce66c312db6855b5cb26cd50eb9a9b8bJakob Bornecrantz	/* Non-Screen Object path does not support surfaces */
5801e81419ce66c312db6855b5cb26cd50eb9a9b8bJakob Bornecrantz	if (!dev_priv->sou_priv)
5901e81419ce66c312db6855b5cb26cd50eb9a9b8bJakob Bornecrantz		return false;
6001e81419ce66c312db6855b5cb26cd50eb9a9b8bJakob Bornecrantz
618e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantz	return true;
628e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantz}
638e19a951774a16cf2626292ae06fd2b62630e67eJakob Bornecrantz
64d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantzbool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv)
65d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz{
66d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
67d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz	uint32_t caps;
68d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz
69d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz	if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
70d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz		return false;
71d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz
72d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz	caps = ioread32(fifo_mem + SVGA_FIFO_CAPABILITIES);
73d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz	if (caps & SVGA_FIFO_CAP_PITCHLOCK)
74d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz		return true;
75d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz
76d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz	return false;
77d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz}
78d7e1958dbe4a7b81d4cab5fab545a068501b967eJakob Bornecrantz
79fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
80fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
81fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
82fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t max;
83fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t min;
84fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t dummy;
85fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
86fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	fifo->static_buffer_size = VMWGFX_FIFO_STATIC_SIZE;
87fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	fifo->static_buffer = vmalloc(fifo->static_buffer_size);
88fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (unlikely(fifo->static_buffer == NULL))
89fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		return -ENOMEM;
90fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
91fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	fifo->dynamic_buffer = NULL;
92fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	fifo->reserved_size = 0;
93fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	fifo->using_bounce_buffer = false;
94fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
9585b9e4878f3b16993fba871c0c68d0948ec9c7c6Thomas Hellstrom	mutex_init(&fifo->fifo_mutex);
96fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	init_rwsem(&fifo->rwsem);
97fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
98fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	/*
99fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	 * Allow mapping the first page read-only to user-space.
100fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	 */
101fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
102fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	DRM_INFO("width %d\n", vmw_read(dev_priv, SVGA_REG_WIDTH));
103fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	DRM_INFO("height %d\n", vmw_read(dev_priv, SVGA_REG_HEIGHT));
104fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	DRM_INFO("bpp %d\n", vmw_read(dev_priv, SVGA_REG_BITS_PER_PIXEL));
105fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
106fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	mutex_lock(&dev_priv->hw_mutex);
107fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE);
108fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE);
10930c78bb838b26ec7997515844c0c734e454b3cbaThomas Hellstrom	dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES);
110fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
111fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
112fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	min = 4;
113fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO)
114fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		min = vmw_read(dev_priv, SVGA_REG_MEM_REGS);
115fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	min <<= 2;
116fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
117fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (min < PAGE_SIZE)
118fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		min = PAGE_SIZE;
119fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
120fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	iowrite32(min, fifo_mem + SVGA_FIFO_MIN);
121fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	iowrite32(dev_priv->mmio_size, fifo_mem + SVGA_FIFO_MAX);
122fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	wmb();
123fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	iowrite32(min,  fifo_mem + SVGA_FIFO_NEXT_CMD);
124fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	iowrite32(min,  fifo_mem + SVGA_FIFO_STOP);
125fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	iowrite32(0, fifo_mem + SVGA_FIFO_BUSY);
126fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	mb();
127fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
128fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	vmw_write(dev_priv, SVGA_REG_CONFIG_DONE, 1);
129fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	mutex_unlock(&dev_priv->hw_mutex);
130fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
131fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	max = ioread32(fifo_mem + SVGA_FIFO_MAX);
132fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	min = ioread32(fifo_mem  + SVGA_FIFO_MIN);
133fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	fifo->capabilities = ioread32(fifo_mem + SVGA_FIFO_CAPABILITIES);
134fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
135fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	DRM_INFO("Fifo max 0x%08x min 0x%08x cap 0x%08x\n",
136fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		 (unsigned int) max,
137fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		 (unsigned int) min,
138fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		 (unsigned int) fifo->capabilities);
139fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
1406bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom	atomic_set(&dev_priv->marker_seq, dev_priv->last_read_seqno);
1416bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom	iowrite32(dev_priv->last_read_seqno, fifo_mem + SVGA_FIFO_FENCE);
1426bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom	vmw_marker_queue_init(&fifo->marker_queue);
143fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	return vmw_fifo_send_fence(dev_priv, &dummy);
144fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
145fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
146fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason)
147fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
148fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
149fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
150fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	mutex_lock(&dev_priv->hw_mutex);
151fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
152fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (unlikely(ioread32(fifo_mem + SVGA_FIFO_BUSY) == 0)) {
153fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		iowrite32(1, fifo_mem + SVGA_FIFO_BUSY);
154fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		vmw_write(dev_priv, SVGA_REG_SYNC, reason);
155fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
156fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
157fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	mutex_unlock(&dev_priv->hw_mutex);
158fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
159fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
160fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
161fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
162fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
163fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
164fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	mutex_lock(&dev_priv->hw_mutex);
165fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
166fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0)
167fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
168fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
1696bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom	dev_priv->last_read_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
170fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
171fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	vmw_write(dev_priv, SVGA_REG_CONFIG_DONE,
172fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		  dev_priv->config_done_state);
173fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	vmw_write(dev_priv, SVGA_REG_ENABLE,
174fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		  dev_priv->enable_state);
17530c78bb838b26ec7997515844c0c734e454b3cbaThomas Hellstrom	vmw_write(dev_priv, SVGA_REG_TRACES,
17630c78bb838b26ec7997515844c0c734e454b3cbaThomas Hellstrom		  dev_priv->traces_state);
177fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
178fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	mutex_unlock(&dev_priv->hw_mutex);
1796bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom	vmw_marker_queue_takedown(&fifo->marker_queue);
180fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
181fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (likely(fifo->static_buffer != NULL)) {
182fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		vfree(fifo->static_buffer);
183fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		fifo->static_buffer = NULL;
184fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
185fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
186fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (likely(fifo->dynamic_buffer != NULL)) {
187fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		vfree(fifo->dynamic_buffer);
188fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		fifo->dynamic_buffer = NULL;
189fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
190fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
191fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
192fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic bool vmw_fifo_is_full(struct vmw_private *dev_priv, uint32_t bytes)
193fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
194fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
195fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t max = ioread32(fifo_mem + SVGA_FIFO_MAX);
196fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD);
197fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t min = ioread32(fifo_mem + SVGA_FIFO_MIN);
198fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t stop = ioread32(fifo_mem + SVGA_FIFO_STOP);
199fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
200fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	return ((max - next_cmd) + (stop - min) <= bytes);
201fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
202fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
203fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_fifo_wait_noirq(struct vmw_private *dev_priv,
204fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			       uint32_t bytes, bool interruptible,
205fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			       unsigned long timeout)
206fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
207fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	int ret = 0;
208fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	unsigned long end_jiffies = jiffies + timeout;
209fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	DEFINE_WAIT(__wait);
210fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
211fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	DRM_INFO("Fifo wait noirq.\n");
212fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
213fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	for (;;) {
214fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		prepare_to_wait(&dev_priv->fifo_queue, &__wait,
215fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				(interruptible) ?
216fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
217fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		if (!vmw_fifo_is_full(dev_priv, bytes))
218fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			break;
219fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		if (time_after_eq(jiffies, end_jiffies)) {
220fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			ret = -EBUSY;
221fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			DRM_ERROR("SVGA device lockup.\n");
222fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			break;
223fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		}
224fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		schedule_timeout(1);
225fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		if (interruptible && signal_pending(current)) {
2263d3a5b3290043618e8409f3fb68a63de6156fdd4Thomas Hellstrom			ret = -ERESTARTSYS;
227fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			break;
228fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		}
229fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
230fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	finish_wait(&dev_priv->fifo_queue, &__wait);
231fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	wake_up_all(&dev_priv->fifo_queue);
232fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	DRM_INFO("Fifo noirq exit.\n");
233fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	return ret;
234fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
235fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
236fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_fifo_wait(struct vmw_private *dev_priv,
237fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			 uint32_t bytes, bool interruptible,
238fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			 unsigned long timeout)
239fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
240fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	long ret = 1L;
241fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	unsigned long irq_flags;
242fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
243fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (likely(!vmw_fifo_is_full(dev_priv, bytes)))
244fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		return 0;
245fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
246fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_FIFOFULL);
247fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
248fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		return vmw_fifo_wait_noirq(dev_priv, bytes,
249fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz					   interruptible, timeout);
250fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
251fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	mutex_lock(&dev_priv->hw_mutex);
252fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (atomic_add_return(1, &dev_priv->fifo_queue_waiters) > 0) {
253fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
254fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		outl(SVGA_IRQFLAG_FIFO_PROGRESS,
255fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		     dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
25657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom		dev_priv->irq_mask |= SVGA_IRQFLAG_FIFO_PROGRESS;
25757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
258fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
259fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
260fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	mutex_unlock(&dev_priv->hw_mutex);
261fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
262fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (interruptible)
263fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		ret = wait_event_interruptible_timeout
264fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		    (dev_priv->fifo_queue,
265fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		     !vmw_fifo_is_full(dev_priv, bytes), timeout);
266fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	else
267fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		ret = wait_event_timeout
268fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		    (dev_priv->fifo_queue,
269fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		     !vmw_fifo_is_full(dev_priv, bytes), timeout);
270fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2713d3a5b3290043618e8409f3fb68a63de6156fdd4Thomas Hellstrom	if (unlikely(ret == 0))
272fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		ret = -EBUSY;
273fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	else if (likely(ret > 0))
274fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		ret = 0;
275fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
276fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	mutex_lock(&dev_priv->hw_mutex);
277fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (atomic_dec_and_test(&dev_priv->fifo_queue_waiters)) {
278fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
27957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom		dev_priv->irq_mask &= ~SVGA_IRQFLAG_FIFO_PROGRESS;
28057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
281fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
282fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
283fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	mutex_unlock(&dev_priv->hw_mutex);
284fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
285fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	return ret;
286fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
287fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
288de12d44fcad409e1b2956ef0ffd48818423fc701Jakob Bornecrantz/**
289de12d44fcad409e1b2956ef0ffd48818423fc701Jakob Bornecrantz * Reserve @bytes number of bytes in the fifo.
290de12d44fcad409e1b2956ef0ffd48818423fc701Jakob Bornecrantz *
291de12d44fcad409e1b2956ef0ffd48818423fc701Jakob Bornecrantz * This function will return NULL (error) on two conditions:
292de12d44fcad409e1b2956ef0ffd48818423fc701Jakob Bornecrantz *  If it timeouts waiting for fifo space, or if @bytes is larger than the
293de12d44fcad409e1b2956ef0ffd48818423fc701Jakob Bornecrantz *   available fifo space.
294de12d44fcad409e1b2956ef0ffd48818423fc701Jakob Bornecrantz *
295de12d44fcad409e1b2956ef0ffd48818423fc701Jakob Bornecrantz * Returns:
296de12d44fcad409e1b2956ef0ffd48818423fc701Jakob Bornecrantz *   Pointer to the fifo, or null on error (possible hardware hang).
297de12d44fcad409e1b2956ef0ffd48818423fc701Jakob Bornecrantz */
298fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes)
299fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
300fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
301fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
302fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t max;
303fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t min;
304fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t next_cmd;
305fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE;
306fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	int ret;
307fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
30885b9e4878f3b16993fba871c0c68d0948ec9c7c6Thomas Hellstrom	mutex_lock(&fifo_state->fifo_mutex);
309fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	max = ioread32(fifo_mem + SVGA_FIFO_MAX);
310fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	min = ioread32(fifo_mem + SVGA_FIFO_MIN);
311fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD);
312fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
313fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (unlikely(bytes >= (max - min)))
314fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		goto out_err;
315fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
316fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	BUG_ON(fifo_state->reserved_size != 0);
317fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	BUG_ON(fifo_state->dynamic_buffer != NULL);
318fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
319fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	fifo_state->reserved_size = bytes;
320fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
321fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	while (1) {
322fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		uint32_t stop = ioread32(fifo_mem + SVGA_FIFO_STOP);
323fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		bool need_bounce = false;
324fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		bool reserve_in_place = false;
325fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
326fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		if (next_cmd >= stop) {
327fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			if (likely((next_cmd + bytes < max ||
328fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				    (next_cmd + bytes == max && stop > min))))
329fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				reserve_in_place = true;
330fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
331fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			else if (vmw_fifo_is_full(dev_priv, bytes)) {
332fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				ret = vmw_fifo_wait(dev_priv, bytes,
333fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz						    false, 3 * HZ);
334fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				if (unlikely(ret != 0))
335fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz					goto out_err;
336fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			} else
337fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				need_bounce = true;
338fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
339fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		} else {
340fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
341fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			if (likely((next_cmd + bytes < stop)))
342fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				reserve_in_place = true;
343fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			else {
344fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				ret = vmw_fifo_wait(dev_priv, bytes,
345fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz						    false, 3 * HZ);
346fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				if (unlikely(ret != 0))
347fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz					goto out_err;
348fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			}
349fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		}
350fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
351fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		if (reserve_in_place) {
352fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			if (reserveable || bytes <= sizeof(uint32_t)) {
353fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				fifo_state->using_bounce_buffer = false;
354fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
355fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				if (reserveable)
356fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz					iowrite32(bytes, fifo_mem +
357fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz						  SVGA_FIFO_RESERVED);
358fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				return fifo_mem + (next_cmd >> 2);
359fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			} else {
360fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				need_bounce = true;
361fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			}
362fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		}
363fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
364fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		if (need_bounce) {
365fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			fifo_state->using_bounce_buffer = true;
366fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			if (bytes < fifo_state->static_buffer_size)
367fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				return fifo_state->static_buffer;
368fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			else {
369fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				fifo_state->dynamic_buffer = vmalloc(bytes);
370fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				return fifo_state->dynamic_buffer;
371fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			}
372fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		}
373fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
374fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout_err:
375fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	fifo_state->reserved_size = 0;
37685b9e4878f3b16993fba871c0c68d0948ec9c7c6Thomas Hellstrom	mutex_unlock(&fifo_state->fifo_mutex);
377fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	return NULL;
378fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
379fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
380fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_fifo_res_copy(struct vmw_fifo_state *fifo_state,
381fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			      __le32 __iomem *fifo_mem,
382fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			      uint32_t next_cmd,
383fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			      uint32_t max, uint32_t min, uint32_t bytes)
384fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
385fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t chunk_size = max - next_cmd;
386fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t rest;
387fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t *buffer = (fifo_state->dynamic_buffer != NULL) ?
388fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	    fifo_state->dynamic_buffer : fifo_state->static_buffer;
389fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
390fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (bytes < chunk_size)
391fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		chunk_size = bytes;
392fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
393fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	iowrite32(bytes, fifo_mem + SVGA_FIFO_RESERVED);
394fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	mb();
395fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	memcpy_toio(fifo_mem + (next_cmd >> 2), buffer, chunk_size);
396fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	rest = bytes - chunk_size;
397fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (rest)
398fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		memcpy_toio(fifo_mem + (min >> 2), buffer + (chunk_size >> 2),
399fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			    rest);
400fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
401fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
402fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_fifo_slow_copy(struct vmw_fifo_state *fifo_state,
403fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			       __le32 __iomem *fifo_mem,
404fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			       uint32_t next_cmd,
405fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			       uint32_t max, uint32_t min, uint32_t bytes)
406fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
407fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t *buffer = (fifo_state->dynamic_buffer != NULL) ?
408fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	    fifo_state->dynamic_buffer : fifo_state->static_buffer;
409fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
410fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	while (bytes > 0) {
411fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		iowrite32(*buffer++, fifo_mem + (next_cmd >> 2));
412fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		next_cmd += sizeof(uint32_t);
413fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		if (unlikely(next_cmd == max))
414fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			next_cmd = min;
415fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		mb();
416fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		iowrite32(next_cmd, fifo_mem + SVGA_FIFO_NEXT_CMD);
417fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		mb();
418fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		bytes -= sizeof(uint32_t);
419fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
420fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
421fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
422fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes)
423fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
424fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
425fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
426fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD);
427fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t max = ioread32(fifo_mem + SVGA_FIFO_MAX);
428fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t min = ioread32(fifo_mem + SVGA_FIFO_MIN);
429fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	bool reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE;
430fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
431fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	BUG_ON((bytes & 3) != 0);
432fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	BUG_ON(bytes > fifo_state->reserved_size);
433fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
434fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	fifo_state->reserved_size = 0;
435fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
436fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (fifo_state->using_bounce_buffer) {
437fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		if (reserveable)
438fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			vmw_fifo_res_copy(fifo_state, fifo_mem,
439fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz					  next_cmd, max, min, bytes);
440fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		else
441fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			vmw_fifo_slow_copy(fifo_state, fifo_mem,
442fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz					   next_cmd, max, min, bytes);
443fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
444fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		if (fifo_state->dynamic_buffer) {
445fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			vfree(fifo_state->dynamic_buffer);
446fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			fifo_state->dynamic_buffer = NULL;
447fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		}
448fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
449fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
450fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
45185b9e4878f3b16993fba871c0c68d0948ec9c7c6Thomas Hellstrom	down_write(&fifo_state->rwsem);
452fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (fifo_state->using_bounce_buffer || reserveable) {
453fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		next_cmd += bytes;
454fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		if (next_cmd >= max)
455fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			next_cmd -= max - min;
456fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		mb();
457fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		iowrite32(next_cmd, fifo_mem + SVGA_FIFO_NEXT_CMD);
458fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
459fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
460fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (reserveable)
461fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		iowrite32(0, fifo_mem + SVGA_FIFO_RESERVED);
462fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	mb();
463fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	up_write(&fifo_state->rwsem);
46485b9e4878f3b16993fba871c0c68d0948ec9c7c6Thomas Hellstrom	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
46585b9e4878f3b16993fba871c0c68d0948ec9c7c6Thomas Hellstrom	mutex_unlock(&fifo_state->fifo_mutex);
466fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
467fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
4686bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstromint vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *seqno)
469fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
470fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
471fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	struct svga_fifo_cmd_fence *cmd_fence;
472fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	void *fm;
473fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	int ret = 0;
474fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t bytes = sizeof(__le32) + sizeof(*cmd_fence);
475fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
476fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	fm = vmw_fifo_reserve(dev_priv, bytes);
477fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (unlikely(fm == NULL)) {
4786bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom		*seqno = atomic_read(&dev_priv->marker_seq);
479fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		ret = -ENOMEM;
4806bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom		(void)vmw_fallback_wait(dev_priv, false, true, *seqno,
481fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz					false, 3*HZ);
482fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		goto out_err;
483fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
484fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
485fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	do {
4866bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom		*seqno = atomic_add_return(1, &dev_priv->marker_seq);
4876bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom	} while (*seqno == 0);
488fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
489fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE)) {
490fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
491fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		/*
492fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		 * Don't request hardware to send a fence. The
493fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		 * waiting code in vmwgfx_irq.c will emulate this.
494fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		 */
495fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
496fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		vmw_fifo_commit(dev_priv, 0);
497fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		return 0;
498fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
499fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
500fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	*(__le32 *) fm = cpu_to_le32(SVGA_CMD_FENCE);
501fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	cmd_fence = (struct svga_fifo_cmd_fence *)
502fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	    ((unsigned long)fm + sizeof(__le32));
503fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
5046bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom	iowrite32(*seqno, &cmd_fence->fence);
505fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	vmw_fifo_commit(dev_priv, bytes);
5066bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom	(void) vmw_marker_push(&fifo_state->marker_queue, *seqno);
5076bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom	vmw_update_seqno(dev_priv, fifo_state);
508fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
509fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout_err:
510fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	return ret;
511fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
512e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
513e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom/**
514e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * vmw_fifo_emit_dummy_query - emits a dummy query to the fifo.
515e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
516e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * @dev_priv: The device private structure.
517e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * @cid: The hardware context id used for the query.
518e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
519e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * This function is used to emit a dummy occlusion query with
520e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * no primitives rendered between query begin and query end.
521e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * It's used to provide a query barrier, in order to know that when
522e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * this query is finished, all preceding queries are also finished.
523e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
524e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * A Query results structure should have been initialized at the start
525e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * of the dev_priv->dummy_query_bo buffer object. And that buffer object
526e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * must also be either reserved or pinned when this function is called.
527e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
528e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * Returns -ENOMEM on failure to reserve fifo space.
529e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom */
530e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstromint vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv,
531e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom			      uint32_t cid)
532e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom{
533e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	/*
534e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	 * A query wait without a preceding query end will
535e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	 * actually finish all queries for this cid
536e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	 * without writing to the query result structure.
537e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	 */
538e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
539e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	struct ttm_buffer_object *bo = dev_priv->dummy_query_bo;
540e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	struct {
541e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		SVGA3dCmdHeader header;
542e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		SVGA3dCmdWaitForQuery body;
543e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	} *cmd;
544e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
545e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
546e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
547e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	if (unlikely(cmd == NULL)) {
548e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		DRM_ERROR("Out of fifo space for dummy query.\n");
549e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		return -ENOMEM;
550e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	}
551e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
552e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	cmd->header.id = SVGA_3D_CMD_WAIT_FOR_QUERY;
553e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	cmd->header.size = sizeof(cmd->body);
554e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	cmd->body.cid = cid;
555e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	cmd->body.type = SVGA3D_QUERYTYPE_OCCLUSION;
556e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
557e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	if (bo->mem.mem_type == TTM_PL_VRAM) {
558e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		cmd->body.guestResult.gmrId = SVGA_GMR_FRAMEBUFFER;
559e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		cmd->body.guestResult.offset = bo->offset;
560e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	} else {
561e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		cmd->body.guestResult.gmrId = bo->mem.start;
562e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		cmd->body.guestResult.offset = 0;
563e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	}
564e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
565e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	vmw_fifo_commit(dev_priv, sizeof(*cmd));
566e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
567e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	return 0;
568e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom}
569