]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/xe: Error handling in xe_force_wake_get()
authorHimal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Mon, 14 Oct 2024 07:55:39 +0000 (13:25 +0530)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Thu, 17 Oct 2024 14:17:07 +0000 (10:17 -0400)
If an acknowledgment timeout occurs for a forcewake domain awake
request, do not increment the reference count for the domain. This
ensures that subsequent _get calls do not incorrectly assume the domain
is awake. The return value is a mask of domains that got refcounted,
and these domains need to be provided for subsequent xe_force_wake_put
call.

While at it, add simple kernel-doc for xe_force_wake_get()

v3
- Use explicit type for mask (Michal/Badal)
- Improve kernel-doc (Michal)
- Use unsigned int instead of abusing enum (Michal)

v5
- Use unsigned int for return (MattB/Badal/Rodrigo)
- use xe_gt_WARN for domain awake ack failure (Badal/Rodrigo)

v6
- Change XE_FORCEWAKE_ALL to single bit, this helps accommodate
actually refcounted domains in return. (Michal)
- Modify commit message and warn message (Badal)
- Remove unnecessary information in kernel-doc (Michal)

v7
- Add assert condition for valid input domains (Badal)

v9
- Update kernel-doc and simplify conditions (Michal)

Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Badal Nilawar <badal.nilawar@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Lucas De Marchi <lucas.demarchi@intel.com>
Cc: Nirmoy Das <nirmoy.das@intel.com>
Reviewed-by: Badal Nilawar <badal.nilawar@intel.com>
Reviewed-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241014075601.2324382-5-himal.prasad.ghimiray@intel.com
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
drivers/gpu/drm/xe/xe_force_wake.c
drivers/gpu/drm/xe/xe_force_wake.h
drivers/gpu/drm/xe/xe_force_wake_types.h

index ac0419da71731e2c10c2e5c50d0920e39f72f25f..d36ed4f8bdbe97a1800d3e1283c9a6f6f1bf0905 100644 (file)
@@ -154,29 +154,61 @@ static int domain_sleep_wait(struct xe_gt *gt,
                                         (ffs(tmp__) - 1))) && \
                                         domain__->reg_ctl.addr)
 
-int xe_force_wake_get(struct xe_force_wake *fw,
-                     enum xe_force_wake_domains domains)
+/**
+ * xe_force_wake_get() : Increase the domain refcount
+ * @fw: struct xe_force_wake
+ * @domains: forcewake domains to get refcount on
+ *
+ * This function wakes up @domains if they are asleep and takes references.
+ * If requested domain is XE_FORCEWAKE_ALL then only applicable/initialized
+ * domains will be considered for refcount and it is a caller responsibility
+ * to check returned ref if it includes any specific domain by using
+ * xe_force_wake_ref_has_domain() function. Caller must call
+ * xe_force_wake_put() function to decrease incremented refcounts.
+ *
+ * Return: opaque reference to woken domains or zero if none of requested
+ * domains were awake.
+ */
+unsigned int xe_force_wake_get(struct xe_force_wake *fw,
+                              enum xe_force_wake_domains domains)
 {
        struct xe_gt *gt = fw->gt;
        struct xe_force_wake_domain *domain;
-       enum xe_force_wake_domains tmp, woken = 0;
+       unsigned int ref_incr = 0, awake_rqst = 0, awake_failed = 0;
+       unsigned int tmp, ref_rqst;
        unsigned long flags;
-       int ret = 0;
 
+       xe_gt_assert(gt, is_power_of_2(domains));
+       xe_gt_assert(gt, domains <= XE_FORCEWAKE_ALL);
+       xe_gt_assert(gt, domains == XE_FORCEWAKE_ALL || fw->initialized_domains & domains);
+
+       ref_rqst = (domains == XE_FORCEWAKE_ALL) ? fw->initialized_domains : domains;
        spin_lock_irqsave(&fw->lock, flags);
-       for_each_fw_domain_masked(domain, domains, fw, tmp) {
+       for_each_fw_domain_masked(domain, ref_rqst, fw, tmp) {
                if (!domain->ref++) {
-                       woken |= BIT(domain->id);
+                       awake_rqst |= BIT(domain->id);
                        domain_wake(gt, domain);
                }
+               ref_incr |= BIT(domain->id);
        }
-       for_each_fw_domain_masked(domain, woken, fw, tmp) {
-               ret |= domain_wake_wait(gt, domain);
+       for_each_fw_domain_masked(domain, awake_rqst, fw, tmp) {
+               if (domain_wake_wait(gt, domain) == 0) {
+                       fw->awake_domains |= BIT(domain->id);
+               } else {
+                       awake_failed |= BIT(domain->id);
+                       --domain->ref;
+               }
        }
-       fw->awake_domains |= woken;
+       ref_incr &= ~awake_failed;
        spin_unlock_irqrestore(&fw->lock, flags);
 
-       return ret;
+       xe_gt_WARN(gt, awake_failed, "Forcewake domain%s %#x failed to acknowledge awake request\n",
+                  str_plural(hweight_long(awake_failed)), awake_failed);
+
+       if (domains == XE_FORCEWAKE_ALL && ref_incr == fw->initialized_domains)
+               ref_incr |= XE_FORCEWAKE_ALL;
+
+       return ref_incr;
 }
 
 int xe_force_wake_put(struct xe_force_wake *fw,
index 1608a55edc846e070a5faf98147ba7ef3318741a..75fa1a19797c0cd46b9f6ba1401d9b808cbcb3b3 100644 (file)
@@ -15,8 +15,8 @@ void xe_force_wake_init_gt(struct xe_gt *gt,
                           struct xe_force_wake *fw);
 void xe_force_wake_init_engines(struct xe_gt *gt,
                                struct xe_force_wake *fw);
-int xe_force_wake_get(struct xe_force_wake *fw,
-                     enum xe_force_wake_domains domains);
+unsigned int xe_force_wake_get(struct xe_force_wake *fw,
+                              enum xe_force_wake_domains domains);
 int xe_force_wake_put(struct xe_force_wake *fw,
                      enum xe_force_wake_domains domains);
 
index fde17dc3d01e041e1cb531d9fc3dbb304d245aad..899fbbcb3ea9c6629ebad81ce67189afccd89f0a 100644 (file)
@@ -48,7 +48,7 @@ enum xe_force_wake_domains {
        XE_FW_MEDIA_VEBOX2      = BIT(XE_FW_DOMAIN_ID_MEDIA_VEBOX2),
        XE_FW_MEDIA_VEBOX3      = BIT(XE_FW_DOMAIN_ID_MEDIA_VEBOX3),
        XE_FW_GSC               = BIT(XE_FW_DOMAIN_ID_GSC),
-       XE_FORCEWAKE_ALL        = BIT(XE_FW_DOMAIN_ID_COUNT) - 1
+       XE_FORCEWAKE_ALL        = BIT(XE_FW_DOMAIN_ID_COUNT)
 };
 
 /**