@@ -21,6 +21,7 @@ struct iwl_trans_dev_restart_data {
21
21
struct list_head list ;
22
22
unsigned int restart_count ;
23
23
time64_t last_error ;
24
+ bool backoff ;
24
25
char name [];
25
26
};
26
27
@@ -125,13 +126,20 @@ iwl_trans_determine_restart_mode(struct iwl_trans *trans)
125
126
if (!data )
126
127
return at_least ;
127
128
128
- if (ktime_get_boottime_seconds () - data -> last_error >=
129
+ if (!data -> backoff &&
130
+ ktime_get_boottime_seconds () - data -> last_error >=
129
131
IWL_TRANS_RESET_OK_TIME )
130
132
data -> restart_count = 0 ;
131
133
132
134
index = data -> restart_count ;
133
- if (index >= ARRAY_SIZE (escalation_list ))
135
+ if (index >= ARRAY_SIZE (escalation_list )) {
134
136
index = ARRAY_SIZE (escalation_list ) - 1 ;
137
+ if (!data -> backoff ) {
138
+ data -> backoff = true;
139
+ return IWL_RESET_MODE_BACKOFF ;
140
+ }
141
+ data -> backoff = false;
142
+ }
135
143
136
144
return max (at_least , escalation_list [index ]);
137
145
}
@@ -140,7 +148,8 @@ iwl_trans_determine_restart_mode(struct iwl_trans *trans)
140
148
141
149
static void iwl_trans_restart_wk (struct work_struct * wk )
142
150
{
143
- struct iwl_trans * trans = container_of (wk , typeof (* trans ), restart .wk );
151
+ struct iwl_trans * trans = container_of (wk , typeof (* trans ),
152
+ restart .wk .work );
144
153
struct iwl_trans_reprobe * reprobe ;
145
154
enum iwl_reset_mode mode ;
146
155
@@ -168,6 +177,12 @@ static void iwl_trans_restart_wk(struct work_struct *wk)
168
177
return ;
169
178
170
179
mode = iwl_trans_determine_restart_mode (trans );
180
+ if (mode == IWL_RESET_MODE_BACKOFF ) {
181
+ IWL_ERR (trans , "Too many device errors - delay next reset\n" );
182
+ queue_delayed_work (system_unbound_wq , & trans -> restart .wk ,
183
+ IWL_TRANS_RESET_DELAY );
184
+ return ;
185
+ }
171
186
172
187
iwl_trans_inc_restart_count (trans -> dev );
173
188
@@ -227,7 +242,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
227
242
trans -> dev = dev ;
228
243
trans -> num_rx_queues = 1 ;
229
244
230
- INIT_WORK (& trans -> restart .wk , iwl_trans_restart_wk );
245
+ INIT_DELAYED_WORK (& trans -> restart .wk , iwl_trans_restart_wk );
231
246
232
247
return trans ;
233
248
}
@@ -271,7 +286,7 @@ int iwl_trans_init(struct iwl_trans *trans)
271
286
272
287
void iwl_trans_free (struct iwl_trans * trans )
273
288
{
274
- cancel_work_sync (& trans -> restart .wk );
289
+ cancel_delayed_work_sync (& trans -> restart .wk );
275
290
kmem_cache_destroy (trans -> dev_cmd_pool );
276
291
}
277
292
@@ -403,7 +418,7 @@ void iwl_trans_op_mode_leave(struct iwl_trans *trans)
403
418
404
419
iwl_trans_pcie_op_mode_leave (trans );
405
420
406
- cancel_work_sync (& trans -> restart .wk );
421
+ cancel_delayed_work_sync (& trans -> restart .wk );
407
422
408
423
trans -> op_mode = NULL ;
409
424
0 commit comments