Index: dev/drm/drm_bufs.c =================================================================== --- dev/drm/drm_bufs.c (revision 193732) +++ dev/drm/drm_bufs.c (working copy) @@ -296,6 +296,9 @@ { DRM_SPINLOCK_ASSERT(&dev->dev_lock); + if (map == NULL) + return; + TAILQ_REMOVE(&dev->maplist, map, link); switch (map->type) { @@ -306,7 +309,7 @@ case _DRM_FRAME_BUFFER: if (map->mtrr) { int __unused retcode; - + retcode = drm_mtrr_del(0, map->offset, map->size, DRM_MTRR_WC); DRM_DEBUG("mtrr_del = %d\n", retcode); Index: dev/drm/radeon_cp.c =================================================================== --- dev/drm/radeon_cp.c (revision 193732) +++ dev/drm/radeon_cp.c (working copy) @@ -2063,17 +2063,31 @@ ret = drm_addmap(dev, drm_get_resource_start(dev, 2), drm_get_resource_len(dev, 2), _DRM_REGISTERS, _DRM_READ_ONLY | _DRM_DRIVER, &dev_priv->mmio); - if (ret != 0) - return ret; + if (ret) + goto error; ret = drm_vblank_init(dev, 2); - if (ret) { - radeon_driver_unload(dev); - return ret; - } + if (ret) + goto error; + dev->max_vblank_count = 0x001fffff; + /* Setup the interrupt handler */ + radeon_driver_irq_preinstall(dev); + ret = -drm_irq_setup(dev); + if (ret) + goto error; + ret = -drm_irq_install(dev); + if (ret) + goto error; + DRM_DEBUG("%s card detected\n", - ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); + ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : + (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); + + return 0; + +error: + radeon_driver_unload(dev); return ret; } @@ -2104,6 +2118,13 @@ DRM_DEBUG("\n"); + /* uninstall the interrupt handler */ + if (dev->irq_enabled) + drm_irq_uninstall(dev); + DRM_UNLOCK(); + drm_irq_teardown(dev); + DRM_LOCK(); + drm_rmmap(dev, dev_priv->mmio); drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); Index: dev/drm/drm_irq.c =================================================================== --- dev/drm/drm_irq.c (revision 193732) +++ dev/drm/drm_irq.c (working copy) @@ -70,6 +70,9 @@ struct drm_device *dev = (struct drm_device *)arg; int i; + /* Make sure that we are called with the lock held */ + mtx_assert(&dev->vbl_lock, MA_OWNED); + if (callout_pending(&dev->vblank_disable_timer)) { /* callout was reset */ return; @@ -86,8 +89,8 @@ return; for (i = 0; i < dev->num_crtcs; i++) { - if (atomic_read(&dev->vblank[i].refcount) == 0 && - dev->vblank[i].enabled && !dev->vblank[i].inmodeset) { + if (dev->vblank[i].refcount == 0 && + dev->vblank[i].enabled) { DRM_DEBUG("disabling vblank on crtc %d\n", i); dev->vblank[i].last = dev->driver->get_vblank_counter(dev, i); @@ -109,7 +112,9 @@ callout_drain(&dev->vblank_disable_timer); + DRM_SPINLOCK(&dev->vbl_lock); vblank_disable_fn((void *)dev); + DRM_SPINUNLOCK(&dev->vbl_lock); free(dev->vblank, DRM_MEM_DRIVER); @@ -132,14 +137,15 @@ DRM_DEBUG("\n"); /* Zero per-crtc vblank stuff */ + DRM_SPINLOCK(&dev->vbl_lock); for (i = 0; i < num_crtcs; i++) { DRM_INIT_WAITQUEUE(&dev->vblank[i].queue); TAILQ_INIT(&dev->vblank[i].sigs); - atomic_set(&dev->vblank[i].count, 0); - atomic_set(&dev->vblank[i].refcount, 0); + dev->vblank[i].refcount = 0; + atomic_set_rel_32(&dev->vblank[i].count, 0); } - dev->vblank_disable_allowed = 0; + DRM_SPINUNLOCK(&dev->vbl_lock); return 0; @@ -148,98 +154,50 @@ return ret; } -int drm_irq_install(struct drm_device *dev) +int +drm_irq_install(struct drm_device *dev) { - int crtc, retcode; + DRM_SPINLOCK_ASSERT(&dev->dev_lock); - if (dev->irq == 0 || dev->dev_private == NULL) - return EINVAL; - - DRM_DEBUG("irq=%d\n", dev->irq); - - DRM_LOCK(); - if (dev->irq_enabled) { - DRM_UNLOCK(); - return EBUSY; - } dev->irq_enabled = 1; - dev->context_flag = 0; - - /* Before installing handler */ - dev->driver->irq_preinstall(dev); - DRM_UNLOCK(); - - /* Install handler */ -#if __FreeBSD_version >= 700031 - retcode = bus_setup_intr(dev->device, dev->irqr, - INTR_TYPE_TTY | INTR_MPSAFE, - NULL, drm_irq_handler_wrap, dev, &dev->irqh); -#else - retcode = bus_setup_intr(dev->device, dev->irqr, - INTR_TYPE_TTY | INTR_MPSAFE, - drm_irq_handler_wrap, dev, &dev->irqh); -#endif - if (retcode != 0) - goto err; - - /* After installing handler */ - DRM_LOCK(); + DRM_SPINLOCK(&dev->irq_lock); dev->driver->irq_postinstall(dev); - DRM_UNLOCK(); - if (dev->driver->enable_vblank) { - DRM_SPINLOCK(&dev->vbl_lock); - for( crtc = 0 ; crtc < dev->num_crtcs ; crtc++) { - if (dev->driver->enable_vblank(dev, crtc) == 0) { - dev->vblank[crtc].enabled = 1; - } - } - callout_reset(&dev->vblank_disable_timer, 5 * DRM_HZ, - (timeout_t *)vblank_disable_fn, (void *)dev); - DRM_SPINUNLOCK(&dev->vbl_lock); - } + DRM_SPINUNLOCK(&dev->irq_lock); return 0; -err: - DRM_LOCK(); - dev->irq_enabled = 0; - DRM_UNLOCK(); - - return retcode; } -int drm_irq_uninstall(struct drm_device *dev) +int +drm_irq_uninstall(struct drm_device *dev) { - int crtc; + DRM_SPINLOCK_ASSERT(&dev->dev_lock); - if (!dev->irq_enabled) - return EINVAL; + DRM_SPINLOCK(&dev->irq_lock); + dev->driver->irq_uninstall(dev); + DRM_SPINUNLOCK(&dev->irq_lock); dev->irq_enabled = 0; - /* - * Wake up any waiters so they don't hang. - */ - DRM_SPINLOCK(&dev->vbl_lock); - for (crtc = 0; crtc < dev->num_crtcs; crtc++) { - if (dev->vblank[crtc].enabled) { - DRM_WAKEUP(&dev->vblank[crtc].queue); - dev->vblank[crtc].last = - dev->driver->get_vblank_counter(dev, crtc); - dev->vblank[crtc].enabled = 0; - } - } - DRM_SPINUNLOCK(&dev->vbl_lock); + return 0; +} - DRM_DEBUG("irq=%d\n", dev->irq); +int +drm_irq_setup(struct drm_device *dev) +{ + int intr_flags; - dev->driver->irq_uninstall(dev); + intr_flags = INTR_TYPE_TTY | INTR_MPSAFE; + if (dev->msi_enabled) + intr_flags |= INTR_EXCL; + return bus_setup_intr(dev->device, dev->irqr, intr_flags, NULL, + drm_irq_handler_wrap, dev, &dev->irqh); +} - DRM_UNLOCK(); - bus_teardown_intr(dev->device, dev->irqr, dev->irqh); - DRM_LOCK(); - - return 0; +int +drm_irq_teardown(struct drm_device *dev) +{ + return bus_teardown_intr(dev->device, dev->irqr, dev->irqh); } int drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -257,7 +215,10 @@ if (dev->if_version < DRM_IF_VERSION(1, 2) && ctl->irq != dev->irq) return EINVAL; - return drm_irq_install(dev); + DRM_LOCK(); + err = drm_irq_install(dev); + DRM_UNLOCK(); + return err; case DRM_UNINST_HANDLER: if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return 0; @@ -272,7 +233,7 @@ u32 drm_vblank_count(struct drm_device *dev, int crtc) { - return atomic_read(&dev->vblank[crtc].count); + return atomic_load_acq_32(&dev->vblank[crtc].count); } static void drm_update_vblank_count(struct drm_device *dev, int crtc) @@ -298,45 +259,49 @@ DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", crtc, diff); - atomic_add(diff, &dev->vblank[crtc].count); + atomic_add_rel_32(&dev->vblank[crtc].count, diff); } int drm_vblank_get(struct drm_device *dev, int crtc) { int ret = 0; - DRM_SPINLOCK(&dev->vbl_lock); + /* Make sure that we are called with the lock held */ + mtx_assert(&dev->vbl_lock, MA_OWNED); + /* Going from 0->1 means we have to enable interrupts again */ - atomic_add_acq_int(&dev->vblank[crtc].refcount, 1); - if (dev->vblank[crtc].refcount == 1 && + if (++dev->vblank[crtc].refcount == 1 && !dev->vblank[crtc].enabled) { ret = dev->driver->enable_vblank(dev, crtc); DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); if (ret) - atomic_dec(&dev->vblank[crtc].refcount); + --dev->vblank[crtc].refcount; else { dev->vblank[crtc].enabled = 1; drm_update_vblank_count(dev, crtc); } } - DRM_SPINUNLOCK(&dev->vbl_lock); + if (dev->vblank[crtc].enabled) { + dev->vblank[crtc].last = + dev->driver->get_vblank_counter(dev, crtc); + } + return ret; } void drm_vblank_put(struct drm_device *dev, int crtc) { - KASSERT(atomic_read(&dev->vblank[crtc].refcount) > 0, + /* Make sure that we are called with the lock held */ + mtx_assert(&dev->vbl_lock, MA_OWNED); + + KASSERT(dev->vblank[crtc].refcount > 0, ("invalid refcount")); /* Last user schedules interrupt disable */ - atomic_subtract_acq_int(&dev->vblank[crtc].refcount, 1); - - DRM_SPINLOCK(&dev->vbl_lock); - if (dev->vblank[crtc].refcount == 0) + if (--dev->vblank[crtc].refcount == 0) callout_reset(&dev->vblank_disable_timer, 5 * DRM_HZ, (timeout_t *)vblank_disable_fn, (void *)dev); - DRM_SPINUNLOCK(&dev->vbl_lock); } int drm_modeset_ctl(struct drm_device *dev, void *data, @@ -345,13 +310,11 @@ struct drm_modeset_ctl *modeset = data; int crtc, ret = 0; - DRM_DEBUG("num_crtcs=%d\n", dev->num_crtcs); /* If drm_vblank_init() hasn't been called yet, just no-op */ if (!dev->num_crtcs) goto out; crtc = modeset->crtc; - DRM_DEBUG("crtc=%d\n", crtc); if (crtc >= dev->num_crtcs) { ret = EINVAL; goto out; @@ -366,25 +329,25 @@ */ switch (modeset->cmd) { case _DRM_PRE_MODESET: - DRM_DEBUG("pre-modeset\n"); + DRM_DEBUG("pre-modeset, crtc %d\n", crtc); + DRM_SPINLOCK(&dev->vbl_lock); if (!dev->vblank[crtc].inmodeset) { dev->vblank[crtc].inmodeset = 0x1; if (drm_vblank_get(dev, crtc) == 0) dev->vblank[crtc].inmodeset |= 0x2; } + DRM_SPINUNLOCK(&dev->vbl_lock); break; case _DRM_POST_MODESET: - DRM_DEBUG("post-modeset\n"); + DRM_DEBUG("post-modeset, crtc %d\n", crtc); + DRM_SPINLOCK(&dev->vbl_lock); if (dev->vblank[crtc].inmodeset) { - DRM_SPINLOCK(&dev->vbl_lock); - dev->vblank_disable_allowed = 1; - DRM_SPINUNLOCK(&dev->vbl_lock); - if (dev->vblank[crtc].inmodeset & 0x2) drm_vblank_put(dev, crtc); - dev->vblank[crtc].inmodeset = 0; } + dev->vblank_disable_allowed = 1; + DRM_SPINUNLOCK(&dev->vbl_lock); break; default: ret = EINVAL; @@ -401,8 +364,9 @@ unsigned int flags, seq, crtc; int ret = 0; - if (!dev->irq_enabled) + if (!dev->irq_enabled) { return EINVAL; + } if (vblwait->request.type & ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) { @@ -415,10 +379,13 @@ flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK; crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0; - if (crtc >= dev->num_crtcs) + if (crtc >= dev->num_crtcs) { return EINVAL; + } + DRM_SPINLOCK(&dev->vbl_lock); ret = drm_vblank_get(dev, crtc); + DRM_SPINUNLOCK(&dev->vbl_lock); if (ret) { DRM_ERROR("failed to acquire vblank counter, %d\n", ret); return ret; @@ -438,7 +405,9 @@ if ((flags & _DRM_VBLANK_NEXTONMISS) && (seq - vblwait->request.sequence) <= (1<<23)) { + DRM_LOCK(); vblwait->request.sequence = seq + 1; + DRM_UNLOCK(); } if (flags & _DRM_VBLANK_SIGNAL) { @@ -463,7 +432,6 @@ } else { DRM_DEBUG("waiting on vblank count %d, crtc %d\n", vblwait->request.sequence, crtc); - dev->vblank[crtc].last = vblwait->request.sequence; for ( ret = 0 ; !ret && !(((drm_vblank_count(dev, crtc) - vblwait->request.sequence) <= (1 << 23)) || !dev->irq_enabled) ; ) { @@ -473,10 +441,14 @@ !dev->irq_enabled)) ret = mtx_sleep(&dev->vblank[crtc].queue, &dev->irq_lock, PCATCH, "vblwtq", - 3 * DRM_HZ); + DRM_HZ); mtx_unlock(&dev->irq_lock); } + if (ret == EWOULDBLOCK) { + DRM_DEBUG("timed out waiting on vblank\n"); + /* ret = EBUSY; */ + } if (ret != EINTR && ret != ERESTART) { struct timeval now; @@ -492,7 +464,10 @@ } done: + DRM_SPINLOCK(&dev->vbl_lock); drm_vblank_put(dev, crtc); + DRM_SPINUNLOCK(&dev->vbl_lock); + return ret; } @@ -526,7 +501,7 @@ void drm_handle_vblank(struct drm_device *dev, int crtc) { - atomic_inc(&dev->vblank[crtc].count); + atomic_add_rel_32(&dev->vblank[crtc].count, 1); DRM_WAKEUP(&dev->vblank[crtc].queue); drm_vbl_send_signals(dev, crtc); } Index: dev/drm/i915_drm.h =================================================================== --- dev/drm/i915_drm.h (revision 193732) +++ dev/drm/i915_drm.h (working copy) @@ -284,6 +284,7 @@ #define I915_PARAM_LAST_DISPATCH 3 #define I915_PARAM_CHIPSET_ID 4 #define I915_PARAM_HAS_GEM 5 +#define I915_PARAM_NUM_FENCES_AVAIL 6 typedef struct drm_i915_getparam { int param; @@ -295,6 +296,7 @@ #define I915_SETPARAM_USE_MI_BATCHBUFFER_START 1 #define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2 #define I915_SETPARAM_ALLOW_BATCHBUFFER 3 +#define I915_SETPARAM_NUM_USED_FENCES 4 typedef struct drm_i915_setparam { int param; Index: dev/drm/i915_irq.c =================================================================== --- dev/drm/i915_irq.c (revision 193732) +++ dev/drm/i915_irq.c (working copy) @@ -53,12 +53,6 @@ #define I915_INTERRUPT_ENABLE_MASK (I915_INTERRUPT_ENABLE_FIX | \ I915_INTERRUPT_ENABLE_VAR) -#define I915_PIPE_VBLANK_STATUS (PIPE_START_VBLANK_INTERRUPT_STATUS |\ - PIPE_VBLANK_INTERRUPT_STATUS) - -#define I915_PIPE_VBLANK_ENABLE (PIPE_START_VBLANK_INTERRUPT_ENABLE |\ - PIPE_VBLANK_INTERRUPT_ENABLE) - #define DRM_I915_VBLANK_PIPE_ALL (DRM_I915_VBLANK_PIPE_A | \ DRM_I915_VBLANK_PIPE_B) @@ -154,7 +148,7 @@ low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; if (!i915_pipe_enabled(dev, pipe)) { - DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe); + DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe); return 0; } @@ -177,13 +171,13 @@ return count; } -u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) +u32 g45_get_vblank_counter(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45; if (!i915_pipe_enabled(dev, pipe)) { - DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe); + DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe); return 0; } @@ -196,25 +190,9 @@ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 iir, new_iir; u32 pipea_stats, pipeb_stats; - u32 vblank_status; - u32 vblank_enable; - int irq_received; - atomic_inc(&dev_priv->irq_received); + for (iir = I915_READ(IIR) ; iir != 0 ; iir = new_iir) { - iir = I915_READ(IIR); - - if (IS_I965G(dev)) { - vblank_status = I915_START_VBLANK_INTERRUPT_STATUS; - vblank_enable = PIPE_START_VBLANK_INTERRUPT_ENABLE; - } else { - vblank_status = I915_VBLANK_INTERRUPT_STATUS; - vblank_enable = I915_VBLANK_INTERRUPT_ENABLE; - } - - for (;;) { - irq_received = iir != 0; - /* Can't rely on pipestat interrupt bit in iir as it might * have been cleared after the pipestat interrupt was received. * It doesn't set the bit in iir again, but it still produces @@ -229,18 +207,13 @@ */ if (pipea_stats & 0x8000ffff) { I915_WRITE(PIPEASTAT, pipea_stats); - irq_received = 1; } if (pipeb_stats & 0x8000ffff) { I915_WRITE(PIPEBSTAT, pipeb_stats); - irq_received = 1; } DRM_SPINUNLOCK(&dev_priv->user_irq_lock); - if (!irq_received) - break; - I915_WRITE(IIR, iir); new_iir = I915_READ(IIR); /* Flush posted writes */ @@ -252,10 +225,12 @@ DRM_WAKEUP(&dev_priv->irq_queue); } - if (pipea_stats & vblank_status) + if (dev->vblank[0].enabled && + pipea_stats & dev_priv->vblank_status) drm_handle_vblank(dev, 0); - if (pipeb_stats & vblank_status) + if (dev->vblank[1].enabled && + pipeb_stats & dev_priv->vblank_status) drm_handle_vblank(dev, 1); /* With MSI, interrupts are only generated when iir @@ -305,9 +280,12 @@ { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + if (dev->irq_enabled == 0) + return; + DRM_DEBUG("\n"); DRM_SPINLOCK(&dev_priv->user_irq_lock); - if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) + if (++dev_priv->user_irq_refcount == 1) i915_enable_irq(dev_priv, I915_USER_INTERRUPT); DRM_SPINUNLOCK(&dev_priv->user_irq_lock); } @@ -316,12 +294,13 @@ { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + if (dev->irq_enabled == 0) + return; + DRM_SPINLOCK(&dev_priv->user_irq_lock); - if (dev->irq_enabled) { - KASSERT(dev_priv->user_irq_refcount > 0, ("invalid refcount")); - if (--dev_priv->user_irq_refcount == 0) - i915_disable_irq(dev_priv, I915_USER_INTERRUPT); - } + KASSERT(dev_priv->user_irq_refcount > 0, ("invalid refcount")); + if (--dev_priv->user_irq_refcount == 0) + i915_disable_irq(dev_priv, I915_USER_INTERRUPT); DRM_SPINUNLOCK(&dev_priv->user_irq_lock); } @@ -352,7 +331,8 @@ if (ret == -ERESTART) DRM_DEBUG("restarting syscall\n"); - if (ret == -EBUSY) { + if (ret == -EWOULDBLOCK) { + /* ret = -EBUSY; */ DRM_ERROR("EBUSY -- rec: %d emitted: %d\n", READ_BREADCRUMB(dev_priv), (int)dev_priv->counter); } @@ -378,10 +358,13 @@ result = i915_emit_irq(dev); + DRM_UNLOCK(); if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) { DRM_ERROR("copy_to_user\n"); + DRM_LOCK(); return -EFAULT; } + DRM_LOCK(); return 0; } @@ -394,7 +377,7 @@ drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_irq_wait_t *irqwait = data; - if (!dev_priv) { + if (!dev_priv || !irqwait) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -408,20 +391,12 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; - u32 pipeconf; - pipeconf = I915_READ(pipeconf_reg); - if (!(pipeconf & PIPEACONF_ENABLE)) + if (!i915_pipe_enabled(dev, pipe)) return -EINVAL; DRM_SPINLOCK(&dev_priv->user_irq_lock); - if (IS_I965G(dev)) - i915_enable_pipestat(dev_priv, pipe, - PIPE_START_VBLANK_INTERRUPT_ENABLE); - else - i915_enable_pipestat(dev_priv, pipe, - PIPE_VBLANK_INTERRUPT_ENABLE); + i915_enable_pipestat(dev_priv, pipe, dev_priv->vblank_enable); DRM_SPINUNLOCK(&dev_priv->user_irq_lock); return 0; } @@ -434,9 +409,7 @@ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; DRM_SPINLOCK(&dev_priv->user_irq_lock); - i915_disable_pipestat(dev_priv, pipe, - PIPE_VBLANK_INTERRUPT_ENABLE | - PIPE_START_VBLANK_INTERRUPT_ENABLE); + i915_disable_pipestat(dev_priv, pipe, dev_priv->vblank_enable); DRM_SPINUNLOCK(&dev_priv->user_irq_lock); } @@ -466,7 +439,7 @@ return -EINVAL; } - pipe->pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; + pipe->pipe = DRM_I915_VBLANK_PIPE_ALL; return 0; } @@ -500,8 +473,6 @@ { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - atomic_set_int(&dev_priv->irq_received, 0); - I915_WRITE(HWSTAM, 0xeffe); I915_WRITE(PIPEASTAT, 0); I915_WRITE(PIPEBSTAT, 0); @@ -514,17 +485,17 @@ { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; + dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_ALL; - dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ - /* Unmask the interrupts that we always want on. */ dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX; - dev_priv->pipestat[0] = 0; - dev_priv->pipestat[1] = 0; - /* Disable pipe interrupt enables, clear pending pipe status */ + /* + * If you driver is going to be brain-damaged and setup + * vblank interrupts before you install the handler, then + * you can't nuke it here. + */ I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff); I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff); @@ -533,6 +504,10 @@ I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK); I915_WRITE(IMR, dev_priv->irq_mask_reg); + I915_WRITE(PIPEASTAT, dev_priv->pipestat[0] | + (dev_priv->pipestat[0] >> 16)); + I915_WRITE(PIPEBSTAT, dev_priv->pipestat[1] | + (dev_priv->pipestat[1] >> 16)); (void) I915_READ(IER); return 0; Index: dev/drm/drm_agpsupport.c =================================================================== --- dev/drm/drm_agpsupport.c (revision 193732) +++ dev/drm/drm_agpsupport.c (working copy) @@ -227,6 +227,9 @@ return ENOMEM; } + pmap_change_attr((vm_offset_t)handle, pages << AGP_PAGE_SHIFT, + PAT_WRITE_COMBINING); + entry->handle = handle; entry->bound = 0; entry->pages = pages; Index: dev/drm/i915_dma.c =================================================================== --- dev/drm/i915_dma.c (revision 193732) +++ dev/drm/i915_dma.c (working copy) @@ -141,12 +141,6 @@ static int i915_dma_cleanup(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; - /* Make sure interrupts are disabled here because the uninstall ioctl - * may not have been called from userspace and after dev_private - * is freed, it's too late. - */ - if (dev->irq_enabled) - drm_irq_uninstall(dev); if (dev_priv->ring.virtual_start) { drm_core_ioremapfree(&dev_priv->ring.map, dev); @@ -439,17 +433,21 @@ drm_i915_private_t *dev_priv = dev->dev_private; RING_LOCALS; + DRM_LOCK(); if (++dev_priv->counter > 0x7FFFFFFFUL) dev_priv->counter = 0; if (dev_priv->sarea_priv) dev_priv->sarea_priv->last_enqueue = dev_priv->counter; + DRM_DEBUG("emitting: %d\n", dev_priv->counter); + BEGIN_LP_RING(4); OUT_RING(MI_STORE_DWORD_INDEX); OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); OUT_RING(dev_priv->counter); OUT_RING(0); ADVANCE_LP_RING(); + DRM_UNLOCK(); } static int i915_dispatch_cmdbuffer(struct drm_device * dev, @@ -481,6 +479,7 @@ } i915_emit_breadcrumb(dev); + return 0; } @@ -644,18 +643,17 @@ return -EFAULT; } } - DRM_LOCK(); ret = i915_dispatch_batchbuffer(dev, batch); - if (sarea_priv) - sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); - - DRM_UNLOCK(); if (batch->num_cliprects) vsunlock(batch->cliprects, cliplen); + DRM_LOCK(); + if (sarea_priv) + sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + return ret; } @@ -697,10 +695,9 @@ return -EFAULT; } } - DRM_LOCK(); ret = i915_dispatch_cmdbuffer(dev, cmdbuf); - DRM_UNLOCK(); + if (cmdbuf->num_cliprects) { vsunlock(cmdbuf->buf, cmdbuf->sz); vsunlock(cmdbuf->cliprects, cliplen); @@ -759,15 +756,21 @@ /* We need to reset this to 1 once we have GEM */ value = 0; break; + case I915_PARAM_NUM_FENCES_AVAIL: + value = dev_priv->num_fence_regs - dev_priv->fence_reg_start; + break; default: DRM_DEBUG("Unknown parameter %d\n", param->param); return -EINVAL; } + DRM_UNLOCK(); if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { DRM_ERROR("DRM_COPY_TO_USER failed\n"); + DRM_LOCK(); return -EFAULT; } + DRM_LOCK(); return 0; } @@ -792,6 +795,13 @@ case I915_SETPARAM_ALLOW_BATCHBUFFER: dev_priv->allow_batchbuffer = param->value; break; + case I915_SETPARAM_NUM_USED_FENCES: + if (param->value > dev_priv->num_fence_regs || + param->value < 0) + return -EINVAL; + /* Userspace can use first N regs */ + dev_priv->fence_reg_start = param->value; + break; default: DRM_DEBUG("unknown parameter %d\n", param->param); return -EINVAL; @@ -870,24 +880,16 @@ ret = drm_addmap(dev, base, size, _DRM_REGISTERS, _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio_map); - - if (IS_GM45(dev)) - dev->driver->get_vblank_counter = gm45_get_vblank_counter; - else - dev->driver->get_vblank_counter = i915_get_vblank_counter; - + if (ret) + goto error; #ifdef I915_HAVE_GEM i915_gem_load(dev); #endif /* Init HWS */ if (!I915_NEED_GFX_HWS(dev)) { ret = i915_init_phys_hws(dev); - if (ret != 0) { - drm_rmmap(dev, dev_priv->mmio_map); - drm_free(dev_priv, sizeof(struct drm_i915_private), - DRM_MEM_DRIVER); - return ret; - } + if (ret) + goto error; } #ifdef __linux__ /* On the 945G/GM, the chipset reports the MSI capability on the @@ -909,13 +911,41 @@ DRM_SPININIT(&dev_priv->user_irq_lock, "userirq"); dev_priv->user_irq_refcount = 0; - ret = drm_vblank_init(dev, I915_NUM_PIPE); + if (IS_G4X(dev)) { + dev->driver->get_vblank_counter = g45_get_vblank_counter; + dev->max_vblank_count = 0xffffffff; /* 32 bits of frame count */ + } else { + dev->driver->get_vblank_counter = i915_get_vblank_counter; + dev->max_vblank_count = 0x00ffffff; /* 24 bits of frame count */ + } - if (ret) { - (void) i915_driver_unload(dev); - return ret; + if (IS_I965G(dev)) { + dev_priv->vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS; + dev_priv->vblank_enable = PIPE_START_VBLANK_INTERRUPT_ENABLE; + } else { + dev_priv->vblank_status = I915_VBLANK_INTERRUPT_STATUS; + dev_priv->vblank_enable = I915_VBLANK_INTERRUPT_ENABLE; } + ret = drm_vblank_init(dev, I915_NUM_PIPE); + if (ret) + goto error; + + /* Setup the interrupt handler */ + i915_driver_irq_preinstall(dev); + DRM_UNLOCK(); + ret = -drm_irq_setup(dev); + DRM_LOCK(); + if (ret) + goto error; + ret = -drm_irq_install(dev); + if (ret) + goto error; + + return 0; + +error: + i915_driver_unload(dev); return ret; } @@ -923,6 +953,13 @@ { struct drm_i915_private *dev_priv = dev->dev_private; + /* uninstall the interrupt handler */ + if (dev->irq_enabled) + drm_irq_uninstall(dev); + DRM_UNLOCK(); + drm_irq_teardown(dev); + DRM_LOCK(); + i915_free_hws(dev); drm_rmmap(dev, dev_priv->mmio_map); @@ -931,9 +968,9 @@ #endif DRM_SPINUNINIT(&dev_priv->user_irq_lock); - drm_free(dev->dev_private, sizeof(drm_i915_private_t), - DRM_MEM_DRIVER); + drm_free(dev->dev_private, sizeof(*dev_priv), DRM_MEM_DRIVER); + dev->dev_private = NULL; return 0; } Index: dev/drm/i915_mem.c =================================================================== --- dev/drm/i915_mem.c (revision 193732) +++ dev/drm/i915_mem.c (working copy) @@ -300,11 +300,14 @@ mark_block(dev, block, 1); + DRM_UNLOCK(); if (DRM_COPY_TO_USER(alloc->region_offset, &block->start, sizeof(int))) { DRM_ERROR("copy_to_user\n"); + DRM_LOCK(); return -EFAULT; } + DRM_LOCK(); return 0; } Index: dev/drm/radeon_drv.h =================================================================== --- dev/drm/radeon_drv.h (revision 193732) +++ dev/drm/radeon_drv.h (working copy) @@ -309,7 +309,6 @@ atomic_t swi_emitted; int vblank_crtc; uint32_t irq_enable_reg; - int irq_enabled; uint32_t r500_disp_irq_reg; struct radeon_surface surfaces[RADEON_MAX_SURFACES]; Index: dev/drm/i915_reg.h =================================================================== --- dev/drm/i915_reg.h (revision 193732) +++ dev/drm/i915_reg.h (working copy) @@ -193,6 +193,8 @@ #define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) #define I830_FENCE_PITCH_SHIFT 4 #define I830_FENCE_REG_VALID (1<<0) +#define I830_FENCE_MAX_PITCH_VAL 0x10 +#define I830_FENCE_MAX_SIZE_VAL (1<<8) #define I915_FENCE_START_MASK 0x0ff00000 #define I915_FENCE_SIZE_BITS(size) ((ffs((size) >> 20) - 1) << 8) @@ -201,6 +203,7 @@ #define I965_FENCE_PITCH_SHIFT 2 #define I965_FENCE_TILING_Y_SHIFT 1 #define I965_FENCE_REG_VALID (1<<0) +#define I965_FENCE_MAX_PITCH_VAL 0x0400 /* * Instruction and interrupt control regs @@ -362,6 +365,7 @@ #define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */ #define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ #define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ +#define DPLL_FPA01_P1_POST_DIV_MASK_IGD 0x00ff8000 /* IGD */ #define I915_FIFO_UNDERRUN_STATUS (1UL<<31) #define I915_CRC_ERROR_ENABLE (1UL<<29) @@ -438,6 +442,7 @@ */ #define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000 #define DPLL_FPA01_P1_POST_DIV_SHIFT 16 +#define DPLL_FPA01_P1_POST_DIV_SHIFT_IGD 15 /* i830, required in DVO non-gang */ #define PLL_P2_DIVIDE_BY_4 (1 << 23) #define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ @@ -504,10 +509,12 @@ #define FPB0 0x06048 #define FPB1 0x0604c #define FP_N_DIV_MASK 0x003f0000 +#define FP_N_IGD_DIV_MASK 0x00ff0000 #define FP_N_DIV_SHIFT 16 #define FP_M1_DIV_MASK 0x00003f00 #define FP_M1_DIV_SHIFT 8 #define FP_M2_DIV_MASK 0x0000003f +#define FP_M2_IGD_DIV_MASK 0x000000ff #define FP_M2_DIV_SHIFT 0 #define DPLL_TEST 0x606c #define DPLLB_TEST_SDVO_DIV_1 (0 << 22) @@ -632,7 +639,31 @@ #define TV_HOTPLUG_INT_EN (1 << 18) #define CRT_HOTPLUG_INT_EN (1 << 9) #define CRT_HOTPLUG_FORCE_DETECT (1 << 3) +#define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8) +/* must use period 64 on GM45 according to docs */ +#define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8) +#define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7) +#define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5) +#define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4) +#define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4) +#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2) +#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) +#define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */ +#define CRT_FORCE_HOTPLUG_MASK 0xfffffe1f +#define HOTPLUG_EN_MASK (HDMIB_HOTPLUG_INT_EN | \ + HDMIC_HOTPLUG_INT_EN | \ + HDMID_HOTPLUG_INT_EN | \ + SDVOB_HOTPLUG_INT_EN | \ + SDVOC_HOTPLUG_INT_EN | \ + TV_HOTPLUG_INT_EN | \ + CRT_HOTPLUG_INT_EN) + #define PORT_HOTPLUG_STAT 0x61114 #define HDMIB_HOTPLUG_INT_STATUS (1 << 29) #define HDMIC_HOTPLUG_INT_STATUS (1 << 28) @@ -859,7 +890,7 @@ */ # define TV_ENC_C0_FIX (1 << 10) /** Bits that must be preserved by software */ -# define TV_CTL_SAVE ((3 << 8) | (3 << 6)) +# define TV_CTL_SAVE ((1 << 11) | (3 << 9) | (7 << 6) | 0xf) # define TV_FUSE_STATE_MASK (3 << 4) /** Read-only state that reports all features enabled */ # define TV_FUSE_STATE_ENABLED (0 << 4) Index: dev/drm/drmP.h =================================================================== --- dev/drm/drmP.h (revision 193732) +++ dev/drm/drmP.h (working copy) @@ -791,10 +791,8 @@ /* IRQ support (drm_irq.c) */ int drm_irq_install(struct drm_device *dev); int drm_irq_uninstall(struct drm_device *dev); -irqreturn_t drm_irq_handler(DRM_IRQ_ARGS); -void drm_driver_irq_preinstall(struct drm_device *dev); -void drm_driver_irq_postinstall(struct drm_device *dev); -void drm_driver_irq_uninstall(struct drm_device *dev); +int drm_irq_setup(struct drm_device *dev); +int drm_irq_teardown(struct drm_device *dev); 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); Index: dev/drm/drm_drv.c =================================================================== --- dev/drm/drm_drv.c (revision 193732) +++ dev/drm/drm_drv.c (working copy) @@ -201,14 +201,8 @@ unit = device_get_unit(kdev); dev = device_get_softc(kdev); -#if __FreeBSD_version < 700010 - if (!strcmp(device_get_name(kdev), "drmsub")) - dev->device = device_get_parent(kdev); - else - dev->device = kdev; -#else dev->device = kdev; -#endif + dev->devnode = make_dev(&drm_cdevsw, unit, DRM_DEV_UID, @@ -216,17 +210,13 @@ DRM_DEV_MODE, "dri/card%d", unit); -#if __FreeBSD_version >= 700053 - dev->pci_domain = pci_get_domain(dev->device); -#else - dev->pci_domain = 0; -#endif - dev->pci_bus = pci_get_bus(dev->device); - dev->pci_slot = pci_get_slot(dev->device); - dev->pci_func = pci_get_function(dev->device); + dev->pci_domain = pci_get_domain(kdev); + dev->pci_bus = pci_get_bus(kdev); + dev->pci_slot = pci_get_slot(kdev); + dev->pci_func = pci_get_function(kdev); - dev->pci_vendor = pci_get_vendor(dev->device); - dev->pci_device = pci_get_device(dev->device); + dev->pci_vendor = pci_get_vendor(kdev); + dev->pci_device = pci_get_device(kdev); if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) { if (drm_msi && @@ -245,7 +235,7 @@ } dev->irqr = bus_alloc_resource_any(dev->device, SYS_RES_IRQ, - &dev->irqrid, RF_SHAREABLE); + &dev->irqrid, RF_ACTIVE | RF_SHAREABLE); if (!dev->irqr) { return ENOENT; } @@ -253,15 +243,15 @@ dev->irq = (int) rman_get_start(dev->irqr); } + id_entry = drm_find_description(dev->pci_vendor, + dev->pci_device, idlist); + dev->id_entry = id_entry; + mtx_init(&dev->dev_lock, "drmdev", NULL, MTX_DEF); mtx_init(&dev->irq_lock, "drmirq", NULL, MTX_DEF); mtx_init(&dev->vbl_lock, "drmvbl", NULL, MTX_DEF); mtx_init(&dev->drw_lock, "drmdrw", NULL, MTX_DEF); - id_entry = drm_find_description(dev->pci_vendor, - dev->pci_device, idlist); - dev->id_entry = id_entry; - return drm_load(dev); } @@ -273,11 +263,14 @@ drm_unload(dev); - bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, dev->irqr); + if (dev->irqr) { + bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, + dev->irqr); - if (dev->msi_enabled) { - pci_release_msi(dev->device); - DRM_INFO("MSI released\n"); + if (dev->msi_enabled) { + pci_release_msi(dev->device); + DRM_INFO("MSI released\n"); + } } return 0; @@ -334,7 +327,6 @@ } dev->lock.lock_queue = 0; - dev->irq_enabled = 0; dev->context_flag = 0; dev->last_context = 0; dev->if_version = 0; @@ -359,9 +351,6 @@ if (dev->driver->lastclose != NULL) dev->driver->lastclose(dev); - if (dev->irq_enabled) - drm_irq_uninstall(dev); - if (dev->unique) { free(dev->unique, DRM_MEM_DRIVER); dev->unique = NULL; @@ -446,13 +435,15 @@ for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++) atomic_set(&dev->counts[i], 0); + /* Enable busmastering */ + if (pci_enable_busmaster(dev->device)) + DRM_ERROR("Request to enable bus-master failed.\n"); + if (dev->driver->load != NULL) { DRM_LOCK(); /* Shared code returns -errno. */ retcode = -dev->driver->load(dev, dev->id_entry->driver_private); - if (pci_enable_busmaster(dev->device)) - DRM_ERROR("Request to enable bus-master failed.\n"); DRM_UNLOCK(); if (retcode != 0) goto error; @@ -530,12 +521,21 @@ DRM_DEBUG("mtrr_del = %d", retcode); } - drm_vblank_cleanup(dev); - DRM_LOCK(); drm_lastclose(dev); DRM_UNLOCK(); + if (dev->driver->unload != NULL) { + DRM_LOCK(); + dev->driver->unload(dev); + DRM_UNLOCK(); + } + + drm_vblank_cleanup(dev); + + if (pci_disable_busmaster(dev->device)) + DRM_ERROR("pci_disable_busmaster failed!\n"); + /* Clean up PCI resources allocated by drm_bufs.c. We're not really * worried about resource consumption while the DRM is inactive (between * lastclose and firstopen or unload) because these aren't actually @@ -554,19 +554,10 @@ dev->agp = NULL; } - if (dev->driver->unload != NULL) { - DRM_LOCK(); - dev->driver->unload(dev); - DRM_UNLOCK(); - } - delete_unrhdr(dev->drw_unrhdr); drm_mem_uninit(); - if (pci_disable_busmaster(dev->device)) - DRM_ERROR("Request to disable bus-master failed.\n"); - mtx_destroy(&dev->drw_lock); mtx_destroy(&dev->vbl_lock); mtx_destroy(&dev->irq_lock); Index: dev/drm/i915_drv.c =================================================================== --- dev/drm/i915_drv.c (revision 193732) +++ dev/drm/i915_drv.c (working copy) @@ -52,7 +52,10 @@ return -ENODEV; } + DRM_LOCK(); + DRM_DEBUG("starting suspend\n"); i915_save_state(dev); + DRM_UNLOCK(); return (bus_generic_suspend(kdev)); } @@ -61,7 +64,10 @@ { struct drm_device *dev = device_get_softc(kdev); + DRM_LOCK(); + DRM_DEBUG("starting resume\n"); i915_restore_state(dev); + DRM_UNLOCK(); return (bus_generic_resume(kdev)); } Index: dev/drm/i915_drv.h =================================================================== --- dev/drm/i915_drv.h (revision 193732) +++ dev/drm/i915_drv.h (working copy) @@ -105,11 +105,22 @@ int enabled; }; +struct drm_i915_master_private { + drm_local_map_t *sarea; + struct _drm_i915_sarea *sarea_priv; +}; +#define I915_FENCE_REG_NONE -1 + +struct drm_i915_fence_reg { + struct drm_gem_object *obj; +}; + typedef struct drm_i915_private { struct drm_device *dev; drm_local_map_t *sarea; drm_local_map_t *mmio_map; + int has_gem; drm_i915_sarea_t *sarea_priv; drm_i915_ring_buffer_t ring; @@ -129,12 +140,11 @@ int page_flipping; wait_queue_head_t irq_queue; - atomic_t irq_received; /** Protects user_irq_refcount and irq_mask_reg */ DRM_SPINTYPE user_irq_lock; /** Refcount for i915_user_irq_get() versus i915_user_irq_put(). */ int user_irq_refcount; - /** Cached value of IER to avoid reads in updating the bitfield */ + /** Cached value of IMR to avoid reads in updating the bitfield */ u32 irq_mask_reg; u32 pipestat[2]; @@ -143,9 +153,15 @@ struct mem_block *agp_heap; unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; int vblank_pipe; + u32 vblank_status; + u32 vblank_enable; struct intel_opregion opregion; + struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */ + int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ + int num_fence_regs; /* 8 on pre-965, 16 otherwise */ + /* Register state */ u8 saveLBB; u32 saveDSPACNTR; @@ -353,7 +369,8 @@ /** AGP memory structure for our GTT binding. */ DRM_AGP_MEM *agp_mem; - struct page **page_list; + struct page **pages; + int pages_refcount; /** * Current offset of the object in GTT space. @@ -361,7 +378,22 @@ * This is the same as gtt_space->start */ uint32_t gtt_offset; + /** + * Required alignment for the object + */ + uint32_t gtt_alignment; + /** + * Fake offset for use by mmap(2) + */ + uint64_t mmap_offset; + /** + * Fence register bits (if any) for this object. Will be set + * as needed when mapped into the GTT. + * Protected by dev->struct_mutex. + */ + int fence_reg; + /** Boolean whether this object has a valid gtt offset. */ int gtt_bound; @@ -373,6 +405,7 @@ /** Current tiling mode for the object. */ uint32_t tiling_mode; + uint32_t stride; /** AGP mapping type (AGP_USER_MEMORY or AGP_USER_CACHED_MEMORY */ uint32_t agp_type; @@ -453,7 +486,7 @@ extern int i915_enable_vblank(struct drm_device *dev, int crtc); extern void i915_disable_vblank(struct drm_device *dev, int crtc); extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc); -extern u32 gm45_get_vblank_counter(struct drm_device *dev, int crtc); +extern u32 g45_get_vblank_counter(struct drm_device *dev, int crtc); extern int i915_vblank_swap(struct drm_device *dev, void *data, struct drm_file *file_priv); Index: dev/drm/drm_memory.c =================================================================== --- dev/drm/drm_memory.c (revision 193732) +++ dev/drm/drm_memory.c (working copy) @@ -87,6 +87,7 @@ int drm_mtrr_add(unsigned long offset, size_t size, int flags) { +#if 1 int act; struct mem_range_desc mrdesc; @@ -96,11 +97,18 @@ act = MEMRANGE_SET_UPDATE; strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner)); return mem_range_attr_set(&mrdesc, &act); +#else + if (flags == DRM_MTRR_WC) + return pmap_change_attr(offset, size, PAT_WRITE_COMBINING); + else + return EINVAL; +#endif } int drm_mtrr_del(int __unused handle, unsigned long offset, size_t size, int flags) { +#if 1 int act; struct mem_range_desc mrdesc; @@ -110,4 +118,7 @@ act = MEMRANGE_SET_REMOVE; strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner)); return mem_range_attr_set(&mrdesc, &act); +#else + return pmap_change_attr(offset, size, PAT_WRITE_BACK); +#endif } Index: dev/drm/mga_irq.c =================================================================== --- dev/drm/mga_irq.c (revision 193732) +++ dev/drm/mga_irq.c (working copy) @@ -178,6 +178,4 @@ /* Disable *all* interrupts */ MGA_WRITE(MGA_IEN, 0); - - dev->irq_enabled = 0; } Index: dev/drm/radeon_irq.c =================================================================== --- dev/drm/radeon_irq.c (revision 193732) +++ dev/drm/radeon_irq.c (working copy) @@ -380,8 +380,6 @@ atomic_set(&dev_priv->swi_emitted, 0); DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); - dev->max_vblank_count = 0x001fffff; - radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); return 0; @@ -394,8 +392,6 @@ if (!dev_priv) return; - dev_priv->irq_enabled = 0; - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) RADEON_WRITE(R500_DxMODE_INT_MASK, 0); /* Disable *all* interrupts */ Index: dev/drm/drm_sysctl.c =================================================================== --- dev/drm/drm_sysctl.c (revision 193732) +++ dev/drm/drm_sysctl.c (working copy) @@ -38,6 +38,7 @@ static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS; static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS; static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS; +static int drm_vblank_info DRM_SYSCTL_HANDLER_ARGS; struct drm_sysctl_list { const char *name; @@ -47,6 +48,7 @@ {"vm", drm_vm_info}, {"clients", drm_clients_info}, {"bufs", drm_bufs_info}, + {"vblank", drm_vblank_info}, }; #define DRM_SYSCTL_ENTRIES (sizeof(drm_sysctl_list)/sizeof(drm_sysctl_list[0])) @@ -313,3 +315,25 @@ free(tempprivs, DRM_MEM_DRIVER); return retcode; } + +static int drm_vblank_info DRM_SYSCTL_HANDLER_ARGS +{ + struct drm_device *dev = arg1; + char buf[128]; + int retcode; + int i; + + DRM_SYSCTL_PRINT("\ncrtc ref count last enabled inmodeset\n"); + for(i = 0 ; i < dev->num_crtcs ; i++) { + DRM_SYSCTL_PRINT(" %02d %02d %08d %08d %02d %02d\n", + i, atomic_load_acq_32(&dev->vblank[i].refcount), + atomic_load_acq_32(&dev->vblank[i].count), + atomic_load_acq_32(&dev->vblank[i].last), + atomic_load_acq_int(&dev->vblank[i].enabled), + atomic_load_acq_int(&dev->vblank[i].inmodeset)); + } + + SYSCTL_OUT(req, "", -1); +done: + return retcode; +} Index: dev/drm/drm_context.c =================================================================== --- dev/drm/drm_context.c (revision 193732) +++ dev/drm/drm_context.c (working copy) @@ -80,7 +80,7 @@ ctx_sareas = realloc(dev->context_sareas, dev->max_context * sizeof(*dev->context_sareas), - DRM_MEM_SAREA, M_NOWAIT); + DRM_MEM_SAREA, M_NOWAIT | M_ZERO); if (ctx_sareas == NULL) { clear_bit(bit, dev->ctx_bitmap); DRM_UNLOCK(); @@ -92,7 +92,7 @@ /* max_context == 1 at this point */ dev->context_sareas = malloc(dev->max_context * sizeof(*dev->context_sareas), DRM_MEM_SAREA, - M_NOWAIT); + M_NOWAIT | M_ZERO); if (dev->context_sareas == NULL) { clear_bit(bit, dev->ctx_bitmap); DRM_UNLOCK();