@@ -21,6 +21,7 @@ struct iwl_trans_dev_restart_data {
2121 struct list_head list ;
2222 unsigned int restart_count ;
2323 time64_t last_error ;
24+ bool backoff ;
2425 char name [];
2526};
2627
@@ -125,13 +126,20 @@ iwl_trans_determine_restart_mode(struct iwl_trans *trans)
125126 if (!data )
126127 return at_least ;
127128
128- if (ktime_get_boottime_seconds () - data -> last_error >=
129+ if (!data -> backoff &&
130+ ktime_get_boottime_seconds () - data -> last_error >=
129131 IWL_TRANS_RESET_OK_TIME )
130132 data -> restart_count = 0 ;
131133
132134 index = data -> restart_count ;
133- if (index >= ARRAY_SIZE (escalation_list ))
135+ if (index >= ARRAY_SIZE (escalation_list )) {
134136 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+ }
135143
136144 return max (at_least , escalation_list [index ]);
137145}
@@ -140,7 +148,8 @@ iwl_trans_determine_restart_mode(struct iwl_trans *trans)
140148
141149static void iwl_trans_restart_wk (struct work_struct * wk )
142150{
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 );
144153 struct iwl_trans_reprobe * reprobe ;
145154 enum iwl_reset_mode mode ;
146155
@@ -168,6 +177,12 @@ static void iwl_trans_restart_wk(struct work_struct *wk)
168177 return ;
169178
170179 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+ }
171186
172187 iwl_trans_inc_restart_count (trans -> dev );
173188
@@ -227,7 +242,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
227242 trans -> dev = dev ;
228243 trans -> num_rx_queues = 1 ;
229244
230- INIT_WORK (& trans -> restart .wk , iwl_trans_restart_wk );
245+ INIT_DELAYED_WORK (& trans -> restart .wk , iwl_trans_restart_wk );
231246
232247 return trans ;
233248}
@@ -271,7 +286,7 @@ int iwl_trans_init(struct iwl_trans *trans)
271286
272287void iwl_trans_free (struct iwl_trans * trans )
273288{
274- cancel_work_sync (& trans -> restart .wk );
289+ cancel_delayed_work_sync (& trans -> restart .wk );
275290 kmem_cache_destroy (trans -> dev_cmd_pool );
276291}
277292
@@ -403,7 +418,7 @@ void iwl_trans_op_mode_leave(struct iwl_trans *trans)
403418
404419 iwl_trans_pcie_op_mode_leave (trans );
405420
406- cancel_work_sync (& trans -> restart .wk );
421+ cancel_delayed_work_sync (& trans -> restart .wk );
407422
408423 trans -> op_mode = NULL ;
409424
0 commit comments