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 "drmP.h" 29fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#include "vmwgfx_drv.h" 30fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 31fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#define VMW_FENCE_WRAP (1 << 24) 32fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 33fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzirqreturn_t vmw_irq_handler(DRM_IRQ_ARGS) 34fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 35fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_device *dev = (struct drm_device *)arg; 36fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 3757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom uint32_t status, masked_status; 38fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 39fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz spin_lock(&dev_priv->irq_lock); 40fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); 4157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom masked_status = status & dev_priv->irq_mask; 42fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz spin_unlock(&dev_priv->irq_lock); 43fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 4457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (likely(status)) 4557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); 46ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 4757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (!masked_status) 4857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom return IRQ_NONE; 4957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 5057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (masked_status & (SVGA_IRQFLAG_ANY_FENCE | 5157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom SVGA_IRQFLAG_FENCE_GOAL)) { 5257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom vmw_fences_update(dev_priv->fman); 53fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz wake_up_all(&dev_priv->fence_queue); 54ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom } 5557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 5657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (masked_status & SVGA_IRQFLAG_FIFO_PROGRESS) 57fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz wake_up_all(&dev_priv->fifo_queue); 58fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 59fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 6057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom return IRQ_HANDLED; 61fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 62fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 636bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstromstatic bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t seqno) 64fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 65fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t busy; 66fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 67fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz mutex_lock(&dev_priv->hw_mutex); 68fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz busy = vmw_read(dev_priv, SVGA_REG_BUSY); 69fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz mutex_unlock(&dev_priv->hw_mutex); 70fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 71fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return (busy == 0); 72fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 73fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 746bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstromvoid vmw_update_seqno(struct vmw_private *dev_priv, 751925d4565888eb313cc923372da6a08bbfb3a859Thomas Hellstrom struct vmw_fifo_state *fifo_state) 761925d4565888eb313cc923372da6a08bbfb3a859Thomas Hellstrom{ 771925d4565888eb313cc923372da6a08bbfb3a859Thomas Hellstrom __le32 __iomem *fifo_mem = dev_priv->mmio_virt; 786bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom uint32_t seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE); 791925d4565888eb313cc923372da6a08bbfb3a859Thomas Hellstrom 806bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom if (dev_priv->last_read_seqno != seqno) { 816bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom dev_priv->last_read_seqno = seqno; 826bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom vmw_marker_pull(&fifo_state->marker_queue, seqno); 8357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom vmw_fences_update(dev_priv->fman); 841925d4565888eb313cc923372da6a08bbfb3a859Thomas Hellstrom } 851925d4565888eb313cc923372da6a08bbfb3a859Thomas Hellstrom} 86fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 876bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrombool vmw_seqno_passed(struct vmw_private *dev_priv, 886bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom uint32_t seqno) 89fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 90fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_fifo_state *fifo_state; 91fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz bool ret; 92fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 936bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP)) 94fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return true; 95fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 961925d4565888eb313cc923372da6a08bbfb3a859Thomas Hellstrom fifo_state = &dev_priv->fifo; 976bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom vmw_update_seqno(dev_priv, fifo_state); 986bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP)) 99fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return true; 100fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 101fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE) && 1026bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom vmw_fifo_idle(dev_priv, seqno)) 103fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return true; 104fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 105fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz /** 1066bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom * Then check if the seqno is higher than what we've actually 107fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * emitted. Then the fence is stale and signaled. 108fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 109fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1106bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom ret = ((atomic_read(&dev_priv->marker_seq) - seqno) 11185b9e4878f3b16993fba871c0c68d0948ec9c7c6Thomas Hellstrom > VMW_FENCE_WRAP); 112fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 113fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 114fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 115fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 116fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_fallback_wait(struct vmw_private *dev_priv, 117fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz bool lazy, 118fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz bool fifo_idle, 1196bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom uint32_t seqno, 120fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz bool interruptible, 121fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz unsigned long timeout) 122fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 123fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_fifo_state *fifo_state = &dev_priv->fifo; 124fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 125fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t count = 0; 126fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t signal_seq; 127fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 128fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz unsigned long end_jiffies = jiffies + timeout; 129fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz bool (*wait_condition)(struct vmw_private *, uint32_t); 130fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DEFINE_WAIT(__wait); 131fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 132fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz wait_condition = (fifo_idle) ? &vmw_fifo_idle : 1336bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom &vmw_seqno_passed; 134fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 135fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz /** 136fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Block command submission while waiting for idle. 137fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 138fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 139fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (fifo_idle) 140fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz down_read(&fifo_state->rwsem); 1416bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom signal_seq = atomic_read(&dev_priv->marker_seq); 142fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = 0; 143fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 144fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz for (;;) { 145fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz prepare_to_wait(&dev_priv->fence_queue, &__wait, 146fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (interruptible) ? 147fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); 1486bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom if (wait_condition(dev_priv, seqno)) 149fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz break; 150fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (time_after_eq(jiffies, end_jiffies)) { 151fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("SVGA device lockup.\n"); 152fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz break; 153fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 154fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (lazy) 155fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz schedule_timeout(1); 156fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz else if ((++count & 0x0F) == 0) { 157fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz /** 158fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * FIXME: Use schedule_hr_timeout here for 159fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * newer kernels and lower CPU utilization. 160fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 161fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 162fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz __set_current_state(TASK_RUNNING); 163fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz schedule(); 164fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz __set_current_state((interruptible) ? 165fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz TASK_INTERRUPTIBLE : 166fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz TASK_UNINTERRUPTIBLE); 167fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 168fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (interruptible && signal_pending(current)) { 1693d3a5b3290043618e8409f3fb68a63de6156fdd4Thomas Hellstrom ret = -ERESTARTSYS; 170fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz break; 171fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 172fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 173fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz finish_wait(&dev_priv->fence_queue, &__wait); 174fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (ret == 0 && fifo_idle) { 175fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz __le32 __iomem *fifo_mem = dev_priv->mmio_virt; 176fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz iowrite32(signal_seq, fifo_mem + SVGA_FIFO_FENCE); 177fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 178fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz wake_up_all(&dev_priv->fence_queue); 179fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (fifo_idle) 180fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz up_read(&fifo_state->rwsem); 181fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 182fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 183fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 184fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 185ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromvoid vmw_seqno_waiter_add(struct vmw_private *dev_priv) 1864f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom{ 1874f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom mutex_lock(&dev_priv->hw_mutex); 1884f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom if (dev_priv->fence_queue_waiters++ == 0) { 1894f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom unsigned long irq_flags; 1904f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom 1914f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); 1924f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom outl(SVGA_IRQFLAG_ANY_FENCE, 1934f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); 19457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom dev_priv->irq_mask |= SVGA_IRQFLAG_ANY_FENCE; 19557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); 1964f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); 1974f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom } 1984f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom mutex_unlock(&dev_priv->hw_mutex); 1994f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom} 2004f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom 201ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromvoid vmw_seqno_waiter_remove(struct vmw_private *dev_priv) 2024f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom{ 2034f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom mutex_lock(&dev_priv->hw_mutex); 2044f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom if (--dev_priv->fence_queue_waiters == 0) { 2054f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom unsigned long irq_flags; 2064f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom 2074f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); 20857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom dev_priv->irq_mask &= ~SVGA_IRQFLAG_ANY_FENCE; 20957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); 21057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); 21157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 21257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom mutex_unlock(&dev_priv->hw_mutex); 21357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom} 21457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 21557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 21657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstromvoid vmw_goal_waiter_add(struct vmw_private *dev_priv) 21757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom{ 21857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom mutex_lock(&dev_priv->hw_mutex); 21957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (dev_priv->goal_queue_waiters++ == 0) { 22057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom unsigned long irq_flags; 22157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 22257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); 22357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom outl(SVGA_IRQFLAG_FENCE_GOAL, 22457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); 22557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom dev_priv->irq_mask |= SVGA_IRQFLAG_FENCE_GOAL; 22657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); 22757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); 22857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 22957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom mutex_unlock(&dev_priv->hw_mutex); 23057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom} 23157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 23257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstromvoid vmw_goal_waiter_remove(struct vmw_private *dev_priv) 23357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom{ 23457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom mutex_lock(&dev_priv->hw_mutex); 23557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (--dev_priv->goal_queue_waiters == 0) { 23657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom unsigned long irq_flags; 23757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 23857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); 23957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom dev_priv->irq_mask &= ~SVGA_IRQFLAG_FENCE_GOAL; 24057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); 2414f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); 2424f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom } 2434f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom mutex_unlock(&dev_priv->hw_mutex); 2444f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom} 2454f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom 2466bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstromint vmw_wait_seqno(struct vmw_private *dev_priv, 2476bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom bool lazy, uint32_t seqno, 2486bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom bool interruptible, unsigned long timeout) 249fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 250fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz long ret; 251fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_fifo_state *fifo = &dev_priv->fifo; 252fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 2536bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP)) 254fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 255fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 2566bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom if (likely(vmw_seqno_passed(dev_priv, seqno))) 257fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 258fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 259fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC); 260fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 261fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (!(fifo->capabilities & SVGA_FIFO_CAP_FENCE)) 2626bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom return vmw_fallback_wait(dev_priv, lazy, true, seqno, 263fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz interruptible, timeout); 264fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 265fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK)) 2666bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom return vmw_fallback_wait(dev_priv, lazy, false, seqno, 267fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz interruptible, timeout); 268fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 2694f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom vmw_seqno_waiter_add(dev_priv); 270fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 271fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (interruptible) 272fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = wait_event_interruptible_timeout 273fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (dev_priv->fence_queue, 2746bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom vmw_seqno_passed(dev_priv, seqno), 275fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz timeout); 276fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz else 277fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = wait_event_timeout 278fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (dev_priv->fence_queue, 2796bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom vmw_seqno_passed(dev_priv, seqno), 280fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz timeout); 281fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 2824f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom vmw_seqno_waiter_remove(dev_priv); 2834f73a96bd76914009682432842ac04a32ab9115bThomas Hellstrom 2843d3a5b3290043618e8409f3fb68a63de6156fdd4Thomas Hellstrom if (unlikely(ret == 0)) 285fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EBUSY; 286fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz else if (likely(ret > 0)) 287fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = 0; 288fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 289fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 290fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 291fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 292fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_irq_preinstall(struct drm_device *dev) 293fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 294fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 295fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t status; 296fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 297fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK)) 298fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return; 299fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 300fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz spin_lock_init(&dev_priv->irq_lock); 301fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); 302fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); 303fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 304fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 305fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_irq_postinstall(struct drm_device *dev) 306fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 307fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 308fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 309fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 310fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_irq_uninstall(struct drm_device *dev) 311fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 312fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 313fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t status; 314fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 315fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK)) 316fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return; 317fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 318fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz mutex_lock(&dev_priv->hw_mutex); 319fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_write(dev_priv, SVGA_REG_IRQMASK, 0); 320fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz mutex_unlock(&dev_priv->hw_mutex); 321fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 322fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); 323fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); 324fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 325