.. | .. |
---|
5 | 5 | * |
---|
6 | 6 | * GPL LICENSE SUMMARY |
---|
7 | 7 | * |
---|
8 | | - * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. |
---|
| 8 | + * Copyright(c) 2013 - 2014, 2019 Intel Corporation. All rights reserved. |
---|
9 | 9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
---|
10 | 10 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH |
---|
| 11 | + * Copyright(c) 2019 - 2020 Intel Corporation |
---|
11 | 12 | * |
---|
12 | 13 | * This program is free software; you can redistribute it and/or modify |
---|
13 | 14 | * it under the terms of version 2 of the GNU General Public License as |
---|
.. | .. |
---|
18 | 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
19 | 20 | * General Public License for more details. |
---|
20 | 21 | * |
---|
21 | | - * You should have received a copy of the GNU General Public License |
---|
22 | | - * along with this program; if not, write to the Free Software |
---|
23 | | - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, |
---|
24 | | - * USA |
---|
25 | | - * |
---|
26 | 22 | * The full GNU General Public License is included in this distribution |
---|
27 | 23 | * in the file called COPYING. |
---|
28 | 24 | * |
---|
.. | .. |
---|
32 | 28 | * |
---|
33 | 29 | * BSD LICENSE |
---|
34 | 30 | * |
---|
35 | | - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
---|
| 31 | + * Copyright(c) 2012 - 2014, 2019 Intel Corporation. All rights reserved. |
---|
36 | 32 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
---|
37 | 33 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH |
---|
| 34 | + * Copyright(c) 2019 - 2020 Intel Corporation |
---|
38 | 35 | * All rights reserved. |
---|
39 | 36 | * |
---|
40 | 37 | * Redistribution and use in source and binary forms, with or without |
---|
.. | .. |
---|
231 | 228 | iwl_mvm_enter_ctkill(mvm); |
---|
232 | 229 | } |
---|
233 | 230 | |
---|
234 | | -static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm) |
---|
| 231 | +/* |
---|
| 232 | + * send the DTS_MEASUREMENT_TRIGGER command with or without waiting for a |
---|
| 233 | + * response. If we get a response then the measurement is stored in 'temp' |
---|
| 234 | + */ |
---|
| 235 | +static int iwl_mvm_send_temp_cmd(struct iwl_mvm *mvm, bool response, s32 *temp) |
---|
235 | 236 | { |
---|
236 | | - struct iwl_dts_measurement_cmd cmd = { |
---|
| 237 | + struct iwl_host_cmd cmd = {}; |
---|
| 238 | + struct iwl_dts_measurement_cmd dts_cmd = { |
---|
237 | 239 | .flags = cpu_to_le32(DTS_TRIGGER_CMD_FLAGS_TEMP), |
---|
238 | 240 | }; |
---|
239 | | - struct iwl_ext_dts_measurement_cmd extcmd = { |
---|
240 | | - .control_mode = cpu_to_le32(DTS_AUTOMATIC), |
---|
| 241 | + struct iwl_ext_dts_measurement_cmd ext_cmd = { |
---|
| 242 | + .control_mode = cpu_to_le32(DTS_DIRECT_WITHOUT_MEASURE), |
---|
241 | 243 | }; |
---|
242 | | - u32 cmdid; |
---|
| 244 | + struct iwl_dts_measurement_resp *resp; |
---|
| 245 | + void *cmd_ptr; |
---|
| 246 | + int ret; |
---|
| 247 | + u32 cmd_flags = 0; |
---|
| 248 | + u16 len; |
---|
243 | 249 | |
---|
244 | | - cmdid = iwl_cmd_id(CMD_DTS_MEASUREMENT_TRIGGER_WIDE, |
---|
245 | | - PHY_OPS_GROUP, 0); |
---|
| 250 | + /* Check which command format is used (regular/extended) */ |
---|
| 251 | + if (fw_has_capa(&mvm->fw->ucode_capa, |
---|
| 252 | + IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE)) { |
---|
| 253 | + len = sizeof(ext_cmd); |
---|
| 254 | + cmd_ptr = &ext_cmd; |
---|
| 255 | + } else { |
---|
| 256 | + len = sizeof(dts_cmd); |
---|
| 257 | + cmd_ptr = &dts_cmd; |
---|
| 258 | + } |
---|
| 259 | + /* The command version where we get a response is zero length */ |
---|
| 260 | + if (response) { |
---|
| 261 | + cmd_flags = CMD_WANT_SKB; |
---|
| 262 | + len = 0; |
---|
| 263 | + } |
---|
246 | 264 | |
---|
247 | | - if (!fw_has_capa(&mvm->fw->ucode_capa, |
---|
248 | | - IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE)) |
---|
249 | | - return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(cmd), &cmd); |
---|
| 265 | + cmd.id = WIDE_ID(PHY_OPS_GROUP, CMD_DTS_MEASUREMENT_TRIGGER_WIDE); |
---|
| 266 | + cmd.len[0] = len; |
---|
| 267 | + cmd.flags = cmd_flags; |
---|
| 268 | + cmd.data[0] = cmd_ptr; |
---|
250 | 269 | |
---|
251 | | - return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(extcmd), &extcmd); |
---|
| 270 | + IWL_DEBUG_TEMP(mvm, |
---|
| 271 | + "Sending temperature measurement command - %s response\n", |
---|
| 272 | + response ? "with" : "without"); |
---|
| 273 | + ret = iwl_mvm_send_cmd(mvm, &cmd); |
---|
| 274 | + |
---|
| 275 | + if (ret) { |
---|
| 276 | + IWL_ERR(mvm, |
---|
| 277 | + "Failed to send the temperature measurement command (err=%d)\n", |
---|
| 278 | + ret); |
---|
| 279 | + return ret; |
---|
| 280 | + } |
---|
| 281 | + |
---|
| 282 | + if (response) { |
---|
| 283 | + resp = (void *)cmd.resp_pkt->data; |
---|
| 284 | + *temp = le32_to_cpu(resp->temp); |
---|
| 285 | + IWL_DEBUG_TEMP(mvm, |
---|
| 286 | + "Got temperature measurement response: temp=%d\n", |
---|
| 287 | + *temp); |
---|
| 288 | + iwl_free_resp(&cmd); |
---|
| 289 | + } |
---|
| 290 | + |
---|
| 291 | + return ret; |
---|
252 | 292 | } |
---|
253 | 293 | |
---|
254 | 294 | int iwl_mvm_get_temp(struct iwl_mvm *mvm, s32 *temp) |
---|
.. | .. |
---|
257 | 297 | static u16 temp_notif[] = { WIDE_ID(PHY_OPS_GROUP, |
---|
258 | 298 | DTS_MEASUREMENT_NOTIF_WIDE) }; |
---|
259 | 299 | int ret; |
---|
| 300 | + u8 cmd_ver; |
---|
| 301 | + |
---|
| 302 | + /* |
---|
| 303 | + * If command version is 1 we send the command and immediately get |
---|
| 304 | + * a response. For older versions we send the command and wait for a |
---|
| 305 | + * notification (no command TLV for previous versions). |
---|
| 306 | + */ |
---|
| 307 | + cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_OPS_GROUP, |
---|
| 308 | + CMD_DTS_MEASUREMENT_TRIGGER_WIDE, |
---|
| 309 | + IWL_FW_CMD_VER_UNKNOWN); |
---|
| 310 | + if (cmd_ver == 1) |
---|
| 311 | + return iwl_mvm_send_temp_cmd(mvm, true, temp); |
---|
260 | 312 | |
---|
261 | 313 | lockdep_assert_held(&mvm->mutex); |
---|
262 | 314 | |
---|
.. | .. |
---|
264 | 316 | temp_notif, ARRAY_SIZE(temp_notif), |
---|
265 | 317 | iwl_mvm_temp_notif_wait, temp); |
---|
266 | 318 | |
---|
267 | | - ret = iwl_mvm_get_temp_cmd(mvm); |
---|
| 319 | + ret = iwl_mvm_send_temp_cmd(mvm, false, temp); |
---|
268 | 320 | if (ret) { |
---|
269 | | - IWL_ERR(mvm, "Failed to get the temperature (err=%d)\n", ret); |
---|
270 | 321 | iwl_remove_notification(&mvm->notif_wait, &wait_temp_notif); |
---|
271 | 322 | return ret; |
---|
272 | 323 | } |
---|
.. | .. |
---|
298 | 349 | |
---|
299 | 350 | duration = tt->params.ct_kill_duration; |
---|
300 | 351 | |
---|
| 352 | + flush_work(&mvm->roc_done_wk); |
---|
| 353 | + |
---|
301 | 354 | mutex_lock(&mvm->mutex); |
---|
302 | 355 | |
---|
303 | 356 | if (__iwl_mvm_mac_start(mvm)) |
---|
304 | 357 | goto reschedule; |
---|
305 | 358 | |
---|
306 | | - /* make sure the device is available for direct read/writes */ |
---|
307 | | - if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_CHECK_CTKILL)) { |
---|
308 | | - __iwl_mvm_mac_stop(mvm); |
---|
309 | | - goto reschedule; |
---|
310 | | - } |
---|
311 | | - |
---|
312 | 359 | ret = iwl_mvm_get_temp(mvm, &temp); |
---|
313 | | - |
---|
314 | | - iwl_mvm_unref(mvm, IWL_MVM_REF_CHECK_CTKILL); |
---|
315 | 360 | |
---|
316 | 361 | __iwl_mvm_mac_stop(mvm); |
---|
317 | 362 | |
---|
.. | .. |
---|
356 | 401 | struct iwl_mvm_sta *mvmsta; |
---|
357 | 402 | int i, err; |
---|
358 | 403 | |
---|
359 | | - for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) { |
---|
| 404 | + for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) { |
---|
360 | 405 | mvmsta = iwl_mvm_sta_from_staid_protected(mvm, i); |
---|
361 | 406 | if (!mvmsta) |
---|
362 | 407 | continue; |
---|
.. | .. |
---|
495 | 540 | |
---|
496 | 541 | /* budget in mWatt */ |
---|
497 | 542 | static const u32 iwl_mvm_cdev_budgets[] = { |
---|
498 | | - 2000, /* cooling state 0 */ |
---|
499 | | - 1800, /* cooling state 1 */ |
---|
500 | | - 1600, /* cooling state 2 */ |
---|
501 | | - 1400, /* cooling state 3 */ |
---|
502 | | - 1200, /* cooling state 4 */ |
---|
503 | | - 1000, /* cooling state 5 */ |
---|
504 | | - 900, /* cooling state 6 */ |
---|
505 | | - 800, /* cooling state 7 */ |
---|
506 | | - 700, /* cooling state 8 */ |
---|
507 | | - 650, /* cooling state 9 */ |
---|
508 | | - 600, /* cooling state 10 */ |
---|
509 | | - 550, /* cooling state 11 */ |
---|
510 | | - 500, /* cooling state 12 */ |
---|
511 | | - 450, /* cooling state 13 */ |
---|
512 | | - 400, /* cooling state 14 */ |
---|
513 | | - 350, /* cooling state 15 */ |
---|
514 | | - 300, /* cooling state 16 */ |
---|
515 | | - 250, /* cooling state 17 */ |
---|
516 | | - 200, /* cooling state 18 */ |
---|
517 | | - 150, /* cooling state 19 */ |
---|
| 543 | + 2400, /* cooling state 0 */ |
---|
| 544 | + 2000, /* cooling state 1 */ |
---|
| 545 | + 1800, /* cooling state 2 */ |
---|
| 546 | + 1600, /* cooling state 3 */ |
---|
| 547 | + 1400, /* cooling state 4 */ |
---|
| 548 | + 1200, /* cooling state 5 */ |
---|
| 549 | + 1000, /* cooling state 6 */ |
---|
| 550 | + 900, /* cooling state 7 */ |
---|
| 551 | + 800, /* cooling state 8 */ |
---|
| 552 | + 700, /* cooling state 9 */ |
---|
| 553 | + 650, /* cooling state 10 */ |
---|
| 554 | + 600, /* cooling state 11 */ |
---|
| 555 | + 550, /* cooling state 12 */ |
---|
| 556 | + 500, /* cooling state 13 */ |
---|
| 557 | + 450, /* cooling state 14 */ |
---|
| 558 | + 400, /* cooling state 15 */ |
---|
| 559 | + 350, /* cooling state 16 */ |
---|
| 560 | + 300, /* cooling state 17 */ |
---|
| 561 | + 250, /* cooling state 18 */ |
---|
| 562 | + 200, /* cooling state 19 */ |
---|
| 563 | + 150, /* cooling state 20 */ |
---|
518 | 564 | }; |
---|
519 | 565 | |
---|
520 | 566 | int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 state) |
---|
.. | .. |
---|
568 | 614 | return ((s16)le16_to_cpu(*(__le16 *)a) - |
---|
569 | 615 | (s16)le16_to_cpu(*(__le16 *)b)); |
---|
570 | 616 | } |
---|
| 617 | +#endif |
---|
571 | 618 | |
---|
572 | 619 | int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm) |
---|
573 | 620 | { |
---|
574 | 621 | struct temp_report_ths_cmd cmd = {0}; |
---|
575 | | - int ret, i, j, idx = 0; |
---|
| 622 | + int ret; |
---|
| 623 | +#ifdef CONFIG_THERMAL |
---|
| 624 | + int i, j, idx = 0; |
---|
576 | 625 | |
---|
577 | 626 | lockdep_assert_held(&mvm->mutex); |
---|
578 | 627 | |
---|
579 | 628 | if (!mvm->tz_device.tzone) |
---|
580 | | - return -EINVAL; |
---|
| 629 | + goto send; |
---|
581 | 630 | |
---|
582 | 631 | /* The driver holds array of temperature trips that are unsorted |
---|
583 | 632 | * and uncompressed, the FW should get it compressed and sorted |
---|
.. | .. |
---|
610 | 659 | } |
---|
611 | 660 | |
---|
612 | 661 | send: |
---|
| 662 | +#endif |
---|
613 | 663 | ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(PHY_OPS_GROUP, |
---|
614 | 664 | TEMP_REPORTING_THRESHOLDS_CMD), |
---|
615 | 665 | 0, sizeof(cmd), &cmd); |
---|
.. | .. |
---|
620 | 670 | return ret; |
---|
621 | 671 | } |
---|
622 | 672 | |
---|
| 673 | +#ifdef CONFIG_THERMAL |
---|
623 | 674 | static int iwl_mvm_tzone_get_temp(struct thermal_zone_device *device, |
---|
624 | 675 | int *temperature) |
---|
625 | 676 | { |
---|
.. | .. |
---|
738 | 789 | |
---|
739 | 790 | static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm) |
---|
740 | 791 | { |
---|
741 | | - int i; |
---|
| 792 | + int i, ret; |
---|
742 | 793 | char name[16]; |
---|
743 | 794 | static atomic_t counter = ATOMIC_INIT(0); |
---|
744 | 795 | |
---|
.. | .. |
---|
764 | 815 | return; |
---|
765 | 816 | } |
---|
766 | 817 | |
---|
| 818 | + ret = thermal_zone_device_enable(mvm->tz_device.tzone); |
---|
| 819 | + if (ret) { |
---|
| 820 | + IWL_DEBUG_TEMP(mvm, "Failed to enable thermal zone\n"); |
---|
| 821 | + thermal_zone_device_unregister(mvm->tz_device.tzone); |
---|
| 822 | + return; |
---|
| 823 | + } |
---|
| 824 | + |
---|
767 | 825 | /* 0 is a valid temperature, |
---|
768 | 826 | * so initialize the array with S16_MIN which invalid temperature |
---|
769 | 827 | */ |
---|