1 /*        $NetBSD: vmwgfx_fifo.c,v 1.4 2022/10/25 23:34:06 riastradh Exp $      */
2 
3 // SPDX-License-Identifier: GPL-2.0 OR MIT
4 /**************************************************************************
5  *
6  * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the
10  * "Software"), to deal in the Software without restriction, including
11  * without limitation the rights to use, copy, modify, merge, publish,
12  * distribute, sub license, and/or sell copies of the Software, and to
13  * permit persons to whom the Software is furnished to do so, subject to
14  * the following conditions:
15  *
16  * The above copyright notice and this permission notice (including the
17  * next paragraph) shall be included in all copies or substantial portions
18  * of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
23  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
24  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
25  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
26  * USE OR OTHER DEALINGS IN THE SOFTWARE.
27  *
28  **************************************************************************/
29 
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: vmwgfx_fifo.c,v 1.4 2022/10/25 23:34:06 riastradh Exp $");
32 
33 #include <linux/sched/signal.h>
34 
35 #include <drm/ttm/ttm_placement.h>
36 
37 #include "vmwgfx_drv.h"
38 
39 #include <linux/nbsd-namespace.h>
40 
41 struct vmw_temp_set_context {
42           SVGA3dCmdHeader header;
43           SVGA3dCmdDXTempSetContext body;
44 };
45 
vmw_fifo_have_3d(struct vmw_private * dev_priv)46 bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
47 {
48           u32 *fifo_mem = dev_priv->mmio_virt;
49           uint32_t fifo_min, hwversion;
50           const struct vmw_fifo_state *fifo = &dev_priv->fifo;
51 
52           if (!(dev_priv->capabilities & SVGA_CAP_3D))
53                     return false;
54 
55           if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) {
56                     uint32_t result;
57 
58                     if (!dev_priv->has_mob)
59                               return false;
60 
61                     spin_lock(&dev_priv->cap_lock);
62                     vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_3D);
63                     result = vmw_read(dev_priv, SVGA_REG_DEV_CAP);
64                     spin_unlock(&dev_priv->cap_lock);
65 
66                     return (result != 0);
67           }
68 
69           if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
70                     return false;
71 
72           fifo_min = vmw_mmio_read(fifo_mem  + SVGA_FIFO_MIN);
73           if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
74                     return false;
75 
76           hwversion = vmw_mmio_read(fifo_mem +
77                                           ((fifo->capabilities &
78                                             SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ?
79                                            SVGA_FIFO_3D_HWVERSION_REVISED :
80                                            SVGA_FIFO_3D_HWVERSION));
81 
82           if (hwversion == 0)
83                     return false;
84 
85           if (hwversion < SVGA3D_HWVERSION_WS8_B1)
86                     return false;
87 
88           /* Legacy Display Unit does not support surfaces */
89           if (dev_priv->active_display_unit == vmw_du_legacy)
90                     return false;
91 
92           return true;
93 }
94 
vmw_fifo_have_pitchlock(struct vmw_private * dev_priv)95 bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv)
96 {
97           u32  *fifo_mem = dev_priv->mmio_virt;
98           uint32_t caps;
99 
100           if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
101                     return false;
102 
103           caps = vmw_mmio_read(fifo_mem + SVGA_FIFO_CAPABILITIES);
104           if (caps & SVGA_FIFO_CAP_PITCHLOCK)
105                     return true;
106 
107           return false;
108 }
109 
vmw_fifo_init(struct vmw_private * dev_priv,struct vmw_fifo_state * fifo)110 int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
111 {
112           u32  *fifo_mem = dev_priv->mmio_virt;
113           uint32_t max;
114           uint32_t min;
115 
116           fifo->dx = false;
117           fifo->static_buffer_size = VMWGFX_FIFO_STATIC_SIZE;
118           fifo->static_buffer = vmalloc(fifo->static_buffer_size);
119           if (unlikely(fifo->static_buffer == NULL))
120                     return -ENOMEM;
121 
122           fifo->dynamic_buffer = NULL;
123           fifo->reserved_size = 0;
124           fifo->using_bounce_buffer = false;
125 
126           mutex_init(&fifo->fifo_mutex);
127           init_rwsem(&fifo->rwsem);
128 
129           DRM_INFO("width %d\n", vmw_read(dev_priv, SVGA_REG_WIDTH));
130           DRM_INFO("height %d\n", vmw_read(dev_priv, SVGA_REG_HEIGHT));
131           DRM_INFO("bpp %d\n", vmw_read(dev_priv, SVGA_REG_BITS_PER_PIXEL));
132 
133           dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE);
134           dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE);
135           dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES);
136 
137           vmw_write(dev_priv, SVGA_REG_ENABLE, SVGA_REG_ENABLE_ENABLE |
138                       SVGA_REG_ENABLE_HIDE);
139           vmw_write(dev_priv, SVGA_REG_TRACES, 0);
140 
141           min = 4;
142           if (dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO)
143                     min = vmw_read(dev_priv, SVGA_REG_MEM_REGS);
144           min <<= 2;
145 
146           if (min < PAGE_SIZE)
147                     min = PAGE_SIZE;
148 
149           vmw_mmio_write(min, fifo_mem + SVGA_FIFO_MIN);
150           vmw_mmio_write(dev_priv->mmio_size, fifo_mem + SVGA_FIFO_MAX);
151           wmb();
152           vmw_mmio_write(min,  fifo_mem + SVGA_FIFO_NEXT_CMD);
153           vmw_mmio_write(min,  fifo_mem + SVGA_FIFO_STOP);
154           vmw_mmio_write(0, fifo_mem + SVGA_FIFO_BUSY);
155           mb();
156 
157           vmw_write(dev_priv, SVGA_REG_CONFIG_DONE, 1);
158 
159           max = vmw_mmio_read(fifo_mem + SVGA_FIFO_MAX);
160           min = vmw_mmio_read(fifo_mem  + SVGA_FIFO_MIN);
161           fifo->capabilities = vmw_mmio_read(fifo_mem + SVGA_FIFO_CAPABILITIES);
162 
163           DRM_INFO("Fifo max 0x%08x min 0x%08x cap 0x%08x\n",
164                      (unsigned int) max,
165                      (unsigned int) min,
166                      (unsigned int) fifo->capabilities);
167 
168           atomic_set(&dev_priv->marker_seq, dev_priv->last_read_seqno);
169           vmw_mmio_write(dev_priv->last_read_seqno, fifo_mem + SVGA_FIFO_FENCE);
170           vmw_marker_queue_init(&fifo->marker_queue);
171 
172           return 0;
173 }
174 
vmw_fifo_ping_host(struct vmw_private * dev_priv,uint32_t reason)175 void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason)
176 {
177           u32 *fifo_mem = dev_priv->mmio_virt;
178 
179           preempt_disable();
180           if (cmpxchg(fifo_mem + SVGA_FIFO_BUSY, 0, 1) == 0)
181                     vmw_write(dev_priv, SVGA_REG_SYNC, reason);
182           preempt_enable();
183 }
184 
vmw_fifo_release(struct vmw_private * dev_priv,struct vmw_fifo_state * fifo)185 void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
186 {
187           u32  *fifo_mem = dev_priv->mmio_virt;
188 
189           vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
190           while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0)
191                     ;
192 
193           dev_priv->last_read_seqno = vmw_mmio_read(fifo_mem + SVGA_FIFO_FENCE);
194 
195           vmw_write(dev_priv, SVGA_REG_CONFIG_DONE,
196                       dev_priv->config_done_state);
197           vmw_write(dev_priv, SVGA_REG_ENABLE,
198                       dev_priv->enable_state);
199           vmw_write(dev_priv, SVGA_REG_TRACES,
200                       dev_priv->traces_state);
201 
202           vmw_marker_queue_takedown(&fifo->marker_queue);
203 
204           if (likely(fifo->static_buffer != NULL)) {
205                     vfree(fifo->static_buffer);
206                     fifo->static_buffer = NULL;
207           }
208 
209           if (likely(fifo->dynamic_buffer != NULL)) {
210                     vfree(fifo->dynamic_buffer);
211                     fifo->dynamic_buffer = NULL;
212           }
213 }
214 
vmw_fifo_is_full(struct vmw_private * dev_priv,uint32_t bytes)215 static bool vmw_fifo_is_full(struct vmw_private *dev_priv, uint32_t bytes)
216 {
217           u32  *fifo_mem = dev_priv->mmio_virt;
218           uint32_t max = vmw_mmio_read(fifo_mem + SVGA_FIFO_MAX);
219           uint32_t next_cmd = vmw_mmio_read(fifo_mem + SVGA_FIFO_NEXT_CMD);
220           uint32_t min = vmw_mmio_read(fifo_mem + SVGA_FIFO_MIN);
221           uint32_t stop = vmw_mmio_read(fifo_mem + SVGA_FIFO_STOP);
222 
223           return ((max - next_cmd) + (stop - min) <= bytes);
224 }
225 
vmw_fifo_wait_noirq(struct vmw_private * dev_priv,uint32_t bytes,bool interruptible,unsigned long timeout)226 static int vmw_fifo_wait_noirq(struct vmw_private *dev_priv,
227                                      uint32_t bytes, bool interruptible,
228                                      unsigned long timeout)
229 {
230           int ret = 0;
231           unsigned long end_jiffies = jiffies + timeout;
232 #ifdef __NetBSD__
233           assert_spin_locked(&dev_priv->fifo_lock);
234 #else
235           DEFINE_WAIT(__wait);
236 #endif
237 
238           DRM_INFO("Fifo wait noirq.\n");
239 
240           for (;;) {
241 #ifndef __NetBSD__
242                     prepare_to_wait(&dev_priv->fifo_queue, &__wait,
243                                         (interruptible) ?
244                                         TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
245 #endif
246                     if (!vmw_fifo_is_full(dev_priv, bytes))
247                               break;
248                     if (time_after_eq(jiffies, end_jiffies)) {
249                               ret = -EBUSY;
250                               DRM_ERROR("SVGA device lockup.\n");
251                               break;
252                     }
253 #ifdef __NetBSD__
254                     if (interruptible) {
255                               DRM_SPIN_TIMED_WAIT_UNTIL(ret, &dev_priv->fifo_queue,
256                                   &dev_priv->fifo_lock, 1,
257                                   !vmw_fifo_is_full(dev_priv, bytes));
258                     } else {
259                               DRM_SPIN_TIMED_WAIT_NOINTR_UNTIL(ret,
260                                   &dev_priv->fifo_queue,
261                                   &dev_priv->fifo_lock, 1,
262                                   !vmw_fifo_is_full(dev_priv, bytes));
263                     }
264                     if (ret) {
265                               if (ret > 0) /* success */
266                                         ret = 0;
267                               break;
268                     }
269                     /*
270                      * ret=0 means the wait timed out after one tick, so
271                      * try again
272                      */
273 #else
274                     schedule_timeout(1);
275                     if (interruptible && signal_pending(current)) {
276                               ret = -ERESTARTSYS;
277                               break;
278                     }
279 #endif
280           }
281 #ifdef __NetBSD__
282           DRM_SPIN_WAKEUP_ALL(&dev_priv->fifo_queue, &dev_priv->fifo_lock);
283 #else
284           finish_wait(&dev_priv->fifo_queue, &__wait);
285           wake_up_all(&dev_priv->fifo_queue);
286 #endif
287           DRM_INFO("Fifo noirq exit.\n");
288           return ret;
289 }
290 
vmw_fifo_wait(struct vmw_private * dev_priv,uint32_t bytes,bool interruptible,unsigned long timeout)291 static int vmw_fifo_wait(struct vmw_private *dev_priv,
292                                uint32_t bytes, bool interruptible,
293                                unsigned long timeout)
294 {
295           long ret = 1L;
296 
297           spin_lock(&dev_priv->fifo_lock);
298 
299           if (likely(!vmw_fifo_is_full(dev_priv, bytes))) {
300                     spin_unlock(&dev_priv->fifo_lock);
301                     return 0;
302           }
303 
304           vmw_fifo_ping_host(dev_priv, SVGA_SYNC_FIFOFULL);
305           if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK)) {
306                     ret = vmw_fifo_wait_noirq(dev_priv, bytes,
307                                                      interruptible, timeout);
308                     spin_unlock(&dev_priv->fifo_lock);
309                     return ret;
310           }
311 
312           vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_FIFO_PROGRESS,
313                                      &dev_priv->fifo_queue_waiters);
314 
315           if (interruptible)
316                     DRM_SPIN_TIMED_WAIT_UNTIL(ret, &dev_priv->fifo_queue,
317                         &dev_priv->fifo_lock, timeout,
318                         !vmw_fifo_is_full(dev_priv, bytes));
319           else
320                     DRM_SPIN_TIMED_WAIT_NOINTR_UNTIL(ret, &dev_priv->fifo_queue,
321                         &dev_priv->fifo_lock, timeout,
322                         !vmw_fifo_is_full(dev_priv, bytes));
323 
324           if (unlikely(ret == 0))
325                     ret = -EBUSY;
326           else if (likely(ret > 0))
327                     ret = 0;
328 
329           vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_FIFO_PROGRESS,
330                                           &dev_priv->fifo_queue_waiters);
331 
332           spin_unlock(&dev_priv->fifo_lock);
333 
334           return ret;
335 }
336 
337 /**
338  * Reserve @bytes number of bytes in the fifo.
339  *
340  * This function will return NULL (error) on two conditions:
341  *  If it timeouts waiting for fifo space, or if @bytes is larger than the
342  *   available fifo space.
343  *
344  * Returns:
345  *   Pointer to the fifo, or null on error (possible hardware hang).
346  */
vmw_local_fifo_reserve(struct vmw_private * dev_priv,uint32_t bytes)347 static void *vmw_local_fifo_reserve(struct vmw_private *dev_priv,
348                                             uint32_t bytes)
349 {
350           struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
351           u32  *fifo_mem = dev_priv->mmio_virt;
352           uint32_t max;
353           uint32_t min;
354           uint32_t next_cmd;
355           uint32_t reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE;
356           int ret;
357 
358           mutex_lock(&fifo_state->fifo_mutex);
359           max = vmw_mmio_read(fifo_mem + SVGA_FIFO_MAX);
360           min = vmw_mmio_read(fifo_mem + SVGA_FIFO_MIN);
361           next_cmd = vmw_mmio_read(fifo_mem + SVGA_FIFO_NEXT_CMD);
362 
363           if (unlikely(bytes >= (max - min)))
364                     goto out_err;
365 
366           BUG_ON(fifo_state->reserved_size != 0);
367           BUG_ON(fifo_state->dynamic_buffer != NULL);
368 
369           fifo_state->reserved_size = bytes;
370 
371           while (1) {
372                     uint32_t stop = vmw_mmio_read(fifo_mem + SVGA_FIFO_STOP);
373                     bool need_bounce = false;
374                     bool reserve_in_place = false;
375 
376                     if (next_cmd >= stop) {
377                               if (likely((next_cmd + bytes < max ||
378                                             (next_cmd + bytes == max && stop > min))))
379                                         reserve_in_place = true;
380 
381                               else if (vmw_fifo_is_full(dev_priv, bytes)) {
382                                         ret = vmw_fifo_wait(dev_priv, bytes,
383                                                                 false, 3 * HZ);
384                                         if (unlikely(ret != 0))
385                                                   goto out_err;
386                               } else
387                                         need_bounce = true;
388 
389                     } else {
390 
391                               if (likely((next_cmd + bytes < stop)))
392                                         reserve_in_place = true;
393                               else {
394                                         ret = vmw_fifo_wait(dev_priv, bytes,
395                                                                 false, 3 * HZ);
396                                         if (unlikely(ret != 0))
397                                                   goto out_err;
398                               }
399                     }
400 
401                     if (reserve_in_place) {
402                               if (reserveable || bytes <= sizeof(uint32_t)) {
403                                         fifo_state->using_bounce_buffer = false;
404 
405                                         if (reserveable)
406                                                   vmw_mmio_write(bytes, fifo_mem +
407                                                                    SVGA_FIFO_RESERVED);
408                                         return (void __force *) (fifo_mem +
409                                                                        (next_cmd >> 2));
410                               } else {
411                                         need_bounce = true;
412                               }
413                     }
414 
415                     if (need_bounce) {
416                               fifo_state->using_bounce_buffer = true;
417                               if (bytes < fifo_state->static_buffer_size)
418                                         return fifo_state->static_buffer;
419                               else {
420                                         fifo_state->dynamic_buffer = vmalloc(bytes);
421                                         if (!fifo_state->dynamic_buffer)
422                                                   goto out_err;
423                                         return fifo_state->dynamic_buffer;
424                               }
425                     }
426           }
427 out_err:
428           fifo_state->reserved_size = 0;
429           mutex_unlock(&fifo_state->fifo_mutex);
430 
431           return NULL;
432 }
433 
vmw_fifo_reserve_dx(struct vmw_private * dev_priv,uint32_t bytes,int ctx_id)434 void *vmw_fifo_reserve_dx(struct vmw_private *dev_priv, uint32_t bytes,
435                                 int ctx_id)
436 {
437           void *ret;
438 
439           if (dev_priv->cman)
440                     ret = vmw_cmdbuf_reserve(dev_priv->cman, bytes,
441                                                    ctx_id, false, NULL);
442           else if (ctx_id == SVGA3D_INVALID_ID)
443                     ret = vmw_local_fifo_reserve(dev_priv, bytes);
444           else {
445                     WARN(1, "Command buffer has not been allocated.\n");
446                     ret = NULL;
447           }
448           if (IS_ERR_OR_NULL(ret))
449                     return NULL;
450 
451           return ret;
452 }
453 
vmw_fifo_res_copy(struct vmw_fifo_state * fifo_state,u32 * fifo_mem,uint32_t next_cmd,uint32_t max,uint32_t min,uint32_t bytes)454 static void vmw_fifo_res_copy(struct vmw_fifo_state *fifo_state,
455                                     u32  *fifo_mem,
456                                     uint32_t next_cmd,
457                                     uint32_t max, uint32_t min, uint32_t bytes)
458 {
459           uint32_t chunk_size = max - next_cmd;
460           uint32_t rest;
461           uint32_t *buffer = (fifo_state->dynamic_buffer != NULL) ?
462               fifo_state->dynamic_buffer : fifo_state->static_buffer;
463 
464           if (bytes < chunk_size)
465                     chunk_size = bytes;
466 
467           vmw_mmio_write(bytes, fifo_mem + SVGA_FIFO_RESERVED);
468           mb();
469           memcpy(fifo_mem + (next_cmd >> 2), buffer, chunk_size);
470           rest = bytes - chunk_size;
471           if (rest)
472                     memcpy(fifo_mem + (min >> 2), buffer + (chunk_size >> 2), rest);
473 }
474 
vmw_fifo_slow_copy(struct vmw_fifo_state * fifo_state,u32 * fifo_mem,uint32_t next_cmd,uint32_t max,uint32_t min,uint32_t bytes)475 static void vmw_fifo_slow_copy(struct vmw_fifo_state *fifo_state,
476                                      u32  *fifo_mem,
477                                      uint32_t next_cmd,
478                                      uint32_t max, uint32_t min, uint32_t bytes)
479 {
480           uint32_t *buffer = (fifo_state->dynamic_buffer != NULL) ?
481               fifo_state->dynamic_buffer : fifo_state->static_buffer;
482 
483           while (bytes > 0) {
484                     vmw_mmio_write(*buffer++, fifo_mem + (next_cmd >> 2));
485                     next_cmd += sizeof(uint32_t);
486                     if (unlikely(next_cmd == max))
487                               next_cmd = min;
488                     mb();
489                     vmw_mmio_write(next_cmd, fifo_mem + SVGA_FIFO_NEXT_CMD);
490                     mb();
491                     bytes -= sizeof(uint32_t);
492           }
493 }
494 
vmw_local_fifo_commit(struct vmw_private * dev_priv,uint32_t bytes)495 static void vmw_local_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes)
496 {
497           struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
498           u32  *fifo_mem = dev_priv->mmio_virt;
499           uint32_t next_cmd = vmw_mmio_read(fifo_mem + SVGA_FIFO_NEXT_CMD);
500           uint32_t max = vmw_mmio_read(fifo_mem + SVGA_FIFO_MAX);
501           uint32_t min = vmw_mmio_read(fifo_mem + SVGA_FIFO_MIN);
502           bool reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE;
503 
504           if (fifo_state->dx)
505                     bytes += sizeof(struct vmw_temp_set_context);
506 
507           fifo_state->dx = false;
508           BUG_ON((bytes & 3) != 0);
509           BUG_ON(bytes > fifo_state->reserved_size);
510 
511           fifo_state->reserved_size = 0;
512 
513           if (fifo_state->using_bounce_buffer) {
514                     if (reserveable)
515                               vmw_fifo_res_copy(fifo_state, fifo_mem,
516                                                     next_cmd, max, min, bytes);
517                     else
518                               vmw_fifo_slow_copy(fifo_state, fifo_mem,
519                                                      next_cmd, max, min, bytes);
520 
521                     if (fifo_state->dynamic_buffer) {
522                               vfree(fifo_state->dynamic_buffer);
523                               fifo_state->dynamic_buffer = NULL;
524                     }
525 
526           }
527 
528           down_write(&fifo_state->rwsem);
529           if (fifo_state->using_bounce_buffer || reserveable) {
530                     next_cmd += bytes;
531                     if (next_cmd >= max)
532                               next_cmd -= max - min;
533                     mb();
534                     vmw_mmio_write(next_cmd, fifo_mem + SVGA_FIFO_NEXT_CMD);
535           }
536 
537           if (reserveable)
538                     vmw_mmio_write(0, fifo_mem + SVGA_FIFO_RESERVED);
539           mb();
540           up_write(&fifo_state->rwsem);
541           vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
542           mutex_unlock(&fifo_state->fifo_mutex);
543 }
544 
vmw_fifo_commit(struct vmw_private * dev_priv,uint32_t bytes)545 void vmw_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes)
546 {
547           if (dev_priv->cman)
548                     vmw_cmdbuf_commit(dev_priv->cman, bytes, NULL, false);
549           else
550                     vmw_local_fifo_commit(dev_priv, bytes);
551 }
552 
553 
554 /**
555  * vmw_fifo_commit_flush - Commit fifo space and flush any buffered commands.
556  *
557  * @dev_priv: Pointer to device private structure.
558  * @bytes: Number of bytes to commit.
559  */
vmw_fifo_commit_flush(struct vmw_private * dev_priv,uint32_t bytes)560 void vmw_fifo_commit_flush(struct vmw_private *dev_priv, uint32_t bytes)
561 {
562           if (dev_priv->cman)
563                     vmw_cmdbuf_commit(dev_priv->cman, bytes, NULL, true);
564           else
565                     vmw_local_fifo_commit(dev_priv, bytes);
566 }
567 
568 /**
569  * vmw_fifo_flush - Flush any buffered commands and make sure command processing
570  * starts.
571  *
572  * @dev_priv: Pointer to device private structure.
573  * @interruptible: Whether to wait interruptible if function needs to sleep.
574  */
vmw_fifo_flush(struct vmw_private * dev_priv,bool interruptible)575 int vmw_fifo_flush(struct vmw_private *dev_priv, bool interruptible)
576 {
577           might_sleep();
578 
579           if (dev_priv->cman)
580                     return vmw_cmdbuf_cur_flush(dev_priv->cman, interruptible);
581           else
582                     return 0;
583 }
584 
vmw_fifo_send_fence(struct vmw_private * dev_priv,uint32_t * seqno)585 int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *seqno)
586 {
587           struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
588           struct svga_fifo_cmd_fence *cmd_fence;
589           u32 *fm;
590           int ret = 0;
591           uint32_t bytes = sizeof(u32) + sizeof(*cmd_fence);
592 
593           fm = VMW_FIFO_RESERVE(dev_priv, bytes);
594           if (unlikely(fm == NULL)) {
595                     *seqno = atomic_read(&dev_priv->marker_seq);
596                     ret = -ENOMEM;
597                     (void)vmw_fallback_wait(dev_priv, false, true, *seqno,
598                                                   false, 3*HZ);
599                     goto out_err;
600           }
601 
602           do {
603                     *seqno = atomic_add_return(1, &dev_priv->marker_seq);
604           } while (*seqno == 0);
605 
606           if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE)) {
607 
608                     /*
609                      * Don't request hardware to send a fence. The
610                      * waiting code in vmwgfx_irq.c will emulate this.
611                      */
612 
613                     vmw_fifo_commit(dev_priv, 0);
614                     return 0;
615           }
616 
617           *fm++ = SVGA_CMD_FENCE;
618           cmd_fence = (struct svga_fifo_cmd_fence *) fm;
619           cmd_fence->fence = *seqno;
620           vmw_fifo_commit_flush(dev_priv, bytes);
621           (void) vmw_marker_push(&fifo_state->marker_queue, *seqno);
622           spin_lock(&dev_priv->fence_lock);
623           vmw_update_seqno(dev_priv, fifo_state);
624           spin_unlock(&dev_priv->fence_lock);
625 
626 out_err:
627           return ret;
628 }
629 
630 /**
631  * vmw_fifo_emit_dummy_legacy_query - emits a dummy query to the fifo using
632  * legacy query commands.
633  *
634  * @dev_priv: The device private structure.
635  * @cid: The hardware context id used for the query.
636  *
637  * See the vmw_fifo_emit_dummy_query documentation.
638  */
vmw_fifo_emit_dummy_legacy_query(struct vmw_private * dev_priv,uint32_t cid)639 static int vmw_fifo_emit_dummy_legacy_query(struct vmw_private *dev_priv,
640                                                       uint32_t cid)
641 {
642           /*
643            * A query wait without a preceding query end will
644            * actually finish all queries for this cid
645            * without writing to the query result structure.
646            */
647 
648           struct ttm_buffer_object *bo = &dev_priv->dummy_query_bo->base;
649           struct {
650                     SVGA3dCmdHeader header;
651                     SVGA3dCmdWaitForQuery body;
652           } *cmd;
653 
654           cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
655           if (unlikely(cmd == NULL))
656                     return -ENOMEM;
657 
658           cmd->header.id = SVGA_3D_CMD_WAIT_FOR_QUERY;
659           cmd->header.size = sizeof(cmd->body);
660           cmd->body.cid = cid;
661           cmd->body.type = SVGA3D_QUERYTYPE_OCCLUSION;
662 
663           if (bo->mem.mem_type == TTM_PL_VRAM) {
664                     cmd->body.guestResult.gmrId = SVGA_GMR_FRAMEBUFFER;
665                     cmd->body.guestResult.offset = bo->offset;
666           } else {
667                     cmd->body.guestResult.gmrId = bo->mem.start;
668                     cmd->body.guestResult.offset = 0;
669           }
670 
671           vmw_fifo_commit(dev_priv, sizeof(*cmd));
672 
673           return 0;
674 }
675 
676 /**
677  * vmw_fifo_emit_dummy_gb_query - emits a dummy query to the fifo using
678  * guest-backed resource query commands.
679  *
680  * @dev_priv: The device private structure.
681  * @cid: The hardware context id used for the query.
682  *
683  * See the vmw_fifo_emit_dummy_query documentation.
684  */
vmw_fifo_emit_dummy_gb_query(struct vmw_private * dev_priv,uint32_t cid)685 static int vmw_fifo_emit_dummy_gb_query(struct vmw_private *dev_priv,
686                                                   uint32_t cid)
687 {
688           /*
689            * A query wait without a preceding query end will
690            * actually finish all queries for this cid
691            * without writing to the query result structure.
692            */
693 
694           struct ttm_buffer_object *bo = &dev_priv->dummy_query_bo->base;
695           struct {
696                     SVGA3dCmdHeader header;
697                     SVGA3dCmdWaitForGBQuery body;
698           } *cmd;
699 
700           cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
701           if (unlikely(cmd == NULL))
702                     return -ENOMEM;
703 
704           cmd->header.id = SVGA_3D_CMD_WAIT_FOR_GB_QUERY;
705           cmd->header.size = sizeof(cmd->body);
706           cmd->body.cid = cid;
707           cmd->body.type = SVGA3D_QUERYTYPE_OCCLUSION;
708           BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
709           cmd->body.mobid = bo->mem.start;
710           cmd->body.offset = 0;
711 
712           vmw_fifo_commit(dev_priv, sizeof(*cmd));
713 
714           return 0;
715 }
716 
717 
718 /**
719  * vmw_fifo_emit_dummy_gb_query - emits a dummy query to the fifo using
720  * appropriate resource query commands.
721  *
722  * @dev_priv: The device private structure.
723  * @cid: The hardware context id used for the query.
724  *
725  * This function is used to emit a dummy occlusion query with
726  * no primitives rendered between query begin and query end.
727  * It's used to provide a query barrier, in order to know that when
728  * this query is finished, all preceding queries are also finished.
729  *
730  * A Query results structure should have been initialized at the start
731  * of the dev_priv->dummy_query_bo buffer object. And that buffer object
732  * must also be either reserved or pinned when this function is called.
733  *
734  * Returns -ENOMEM on failure to reserve fifo space.
735  */
vmw_fifo_emit_dummy_query(struct vmw_private * dev_priv,uint32_t cid)736 int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv,
737                                     uint32_t cid)
738 {
739           if (dev_priv->has_mob)
740                     return vmw_fifo_emit_dummy_gb_query(dev_priv, cid);
741 
742           return vmw_fifo_emit_dummy_legacy_query(dev_priv, cid);
743 }
744