Received: by 2002:a05:6a10:7420:0:0:0:0 with SMTP id hk32csp4424172pxb; Mon, 21 Feb 2022 21:10:41 -0800 (PST) X-Google-Smtp-Source: ABdhPJzGguRlpWBbkIdPwGUUL6UBEjNx+6QSuoUQib0PZ82bqvO3xZSXEakhAO286QD0muUltm8X X-Received: by 2002:a17:90b:2513:b0:1bc:545d:8dbe with SMTP id ns19-20020a17090b251300b001bc545d8dbemr2377059pjb.182.1645506641710; Mon, 21 Feb 2022 21:10:41 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1645506641; cv=none; d=google.com; s=arc-20160816; b=qGgK1hig/UjNqQPKI8HnPntz6va4AoN/u8M+92l0zM5Xt/sg1g5/loZKCY7OqUOeh+ DFJe2AEEi4V2H/bckAitcnSEDHZP/MOcIT5y2Tz6eADkfaUtaXNhWQCIfVBxAaxKlbF6 pBe33tmAtluB9DRmfh7DNOnyv7XMhJBZ+/HPzji4zCa9stCmx2W/70UHDb0ApGNYc9O9 H5vtsKqxfmOuppEIa2C7z2qcOEZRS5eewF6BzfUGqKCEdue+ch025E5xbayWWVHjjg/o nMdyVPIbDXkac6BiWhr6y2GSgzrdEB3m07wjzHoNNwvRWdCmS3Y1iPB1xO4fAVvghVtY ldOQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:organization :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=/YQACXeV5l6f7ganPslhmGnej8gX60h1OosUY5UJaps=; b=cGGNoEbE6r/kEd6IUVpQkyi//37bmDfwiBldVib3tgOLtNznqSjGMnp0L4J74HW25N x7UAJ4ZoOStgT88noImGK1Xk+fjZm35T/ZaDkb2wUfVmiXF7XoqBUWUbwWFjG/XZho7d ae+X53H0w48UtPVRzTpAg69x3lqEyuFhl+Bj/tCqKoU4c/KJsijvWeuwpPcL+fMPvJHN COA0iU3ItIg9ngx7HhcMUFkLkKoL/2yoiucRu1pCK2N6OYpJ8y4+85Mc2WQbnBkn4P8M TqaqfsjwqRJAHmvwgNc2P09JIrQsC28/1RwLfC2gQs2ZCPCvx+gNjSZroEbn4Adz5Xjq d/LA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b="YqNN6jY/"; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [23.128.96.19]) by mx.google.com with ESMTPS id c8si2104307pll.597.2022.02.21.21.10.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Feb 2022 21:10:41 -0800 (PST) Received-SPF: softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) client-ip=23.128.96.19; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b="YqNN6jY/"; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id CE6D0CB90B; Mon, 21 Feb 2022 20:43:30 -0800 (PST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237054AbiBUX1i (ORCPT + 99 others); Mon, 21 Feb 2022 18:27:38 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:41210 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236923AbiBUX07 (ORCPT ); Mon, 21 Feb 2022 18:26:59 -0500 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 773AE24F19; Mon, 21 Feb 2022 15:26:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1645485992; x=1677021992; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+cYQCtajtLHF13wD1Ab8Zm6c/BiUXjG1ZHacvq+QS4Q=; b=YqNN6jY/VVreuZzx6UJEp5TyEDXQ05tegOquQ0UI0Q2RzPPsgtv5pFfc xNsdLXlrsRwEK1jB3GTZl7oNtVrOOFRy/KmAFipxfMFDtYwYuRyjNBYbr 9w2GUjPZoOos4443uqCOxkRH07/VvKFNkfbuIOUI4gbKBKPxibTLGY6ic yygtSY7SjFNvHqWA/GecgqYEGu09ssJF/K0qn3hyiA4Mxf7xxascsBX2Y RRjY6LiCv99aJL0OMmh6LYz3+mNulDgB7zxjTAn9Y4VFCKEdKybAnThhK Ca3pdCGCc1Iaub7LxBfM7JiuEKd58BZCCa639ahH1AQTOg9LD/AelPyFc g==; X-IronPort-AV: E=McAfee;i="6200,9189,10265"; a="338011939" X-IronPort-AV: E=Sophos;i="5.88,386,1635231600"; d="scan'208";a="338011939" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Feb 2022 15:26:31 -0800 X-IronPort-AV: E=Sophos;i="5.88,386,1635231600"; d="scan'208";a="706397094" Received: from lab-ah.igk.intel.com ([10.91.215.196]) by orsmga005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Feb 2022 15:26:28 -0800 From: Andrzej Hajda To: linux-kernel@vger.kernel.org, intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org, netdev Cc: Andrzej Hajda , Jani Nikula , Daniel Vetter , Lucas De Marchi , Chris Wilson , Eric Dumazet , Dmitry Vyukov , Jakub Kicinski Subject: [PATCH v3 11/11] drm/i915: replace Intel internal tracker with kernel core ref_tracker Date: Tue, 22 Feb 2022 00:25:42 +0100 Message-Id: <20220221232542.1481315-12-andrzej.hajda@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220221232542.1481315-1-andrzej.hajda@intel.com> References: <20220221232542.1481315-1-andrzej.hajda@intel.com> MIME-Version: 1.0 Organization: Intel Technology Poland sp. z o.o. - ul. Slowackiego 173, 80-298 Gdansk - KRS 101882 - NIP 957-07-52-316 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=0.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,PDS_OTHER_BAD_TLD,RDNS_NONE,SPF_HELO_NONE, T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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. Signed-off-by: Andrzej Hajda Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/Kconfig.debug | 11 +- drivers/gpu/drm/i915/Makefile | 3 - .../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/intel_runtime_pm.c | 25 +- drivers/gpu/drm/i915/intel_runtime_pm.h | 2 +- drivers/gpu/drm/i915/intel_wakeref.c | 8 +- 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 ------ 11 files changed, 87 insertions(+), 350 deletions(-) delete mode 100644 drivers/gpu/drm/i915/intel_wakeref_tracker.c delete mode 100644 drivers/gpu/drm/i915/intel_wakeref_tracker.h diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug index 3bdc73f30a9e1..6c57f3e265f20 100644 --- a/drivers/gpu/drm/i915/Kconfig.debug +++ b/drivers/gpu/drm/i915/Kconfig.debug @@ -32,6 +32,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 @@ -46,7 +47,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 @@ -238,18 +238,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 @@ -263,9 +258,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 88a403d3294cb..1f8d71430e2e6 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -76,9 +76,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 9ebae7ac32356..0e1bf724f89b5 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -2107,7 +2107,7 @@ print_async_put_domains_state(struct i915_power_domains *power_domains) struct drm_i915_private, 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 52e46e7830ff5..cf8cc348942cb 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -273,7 +273,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); } diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index 7ee65a93f926f..01a055d0d0989 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -129,7 +129,7 @@ static const struct intel_wakeref_ops wf_ops = { void intel_gt_pm_init_early(struct intel_gt *gt) { - intel_wakeref_init(>->wakeref, gt->uncore->rpm, &wf_ops); + intel_wakeref_init(>->wakeref, gt->uncore->rpm, &wf_ops, "GT"); seqcount_mutex_init(>->stats.lock, >->wakeref.mutex); } diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 7bd10efa56bf3..18e4b2f169e75 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -54,35 +54,35 @@ 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 track_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm) { - if (!rpm->available) + 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, diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.h b/drivers/gpu/drm/i915/intel_runtime_pm.h index 0871fa2176474..db5692f1eb67e 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.h +++ b/drivers/gpu/drm/i915/intel_runtime_pm.h @@ -61,7 +61,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 }; diff --git a/drivers/gpu/drm/i915/intel_wakeref.c b/drivers/gpu/drm/i915/intel_wakeref.c index db4887e33ea60..97fe9a0f0adbd 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.c +++ b/drivers/gpu/drm/i915/intel_wakeref.c @@ -62,6 +62,9 @@ static void ____intel_wakeref_put_last(struct intel_wakeref *wf) if (likely(!wf->ops->put(wf))) { rpm_put(wf); wake_up_var(&wf->wakeref); +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_WAKEREF) + ref_tracker_dir_exit(&wf->debug); +#endif } unlock: @@ -96,7 +99,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 +114,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 38439deefc5cc..e0cd78fb60761 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); @@ -266,17 +274,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 a0bcef13a1085..0000000000000 --- 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.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 61df68e28c0fb..0000000000000 --- 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 */ -- 2.25.1