From patchwork Fri Apr 8 17:47:29 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Widawsky X-Patchwork-Id: 695351 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p38HnbDL023979 for ; Fri, 8 Apr 2011 17:49:57 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 355DF9F369 for ; Fri, 8 Apr 2011 10:49:37 -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 299DA9E9C6 for ; Fri, 8 Apr 2011 10:47:58 -0700 (PDT) Received: from localhost.localdomain (fruit.freedesktop.org [131.252.210.190]) by cloud01.chad-versace.us (Postfix) with ESMTPSA id B3F6C1D406B; Fri, 8 Apr 2011 17:48:48 +0000 (UTC) From: Ben Widawsky To: intel-gfx@lists.freedesktop.org Date: Fri, 8 Apr 2011 10:47:29 -0700 Message-Id: <1302284850-8274-4-git-send-email-ben@bwidawsk.net> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: <1302284850-8274-1-git-send-email-ben@bwidawsk.net> References: <1302284850-8274-1-git-send-email-ben@bwidawsk.net> Subject: [Intel-gfx] [PATCH 3/4] drm/i915: userspace interface to the forcewake refcount 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]); Fri, 08 Apr 2011 17:49:57 +0000 (UTC) In the simple case, all that needs to happen is grab the lock, possibly wake the GPU and bump the refcount. In the not simple case, we close our eyes and hope for the best (but we only do it one at a time). Signed-off-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_debugfs.c | 99 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_drv.c | 12 ++++- drivers/gpu/drm/i915/i915_drv.h | 1 + 3 files changed, 110 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6eee101..286896e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1193,6 +1193,19 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) return 0; } +static int i915_gen6_forcewake_count_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + seq_printf(m, "forcewake count = %d\n", dev_priv->forcewake_count); + seq_printf(m, "forcewake forced = %d\n", + atomic_read(&dev_priv->forcewake_force)); + + return 0; +} + static int i915_wedged_open(struct inode *inode, struct file *filp) @@ -1295,6 +1308,85 @@ static int i915_wedged_create(struct dentry *root, struct drm_minor *minor) return drm_add_fake_info_node(minor, ent, &i915_wedged_fops); } +static int i915_forcewake_open(struct inode *inode, struct file *file) +{ + struct drm_device *dev = inode->i_private; + struct drm_i915_private *dev_priv = dev->dev_private; + int ret; + bool locked; + + if (!IS_GEN6(dev)) + return 0; + + ret = i915_mutex_lock_interruptible(dev); + locked = (ret == 0) ? true : false; + + if (!locked) { + /* + * Only let one user violently forcewake, else it gets messy, + * that user must be responsible for cleanup as well. Store + * away current for later cleanup. + */ + if (atomic_cmpxchg(&dev_priv->forcewake_force, 0, 1) != 0) + return -EBUSY; + file->private_data = current; + } + + /* We either have the lock, or we've set forcewake */ + gen6_gt_force_wake_get(dev_priv); + + if (locked) { + atomic_set(&dev_priv->forcewake_force, 0); + mutex_unlock(&dev->struct_mutex); + } + + return 0; +} + +int i915_forcewake_release(struct inode *inode, struct file *file) +{ + struct drm_device *dev = inode->i_private; + struct drm_i915_private *dev_priv = dev->dev_private; + + if (!IS_GEN6(dev)) + return 0; + + /* more ugliness as a result of force */ + if (file->private_data == current) { + WARN_ON(!atomic_read(&dev_priv->forcewake_force)); + WARN_ON(i915_mutex_lock_interruptible(dev)); + gen6_gt_force_wake_put(dev_priv); + atomic_set(&dev_priv->forcewake_force, 0); + } else { + mutex_lock(&dev->struct_mutex); + gen6_gt_force_wake_put(dev_priv); + atomic_set(&dev_priv->forcewake_force, 0); + mutex_unlock(&dev->struct_mutex); + } + return 0; +} + +static const struct file_operations i915_forcewake_fops = { + .owner = THIS_MODULE, + .open = i915_forcewake_open, + .release = i915_forcewake_release, +}; + +static int i915_forcewake_create(struct dentry *root, struct drm_minor *minor) +{ + struct drm_device *dev = minor->dev; + struct dentry *ent; + + ent = debugfs_create_file("i915_forcewake_lock", + S_IRWXU, + root, dev, + &i915_forcewake_fops); + if (IS_ERR(ent)) + return PTR_ERR(ent); + + return 0; +} + static struct drm_info_list i915_debugfs_list[] = { {"i915_capabilities", i915_capabilities, 0}, {"i915_gem_objects", i915_gem_object_info, 0}, @@ -1331,6 +1423,7 @@ static struct drm_info_list i915_debugfs_list[] = { {"i915_sr_status", i915_sr_status, 0}, {"i915_opregion", i915_opregion, 0}, {"i915_gem_framebuffer", i915_gem_framebuffer_info, 0}, + {"i915_gen6_forcewake_count", i915_gen6_forcewake_count_info, 0}, }; #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) @@ -1342,6 +1435,10 @@ int i915_debugfs_init(struct drm_minor *minor) if (ret) return ret; + ret = i915_forcewake_create(minor->debugfs_root, minor); + if (ret) + return ret; + return drm_debugfs_create_files(i915_debugfs_list, I915_DEBUGFS_ENTRIES, minor->debugfs_root, minor); @@ -1351,6 +1448,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_forcewake_fops, + 1, minor); drm_debugfs_remove_files((struct drm_info_list *) &i915_wedged_fops, 1, minor); } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ce59cd4..fcd5c9a 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -281,7 +281,14 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) { - WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); + /* + * It takes a long time to wake, but the count is incremented + * immediately. Not having the lock causes a race, but all bets are off + * when using forced forcewake, which should only be touched through + * root-only entry in debugfs. + */ + WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex) && + !atomic_read(&dev_priv->forcewake_force)); if (dev_priv->forcewake_count++ == 0) __gen6_gt_force_wake_get(dev_priv); @@ -295,7 +302,8 @@ static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) { - WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); + WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex) && + !atomic_read(&dev_priv->forcewake_force)); if (--dev_priv->forcewake_count == 0) __gen6_gt_force_wake_put(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f024927..f1c8a70 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -705,6 +705,7 @@ typedef struct drm_i915_private { struct drm_property *broadcast_rgb_property; int forcewake_count; + atomic_t forcewake_force; } drm_i915_private_t; struct drm_i915_gem_object {