@@ -537,4 +537,5 @@ int intel_guc_invalidate_tlb_engines(struct intel_guc *guc);
int intel_guc_invalidate_tlb_guc(struct intel_guc *guc);
int intel_guc_tlb_invalidation_done(struct intel_guc *guc,
const u32 *payload, u32 len);
+void wake_up_all_tlb_invalidate(struct intel_guc *guc);
#endif
@@ -1796,6 +1796,20 @@ static void __guc_reset_context(struct intel_context *ce, intel_engine_mask_t st
intel_context_put(parent);
}
+void wake_up_all_tlb_invalidate(struct intel_guc *guc)
+{
+ struct intel_guc_tlb_wait *wait;
+ unsigned long i;
+
+ if (!intel_guc_tlb_invalidation_is_available(guc))
+ return;
+
+ xa_lock_irq(&guc->tlb_lookup);
+ xa_for_each(&guc->tlb_lookup, i, wait)
+ wake_up(&wait->wq);
+ xa_unlock_irq(&guc->tlb_lookup);
+}
+
void intel_guc_submission_reset(struct intel_guc *guc, intel_engine_mask_t stalled)
{
struct intel_context *ce;
@@ -1925,9 +1939,6 @@ void intel_guc_submission_cancel_requests(struct intel_guc *guc)
void intel_guc_submission_reset_finish(struct intel_guc *guc)
{
- struct intel_guc_tlb_wait *wait;
- unsigned long i;
-
/* Reset called during driver load or during wedge? */
if (unlikely(!guc_submission_initialized(guc) ||
intel_gt_is_wedged(guc_to_gt(guc)))) {
@@ -1951,12 +1962,7 @@ void intel_guc_submission_reset_finish(struct intel_guc *guc)
* The full GT reset will have cleared the TLB caches and flushed the
* G2H message queue; we can release all the blocked waiters.
*/
- if (intel_guc_tlb_invalidation_is_available(guc)) {
- xa_lock_irq(&guc->tlb_lookup);
- xa_for_each(&guc->tlb_lookup, i, wait)
- wake_up(&wait->wq);
- xa_unlock_irq(&guc->tlb_lookup);
- }
+ wake_up_all_tlb_invalidate(guc);
}
static void destroyed_worker_func(struct work_struct *w);
@@ -688,6 +688,8 @@ void intel_uc_suspend(struct intel_uc *uc)
/* flush the GSC worker */
intel_gsc_uc_flush_work(&uc->gsc);
+ wake_up_all_tlb_invalidate(guc);
+
if (!intel_guc_is_ready(guc)) {
guc->interrupts.enabled = false;
return;
@@ -736,6 +738,11 @@ static int __uc_resume(struct intel_uc *uc, bool enable_communication)
intel_gsc_uc_resume(&uc->gsc);
+ if (intel_guc_tlb_invalidation_is_available(guc)) {
+ intel_guc_invalidate_tlb_engines(guc);
+ intel_guc_invalidate_tlb_guc(guc);
+ }
+
return 0;
}