1 /****************************************************************************** 2 * 3 * This file is provided under a dual BSD/GPLv2 license. When using or 4 * redistributing this file, you may do so under either license. 5 * 6 * GPL LICENSE SUMMARY 7 * 8 * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. 9 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH 10 * Copyright(c) 2015 - 2017 Intel Deutschland GmbH 11 * Copyright(c) 2018 - 2019 Intel Corporation 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of version 2 of the GNU General Public License as 15 * published by the Free Software Foundation. 16 * 17 * This program is distributed in the hope that it will be useful, but 18 * WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 * General Public License for more details. 21 * 22 * The full GNU General Public License is included in this distribution 23 * in the file called COPYING. 24 * 25 * Contact Information: 26 * Intel Linux Wireless <linuxwifi@intel.com> 27 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 28 * 29 * BSD LICENSE 30 * 31 * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. 32 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH 33 * Copyright(c) 2015 - 2017 Intel Deutschland GmbH 34 * Copyright(c) 2018 - 2019 Intel Corporation 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 41 * * Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * * Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in 45 * the documentation and/or other materials provided with the 46 * distribution. 47 * * Neither the name Intel Corporation nor the names of its 48 * contributors may be used to endorse or promote products derived 49 * from this software without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 52 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 53 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 54 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 55 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 56 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 57 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 58 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 59 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 60 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 61 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 * 63 *****************************************************************************/ 64 65 #ifndef __iwl_fw_dbg_h__ 66 #define __iwl_fw_dbg_h__ 67 #include <linux/workqueue.h> 68 #include <net/cfg80211.h> 69 #include "runtime.h" 70 #include "iwl-prph.h" 71 #include "iwl-io.h" 72 #include "file.h" 73 #include "error-dump.h" 74 #include "api/commands.h" 75 #include "api/dbg-tlv.h" 76 #include "api/alive.h" 77 78 /** 79 * struct iwl_fw_dump_desc - describes the dump 80 * @len: length of trig_desc->data 81 * @trig_desc: the description of the dump 82 */ 83 struct iwl_fw_dump_desc { 84 size_t len; 85 /* must be last */ 86 struct iwl_fw_error_dump_trigger_desc trig_desc; 87 }; 88 89 /** 90 * struct iwl_fw_dbg_params - register values to restore 91 * @in_sample: DBGC_IN_SAMPLE value 92 * @out_ctrl: DBGC_OUT_CTRL value 93 */ 94 struct iwl_fw_dbg_params { 95 u32 in_sample; 96 u32 out_ctrl; 97 }; 98 99 extern const struct iwl_fw_dump_desc iwl_dump_desc_assert; 100 101 static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt) 102 { 103 if (fwrt->dump.desc != &iwl_dump_desc_assert) 104 kfree(fwrt->dump.desc); 105 fwrt->dump.desc = NULL; 106 fwrt->dump.lmac_err_id[0] = 0; 107 if (fwrt->smem_cfg.num_lmacs > 1) 108 fwrt->dump.lmac_err_id[1] = 0; 109 fwrt->dump.umac_err_id = 0; 110 } 111 112 int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, 113 const struct iwl_fw_dump_desc *desc, 114 bool monitor_only, unsigned int delay); 115 int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt, 116 enum iwl_fw_dbg_trigger trig_type); 117 int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, 118 enum iwl_fw_ini_trigger_id id); 119 int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, u32 legacy_trigger_id); 120 int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, 121 enum iwl_fw_dbg_trigger trig, const char *str, 122 size_t len, struct iwl_fw_dbg_trigger_tlv *trigger); 123 int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt, 124 struct iwl_fw_dbg_trigger_tlv *trigger, 125 const char *fmt, ...) __printf(3, 4); 126 int iwl_fw_start_dbg_conf(struct iwl_fw_runtime *fwrt, u8 id); 127 128 #define iwl_fw_dbg_trigger_enabled(fw, id) ({ \ 129 void *__dbg_trigger = (fw)->dbg.trigger_tlv[(id)]; \ 130 unlikely(__dbg_trigger); \ 131 }) 132 133 static inline struct iwl_fw_dbg_trigger_tlv* 134 _iwl_fw_dbg_get_trigger(const struct iwl_fw *fw, enum iwl_fw_dbg_trigger id) 135 { 136 return fw->dbg.trigger_tlv[id]; 137 } 138 139 #define iwl_fw_dbg_get_trigger(fw, id) ({ \ 140 BUILD_BUG_ON(!__builtin_constant_p(id)); \ 141 BUILD_BUG_ON((id) >= FW_DBG_TRIGGER_MAX); \ 142 _iwl_fw_dbg_get_trigger((fw), (id)); \ 143 }) 144 145 static inline bool 146 iwl_fw_dbg_trigger_vif_match(struct iwl_fw_dbg_trigger_tlv *trig, 147 struct wireless_dev *wdev) 148 { 149 u32 trig_vif = le32_to_cpu(trig->vif_type); 150 151 return trig_vif == IWL_FW_DBG_CONF_VIF_ANY || 152 wdev->iftype == trig_vif; 153 } 154 155 static inline bool 156 iwl_fw_dbg_trigger_stop_conf_match(struct iwl_fw_runtime *fwrt, 157 struct iwl_fw_dbg_trigger_tlv *trig) 158 { 159 return ((trig->mode & IWL_FW_DBG_TRIGGER_STOP) && 160 (fwrt->dump.conf == FW_DBG_INVALID || 161 (BIT(fwrt->dump.conf) & le32_to_cpu(trig->stop_conf_ids)))); 162 } 163 164 static inline bool 165 iwl_fw_dbg_no_trig_window(struct iwl_fw_runtime *fwrt, u32 id, u32 dis_usec) 166 { 167 unsigned long wind_jiff = usecs_to_jiffies(dis_usec); 168 169 /* If this is the first event checked, jump to update start ts */ 170 if (fwrt->dump.non_collect_ts_start[id] && 171 (time_after(fwrt->dump.non_collect_ts_start[id] + wind_jiff, 172 jiffies))) 173 return true; 174 175 fwrt->dump.non_collect_ts_start[id] = jiffies; 176 return false; 177 } 178 179 static inline bool 180 iwl_fw_dbg_trigger_check_stop(struct iwl_fw_runtime *fwrt, 181 struct wireless_dev *wdev, 182 struct iwl_fw_dbg_trigger_tlv *trig) 183 { 184 u32 usec = le16_to_cpu(trig->trig_dis_ms) * USEC_PER_MSEC; 185 186 if (wdev && !iwl_fw_dbg_trigger_vif_match(trig, wdev)) 187 return false; 188 189 if (iwl_fw_dbg_no_trig_window(fwrt, le32_to_cpu(trig->id), usec)) { 190 IWL_WARN(fwrt, "Trigger %d occurred while no-collect window.\n", 191 trig->id); 192 return false; 193 } 194 195 return iwl_fw_dbg_trigger_stop_conf_match(fwrt, trig); 196 } 197 198 static inline struct iwl_fw_dbg_trigger_tlv* 199 _iwl_fw_dbg_trigger_on(struct iwl_fw_runtime *fwrt, 200 struct wireless_dev *wdev, 201 const enum iwl_fw_dbg_trigger id) 202 { 203 struct iwl_fw_dbg_trigger_tlv *trig; 204 205 if (fwrt->trans->dbg.ini_valid) 206 return NULL; 207 208 if (!iwl_fw_dbg_trigger_enabled(fwrt->fw, id)) 209 return NULL; 210 211 trig = _iwl_fw_dbg_get_trigger(fwrt->fw, id); 212 213 if (!iwl_fw_dbg_trigger_check_stop(fwrt, wdev, trig)) 214 return NULL; 215 216 return trig; 217 } 218 219 #define iwl_fw_dbg_trigger_on(fwrt, wdev, id) ({ \ 220 BUILD_BUG_ON(!__builtin_constant_p(id)); \ 221 BUILD_BUG_ON((id) >= FW_DBG_TRIGGER_MAX); \ 222 _iwl_fw_dbg_trigger_on((fwrt), (wdev), (id)); \ 223 }) 224 225 static inline bool 226 iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt, 227 enum iwl_fw_ini_trigger_id id) 228 { 229 struct iwl_fw_ini_trigger *trig; 230 u32 usec; 231 232 if (!fwrt->trans->dbg.ini_valid || id == IWL_FW_TRIGGER_ID_INVALID || 233 id >= IWL_FW_TRIGGER_ID_NUM || !fwrt->dump.active_trigs[id].active) 234 return false; 235 236 trig = fwrt->dump.active_trigs[id].trig; 237 usec = le32_to_cpu(trig->ignore_consec); 238 239 if (iwl_fw_dbg_no_trig_window(fwrt, id, usec)) { 240 IWL_WARN(fwrt, "Trigger %d fired in no-collect window\n", id); 241 return false; 242 } 243 244 return true; 245 } 246 247 static inline void 248 _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt, 249 struct wireless_dev *wdev, 250 struct iwl_fw_dbg_trigger_tlv *trigger) 251 { 252 if (!trigger) 253 return; 254 255 if (!iwl_fw_dbg_trigger_check_stop(fwrt, wdev, trigger)) 256 return; 257 258 iwl_fw_dbg_collect_trig(fwrt, trigger, NULL); 259 } 260 261 #define iwl_fw_dbg_trigger_simple_stop(fwrt, wdev, trig) \ 262 _iwl_fw_dbg_trigger_simple_stop((fwrt), (wdev), \ 263 iwl_fw_dbg_get_trigger((fwrt)->fw,\ 264 (trig))) 265 266 static inline void 267 _iwl_fw_dbg_stop_recording(struct iwl_trans *trans, 268 struct iwl_fw_dbg_params *params) 269 { 270 if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) { 271 iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100); 272 return; 273 } 274 275 if (params) { 276 params->in_sample = iwl_read_umac_prph(trans, DBGC_IN_SAMPLE); 277 params->out_ctrl = iwl_read_umac_prph(trans, DBGC_OUT_CTRL); 278 } 279 280 iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, 0); 281 /* wait for the DBGC to finish writing the internal buffer to DRAM to 282 * avoid halting the HW while writing 283 */ 284 usleep_range(700, 1000); 285 iwl_write_umac_prph(trans, DBGC_OUT_CTRL, 0); 286 #ifdef CONFIG_IWLWIFI_DEBUGFS 287 trans->dbg.rec_on = false; 288 #endif 289 } 290 291 static inline void 292 iwl_fw_dbg_stop_recording(struct iwl_trans *trans, 293 struct iwl_fw_dbg_params *params) 294 { 295 /* if the FW crashed or not debug monitor cfg was given, there is 296 * no point in stopping 297 */ 298 if (test_bit(STATUS_FW_ERROR, &trans->status) || 299 (!trans->dbg.dest_tlv && 300 trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID)) 301 return; 302 303 if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) { 304 IWL_ERR(trans, 305 "WRT: unsupported device family %d for debug stop recording\n", 306 trans->cfg->device_family); 307 return; 308 } 309 _iwl_fw_dbg_stop_recording(trans, params); 310 } 311 312 static inline void 313 _iwl_fw_dbg_restart_recording(struct iwl_trans *trans, 314 struct iwl_fw_dbg_params *params) 315 { 316 if (WARN_ON(!params)) 317 return; 318 319 if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) { 320 iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100); 321 iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1); 322 iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1); 323 } else { 324 iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, params->in_sample); 325 iwl_write_umac_prph(trans, DBGC_OUT_CTRL, params->out_ctrl); 326 } 327 } 328 329 #ifdef CONFIG_IWLWIFI_DEBUGFS 330 static inline void iwl_fw_set_dbg_rec_on(struct iwl_fw_runtime *fwrt) 331 { 332 if (fwrt->cur_fw_img == IWL_UCODE_REGULAR && 333 (fwrt->fw->dbg.dest_tlv || 334 fwrt->trans->dbg.ini_dest != IWL_FW_INI_LOCATION_INVALID)) 335 fwrt->trans->dbg.rec_on = true; 336 } 337 #endif 338 339 static inline void 340 iwl_fw_dbg_restart_recording(struct iwl_fw_runtime *fwrt, 341 struct iwl_fw_dbg_params *params) 342 { 343 /* if the FW crashed or not debug monitor cfg was given, there is 344 * no point in restarting 345 */ 346 if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status) || 347 (!fwrt->trans->dbg.dest_tlv && 348 fwrt->trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID)) 349 return; 350 351 if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) { 352 IWL_ERR(fwrt, 353 "WRT: unsupported device family %d for debug restart recording\n", 354 fwrt->trans->cfg->device_family); 355 return; 356 } 357 _iwl_fw_dbg_restart_recording(fwrt->trans, params); 358 #ifdef CONFIG_IWLWIFI_DEBUGFS 359 iwl_fw_set_dbg_rec_on(fwrt); 360 #endif 361 } 362 363 static inline void iwl_fw_dump_conf_clear(struct iwl_fw_runtime *fwrt) 364 { 365 fwrt->dump.conf = FW_DBG_INVALID; 366 } 367 368 void iwl_fw_error_dump_wk(struct work_struct *work); 369 370 static inline bool iwl_fw_dbg_type_on(struct iwl_fw_runtime *fwrt, u32 type) 371 { 372 return (fwrt->fw->dbg.dump_mask & BIT(type)); 373 } 374 375 static inline bool iwl_fw_dbg_is_d3_debug_enabled(struct iwl_fw_runtime *fwrt) 376 { 377 return fw_has_capa(&fwrt->fw->ucode_capa, 378 IWL_UCODE_TLV_CAPA_D3_DEBUG) && 379 fwrt->trans->cfg->d3_debug_data_length && fwrt->ops && 380 fwrt->ops->d3_debug_enable && 381 fwrt->ops->d3_debug_enable(fwrt->ops_ctx) && 382 iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_D3_DEBUG_DATA); 383 } 384 385 static inline bool iwl_fw_dbg_is_paging_enabled(struct iwl_fw_runtime *fwrt) 386 { 387 return iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_PAGING) && 388 !fwrt->trans->cfg->gen2 && 389 fwrt->cur_fw_img < IWL_UCODE_TYPE_MAX && 390 fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size && 391 fwrt->fw_paging_db[0].fw_paging_block; 392 } 393 394 void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt); 395 396 static inline void iwl_fw_flush_dumps(struct iwl_fw_runtime *fwrt) 397 { 398 int i; 399 400 del_timer(&fwrt->dump.periodic_trig); 401 for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) { 402 flush_delayed_work(&fwrt->dump.wks[i].wk); 403 fwrt->dump.wks[i].ini_trig_id = IWL_FW_TRIGGER_ID_INVALID; 404 } 405 } 406 407 static inline void iwl_fw_cancel_dumps(struct iwl_fw_runtime *fwrt) 408 { 409 int i; 410 411 del_timer(&fwrt->dump.periodic_trig); 412 for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) { 413 cancel_delayed_work_sync(&fwrt->dump.wks[i].wk); 414 fwrt->dump.wks[i].ini_trig_id = IWL_FW_TRIGGER_ID_INVALID; 415 } 416 } 417 418 #ifdef CONFIG_IWLWIFI_DEBUGFS 419 static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt) 420 { 421 fwrt->timestamp.delay = 0; 422 cancel_delayed_work_sync(&fwrt->timestamp.wk); 423 } 424 425 void iwl_fw_trigger_timestamp(struct iwl_fw_runtime *fwrt, u32 delay); 426 427 static inline void iwl_fw_suspend_timestamp(struct iwl_fw_runtime *fwrt) 428 { 429 cancel_delayed_work_sync(&fwrt->timestamp.wk); 430 } 431 432 static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) 433 { 434 if (!fwrt->timestamp.delay) 435 return; 436 437 schedule_delayed_work(&fwrt->timestamp.wk, 438 round_jiffies_relative(fwrt->timestamp.delay)); 439 } 440 441 #else 442 443 static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt) {} 444 445 static inline void iwl_fw_trigger_timestamp(struct iwl_fw_runtime *fwrt, 446 u32 delay) {} 447 448 static inline void iwl_fw_suspend_timestamp(struct iwl_fw_runtime *fwrt) {} 449 450 static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) {} 451 452 #endif /* CONFIG_IWLWIFI_DEBUGFS */ 453 454 void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, 455 enum iwl_fw_ini_apply_point apply_point); 456 457 void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt); 458 459 static inline void iwl_fw_lmac1_set_alive_err_table(struct iwl_trans *trans, 460 u32 lmac_error_event_table) 461 { 462 if (!(trans->dbg.error_event_table_tlv_status & 463 IWL_ERROR_EVENT_TABLE_LMAC1) || 464 WARN_ON(trans->dbg.lmac_error_event_table[0] != 465 lmac_error_event_table)) 466 trans->dbg.lmac_error_event_table[0] = lmac_error_event_table; 467 } 468 469 static inline void iwl_fw_umac_set_alive_err_table(struct iwl_trans *trans, 470 u32 umac_error_event_table) 471 { 472 if (!(trans->dbg.error_event_table_tlv_status & 473 IWL_ERROR_EVENT_TABLE_UMAC) || 474 WARN_ON(trans->dbg.umac_error_event_table != 475 umac_error_event_table)) 476 trans->dbg.umac_error_event_table = umac_error_event_table; 477 } 478 479 static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt) 480 { 481 if (fwrt->trans->dbg.ini_valid && fwrt->trans->dbg.hw_error) { 482 _iwl_fw_dbg_ini_collect(fwrt, IWL_FW_TRIGGER_ID_FW_HW_ERROR); 483 fwrt->trans->dbg.hw_error = false; 484 } else { 485 iwl_fw_dbg_collect_desc(fwrt, &iwl_dump_desc_assert, false, 0); 486 } 487 } 488 489 void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t); 490 491 void iwl_fw_error_print_fseq_regs(struct iwl_fw_runtime *fwrt); 492 493 static inline void iwl_fwrt_update_fw_versions(struct iwl_fw_runtime *fwrt, 494 struct iwl_lmac_alive *lmac, 495 struct iwl_umac_alive *umac) 496 { 497 if (lmac) { 498 fwrt->dump.fw_ver.type = lmac->ver_type; 499 fwrt->dump.fw_ver.subtype = lmac->ver_subtype; 500 fwrt->dump.fw_ver.lmac_major = le32_to_cpu(lmac->ucode_major); 501 fwrt->dump.fw_ver.lmac_minor = le32_to_cpu(lmac->ucode_minor); 502 } 503 504 if (umac) { 505 fwrt->dump.fw_ver.umac_major = le32_to_cpu(umac->umac_major); 506 fwrt->dump.fw_ver.umac_minor = le32_to_cpu(umac->umac_minor); 507 } 508 } 509 #endif /* __iwl_fw_dbg_h__ */ 510