From: <jb...@ke...> - 2008-01-23 02:24:55
|
linux-core/drmP.h | 91 +++++++++-- linux-core/drm_drv.c | 4 linux-core/drm_irq.c | 356 ++++++++++++++++++++++++++++++++++++++-------- linux-core/i915_drv.c | 8 - linux-core/mach64_drv.c | 6 linux-core/mga_drv.c | 7 linux-core/r128_drv.c | 7 linux-core/radeon_drv.c | 8 - shared-core/drm.h | 17 ++ shared-core/i915_drv.h | 49 +++++- shared-core/i915_irq.c | 252 +++++++++++++++++++++++--------- shared-core/mach64_drv.h | 13 + shared-core/mach64_irq.c | 88 ++++++----- shared-core/mga_drv.h | 10 - shared-core/mga_irq.c | 69 ++++++-- shared-core/nouveau_drv.h | 2 shared-core/nouveau_irq.c | 4 shared-core/r128_drv.h | 9 - shared-core/r128_irq.c | 55 ++++--- shared-core/radeon_drv.h | 19 +- shared-core/radeon_irq.c | 171 ++++++++++------------ shared-core/via_drv.c | 6 shared-core/via_drv.h | 7 shared-core/via_irq.c | 71 ++++----- 24 files changed, 933 insertions(+), 396 deletions(-) New commits: commit 531f25cfe9d0319f78fe58260bfed08d5e3e8bcc Author: Jesse Barnes <jb...@ni...> Date: Tue Jan 22 15:16:01 2008 -0800 Correct vblank count value The frame count registers don't increment until the start of the next frame, so make sure we return an incremented count if called during the actual vblank period. diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index b8d027d..2c1f2c2 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -471,6 +471,9 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define I915REG_INT_ENABLE_R 0x020a0 #define I915REG_INSTPM 0x020c0 +#define PIPEADSL 0x70000 +#define PIPEBDSL 0x71000 + #define I915REG_PIPEASTAT 0x70024 #define I915REG_PIPEBSTAT 0x71024 /* @@ -790,6 +793,9 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define BCLRPAT_B 0x61020 #define VSYNCSHIFT_B 0x61028 +#define HACTIVE_MASK 0x00000fff +#define VBLANK_START_MASK 0x00001fff + #define PP_STATUS 0x61200 # define PP_ON (1 << 31) /** diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index bef73b6..7ad21a9 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -69,8 +69,6 @@ i915_get_pipe(struct drm_device *dev, int plane) static int i915_get_plane(struct drm_device *dev, int pipe) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - if (i915_get_pipe(dev, 0) == pipe) return 0; return 1; @@ -349,12 +347,16 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long high_frame; unsigned long low_frame; + unsigned long pipedsl, vblank, htotal; u32 high1, high2, low, count; int pipe; pipe = i915_get_pipe(dev, plane); high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH; low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; + pipedsl = pipe ? PIPEBDSL : PIPEADSL; + vblank = pipe ? VBLANK_B : VBLANK_A; + htotal = pipe ? HTOTAL_B : HTOTAL_A; if (!i915_pipe_enabled(dev, pipe)) { printk(KERN_ERR "trying to get vblank count for disabled " @@ -378,6 +380,15 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane) count = (high1 << 8) | low; + /* + * If we're in the middle of the vblank period, the + * above regs won't have been updated yet, so return + * an incremented count to stay accurate + */ + if ((I915_READ(pipedsl) >= (I915_READ(vblank) & VBLANK_START_MASK)) || + (I915_READ(pipedsl) < (I915_READ(htotal) & HACTIVE_MASK))) + count++; + return count; } commit 893e311999d1565943899d73c56c674fc9b6e502 Author: Jesse Barnes <jb...@ni...> Date: Tue Jan 22 13:11:29 2008 -0800 i915 irq fixes Ack the IRQs correctly (PIPExSTAT first followed by IIR). Don't read vblank counter registers on disabled pipes (might hang otherwise). And deal with flipped pipe/plane mappings if present. diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 9b46b12..bef73b6 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -42,9 +42,9 @@ * @dev: DRM device * @plane: plane to look for * - * We need to get the pipe associated with a given plane to correctly perform - * vblank driven swapping, and they may not always be equal. So look up the - * pipe associated with @plane here. + * The Intel Mesa & 2D drivers call the vblank routines with a plane number + * rather than a pipe number, since they may not always be equal. This routine + * maps the given @plane back to a pipe number. */ static int i915_get_pipe(struct drm_device *dev, int plane) @@ -58,6 +58,46 @@ i915_get_pipe(struct drm_device *dev, int plane) } /** + * i915_get_plane - return the the plane associated with a given pipe + * @dev: DRM device + * @pipe: pipe to look for + * + * The Intel Mesa & 2D drivers call the vblank routines with a plane number + * rather than a plane number, since they may not always be equal. This routine + * maps the given @pipe back to a plane number. + */ +static int +i915_get_plane(struct drm_device *dev, int pipe) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + + if (i915_get_pipe(dev, 0) == pipe) + return 0; + return 1; +} + +/** + * i915_pipe_enabled - check if a pipe is enabled + * @dev: DRM device + * @pipe: pipe to check + * + * Reading certain registers when the pipe is disabled can hang the chip. + * Use this routine to make sure the PLL is running and the pipe is active + * before reading such registers if unsure. + */ +static int +i915_pipe_enabled(struct drm_device *dev, int pipe) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF; + + if (I915_READ(pipeconf) & PIPEACONF_ENABLE) + return 1; + + return 0; +} + +/** * Emit a synchronous flip. * * This function must be called with the drawable spinlock held. @@ -146,14 +186,14 @@ static void i915_vblank_tasklet(struct drm_device *dev) list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) { drm_i915_vbl_swap_t *vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); - int crtc = i915_get_pipe(dev, vbl_swap->plane); + int pipe = i915_get_pipe(dev, vbl_swap->plane); - if ((counter[crtc] - vbl_swap->sequence) > (1<<23)) + if ((counter[pipe] - vbl_swap->sequence) > (1<<23)) continue; list_del(list); dev_priv->swaps_pending--; - drm_vblank_put(dev, crtc); + drm_vblank_put(dev, pipe); DRM_SPINUNLOCK(&dev_priv->swaps_lock); DRM_SPINLOCK(&dev->drw_lock); @@ -304,12 +344,23 @@ static void i915_vblank_tasklet(struct drm_device *dev) } } -u32 i915_get_vblank_counter(struct drm_device *dev, int crtc) +u32 i915_get_vblank_counter(struct drm_device *dev, int plane) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - unsigned long high_frame = crtc ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH; - unsigned long low_frame = crtc ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; + unsigned long high_frame; + unsigned long low_frame; u32 high1, high2, low, count; + int pipe; + + pipe = i915_get_pipe(dev, plane); + high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH; + low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; + + if (!i915_pipe_enabled(dev, pipe)) { + printk(KERN_ERR "trying to get vblank count for disabled " + "pipe %d\n", pipe); + return 0; + } /* * High & low register fields aren't synchronized, so make sure @@ -348,6 +399,23 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) if (temp == 0) return IRQ_NONE; + /* + * Clear the PIPE(A|B)STAT regs before the IIR otherwise + * we may get extra interrupts. + */ + if (temp & VSYNC_PIPEA_FLAG) { + drm_handle_vblank(dev, i915_get_plane(dev, 0)); + I915_WRITE(I915REG_PIPEASTAT, + pipea_stats | I915_VBLANK_INTERRUPT_ENABLE | + I915_VBLANK_CLEAR); + } + if (temp & VSYNC_PIPEB_FLAG) { + drm_handle_vblank(dev, i915_get_plane(dev, 1)); + I915_WRITE(I915REG_PIPEBSTAT, + pipeb_stats | I915_VBLANK_INTERRUPT_ENABLE | + I915_VBLANK_CLEAR); + } + I915_WRITE16(I915REG_INT_IDENTITY_R, temp); (void) I915_READ16(I915REG_INT_IDENTITY_R); /* Flush posted write */ @@ -363,24 +431,9 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) #endif } - /* - * Use drm_update_vblank_counter here to deal with potential lost - * interrupts - */ - if (temp & VSYNC_PIPEA_FLAG) - drm_handle_vblank(dev, 0); - if (temp & VSYNC_PIPEB_FLAG) - drm_handle_vblank(dev, 1); - if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { if (dev_priv->swaps_pending > 0) drm_locked_tasklet(dev, i915_vblank_tasklet); - I915_WRITE(I915REG_PIPEASTAT, - pipea_stats|I915_VBLANK_INTERRUPT_ENABLE| - I915_VBLANK_CLEAR); - I915_WRITE(I915REG_PIPEBSTAT, - pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE| - I915_VBLANK_CLEAR); } return IRQ_HANDLED; @@ -494,11 +547,12 @@ int i915_irq_wait(struct drm_device *dev, void *data, return i915_wait_irq(dev, irqwait->irq_seq); } -int i915_enable_vblank(struct drm_device *dev, int crtc) +int i915_enable_vblank(struct drm_device *dev, int plane) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + int pipe = i915_get_pipe(dev, plane); - switch (crtc) { + switch (pipe) { case 0: dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG; break; @@ -506,8 +560,8 @@ int i915_enable_vblank(struct drm_device *dev, int crtc) dev_priv->irq_enable_reg |= VSYNC_PIPEB_FLAG; break; default: - DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", - crtc); + DRM_ERROR("tried to enable vblank on non-existent pipe %d\n", + pipe); break; } @@ -516,11 +570,12 @@ int i915_enable_vblank(struct drm_device *dev, int crtc) return 0; } -void i915_disable_vblank(struct drm_device *dev, int crtc) +void i915_disable_vblank(struct drm_device *dev, int plane) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + int pipe = i915_get_pipe(dev, plane); - switch (crtc) { + switch (pipe) { case 0: dev_priv->irq_enable_reg &= ~VSYNC_PIPEA_FLAG; break; @@ -528,8 +583,8 @@ void i915_disable_vblank(struct drm_device *dev, int crtc) dev_priv->irq_enable_reg &= ~VSYNC_PIPEB_FLAG; break; default: - DRM_ERROR("tried to disable vblank on non-existent crtc %d\n", - crtc); + DRM_ERROR("tried to disable vblank on non-existent pipe %d\n", + pipe); break; } commit 0cd4cbc9a6330bd619608f274592082de7c05bcf Merge: 128a8f7... 5231a52... Author: Jesse Barnes <jb...@ho...> Date: Tue Jan 22 09:42:37 2008 -0800 Merge branch 'master' into vblank-rework, including mach64 support Conflicts: linux-core/drmP.h linux-core/drm_drv.c shared-core/i915_drv.h shared-core/i915_irq.c shared-core/mga_irq.c shared-core/radeon_irq.c shared-core/via_irq.c Mostly trivial conflicts. mach64 support from Mathieu Bérard. diff --cc linux-core/drmP.h index 332ee1c,dbf2a92..4e8b087 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@@ -631,56 -624,14 +622,56 @@@ struct drm_driver int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv); void (*dma_ready) (struct drm_device *); int (*dma_quiescent) (struct drm_device *); - int (*context_ctor) (struct drm_device * dev, int context); - int (*context_dtor) (struct drm_device * dev, int context); - int (*kernel_context_switch) (struct drm_device * dev, int old, + int (*context_ctor) (struct drm_device *dev, int context); + int (*context_dtor) (struct drm_device *dev, int context); + int (*kernel_context_switch) (struct drm_device *dev, int old, int new); - void (*kernel_context_switch_unlock) (struct drm_device *dev); - int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence); - int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence); + void (*kernel_context_switch_unlock) (struct drm_device * dev); + /** + * get_vblank_counter - get raw hardware vblank counter + * @dev: DRM device + * @crtc: counter to fetch + * + * Driver callback for fetching a raw hardware vblank counter + * for @crtc. If a device doesn't have a hardware counter, the + * driver can simply return the value of drm_vblank_count and + * make the enable_vblank() and disable_vblank() hooks into no-ops, + * leaving interrupts enabled at all times. + * + * Wraparound handling and loss of events due to modesetting is dealt + * with in the DRM core code. + * + * RETURNS + * Raw vblank counter value. + */ + u32 (*get_vblank_counter) (struct drm_device *dev, int crtc); + + /** + * enable_vblank - enable vblank interrupt events + * @dev: DRM device + * @crtc: which irq to enable + * + * Enable vblank interrupts for @crtc. If the device doesn't have + * a hardware vblank counter, this routine should be a no-op, since + * interrupts will have to stay on to keep the count accurate. + * + * RETURNS + * Zero on success, appropriate errno if the given @crtc's vblank + * interrupt cannot be enabled. + */ + int (*enable_vblank) (struct drm_device *dev, int crtc); + + /** + * disable_vblank - disable vblank interrupt events + * @dev: DRM device + * @crtc: which irq to enable + * + * Disable vblank interrupts for @crtc. If the device doesn't have + * a hardware vblank counter, this routine should be a no-op, since + * interrupts will have to stay on to keep the count accurate. + */ + void (*disable_vblank) (struct drm_device *dev, int crtc); - int (*dri_library_name) (struct drm_device * dev, char * buf); + int (*dri_library_name) (struct drm_device *dev, char * buf); /** * Called by \c drm_device_is_agp. Typically used to determine if a @@@ -697,9 -648,9 +688,9 @@@ /* these have to be filled in */ irqreturn_t(*irq_handler) (DRM_IRQ_ARGS); - void (*irq_preinstall) (struct drm_device * dev); - int (*irq_postinstall) (struct drm_device * dev); - void (*irq_uninstall) (struct drm_device * dev); + void (*irq_preinstall) (struct drm_device *dev); - void (*irq_postinstall) (struct drm_device *dev); ++ int (*irq_postinstall) (struct drm_device *dev); + void (*irq_uninstall) (struct drm_device *dev); void (*reclaim_buffers) (struct drm_device *dev, struct drm_file *file_priv); void (*reclaim_buffers_locked) (struct drm_device *dev, diff --cc linux-core/drm_drv.c index 296a326,343d5f3..3c2794d --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@@ -121,13 -122,14 +121,13 @@@ static struct drm_ioctl_desc drm_ioctls DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_MM_INIT, drm_mm_init_ioctl, - + DRM_IOCTL_DEF(DRM_IOCTL_MM_INIT, drm_mm_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_MM_TAKEDOWN, drm_mm_takedown_ioctl, + DRM_IOCTL_DEF(DRM_IOCTL_MM_TAKEDOWN, drm_mm_takedown_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_MM_LOCK, drm_mm_lock_ioctl, + DRM_IOCTL_DEF(DRM_IOCTL_MM_LOCK, drm_mm_lock_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_MM_UNLOCK, drm_mm_unlock_ioctl, + DRM_IOCTL_DEF(DRM_IOCTL_MM_UNLOCK, drm_mm_unlock_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_FENCE_CREATE, drm_fence_create_ioctl, DRM_AUTH), diff --cc linux-core/drm_irq.c index 4aa58d7,866878a..2a5a453 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@@ -188,8 -106,19 +188,8 @@@ int drm_irq_install(struct drm_device dev->irq_enabled = 1; mutex_unlock(&dev->struct_mutex); - DRM_DEBUG("%s: irq=%d\n", __FUNCTION__, dev->irq); + DRM_DEBUG("irq=%d\n", dev->irq); - if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) { - init_waitqueue_head(&dev->vbl_queue); - - spin_lock_init(&dev->vbl_lock); - - INIT_LIST_HEAD(&dev->vbl_sigs); - INIT_LIST_HEAD(&dev->vbl_sigs2); - - dev->vbl_pending = 0; - } - /* Before installing handler */ dev->driver->irq_preinstall(dev); diff --cc linux-core/mach64_drv.c index 9709934,9709934..16bc9ff --- a/linux-core/mach64_drv.c +++ b/linux-core/mach64_drv.c @@@ -42,9 -42,9 +42,11 @@@ static int probe(struct pci_dev *pdev, static struct drm_driver driver = { .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA -- | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, ++ | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, .lastclose = mach64_driver_lastclose, -- .vblank_wait = mach64_driver_vblank_wait, ++ .get_vblank_counter = mach64_get_vblank_counter, ++ .enable_vblank = mach64_enable_vblank, ++ .disable_vblank = mach64_disable_vblank, .irq_preinstall = mach64_driver_irq_preinstall, .irq_postinstall = mach64_driver_irq_postinstall, .irq_uninstall = mach64_driver_irq_uninstall, diff --cc shared-core/i915_irq.c index 46d0966,4a96800..9b46b12 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@@ -339,11 -310,12 +339,11 @@@ irqreturn_t i915_driver_irq_handler(DRM pipea_stats = I915_READ(I915REG_PIPEASTAT); pipeb_stats = I915_READ(I915REG_PIPEBSTAT); - + temp = I915_READ16(I915REG_INT_IDENTITY_R); - temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG); #if 0 - DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); + DRM_DEBUG("flag=%08x\n", temp); #endif if (temp == 0) return IRQ_NONE; @@@ -363,19 -333,28 +363,19 @@@ #endif } - if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { - int vblank_pipe = dev_priv->vblank_pipe; - - if ((vblank_pipe & - (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) - == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) { - if (temp & VSYNC_PIPEA_FLAG) - atomic_inc(&dev->vbl_received); - if (temp & VSYNC_PIPEB_FLAG) - atomic_inc(&dev->vbl_received2); - } else if (((temp & VSYNC_PIPEA_FLAG) && - (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) || - ((temp & VSYNC_PIPEB_FLAG) && - (vblank_pipe & DRM_I915_VBLANK_PIPE_B))) - atomic_inc(&dev->vbl_received); - - DRM_WAKEUP(&dev->vbl_queue); - drm_vbl_send_signals(dev); + /* + * Use drm_update_vblank_counter here to deal with potential lost + * interrupts + */ + if (temp & VSYNC_PIPEA_FLAG) + drm_handle_vblank(dev, 0); + if (temp & VSYNC_PIPEB_FLAG) + drm_handle_vblank(dev, 1); + if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { if (dev_priv->swaps_pending > 0) drm_locked_tasklet(dev, i915_vblank_tasklet); - I915_WRITE(I915REG_PIPEASTAT, + I915_WRITE(I915REG_PIPEASTAT, pipea_stats|I915_VBLANK_INTERRUPT_ENABLE| I915_VBLANK_CLEAR); I915_WRITE(I915REG_PIPEBSTAT, @@@ -458,9 -431,42 +452,10 @@@ static int i915_wait_irq(struct drm_dev return ret; } -static int i915_driver_vblank_do_wait(struct drm_device *dev, - unsigned int *sequence, - atomic_t *counter) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - unsigned int cur_vblank; - int ret = 0; - - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(counter)) - - *sequence) <= (1<<23))); - - *sequence = cur_vblank; - - return ret; -} - -int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence) -{ - return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received); -} - -int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence) -{ - return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2); -} - /* Needs the lock as it touches the ring. */ - int i915_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv) + int i915_irq_emit(struct drm_device *dev, void *data, + struct drm_file *file_priv) { drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_irq_emit_t *emit = data; @@@ -788,8 -741,7 +782,8 @@@ int i915_driver_irq_postinstall(struct * Initialize the hardware status page IRQ location. */ - I915_WRITE(I915REG_INSTPM, ( 1 << 5) | ( 1 << 21)); + I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21)); + return 0; } void i915_driver_irq_uninstall(struct drm_device * dev) diff --cc shared-core/mach64_drv.h index cebd4c6,91553ce..fb8a772 --- a/shared-core/mach64_drv.h +++ b/shared-core/mach64_drv.h @@@ -96,6 -96,6 +96,8 @@@ typedef struct drm_mach64_private unsigned int depth_bpp; unsigned int depth_offset, depth_pitch; ++ atomic_t vbl_received; /**< Number of vblanks received. */ ++ u32 front_offset_pitch; u32 back_offset_pitch; u32 depth_offset_pitch; @@@ -155,13 -160,13 +162,14 @@@ extern int mach64_dma_blit(struct drm_d struct drm_file *file_priv); extern int mach64_get_param(struct drm_device *dev, void *data, struct drm_file *file_priv); --extern int mach64_driver_vblank_wait(struct drm_device * dev, -- unsigned int *sequence); ++extern u32 mach64_get_vblank_counter(struct drm_device *dev, int crtc); ++extern int mach64_enable_vblank(struct drm_device *dev, int crtc); ++extern void mach64_disable_vblank(struct drm_device *dev, int crtc); extern irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS); --extern void mach64_driver_irq_preinstall(struct drm_device * dev); --extern void mach64_driver_irq_postinstall(struct drm_device * dev); --extern void mach64_driver_irq_uninstall(struct drm_device * dev); ++extern void mach64_driver_irq_preinstall(struct drm_device *dev); ++extern int mach64_driver_irq_postinstall(struct drm_device *dev); ++extern void mach64_driver_irq_uninstall(struct drm_device *dev); /* ================================================================ * Registers diff --cc shared-core/mach64_irq.c index 4122dd9,4122dd9..2d522a6 --- a/shared-core/mach64_irq.c +++ b/shared-core/mach64_irq.c @@@ -42,9 -42,9 +42,8 @@@ irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS) { -- struct drm_device *dev = (struct drm_device *) arg; -- drm_mach64_private_t *dev_priv = -- (drm_mach64_private_t *) dev->dev_private; ++ struct drm_device *dev = arg; ++ drm_mach64_private_t *dev_priv = dev->dev_private; int status; status = MACH64_READ(MACH64_CRTC_INT_CNTL); @@@ -62,74 -62,74 +61,81 @@@ (status & ~MACH64_CRTC_INT_ACKS) | MACH64_CRTC_VBLANK_INT); -- atomic_inc(&dev->vbl_received); -- DRM_WAKEUP(&dev->vbl_queue); -- drm_vbl_send_signals(dev); ++ atomic_inc(&dev_priv->vbl_received); ++ drm_handle_vblank(dev, 0); return IRQ_HANDLED; } return IRQ_NONE; } --int mach64_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence) ++u32 mach64_get_vblank_counter(struct drm_device * dev, int crtc) { -- unsigned int cur_vblank; -- int ret = 0; -- -- /* Assume that the user has missed the current sequence number -- * by about a day rather than she wants to wait for years -- * using vertical blanks... -- */ -- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, -- (((cur_vblank = atomic_read(&dev->vbl_received)) -- - *sequence) <= (1 << 23))); ++ const drm_mach64_private_t *const dev_priv = dev->dev_private; ++ ++ if (crtc != 0) { ++ return 0; ++ } ++ ++ return atomic_read(&dev_priv->vbl_received); ++} -- *sequence = cur_vblank; ++int mach64_enable_vblank(struct drm_device * dev, int crtc) ++{ ++ drm_mach64_private_t *dev_priv = dev->dev_private; ++ u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL); ++ ++ if (crtc != 0) { ++ DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", crtc); ++ return 0; ++ } ++ ++ DRM_DEBUG("before enable vblank CRTC_INT_CTNL: 0x%08x\n", status); ++ ++ /* Turn on VBLANK interrupt */ ++ MACH64_WRITE(MACH64_CRTC_INT_CNTL, MACH64_READ(MACH64_CRTC_INT_CNTL) ++ | MACH64_CRTC_VBLANK_INT_EN); -- return ret; ++ return 0; } --/* drm_dma.h hooks --*/ --void mach64_driver_irq_preinstall(struct drm_device * dev) --{ -- drm_mach64_private_t *dev_priv = -- (drm_mach64_private_t *) dev->dev_private; ++void mach64_disable_vblank(struct drm_device * dev, int crtc) ++{ ++ drm_mach64_private_t *dev_priv = dev->dev_private; u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL); -- DRM_DEBUG("before install CRTC_INT_CTNL: 0x%08x\n", status); ++ DRM_DEBUG("before disable vblank CRTC_INT_CTNL: 0x%08x\n", status); /* Disable and clear VBLANK interrupt */ MACH64_WRITE(MACH64_CRTC_INT_CNTL, (status & ~MACH64_CRTC_VBLANK_INT_EN) | MACH64_CRTC_VBLANK_INT); } --void mach64_driver_irq_postinstall(struct drm_device * dev) ++/* drm_dma.h hooks ++*/ ++void mach64_driver_irq_preinstall(struct drm_device * dev) { -- drm_mach64_private_t *dev_priv = -- (drm_mach64_private_t *) dev->dev_private; ++ drm_mach64_private_t *dev_priv = dev->dev_private; -- /* Turn on VBLANK interrupt */ -- MACH64_WRITE(MACH64_CRTC_INT_CNTL, MACH64_READ(MACH64_CRTC_INT_CNTL) -- | MACH64_CRTC_VBLANK_INT_EN); ++ u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL); -- DRM_DEBUG("after install CRTC_INT_CTNL: 0x%08x\n", -- MACH64_READ(MACH64_CRTC_INT_CNTL)); ++ DRM_DEBUG("before install CRTC_INT_CTNL: 0x%08x\n", status); ++ mach64_disable_vblank(dev,0); ++} ++ ++int mach64_driver_irq_postinstall(struct drm_device * dev) ++{ ++ return drm_vblank_init(dev, 1); } void mach64_driver_irq_uninstall(struct drm_device * dev) { -- drm_mach64_private_t *dev_priv = -- (drm_mach64_private_t *) dev->dev_private; ++ drm_mach64_private_t *dev_priv = dev->dev_private; if (!dev_priv) return; -- /* Disable and clear VBLANK interrupt */ -- MACH64_WRITE(MACH64_CRTC_INT_CNTL, -- (MACH64_READ(MACH64_CRTC_INT_CNTL) & -- ~MACH64_CRTC_VBLANK_INT_EN) -- | MACH64_CRTC_VBLANK_INT); ++ mach64_disable_vblank(dev, 0); DRM_DEBUG("after uninstall CRTC_INT_CTNL: 0x%08x\n", MACH64_READ(MACH64_CRTC_INT_CNTL)); diff --cc shared-core/mga_irq.c index 0d4b473,0f83577..4fe8632 --- a/shared-core/mga_irq.c +++ b/shared-core/mga_irq.c @@@ -87,37 -74,27 +87,39 @@@ irqreturn_t mga_driver_irq_handler(DRM_ handled = 1; } - return (handled) ? IRQ_HANDLED : IRQ_NONE; + if (handled) + return IRQ_HANDLED; + return IRQ_NONE; } -int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence) +int mga_enable_vblank(struct drm_device *dev, int crtc) { - unsigned int cur_vblank; - int ret = 0; + drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - /* Assume that the user has missed the current sequence number - * by about a day rather than she wants to wait for years - * using vertical blanks... - */ - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(&dev->vbl_received)) - - *sequence) <= (1 << 23))); + if (crtc != 0) { + DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", + crtc); + return 0; + } - *sequence = cur_vblank; + MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); + return 0; +} - return ret; + +void mga_disable_vblank(struct drm_device *dev, int crtc) +{ + if (crtc != 0) { + DRM_ERROR("tried to disable vblank on non-existent crtc %d\n", + crtc); + } + + /* Do *NOT* disable the vertical refresh interrupt. MGA doesn't have + * a nice hardware counter that tracks the number of refreshes when + * the interrupt is disabled, and the kernel doesn't know the refresh + * rate to calculate an estimate. + */ + /* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */ } int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence) diff --cc shared-core/radeon_drv.h index a71b0be,c727880..bd51de1 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@@ -299,11 -305,9 +305,12 @@@ typedef struct drm_radeon_private u32 scratch_ages[5]; + unsigned int crtc_last_cnt; + unsigned int crtc2_last_cnt; + /* starting from here on, data is preserved accross an open */ uint32_t flags; /* see radeon_chip_flags */ + unsigned long fb_aper_offset; } drm_radeon_private_t; diff --cc shared-core/radeon_irq.c index 6ba3c14,7e202d2..79e4e86 --- a/shared-core/radeon_irq.c +++ b/shared-core/radeon_irq.c @@@ -175,13 -144,17 +175,13 @@@ static int radeon_wait_irq(struct drm_d return ret; } -static int radeon_driver_vblank_do_wait(struct drm_device * dev, - unsigned int *sequence, int crtc) +u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc) { - drm_radeon_private_t *dev_priv = - (drm_radeon_private_t *) dev->dev_private; - unsigned int cur_vblank; - int ret = 0; - int ack = 0; - atomic_t *counter; + drm_radeon_private_t *dev_priv = dev->dev_private; + u32 crtc_cnt_reg, crtc_status_reg; + if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } diff --cc shared-core/via_irq.c index a1d3324,2f9b203..b8e652e --- a/shared-core/via_irq.c +++ b/shared-core/via_irq.c @@@ -90,22 -89,13 +89,22 @@@ static int via_num_unichrome = ARRAY_SI static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1}; - static unsigned time_diff(struct timeval *now,struct timeval *then) + static unsigned time_diff(struct timeval *now,struct timeval *then) { - return (now->tv_usec >= then->tv_usec) ? - now->tv_usec - then->tv_usec : - 1000000 - (then->tv_usec - now->tv_usec); + return (now->tv_usec >= then->tv_usec) ? + now->tv_usec - then->tv_usec : + 1000000 - (then->tv_usec - now->tv_usec); } +u32 via_get_vblank_counter(struct drm_device *dev, int crtc) +{ + drm_via_private_t *dev_priv = dev->dev_private; + if (crtc != 0) + return 0; + + return atomic_read(&dev_priv->vbl_received); +} + irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; @@@ -133,18 -123,19 +132,18 @@@ dev_priv->last_vblank = cur_vblank; dev_priv->last_vblank_valid = 1; } - if (!(atomic_read(&dev->vbl_received) & 0xFF)) { + if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) { DRM_DEBUG("US per vblank is: %u\n", - dev_priv->usec_per_vblank); + dev_priv->usec_per_vblank); } - DRM_WAKEUP(&dev->vbl_queue); - drm_vbl_send_signals(dev); + drm_handle_vblank(dev, 0); handled = 1; } - - for (i=0; i<dev_priv->num_irqs; ++i) { + + for (i = 0; i < dev_priv->num_irqs; ++i) { if (status & cur_irq->pending_mask) { - atomic_inc( &cur_irq->irq_received ); - DRM_WAKEUP( &cur_irq->irq_queue ); + atomic_inc(&cur_irq->irq_received); + DRM_WAKEUP(&cur_irq->irq_queue); handled = 1; #ifdef VIA_HAVE_DMABLIT if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) { @@@ -189,20 -182,19 +188,15 @@@ int via_enable_vblank(struct drm_devic return -EINVAL; } - viadrv_acknowledge_irqs(dev_priv); - - /* Assume that the user has missed the current sequence number - * by about a day rather than she wants to wait for years - * using vertical blanks... - */ - - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(&dev->vbl_received)) - - *sequence) <= (1 << 23))); + status = VIA_READ(VIA_REG_INTERRUPT); + VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE); + return 0; +} - *sequence = cur_vblank; - return ret; +void via_disable_vblank(struct drm_device *dev, int crtc) +{ + if (crtc != 0) + DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc); - - /* - * FIXME: implement proper interrupt disable by using the vblank - * counter register (if available). - */ } static int commit 128a8f7ea20af2549e448157b431d5c1f90f37c3 Author: Jesse Barnes <jes...@in...> Date: Thu Nov 1 15:02:26 2007 -0700 Use unsigned long instead of u64 in drm_modeset_ctl_t A bad idea, ABI-wise, but we're going to be changing this structure anyway before we merge upstream, so just fix the build for now. diff --git a/shared-core/drm.h b/shared-core/drm.h index 3092e53..cbd6a94 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -565,7 +565,7 @@ typedef enum { * \sa drmModesetCtl(). */ typedef struct drm_modeset_ctl { - u64 arg; + unsigned long arg; drm_modeset_ctl_cmd_t cmd; } drm_modeset_ctl_t; commit 00d60265570c866261c09fd3397d5853a1ce196a Author: Jesse Barnes <jes...@in...> Date: Thu Nov 1 12:50:03 2007 -0700 Cleanup vblank_init and fix drm_irq_install The vblank_init function wanted a couple of cleanups. Also, drm_irq_install wasn't checking the new return value of irq_postinstall. If it returns a failure, assume IRQs didn't get set up and take appropriate action. diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index e917e7e..4aa58d7 100644 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@ -85,7 +85,7 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) { int i, ret = -ENOMEM; - setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,\ + setup_timer(&dev->vblank_disable_timer, vblank_disable_fn, (unsigned long)dev); spin_lock_init(&dev->vbl_lock); atomic_set(&dev->vbl_signal_pending, 0); @@ -111,18 +111,16 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) if (!dev->vblank_refcount) goto err; - dev->last_vblank = drm_calloc(1, sizeof(u32) * num_crtcs, - DRM_MEM_DRIVER); + dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER); if (!dev->last_vblank) goto err; - dev->vblank_premodeset = drm_calloc(1, sizeof(u32) * num_crtcs, + dev->vblank_premodeset = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER); if (!dev->vblank_premodeset) goto err; - dev->vblank_offset = drm_calloc(1, sizeof(u32) * num_crtcs, - DRM_MEM_DRIVER); + dev->vblank_offset = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER); if (!dev->vblank_offset) goto err; @@ -210,6 +208,11 @@ int drm_irq_install(struct drm_device * dev) /* After installing handler */ ret = dev->driver->irq_postinstall(dev); + if (ret < 0) { + mutex_lock(&dev->struct_mutex); + dev->irq_enabled = 0; + mutex_unlock(&dev->struct_mutex); + } return ret; } commit 91aae7e683786a48547872b0a5fa92b2232e02c0 Merge: 7e9ea55... 79744d7... Author: Jesse Barnes <jes...@in...> Date: Tue Oct 30 12:52:46 2007 -0700 Merge branch 'master' into vblank-rework, fixup remaining drivers Conflicts: linux-core/drmP.h linux-core/drm_drv.c linux-core/drm_irq.c shared-core/i915_drv.h shared-core/i915_irq.c shared-core/mga_drv.h shared-core/mga_irq.c shared-core/radeon_drv.h shared-core/radeon_irq.c Merge in the latest master bits and update the remaining drivers (except mach64 which math_b is working on). Also remove the 9xx hack from the i915 driver; it seems to be correct. diff --cc linux-core/drmP.h index 0ab69fe,ac3ca4d..332ee1c --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@@ -687,16 -658,17 +698,17 @@@ struct drm_driver /* these have to be filled in */ irqreturn_t(*irq_handler) (DRM_IRQ_ARGS); void (*irq_preinstall) (struct drm_device * dev); - void (*irq_postinstall) (struct drm_device * dev); + int (*irq_postinstall) (struct drm_device * dev); void (*irq_uninstall) (struct drm_device * dev); - void (*reclaim_buffers) (struct drm_device *dev, struct file * filp); + void (*reclaim_buffers) (struct drm_device *dev, + struct drm_file *file_priv); void (*reclaim_buffers_locked) (struct drm_device *dev, - struct file * filp); + struct drm_file *file_priv); void (*reclaim_buffers_idlelocked) (struct drm_device *dev, - struct file * filp); - unsigned long (*get_map_ofs) (drm_map_t * map); + struct drm_file *file_priv); + unsigned long (*get_map_ofs) (struct drm_map * map); unsigned long (*get_reg_ofs) (struct drm_device * dev); - void (*set_version) (struct drm_device * dev, drm_set_version_t * sv); + void (*set_version) (struct drm_device * dev, struct drm_set_version * sv); struct drm_fence_driver *fence_driver; struct drm_bo_driver *bo_driver; @@@ -854,10 -821,9 +867,10 @@@ struct drm_device #ifdef __alpha__ struct pci_controller *hose; #endif + int num_crtcs; /**< Number of CRTCs on this device */ - drm_sg_mem_t *sg; /**< Scatter gather memory */ + struct drm_sg_mem *sg; /**< Scatter gather memory */ void *dev_private; /**< device private data */ - drm_sigdata_t sigdata; /**< For block_all_signals */ + struct drm_sigdata sigdata; /**< For block_all_signals */ sigset_t sigmask; struct drm_driver *driver; @@@ -1072,94 -1040,90 +1087,98 @@@ extern void drm_idlelock_release(struc * DMA quiscent + idle. DMA quiescent usually requires the hardware lock. */ - extern int drm_i_have_hw_lock(struct file *filp); - extern int drm_kernel_take_hw_lock(struct file *filp); + extern int drm_i_have_hw_lock(struct drm_device *dev, + struct drm_file *file_priv); /* Buffer management support (drm_bufs.h) */ - extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request); - extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request); - extern int drm_addbufs_fb (drm_device_t * dev, drm_buf_desc_t * request); - extern int drm_addmap(drm_device_t * dev, unsigned int offset, - unsigned int size, drm_map_type_t type, - drm_map_flags_t flags, drm_local_map_t ** map_ptr); - extern int drm_addmap_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - extern int drm_rmmap(drm_device_t *dev, drm_local_map_t *map); - extern int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map); - extern int drm_rmmap_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - extern int drm_addbufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - extern int drm_infobufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - extern int drm_markbufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - extern int drm_freebufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - extern int drm_mapbufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); + extern int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc * request); + extern int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc * request); + extern int drm_addbufs_fb (struct drm_device *dev, struct drm_buf_desc * request); + extern int drm_addmap(struct drm_device *dev, unsigned int offset, + unsigned int size, enum drm_map_type type, + enum drm_map_flags flags, drm_local_map_t ** map_ptr); + extern int drm_addmap_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + extern int drm_rmmap(struct drm_device *dev, drm_local_map_t *map); + extern int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map); + extern int drm_rmmap_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + extern int drm_addbufs(struct drm_device *dev, void *data, + struct drm_file *file_priv); + extern int drm_infobufs(struct drm_device *dev, void *data, + struct drm_file *file_priv); + extern int drm_markbufs(struct drm_device *dev, void *data, + struct drm_file *file_priv); + extern int drm_freebufs(struct drm_device *dev, void *data, + struct drm_file *file_priv); + extern int drm_mapbufs(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern int drm_order(unsigned long size); - extern unsigned long drm_get_resource_start(drm_device_t *dev, + extern unsigned long drm_get_resource_start(struct drm_device *dev, unsigned int resource); - extern unsigned long drm_get_resource_len(drm_device_t *dev, + extern unsigned long drm_get_resource_len(struct drm_device *dev, unsigned int resource); + extern struct drm_map_list *drm_find_matching_map(struct drm_device *dev, + drm_local_map_t *map); + /* DMA support (drm_dma.h) */ - extern int drm_dma_setup(drm_device_t * dev); - extern void drm_dma_takedown(drm_device_t * dev); - extern void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf); - extern void drm_core_reclaim_buffers(drm_device_t *dev, struct file *filp); + extern int drm_dma_setup(struct drm_device *dev); + extern void drm_dma_takedown(struct drm_device *dev); + extern void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf); + extern void drm_core_reclaim_buffers(struct drm_device *dev, + struct drm_file *filp); /* IRQ support (drm_irq.h) */ - extern int drm_control(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); + extern int drm_control(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS); - extern int drm_irq_uninstall(drm_device_t *dev); - extern void drm_driver_irq_preinstall(drm_device_t * dev); - extern void drm_driver_irq_postinstall(drm_device_t * dev); - extern void drm_driver_irq_uninstall(drm_device_t * dev); - - extern int drm_vblank_init(drm_device_t *dev, int num_crtcs); - extern int drm_wait_vblank(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - extern int drm_vblank_wait(drm_device_t * dev, unsigned int *vbl_seq); - extern void drm_locked_tasklet(drm_device_t *dev, void(*func)(drm_device_t*)); - extern u32 drm_vblank_count(drm_device_t *dev, int crtc); - extern void drm_update_vblank_count(drm_device_t *dev, int crtc); - extern void drm_handle_vblank(drm_device_t *dev, int crtc); - extern int drm_vblank_get(drm_device_t *dev, int crtc); - extern void drm_vblank_put(drm_device_t *dev, int crtc); + extern int drm_irq_install(struct drm_device *dev); + extern int drm_irq_uninstall(struct drm_device *dev); + extern void drm_driver_irq_preinstall(struct drm_device *dev); + extern void drm_driver_irq_postinstall(struct drm_device *dev); + extern void drm_driver_irq_uninstall(struct drm_device *dev); + -extern int drm_wait_vblank(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq); -extern void drm_vbl_send_signals(struct drm_device *dev); ++extern int drm_vblank_init(struct drm_device *dev, int num_crtcs); ++extern int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *filp); ++extern int drm_vblank_wait(struct drm_device * dev, unsigned int *vbl_seq); + extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*)); ++extern u32 drm_vblank_count(struct drm_device *dev, int crtc); ++extern void drm_update_vblank_count(struct drm_device *dev, int crtc); ++extern void drm_handle_vblank(struct drm_device *dev, int crtc); ++extern int drm_vblank_get(struct drm_device *dev, int crtc); ++extern void drm_vblank_put(struct drm_device *dev, int crtc); + + /* Modesetting support */ - extern int drm_modeset_ctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); ++extern int drm_modeset_ctl(struct drm_device *dev, void *data, ++ struct drm_file *file_priv); /* AGP/GART support (drm_agpsupport.h) */ - extern drm_agp_head_t *drm_agp_init(drm_device_t *dev); - extern int drm_agp_acquire(drm_device_t * dev); - extern int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - extern int drm_agp_release(drm_device_t *dev); - extern int drm_agp_release_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - extern int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode); - extern int drm_agp_enable_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - extern int drm_agp_info(drm_device_t * dev, drm_agp_info_t *info); - extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - extern int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request); - extern int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - extern int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request); - extern int drm_agp_free_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - extern int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request); - extern int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - extern int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request); - extern int drm_agp_bind_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); + extern struct drm_agp_head *drm_agp_init(struct drm_device *dev); + extern int drm_agp_acquire(struct drm_device *dev); + extern int drm_agp_acquire_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + extern int drm_agp_release(struct drm_device *dev); + extern int drm_agp_release_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + extern int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode); + extern int drm_agp_enable_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + extern int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info); + extern int drm_agp_info_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + extern int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request); + extern int drm_agp_alloc_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + extern int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request); + extern int drm_agp_free_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + extern int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request); + extern int drm_agp_unbind_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request); + extern int drm_agp_bind_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11) extern DRM_AGP_MEM *drm_agp_allocate_memory(size_t pages, u32 type); #else diff --cc linux-core/drm_drv.c index 1b37ee4,47d1765..296a326 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@@ -48,82 -48,108 +48,106 @@@ #include "drmP.h" #include "drm_core.h" - static void drm_cleanup(drm_device_t * dev); + static void drm_cleanup(struct drm_device * dev); int drm_fb_loaded = 0; - static int drm_version(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); + static int drm_version(struct drm_device *dev, void *data, + struct drm_file *file_priv); /** Ioctl table */ - static drm_ioctl_desc_t drm_ioctls[] = { - [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = {drm_version, 0}, - [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = {drm_getunique, 0}, - [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = {drm_getmagic, 0}, - [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = {drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = {drm_getmap, 0}, - [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = {drm_getclient, 0}, - [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = {drm_getstats, 0}, - [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = {drm_setversion, DRM_MASTER|DRM_ROOT_ONLY}, - - [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = {drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = {drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - - [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = {drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = {drm_rmmap_ioctl, DRM_AUTH}, - - [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, DRM_AUTH}, - - [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = {drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = {drm_resctx, DRM_AUTH}, - - [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = {drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = {drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - - [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = {drm_lock, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = {drm_unlock, DRM_AUTH}, - - [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = {drm_noop, DRM_AUTH}, - - [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = {drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = {drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = {drm_infobufs, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = {drm_mapbufs, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = {drm_freebufs, DRM_AUTH}, + static struct drm_ioctl_desc drm_ioctls[] = { + DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0), + DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0), + DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0), + DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0), + DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0), + DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0), + DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY), + + DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + + DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH), + + DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH), + + DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH), + + DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + + DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH), + + DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH), + + DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH), /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */ - [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = {NULL, DRM_AUTH}, + DRM_IOCTL_DEF(DRM_IOCTL_DMA, NULL, DRM_AUTH), - [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = {drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), #if __OS_HAS_AGP - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = {drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = {drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = {drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = {drm_agp_info_ioctl, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = {drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = {drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = {drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = {drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), #endif - [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = {drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - - [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0}, - [DRM_IOCTL_NR(DRM_IOCTL_FENCE)] = {drm_fence_ioctl, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_IOCTL_BUFOBJ)] = {drm_bo_ioctl, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_IOCTL_MM_INIT)] = {drm_mm_init_ioctl, - DRM_AUTH }, - - [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_MODESET_CTL)] = {drm_modeset_ctl, 0}, + DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - + DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0), + - // DRM_IOCTL_DEF(DRM_IOCTL_BUFOBJ, drm_bo_ioctl, DRM_AUTH), ++ DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0), + + DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + - + DRM_IOCTL_DEF(DRM_IOCTL_MM_INIT, drm_mm_init_ioctl, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_MM_TAKEDOWN, drm_mm_takedown_ioctl, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_MM_LOCK, drm_mm_lock_ioctl, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_MM_UNLOCK, drm_mm_unlock_ioctl, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + + DRM_IOCTL_DEF(DRM_IOCTL_FENCE_CREATE, drm_fence_create_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_FENCE_REFERENCE, drm_fence_reference_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_FENCE_UNREFERENCE, drm_fence_unreference_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_FENCE_SIGNALED, drm_fence_signaled_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_FENCE_FLUSH, drm_fence_flush_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_FENCE_WAIT, drm_fence_wait_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_FENCE_EMIT, drm_fence_emit_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_FENCE_BUFFERS, drm_fence_buffers_ioctl, DRM_AUTH), + + DRM_IOCTL_DEF(DRM_IOCTL_BO_CREATE, drm_bo_create_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_BO_MAP, drm_bo_map_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_BO_UNMAP, drm_bo_unmap_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_BO_REFERENCE, drm_bo_reference_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_BO_UNREFERENCE, drm_bo_unreference_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_BO_SETSTATUS, drm_bo_setstatus_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_BO_INFO, drm_bo_info_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_BO_WAIT_IDLE, drm_bo_wait_idle_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_BO_VERSION, drm_bo_version_ioctl, 0), }; #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) diff --cc linux-core/drm_irq.c index eea00ac,25166b6..e917e7e --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@@ -74,93 -71,6 +71,90 @@@ int drm_irq_by_busid(struct drm_device - DRM_DEBUG("%d:%d:%d => IRQ %d\n", p.busnum, p.devnum, p.funcnum, p.irq); - if (copy_to_user(argp, &p, sizeof(p))) - return -EFAULT; return 0; } +static void vblank_disable_fn(unsigned long arg) +{ - drm_device_t *dev = (drm_device_t *)arg; ++ struct drm_device *dev = (struct drm_device *)arg; + int i; + + for (i = 0; i < dev->num_crtcs; i++) + if (atomic_read(&dev->vblank_refcount[i]) == 0) + dev->driver->disable_vblank(dev, i); +} + - int drm_vblank_init(drm_device_t *dev, int num_crtcs) ++int drm_vblank_init(struct drm_device *dev, int num_crtcs) +{ + int i, ret = -ENOMEM; + + setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,\ + (unsigned long)dev); + spin_lock_init(&dev->vbl_lock); + atomic_set(&dev->vbl_signal_pending, 0); + dev->num_crtcs = num_crtcs; + + dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs, + DRM_MEM_DRIVER); + if (!dev->vbl_queue) + goto err; + + dev->vbl_sigs = drm_alloc(sizeof(struct list_head) * num_crtcs, + DRM_MEM_DRIVER); + if (!dev->vbl_sigs) + goto err; + + dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs, + DRM_MEM_DRIVER); + if (!dev->_vblank_count) + goto err; + + dev->vblank_refcount = drm_alloc(sizeof(atomic_t) * num_crtcs, + DRM_MEM_DRIVER); + if (!dev->vblank_refcount) + goto err; + + dev->last_vblank = drm_calloc(1, sizeof(u32) * num_crtcs, + DRM_MEM_DRIVER); + if (!dev->last_vblank) + goto err; + + dev->vblank_premodeset = drm_calloc(1, sizeof(u32) * num_crtcs, + DRM_MEM_DRIVER); + if (!dev->vblank_premodeset) + goto err; + + dev->vblank_offset = drm_calloc(1, sizeof(u32) * num_crtcs, + DRM_MEM_DRIVER); + if (!dev->vblank_offset) + goto err; + + /* Zero per-crtc vblank stuff */ + for (i = 0; i < num_crtcs; i++) { + init_waitqueue_head(&dev->vbl_queue[i]); + INIT_LIST_HEAD(&dev->vbl_sigs[i]); + atomic_set(&dev->_vblank_count[i], 0); + atomic_set(&dev->vblank_refcount[i], 0); + } + + return 0; + +err: + drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * num_crtcs, + DRM_MEM_DRIVER); + drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * num_crtcs, + DRM_MEM_DRIVER); + drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) * num_crtcs, + DRM_MEM_DRIVER); + drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) * + num_crtcs, DRM_MEM_DRIVER); + drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * num_crtcs, + DRM_MEM_DRIVER); + drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) * + num_crtcs, DRM_MEM_DRIVER); + drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * num_crtcs, + DRM_MEM_DRIVER); + return ret; +} +EXPORT_SYMBOL(drm_vblank_init); + /** * Install IRQ handler. * @@@ -170,9 -80,9 +164,9 @@@ * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions * before and after the installation. */ - static int drm_irq_install(drm_device_t * dev) + int drm_irq_install(struct drm_device * dev) { - int ret; + int ret = 0; unsigned long sh_flags = 0; if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) @@@ -215,10 -136,11 +209,11 @@@ } /* After installing handler */ - dev->driver->irq_postinstall(dev); + ret ... [truncated message content] |