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