From 51e39089c95cd4f57a6696e0c2023a10527efb9a Mon Sep 17 00:00:00 2001 From: Robert Noland Date: Sat, 28 Feb 2009 02:37:55 +0000 Subject: Initialize the vblank structures at load time. Previously we did this at irq install/uninstall time, but when we vt switch, we uninstall the irq handler. When the irq handler is reinstalled, the modeset ioctl happens first. The modeset ioctl is supposed to tell us that we can disable vblank interrupts if there are no active consumers. This will fail after a vt switch until another modeset ioctl is called via dpms or xrandr. Leading to cases where either interrupts are on and can't be disabled, or worse, no interrupts at all. MFC after: 2 weeks --- sys/dev/drm/drmP.h | 1 + sys/dev/drm/drm_drv.c | 2 ++ sys/dev/drm/drm_irq.c | 4 +--- sys/dev/drm/i915_dma.c | 7 +++++++ sys/dev/drm/i915_drv.h | 2 ++ sys/dev/drm/i915_irq.c | 5 ----- sys/dev/drm/mach64_drv.c | 7 +++++++ sys/dev/drm/mach64_drv.h | 1 + sys/dev/drm/mach64_irq.c | 2 +- sys/dev/drm/mga_dma.c | 8 ++++++++ sys/dev/drm/mga_irq.c | 5 ----- sys/dev/drm/r128_drv.c | 6 ++++++ sys/dev/drm/r128_drv.h | 1 + sys/dev/drm/r128_irq.c | 2 +- sys/dev/drm/radeon_cp.c | 6 ++++++ sys/dev/drm/radeon_irq.c | 5 ----- 16 files changed, 44 insertions(+), 20 deletions(-) diff --git a/sys/dev/drm/drmP.h b/sys/dev/drm/drmP.h index 70ce9177935f..10ba4aece58d 100644 --- a/sys/dev/drm/drmP.h +++ b/sys/dev/drm/drmP.h @@ -794,6 +794,7 @@ void drm_handle_vblank(struct drm_device *dev, int crtc); u32 drm_vblank_count(struct drm_device *dev, int crtc); int drm_vblank_get(struct drm_device *dev, int crtc); void drm_vblank_put(struct drm_device *dev, int crtc); +void drm_vblank_cleanup(struct drm_device *dev); int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq); int drm_vblank_init(struct drm_device *dev, int num_crtcs); void drm_vbl_send_signals(struct drm_device *dev, int crtc); diff --git a/sys/dev/drm/drm_drv.c b/sys/dev/drm/drm_drv.c index 0b22491337e5..a753f9101e1d 100644 --- a/sys/dev/drm/drm_drv.c +++ b/sys/dev/drm/drm_drv.c @@ -523,6 +523,8 @@ static void drm_unload(struct drm_device *dev) DRM_DEBUG("mtrr_del = %d", retcode); } + drm_vblank_cleanup(dev); + DRM_LOCK(); drm_lastclose(dev); DRM_UNLOCK(); diff --git a/sys/dev/drm/drm_irq.c b/sys/dev/drm/drm_irq.c index 54392ae6e127..00e1c9d84e15 100644 --- a/sys/dev/drm/drm_irq.c +++ b/sys/dev/drm/drm_irq.c @@ -96,7 +96,7 @@ static void vblank_disable_fn(void *arg) } } -static void drm_vblank_cleanup(struct drm_device *dev) +void drm_vblank_cleanup(struct drm_device *dev) { unsigned long irqflags; @@ -213,8 +213,6 @@ int drm_irq_uninstall(struct drm_device *dev) bus_teardown_intr(dev->device, dev->irqr, dev->irqh); DRM_LOCK(); - drm_vblank_cleanup(dev); - return 0; } diff --git a/sys/dev/drm/i915_dma.c b/sys/dev/drm/i915_dma.c index a59aa38bdb37..199683130463 100644 --- a/sys/dev/drm/i915_dma.c +++ b/sys/dev/drm/i915_dma.c @@ -902,6 +902,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) #endif DRM_SPININIT(&dev_priv->user_irq_lock, "userirq"); + ret = drm_vblank_init(dev, I915_NUM_PIPE); + + if (ret) { + (void) i915_driver_unload(dev); + return ret; + } + return ret; } diff --git a/sys/dev/drm/i915_drv.h b/sys/dev/drm/i915_drv.h index b67eff8c5dd5..0935a7048e10 100644 --- a/sys/dev/drm/i915_drv.h +++ b/sys/dev/drm/i915_drv.h @@ -49,6 +49,8 @@ enum pipe { PIPE_B, }; +#define I915_NUM_PIPE 2 + /* Interface history: * * 1.1: Original. diff --git a/sys/dev/drm/i915_irq.c b/sys/dev/drm/i915_irq.c index f30dcde4f153..1117f62f24db 100644 --- a/sys/dev/drm/i915_irq.c +++ b/sys/dev/drm/i915_irq.c @@ -484,11 +484,6 @@ void i915_driver_irq_preinstall(struct drm_device * dev) int i915_driver_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - int ret, num_pipes = 2; - - ret = drm_vblank_init(dev, num_pipes); - if (ret) - return ret; dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; diff --git a/sys/dev/drm/mach64_drv.c b/sys/dev/drm/mach64_drv.c index 6c72d13403c2..c8fd0804274f 100644 --- a/sys/dev/drm/mach64_drv.c +++ b/sys/dev/drm/mach64_drv.c @@ -54,6 +54,7 @@ static void mach64_configure(struct drm_device *dev) DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ; dev->driver->buf_priv_size = 1; /* No dev_priv */ + dev->driver->load = mach64_driver_load; dev->driver->lastclose = mach64_driver_lastclose; dev->driver->get_vblank_counter = mach64_get_vblank_counter; dev->driver->enable_vblank = mach64_enable_vblank; @@ -94,6 +95,12 @@ mach64_attach(device_t nbdev) return drm_attach(nbdev, mach64_pciidlist); } +int +mach64_driver_load(struct drm_device * dev, unsigned long flags) +{ + return drm_vblank_init(dev, 1); +} + static int mach64_detach(device_t nbdev) { diff --git a/sys/dev/drm/mach64_drv.h b/sys/dev/drm/mach64_drv.h index 9c854548a003..7d68c4607c00 100644 --- a/sys/dev/drm/mach64_drv.h +++ b/sys/dev/drm/mach64_drv.h @@ -166,6 +166,7 @@ extern int mach64_dma_blit(struct drm_device *dev, void *data, extern int mach64_get_param(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int mach64_driver_load(struct drm_device * dev, unsigned long flags); 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); diff --git a/sys/dev/drm/mach64_irq.c b/sys/dev/drm/mach64_irq.c index d43372482e57..d4458d6cb87c 100644 --- a/sys/dev/drm/mach64_irq.c +++ b/sys/dev/drm/mach64_irq.c @@ -146,7 +146,7 @@ void mach64_driver_irq_preinstall(struct drm_device * dev) int mach64_driver_irq_postinstall(struct drm_device * dev) { - return drm_vblank_init(dev, 1); + return 0; } void mach64_driver_irq_uninstall(struct drm_device * dev) diff --git a/sys/dev/drm/mga_dma.c b/sys/dev/drm/mga_dma.c index 14c2d7314e57..e081e2c72c3c 100644 --- a/sys/dev/drm/mga_dma.c +++ b/sys/dev/drm/mga_dma.c @@ -399,6 +399,7 @@ int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf) int mga_driver_load(struct drm_device *dev, unsigned long flags) { drm_mga_private_t *dev_priv; + int ret; dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER); if (!dev_priv) @@ -418,6 +419,13 @@ int mga_driver_load(struct drm_device *dev, unsigned long flags) dev->types[7] = _DRM_STAT_PRIMARY; dev->types[8] = _DRM_STAT_SECONDARY; + ret = drm_vblank_init(dev, 1); + + if (ret) { + (void) mga_driver_unload(dev); + return ret; + } + return 0; } diff --git a/sys/dev/drm/mga_irq.c b/sys/dev/drm/mga_irq.c index 0d59993f481f..005d43d47443 100644 --- a/sys/dev/drm/mga_irq.c +++ b/sys/dev/drm/mga_irq.c @@ -157,11 +157,6 @@ void mga_driver_irq_preinstall(struct drm_device * dev) int mga_driver_irq_postinstall(struct drm_device * dev) { drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - int ret; - - ret = drm_vblank_init(dev, 1); - if (ret) - return ret; DRM_INIT_WAITQUEUE(&dev_priv->fence_queue); diff --git a/sys/dev/drm/r128_drv.c b/sys/dev/drm/r128_drv.c index 8d2994583048..575ca08d27aa 100644 --- a/sys/dev/drm/r128_drv.c +++ b/sys/dev/drm/r128_drv.c @@ -52,6 +52,7 @@ static void r128_configure(struct drm_device *dev) DRIVER_SG | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ; dev->driver->buf_priv_size = sizeof(drm_r128_buf_priv_t); + dev->driver->load = r128_driver_load; dev->driver->preclose = r128_driver_preclose; dev->driver->lastclose = r128_driver_lastclose; dev->driver->get_vblank_counter = r128_get_vblank_counter; @@ -93,6 +94,11 @@ r128_attach(device_t nbdev) return drm_attach(nbdev, r128_pciidlist); } +int r128_driver_load(struct drm_device * dev, unsigned long flags) +{ + return drm_vblank_init(dev, 1); +} + static int r128_detach(device_t nbdev) { diff --git a/sys/dev/drm/r128_drv.h b/sys/dev/drm/r128_drv.h index 0c223c6a0f6e..ee7d8f9c6844 100644 --- a/sys/dev/drm/r128_drv.h +++ b/sys/dev/drm/r128_drv.h @@ -162,6 +162,7 @@ extern void r128_driver_irq_preinstall(struct drm_device * dev); extern int r128_driver_irq_postinstall(struct drm_device * dev); extern void r128_driver_irq_uninstall(struct drm_device * dev); extern void r128_driver_lastclose(struct drm_device * dev); +extern int r128_driver_load(struct drm_device * dev, unsigned long flags); extern void r128_driver_preclose(struct drm_device * dev, struct drm_file *file_priv); diff --git a/sys/dev/drm/r128_irq.c b/sys/dev/drm/r128_irq.c index ec5eea1da074..6be6a1c15449 100644 --- a/sys/dev/drm/r128_irq.c +++ b/sys/dev/drm/r128_irq.c @@ -105,7 +105,7 @@ void r128_driver_irq_preinstall(struct drm_device * dev) int r128_driver_irq_postinstall(struct drm_device * dev) { - return drm_vblank_init(dev, 1); + return 0; } void r128_driver_irq_uninstall(struct drm_device * dev) diff --git a/sys/dev/drm/radeon_cp.c b/sys/dev/drm/radeon_cp.c index f0cc7f6b4426..6216d964973e 100644 --- a/sys/dev/drm/radeon_cp.c +++ b/sys/dev/drm/radeon_cp.c @@ -1751,6 +1751,12 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) else dev_priv->flags |= RADEON_IS_PCI; + ret = drm_vblank_init(dev, 2); + if (ret) { + radeon_driver_unload(dev); + return ret; + } + DRM_DEBUG("%s card detected\n", ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); return ret; diff --git a/sys/dev/drm/radeon_irq.c b/sys/dev/drm/radeon_irq.c index b6d03b2c9a32..3844fd6e8367 100644 --- a/sys/dev/drm/radeon_irq.c +++ b/sys/dev/drm/radeon_irq.c @@ -372,15 +372,10 @@ int radeon_driver_irq_postinstall(struct drm_device * dev) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; - int ret; atomic_set(&dev_priv->swi_emitted, 0); DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); - ret = drm_vblank_init(dev, 2); - if (ret) - return ret; - dev->max_vblank_count = 0x001fffff; radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); -- cgit v1.2.3