From patchwork Mon Mar 6 16:31:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 13161750 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 49527C64EC4 for ; Mon, 6 Mar 2023 16:32:33 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 6CE8410E2F1; Mon, 6 Mar 2023 16:32:28 +0000 (UTC) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by gabe.freedesktop.org (Postfix) with ESMTPS id 6658210E2F1; Mon, 6 Mar 2023 16:32:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678120346; x=1709656346; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=XCsSIC3ScIVlFqqz1tOQmvQAk4siU7dIf3EqDWAqQeU=; b=hf4RVTJ4AhuziPMmURz0wqU7IBDlHX/iQbElOClEdT6C0SpQ6z/v1Zz1 9xS/QmOezk4UFm28Ckc46JJUpSfOeKryZ9vi4FEoGm2imAZ+IlEbF/ZMG Ye1VoZsnxVidpwwmzA20AVmppCiff43o2U8FgPGyvm71AdwDJumrpY9Fs R9IQWkiI9tIMxYfx8GUjs1k6rqpBUiL0Nfz4LZyagBUk4xEbUsI7rz7cI T07Gf8YEL017ETjboNAWS5YRUGiVR0PAM9HXbcryQ66qB/Sx5dSXgThHN z/G4HLw+lLV4eHCB/gWZgzg3c982Cbc3D9IyV618Ttq2qIh/2APee8coV w==; X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="315998576" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="315998576" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:26 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="745132798" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="745132798" Received: from lab-ah.igk.intel.com ([10.102.42.211]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:23 -0800 From: Andrzej Hajda Date: Mon, 06 Mar 2023 17:31:57 +0100 MIME-Version: 1.0 Message-Id: <20230224-track_gt-v4-1-464e8ab4c9ab@intel.com> References: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> In-Reply-To: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> To: Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , Tvrtko Ursulin , David Airlie , Daniel Vetter X-Mailer: b4 0.11.1 Subject: [Intel-gfx] [PATCH v4 01/10] lib/ref_tracker: add unlocked leak print helper X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: netdev@vger.kernel.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Chris Wilson , Eric Dumazet , Chris Wilson , Andrzej Hajda , Jakub Kicinski , Dmitry Vyukov Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" To have reliable detection of leaks, caller must be able to check under the same lock both: tracked counter and the leaks. dir.lock is natural candidate for such lock and unlocked print helper can be called with this lock taken. As a bonus we can reuse this helper in ref_tracker_dir_exit. Signed-off-by: Andrzej Hajda --- include/linux/ref_tracker.h | 8 ++++++ lib/ref_tracker.c | 66 ++++++++++++++++++++++++++------------------- 2 files changed, 46 insertions(+), 28 deletions(-) diff --git a/include/linux/ref_tracker.h b/include/linux/ref_tracker.h index 9ca353ab712b5e..3e9e9df2a41f5f 100644 --- a/include/linux/ref_tracker.h +++ b/include/linux/ref_tracker.h @@ -36,6 +36,9 @@ static inline void ref_tracker_dir_init(struct ref_tracker_dir *dir, void ref_tracker_dir_exit(struct ref_tracker_dir *dir); +void __ref_tracker_dir_print(struct ref_tracker_dir *dir, + unsigned int display_limit); + void ref_tracker_dir_print(struct ref_tracker_dir *dir, unsigned int display_limit); @@ -56,6 +59,11 @@ static inline void ref_tracker_dir_exit(struct ref_tracker_dir *dir) { } +static inline void __ref_tracker_dir_print(struct ref_tracker_dir *dir, + unsigned int display_limit) +{ +} + static inline void ref_tracker_dir_print(struct ref_tracker_dir *dir, unsigned int display_limit) { diff --git a/lib/ref_tracker.c b/lib/ref_tracker.c index dc7b14aa3431e2..5e9f90bbf771b0 100644 --- a/lib/ref_tracker.c +++ b/lib/ref_tracker.c @@ -14,6 +14,38 @@ struct ref_tracker { depot_stack_handle_t free_stack_handle; }; +void __ref_tracker_dir_print(struct ref_tracker_dir *dir, + unsigned int display_limit) +{ + struct ref_tracker *tracker; + unsigned int i = 0; + + lockdep_assert_held(&dir->lock); + + list_for_each_entry(tracker, &dir->list, head) { + if (i < display_limit) { + pr_err("leaked reference.\n"); + if (tracker->alloc_stack_handle) + stack_depot_print(tracker->alloc_stack_handle); + i++; + } else { + break; + } + } +} +EXPORT_SYMBOL(__ref_tracker_dir_print); + +void ref_tracker_dir_print(struct ref_tracker_dir *dir, + unsigned int display_limit) +{ + unsigned long flags; + + spin_lock_irqsave(&dir->lock, flags); + __ref_tracker_dir_print(dir, display_limit); + spin_unlock_irqrestore(&dir->lock, flags); +} +EXPORT_SYMBOL(ref_tracker_dir_print); + void ref_tracker_dir_exit(struct ref_tracker_dir *dir) { struct ref_tracker *tracker, *n; @@ -27,13 +59,13 @@ void ref_tracker_dir_exit(struct ref_tracker_dir *dir) kfree(tracker); dir->quarantine_avail++; } - list_for_each_entry_safe(tracker, n, &dir->list, head) { - pr_err("leaked reference.\n"); - if (tracker->alloc_stack_handle) - stack_depot_print(tracker->alloc_stack_handle); + if (!list_empty(&dir->list)) { + __ref_tracker_dir_print(dir, 16); leak = true; - list_del(&tracker->head); - kfree(tracker); + list_for_each_entry_safe(tracker, n, &dir->list, head) { + list_del(&tracker->head); + kfree(tracker); + } } spin_unlock_irqrestore(&dir->lock, flags); WARN_ON_ONCE(leak); @@ -42,28 +74,6 @@ void ref_tracker_dir_exit(struct ref_tracker_dir *dir) } EXPORT_SYMBOL(ref_tracker_dir_exit); -void ref_tracker_dir_print(struct ref_tracker_dir *dir, - unsigned int display_limit) -{ - struct ref_tracker *tracker; - unsigned long flags; - unsigned int i = 0; - - spin_lock_irqsave(&dir->lock, flags); - list_for_each_entry(tracker, &dir->list, head) { - if (i < display_limit) { - pr_err("leaked reference.\n"); - if (tracker->alloc_stack_handle) - stack_depot_print(tracker->alloc_stack_handle); - i++; - } else { - break; - } - } - spin_unlock_irqrestore(&dir->lock, flags); -} -EXPORT_SYMBOL(ref_tracker_dir_print); - int ref_tracker_alloc(struct ref_tracker_dir *dir, struct ref_tracker **trackerp, gfp_t gfp) From patchwork Mon Mar 6 16:31:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 13161751 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 98B76C64EC4 for ; Mon, 6 Mar 2023 16:32:37 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id BE65D10E3DE; Mon, 6 Mar 2023 16:32:31 +0000 (UTC) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by gabe.freedesktop.org (Postfix) with ESMTPS id 84D4810E3C8; Mon, 6 Mar 2023 16:32:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678120349; x=1709656349; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=PX8UQ6oITUhb4x6lXD3oy5zdW3SXv9aazhZK9zfdjvM=; b=RBix+PP/N0jvA4uxV0m+DYXAc8dxCwDjG0/CNg/qLi0OxDEGyfYqp0XC pcgUuIGe6f9uzKxccUkEXDn0WNy5PulOZJ+k0x93n/6mNpuwiwQ6zwUKP r2xvj3cToH97FVpVgCw6azBB801ShOnSmRAqxh1vfWpdiCQlZHLDoMzke 4MjxIFUqTQLccrm/z99tsGzStqHgC0GtOnRTN0fuTJGqYa4VRQoHEc9WS 97qWcP2mgIdGtJO0p5TgQi4sO2szm3xO61Pen1P3dn6vwMkxycZqYTSAK RMkrkoWdLEf75hSnW5ufiKZ6CDfFwcA5ocT2h6fmr2/o1242v4rtMlheH g==; X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="315998604" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="315998604" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:29 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="745132826" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="745132826" Received: from lab-ah.igk.intel.com ([10.102.42.211]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:26 -0800 From: Andrzej Hajda Date: Mon, 06 Mar 2023 17:31:58 +0100 MIME-Version: 1.0 Message-Id: <20230224-track_gt-v4-2-464e8ab4c9ab@intel.com> References: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> In-Reply-To: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> To: Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , Tvrtko Ursulin , David Airlie , Daniel Vetter X-Mailer: b4 0.11.1 Subject: [Intel-gfx] [PATCH v4 02/10] lib/ref_tracker: __ref_tracker_dir_print improve printing X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: netdev@vger.kernel.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Chris Wilson , Eric Dumazet , Chris Wilson , Andrzej Hajda , Jakub Kicinski , Dmitry Vyukov Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" To improve readability of ref_tracker printing following changes have been performed: - reports are printed per stack_handle - log is more compact, - added display name for ref_tracker_dir, - stack trace is printed indented, in the same printk call, - total number of references is printed every time, - print info about dropped references. Signed-off-by: Andrzej Hajda --- include/linux/ref_tracker.h | 15 ++++++-- lib/ref_tracker.c | 90 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 91 insertions(+), 14 deletions(-) diff --git a/include/linux/ref_tracker.h b/include/linux/ref_tracker.h index 3e9e9df2a41f5f..a2cf1f6309adb2 100644 --- a/include/linux/ref_tracker.h +++ b/include/linux/ref_tracker.h @@ -17,12 +17,19 @@ struct ref_tracker_dir { bool dead; struct list_head list; /* List of active trackers */ struct list_head quarantine; /* List of dead trackers */ + char name[32]; #endif }; #ifdef CONFIG_REF_TRACKER -static inline void ref_tracker_dir_init(struct ref_tracker_dir *dir, - unsigned int quarantine_count) + +// Temporary allow two and three arguments, until consumers are converted +#define ref_tracker_dir_init(_d, _q, args...) _ref_tracker_dir_init(_d, _q, ##args, #_d) +#define _ref_tracker_dir_init(_d, _q, _n, ...) __ref_tracker_dir_init(_d, _q, _n) + +static inline void __ref_tracker_dir_init(struct ref_tracker_dir *dir, + unsigned int quarantine_count, + const char *name) { INIT_LIST_HEAD(&dir->list); INIT_LIST_HEAD(&dir->quarantine); @@ -31,6 +38,7 @@ static inline void ref_tracker_dir_init(struct ref_tracker_dir *dir, dir->dead = false; refcount_set(&dir->untracked, 1); refcount_set(&dir->no_tracker, 1); + strlcpy(dir->name, name, sizeof(dir->name)); stack_depot_init(); } @@ -51,7 +59,8 @@ int ref_tracker_free(struct ref_tracker_dir *dir, #else /* CONFIG_REF_TRACKER */ static inline void ref_tracker_dir_init(struct ref_tracker_dir *dir, - unsigned int quarantine_count) + unsigned int quarantine_count, + ...) { } diff --git a/lib/ref_tracker.c b/lib/ref_tracker.c index 5e9f90bbf771b0..ab1253fde244ea 100644 --- a/lib/ref_tracker.c +++ b/lib/ref_tracker.c @@ -1,11 +1,16 @@ // SPDX-License-Identifier: GPL-2.0-or-later + +#define pr_fmt(fmt) "ref_tracker: " fmt + #include +#include #include #include #include #include #define REF_TRACKER_STACK_ENTRIES 16 +#define STACK_BUF_SIZE 1024 struct ref_tracker { struct list_head head; /* anchor into dir->list or dir->quarantine */ @@ -14,24 +19,87 @@ struct ref_tracker { depot_stack_handle_t free_stack_handle; }; -void __ref_tracker_dir_print(struct ref_tracker_dir *dir, - unsigned int display_limit) +struct ref_tracker_dir_stats { + int total; + int count; + struct { + depot_stack_handle_t stack_handle; + unsigned int count; + } stacks[]; +}; + +static struct ref_tracker_dir_stats * +ref_tracker_get_stats(struct ref_tracker_dir *dir, unsigned int limit) { + struct ref_tracker_dir_stats *stats; struct ref_tracker *tracker; - unsigned int i = 0; - lockdep_assert_held(&dir->lock); + stats = kmalloc(struct_size(stats, stacks, limit), + GFP_NOWAIT | __GFP_NOWARN); + if (!stats) + return ERR_PTR(-ENOMEM); + stats->total = 0; + stats->count = 0; list_for_each_entry(tracker, &dir->list, head) { - if (i < display_limit) { - pr_err("leaked reference.\n"); - if (tracker->alloc_stack_handle) - stack_depot_print(tracker->alloc_stack_handle); - i++; - } else { - break; + depot_stack_handle_t stack = tracker->alloc_stack_handle; + int i; + + ++stats->total; + for (i = 0; i < stats->count; ++i) + if (stats->stacks[i].stack_handle == stack) + break; + if (i >= limit) + continue; + if (i >= stats->count) { + stats->stacks[i].stack_handle = stack; + stats->stacks[i].count = 0; + ++stats->count; } + ++stats->stacks[i].count; + } + + return stats; +} + +void __ref_tracker_dir_print(struct ref_tracker_dir *dir, + unsigned int display_limit) +{ + struct ref_tracker_dir_stats *stats; + unsigned int i = 0, skipped; + depot_stack_handle_t stack; + char *sbuf; + + lockdep_assert_held(&dir->lock); + + if (list_empty(&dir->list)) + return; + + stats = ref_tracker_get_stats(dir, display_limit); + if (IS_ERR(stats)) { + pr_err("%s@%pK: couldn't get stats, error %pe\n", + dir->name, dir, stats); + return; } + + sbuf = kmalloc(STACK_BUF_SIZE, GFP_NOWAIT | __GFP_NOWARN); + + for (i = 0, skipped = stats->total; i < stats->count; ++i) { + stack = stats->stacks[i].stack_handle; + if (sbuf && !stack_depot_snprint(stack, sbuf, STACK_BUF_SIZE, 4)) + sbuf[0] = 0; + pr_err("%s@%pK has %d/%d users at\n%s\n", dir->name, dir, + stats->stacks[i].count, stats->total, sbuf); + skipped -= stats->stacks[i].count; + } + + if (skipped) + pr_err("%s@%pK skipped reports about %d/%d users.\n", + dir->name, dir, skipped, stats->total); + + kfree(sbuf); + + kfree(stats); } EXPORT_SYMBOL(__ref_tracker_dir_print); From patchwork Mon Mar 6 16:31:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 13161752 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 42CC8C61DA4 for ; Mon, 6 Mar 2023 16:32:43 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 9667110E3ED; Mon, 6 Mar 2023 16:32:37 +0000 (UTC) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0190810E3EC; Mon, 6 Mar 2023 16:32:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678120354; x=1709656354; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=fkjGvDLGnqfWXqERgwLxoLJ8bMf+bRuRswHYc5L4n/I=; b=AC3xOPTXdwjzi9gXMoUbPItH+/Ay8eSaMAxEGrPgCDk3Lr9KKOqyQ4UG BPylngjacsqnppx1ORANK1BKvcbadA1FdqfYrYkfuhnl619PPOJ8wDxaC rZsXEt/csldPd2NTXdkpKRHaHw/iY8pswoprtjxCOYikboZwlJ/kKNVYv AFJaH80EBWpPiB2gmWPrjjXjA0Vu3YVFauIWmyWQV92TiMxhW91lZZo/u O7TwIfrlu0lo74BqRvOl0/9dfNu/ZRirzw4VquD3H7B/RVzKXlrVMxrM2 ovpTji5HYEPW7aZPADB0L/4V9IYl3ycK0lHwQlvClhPT/EbAFavMJTkqf w==; X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="315998630" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="315998630" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:32 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="745132845" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="745132845" Received: from lab-ah.igk.intel.com ([10.102.42.211]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:29 -0800 From: Andrzej Hajda Date: Mon, 06 Mar 2023 17:31:59 +0100 MIME-Version: 1.0 Message-Id: <20230224-track_gt-v4-3-464e8ab4c9ab@intel.com> References: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> In-Reply-To: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> To: Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , Tvrtko Ursulin , David Airlie , Daniel Vetter X-Mailer: b4 0.11.1 Subject: [Intel-gfx] [PATCH v4 03/10] lib/ref_tracker: add printing to memory buffer X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: netdev@vger.kernel.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Chris Wilson , Eric Dumazet , Chris Wilson , Andrzej Hajda , Jakub Kicinski , Dmitry Vyukov Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" In case one wants to show stats via debugfs. Signed-off-by: Andrzej Hajda --- include/linux/ref_tracker.h | 8 +++++++ lib/ref_tracker.c | 56 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/include/linux/ref_tracker.h b/include/linux/ref_tracker.h index a2cf1f6309adb2..2fdbfd2e14797a 100644 --- a/include/linux/ref_tracker.h +++ b/include/linux/ref_tracker.h @@ -50,6 +50,8 @@ void __ref_tracker_dir_print(struct ref_tracker_dir *dir, void ref_tracker_dir_print(struct ref_tracker_dir *dir, unsigned int display_limit); +int ref_tracker_dir_snprint(struct ref_tracker_dir *dir, char *buf, size_t size); + int ref_tracker_alloc(struct ref_tracker_dir *dir, struct ref_tracker **trackerp, gfp_t gfp); @@ -78,6 +80,12 @@ static inline void ref_tracker_dir_print(struct ref_tracker_dir *dir, { } +static inline int ref_tracker_dir_snprint(struct ref_tracker_dir *dir, + char *buf, size_t size) +{ + return 0; +} + static inline int ref_tracker_alloc(struct ref_tracker_dir *dir, struct ref_tracker **trackerp, gfp_t gfp) diff --git a/lib/ref_tracker.c b/lib/ref_tracker.c index ab1253fde244ea..2ef4596b6b36f5 100644 --- a/lib/ref_tracker.c +++ b/lib/ref_tracker.c @@ -62,8 +62,27 @@ ref_tracker_get_stats(struct ref_tracker_dir *dir, unsigned int limit) return stats; } -void __ref_tracker_dir_print(struct ref_tracker_dir *dir, - unsigned int display_limit) +struct ostream { + char *buf; + int size, used; +}; + +#define pr_ostream(stream, fmt, args...) \ +({ \ + struct ostream *_s = (stream); \ +\ + if (!_s->buf) { \ + pr_err(fmt, ##args); \ + } else { \ + int ret, len = _s->size - _s->used; \ + ret = snprintf(_s->buf + _s->used, len, pr_fmt(fmt), ##args); \ + _s->used += min(ret, len); \ + } \ +}) + +static void +__ref_tracker_dir_pr_ostream(struct ref_tracker_dir *dir, + unsigned int display_limit, struct ostream *s) { struct ref_tracker_dir_stats *stats; unsigned int i = 0, skipped; @@ -77,8 +96,8 @@ void __ref_tracker_dir_print(struct ref_tracker_dir *dir, stats = ref_tracker_get_stats(dir, display_limit); if (IS_ERR(stats)) { - pr_err("%s@%pK: couldn't get stats, error %pe\n", - dir->name, dir, stats); + pr_ostream(s, "%s@%pK: couldn't get stats, error %pe\n", + dir->name, dir, stats); return; } @@ -88,19 +107,27 @@ void __ref_tracker_dir_print(struct ref_tracker_dir *dir, stack = stats->stacks[i].stack_handle; if (sbuf && !stack_depot_snprint(stack, sbuf, STACK_BUF_SIZE, 4)) sbuf[0] = 0; - pr_err("%s@%pK has %d/%d users at\n%s\n", dir->name, dir, - stats->stacks[i].count, stats->total, sbuf); + pr_ostream(s, "%s@%pK has %d/%d users at\n%s\n", dir->name, dir, + stats->stacks[i].count, stats->total, sbuf); skipped -= stats->stacks[i].count; } if (skipped) - pr_err("%s@%pK skipped reports about %d/%d users.\n", - dir->name, dir, skipped, stats->total); + pr_ostream(s, "%s@%pK skipped reports about %d/%d users.\n", + dir->name, dir, skipped, stats->total); kfree(sbuf); kfree(stats); } + +void __ref_tracker_dir_print(struct ref_tracker_dir *dir, + unsigned int display_limit) +{ + struct ostream os = {}; + + __ref_tracker_dir_pr_ostream(dir, display_limit, &os); +} EXPORT_SYMBOL(__ref_tracker_dir_print); void ref_tracker_dir_print(struct ref_tracker_dir *dir, @@ -114,6 +141,19 @@ void ref_tracker_dir_print(struct ref_tracker_dir *dir, } EXPORT_SYMBOL(ref_tracker_dir_print); +int ref_tracker_dir_snprint(struct ref_tracker_dir *dir, char *buf, size_t size) +{ + struct ostream os = { .buf = buf, .size = size }; + unsigned long flags; + + spin_lock_irqsave(&dir->lock, flags); + __ref_tracker_dir_pr_ostream(dir, 16, &os); + spin_unlock_irqrestore(&dir->lock, flags); + + return os.used; +} +EXPORT_SYMBOL(ref_tracker_dir_snprint); + void ref_tracker_dir_exit(struct ref_tracker_dir *dir) { struct ref_tracker *tracker, *n; From patchwork Mon Mar 6 16:32:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 13161753 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E6013C678D4 for ; Mon, 6 Mar 2023 16:32:45 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 3185E10E3F6; Mon, 6 Mar 2023 16:32:39 +0000 (UTC) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by gabe.freedesktop.org (Postfix) with ESMTPS id 39DA710E3EC; Mon, 6 Mar 2023 16:32:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678120356; x=1709656356; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=0eAGjVOQ2rbaK9zJyF59qMjxM1fjU52p32WNDpV9uis=; b=lrLrVFHk+AxKoCSOlvF9V7Rx9uIrtFqTkTgDYS2UYU0QEHlgwdtJMHKz jCAnzvfCfCUgFvmC+9A+cMN9O1Q/50lL4oFVY+GZIpUCdp1gJYSBAlmRE lT63vGjAZChsDrEgIFXMNv4W/+EEQ16DHF46hwPbJzyn4zqzz5AboPjU4 ehGn1ihmLgGDx8dM4HVOnFDT+0jDFP5wQIufKbVESvas4skpic9vTOQQE CwBoKUX+OJwNAo9Nj+qNbHoZlQbBRR1fYip5sb1mCT0EtuT5IFAqZUtK8 Z6ajWREmtR9YCYAOVl5NrxD99K3wH010D+1dGrsQTPM9BWqg3eLuPcS+g Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="315998657" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="315998657" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:35 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="745132872" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="745132872" Received: from lab-ah.igk.intel.com ([10.102.42.211]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:32 -0800 From: Andrzej Hajda Date: Mon, 06 Mar 2023 17:32:00 +0100 MIME-Version: 1.0 Message-Id: <20230224-track_gt-v4-4-464e8ab4c9ab@intel.com> References: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> In-Reply-To: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> To: Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , Tvrtko Ursulin , David Airlie , Daniel Vetter X-Mailer: b4 0.11.1 Subject: [Intel-gfx] [PATCH v4 04/10] lib/ref_tracker: remove warnings in case of allocation failure X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: netdev@vger.kernel.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Chris Wilson , Eric Dumazet , Chris Wilson , Andrzej Hajda , Jakub Kicinski , Dmitry Vyukov Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Library can handle allocation failures. To avoid allocation warnings __GFP_NOWARN has been added everywhere. Moreover GFP_ATOMIC has been replaced with GFP_NOWAIT in case of stack allocation on tracker free call. Signed-off-by: Andrzej Hajda Reviewed-by: Andi Shyti --- lib/ref_tracker.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/ref_tracker.c b/lib/ref_tracker.c index 2ef4596b6b36f5..cae4498fcfd701 100644 --- a/lib/ref_tracker.c +++ b/lib/ref_tracker.c @@ -189,7 +189,7 @@ int ref_tracker_alloc(struct ref_tracker_dir *dir, unsigned long entries[REF_TRACKER_STACK_ENTRIES]; struct ref_tracker *tracker; unsigned int nr_entries; - gfp_t gfp_mask = gfp; + gfp_t gfp_mask = gfp | __GFP_NOWARN; unsigned long flags; WARN_ON_ONCE(dir->dead); @@ -237,7 +237,8 @@ int ref_tracker_free(struct ref_tracker_dir *dir, return -EEXIST; } nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 1); - stack_handle = stack_depot_save(entries, nr_entries, GFP_ATOMIC); + stack_handle = stack_depot_save(entries, nr_entries, + GFP_NOWAIT | __GFP_NOWARN); spin_lock_irqsave(&dir->lock, flags); if (tracker->dead) { From patchwork Mon Mar 6 16:32:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 13161754 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C8290C678D4 for ; Mon, 6 Mar 2023 16:32:48 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id EBB8710E3F7; Mon, 6 Mar 2023 16:32:40 +0000 (UTC) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by gabe.freedesktop.org (Postfix) with ESMTPS id 142AB10E3F5; Mon, 6 Mar 2023 16:32:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678120359; x=1709656359; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=ON7/HzslYGhXzSc02vWwvEfrToct6tCg5PzOWD35lw0=; b=k0ttoIi7K0+2HSqRzo7iRLUoVZQAhFS4jxO/nLiMGNLTFoe30vLSfuOh sueSrtnKgf1cdfsmdVXplOnuQzVcWR6zb7NYkaMhuMTNl/LHgBzxN3Ggr /Vv+Xath+L76PjHAf0Tl4T1PndPuFpOJqkV+em9YivecJ2sNMP5V3PAbb is7lq6EzU7r5uE1zEuu/psCtm67iFhevSbkQhu0vikFsZxGrl2BXic23h lotJS0dckgOtIhu4PtsNzE4uTrrkiAYRixAzayV05gSC1EeEbvRL+DovE sFy+b4gYd6EU238MZjbEBQ8TQuCgVwqc2cDqMtkqRLFW+zZDTcMXqqVrW A==; X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="315998689" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="315998689" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:38 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="745132890" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="745132890" Received: from lab-ah.igk.intel.com ([10.102.42.211]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:35 -0800 From: Andrzej Hajda Date: Mon, 06 Mar 2023 17:32:01 +0100 MIME-Version: 1.0 Message-Id: <20230224-track_gt-v4-5-464e8ab4c9ab@intel.com> References: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> In-Reply-To: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> To: Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , Tvrtko Ursulin , David Airlie , Daniel Vetter X-Mailer: b4 0.11.1 Subject: [Intel-gfx] [PATCH v4 05/10] drm/i915: Separate wakeref tracking types from rpm X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: netdev@vger.kernel.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Chris Wilson , Eric Dumazet , Chris Wilson , Andrzej Hajda , Jakub Kicinski , Dmitry Vyukov Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" These structs will be used by other subsystems. Signed-off-by: Andrzej Hajda --- drivers/gpu/drm/i915/intel_runtime_pm.c | 14 +++++++------- drivers/gpu/drm/i915/intel_runtime_pm.h | 10 +--------- drivers/gpu/drm/i915/intel_wakeref.h | 4 ++-- drivers/gpu/drm/i915/intel_wakeref_tracker.h | 24 ++++++++++++++++++++++++ 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 129746713d072f..1901eedb6704a2 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -164,7 +164,7 @@ static int cmphandle(const void *_a, const void *_b) static void __print_intel_runtime_pm_wakeref(struct drm_printer *p, - const struct intel_runtime_pm_debug *dbg) + const struct intel_wakeref_tracker *dbg) { unsigned long i; char *buf; @@ -202,8 +202,8 @@ __print_intel_runtime_pm_wakeref(struct drm_printer *p, } static noinline void -__untrack_all_wakerefs(struct intel_runtime_pm_debug *debug, - struct intel_runtime_pm_debug *saved) +__untrack_all_wakerefs(struct intel_wakeref_tracker *debug, + struct intel_wakeref_tracker *saved) { *saved = *debug; @@ -213,7 +213,7 @@ __untrack_all_wakerefs(struct intel_runtime_pm_debug *debug, } static void -dump_and_free_wakeref_tracking(struct intel_runtime_pm_debug *debug) +dump_and_free_wakeref_tracking(struct intel_wakeref_tracker *debug) { if (debug->count) { struct drm_printer p = drm_debug_printer("i915"); @@ -227,7 +227,7 @@ dump_and_free_wakeref_tracking(struct intel_runtime_pm_debug *debug) static noinline void __intel_wakeref_dec_and_check_tracking(struct intel_runtime_pm *rpm) { - struct intel_runtime_pm_debug dbg = {}; + struct intel_wakeref_tracker dbg = {}; unsigned long flags; if (!atomic_dec_and_lock_irqsave(&rpm->wakeref_count, @@ -244,7 +244,7 @@ __intel_wakeref_dec_and_check_tracking(struct intel_runtime_pm *rpm) static noinline void untrack_all_intel_runtime_pm_wakerefs(struct intel_runtime_pm *rpm) { - struct intel_runtime_pm_debug dbg = {}; + struct intel_wakeref_tracker dbg = {}; unsigned long flags; spin_lock_irqsave(&rpm->debug.lock, flags); @@ -257,7 +257,7 @@ untrack_all_intel_runtime_pm_wakerefs(struct intel_runtime_pm *rpm) void print_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm, struct drm_printer *p) { - struct intel_runtime_pm_debug dbg = {}; + struct intel_wakeref_tracker dbg = {}; do { unsigned long alloc = dbg.count; diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.h b/drivers/gpu/drm/i915/intel_runtime_pm.h index e592e8d6499a1f..a8dc2baf79844f 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.h +++ b/drivers/gpu/drm/i915/intel_runtime_pm.h @@ -83,15 +83,7 @@ struct intel_runtime_pm { * paired rpm_put) we can remove corresponding pairs of and keep * the array trimmed to active wakerefs. */ - struct intel_runtime_pm_debug { - spinlock_t lock; - - depot_stack_handle_t last_acquire; - depot_stack_handle_t last_release; - - depot_stack_handle_t *owners; - unsigned long count; - } debug; + struct intel_wakeref_tracker debug; #endif }; diff --git a/drivers/gpu/drm/i915/intel_wakeref.h b/drivers/gpu/drm/i915/intel_wakeref.h index 71b8a63f6f104d..583fdaadd9912c 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.h +++ b/drivers/gpu/drm/i915/intel_wakeref.h @@ -17,6 +17,8 @@ #include #include +#include "intel_wakeref_tracker.h" + #if IS_ENABLED(CONFIG_DRM_I915_DEBUG) #define INTEL_WAKEREF_BUG_ON(expr) BUG_ON(expr) #else @@ -26,8 +28,6 @@ struct intel_runtime_pm; struct intel_wakeref; -typedef depot_stack_handle_t intel_wakeref_t; - struct intel_wakeref_ops { int (*get)(struct intel_wakeref *wf); int (*put)(struct intel_wakeref *wf); diff --git a/drivers/gpu/drm/i915/intel_wakeref_tracker.h b/drivers/gpu/drm/i915/intel_wakeref_tracker.h new file mode 100644 index 00000000000000..74e6261fb31260 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_wakeref_tracker.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef INTEL_WAKEREF_TRACKER_H +#define INTEL_WAKEREF_TRACKER_H + +#include +#include + +typedef depot_stack_handle_t intel_wakeref_t; + +struct intel_wakeref_tracker { + spinlock_t lock; + + depot_stack_handle_t last_acquire; + depot_stack_handle_t last_release; + + depot_stack_handle_t *owners; + unsigned long count; +}; + +#endif /* INTEL_WAKEREF_TRACKER_H */ From patchwork Mon Mar 6 16:32:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 13161755 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 990ACC64EC4 for ; Mon, 6 Mar 2023 16:32:49 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 6DFC110E3FC; Mon, 6 Mar 2023 16:32:45 +0000 (UTC) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by gabe.freedesktop.org (Postfix) with ESMTPS id 87D9B10E3FB; Mon, 6 Mar 2023 16:32:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678120363; x=1709656363; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=BhfK79fE5vN8BNwfVi+MLNZ4A3qH1w+Mrg6SozqG8xA=; b=F2eeXxw+0gZsPiabbz9No3CQ82LJ7m/NyRT2L0hA1v2Qs90LaZXbTeSz mrK+WHEGbi3qOwSZAKXJgj7Dk+/GVcgPDHmEvf/aDHxnt/Xbgztwzxb2y 4c3OBUIAfW07rMeanuacjVoqJnliQ0KtPoBtG37WDY34frMVwQBfWRcsH HMFXP/3WZMk7cwTZ1DdHQMF9HbXZ4Z9hPy3ziuwRYRmN40D3V3/mWMlbS IK0K8XyCjBe7TS3wA/UhdvglZq1ozCfcvp9ga2oZQ2cXb5qtQg+Yx1dw2 wk1ZXhJ2dxQ8Z/OTurSsOPhgYqoyCeSn2LRqJIQbbgZ/PnvA9s2WtZvEy Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="315998733" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="315998733" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:42 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="745132914" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="745132914" Received: from lab-ah.igk.intel.com ([10.102.42.211]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:38 -0800 From: Andrzej Hajda Date: Mon, 06 Mar 2023 17:32:02 +0100 MIME-Version: 1.0 Message-Id: <20230224-track_gt-v4-6-464e8ab4c9ab@intel.com> References: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> In-Reply-To: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> To: Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , Tvrtko Ursulin , David Airlie , Daniel Vetter X-Mailer: b4 0.11.1 Subject: [Intel-gfx] [PATCH v4 06/10] drm/i915: Separate wakeref tracking X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: netdev@vger.kernel.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Chris Wilson , Eric Dumazet , Chris Wilson , Andrzej Hajda , Jakub Kicinski , Dmitry Vyukov Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Chris Wilson Extract the callstack tracking of intel_runtime_pm.c into its own utility so that that we can reuse it for other online debugging of scoped wakerefs. Signed-off-by: Chris Wilson Signed-off-by: Andrzej Hajda --- drivers/gpu/drm/i915/Kconfig.debug | 9 ++ drivers/gpu/drm/i915/Makefile | 4 + drivers/gpu/drm/i915/intel_runtime_pm.c | 222 +++---------------------- drivers/gpu/drm/i915/intel_wakeref.h | 2 +- drivers/gpu/drm/i915/intel_wakeref_tracker.c | 234 +++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_wakeref_tracker.h | 52 ++++++ 6 files changed, 319 insertions(+), 204 deletions(-) diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug index 93dfb7ed970547..5fde52107e3b44 100644 --- a/drivers/gpu/drm/i915/Kconfig.debug +++ b/drivers/gpu/drm/i915/Kconfig.debug @@ -25,6 +25,7 @@ config DRM_I915_DEBUG select PREEMPT_COUNT select I2C_CHARDEV select STACKDEPOT + select STACKTRACE select DRM_DP_AUX_CHARDEV select X86_MSR # used by igt/pm_rpm select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks) @@ -37,6 +38,7 @@ config DRM_I915_DEBUG select DRM_I915_DEBUG_GEM select DRM_I915_DEBUG_GEM_ONCE select DRM_I915_DEBUG_MMIO + select DRM_I915_TRACK_WAKEREF select DRM_I915_DEBUG_RUNTIME_PM select DRM_I915_SW_FENCE_DEBUG_OBJECTS select DRM_I915_SELFTEST @@ -227,11 +229,18 @@ config DRM_I915_DEBUG_VBLANK_EVADE If in doubt, say "N". +config DRM_I915_TRACK_WAKEREF + depends on STACKDEPOT + depends on STACKTRACE + bool + config DRM_I915_DEBUG_RUNTIME_PM bool "Enable extra state checking for runtime PM" depends on DRM_I915 default n select STACKDEPOT + select STACKTRACE + select DRM_I915_TRACK_WAKEREF help Choose this option to turn on extra state checking for the runtime PM functionality. This may introduce overhead during diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index b2f91a1f826858..42daff6d575a82 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -81,6 +81,10 @@ i915-$(CONFIG_DEBUG_FS) += \ i915_debugfs_params.o \ display/intel_display_debugfs.o \ display/intel_pipe_crc.o + +i915-$(CONFIG_DRM_I915_TRACK_WAKEREF) += \ + intel_wakeref_tracker.o + i915-$(CONFIG_PERF_EVENTS) += i915_pmu.o # "Graphics Technology" (aka we talk to the gpu) diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 1901eedb6704a2..43149cf12dc864 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -52,182 +52,37 @@ #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) -#include - -#define STACKDEPTH 8 - -static noinline depot_stack_handle_t __save_depot_stack(void) -{ - unsigned long entries[STACKDEPTH]; - unsigned int n; - - n = stack_trace_save(entries, ARRAY_SIZE(entries), 1); - return stack_depot_save(entries, n, GFP_NOWAIT | __GFP_NOWARN); -} - static void init_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm) { - spin_lock_init(&rpm->debug.lock); - stack_depot_init(); + intel_wakeref_tracker_init(&rpm->debug); } -static noinline depot_stack_handle_t +static intel_wakeref_t track_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm) { - depot_stack_handle_t stack, *stacks; - unsigned long flags; - - if (rpm->no_wakeref_tracking) - return -1; - - stack = __save_depot_stack(); - if (!stack) + if (!rpm->available || rpm->no_wakeref_tracking) return -1; - spin_lock_irqsave(&rpm->debug.lock, flags); - - if (!rpm->debug.count) - rpm->debug.last_acquire = stack; - - stacks = krealloc(rpm->debug.owners, - (rpm->debug.count + 1) * sizeof(*stacks), - GFP_NOWAIT | __GFP_NOWARN); - if (stacks) { - stacks[rpm->debug.count++] = stack; - rpm->debug.owners = stacks; - } else { - stack = -1; - } - - spin_unlock_irqrestore(&rpm->debug.lock, flags); - - return stack; + return intel_wakeref_tracker_add(&rpm->debug); } static void untrack_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm, - depot_stack_handle_t stack) + intel_wakeref_t wakeref) { - struct drm_i915_private *i915 = container_of(rpm, - struct drm_i915_private, - runtime_pm); - unsigned long flags, n; - bool found = false; - - if (unlikely(stack == -1)) - return; - - spin_lock_irqsave(&rpm->debug.lock, flags); - for (n = rpm->debug.count; n--; ) { - if (rpm->debug.owners[n] == stack) { - memmove(rpm->debug.owners + n, - rpm->debug.owners + n + 1, - (--rpm->debug.count - n) * sizeof(stack)); - found = true; - break; - } - } - spin_unlock_irqrestore(&rpm->debug.lock, flags); - - if (drm_WARN(&i915->drm, !found, - "Unmatched wakeref (tracking %lu), count %u\n", - rpm->debug.count, atomic_read(&rpm->wakeref_count))) { - char *buf; - - buf = kmalloc(PAGE_SIZE, GFP_NOWAIT | __GFP_NOWARN); - if (!buf) - return; - - stack_depot_snprint(stack, buf, PAGE_SIZE, 2); - DRM_DEBUG_DRIVER("wakeref %x from\n%s", stack, buf); - - stack = READ_ONCE(rpm->debug.last_release); - if (stack) { - stack_depot_snprint(stack, buf, PAGE_SIZE, 2); - DRM_DEBUG_DRIVER("wakeref last released at\n%s", buf); - } - - kfree(buf); - } + intel_wakeref_tracker_remove(&rpm->debug, wakeref); } -static int cmphandle(const void *_a, const void *_b) +static void untrack_all_intel_runtime_pm_wakerefs(struct intel_runtime_pm *rpm) { - const depot_stack_handle_t * const a = _a, * const b = _b; + struct drm_printer p = drm_debug_printer("i915"); - if (*a < *b) - return -1; - else if (*a > *b) - return 1; - else - return 0; -} - -static void -__print_intel_runtime_pm_wakeref(struct drm_printer *p, - const struct intel_wakeref_tracker *dbg) -{ - unsigned long i; - char *buf; - - buf = kmalloc(PAGE_SIZE, GFP_NOWAIT | __GFP_NOWARN); - if (!buf) - return; - - if (dbg->last_acquire) { - stack_depot_snprint(dbg->last_acquire, buf, PAGE_SIZE, 2); - drm_printf(p, "Wakeref last acquired:\n%s", buf); - } - - if (dbg->last_release) { - stack_depot_snprint(dbg->last_release, buf, PAGE_SIZE, 2); - drm_printf(p, "Wakeref last released:\n%s", buf); - } - - drm_printf(p, "Wakeref count: %lu\n", dbg->count); - - sort(dbg->owners, dbg->count, sizeof(*dbg->owners), cmphandle, NULL); - - for (i = 0; i < dbg->count; i++) { - depot_stack_handle_t stack = dbg->owners[i]; - unsigned long rep; - - rep = 1; - while (i + 1 < dbg->count && dbg->owners[i + 1] == stack) - rep++, i++; - stack_depot_snprint(stack, buf, PAGE_SIZE, 2); - drm_printf(p, "Wakeref x%lu taken at:\n%s", rep, buf); - } - - kfree(buf); -} - -static noinline void -__untrack_all_wakerefs(struct intel_wakeref_tracker *debug, - struct intel_wakeref_tracker *saved) -{ - *saved = *debug; - - debug->owners = NULL; - debug->count = 0; - debug->last_release = __save_depot_stack(); -} - -static void -dump_and_free_wakeref_tracking(struct intel_wakeref_tracker *debug) -{ - if (debug->count) { - struct drm_printer p = drm_debug_printer("i915"); - - __print_intel_runtime_pm_wakeref(&p, debug); - } - - kfree(debug->owners); + intel_wakeref_tracker_reset(&rpm->debug, &p); } static noinline void __intel_wakeref_dec_and_check_tracking(struct intel_runtime_pm *rpm) { - struct intel_wakeref_tracker dbg = {}; + struct intel_wakeref_tracker saved; unsigned long flags; if (!atomic_dec_and_lock_irqsave(&rpm->wakeref_count, @@ -235,60 +90,21 @@ __intel_wakeref_dec_and_check_tracking(struct intel_runtime_pm *rpm) flags)) return; - __untrack_all_wakerefs(&rpm->debug, &dbg); + saved = __intel_wakeref_tracker_reset(&rpm->debug); spin_unlock_irqrestore(&rpm->debug.lock, flags); - dump_and_free_wakeref_tracking(&dbg); -} - -static noinline void -untrack_all_intel_runtime_pm_wakerefs(struct intel_runtime_pm *rpm) -{ - struct intel_wakeref_tracker dbg = {}; - unsigned long flags; - - spin_lock_irqsave(&rpm->debug.lock, flags); - __untrack_all_wakerefs(&rpm->debug, &dbg); - spin_unlock_irqrestore(&rpm->debug.lock, flags); + if (saved.count) { + struct drm_printer p = drm_debug_printer("i915"); - dump_and_free_wakeref_tracking(&dbg); + __intel_wakeref_tracker_show(&saved, &p); + intel_wakeref_tracker_fini(&saved); + } } void print_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm, struct drm_printer *p) { - struct intel_wakeref_tracker dbg = {}; - - do { - unsigned long alloc = dbg.count; - depot_stack_handle_t *s; - - spin_lock_irq(&rpm->debug.lock); - dbg.count = rpm->debug.count; - if (dbg.count <= alloc) { - memcpy(dbg.owners, - rpm->debug.owners, - dbg.count * sizeof(*s)); - } - dbg.last_acquire = rpm->debug.last_acquire; - dbg.last_release = rpm->debug.last_release; - spin_unlock_irq(&rpm->debug.lock); - if (dbg.count <= alloc) - break; - - s = krealloc(dbg.owners, - dbg.count * sizeof(*s), - GFP_NOWAIT | __GFP_NOWARN); - if (!s) - goto out; - - dbg.owners = s; - } while (1); - - __print_intel_runtime_pm_wakeref(p, &dbg); - -out: - kfree(dbg.owners); + intel_wakeref_tracker_show(&rpm->debug, p); } #else @@ -297,14 +113,14 @@ static void init_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm) { } -static depot_stack_handle_t +static intel_wakeref_t track_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm) { return -1; } static void untrack_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm, - intel_wakeref_t wref) + intel_wakeref_t wakeref) { } diff --git a/drivers/gpu/drm/i915/intel_wakeref.h b/drivers/gpu/drm/i915/intel_wakeref.h index 583fdaadd9912c..20720fbcc28d46 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.h +++ b/drivers/gpu/drm/i915/intel_wakeref.h @@ -19,7 +19,7 @@ #include "intel_wakeref_tracker.h" -#if IS_ENABLED(CONFIG_DRM_I915_DEBUG) +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_WAKEREF) #define INTEL_WAKEREF_BUG_ON(expr) BUG_ON(expr) #else #define INTEL_WAKEREF_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr) diff --git a/drivers/gpu/drm/i915/intel_wakeref_tracker.c b/drivers/gpu/drm/i915/intel_wakeref_tracker.c new file mode 100644 index 00000000000000..c92035030a75cc --- /dev/null +++ b/drivers/gpu/drm/i915/intel_wakeref_tracker.c @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2021 Intel Corporation + */ + +#include +#include +#include +#include + +#include + +#include "intel_wakeref_tracker.h" + +#define STACKDEPTH 8 + +static noinline depot_stack_handle_t __save_depot_stack(void) +{ + unsigned long entries[STACKDEPTH]; + unsigned int n; + + n = stack_trace_save(entries, ARRAY_SIZE(entries), 1); + return stack_depot_save(entries, n, GFP_NOWAIT | __GFP_NOWARN); +} + +static void __print_depot_stack(depot_stack_handle_t stack, + char *buf, int sz, int indent) +{ + unsigned long *entries; + unsigned int nr_entries; + + nr_entries = stack_depot_fetch(stack, &entries); + stack_trace_snprint(buf, sz, entries, nr_entries, indent); +} + +static int cmphandle(const void *_a, const void *_b) +{ + const depot_stack_handle_t * const a = _a, * const b = _b; + + if (*a < *b) + return -1; + else if (*a > *b) + return 1; + else + return 0; +} + +void +__intel_wakeref_tracker_show(const struct intel_wakeref_tracker *w, + struct drm_printer *p) +{ + unsigned long i; + char *buf; + + buf = kmalloc(PAGE_SIZE, GFP_NOWAIT | __GFP_NOWARN); + if (!buf) + return; + + if (w->last_acquire) { + __print_depot_stack(w->last_acquire, buf, PAGE_SIZE, 2); + drm_printf(p, "Wakeref last acquired:\n%s", buf); + } + + if (w->last_release) { + __print_depot_stack(w->last_release, buf, PAGE_SIZE, 2); + drm_printf(p, "Wakeref last released:\n%s", buf); + } + + drm_printf(p, "Wakeref count: %lu\n", w->count); + + sort(w->owners, w->count, sizeof(*w->owners), cmphandle, NULL); + + for (i = 0; i < w->count; i++) { + depot_stack_handle_t stack = w->owners[i]; + unsigned long rep; + + rep = 1; + while (i + 1 < w->count && w->owners[i + 1] == stack) + rep++, i++; + __print_depot_stack(stack, buf, PAGE_SIZE, 2); + drm_printf(p, "Wakeref x%lu taken at:\n%s", rep, buf); + } + + kfree(buf); +} + +void intel_wakeref_tracker_show(struct intel_wakeref_tracker *w, + struct drm_printer *p) +{ + struct intel_wakeref_tracker tmp = {}; + + do { + unsigned long alloc = tmp.count; + depot_stack_handle_t *s; + + spin_lock_irq(&w->lock); + tmp.count = w->count; + if (tmp.count <= alloc) + memcpy(tmp.owners, w->owners, tmp.count * sizeof(*s)); + tmp.last_acquire = w->last_acquire; + tmp.last_release = w->last_release; + spin_unlock_irq(&w->lock); + if (tmp.count <= alloc) + break; + + s = krealloc(tmp.owners, + tmp.count * sizeof(*s), + GFP_NOWAIT | __GFP_NOWARN); + if (!s) + goto out; + + tmp.owners = s; + } while (1); + + __intel_wakeref_tracker_show(&tmp, p); + +out: + intel_wakeref_tracker_fini(&tmp); +} + +intel_wakeref_t intel_wakeref_tracker_add(struct intel_wakeref_tracker *w) +{ + depot_stack_handle_t stack, *stacks; + unsigned long flags; + + stack = __save_depot_stack(); + if (!stack) + return -1; + + spin_lock_irqsave(&w->lock, flags); + + if (!w->count) + w->last_acquire = stack; + + stacks = krealloc(w->owners, + (w->count + 1) * sizeof(*stacks), + GFP_NOWAIT | __GFP_NOWARN); + if (stacks) { + stacks[w->count++] = stack; + w->owners = stacks; + } else { + stack = -1; + } + + spin_unlock_irqrestore(&w->lock, flags); + + return stack; +} + +void intel_wakeref_tracker_remove(struct intel_wakeref_tracker *w, + intel_wakeref_t stack) +{ + unsigned long flags, n; + bool found = false; + + if (unlikely(stack == -1)) + return; + + spin_lock_irqsave(&w->lock, flags); + for (n = w->count; n--; ) { + if (w->owners[n] == stack) { + memmove(w->owners + n, + w->owners + n + 1, + (--w->count - n) * sizeof(stack)); + found = true; + break; + } + } + spin_unlock_irqrestore(&w->lock, flags); + + if (WARN(!found, + "Unmatched wakeref %x, tracking %lu\n", + stack, w->count)) { + char *buf; + + buf = kmalloc(PAGE_SIZE, GFP_NOWAIT | __GFP_NOWARN); + if (!buf) + return; + + __print_depot_stack(stack, buf, PAGE_SIZE, 2); + pr_err("wakeref %x from\n%s", stack, buf); + + stack = READ_ONCE(w->last_release); + if (stack && !w->count) { + __print_depot_stack(stack, buf, PAGE_SIZE, 2); + pr_err("wakeref last released at\n%s", buf); + } + + kfree(buf); + } +} + +struct intel_wakeref_tracker +__intel_wakeref_tracker_reset(struct intel_wakeref_tracker *w) +{ + struct intel_wakeref_tracker saved; + + lockdep_assert_held(&w->lock); + + saved = *w; + + w->owners = NULL; + w->count = 0; + w->last_release = __save_depot_stack(); + + return saved; +} + +void intel_wakeref_tracker_reset(struct intel_wakeref_tracker *w, + struct drm_printer *p) +{ + struct intel_wakeref_tracker tmp; + + spin_lock_irq(&w->lock); + tmp = __intel_wakeref_tracker_reset(w); + spin_unlock_irq(&w->lock); + + if (tmp.count) + __intel_wakeref_tracker_show(&tmp, p); + + intel_wakeref_tracker_fini(&tmp); +} + +void intel_wakeref_tracker_init(struct intel_wakeref_tracker *w) +{ + memset(w, 0, sizeof(*w)); + spin_lock_init(&w->lock); + stack_depot_init(); +} + +void intel_wakeref_tracker_fini(struct intel_wakeref_tracker *w) +{ + kfree(w->owners); +} diff --git a/drivers/gpu/drm/i915/intel_wakeref_tracker.h b/drivers/gpu/drm/i915/intel_wakeref_tracker.h index 74e6261fb31260..61df68e28c0fbf 100644 --- a/drivers/gpu/drm/i915/intel_wakeref_tracker.h +++ b/drivers/gpu/drm/i915/intel_wakeref_tracker.h @@ -6,11 +6,14 @@ #ifndef INTEL_WAKEREF_TRACKER_H #define INTEL_WAKEREF_TRACKER_H +#include #include #include typedef depot_stack_handle_t intel_wakeref_t; +struct drm_printer; + struct intel_wakeref_tracker { spinlock_t lock; @@ -21,4 +24,53 @@ struct intel_wakeref_tracker { unsigned long count; }; +#if IS_ENABLED(CONFIG_DRM_I915_TRACK_WAKEREF) + +void intel_wakeref_tracker_init(struct intel_wakeref_tracker *w); +void intel_wakeref_tracker_fini(struct intel_wakeref_tracker *w); + +intel_wakeref_t intel_wakeref_tracker_add(struct intel_wakeref_tracker *w); +void intel_wakeref_tracker_remove(struct intel_wakeref_tracker *w, + intel_wakeref_t handle); + +struct intel_wakeref_tracker +__intel_wakeref_tracker_reset(struct intel_wakeref_tracker *w); +void intel_wakeref_tracker_reset(struct intel_wakeref_tracker *w, + struct drm_printer *p); + +void __intel_wakeref_tracker_show(const struct intel_wakeref_tracker *w, + struct drm_printer *p); +void intel_wakeref_tracker_show(struct intel_wakeref_tracker *w, + struct drm_printer *p); + +#else + +static inline void intel_wakeref_tracker_init(struct intel_wakeref_tracker *w) {} +static inline void intel_wakeref_tracker_fini(struct intel_wakeref_tracker *w) {} + +static inline intel_wakeref_t +intel_wakeref_tracker_add(struct intel_wakeref_tracker *w) +{ + return -1; +} + +static inline void +intel_wakeref_untrack_remove(struct intel_wakeref_tracker *w, intel_wakeref_t handle) {} + +static inline struct intel_wakeref_tracker +__intel_wakeref_tracker_reset(struct intel_wakeref_tracker *w) +{ + return (struct intel_wakeref_tracker){}; +} + +static inline void intel_wakeref_tracker_reset(struct intel_wakeref_tracker *w, + struct drm_printer *p) +{ +} + +static inline void __intel_wakeref_tracker_show(const struct intel_wakeref_tracker *w, struct drm_printer *p) {} +static inline void intel_wakeref_tracker_show(struct intel_wakeref_tracker *w, struct drm_printer *p) {} + +#endif + #endif /* INTEL_WAKEREF_TRACKER_H */ From patchwork Mon Mar 6 16:32:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 13161757 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1B3FBC61DA4 for ; Mon, 6 Mar 2023 16:32:54 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id CAFE410E3FB; Mon, 6 Mar 2023 16:32:50 +0000 (UTC) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5F4FD10E3FE; Mon, 6 Mar 2023 16:32:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678120367; x=1709656367; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=qoAim51aaR0BmJjCmLBn0hafRR/PKyF3Se/QDAAMVMg=; b=MjZmzTK+d33rmZ/QgfDTm8AECOHCZ8yy8FzjzIVJPaeFVobD7/hIyLoK 6pGiwGA+ZAwjlYflsmp0k0KFdcor98wrF6Bv/8PgUcTxuoCmutLtSjE4p WSMJC35ZKeqO2oANzfWEVitJ6r5oNLHBIaDNcWY92Ku+dctjpqRBB69BY 3rjlSXf+60xsUF+J4fCfoVxsjb643aIbSiHi0/Lbj8Toq7xFSwnEY6BzP BH3z9SIS5Dj0KiXp8/TCevBzeENFUQjmeY5XgWLcBUHMR5UKPb21UFAKv pSiTUu0gVZ45jdhEyJn41tq46ovqwexihmZowZCpkPadtWmDwJ9e5LtMf w==; X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="315998771" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="315998771" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:46 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="745132948" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="745132948" Received: from lab-ah.igk.intel.com ([10.102.42.211]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:42 -0800 From: Andrzej Hajda Date: Mon, 06 Mar 2023 17:32:03 +0100 MIME-Version: 1.0 Message-Id: <20230224-track_gt-v4-7-464e8ab4c9ab@intel.com> References: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> In-Reply-To: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> To: Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , Tvrtko Ursulin , David Airlie , Daniel Vetter X-Mailer: b4 0.11.1 Subject: [Intel-gfx] [PATCH v4 07/10] drm/i915: Track leaked gt->wakerefs X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: netdev@vger.kernel.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Chris Wilson , Eric Dumazet , Chris Wilson , Andrzej Hajda , Jakub Kicinski , Dmitry Vyukov Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Chris Wilson Track every intel_gt_pm_get() until its corresponding release in intel_gt_pm_put() by returning a cookie to the caller for acquire that must be passed by on rleased. When there is an imbalance, we can see who either tried to free a stale wakeref, or who forgot to free theirs. v2: Rebase from backporting wakeref leak (Umesh) Signed-off-by: Chris Wilson Signed-off-by: Andrzej Hajda --- drivers/gpu/drm/i915/Kconfig.debug | 15 ++++++++ drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 7 ++-- .../drm/i915/gem/selftests/i915_gem_coherency.c | 10 +++--- drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c | 14 ++++---- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 13 ++++--- drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h | 3 +- drivers/gpu/drm/i915/gt/intel_engine_pm.c | 4 +-- drivers/gpu/drm/i915/gt/intel_engine_types.h | 2 ++ .../gpu/drm/i915/gt/intel_execlists_submission.c | 2 +- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 10 +++--- drivers/gpu/drm/i915/gt/intel_gt_pm.h | 38 +++++++++++++++----- drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c | 4 +-- drivers/gpu/drm/i915/gt/selftest_engine_cs.c | 20 ++++++----- drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 5 +-- drivers/gpu/drm/i915/gt/selftest_reset.c | 10 +++--- drivers/gpu/drm/i915/gt/selftest_rps.c | 17 +++++---- drivers/gpu/drm/i915/gt/selftest_slpc.c | 5 +-- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 9 ++--- drivers/gpu/drm/i915/i915_pmu.c | 16 +++++---- drivers/gpu/drm/i915/intel_wakeref.c | 4 +++ drivers/gpu/drm/i915/intel_wakeref.h | 42 ++++++++++++++++++++++ 21 files changed, 180 insertions(+), 70 deletions(-) diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug index 5fde52107e3b44..63b77dc48d4394 100644 --- a/drivers/gpu/drm/i915/Kconfig.debug +++ b/drivers/gpu/drm/i915/Kconfig.debug @@ -40,6 +40,7 @@ config DRM_I915_DEBUG select DRM_I915_DEBUG_MMIO select DRM_I915_TRACK_WAKEREF select DRM_I915_DEBUG_RUNTIME_PM + select DRM_I915_DEBUG_WAKEREF select DRM_I915_SW_FENCE_DEBUG_OBJECTS select DRM_I915_SELFTEST select BROKEN # for prototype uAPI @@ -249,3 +250,17 @@ config DRM_I915_DEBUG_RUNTIME_PM Recommended for driver developers only. If in doubt, say "N" + +config DRM_I915_DEBUG_WAKEREF + bool "Enable extra tracking for wakerefs" + depends on DRM_I915 + default n + select STACKDEPOT + select STACKTRACE + select DRM_I915_TRACK_WAKEREF + help + Choose this option to turn on extra state checking and usage + tracking for the wakerefPM functionality. This may introduce + overhead during driver runtime. + + If in doubt, say "N" diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 9dce2957b4e5ae..65abcd82b6de93 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -253,6 +253,7 @@ struct i915_execbuffer { struct intel_gt *gt; /* gt for the execbuf */ struct intel_context *context; /* logical state for the request */ struct i915_gem_context *gem_context; /** caller's context */ + intel_wakeref_t wakeref; /** our requests to build */ struct i915_request *requests[MAX_ENGINE_INSTANCE + 1]; @@ -2713,7 +2714,7 @@ eb_select_engine(struct i915_execbuffer *eb) for_each_child(ce, child) intel_context_get(child); - intel_gt_pm_get(ce->engine->gt); + eb->wakeref = intel_gt_pm_get(ce->engine->gt); if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) { err = intel_context_alloc_state(ce); @@ -2752,7 +2753,7 @@ eb_select_engine(struct i915_execbuffer *eb) return err; err: - intel_gt_pm_put(ce->engine->gt); + intel_gt_pm_put(ce->engine->gt, eb->wakeref); for_each_child(ce, child) intel_context_put(child); intel_context_put(ce); @@ -2765,7 +2766,7 @@ eb_put_engine(struct i915_execbuffer *eb) struct intel_context *child; i915_vm_put(eb->context->vm); - intel_gt_pm_put(eb->gt); + intel_gt_pm_put(eb->context->engine->gt, eb->wakeref); for_each_child(eb->context, child) intel_context_put(child); intel_context_put(eb->context); diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c index 3bef1beec7cbb5..3fd68a099a85ef 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c @@ -85,6 +85,7 @@ static int cpu_get(struct context *ctx, unsigned long offset, u32 *v) static int gtt_set(struct context *ctx, unsigned long offset, u32 v) { + intel_wakeref_t wakeref; struct i915_vma *vma; u32 __iomem *map; int err = 0; @@ -99,7 +100,7 @@ static int gtt_set(struct context *ctx, unsigned long offset, u32 v) if (IS_ERR(vma)) return PTR_ERR(vma); - intel_gt_pm_get(vma->vm->gt); + wakeref = intel_gt_pm_get(vma->vm->gt); map = i915_vma_pin_iomap(vma); i915_vma_unpin(vma); @@ -112,12 +113,13 @@ static int gtt_set(struct context *ctx, unsigned long offset, u32 v) i915_vma_unpin_iomap(vma); out_rpm: - intel_gt_pm_put(vma->vm->gt); + intel_gt_pm_put(vma->vm->gt, wakeref); return err; } static int gtt_get(struct context *ctx, unsigned long offset, u32 *v) { + intel_wakeref_t wakeref; struct i915_vma *vma; u32 __iomem *map; int err = 0; @@ -132,7 +134,7 @@ static int gtt_get(struct context *ctx, unsigned long offset, u32 *v) if (IS_ERR(vma)) return PTR_ERR(vma); - intel_gt_pm_get(vma->vm->gt); + wakeref = intel_gt_pm_get(vma->vm->gt); map = i915_vma_pin_iomap(vma); i915_vma_unpin(vma); @@ -145,7 +147,7 @@ static int gtt_get(struct context *ctx, unsigned long offset, u32 *v) i915_vma_unpin_iomap(vma); out_rpm: - intel_gt_pm_put(vma->vm->gt); + intel_gt_pm_put(vma->vm->gt, wakeref); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index 56279908ed305b..f6f36a85688814 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -630,14 +630,14 @@ static bool assert_mmap_offset(struct drm_i915_private *i915, static void disable_retire_worker(struct drm_i915_private *i915) { i915_gem_driver_unregister__shrinker(i915); - intel_gt_pm_get(to_gt(i915)); + intel_gt_pm_get_untracked(to_gt(i915)); cancel_delayed_work_sync(&to_gt(i915)->requests.retire_work); } static void restore_retire_worker(struct drm_i915_private *i915) { igt_flush_test(i915); - intel_gt_pm_put(to_gt(i915)); + intel_gt_pm_put_untracked(to_gt(i915)); i915_gem_driver_register__shrinker(i915); } @@ -778,6 +778,7 @@ static int igt_mmap_offset_exhaustion(void *arg) static int gtt_set(struct drm_i915_gem_object *obj) { + intel_wakeref_t wakeref; struct i915_vma *vma; void __iomem *map; int err = 0; @@ -786,7 +787,7 @@ static int gtt_set(struct drm_i915_gem_object *obj) if (IS_ERR(vma)) return PTR_ERR(vma); - intel_gt_pm_get(vma->vm->gt); + wakeref = intel_gt_pm_get(vma->vm->gt); map = i915_vma_pin_iomap(vma); i915_vma_unpin(vma); if (IS_ERR(map)) { @@ -798,12 +799,13 @@ static int gtt_set(struct drm_i915_gem_object *obj) i915_vma_unpin_iomap(vma); out: - intel_gt_pm_put(vma->vm->gt); + intel_gt_pm_put(vma->vm->gt, wakeref); return err; } static int gtt_check(struct drm_i915_gem_object *obj) { + intel_wakeref_t wakeref; struct i915_vma *vma; void __iomem *map; int err = 0; @@ -812,7 +814,7 @@ static int gtt_check(struct drm_i915_gem_object *obj) if (IS_ERR(vma)) return PTR_ERR(vma); - intel_gt_pm_get(vma->vm->gt); + wakeref = intel_gt_pm_get(vma->vm->gt); map = i915_vma_pin_iomap(vma); i915_vma_unpin(vma); if (IS_ERR(map)) { @@ -828,7 +830,7 @@ static int gtt_check(struct drm_i915_gem_object *obj) i915_vma_unpin_iomap(vma); out: - intel_gt_pm_put(vma->vm->gt); + intel_gt_pm_put(vma->vm->gt, wakeref); return err; } diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index ecc990ec1b9526..d650beb8ed22f6 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -28,11 +28,14 @@ static void irq_disable(struct intel_breadcrumbs *b) static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) { + intel_wakeref_t wakeref; + /* * Since we are waiting on a request, the GPU should be busy * and should have its own rpm reference. */ - if (GEM_WARN_ON(!intel_gt_pm_get_if_awake(b->irq_engine->gt))) + wakeref = intel_gt_pm_get_if_awake(b->irq_engine->gt); + if (GEM_WARN_ON(!wakeref)) return; /* @@ -41,7 +44,7 @@ static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) * which we can add a new waiter and avoid the cost of re-enabling * the irq. */ - WRITE_ONCE(b->irq_armed, true); + WRITE_ONCE(b->irq_armed, wakeref); /* Requests may have completed before we could enable the interrupt. */ if (!b->irq_enabled++ && b->irq_enable(b)) @@ -61,12 +64,14 @@ static void intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b) { + intel_wakeref_t wakeref = b->irq_armed; + GEM_BUG_ON(!b->irq_enabled); if (!--b->irq_enabled) b->irq_disable(b); - WRITE_ONCE(b->irq_armed, false); - intel_gt_pm_put_async(b->irq_engine->gt); + WRITE_ONCE(b->irq_armed, 0); + intel_gt_pm_put_async(b->irq_engine->gt, wakeref); } static void intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b) diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h b/drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h index 72dfd3748c4c33..bdf09fd67b6e70 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h @@ -13,6 +13,7 @@ #include #include "intel_engine_types.h" +#include "intel_wakeref.h" /* * Rather than have every client wait upon all user interrupts, @@ -43,7 +44,7 @@ struct intel_breadcrumbs { spinlock_t irq_lock; /* protects the interrupt from hardirq context */ struct irq_work irq_work; /* for use from inside irq_lock */ unsigned int irq_enabled; - bool irq_armed; + intel_wakeref_t irq_armed; /* Not all breadcrumbs are attached to physical HW */ intel_engine_mask_t engine_mask; diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index e971b153fda976..7db9229d28639c 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -63,7 +63,7 @@ static int __engine_unpark(struct intel_wakeref *wf) ENGINE_TRACE(engine, "\n"); - intel_gt_pm_get(engine->gt); + engine->wakeref_track = intel_gt_pm_get(engine->gt); /* Discard stale context state from across idling */ ce = engine->kernel_context; @@ -276,7 +276,7 @@ static int __engine_park(struct intel_wakeref *wf) engine->park(engine); /* While gt calls i915_vma_parked(), we have to break the lock cycle */ - intel_gt_pm_put_async(engine->gt); + intel_gt_pm_put_async(engine->gt, engine->wakeref_track); return 0; } diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 0a071e5da1a85d..2791d487ab114c 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -431,7 +431,9 @@ struct intel_engine_cs { unsigned long serial; unsigned long wakeref_serial; + intel_wakeref_t wakeref_track; struct intel_wakeref wakeref; + struct file *default_state; struct { diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 3c573d41d40468..80d90aa305f1ea 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -630,7 +630,7 @@ static void __execlists_schedule_out(struct i915_request * const rq, execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT); if (engine->fw_domain && !--engine->fw_active) intel_uncore_forcewake_put(engine->uncore, engine->fw_domain); - intel_gt_pm_put_async(engine->gt); + intel_gt_pm_put_async_untracked(engine->gt); /* * If this is part of a virtual engine, its next request may diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index cef3d6f5c34e01..302f908b37fb2e 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -49,19 +49,20 @@ static void mtl_media_idle(struct intel_gt *gt) static void user_forcewake(struct intel_gt *gt, bool suspend) { int count = atomic_read(>->user_wakeref); + intel_wakeref_t wakeref; /* Inside suspend/resume so single threaded, no races to worry about. */ if (likely(!count)) return; - intel_gt_pm_get(gt); + wakeref = intel_gt_pm_get(gt); if (suspend) { GEM_BUG_ON(count > atomic_read(>->wakeref.count)); atomic_sub(count, >->wakeref.count); } else { atomic_add(count, >->wakeref.count); } - intel_gt_pm_put(gt); + intel_gt_pm_put(gt, wakeref); } static void runtime_begin(struct intel_gt *gt) @@ -248,6 +249,7 @@ int intel_gt_resume(struct intel_gt *gt) { struct intel_engine_cs *engine; enum intel_engine_id id; + intel_wakeref_t wakeref; int err; err = intel_gt_has_unrecoverable_error(gt); @@ -264,7 +266,7 @@ int intel_gt_resume(struct intel_gt *gt) */ gt_sanitize(gt, true); - intel_gt_pm_get(gt); + wakeref = intel_gt_pm_get(gt); intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL); intel_rc6_sanitize(>->rc6); @@ -307,7 +309,7 @@ int intel_gt_resume(struct intel_gt *gt) out_fw: intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); - intel_gt_pm_put(gt); + intel_gt_pm_put(gt, wakeref); return err; err_wedged: diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.h b/drivers/gpu/drm/i915/gt/intel_gt_pm.h index 6c9a4645236467..2ae5fbbede6ca8 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.h @@ -16,19 +16,28 @@ static inline bool intel_gt_pm_is_awake(const struct intel_gt *gt) return intel_wakeref_is_active(>->wakeref); } -static inline void intel_gt_pm_get(struct intel_gt *gt) +static inline void intel_gt_pm_get_untracked(struct intel_gt *gt) { intel_wakeref_get(>->wakeref); } +static inline intel_wakeref_t intel_gt_pm_get(struct intel_gt *gt) +{ + intel_gt_pm_get_untracked(gt); + return intel_wakeref_track(>->wakeref); +} + static inline void __intel_gt_pm_get(struct intel_gt *gt) { __intel_wakeref_get(>->wakeref); } -static inline bool intel_gt_pm_get_if_awake(struct intel_gt *gt) +static inline intel_wakeref_t intel_gt_pm_get_if_awake(struct intel_gt *gt) { - return intel_wakeref_get_if_active(>->wakeref); + if (!intel_wakeref_get_if_active(>->wakeref)) + return 0; + + return intel_wakeref_track(>->wakeref); } static inline void intel_gt_pm_might_get(struct intel_gt *gt) @@ -36,12 +45,18 @@ static inline void intel_gt_pm_might_get(struct intel_gt *gt) intel_wakeref_might_get(>->wakeref); } -static inline void intel_gt_pm_put(struct intel_gt *gt) +static inline void intel_gt_pm_put_untracked(struct intel_gt *gt) { intel_wakeref_put(>->wakeref); } -static inline void intel_gt_pm_put_async(struct intel_gt *gt) +static inline void intel_gt_pm_put(struct intel_gt *gt, intel_wakeref_t handle) +{ + intel_wakeref_untrack(>->wakeref, handle); + intel_gt_pm_put_untracked(gt); +} + +static inline void intel_gt_pm_put_async_untracked(struct intel_gt *gt) { intel_wakeref_put_async(>->wakeref); } @@ -51,9 +66,14 @@ static inline void intel_gt_pm_might_put(struct intel_gt *gt) intel_wakeref_might_put(>->wakeref); } -#define with_intel_gt_pm(gt, tmp) \ - for (tmp = 1, intel_gt_pm_get(gt); tmp; \ - intel_gt_pm_put(gt), tmp = 0) +static inline void intel_gt_pm_put_async(struct intel_gt *gt, intel_wakeref_t handle) +{ + intel_wakeref_untrack(>->wakeref, handle); + intel_gt_pm_put_async_untracked(gt); +} + +#define with_intel_gt_pm(gt, wf) \ + for (wf = intel_gt_pm_get(gt); wf; intel_gt_pm_put(gt, wf), wf = 0) /** * with_intel_gt_pm_if_awake - if GT is PM awake, get a reference to prevent @@ -64,7 +84,7 @@ static inline void intel_gt_pm_might_put(struct intel_gt *gt) * @wf: pointer to a temporary wakeref. */ #define with_intel_gt_pm_if_awake(gt, wf) \ - for (wf = intel_gt_pm_get_if_awake(gt); wf; intel_gt_pm_put_async(gt), wf = 0) + for (wf = intel_gt_pm_get_if_awake(gt); wf; intel_gt_pm_put_async(gt, wf), wf = 0) static inline int intel_gt_pm_wait_for_idle(struct intel_gt *gt) { diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c index 83df4cd5e06cb9..0f5ba4491e4de8 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c @@ -27,7 +27,7 @@ void intel_gt_pm_debugfs_forcewake_user_open(struct intel_gt *gt) { atomic_inc(>->user_wakeref); - intel_gt_pm_get(gt); + intel_gt_pm_get_untracked(gt); if (GRAPHICS_VER(gt->i915) >= 6) intel_uncore_forcewake_user_get(gt->uncore); } @@ -36,7 +36,7 @@ void intel_gt_pm_debugfs_forcewake_user_release(struct intel_gt *gt) { if (GRAPHICS_VER(gt->i915) >= 6) intel_uncore_forcewake_user_put(gt->uncore); - intel_gt_pm_put(gt); + intel_gt_pm_put_untracked(gt); atomic_dec(>->user_wakeref); } diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c index 542ce6d2de1922..f3d21bdfd7f639 100644 --- a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c @@ -21,20 +21,22 @@ static int cmp_u32(const void *A, const void *B) return *a - *b; } -static void perf_begin(struct intel_gt *gt) +static intel_wakeref_t perf_begin(struct intel_gt *gt) { - intel_gt_pm_get(gt); + intel_wakeref_t wakeref = intel_gt_pm_get(gt); /* Boost gpufreq to max [waitboost] and keep it fixed */ atomic_inc(>->rps.num_waiters); schedule_work(>->rps.work); flush_work(>->rps.work); + + return wakeref; } -static int perf_end(struct intel_gt *gt) +static int perf_end(struct intel_gt *gt, intel_wakeref_t wakeref) { atomic_dec(>->rps.num_waiters); - intel_gt_pm_put(gt); + intel_gt_pm_put(gt, wakeref); return igt_flush_test(gt->i915); } @@ -133,12 +135,13 @@ static int perf_mi_bb_start(void *arg) struct intel_gt *gt = arg; struct intel_engine_cs *engine; enum intel_engine_id id; + intel_wakeref_t wakeref; int err = 0; if (GRAPHICS_VER(gt->i915) < 4) /* Any CS_TIMESTAMP? */ return 0; - perf_begin(gt); + wakeref = perf_begin(gt); for_each_engine(engine, gt, id) { struct intel_context *ce = engine->kernel_context; struct i915_vma *batch; @@ -207,7 +210,7 @@ static int perf_mi_bb_start(void *arg) pr_info("%s: MI_BB_START cycles: %u\n", engine->name, trifilter(cycles)); } - if (perf_end(gt)) + if (perf_end(gt, wakeref)) err = -EIO; return err; @@ -260,12 +263,13 @@ static int perf_mi_noop(void *arg) struct intel_gt *gt = arg; struct intel_engine_cs *engine; enum intel_engine_id id; + intel_wakeref_t wakeref; int err = 0; if (GRAPHICS_VER(gt->i915) < 4) /* Any CS_TIMESTAMP? */ return 0; - perf_begin(gt); + wakeref = perf_begin(gt); for_each_engine(engine, gt, id) { struct intel_context *ce = engine->kernel_context; struct i915_vma *base, *nop; @@ -364,7 +368,7 @@ static int perf_mi_noop(void *arg) pr_info("%s: 16K MI_NOOP cycles: %u\n", engine->name, trifilter(cycles)); } - if (perf_end(gt)) + if (perf_end(gt, wakeref)) err = -EIO; return err; diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c index b46425aeb2f048..23bd3ab9ddeea1 100644 --- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c @@ -81,6 +81,7 @@ static int live_gt_clocks(void *arg) struct intel_gt *gt = arg; struct intel_engine_cs *engine; enum intel_engine_id id; + intel_wakeref_t wakeref; int err = 0; if (!gt->clock_frequency) { /* unknown */ @@ -91,7 +92,7 @@ static int live_gt_clocks(void *arg) if (GRAPHICS_VER(gt->i915) < 4) /* Any CS_TIMESTAMP? */ return 0; - intel_gt_pm_get(gt); + wakeref = intel_gt_pm_get(gt); intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL); for_each_engine(engine, gt, id) { @@ -128,7 +129,7 @@ static int live_gt_clocks(void *arg) } intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); - intel_gt_pm_put(gt); + intel_gt_pm_put(gt, wakeref); return err; } diff --git a/drivers/gpu/drm/i915/gt/selftest_reset.c b/drivers/gpu/drm/i915/gt/selftest_reset.c index a9e0a91bc0e026..ab464cd72b8c39 100644 --- a/drivers/gpu/drm/i915/gt/selftest_reset.c +++ b/drivers/gpu/drm/i915/gt/selftest_reset.c @@ -257,11 +257,12 @@ static int igt_atomic_reset(void *arg) { struct intel_gt *gt = arg; const typeof(*igt_atomic_phases) *p; + intel_wakeref_t wakeref; int err = 0; /* Check that the resets are usable from atomic context */ - intel_gt_pm_get(gt); + wakeref = intel_gt_pm_get(gt); igt_global_reset_lock(gt); /* Flush any requests before we get started and check basics */ @@ -292,7 +293,7 @@ static int igt_atomic_reset(void *arg) unlock: igt_global_reset_unlock(gt); - intel_gt_pm_put(gt); + intel_gt_pm_put(gt, wakeref); return err; } @@ -303,6 +304,7 @@ static int igt_atomic_engine_reset(void *arg) const typeof(*igt_atomic_phases) *p; struct intel_engine_cs *engine; enum intel_engine_id id; + intel_wakeref_t wakeref; int err = 0; /* Check that the resets are usable from atomic context */ @@ -313,7 +315,7 @@ static int igt_atomic_engine_reset(void *arg) if (intel_uc_uses_guc_submission(>->uc)) return 0; - intel_gt_pm_get(gt); + wakeref = intel_gt_pm_get(gt); igt_global_reset_lock(gt); /* Flush any requests before we get started and check basics */ @@ -361,7 +363,7 @@ static int igt_atomic_engine_reset(void *arg) out_unlock: igt_global_reset_unlock(gt); - intel_gt_pm_put(gt); + intel_gt_pm_put(gt, wakeref); return err; } diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.c b/drivers/gpu/drm/i915/gt/selftest_rps.c index 6755bbc4ebdac0..7052a52e44d74e 100644 --- a/drivers/gpu/drm/i915/gt/selftest_rps.c +++ b/drivers/gpu/drm/i915/gt/selftest_rps.c @@ -223,6 +223,7 @@ int live_rps_clock_interval(void *arg) struct intel_engine_cs *engine; enum intel_engine_id id; struct igt_spinner spin; + intel_wakeref_t wakeref; int err = 0; if (!intel_rps_is_enabled(rps) || GRAPHICS_VER(gt->i915) < 6) @@ -235,7 +236,7 @@ int live_rps_clock_interval(void *arg) saved_work = rps->work.func; rps->work.func = dummy_rps_work; - intel_gt_pm_get(gt); + wakeref = intel_gt_pm_get(gt); intel_rps_disable(>->rps); intel_gt_check_clock_frequency(gt); @@ -354,7 +355,7 @@ int live_rps_clock_interval(void *arg) } intel_rps_enable(>->rps); - intel_gt_pm_put(gt); + intel_gt_pm_put(gt, wakeref); igt_spinner_fini(&spin); @@ -375,6 +376,7 @@ int live_rps_control(void *arg) struct intel_engine_cs *engine; enum intel_engine_id id; struct igt_spinner spin; + intel_wakeref_t wakeref; int err = 0; /* @@ -397,7 +399,7 @@ int live_rps_control(void *arg) saved_work = rps->work.func; rps->work.func = dummy_rps_work; - intel_gt_pm_get(gt); + wakeref = intel_gt_pm_get(gt); for_each_engine(engine, gt, id) { struct i915_request *rq; ktime_t min_dt, max_dt; @@ -487,7 +489,7 @@ int live_rps_control(void *arg) break; } } - intel_gt_pm_put(gt); + intel_gt_pm_put(gt, wakeref); igt_spinner_fini(&spin); @@ -1022,6 +1024,7 @@ int live_rps_interrupt(void *arg) struct intel_engine_cs *engine; enum intel_engine_id id; struct igt_spinner spin; + intel_wakeref_t wakeref; u32 pm_events; int err = 0; @@ -1032,9 +1035,9 @@ int live_rps_interrupt(void *arg) if (!intel_rps_has_interrupts(rps) || GRAPHICS_VER(gt->i915) < 6) return 0; - intel_gt_pm_get(gt); - pm_events = rps->pm_events; - intel_gt_pm_put(gt); + pm_events = 0; + with_intel_gt_pm(gt, wakeref) + pm_events = rps->pm_events; if (!pm_events) { pr_err("No RPS PM events registered, but RPS is enabled?\n"); return -ENODEV; diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c b/drivers/gpu/drm/i915/gt/selftest_slpc.c index bd44ce73a5044e..81fa891eac19fc 100644 --- a/drivers/gpu/drm/i915/gt/selftest_slpc.c +++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c @@ -241,6 +241,7 @@ static int run_test(struct intel_gt *gt, int test_type) struct intel_rps *rps = >->rps; struct intel_engine_cs *engine; enum intel_engine_id id; + intel_wakeref_t wakeref; struct igt_spinner spin; u32 slpc_min_freq, slpc_max_freq; int err = 0; @@ -278,7 +279,7 @@ static int run_test(struct intel_gt *gt, int test_type) } intel_gt_pm_wait_for_idle(gt); - intel_gt_pm_get(gt); + wakeref = intel_gt_pm_get(gt); for_each_engine(engine, gt, id) { struct i915_request *rq; u32 max_act_freq; @@ -365,7 +366,7 @@ static int run_test(struct intel_gt *gt, int test_type) if (igt_flush_test(gt->i915)) err = -EIO; - intel_gt_pm_put(gt); + intel_gt_pm_put(gt, wakeref); igt_spinner_fini(&spin); intel_gt_pm_wait_for_idle(gt); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index be495e657d66bd..978820f8697059 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -1106,7 +1106,7 @@ static void scrub_guc_desc_for_outstanding_g2h(struct intel_guc *guc) if (deregister) guc_signal_context_fence(ce); if (destroyed) { - intel_gt_pm_put_async(guc_to_gt(guc)); + intel_gt_pm_put_async_untracked(guc_to_gt(guc)); release_guc_id(guc, ce); __guc_context_destroy(ce); } @@ -1302,6 +1302,7 @@ static ktime_t guc_engine_busyness(struct intel_engine_cs *engine, ktime_t *now) unsigned long flags; u32 reset_count; bool in_reset; + intel_wakeref_t wakeref; spin_lock_irqsave(&guc->timestamp.lock, flags); @@ -1324,7 +1325,7 @@ static ktime_t guc_engine_busyness(struct intel_engine_cs *engine, ktime_t *now) * start_gt_clk is derived from GuC state. To get a consistent * view of activity, we query the GuC state only if gt is awake. */ - if (!in_reset && intel_gt_pm_get_if_awake(gt)) { + if (!in_reset && (wakeref = intel_gt_pm_get_if_awake(gt))) { stats_saved = *stats; gt_stamp_saved = guc->timestamp.gt_stamp; /* @@ -1333,7 +1334,7 @@ static ktime_t guc_engine_busyness(struct intel_engine_cs *engine, ktime_t *now) */ guc_update_engine_gt_clks(engine); guc_update_pm_timestamp(guc, now); - intel_gt_pm_put_async(gt); + intel_gt_pm_put_async(gt, wakeref); if (i915_reset_count(gpu_error) != reset_count) { *stats = stats_saved; guc->timestamp.gt_stamp = gt_stamp_saved; @@ -4545,7 +4546,7 @@ int intel_guc_deregister_done_process_msg(struct intel_guc *guc, intel_context_put(ce); } else if (context_destroyed(ce)) { /* Context has been destroyed */ - intel_gt_pm_put_async(guc_to_gt(guc)); + intel_gt_pm_put_async_untracked(guc_to_gt(guc)); release_guc_id(guc, ce); __guc_context_destroy(ce); } diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 52531ab28c5f55..737d45d11d9f1f 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -168,19 +168,19 @@ static u64 get_rc6(struct intel_gt *gt) { struct drm_i915_private *i915 = gt->i915; struct i915_pmu *pmu = &i915->pmu; + intel_wakeref_t wakeref; unsigned long flags; - bool awake = false; u64 val; - if (intel_gt_pm_get_if_awake(gt)) { + wakeref = intel_gt_pm_get_if_awake(gt); + if (wakeref) { val = __get_rc6(gt); - intel_gt_pm_put_async(gt); - awake = true; + intel_gt_pm_put_async(gt, wakeref); } spin_lock_irqsave(&pmu->lock, flags); - if (awake) { + if (wakeref) { pmu->sample[__I915_SAMPLE_RC6].cur = val; } else { /* @@ -373,12 +373,14 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns) struct drm_i915_private *i915 = gt->i915; struct i915_pmu *pmu = &i915->pmu; struct intel_rps *rps = >->rps; + intel_wakeref_t wakeref; if (!frequency_sampling_enabled(pmu)) return; /* Report 0/0 (actual/requested) frequency while parked. */ - if (!intel_gt_pm_get_if_awake(gt)) + wakeref = intel_gt_pm_get_if_awake(gt); + if (!wakeref) return; if (pmu->enable & config_mask(I915_PMU_ACTUAL_FREQUENCY)) { @@ -409,7 +411,7 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns) period_ns / 1000); } - intel_gt_pm_put_async(gt); + intel_gt_pm_put_async(gt, wakeref); } static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer) diff --git a/drivers/gpu/drm/i915/intel_wakeref.c b/drivers/gpu/drm/i915/intel_wakeref.c index dfd87d08221807..db4887e33ea607 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.c +++ b/drivers/gpu/drm/i915/intel_wakeref.c @@ -108,6 +108,10 @@ void __intel_wakeref_init(struct intel_wakeref *wf, INIT_DELAYED_WORK(&wf->work, __intel_wakeref_put_work); lockdep_init_map(&wf->work.work.lockdep_map, "wakeref.work", &key->work, 0); + +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_WAKEREF) + intel_wakeref_tracker_init(&wf->debug); +#endif } int intel_wakeref_wait_for_idle(struct intel_wakeref *wf) diff --git a/drivers/gpu/drm/i915/intel_wakeref.h b/drivers/gpu/drm/i915/intel_wakeref.h index 20720fbcc28d46..f2de4ccb7f5377 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.h +++ b/drivers/gpu/drm/i915/intel_wakeref.h @@ -43,6 +43,10 @@ struct intel_wakeref { const struct intel_wakeref_ops *ops; struct delayed_work work; + +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_WAKEREF) + struct intel_wakeref_tracker debug; +#endif }; struct intel_wakeref_lockclass { @@ -261,6 +265,44 @@ __intel_wakeref_defer_park(struct intel_wakeref *wf) */ int intel_wakeref_wait_for_idle(struct intel_wakeref *wf); +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_WAKEREF) + +static inline intel_wakeref_t intel_wakeref_track(struct intel_wakeref *wf) +{ + return intel_wakeref_tracker_add(&wf->debug); +} + +static inline void intel_wakeref_untrack(struct intel_wakeref *wf, + intel_wakeref_t handle) +{ + intel_wakeref_tracker_remove(&wf->debug, handle); +} + +static inline void intel_wakeref_show(struct intel_wakeref *wf, + struct drm_printer *p) +{ + intel_wakeref_tracker_show(&wf->debug, p); +} + +#else + +static inline intel_wakeref_t intel_wakeref_track(struct intel_wakeref *wf) +{ + return -1; +} + +static inline void intel_wakeref_untrack(struct intel_wakeref *wf, + intel_wakeref_t handle) +{ +} + +static inline void intel_wakeref_show(struct intel_wakeref *wf, + struct drm_printer *p) +{ +} + +#endif + struct intel_wakeref_auto { struct intel_runtime_pm *rpm; struct timer_list timer; From patchwork Mon Mar 6 16:32:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 13161756 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CB544C64EC4 for ; Mon, 6 Mar 2023 16:32:54 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C848410E405; Mon, 6 Mar 2023 16:32:52 +0000 (UTC) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by gabe.freedesktop.org (Postfix) with ESMTPS id 29E3810E3FF; Mon, 6 Mar 2023 16:32:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678120370; x=1709656370; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=tWIS1fDOoAR997SIfPLRFSn5hDKzRRgGJcW8CcVa3mw=; b=RxuB9jrQ36H7qpxArGFTmF+Atr0DxOXlJIHvjP3aYZA6qhUHdUylWLcF pTWk12YHbQb3H4pDA9LlwUEechgxkMP7ArST6cILSxv3zZktzKjYKh8wr td4y/2ckzIuVY2lz0h7lNYtpLidZ9lQh2Sik9c8qlbt/WE1kFFQphRwsX DfySHFGs4Jh1Md9ZMqyKs80hZKNiLkGTolQaycq2zyyKiBlrs8h5rfJ8k uSMobpTPLzeKjFNLIhvmVODbmQL4naAfjx4luC9Zv+C+LnDPGYpG1Y1Mf eB8MPtv1W5Ho27rsZQR+sQsMNiL4UQZE9cg9wGddfeyg5uVBFwxYcIaT4 g==; X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="315998813" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="315998813" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:49 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="745132975" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="745132975" Received: from lab-ah.igk.intel.com ([10.102.42.211]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:46 -0800 From: Andrzej Hajda Date: Mon, 06 Mar 2023 17:32:04 +0100 MIME-Version: 1.0 Message-Id: <20230224-track_gt-v4-8-464e8ab4c9ab@intel.com> References: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> In-Reply-To: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> To: Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , Tvrtko Ursulin , David Airlie , Daniel Vetter X-Mailer: b4 0.11.1 Subject: [Intel-gfx] [PATCH v4 08/10] drm/i915: Correct type of wakeref variable X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: netdev@vger.kernel.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Chris Wilson , Eric Dumazet , Chris Wilson , Andrzej Hajda , Jakub Kicinski , Dmitry Vyukov Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Wakeref has dedicated type. Assumption it will be int compatible forever is incorrect. Signed-off-by: Andrzej Hajda Reviewed-by: Andi Shyti --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 978820f8697059..c35f551193c9ad 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -3235,7 +3235,7 @@ static void destroyed_worker_func(struct work_struct *w) struct intel_guc *guc = container_of(w, struct intel_guc, submission_state.destroyed_worker); struct intel_gt *gt = guc_to_gt(guc); - int tmp; + intel_wakeref_t tmp; with_intel_gt_pm(gt, tmp) deregister_destroyed_contexts(guc); From patchwork Mon Mar 6 16:32:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 13161758 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D58E6C678D4 for ; Mon, 6 Mar 2023 16:32:56 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B6DDB10E406; Mon, 6 Mar 2023 16:32:55 +0000 (UTC) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0504D10E407; Mon, 6 Mar 2023 16:32:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678120374; x=1709656374; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=KiQTpG2xC8Lc4w8eZlHLbvB6i35tcjKWEVokJHTrMrE=; b=O5TYHzrNXFKEepMRaoCQqEB+prVN5RQVW9DkFKnbmNnenFcBVylRaDId P99jtbAujBMw0zMLChT7GQt6QF4+TZmykuRusBmHzdS1y6vyO/viOzvvY qYpcRmuUP/4TJlU91jYXBdbfb+tTZN5eVWlJVHEDpXNHAt0+7ENWBLl9x wkBykzYy04k/wYgzKOD4OpY47/vK06QIqLPiXzbtdGKih7DiBX6QAaDhJ vmS1/QbxBiOZD97sQ7lHCOlWFcVXzSs1Fn4wn677yWJyfjw29p7jtfmDA 0gKmGk/p6ljE3Q7rXb1im1bUES+HrbCJqyDxIoJ1AEXR+qOny38h+UpJP w==; X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="315998849" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="315998849" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:53 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="745132988" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="745132988" Received: from lab-ah.igk.intel.com ([10.102.42.211]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:49 -0800 From: Andrzej Hajda Date: Mon, 06 Mar 2023 17:32:05 +0100 MIME-Version: 1.0 Message-Id: <20230224-track_gt-v4-9-464e8ab4c9ab@intel.com> References: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> In-Reply-To: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> To: Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , Tvrtko Ursulin , David Airlie , Daniel Vetter X-Mailer: b4 0.11.1 Subject: [Intel-gfx] [PATCH v4 09/10] drm/i915: replace Intel internal tracker with kernel core ref_tracker X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: netdev@vger.kernel.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Chris Wilson , Eric Dumazet , Chris Wilson , Andrzej Hajda , Jakub Kicinski , Dmitry Vyukov Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Beside reusing existing code, the main advantage of ref_tracker is tracking per instance of wakeref. It allows also to catch double put. On the other side we lose information about the first acquire and the last release, but the advantages outweigh it. v2: Call ref_tracker_dir_exit() only at driver shutdown not during suspend so add intel_runtime_pm_driver_last_release (Nirmoy) Signed-off-by: Andrzej Hajda --- drivers/gpu/drm/i915/Kconfig.debug | 11 +- drivers/gpu/drm/i915/Makefile | 3 - drivers/gpu/drm/i915/display/intel_display_power.c | 2 +- drivers/gpu/drm/i915/gt/intel_engine_pm.c | 2 +- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 2 +- drivers/gpu/drm/i915/i915_driver.c | 2 +- drivers/gpu/drm/i915/intel_runtime_pm.c | 27 ++- drivers/gpu/drm/i915/intel_runtime_pm.h | 3 +- drivers/gpu/drm/i915/intel_wakeref.c | 5 +- drivers/gpu/drm/i915/intel_wakeref.h | 72 ++++++- drivers/gpu/drm/i915/intel_wakeref_tracker.c | 234 --------------------- drivers/gpu/drm/i915/intel_wakeref_tracker.h | 76 ------- 12 files changed, 89 insertions(+), 350 deletions(-) diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug index 63b77dc48d4394..d26fb4569873ea 100644 --- a/drivers/gpu/drm/i915/Kconfig.debug +++ b/drivers/gpu/drm/i915/Kconfig.debug @@ -24,6 +24,7 @@ config DRM_I915_DEBUG select DEBUG_FS select PREEMPT_COUNT select I2C_CHARDEV + select REF_TRACKER select STACKDEPOT select STACKTRACE select DRM_DP_AUX_CHARDEV @@ -38,7 +39,6 @@ config DRM_I915_DEBUG select DRM_I915_DEBUG_GEM select DRM_I915_DEBUG_GEM_ONCE select DRM_I915_DEBUG_MMIO - select DRM_I915_TRACK_WAKEREF select DRM_I915_DEBUG_RUNTIME_PM select DRM_I915_DEBUG_WAKEREF select DRM_I915_SW_FENCE_DEBUG_OBJECTS @@ -230,18 +230,13 @@ config DRM_I915_DEBUG_VBLANK_EVADE If in doubt, say "N". -config DRM_I915_TRACK_WAKEREF - depends on STACKDEPOT - depends on STACKTRACE - bool - config DRM_I915_DEBUG_RUNTIME_PM bool "Enable extra state checking for runtime PM" depends on DRM_I915 default n + select REF_TRACKER select STACKDEPOT select STACKTRACE - select DRM_I915_TRACK_WAKEREF help Choose this option to turn on extra state checking for the runtime PM functionality. This may introduce overhead during @@ -255,9 +250,9 @@ config DRM_I915_DEBUG_WAKEREF bool "Enable extra tracking for wakerefs" depends on DRM_I915 default n + select REF_TRACKER select STACKDEPOT select STACKTRACE - select DRM_I915_TRACK_WAKEREF help Choose this option to turn on extra state checking and usage tracking for the wakerefPM functionality. This may introduce diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 42daff6d575a82..8d64846430f8aa 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -82,9 +82,6 @@ i915-$(CONFIG_DEBUG_FS) += \ display/intel_display_debugfs.o \ display/intel_pipe_crc.o -i915-$(CONFIG_DRM_I915_TRACK_WAKEREF) += \ - intel_wakeref_tracker.o - i915-$(CONFIG_PERF_EVENTS) += i915_pmu.o # "Graphics Technology" (aka we talk to the gpu) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 743b919bb2cfd7..56c0a443f45c75 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -403,7 +403,7 @@ print_async_put_domains_state(struct i915_power_domains *power_domains) struct drm_i915_private, display.power.domains); - drm_dbg(&i915->drm, "async_put_wakeref %u\n", + drm_dbg(&i915->drm, "async_put_wakeref %lu\n", power_domains->async_put_wakeref); print_power_domains(power_domains, "async_put_domains[0]", diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index 7db9229d28639c..7063dea2112943 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -289,7 +289,7 @@ void intel_engine_init__pm(struct intel_engine_cs *engine) { struct intel_runtime_pm *rpm = engine->uncore->rpm; - intel_wakeref_init(&engine->wakeref, rpm, &wf_ops); + intel_wakeref_init(&engine->wakeref, rpm, &wf_ops, engine->name); intel_engine_init_heartbeat(engine); intel_gsc_idle_msg_enable(engine); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index 302f908b37fb2e..7f92aa02b2a013 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -166,7 +166,7 @@ void intel_gt_pm_init_early(struct intel_gt *gt) * runtime_pm is per-device rather than per-tile, so this is still the * correct structure. */ - intel_wakeref_init(>->wakeref, >->i915->runtime_pm, &wf_ops); + intel_wakeref_init(>->wakeref, >->i915->runtime_pm, &wf_ops, "GT"); seqcount_mutex_init(>->stats.lock, >->wakeref.mutex); } diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index e3244972521cb1..e971670f4a0e98 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -1017,7 +1017,7 @@ void i915_driver_shutdown(struct drm_i915_private *i915) intel_power_domains_driver_remove(i915); enable_rpm_wakeref_asserts(&i915->runtime_pm); - intel_runtime_pm_driver_release(&i915->runtime_pm); + intel_runtime_pm_driver_last_release(&i915->runtime_pm); } static bool suspend_to_idle(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 43149cf12dc864..7e05098e5d3276 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -54,7 +54,7 @@ static void init_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm) { - intel_wakeref_tracker_init(&rpm->debug); + ref_tracker_dir_init(&rpm->debug, INTEL_REFTRACK_DEAD_COUNT, dev_name(rpm->kdev)); } static intel_wakeref_t @@ -63,26 +63,26 @@ track_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm) if (!rpm->available || rpm->no_wakeref_tracking) return -1; - return intel_wakeref_tracker_add(&rpm->debug); + return intel_ref_tracker_alloc(&rpm->debug); } static void untrack_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm, intel_wakeref_t wakeref) { - intel_wakeref_tracker_remove(&rpm->debug, wakeref); + if (!rpm->available || rpm->no_wakeref_tracking) + return; + + intel_ref_tracker_free(&rpm->debug, wakeref); } static void untrack_all_intel_runtime_pm_wakerefs(struct intel_runtime_pm *rpm) { - struct drm_printer p = drm_debug_printer("i915"); - - intel_wakeref_tracker_reset(&rpm->debug, &p); + ref_tracker_dir_exit(&rpm->debug); } static noinline void __intel_wakeref_dec_and_check_tracking(struct intel_runtime_pm *rpm) { - struct intel_wakeref_tracker saved; unsigned long flags; if (!atomic_dec_and_lock_irqsave(&rpm->wakeref_count, @@ -90,15 +90,8 @@ __intel_wakeref_dec_and_check_tracking(struct intel_runtime_pm *rpm) flags)) return; - saved = __intel_wakeref_tracker_reset(&rpm->debug); + __ref_tracker_dir_print(&rpm->debug, INTEL_REFTRACK_PRINT_LIMIT); spin_unlock_irqrestore(&rpm->debug.lock, flags); - - if (saved.count) { - struct drm_printer p = drm_debug_printer("i915"); - - __intel_wakeref_tracker_show(&saved, &p); - intel_wakeref_tracker_fini(&saved); - } } void print_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm, @@ -455,7 +448,11 @@ void intel_runtime_pm_driver_release(struct intel_runtime_pm *rpm) "i915 raw-wakerefs=%d wakelocks=%d on cleanup\n", intel_rpm_raw_wakeref_count(count), intel_rpm_wakelock_count(count)); +} +void intel_runtime_pm_driver_last_release(struct intel_runtime_pm *rpm) +{ + intel_runtime_pm_driver_release(rpm); untrack_all_intel_runtime_pm_wakerefs(rpm); } diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.h b/drivers/gpu/drm/i915/intel_runtime_pm.h index a8dc2baf79844f..2f81d685bdb4d1 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.h +++ b/drivers/gpu/drm/i915/intel_runtime_pm.h @@ -83,7 +83,7 @@ struct intel_runtime_pm { * paired rpm_put) we can remove corresponding pairs of and keep * the array trimmed to active wakerefs. */ - struct intel_wakeref_tracker debug; + struct ref_tracker_dir debug; #endif }; @@ -187,6 +187,7 @@ void intel_runtime_pm_init_early(struct intel_runtime_pm *rpm); void intel_runtime_pm_enable(struct intel_runtime_pm *rpm); void intel_runtime_pm_disable(struct intel_runtime_pm *rpm); void intel_runtime_pm_driver_release(struct intel_runtime_pm *rpm); +void intel_runtime_pm_driver_last_release(struct intel_runtime_pm *rpm); intel_wakeref_t intel_runtime_pm_get(struct intel_runtime_pm *rpm); intel_wakeref_t intel_runtime_pm_get_if_in_use(struct intel_runtime_pm *rpm); diff --git a/drivers/gpu/drm/i915/intel_wakeref.c b/drivers/gpu/drm/i915/intel_wakeref.c index db4887e33ea607..61f974d97a3757 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.c +++ b/drivers/gpu/drm/i915/intel_wakeref.c @@ -96,7 +96,8 @@ static void __intel_wakeref_put_work(struct work_struct *wrk) void __intel_wakeref_init(struct intel_wakeref *wf, struct intel_runtime_pm *rpm, const struct intel_wakeref_ops *ops, - struct intel_wakeref_lockclass *key) + struct intel_wakeref_lockclass *key, + const char *name) { wf->rpm = rpm; wf->ops = ops; @@ -110,7 +111,7 @@ void __intel_wakeref_init(struct intel_wakeref *wf, "wakeref.work", &key->work, 0); #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_WAKEREF) - intel_wakeref_tracker_init(&wf->debug); + ref_tracker_dir_init(&wf->debug, INTEL_REFTRACK_DEAD_COUNT, name); #endif } diff --git a/drivers/gpu/drm/i915/intel_wakeref.h b/drivers/gpu/drm/i915/intel_wakeref.h index f2de4ccb7f5377..cf6828f13943d7 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.h +++ b/drivers/gpu/drm/i915/intel_wakeref.h @@ -7,17 +7,24 @@ #ifndef INTEL_WAKEREF_H #define INTEL_WAKEREF_H +#include + #include #include #include #include #include #include +#include +#include #include #include #include -#include "intel_wakeref_tracker.h" +typedef unsigned long intel_wakeref_t; + +#define INTEL_REFTRACK_DEAD_COUNT 16 +#define INTEL_REFTRACK_PRINT_LIMIT 16 #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_WAKEREF) #define INTEL_WAKEREF_BUG_ON(expr) BUG_ON(expr) @@ -45,7 +52,7 @@ struct intel_wakeref { struct delayed_work work; #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_WAKEREF) - struct intel_wakeref_tracker debug; + struct ref_tracker_dir debug; #endif }; @@ -57,11 +64,12 @@ struct intel_wakeref_lockclass { void __intel_wakeref_init(struct intel_wakeref *wf, struct intel_runtime_pm *rpm, const struct intel_wakeref_ops *ops, - struct intel_wakeref_lockclass *key); -#define intel_wakeref_init(wf, rpm, ops) do { \ + struct intel_wakeref_lockclass *key, + const char *name); +#define intel_wakeref_init(wf, rpm, ops, name) do { \ static struct intel_wakeref_lockclass __key; \ \ - __intel_wakeref_init((wf), (rpm), (ops), &__key); \ + __intel_wakeref_init((wf), (rpm), (ops), &__key, name); \ } while (0) int __intel_wakeref_get_first(struct intel_wakeref *wf); @@ -265,17 +273,67 @@ __intel_wakeref_defer_park(struct intel_wakeref *wf) */ int intel_wakeref_wait_for_idle(struct intel_wakeref *wf); +#define INTEL_WAKEREF_DEF ((intel_wakeref_t)(-1)) + +static inline intel_wakeref_t intel_ref_tracker_alloc(struct ref_tracker_dir *dir) +{ + struct ref_tracker *user = NULL; + + ref_tracker_alloc(dir, &user, GFP_NOWAIT); + + return (intel_wakeref_t)user ?: INTEL_WAKEREF_DEF; +} + +static inline void intel_ref_tracker_free(struct ref_tracker_dir *dir, + intel_wakeref_t handle) +{ + struct ref_tracker *user; + + user = (handle == INTEL_WAKEREF_DEF) ? NULL : (void *)handle; + + ref_tracker_free(dir, &user); +} + +static inline void +intel_wakeref_tracker_show(struct ref_tracker_dir *dir, + struct drm_printer *p) +{ + const size_t buf_size = PAGE_SIZE; + char *buf, *sb, *se; + size_t count; + + buf = kmalloc(buf_size, GFP_NOWAIT); + if (!buf) + return; + + count = ref_tracker_dir_snprint(dir, buf, buf_size); + if (!count) + goto free; + /* printk does not like big buffers, so we split it */ + for (sb = buf; *sb; sb = se + 1) { + se = strchrnul(sb, '\n'); + drm_printf(p, "%.*s", (int)(se - sb + 1), sb); + if (!*se) + break; + } + if (count >= buf_size) + drm_printf(p, "\n...dropped %zd extra bytes of leak report.\n", + count + 1 - buf_size); +free: + kfree(buf); +} + #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_WAKEREF) static inline intel_wakeref_t intel_wakeref_track(struct intel_wakeref *wf) { - return intel_wakeref_tracker_add(&wf->debug); + return intel_ref_tracker_alloc(&wf->debug); } static inline void intel_wakeref_untrack(struct intel_wakeref *wf, intel_wakeref_t handle) { - intel_wakeref_tracker_remove(&wf->debug, handle); + intel_ref_tracker_free(&wf->debug, handle); } static inline void intel_wakeref_show(struct intel_wakeref *wf, diff --git a/drivers/gpu/drm/i915/intel_wakeref_tracker.c b/drivers/gpu/drm/i915/intel_wakeref_tracker.c deleted file mode 100644 index c92035030a75cc..00000000000000 --- a/drivers/gpu/drm/i915/intel_wakeref_tracker.c +++ /dev/null @@ -1,234 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright © 2021 Intel Corporation - */ - -#include -#include -#include -#include - -#include - -#include "intel_wakeref_tracker.h" - -#define STACKDEPTH 8 - -static noinline depot_stack_handle_t __save_depot_stack(void) -{ - unsigned long entries[STACKDEPTH]; - unsigned int n; - - n = stack_trace_save(entries, ARRAY_SIZE(entries), 1); - return stack_depot_save(entries, n, GFP_NOWAIT | __GFP_NOWARN); -} - -static void __print_depot_stack(depot_stack_handle_t stack, - char *buf, int sz, int indent) -{ - unsigned long *entries; - unsigned int nr_entries; - - nr_entries = stack_depot_fetch(stack, &entries); - stack_trace_snprint(buf, sz, entries, nr_entries, indent); -} - -static int cmphandle(const void *_a, const void *_b) -{ - const depot_stack_handle_t * const a = _a, * const b = _b; - - if (*a < *b) - return -1; - else if (*a > *b) - return 1; - else - return 0; -} - -void -__intel_wakeref_tracker_show(const struct intel_wakeref_tracker *w, - struct drm_printer *p) -{ - unsigned long i; - char *buf; - - buf = kmalloc(PAGE_SIZE, GFP_NOWAIT | __GFP_NOWARN); - if (!buf) - return; - - if (w->last_acquire) { - __print_depot_stack(w->last_acquire, buf, PAGE_SIZE, 2); - drm_printf(p, "Wakeref last acquired:\n%s", buf); - } - - if (w->last_release) { - __print_depot_stack(w->last_release, buf, PAGE_SIZE, 2); - drm_printf(p, "Wakeref last released:\n%s", buf); - } - - drm_printf(p, "Wakeref count: %lu\n", w->count); - - sort(w->owners, w->count, sizeof(*w->owners), cmphandle, NULL); - - for (i = 0; i < w->count; i++) { - depot_stack_handle_t stack = w->owners[i]; - unsigned long rep; - - rep = 1; - while (i + 1 < w->count && w->owners[i + 1] == stack) - rep++, i++; - __print_depot_stack(stack, buf, PAGE_SIZE, 2); - drm_printf(p, "Wakeref x%lu taken at:\n%s", rep, buf); - } - - kfree(buf); -} - -void intel_wakeref_tracker_show(struct intel_wakeref_tracker *w, - struct drm_printer *p) -{ - struct intel_wakeref_tracker tmp = {}; - - do { - unsigned long alloc = tmp.count; - depot_stack_handle_t *s; - - spin_lock_irq(&w->lock); - tmp.count = w->count; - if (tmp.count <= alloc) - memcpy(tmp.owners, w->owners, tmp.count * sizeof(*s)); - tmp.last_acquire = w->last_acquire; - tmp.last_release = w->last_release; - spin_unlock_irq(&w->lock); - if (tmp.count <= alloc) - break; - - s = krealloc(tmp.owners, - tmp.count * sizeof(*s), - GFP_NOWAIT | __GFP_NOWARN); - if (!s) - goto out; - - tmp.owners = s; - } while (1); - - __intel_wakeref_tracker_show(&tmp, p); - -out: - intel_wakeref_tracker_fini(&tmp); -} - -intel_wakeref_t intel_wakeref_tracker_add(struct intel_wakeref_tracker *w) -{ - depot_stack_handle_t stack, *stacks; - unsigned long flags; - - stack = __save_depot_stack(); - if (!stack) - return -1; - - spin_lock_irqsave(&w->lock, flags); - - if (!w->count) - w->last_acquire = stack; - - stacks = krealloc(w->owners, - (w->count + 1) * sizeof(*stacks), - GFP_NOWAIT | __GFP_NOWARN); - if (stacks) { - stacks[w->count++] = stack; - w->owners = stacks; - } else { - stack = -1; - } - - spin_unlock_irqrestore(&w->lock, flags); - - return stack; -} - -void intel_wakeref_tracker_remove(struct intel_wakeref_tracker *w, - intel_wakeref_t stack) -{ - unsigned long flags, n; - bool found = false; - - if (unlikely(stack == -1)) - return; - - spin_lock_irqsave(&w->lock, flags); - for (n = w->count; n--; ) { - if (w->owners[n] == stack) { - memmove(w->owners + n, - w->owners + n + 1, - (--w->count - n) * sizeof(stack)); - found = true; - break; - } - } - spin_unlock_irqrestore(&w->lock, flags); - - if (WARN(!found, - "Unmatched wakeref %x, tracking %lu\n", - stack, w->count)) { - char *buf; - - buf = kmalloc(PAGE_SIZE, GFP_NOWAIT | __GFP_NOWARN); - if (!buf) - return; - - __print_depot_stack(stack, buf, PAGE_SIZE, 2); - pr_err("wakeref %x from\n%s", stack, buf); - - stack = READ_ONCE(w->last_release); - if (stack && !w->count) { - __print_depot_stack(stack, buf, PAGE_SIZE, 2); - pr_err("wakeref last released at\n%s", buf); - } - - kfree(buf); - } -} - -struct intel_wakeref_tracker -__intel_wakeref_tracker_reset(struct intel_wakeref_tracker *w) -{ - struct intel_wakeref_tracker saved; - - lockdep_assert_held(&w->lock); - - saved = *w; - - w->owners = NULL; - w->count = 0; - w->last_release = __save_depot_stack(); - - return saved; -} - -void intel_wakeref_tracker_reset(struct intel_wakeref_tracker *w, - struct drm_printer *p) -{ - struct intel_wakeref_tracker tmp; - - spin_lock_irq(&w->lock); - tmp = __intel_wakeref_tracker_reset(w); - spin_unlock_irq(&w->lock); - - if (tmp.count) - __intel_wakeref_tracker_show(&tmp, p); - - intel_wakeref_tracker_fini(&tmp); -} - -void intel_wakeref_tracker_init(struct intel_wakeref_tracker *w) -{ - memset(w, 0, sizeof(*w)); - spin_lock_init(&w->lock); - stack_depot_init(); -} - -void intel_wakeref_tracker_fini(struct intel_wakeref_tracker *w) -{ - kfree(w->owners); -} diff --git a/drivers/gpu/drm/i915/intel_wakeref_tracker.h b/drivers/gpu/drm/i915/intel_wakeref_tracker.h deleted file mode 100644 index 61df68e28c0fbf..00000000000000 --- a/drivers/gpu/drm/i915/intel_wakeref_tracker.h +++ /dev/null @@ -1,76 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2019 Intel Corporation - */ - -#ifndef INTEL_WAKEREF_TRACKER_H -#define INTEL_WAKEREF_TRACKER_H - -#include -#include -#include - -typedef depot_stack_handle_t intel_wakeref_t; - -struct drm_printer; - -struct intel_wakeref_tracker { - spinlock_t lock; - - depot_stack_handle_t last_acquire; - depot_stack_handle_t last_release; - - depot_stack_handle_t *owners; - unsigned long count; -}; - -#if IS_ENABLED(CONFIG_DRM_I915_TRACK_WAKEREF) - -void intel_wakeref_tracker_init(struct intel_wakeref_tracker *w); -void intel_wakeref_tracker_fini(struct intel_wakeref_tracker *w); - -intel_wakeref_t intel_wakeref_tracker_add(struct intel_wakeref_tracker *w); -void intel_wakeref_tracker_remove(struct intel_wakeref_tracker *w, - intel_wakeref_t handle); - -struct intel_wakeref_tracker -__intel_wakeref_tracker_reset(struct intel_wakeref_tracker *w); -void intel_wakeref_tracker_reset(struct intel_wakeref_tracker *w, - struct drm_printer *p); - -void __intel_wakeref_tracker_show(const struct intel_wakeref_tracker *w, - struct drm_printer *p); -void intel_wakeref_tracker_show(struct intel_wakeref_tracker *w, - struct drm_printer *p); - -#else - -static inline void intel_wakeref_tracker_init(struct intel_wakeref_tracker *w) {} -static inline void intel_wakeref_tracker_fini(struct intel_wakeref_tracker *w) {} - -static inline intel_wakeref_t -intel_wakeref_tracker_add(struct intel_wakeref_tracker *w) -{ - return -1; -} - -static inline void -intel_wakeref_untrack_remove(struct intel_wakeref_tracker *w, intel_wakeref_t handle) {} - -static inline struct intel_wakeref_tracker -__intel_wakeref_tracker_reset(struct intel_wakeref_tracker *w) -{ - return (struct intel_wakeref_tracker){}; -} - -static inline void intel_wakeref_tracker_reset(struct intel_wakeref_tracker *w, - struct drm_printer *p) -{ -} - -static inline void __intel_wakeref_tracker_show(const struct intel_wakeref_tracker *w, struct drm_printer *p) {} -static inline void intel_wakeref_tracker_show(struct intel_wakeref_tracker *w, struct drm_printer *p) {} - -#endif - -#endif /* INTEL_WAKEREF_TRACKER_H */ From patchwork Mon Mar 6 16:32:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 13161759 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BFB20C6FA99 for ; Mon, 6 Mar 2023 16:32:59 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0C8B210E409; Mon, 6 Mar 2023 16:32:59 +0000 (UTC) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by gabe.freedesktop.org (Postfix) with ESMTPS id 9BC2B10E408; Mon, 6 Mar 2023 16:32:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678120376; x=1709656376; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=LsmUDbnIlE4apXp83QZEhT9gpY1ZA5IO+nuheEoXvek=; b=k3hXChjW2Yz0HkiCu3nBJQrpeHMyDsRRoONX1KXcqf3rgH/BL8TtDfdL JWjrUKlDhI9C1TKSdzxOw6SfJpxTxKQ1ICZbb9JSv4iQjac45sHx4TmMU x59zJjk+bvmTQhHcrp08GivhVg09LTMv2/hNa58E6LnQ0PI60y8kpWd0/ kPUJOeE0k1eDLc+V3E5vGKBS8Er23oqf7P7gU9MtQrDC+bBmwZB2kC3oH OwcKTqP1s8OuJVBOdhADlDF4cgMr1KAS7iHSjxeWJonMPx8jnklzcmdWe rTnx70yriT/kEEI8isiCibiPBsPH2XwyXxYCph/FM/j5Ngl0WO+f9Ifsb w==; X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="315998878" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="315998878" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:56 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10641"; a="745133009" X-IronPort-AV: E=Sophos;i="5.98,238,1673942400"; d="scan'208";a="745133009" Received: from lab-ah.igk.intel.com ([10.102.42.211]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Mar 2023 08:32:53 -0800 From: Andrzej Hajda Date: Mon, 06 Mar 2023 17:32:06 +0100 MIME-Version: 1.0 Message-Id: <20230224-track_gt-v4-10-464e8ab4c9ab@intel.com> References: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> In-Reply-To: <20230224-track_gt-v4-0-464e8ab4c9ab@intel.com> To: Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , Tvrtko Ursulin , David Airlie , Daniel Vetter X-Mailer: b4 0.11.1 Subject: [Intel-gfx] [PATCH v4 10/10] drm/i915/gt: Hold a wakeref for the active VM X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: netdev@vger.kernel.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Chris Wilson , Eric Dumazet , Chris Wilson , Andrzej Hajda , Jakub Kicinski , Dmitry Vyukov Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Chris Wilson There may be a disconnect between the GT used by the engine and the GT used for the VM, requiring us to hold a wakeref on both while the GPU is active with this request. Signed-off-by: Chris Wilson Signed-off-by: Andrzej Hajda --- drivers/gpu/drm/i915/gt/intel_context.h | 15 +++++++++++---- drivers/gpu/drm/i915/gt/intel_context_types.h | 2 ++ drivers/gpu/drm/i915/gt/intel_engine_pm.c | 4 ++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context.h b/drivers/gpu/drm/i915/gt/intel_context.h index 0a8d553da3f439..582faa21181e58 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.h +++ b/drivers/gpu/drm/i915/gt/intel_context.h @@ -14,6 +14,7 @@ #include "i915_drv.h" #include "intel_context_types.h" #include "intel_engine_types.h" +#include "intel_gt_pm.h" #include "intel_ring_types.h" #include "intel_timeline_types.h" #include "i915_trace.h" @@ -207,8 +208,11 @@ void intel_context_exit_engine(struct intel_context *ce); static inline void intel_context_enter(struct intel_context *ce) { lockdep_assert_held(&ce->timeline->mutex); - if (!ce->active_count++) - ce->ops->enter(ce); + if (ce->active_count++) + return; + + ce->ops->enter(ce); + ce->wakeref = intel_gt_pm_get(ce->vm->gt); } static inline void intel_context_mark_active(struct intel_context *ce) @@ -222,8 +226,11 @@ static inline void intel_context_exit(struct intel_context *ce) { lockdep_assert_held(&ce->timeline->mutex); GEM_BUG_ON(!ce->active_count); - if (!--ce->active_count) - ce->ops->exit(ce); + if (--ce->active_count) + return; + + intel_gt_pm_put_async(ce->vm->gt, ce->wakeref); + ce->ops->exit(ce); } static inline struct intel_context *intel_context_get(struct intel_context *ce) diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index e36670f2e6260b..5dc39a9d7a501c 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -17,6 +17,7 @@ #include "i915_utils.h" #include "intel_engine_types.h" #include "intel_sseu.h" +#include "intel_wakeref.h" #include "uc/intel_guc_fwif.h" @@ -110,6 +111,7 @@ struct intel_context { u32 ring_size; struct intel_ring *ring; struct intel_timeline *timeline; + intel_wakeref_t wakeref; unsigned long flags; #define CONTEXT_BARRIER_BIT 0 diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index 7063dea2112943..c2d17c97bfe989 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -114,6 +114,10 @@ __queue_and_release_pm(struct i915_request *rq, ENGINE_TRACE(engine, "parking\n"); + GEM_BUG_ON(rq->context->active_count != 1); + __intel_gt_pm_get(engine->gt); + rq->context->wakeref = intel_wakeref_track(&engine->gt->wakeref); + /* * We have to serialise all potential retirement paths with our * submission, as we don't want to underflow either the