1 // SPDX-License-Identifier: GPL-2.0-only
2 /******************************************************************************
3 *
4 * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
5 * Copyright (C) 2018, 2020 Intel Corporation
6 *
7 * Portions of this file are derived from the ipw3945 project, as well
8 * as portions of the ieee80211 subsystem header files.
9 *
10 * Contact Information:
11 * Intel Linux Wireless <linuxwifi@intel.com>
12 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
13 *****************************************************************************/
14
15
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/slab.h>
19 #include <net/mac80211.h>
20 #include "iwl-io.h"
21 #include "iwl-modparams.h"
22 #include "iwl-debug.h"
23 #include "agn.h"
24 #include "dev.h"
25 #include "commands.h"
26 #include "tt.h"
27
28 /* default Thermal Throttling transaction table
29 * Current state | Throttling Down | Throttling Up
30 *=============================================================================
31 * Condition Nxt State Condition Nxt State Condition Nxt State
32 *-----------------------------------------------------------------------------
33 * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A
34 * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0
35 * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1
36 * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
37 *=============================================================================
38 */
39 static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = {
40 {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104},
41 {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1},
42 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
43 };
44 static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = {
45 {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95},
46 {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1},
47 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
48 };
49 static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = {
50 {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100},
51 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX},
52 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
53 };
54 static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = {
55 {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD},
56 {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX},
57 {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
58 };
59
60 /* Advance Thermal Throttling default restriction table */
61 static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = {
62 {IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true },
63 {IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true },
64 {IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false },
65 {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false }
66 };
67
iwl_tt_is_low_power_state(struct iwl_priv * priv)68 bool iwl_tt_is_low_power_state(struct iwl_priv *priv)
69 {
70 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
71
72 if (tt->state >= IWL_TI_1)
73 return true;
74 return false;
75 }
76
iwl_tt_current_power_mode(struct iwl_priv * priv)77 u8 iwl_tt_current_power_mode(struct iwl_priv *priv)
78 {
79 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
80
81 return tt->tt_power_mode;
82 }
83
iwl_ht_enabled(struct iwl_priv * priv)84 bool iwl_ht_enabled(struct iwl_priv *priv)
85 {
86 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
87 struct iwl_tt_restriction *restriction;
88
89 if (!priv->thermal_throttle.advanced_tt)
90 return true;
91 restriction = tt->restriction + tt->state;
92 return restriction->is_ht;
93 }
94
iwl_within_ct_kill_margin(struct iwl_priv * priv)95 static bool iwl_within_ct_kill_margin(struct iwl_priv *priv)
96 {
97 s32 temp = priv->temperature; /* degrees CELSIUS except specified */
98 bool within_margin = false;
99
100 if (!priv->thermal_throttle.advanced_tt)
101 within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
102 CT_KILL_THRESHOLD_LEGACY) ? true : false;
103 else
104 within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
105 CT_KILL_THRESHOLD) ? true : false;
106 return within_margin;
107 }
108
iwl_check_for_ct_kill(struct iwl_priv * priv)109 bool iwl_check_for_ct_kill(struct iwl_priv *priv)
110 {
111 bool is_ct_kill = false;
112
113 if (iwl_within_ct_kill_margin(priv)) {
114 iwl_tt_enter_ct_kill(priv);
115 is_ct_kill = true;
116 }
117 return is_ct_kill;
118 }
119
iwl_tx_ant_restriction(struct iwl_priv * priv)120 enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv)
121 {
122 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
123 struct iwl_tt_restriction *restriction;
124
125 if (!priv->thermal_throttle.advanced_tt)
126 return IWL_ANT_OK_MULTI;
127 restriction = tt->restriction + tt->state;
128 return restriction->tx_stream;
129 }
130
iwl_rx_ant_restriction(struct iwl_priv * priv)131 enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
132 {
133 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
134 struct iwl_tt_restriction *restriction;
135
136 if (!priv->thermal_throttle.advanced_tt)
137 return IWL_ANT_OK_MULTI;
138 restriction = tt->restriction + tt->state;
139 return restriction->rx_stream;
140 }
141
142 #define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */
143 #define CT_KILL_WAITING_DURATION (300) /* 300ms duration */
144
145 /*
146 * toggle the bit to wake up uCode and check the temperature
147 * if the temperature is below CT, uCode will stay awake and send card
148 * state notification with CT_KILL bit clear to inform Thermal Throttling
149 * Management to change state. Otherwise, uCode will go back to sleep
150 * without doing anything, driver should continue the 5 seconds timer
151 * to wake up uCode for temperature check until temperature drop below CT
152 */
iwl_tt_check_exit_ct_kill(struct timer_list * t)153 static void iwl_tt_check_exit_ct_kill(struct timer_list *t)
154 {
155 struct iwl_priv *priv = from_timer(priv, t,
156 thermal_throttle.ct_kill_exit_tm);
157 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
158
159 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
160 return;
161
162 if (tt->state == IWL_TI_CT_KILL) {
163 if (priv->thermal_throttle.ct_kill_toggle) {
164 iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
165 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
166 priv->thermal_throttle.ct_kill_toggle = false;
167 } else {
168 iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET,
169 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
170 priv->thermal_throttle.ct_kill_toggle = true;
171 }
172 iwl_read32(priv->trans, CSR_UCODE_DRV_GP1);
173 if (iwl_trans_grab_nic_access(priv->trans))
174 iwl_trans_release_nic_access(priv->trans);
175
176 /* Reschedule the ct_kill timer to occur in
177 * CT_KILL_EXIT_DURATION seconds to ensure we get a
178 * thermal update */
179 IWL_DEBUG_TEMP(priv, "schedule ct_kill exit timer\n");
180 mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,
181 jiffies + CT_KILL_EXIT_DURATION * HZ);
182 }
183 }
184
iwl_perform_ct_kill_task(struct iwl_priv * priv,bool stop)185 static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
186 bool stop)
187 {
188 if (stop) {
189 IWL_DEBUG_TEMP(priv, "Stop all queues\n");
190 if (priv->mac80211_registered)
191 ieee80211_stop_queues(priv->hw);
192 IWL_DEBUG_TEMP(priv,
193 "Schedule 5 seconds CT_KILL Timer\n");
194 mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,
195 jiffies + CT_KILL_EXIT_DURATION * HZ);
196 } else {
197 IWL_DEBUG_TEMP(priv, "Wake all queues\n");
198 if (priv->mac80211_registered)
199 ieee80211_wake_queues(priv->hw);
200 }
201 }
202
iwl_tt_ready_for_ct_kill(struct timer_list * t)203 static void iwl_tt_ready_for_ct_kill(struct timer_list *t)
204 {
205 struct iwl_priv *priv = from_timer(priv, t,
206 thermal_throttle.ct_kill_waiting_tm);
207 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
208
209 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
210 return;
211
212 /* temperature timer expired, ready to go into CT_KILL state */
213 if (tt->state != IWL_TI_CT_KILL) {
214 IWL_DEBUG_TEMP(priv, "entering CT_KILL state when "
215 "temperature timer expired\n");
216 tt->state = IWL_TI_CT_KILL;
217 set_bit(STATUS_CT_KILL, &priv->status);
218 iwl_perform_ct_kill_task(priv, true);
219 }
220 }
221
iwl_prepare_ct_kill_task(struct iwl_priv * priv)222 static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)
223 {
224 IWL_DEBUG_TEMP(priv, "Prepare to enter IWL_TI_CT_KILL\n");
225 /* make request to retrieve statistics information */
226 iwl_send_statistics_request(priv, 0, false);
227 /* Reschedule the ct_kill wait timer */
228 mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm,
229 jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION));
230 }
231
232 #define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY)
233 #define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100)
234 #define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90)
235
236 /*
237 * Legacy thermal throttling
238 * 1) Avoid NIC destruction due to high temperatures
239 * Chip will identify dangerously high temperatures that can
240 * harm the device and will power down
241 * 2) Avoid the NIC power down due to high temperature
242 * Throttle early enough to lower the power consumption before
243 * drastic steps are needed
244 */
iwl_legacy_tt_handler(struct iwl_priv * priv,s32 temp,bool force)245 static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
246 {
247 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
248 enum iwl_tt_state old_state;
249
250 #ifdef CONFIG_IWLWIFI_DEBUG
251 if ((tt->tt_previous_temp) &&
252 (temp > tt->tt_previous_temp) &&
253 ((temp - tt->tt_previous_temp) >
254 IWL_TT_INCREASE_MARGIN)) {
255 IWL_DEBUG_TEMP(priv,
256 "Temperature increase %d degree Celsius\n",
257 (temp - tt->tt_previous_temp));
258 }
259 #endif
260 old_state = tt->state;
261 /* in Celsius */
262 if (temp >= IWL_MINIMAL_POWER_THRESHOLD)
263 tt->state = IWL_TI_CT_KILL;
264 else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2)
265 tt->state = IWL_TI_2;
266 else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1)
267 tt->state = IWL_TI_1;
268 else
269 tt->state = IWL_TI_0;
270
271 #ifdef CONFIG_IWLWIFI_DEBUG
272 tt->tt_previous_temp = temp;
273 #endif
274 /* stop ct_kill_waiting_tm timer */
275 del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
276 if (tt->state != old_state) {
277 switch (tt->state) {
278 case IWL_TI_0:
279 /*
280 * When the system is ready to go back to IWL_TI_0
281 * we only have to call iwl_power_update_mode() to
282 * do so.
283 */
284 break;
285 case IWL_TI_1:
286 tt->tt_power_mode = IWL_POWER_INDEX_3;
287 break;
288 case IWL_TI_2:
289 tt->tt_power_mode = IWL_POWER_INDEX_4;
290 break;
291 default:
292 tt->tt_power_mode = IWL_POWER_INDEX_5;
293 break;
294 }
295 mutex_lock(&priv->mutex);
296 if (old_state == IWL_TI_CT_KILL)
297 clear_bit(STATUS_CT_KILL, &priv->status);
298 if (tt->state != IWL_TI_CT_KILL &&
299 iwl_power_update_mode(priv, true)) {
300 /* TT state not updated
301 * try again during next temperature read
302 */
303 if (old_state == IWL_TI_CT_KILL)
304 set_bit(STATUS_CT_KILL, &priv->status);
305 tt->state = old_state;
306 IWL_ERR(priv, "Cannot update power mode, "
307 "TT state not updated\n");
308 } else {
309 if (tt->state == IWL_TI_CT_KILL) {
310 if (force) {
311 set_bit(STATUS_CT_KILL, &priv->status);
312 iwl_perform_ct_kill_task(priv, true);
313 } else {
314 iwl_prepare_ct_kill_task(priv);
315 tt->state = old_state;
316 }
317 } else if (old_state == IWL_TI_CT_KILL) {
318 iwl_perform_ct_kill_task(priv, false);
319 }
320 IWL_DEBUG_TEMP(priv, "Temperature state changed %u\n",
321 tt->state);
322 IWL_DEBUG_TEMP(priv, "Power Index change to %u\n",
323 tt->tt_power_mode);
324 }
325 mutex_unlock(&priv->mutex);
326 }
327 }
328
329 /*
330 * Advance thermal throttling
331 * 1) Avoid NIC destruction due to high temperatures
332 * Chip will identify dangerously high temperatures that can
333 * harm the device and will power down
334 * 2) Avoid the NIC power down due to high temperature
335 * Throttle early enough to lower the power consumption before
336 * drastic steps are needed
337 * Actions include relaxing the power down sleep thresholds and
338 * decreasing the number of TX streams
339 * 3) Avoid throughput performance impact as much as possible
340 *
341 *=============================================================================
342 * Condition Nxt State Condition Nxt State Condition Nxt State
343 *-----------------------------------------------------------------------------
344 * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A
345 * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0
346 * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1
347 * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
348 *=============================================================================
349 */
iwl_advance_tt_handler(struct iwl_priv * priv,s32 temp,bool force)350 static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
351 {
352 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
353 int i;
354 bool changed = false;
355 enum iwl_tt_state old_state;
356 struct iwl_tt_trans *transaction;
357
358 old_state = tt->state;
359 for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) {
360 /* based on the current TT state,
361 * find the curresponding transaction table
362 * each table has (IWL_TI_STATE_MAX - 1) entries
363 * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1))
364 * will advance to the correct table.
365 * then based on the current temperature
366 * find the next state need to transaction to
367 * go through all the possible (IWL_TI_STATE_MAX - 1) entries
368 * in the current table to see if transaction is needed
369 */
370 transaction = tt->transaction +
371 ((old_state * (IWL_TI_STATE_MAX - 1)) + i);
372 if (temp >= transaction->tt_low &&
373 temp <= transaction->tt_high) {
374 #ifdef CONFIG_IWLWIFI_DEBUG
375 if ((tt->tt_previous_temp) &&
376 (temp > tt->tt_previous_temp) &&
377 ((temp - tt->tt_previous_temp) >
378 IWL_TT_INCREASE_MARGIN)) {
379 IWL_DEBUG_TEMP(priv,
380 "Temperature increase %d "
381 "degree Celsius\n",
382 (temp - tt->tt_previous_temp));
383 }
384 tt->tt_previous_temp = temp;
385 #endif
386 if (old_state !=
387 transaction->next_state) {
388 changed = true;
389 tt->state =
390 transaction->next_state;
391 }
392 break;
393 }
394 }
395 /* stop ct_kill_waiting_tm timer */
396 del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
397 if (changed) {
398 if (tt->state >= IWL_TI_1) {
399 /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */
400 tt->tt_power_mode = IWL_POWER_INDEX_5;
401
402 if (!iwl_ht_enabled(priv)) {
403 struct iwl_rxon_context *ctx;
404
405 for_each_context(priv, ctx) {
406 struct iwl_rxon_cmd *rxon;
407
408 rxon = &ctx->staging;
409
410 /* disable HT */
411 rxon->flags &= ~(
412 RXON_FLG_CHANNEL_MODE_MSK |
413 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
414 RXON_FLG_HT40_PROT_MSK |
415 RXON_FLG_HT_PROT_MSK);
416 }
417 } else {
418 /* check HT capability and set
419 * according to the system HT capability
420 * in case get disabled before */
421 iwl_set_rxon_ht(priv, &priv->current_ht_config);
422 }
423
424 } else {
425 /*
426 * restore system power setting -- it will be
427 * recalculated automatically.
428 */
429
430 /* check HT capability and set
431 * according to the system HT capability
432 * in case get disabled before */
433 iwl_set_rxon_ht(priv, &priv->current_ht_config);
434 }
435 mutex_lock(&priv->mutex);
436 if (old_state == IWL_TI_CT_KILL)
437 clear_bit(STATUS_CT_KILL, &priv->status);
438 if (tt->state != IWL_TI_CT_KILL &&
439 iwl_power_update_mode(priv, true)) {
440 /* TT state not updated
441 * try again during next temperature read
442 */
443 IWL_ERR(priv, "Cannot update power mode, "
444 "TT state not updated\n");
445 if (old_state == IWL_TI_CT_KILL)
446 set_bit(STATUS_CT_KILL, &priv->status);
447 tt->state = old_state;
448 } else {
449 IWL_DEBUG_TEMP(priv,
450 "Thermal Throttling to new state: %u\n",
451 tt->state);
452 if (old_state != IWL_TI_CT_KILL &&
453 tt->state == IWL_TI_CT_KILL) {
454 if (force) {
455 IWL_DEBUG_TEMP(priv,
456 "Enter IWL_TI_CT_KILL\n");
457 set_bit(STATUS_CT_KILL, &priv->status);
458 iwl_perform_ct_kill_task(priv, true);
459 } else {
460 tt->state = old_state;
461 iwl_prepare_ct_kill_task(priv);
462 }
463 } else if (old_state == IWL_TI_CT_KILL &&
464 tt->state != IWL_TI_CT_KILL) {
465 IWL_DEBUG_TEMP(priv, "Exit IWL_TI_CT_KILL\n");
466 iwl_perform_ct_kill_task(priv, false);
467 }
468 }
469 mutex_unlock(&priv->mutex);
470 }
471 }
472
473 /* Card State Notification indicated reach critical temperature
474 * if PSP not enable, no Thermal Throttling function will be performed
475 * just set the GP1 bit to acknowledge the event
476 * otherwise, go into IWL_TI_CT_KILL state
477 * since Card State Notification will not provide any temperature reading
478 * for Legacy mode
479 * so just pass the CT_KILL temperature to iwl_legacy_tt_handler()
480 * for advance mode
481 * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state
482 */
iwl_bg_ct_enter(struct work_struct * work)483 static void iwl_bg_ct_enter(struct work_struct *work)
484 {
485 struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);
486 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
487
488 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
489 return;
490
491 if (!iwl_is_ready(priv))
492 return;
493
494 if (tt->state != IWL_TI_CT_KILL) {
495 IWL_ERR(priv, "Device reached critical temperature "
496 "- ucode going to sleep!\n");
497 if (!priv->thermal_throttle.advanced_tt)
498 iwl_legacy_tt_handler(priv,
499 IWL_MINIMAL_POWER_THRESHOLD,
500 true);
501 else
502 iwl_advance_tt_handler(priv,
503 CT_KILL_THRESHOLD + 1, true);
504 }
505 }
506
507 /* Card State Notification indicated out of critical temperature
508 * since Card State Notification will not provide any temperature reading
509 * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature
510 * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state
511 */
iwl_bg_ct_exit(struct work_struct * work)512 static void iwl_bg_ct_exit(struct work_struct *work)
513 {
514 struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);
515 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
516
517 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
518 return;
519
520 if (!iwl_is_ready(priv))
521 return;
522
523 /* stop ct_kill_exit_tm timer */
524 del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
525
526 if (tt->state == IWL_TI_CT_KILL) {
527 IWL_ERR(priv,
528 "Device temperature below critical"
529 "- ucode awake!\n");
530 /*
531 * exit from CT_KILL state
532 * reset the current temperature reading
533 */
534 priv->temperature = 0;
535 if (!priv->thermal_throttle.advanced_tt)
536 iwl_legacy_tt_handler(priv,
537 IWL_REDUCED_PERFORMANCE_THRESHOLD_2,
538 true);
539 else
540 iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD,
541 true);
542 }
543 }
544
iwl_tt_enter_ct_kill(struct iwl_priv * priv)545 void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
546 {
547 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
548 return;
549
550 IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n");
551 queue_work(priv->workqueue, &priv->ct_enter);
552 }
553
iwl_tt_exit_ct_kill(struct iwl_priv * priv)554 void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
555 {
556 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
557 return;
558
559 IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n");
560 queue_work(priv->workqueue, &priv->ct_exit);
561 }
562
iwl_bg_tt_work(struct work_struct * work)563 static void iwl_bg_tt_work(struct work_struct *work)
564 {
565 struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
566 s32 temp = priv->temperature; /* degrees CELSIUS except specified */
567
568 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
569 return;
570
571 if (!priv->thermal_throttle.advanced_tt)
572 iwl_legacy_tt_handler(priv, temp, false);
573 else
574 iwl_advance_tt_handler(priv, temp, false);
575 }
576
iwl_tt_handler(struct iwl_priv * priv)577 void iwl_tt_handler(struct iwl_priv *priv)
578 {
579 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
580 return;
581
582 IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n");
583 queue_work(priv->workqueue, &priv->tt_work);
584 }
585
586 /* Thermal throttling initialization
587 * For advance thermal throttling:
588 * Initialize Thermal Index and temperature threshold table
589 * Initialize thermal throttling restriction table
590 */
iwl_tt_initialize(struct iwl_priv * priv)591 void iwl_tt_initialize(struct iwl_priv *priv)
592 {
593 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
594 int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
595 struct iwl_tt_trans *transaction;
596
597 IWL_DEBUG_TEMP(priv, "Initialize Thermal Throttling\n");
598
599 memset(tt, 0, sizeof(struct iwl_tt_mgmt));
600
601 tt->state = IWL_TI_0;
602 timer_setup(&priv->thermal_throttle.ct_kill_exit_tm,
603 iwl_tt_check_exit_ct_kill, 0);
604 timer_setup(&priv->thermal_throttle.ct_kill_waiting_tm,
605 iwl_tt_ready_for_ct_kill, 0);
606 /* setup deferred ct kill work */
607 INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
608 INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
609 INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
610
611 if (priv->lib->adv_thermal_throttle) {
612 IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n");
613 tt->restriction = kcalloc(IWL_TI_STATE_MAX,
614 sizeof(struct iwl_tt_restriction),
615 GFP_KERNEL);
616 tt->transaction = kcalloc(IWL_TI_STATE_MAX *
617 (IWL_TI_STATE_MAX - 1),
618 sizeof(struct iwl_tt_trans),
619 GFP_KERNEL);
620 if (!tt->restriction || !tt->transaction) {
621 IWL_ERR(priv, "Fallback to Legacy Throttling\n");
622 priv->thermal_throttle.advanced_tt = false;
623 kfree(tt->restriction);
624 tt->restriction = NULL;
625 kfree(tt->transaction);
626 tt->transaction = NULL;
627 } else {
628 transaction = tt->transaction +
629 (IWL_TI_0 * (IWL_TI_STATE_MAX - 1));
630 memcpy(transaction, &tt_range_0[0], size);
631 transaction = tt->transaction +
632 (IWL_TI_1 * (IWL_TI_STATE_MAX - 1));
633 memcpy(transaction, &tt_range_1[0], size);
634 transaction = tt->transaction +
635 (IWL_TI_2 * (IWL_TI_STATE_MAX - 1));
636 memcpy(transaction, &tt_range_2[0], size);
637 transaction = tt->transaction +
638 (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1));
639 memcpy(transaction, &tt_range_3[0], size);
640 size = sizeof(struct iwl_tt_restriction) *
641 IWL_TI_STATE_MAX;
642 memcpy(tt->restriction,
643 &restriction_range[0], size);
644 priv->thermal_throttle.advanced_tt = true;
645 }
646 } else {
647 IWL_DEBUG_TEMP(priv, "Legacy Thermal Throttling\n");
648 priv->thermal_throttle.advanced_tt = false;
649 }
650 }
651
652 /* cleanup thermal throttling management related memory and timer */
iwl_tt_exit(struct iwl_priv * priv)653 void iwl_tt_exit(struct iwl_priv *priv)
654 {
655 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
656
657 /* stop ct_kill_exit_tm timer if activated */
658 del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
659 /* stop ct_kill_waiting_tm timer if activated */
660 del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
661 cancel_work_sync(&priv->tt_work);
662 cancel_work_sync(&priv->ct_enter);
663 cancel_work_sync(&priv->ct_exit);
664
665 if (priv->thermal_throttle.advanced_tt) {
666 /* free advance thermal throttling memory */
667 kfree(tt->restriction);
668 tt->restriction = NULL;
669 kfree(tt->transaction);
670 tt->transaction = NULL;
671 }
672 }
673