From patchwork Mon Sep 18 11:38:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 9956547 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E9F11601E9 for ; Mon, 18 Sep 2017 11:38:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D8EAC28BE5 for ; Mon, 18 Sep 2017 11:38:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CC60B28C1F; Mon, 18 Sep 2017 11:38:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 48A9D28BE5 for ; Mon, 18 Sep 2017 11:38:30 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D4AFE6E34D; Mon, 18 Sep 2017 11:38:29 +0000 (UTC) X-Original-To: Intel-gfx@lists.freedesktop.org Delivered-To: Intel-gfx@lists.freedesktop.org Received: from mail-wr0-x243.google.com (mail-wr0-x243.google.com [IPv6:2a00:1450:400c:c0c::243]) by gabe.freedesktop.org (Postfix) with ESMTPS id E0ABE6E34C for ; Mon, 18 Sep 2017 11:38:27 +0000 (UTC) Received: by mail-wr0-x243.google.com with SMTP id n64so159379wrb.2 for ; Mon, 18 Sep 2017 04:38:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ursulin-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=QsupDse8AxrRHmw9twDCtf22dGAdl7Y1PC2jPt8M9FM=; b=GcpzcLyOsR9DacA4XB4oWpZ3SFsqY9kmGwBvrrJMNAD4x3DUKVKmD47mKl0ZFkVy/L wvfkqbpkHuWZ+S9fluMjkveGZg4qaw3GJI4cvI6s/Vcs9Oucf9HIDzX6dS8Ak5qBVc5I 7NeCv+prbnxATPHSlepoU5Ag/UM9h3Aher9e3e3P4cThf1MKobq9bnMCgq21knDHFYfQ kJQwXJAaOlR1H1ipG3fm2vF0KKuegxr2PuQY1fadoLjSTS4YzB4hq022kAJ/Htc0Fqsq fnuIyeucA2miOxc1v7kgPRWZ7Q2QFjWq7FoXkrQhzUAehonuSxunQsChX4NFmm+yMQh/ yBMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=QsupDse8AxrRHmw9twDCtf22dGAdl7Y1PC2jPt8M9FM=; b=kHO5j4G1ksKNgkwzN9G3P2ma/8NUZuz4vEbjL6TJ7GvjeO/rbQkMjCiAqlxyilDWl7 wEz9bAEMQGPqU97BumQw3JuKDmSsLUdMT9TNEBFi6bjPBy055GE19bZJaSWBkO/wOSjs 7FJsA4cF5qEN93norDh/+S6R9OK1kGfOTSoFu0oI0+/wCRJ24nYiazfPLO3feDTpbYod eJ9os+AULlDCrrMKuTi1tMQ0yiWU8GTLGObJ05bUAYWiOSYnpLOs7cxEgeo56FH8Xm37 dCol3ct1PUbNUC1paBJisb0RJH3WehnE2UrLdTtobB1eJ5wX0+9nznn6W0wnCBejwj/z 6UQA== X-Gm-Message-State: AHPjjUhYSJ3ue+llFRHVzLt/5BI7+qIbEA9lfcAc1JV0K+08GspCs0sr j8A586lS83z9Bhq7GkM= X-Google-Smtp-Source: ADKCNb6+Wvys7DW0k3o1Go9Ax/6oDyrJCCDBvL60lwe7evmHEOd2JRQ45/FFKtHrJDfkVvx72j5efg== X-Received: by 10.223.178.131 with SMTP id g3mr26189967wrd.78.1505734706152; Mon, 18 Sep 2017 04:38:26 -0700 (PDT) Received: from t460p.intel ([95.146.151.158]) by smtp.gmail.com with ESMTPSA id 90sm6347392wrl.52.2017.09.18.04.38.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Sep 2017 04:38:25 -0700 (PDT) From: Tvrtko Ursulin X-Google-Original-From: Tvrtko Ursulin To: Intel-gfx@lists.freedesktop.org Date: Mon, 18 Sep 2017 12:38:12 +0100 Message-Id: <20170918113814.2591-7-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20170918113814.2591-1-tvrtko.ursulin@linux.intel.com> References: <20170918113814.2591-1-tvrtko.ursulin@linux.intel.com> Subject: [Intel-gfx] [PATCH 6/8] drm/i915: Engine busy time tracking X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP From: Tvrtko Ursulin Track total time requests have been executing on the hardware. We add new kernel API to allow software tracking of time GPU engines are spending executing requests. Both per-engine and global API is added with the latter also being exported for use by external users. v2: * Squashed with the internal API. * Dropped static key. * Made per-engine. * Store time in monotonic ktime. v3: Moved stats clearing to disable. v4: * Comments. * Don't export the API just yet. v5: Whitespace cleanup. v6: * Rename ref to active. * Drop engine aggregate stats for now. * Account initial busy period after enabling stats. Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/intel_engine_cs.c | 84 ++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_lrc.c | 2 + drivers/gpu/drm/i915/intel_ringbuffer.h | 92 +++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 82510d971c7d..cbf978d39052 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -232,6 +232,8 @@ intel_engine_setup(struct drm_i915_private *dev_priv, /* Nothing to do here, execute in order of dependencies */ engine->schedule = NULL; + spin_lock_init(&engine->stats.lock); + ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier); dev_priv->engine_class[info->class][info->instance] = engine; @@ -1556,6 +1558,88 @@ bool intel_engine_can_store_dword(struct intel_engine_cs *engine) } } +/** + * intel_enable_engine_stats() - Enable engine busy tracking on engine + * @engine: engine to enable stats collection + * + * Start collecting the engine busyness data for @engine. + * + * Returns 0 on success or a negative error code. + */ +int intel_enable_engine_stats(struct intel_engine_cs *engine) +{ + unsigned long flags; + + if (!i915.enable_execlists) + return -ENODEV; + + spin_lock_irqsave(&engine->stats.lock, flags); + if (engine->stats.enabled == ~0) + goto busy; + if (engine->stats.enabled++ == 0) + engine->stats.enabled_at = ktime_get(); + spin_unlock_irqrestore(&engine->stats.lock, flags); + + return 0; + +busy: + spin_unlock_irqrestore(&engine->stats.lock, flags); + + return -EBUSY; +} + +/** + * intel_disable_engine_stats() - Disable engine busy tracking on engine + * @engine: engine to disable stats collection + * + * Stops collecting the engine busyness data for @engine. + */ +void intel_disable_engine_stats(struct intel_engine_cs *engine) +{ + unsigned long flags; + + if (!i915.enable_execlists) + return; + + spin_lock_irqsave(&engine->stats.lock, flags); + WARN_ON_ONCE(engine->stats.enabled == 0); + if (--engine->stats.enabled == 0) { + engine->stats.enabled_at = 0; + engine->stats.active = 0; + engine->stats.start = 0; + engine->stats.total = 0; + } + spin_unlock_irqrestore(&engine->stats.lock, flags); +} + +/** + * intel_engine_get_busy_time() - Return current accumulated engine busyness + * @engine: engine to report on + * + * Returns accumulated time @engine was busy since engine stats were enabled. + */ +ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine) +{ + ktime_t total; + unsigned long flags; + + spin_lock_irqsave(&engine->stats.lock, flags); + + total = engine->stats.total; + + /* + * If the engine is executing something at the moment + * add it to the total. + */ + if (engine->stats.active) + total = ktime_add(total, + ktime_sub(ktime_get(), engine->stats.start)); + + spin_unlock_irqrestore(&engine->stats.lock, flags); + + return total; +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/mock_engine.c" #endif diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index ba91db43f163..7f2861014448 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -304,12 +304,14 @@ execlists_context_status_change(struct drm_i915_gem_request *rq, static inline void execlists_context_schedule_in(struct drm_i915_gem_request *rq) { + intel_engine_context_in(rq->engine); execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_IN); } static inline void execlists_context_schedule_out(struct drm_i915_gem_request *rq) { + intel_engine_context_out(rq->engine); execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index cbd1734759b8..ae0a4c498a0f 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -465,6 +465,38 @@ struct intel_engine_cs { * certain bits to encode the command length in the header). */ u32 (*get_cmd_length_mask)(u32 cmd_header); + + struct { + /** + * @lock: Lock protecting the below fields. + */ + spinlock_t lock; + /** + * @enabled: Reference count indicating number of listeners. + */ + unsigned int enabled; + /** + * @active: Number of contexts currently scheduled in. + */ + unsigned int active; + /** + * @enabled_at: Timestamp when busy stats were enabled. + */ + ktime_t enabled_at; + /** + * @start: Timestamp of the last idle to active transition. + * + * Idle is defined as active == 0, active is active > 0. + */ + ktime_t start; + /** + * @total: Total time this engine was busy. + * + * Accumulated time not counting the most recent block in cases + * where engine is currently busy (active > 0). + */ + ktime_t total; + } stats; }; static inline unsigned int @@ -768,4 +800,64 @@ bool intel_engine_can_store_dword(struct intel_engine_cs *engine); struct intel_engine_cs * intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance); +static inline void intel_engine_context_in(struct intel_engine_cs *engine) +{ + unsigned long flags; + + if (READ_ONCE(engine->stats.enabled) == 0) + return; + + spin_lock_irqsave(&engine->stats.lock, flags); + + if (engine->stats.enabled > 0) { + if (engine->stats.active++ == 0) + engine->stats.start = ktime_get(); + GEM_BUG_ON(engine->stats.active == 0); + } + + spin_unlock_irqrestore(&engine->stats.lock, flags); +} + +static inline void intel_engine_context_out(struct intel_engine_cs *engine) +{ + unsigned long flags; + + if (READ_ONCE(engine->stats.enabled) == 0) + return; + + spin_lock_irqsave(&engine->stats.lock, flags); + + if (engine->stats.enabled > 0) { + ktime_t last, now = ktime_get(); + + if (engine->stats.active && --engine->stats.active == 0) { + /* + * Decrement the active context count and in case GPU + * is now idle add up to the running total. + */ + last = ktime_sub(now, engine->stats.start); + + engine->stats.total = ktime_add(engine->stats.total, + last); + } else if (engine->stats.active == 0) { + /* + * After turning on engine stats, context out might be + * the first event in which case we account from the + * time stats gathering was turned on. + */ + last = ktime_sub(now, engine->stats.enabled_at); + + engine->stats.total = ktime_add(engine->stats.total, + last); + } + } + + spin_unlock_irqrestore(&engine->stats.lock, flags); +} + +int intel_enable_engine_stats(struct intel_engine_cs *engine); +void intel_disable_engine_stats(struct intel_engine_cs *engine); + +ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine); + #endif /* _INTEL_RINGBUFFER_H_ */