9
9
#include "xe_guc_ct.h"
10
10
#include "xe_trace.h"
11
11
12
+ #define TLB_TIMEOUT (HZ / 4)
13
+
12
14
static struct xe_gt *
13
15
guc_to_gt (struct xe_guc * guc )
14
16
{
15
17
return container_of (guc , struct xe_gt , uc .guc );
16
18
}
17
19
20
+ static void xe_gt_tlb_fence_timeout (struct work_struct * work )
21
+ {
22
+ struct xe_gt * gt = container_of (work , struct xe_gt ,
23
+ tlb_invalidation .fence_tdr .work );
24
+ struct xe_gt_tlb_invalidation_fence * fence , * next ;
25
+
26
+ mutex_lock (& gt -> uc .guc .ct .lock );
27
+ list_for_each_entry_safe (fence , next ,
28
+ & gt -> tlb_invalidation .pending_fences , link ) {
29
+ s64 since_inval_ms = ktime_ms_delta (ktime_get (),
30
+ fence -> invalidation_time );
31
+
32
+ if (msecs_to_jiffies (since_inval_ms ) < TLB_TIMEOUT )
33
+ break ;
34
+
35
+ trace_xe_gt_tlb_invalidation_fence_timeout (fence );
36
+ drm_err (& gt_to_xe (gt )-> drm , "TLB invalidation fence timeout, seqno=%d" ,
37
+ fence -> seqno );
38
+
39
+ list_del (& fence -> link );
40
+ fence -> base .error = - ETIME ;
41
+ dma_fence_signal (& fence -> base );
42
+ dma_fence_put (& fence -> base );
43
+ }
44
+ if (!list_empty (& gt -> tlb_invalidation .pending_fences ))
45
+ queue_delayed_work (system_wq ,
46
+ & gt -> tlb_invalidation .fence_tdr ,
47
+ TLB_TIMEOUT );
48
+ mutex_unlock (& gt -> uc .guc .ct .lock );
49
+ }
50
+
18
51
/**
19
52
* xe_gt_tlb_invalidation_init - Initialize GT TLB invalidation state
20
53
* @gt: graphics tile
@@ -30,6 +63,8 @@ int xe_gt_tlb_invalidation_init(struct xe_gt *gt)
30
63
INIT_LIST_HEAD (& gt -> tlb_invalidation .pending_fences );
31
64
spin_lock_init (& gt -> tlb_invalidation .lock );
32
65
gt -> tlb_invalidation .fence_context = dma_fence_context_alloc (1 );
66
+ INIT_DELAYED_WORK (& gt -> tlb_invalidation .fence_tdr ,
67
+ xe_gt_tlb_fence_timeout );
33
68
34
69
return 0 ;
35
70
}
@@ -44,6 +79,8 @@ int xe_gt_tlb_invalidation_init(struct xe_gt *gt)
44
79
{
45
80
struct xe_gt_tlb_invalidation_fence * fence , * next ;
46
81
82
+ cancel_delayed_work (& gt -> tlb_invalidation .fence_tdr );
83
+
47
84
mutex_lock (& gt -> uc .guc .ct .lock );
48
85
list_for_each_entry_safe (fence , next ,
49
86
& gt -> tlb_invalidation .pending_fences , link ) {
@@ -67,6 +104,7 @@ static int send_tlb_invalidation(struct xe_guc *guc,
67
104
};
68
105
int seqno ;
69
106
int ret ;
107
+ bool queue_work ;
70
108
71
109
/*
72
110
* XXX: The seqno algorithm relies on TLB invalidation being processed
@@ -76,10 +114,7 @@ static int send_tlb_invalidation(struct xe_guc *guc,
76
114
mutex_lock (& guc -> ct .lock );
77
115
seqno = gt -> tlb_invalidation .seqno ;
78
116
if (fence ) {
79
- /*
80
- * FIXME: How to deal TLB invalidation timeout, right now we
81
- * just have an endless fence which isn't ideal.
82
- */
117
+ queue_work = list_empty (& gt -> tlb_invalidation .pending_fences );
83
118
fence -> seqno = seqno ;
84
119
list_add_tail (& fence -> link ,
85
120
& gt -> tlb_invalidation .pending_fences );
@@ -92,6 +127,13 @@ static int send_tlb_invalidation(struct xe_guc *guc,
92
127
gt -> tlb_invalidation .seqno = 1 ;
93
128
ret = xe_guc_ct_send_locked (& guc -> ct , action , ARRAY_SIZE (action ),
94
129
G2H_LEN_DW_TLB_INVALIDATE , 1 );
130
+ if (!ret && fence ) {
131
+ fence -> invalidation_time = ktime_get ();
132
+ if (queue_work )
133
+ queue_delayed_work (system_wq ,
134
+ & gt -> tlb_invalidation .fence_tdr ,
135
+ TLB_TIMEOUT );
136
+ }
95
137
if (!ret )
96
138
ret = seqno ;
97
139
mutex_unlock (& guc -> ct .lock );
@@ -152,7 +194,7 @@ int xe_gt_tlb_invalidation_wait(struct xe_gt *gt, int seqno)
152
194
*/
153
195
ret = wait_event_timeout (guc -> ct .wq ,
154
196
tlb_invalidation_seqno_past (gt , seqno ),
155
- HZ / 5 );
197
+ TLB_TIMEOUT );
156
198
if (!ret ) {
157
199
drm_err (& xe -> drm , "TLB invalidation time'd out, seqno=%d, recv=%d\n" ,
158
200
seqno , gt -> tlb_invalidation .seqno_recv );
@@ -201,6 +243,12 @@ int xe_guc_tlb_invalidation_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
201
243
if (fence && tlb_invalidation_seqno_past (gt , fence -> seqno )) {
202
244
trace_xe_gt_tlb_invalidation_fence_signal (fence );
203
245
list_del (& fence -> link );
246
+ if (!list_empty (& gt -> tlb_invalidation .pending_fences ))
247
+ mod_delayed_work (system_wq ,
248
+ & gt -> tlb_invalidation .fence_tdr ,
249
+ TLB_TIMEOUT );
250
+ else
251
+ cancel_delayed_work (& gt -> tlb_invalidation .fence_tdr );
204
252
dma_fence_signal (& fence -> base );
205
253
dma_fence_put (& fence -> base );
206
254
}
0 commit comments