@@ -66,19 +66,19 @@ __inval_fence_signal(struct xe_device *xe, struct xe_tlb_inval_fence *fence)
6666static void
6767inval_fence_signal (struct xe_device * xe , struct xe_tlb_inval_fence * fence )
6868{
69+ lockdep_assert_held (& fence -> tlb_inval -> pending_lock );
70+
6971 list_del (& fence -> link );
7072 __inval_fence_signal (xe , fence );
7173}
7274
73- void xe_tlb_inval_fence_signal (struct xe_tlb_inval_fence * fence )
75+ static void
76+ inval_fence_signal_unlocked (struct xe_device * xe ,
77+ struct xe_tlb_inval_fence * fence )
7478{
75- struct xe_gt * gt ;
76-
77- if (WARN_ON_ONCE (!fence -> tlb_inval ))
78- return ;
79-
80- gt = fence -> tlb_inval -> private ;
81- __inval_fence_signal (gt_to_xe (gt ), fence );
79+ spin_lock_irq (& fence -> tlb_inval -> pending_lock );
80+ inval_fence_signal (xe , fence );
81+ spin_unlock_irq (& fence -> tlb_inval -> pending_lock );
8282}
8383
8484static void xe_gt_tlb_fence_timeout (struct work_struct * work )
@@ -221,14 +221,10 @@ static bool tlb_inval_seqno_past(struct xe_gt *gt, int seqno)
221221 return seqno_recv >= seqno ;
222222}
223223
224- static int send_tlb_inval (struct xe_guc * guc ,
225- struct xe_tlb_inval_fence * fence ,
224+ static int send_tlb_inval (struct xe_guc * guc , struct xe_tlb_inval_fence * fence ,
226225 u32 * action , int len )
227226{
228227 struct xe_gt * gt = guc_to_gt (guc );
229- struct xe_device * xe = gt_to_xe (gt );
230- int seqno ;
231- int ret ;
232228
233229 xe_gt_assert (gt , fence );
234230
@@ -238,47 +234,36 @@ static int send_tlb_inval(struct xe_guc *guc,
238234 * need to be updated.
239235 */
240236
241- mutex_lock (& gt -> tlb_inval .seqno_lock );
242- seqno = gt -> tlb_inval .seqno ;
243- fence -> seqno = seqno ;
244- trace_xe_tlb_inval_fence_send (xe , fence );
245- action [1 ] = seqno ;
246- ret = xe_guc_ct_send (& guc -> ct , action , len ,
247- G2H_LEN_DW_TLB_INVALIDATE , 1 );
248- if (!ret ) {
249- spin_lock_irq (& gt -> tlb_inval .pending_lock );
250- /*
251- * We haven't actually published the TLB fence as per
252- * pending_fences, but in theory our seqno could have already
253- * been written as we acquired the pending_lock. In such a case
254- * we can just go ahead and signal the fence here.
255- */
256- if (tlb_inval_seqno_past (gt , seqno )) {
257- __inval_fence_signal (xe , fence );
258- } else {
259- fence -> inval_time = ktime_get ();
260- list_add_tail (& fence -> link ,
261- & gt -> tlb_inval .pending_fences );
262-
263- if (list_is_singular (& gt -> tlb_inval .pending_fences ))
264- queue_delayed_work (system_wq ,
265- & gt -> tlb_inval .fence_tdr ,
266- tlb_timeout_jiffies (gt ));
267- }
268- spin_unlock_irq (& gt -> tlb_inval .pending_lock );
269- } else {
270- __inval_fence_signal (xe , fence );
271- }
272- if (!ret ) {
273- gt -> tlb_inval .seqno = (gt -> tlb_inval .seqno + 1 ) %
274- TLB_INVALIDATION_SEQNO_MAX ;
275- if (!gt -> tlb_inval .seqno )
276- gt -> tlb_inval .seqno = 1 ;
277- }
278- mutex_unlock (& gt -> tlb_inval .seqno_lock );
279237 xe_gt_stats_incr (gt , XE_GT_STATS_ID_TLB_INVAL , 1 );
238+ action [1 ] = fence -> seqno ;
280239
281- return ret ;
240+ return xe_guc_ct_send (& guc -> ct , action , len ,
241+ G2H_LEN_DW_TLB_INVALIDATE , 1 );
242+ }
243+
244+ static void xe_tlb_inval_fence_prep (struct xe_tlb_inval_fence * fence )
245+ {
246+ struct xe_tlb_inval * tlb_inval = fence -> tlb_inval ;
247+ struct xe_gt * gt = tlb_inval -> private ;
248+ struct xe_device * xe = gt_to_xe (gt );
249+
250+ fence -> seqno = tlb_inval -> seqno ;
251+ trace_xe_tlb_inval_fence_send (xe , fence );
252+
253+ spin_lock_irq (& tlb_inval -> pending_lock );
254+ fence -> inval_time = ktime_get ();
255+ list_add_tail (& fence -> link , & tlb_inval -> pending_fences );
256+
257+ if (list_is_singular (& tlb_inval -> pending_fences ))
258+ queue_delayed_work (system_wq ,
259+ & tlb_inval -> fence_tdr ,
260+ tlb_timeout_jiffies (gt ));
261+ spin_unlock_irq (& tlb_inval -> pending_lock );
262+
263+ tlb_inval -> seqno = (tlb_inval -> seqno + 1 ) %
264+ TLB_INVALIDATION_SEQNO_MAX ;
265+ if (!tlb_inval -> seqno )
266+ tlb_inval -> seqno = 1 ;
282267}
283268
284269#define MAKE_INVAL_OP (type ) ((type << XE_GUC_TLB_INVAL_TYPE_SHIFT) | \
@@ -306,7 +291,14 @@ static int xe_tlb_inval_guc(struct xe_gt *gt,
306291 };
307292 int ret ;
308293
294+ mutex_lock (& gt -> tlb_inval .seqno_lock );
295+ xe_tlb_inval_fence_prep (fence );
296+
309297 ret = send_tlb_inval (& gt -> uc .guc , fence , action , ARRAY_SIZE (action ));
298+ if (ret < 0 )
299+ inval_fence_signal_unlocked (gt_to_xe (gt ), fence );
300+ mutex_unlock (& gt -> tlb_inval .seqno_lock );
301+
310302 /*
311303 * -ECANCELED indicates the CT is stopped for a GT reset. TLB caches
312304 * should be nuked on a GT reset so this error can be ignored.
@@ -433,7 +425,7 @@ int xe_tlb_inval_range(struct xe_tlb_inval *tlb_inval,
433425#define MAX_TLB_INVALIDATION_LEN 7
434426 u32 action [MAX_TLB_INVALIDATION_LEN ];
435427 u64 length = end - start ;
436- int len = 0 ;
428+ int len = 0 , ret ;
437429
438430 xe_gt_assert (gt , fence );
439431
@@ -494,7 +486,16 @@ int xe_tlb_inval_range(struct xe_tlb_inval *tlb_inval,
494486
495487 xe_gt_assert (gt , len <= MAX_TLB_INVALIDATION_LEN );
496488
497- return send_tlb_inval (& gt -> uc .guc , fence , action , len );
489+ mutex_lock (& gt -> tlb_inval .seqno_lock );
490+ xe_tlb_inval_fence_prep (fence );
491+
492+ ret = send_tlb_inval (& gt -> uc .guc , fence , action ,
493+ ARRAY_SIZE (action ));
494+ if (ret < 0 )
495+ inval_fence_signal_unlocked (xe , fence );
496+ mutex_unlock (& gt -> tlb_inval .seqno_lock );
497+
498+ return ret ;
498499}
499500
500501/**
0 commit comments