@@ -3422,18 +3422,29 @@ static inline int guc_lrc_desc_unpin(struct intel_context *ce)
3422
3422
* GuC is active, lets destroy this context, but at this point we can still be racing
3423
3423
* with suspend, so we undo everything if the H2G fails in deregister_context so
3424
3424
* that GuC reset will find this context during clean up.
3425
+ *
3426
+ * There is a race condition where the reset code could have altered
3427
+ * this context's state and done a wakeref put before we try to
3428
+ * deregister it here. So check if the context is still set to be
3429
+ * destroyed before undoing earlier changes, to avoid two wakeref puts
3430
+ * on the same context.
3425
3431
*/
3426
3432
ret = deregister_context (ce , ce -> guc_id .id );
3427
3433
if (ret ) {
3434
+ bool pending_destroyed ;
3428
3435
spin_lock_irqsave (& ce -> guc_state .lock , flags );
3429
- set_context_registered (ce );
3430
- clr_context_destroyed (ce );
3436
+ pending_destroyed = context_destroyed (ce );
3437
+ if (pending_destroyed ) {
3438
+ set_context_registered (ce );
3439
+ clr_context_destroyed (ce );
3440
+ }
3431
3441
spin_unlock_irqrestore (& ce -> guc_state .lock , flags );
3432
3442
/*
3433
3443
* As gt-pm is awake at function entry, intel_wakeref_put_async merely decrements
3434
3444
* the wakeref immediately but per function spec usage call this after unlock.
3435
3445
*/
3436
- intel_wakeref_put_async (& gt -> wakeref );
3446
+ if (pending_destroyed )
3447
+ intel_wakeref_put_async (& gt -> wakeref );
3437
3448
}
3438
3449
3439
3450
return ret ;
0 commit comments