| .. | .. |
|---|
| 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 | */ |
|---|