Skip to content

Commit a7ddcea

Browse files
hghimirarodrigovivi
authored andcommitted
drm/xe: Error handling in xe_force_wake_get()
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 <[email protected]> Cc: Badal Nilawar <[email protected]> Cc: Rodrigo Vivi <[email protected]> Cc: Lucas De Marchi <[email protected]> Cc: Nirmoy Das <[email protected]> Reviewed-by: Badal Nilawar <[email protected]> Reviewed-by: Michal Wajdeczko <[email protected]> Signed-off-by: Himal Prasad Ghimiray <[email protected]> Reviewed-by: Nirmoy Das <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] Signed-off-by: Rodrigo Vivi <[email protected]>
1 parent 9d62b07 commit a7ddcea

File tree

3 files changed

+45
-13
lines changed

3 files changed

+45
-13
lines changed

drivers/gpu/drm/xe/xe_force_wake.c

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -154,29 +154,61 @@ static int domain_sleep_wait(struct xe_gt *gt,
154154
(ffs(tmp__) - 1))) && \
155155
domain__->reg_ctl.addr)
156156

157-
int xe_force_wake_get(struct xe_force_wake *fw,
158-
enum xe_force_wake_domains domains)
157+
/**
158+
* xe_force_wake_get() : Increase the domain refcount
159+
* @fw: struct xe_force_wake
160+
* @domains: forcewake domains to get refcount on
161+
*
162+
* This function wakes up @domains if they are asleep and takes references.
163+
* If requested domain is XE_FORCEWAKE_ALL then only applicable/initialized
164+
* domains will be considered for refcount and it is a caller responsibility
165+
* to check returned ref if it includes any specific domain by using
166+
* xe_force_wake_ref_has_domain() function. Caller must call
167+
* xe_force_wake_put() function to decrease incremented refcounts.
168+
*
169+
* Return: opaque reference to woken domains or zero if none of requested
170+
* domains were awake.
171+
*/
172+
unsigned int xe_force_wake_get(struct xe_force_wake *fw,
173+
enum xe_force_wake_domains domains)
159174
{
160175
struct xe_gt *gt = fw->gt;
161176
struct xe_force_wake_domain *domain;
162-
enum xe_force_wake_domains tmp, woken = 0;
177+
unsigned int ref_incr = 0, awake_rqst = 0, awake_failed = 0;
178+
unsigned int tmp, ref_rqst;
163179
unsigned long flags;
164-
int ret = 0;
165180

181+
xe_gt_assert(gt, is_power_of_2(domains));
182+
xe_gt_assert(gt, domains <= XE_FORCEWAKE_ALL);
183+
xe_gt_assert(gt, domains == XE_FORCEWAKE_ALL || fw->initialized_domains & domains);
184+
185+
ref_rqst = (domains == XE_FORCEWAKE_ALL) ? fw->initialized_domains : domains;
166186
spin_lock_irqsave(&fw->lock, flags);
167-
for_each_fw_domain_masked(domain, domains, fw, tmp) {
187+
for_each_fw_domain_masked(domain, ref_rqst, fw, tmp) {
168188
if (!domain->ref++) {
169-
woken |= BIT(domain->id);
189+
awake_rqst |= BIT(domain->id);
170190
domain_wake(gt, domain);
171191
}
192+
ref_incr |= BIT(domain->id);
172193
}
173-
for_each_fw_domain_masked(domain, woken, fw, tmp) {
174-
ret |= domain_wake_wait(gt, domain);
194+
for_each_fw_domain_masked(domain, awake_rqst, fw, tmp) {
195+
if (domain_wake_wait(gt, domain) == 0) {
196+
fw->awake_domains |= BIT(domain->id);
197+
} else {
198+
awake_failed |= BIT(domain->id);
199+
--domain->ref;
200+
}
175201
}
176-
fw->awake_domains |= woken;
202+
ref_incr &= ~awake_failed;
177203
spin_unlock_irqrestore(&fw->lock, flags);
178204

179-
return ret;
205+
xe_gt_WARN(gt, awake_failed, "Forcewake domain%s %#x failed to acknowledge awake request\n",
206+
str_plural(hweight_long(awake_failed)), awake_failed);
207+
208+
if (domains == XE_FORCEWAKE_ALL && ref_incr == fw->initialized_domains)
209+
ref_incr |= XE_FORCEWAKE_ALL;
210+
211+
return ref_incr;
180212
}
181213

182214
int xe_force_wake_put(struct xe_force_wake *fw,

drivers/gpu/drm/xe/xe_force_wake.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ void xe_force_wake_init_gt(struct xe_gt *gt,
1515
struct xe_force_wake *fw);
1616
void xe_force_wake_init_engines(struct xe_gt *gt,
1717
struct xe_force_wake *fw);
18-
int xe_force_wake_get(struct xe_force_wake *fw,
19-
enum xe_force_wake_domains domains);
18+
unsigned int xe_force_wake_get(struct xe_force_wake *fw,
19+
enum xe_force_wake_domains domains);
2020
int xe_force_wake_put(struct xe_force_wake *fw,
2121
enum xe_force_wake_domains domains);
2222

drivers/gpu/drm/xe/xe_force_wake_types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ enum xe_force_wake_domains {
4848
XE_FW_MEDIA_VEBOX2 = BIT(XE_FW_DOMAIN_ID_MEDIA_VEBOX2),
4949
XE_FW_MEDIA_VEBOX3 = BIT(XE_FW_DOMAIN_ID_MEDIA_VEBOX3),
5050
XE_FW_GSC = BIT(XE_FW_DOMAIN_ID_GSC),
51-
XE_FORCEWAKE_ALL = BIT(XE_FW_DOMAIN_ID_COUNT) - 1
51+
XE_FORCEWAKE_ALL = BIT(XE_FW_DOMAIN_ID_COUNT)
5252
};
5353

5454
/**

0 commit comments

Comments
 (0)