From owner-svn-src-head@FreeBSD.ORG Wed Mar 25 01:50:56 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5AE841065670; Wed, 25 Mar 2009 01:50:56 +0000 (UTC) (envelope-from rnoland@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 48C8F8FC16; Wed, 25 Mar 2009 01:50:56 +0000 (UTC) (envelope-from rnoland@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n2P1ouvH062377; Wed, 25 Mar 2009 01:50:56 GMT (envelope-from rnoland@svn.freebsd.org) Received: (from rnoland@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n2P1ou4g062376; Wed, 25 Mar 2009 01:50:56 GMT (envelope-from rnoland@svn.freebsd.org) Message-Id: <200903250150.n2P1ou4g062376@svn.freebsd.org> From: Robert Noland Date: Wed, 25 Mar 2009 01:50:56 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r190401 - head/sys/dev/drm X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 25 Mar 2009 01:50:56 -0000 Author: rnoland Date: Wed Mar 25 01:50:56 2009 New Revision: 190401 URL: http://svn.freebsd.org/changeset/base/190401 Log: Rework the management of vblank interrupts a bit. When a vt switch occurs the irq handler is uninstalled. Interrupts and the state tracking of what was enabled/disabled wasn't working properly. This should resolve the reports of "slow windows" after a vt switch, among other things. The radeon 2d driver seems to work a bit more correctly than the Intel driver. With the Intel driver, vblank interrupts will be enabled at system startup and will only be disabled after an additional modeset (vt switch, dpms, randr event). With this patch, I am able to run glxgears synced to vblank and vt switch while it is running without ill effects. MFC after: 3 days Modified: head/sys/dev/drm/drm_irq.c Modified: head/sys/dev/drm/drm_irq.c ============================================================================== --- head/sys/dev/drm/drm_irq.c Wed Mar 25 01:44:16 2009 (r190400) +++ head/sys/dev/drm/drm_irq.c Wed Mar 25 01:50:56 2009 (r190401) @@ -80,13 +80,14 @@ static void vblank_disable_fn(void *arg) } callout_deactivate(&dev->vblank_disable_timer); - DRM_DEBUG("vblank_disable_allowed=%d\n", dev->vblank_disable_allowed); + DRM_DEBUG("vblank_disable: %s\n", dev->vblank_disable_allowed ? + "allowed" : "denied"); if (!dev->vblank_disable_allowed) return; for (i = 0; i < dev->num_crtcs; i++) { if (atomic_read(&dev->vblank[i].refcount) == 0 && - dev->vblank[i].enabled) { + dev->vblank[i].enabled && !dev->vblank[i].inmodeset) { DRM_DEBUG("disabling vblank on crtc %d\n", i); dev->vblank[i].last = dev->driver->get_vblank_counter(dev, i); @@ -149,7 +150,7 @@ err: int drm_irq_install(struct drm_device *dev) { - int retcode; + int crtc, retcode; if (dev->irq == 0 || dev->dev_private == NULL) return EINVAL; @@ -186,6 +187,17 @@ int drm_irq_install(struct drm_device *d DRM_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); + } return 0; err: @@ -212,9 +224,9 @@ int drm_irq_uninstall(struct drm_device for (crtc = 0; crtc < dev->num_crtcs; crtc++) { if (dev->vblank[crtc].enabled) { DRM_WAKEUP(&dev->vblank[crtc].queue); - dev->vblank[crtc].enabled = 0; dev->vblank[crtc].last = - dev->driver->get_vblank_counter(dev, crtc); + dev->driver->get_vblank_counter(dev, crtc); + dev->vblank[crtc].enabled = 0; } } DRM_SPINUNLOCK(&dev->vbl_lock); @@ -320,9 +332,11 @@ void drm_vblank_put(struct drm_device *d /* 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) 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, @@ -449,31 +463,26 @@ int drm_wait_vblank(struct drm_device *d } else { DRM_DEBUG("waiting on vblank count %d, crtc %d\n", vblwait->request.sequence, crtc); - for ( ret = 0 ; !ret && !((drm_vblank_count(dev, crtc) - - vblwait->request.sequence) <= (1 << 23)) ; ) { - mtx_lock(&dev->irq_lock); - if (!((drm_vblank_count(dev, crtc) - - vblwait->request.sequence) <= (1 << 23))) - ret = mtx_sleep(&dev->vblank[crtc].queue, - &dev->irq_lock, PCATCH, "vblwtq", - 3 * DRM_HZ); - mtx_unlock(&dev->irq_lock); - } - - if (ret == ERESTART) { - DRM_DEBUG("restarting syscall\n"); - return ret; + mtx_lock(&dev->irq_lock); + dev->vblank[crtc].last = vblwait->request.sequence; + for ( ret = 0 ; !ret && !(((drm_vblank_count(dev, crtc) - + vblwait->request.sequence) <= (1 << 23)) || + !dev->irq_enabled) ; ) { + ret = mtx_sleep(&dev->vblank[crtc].queue, + &dev->irq_lock, PCATCH, "vblwtq", + 3 * DRM_HZ); } + mtx_unlock(&dev->irq_lock); - if (ret != EINTR) { + if (ret != EINTR && ret != ERESTART) { struct timeval now; microtime(&now); vblwait->reply.tval_sec = now.tv_sec; vblwait->reply.tval_usec = now.tv_usec; vblwait->reply.sequence = drm_vblank_count(dev, crtc); - DRM_DEBUG("returning %d to client\n", - vblwait->reply.sequence); + DRM_DEBUG("returning %d to client, irq_enabled %d\n", + vblwait->reply.sequence, dev->irq_enabled); } else { DRM_DEBUG("vblank wait interrupted by signal\n"); }