From patchwork Thu Jun 23 22:49:14 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Widawsky X-Patchwork-Id: 914532 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p5NMneXH023186 for ; Thu, 23 Jun 2011 22:50:01 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 55613A02C6 for ; Thu, 23 Jun 2011 15:49:39 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from cloud01.chad-versace.us (184-106-247-128.static.cloud-ips.com [184.106.247.128]) by gabe.freedesktop.org (Postfix) with ESMTP id 7EB6D9E7D0 for ; Thu, 23 Jun 2011 15:49:17 -0700 (PDT) Received: from localhost.localdomain (jfdmzpr06-ext.jf.intel.com [134.134.137.75]) by cloud01.chad-versace.us (Postfix) with ESMTPSA id 4C5EB1D41C1; Thu, 23 Jun 2011 22:51:22 +0000 (UTC) From: Ben Widawsky To: intel-gfx@lists.freedesktop.org Date: Thu, 23 Jun 2011 15:49:14 -0700 Message-Id: <1308869354-3145-1-git-send-email-ben@bwidawsk.net> X-Mailer: git-send-email 1.7.5.2 Subject: [Intel-gfx] [PATCH] drm/i915: hangcheck timeout for debugfs X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Thu, 23 Jun 2011 22:50:02 +0000 (UTC) Provide a user accessible way to change the hangcheck timer. This is useful mostly for disabling the timer completely (value <= 0). Signed-off-by: Ben Widawsky Cc: Keith Packard --- drivers/gpu/drm/i915/i915_debugfs.c | 88 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_dma.c | 1 + drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 7 ++- drivers/gpu/drm/i915/i915_irq.c | 17 +++++-- 5 files changed, 107 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 4d46441..b6582de 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1395,6 +1395,88 @@ static int i915_forcewake_create(struct dentry *root, struct drm_minor *minor) return drm_add_fake_info_node(minor, ent, &i915_forcewake_fops); } +static int i915_hangcheck_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t i915_hangcheck_read(struct file *filp, + char __user *ubuf, + size_t max, + loff_t *ppos) +{ + struct drm_device *dev = filp->private_data; + drm_i915_private_t *dev_priv = dev->dev_private; + char buf[7]; + int len, timeout; + + timeout = atomic_read(&dev_priv->hangcheck_timeout); + len = snprintf(buf, sizeof(buf), "%d\n", timeout); + + return simple_read_from_buffer(ubuf, max, ppos, buf, len); +} + +static ssize_t i915_hangcheck_write(struct file *filp, + const char __user *ubuf, + size_t cnt, + loff_t *ppos) +{ + struct drm_device *dev = filp->private_data; + drm_i915_private_t *dev_priv = dev->dev_private; + char buf[7]; /* 99.9 seconds max */ + int new_timeout = 0; + int ret; + + if (cnt > 0) { + if (cnt > sizeof (buf) - 1) + return -EINVAL; + + if (copy_from_user(buf, ubuf, cnt)) + return -EFAULT; + buf[cnt] = 0; + + new_timeout = simple_strtol(buf, NULL, 0); + } + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; + + if (new_timeout <= 0) { + new_timeout = 0; + del_timer_sync(&dev_priv->hangcheck_timer); + } + + atomic_set(&dev_priv->hangcheck_timeout, new_timeout); + + mutex_unlock(&dev->struct_mutex); + + return cnt; +} + +static const struct file_operations i915_hangcheck_fops = { + .owner = THIS_MODULE, + .open = i915_hangcheck_open, + .read = i915_hangcheck_read, + .write = i915_hangcheck_write, +}; + +static int i915_hangcheck_create(struct dentry *root, struct drm_minor *minor) +{ + struct drm_device *dev = minor->dev; + struct dentry *ent; + + ent = debugfs_create_file("i915_hangcheck_timeout", + S_IRUGO | S_IWUSR, + root, dev, + &i915_hangcheck_fops); + if (IS_ERR(ent)) + return PTR_ERR(ent); + + return drm_add_fake_info_node(minor, ent, &i915_hangcheck_fops); +} + static struct drm_info_list i915_debugfs_list[] = { {"i915_capabilities", i915_capabilities, 0}, {"i915_gem_objects", i915_gem_object_info, 0}, @@ -1448,6 +1530,10 @@ int i915_debugfs_init(struct drm_minor *minor) if (ret) return ret; + ret = i915_hangcheck_create(minor->debugfs_root, minor); + if (ret) + return ret; + return drm_debugfs_create_files(i915_debugfs_list, I915_DEBUGFS_ENTRIES, minor->debugfs_root, minor); @@ -1457,6 +1543,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor) { drm_debugfs_remove_files(i915_debugfs_list, I915_DEBUGFS_ENTRIES, minor); + drm_debugfs_remove_files((struct drm_info_list *) &i915_hangcheck_fops, + 1, minor); drm_debugfs_remove_files((struct drm_info_list *) &i915_forcewake_fops, 1, minor); drm_debugfs_remove_files((struct drm_info_list *) &i915_wedged_fops, diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 0239e99..e44a4a6 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -2092,6 +2092,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, (unsigned long) dev); + atomic_set(&dev_priv->hangcheck_timeout, DRM_I915_HANGCHECK_PERIOD); spin_lock(&mchdev_lock); i915_mch_dev = dev_priv; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8a9fd91..f518e76 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -320,6 +320,7 @@ typedef struct drm_i915_private { #define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */ struct timer_list hangcheck_timer; int hangcheck_count; + atomic_t hangcheck_timeout; uint32_t last_acthd; uint32_t last_instdone; uint32_t last_instdone1; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index cb1f61d..48b140e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1777,8 +1777,11 @@ i915_add_request(struct intel_ring_buffer *ring, ring->outstanding_lazy_request = false; if (!dev_priv->mm.suspended) { - mod_timer(&dev_priv->hangcheck_timer, - jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); + int timeout = atomic_read(&dev_priv->hangcheck_timeout); + if (timeout) { + mod_timer(&dev_priv->hangcheck_timer, jiffies + + msecs_to_jiffies(timeout)); + } if (was_empty) queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b9fafe3..20316d3 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -352,6 +352,7 @@ static void notify_ring(struct drm_device *dev, { struct drm_i915_private *dev_priv = dev->dev_private; u32 seqno; + int timeout; if (ring->obj == NULL) return; @@ -362,9 +363,12 @@ static void notify_ring(struct drm_device *dev, ring->irq_seqno = seqno; wake_up_all(&ring->irq_queue); - dev_priv->hangcheck_count = 0; - mod_timer(&dev_priv->hangcheck_timer, - jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); + timeout = atomic_read(&dev_priv->hangcheck_timeout); + if (timeout) { + dev_priv->hangcheck_count = 0; + mod_timer(&dev_priv->hangcheck_timer, jiffies + + msecs_to_jiffies(timeout)); + } } static void gen6_pm_rps_work(struct work_struct *work) @@ -1721,9 +1725,12 @@ void i915_hangcheck_elapsed(unsigned long data) } repeat: + /* should never be 0, we should drain the timer before setting * to 0 */ + WARN_ON(atomic_read(&dev_priv->hangcheck_timeout) == 0); + /* Reset timer case chip hangs without another request being added */ - mod_timer(&dev_priv->hangcheck_timer, - jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); + mod_timer(&dev_priv->hangcheck_timer, jiffies + + msecs_to_jiffies(atomic_read(&dev_priv->hangcheck_timeout)); } /* drm_dma.h hooks