Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.17-rc4 218 lines 5.6 kB view raw
1/* i915_irq.c -- IRQ support for the I915 -*- linux-c -*- 2 */ 3/* 4 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 */ 28 29#include "drmP.h" 30#include "drm.h" 31#include "i915_drm.h" 32#include "i915_drv.h" 33 34#define USER_INT_FLAG (1<<1) 35#define VSYNC_PIPEB_FLAG (1<<5) 36#define VSYNC_PIPEA_FLAG (1<<7) 37 38#define MAX_NOPID ((u32)~0) 39 40irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) 41{ 42 drm_device_t *dev = (drm_device_t *) arg; 43 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 44 u16 temp; 45 46 temp = I915_READ16(I915REG_INT_IDENTITY_R); 47 temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG); 48 49 DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); 50 51 if (temp == 0) 52 return IRQ_NONE; 53 54 I915_WRITE16(I915REG_INT_IDENTITY_R, temp); 55 56 dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); 57 58 if (temp & USER_INT_FLAG) 59 DRM_WAKEUP(&dev_priv->irq_queue); 60 61 if (temp & VSYNC_PIPEA_FLAG) { 62 atomic_inc(&dev->vbl_received); 63 DRM_WAKEUP(&dev->vbl_queue); 64 drm_vbl_send_signals(dev); 65 } 66 67 return IRQ_HANDLED; 68} 69 70static int i915_emit_irq(drm_device_t * dev) 71{ 72 drm_i915_private_t *dev_priv = dev->dev_private; 73 u32 ret; 74 RING_LOCALS; 75 76 i915_kernel_lost_context(dev); 77 78 DRM_DEBUG("%s\n", __FUNCTION__); 79 80 ret = dev_priv->counter; 81 82 BEGIN_LP_RING(2); 83 OUT_RING(0); 84 OUT_RING(GFX_OP_USER_INTERRUPT); 85 ADVANCE_LP_RING(); 86 87 return ret; 88} 89 90static int i915_wait_irq(drm_device_t * dev, int irq_nr) 91{ 92 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 93 int ret = 0; 94 95 DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr, 96 READ_BREADCRUMB(dev_priv)); 97 98 if (READ_BREADCRUMB(dev_priv) >= irq_nr) 99 return 0; 100 101 dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 102 103 DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ, 104 READ_BREADCRUMB(dev_priv) >= irq_nr); 105 106 if (ret == DRM_ERR(EBUSY)) { 107 DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n", 108 __FUNCTION__, 109 READ_BREADCRUMB(dev_priv), (int)dev_priv->counter); 110 } 111 112 dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); 113 return ret; 114} 115 116int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) 117{ 118 drm_i915_private_t *dev_priv = dev->dev_private; 119 unsigned int cur_vblank; 120 int ret = 0; 121 122 if (!dev_priv) { 123 DRM_ERROR("%s called with no initialization\n", __FUNCTION__); 124 return DRM_ERR(EINVAL); 125 } 126 127 DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, 128 (((cur_vblank = atomic_read(&dev->vbl_received)) 129 - *sequence) <= (1<<23))); 130 131 *sequence = cur_vblank; 132 133 return ret; 134} 135 136 137/* Needs the lock as it touches the ring. 138 */ 139int i915_irq_emit(DRM_IOCTL_ARGS) 140{ 141 DRM_DEVICE; 142 drm_i915_private_t *dev_priv = dev->dev_private; 143 drm_i915_irq_emit_t emit; 144 int result; 145 146 LOCK_TEST_WITH_RETURN(dev, filp); 147 148 if (!dev_priv) { 149 DRM_ERROR("%s called with no initialization\n", __FUNCTION__); 150 return DRM_ERR(EINVAL); 151 } 152 153 DRM_COPY_FROM_USER_IOCTL(emit, (drm_i915_irq_emit_t __user *) data, 154 sizeof(emit)); 155 156 result = i915_emit_irq(dev); 157 158 if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) { 159 DRM_ERROR("copy_to_user\n"); 160 return DRM_ERR(EFAULT); 161 } 162 163 return 0; 164} 165 166/* Doesn't need the hardware lock. 167 */ 168int i915_irq_wait(DRM_IOCTL_ARGS) 169{ 170 DRM_DEVICE; 171 drm_i915_private_t *dev_priv = dev->dev_private; 172 drm_i915_irq_wait_t irqwait; 173 174 if (!dev_priv) { 175 DRM_ERROR("%s called with no initialization\n", __FUNCTION__); 176 return DRM_ERR(EINVAL); 177 } 178 179 DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_i915_irq_wait_t __user *) data, 180 sizeof(irqwait)); 181 182 return i915_wait_irq(dev, irqwait.irq_seq); 183} 184 185/* drm_dma.h hooks 186*/ 187void i915_driver_irq_preinstall(drm_device_t * dev) 188{ 189 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 190 191 I915_WRITE16(I915REG_HWSTAM, 0xfffe); 192 I915_WRITE16(I915REG_INT_MASK_R, 0x0); 193 I915_WRITE16(I915REG_INT_ENABLE_R, 0x0); 194} 195 196void i915_driver_irq_postinstall(drm_device_t * dev) 197{ 198 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 199 200 I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | VSYNC_PIPEA_FLAG); 201 DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); 202} 203 204void i915_driver_irq_uninstall(drm_device_t * dev) 205{ 206 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 207 u16 temp; 208 209 if (!dev_priv) 210 return; 211 212 I915_WRITE16(I915REG_HWSTAM, 0xffff); 213 I915_WRITE16(I915REG_INT_MASK_R, 0xffff); 214 I915_WRITE16(I915REG_INT_ENABLE_R, 0x0); 215 216 temp = I915_READ16(I915REG_INT_IDENTITY_R); 217 I915_WRITE16(I915REG_INT_IDENTITY_R, temp); 218}