1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2012-2014, 2018-2023, 2025 Intel Corporation 4 * Copyright (C) 2013-2015 Intel Mobile Communications GmbH 5 * Copyright (C) 2016-2017 Intel Deutschland GmbH 6 */ 7 #include <linux/vmalloc.h> 8 #include <linux/err.h> 9 #include <linux/hex.h> 10 #include <linux/ieee80211.h> 11 #include <linux/netdevice.h> 12 #include <linux/dmi.h> 13 14 #include "mvm.h" 15 #include "sta.h" 16 #include "iwl-trans.h" 17 #include "debugfs.h" 18 #include "iwl-modparams.h" 19 #include "iwl-drv.h" 20 #include "iwl-utils.h" 21 #include "fw/error-dump.h" 22 #include "fw/api/phy-ctxt.h" 23 24 static ssize_t iwl_dbgfs_ctdp_budget_read(struct file *file, 25 char __user *user_buf, 26 size_t count, loff_t *ppos) 27 { 28 struct iwl_mvm *mvm = file->private_data; 29 char buf[16]; 30 int pos, budget; 31 32 if (!iwl_mvm_is_ctdp_supported(mvm)) 33 return -EOPNOTSUPP; 34 35 if (!iwl_mvm_firmware_running(mvm) || 36 mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR) 37 return -EIO; 38 39 mutex_lock(&mvm->mutex); 40 budget = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_REPORT, 0); 41 mutex_unlock(&mvm->mutex); 42 43 if (budget < 0) 44 return budget; 45 46 pos = scnprintf(buf, sizeof(buf), "%d\n", budget); 47 48 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 49 } 50 51 static ssize_t iwl_dbgfs_stop_ctdp_write(struct iwl_mvm *mvm, char *buf, 52 size_t count, loff_t *ppos) 53 { 54 int ret; 55 bool force; 56 57 if (!kstrtobool(buf, &force)) 58 IWL_DEBUG_INFO(mvm, 59 "force start is %d [0=disabled, 1=enabled]\n", 60 force); 61 62 /* we allow skipping cap support check and force stop ctdp 63 * statistics collection and with guerantee that it is 64 * safe to use. 65 */ 66 if (!force && !iwl_mvm_is_ctdp_supported(mvm)) 67 return -EOPNOTSUPP; 68 69 if (!iwl_mvm_firmware_running(mvm) || 70 mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR) 71 return -EIO; 72 73 mutex_lock(&mvm->mutex); 74 ret = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_STOP, 0); 75 mutex_unlock(&mvm->mutex); 76 77 return ret ?: count; 78 } 79 80 static ssize_t iwl_dbgfs_start_ctdp_write(struct iwl_mvm *mvm, 81 char *buf, size_t count, 82 loff_t *ppos) 83 { 84 int ret; 85 bool force; 86 87 if (!kstrtobool(buf, &force)) 88 IWL_DEBUG_INFO(mvm, 89 "force start is %d [0=disabled, 1=enabled]\n", 90 force); 91 92 /* we allow skipping cap support check and force enable ctdp 93 * for statistics collection and with guerantee that it is 94 * safe to use. 95 */ 96 if (!force && !iwl_mvm_is_ctdp_supported(mvm)) 97 return -EOPNOTSUPP; 98 99 if (!iwl_mvm_firmware_running(mvm) || 100 mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR) 101 return -EIO; 102 103 mutex_lock(&mvm->mutex); 104 ret = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_START, 0); 105 mutex_unlock(&mvm->mutex); 106 107 return ret ?: count; 108 } 109 110 static ssize_t iwl_dbgfs_force_ctkill_write(struct iwl_mvm *mvm, char *buf, 111 size_t count, loff_t *ppos) 112 { 113 if (!iwl_mvm_firmware_running(mvm) || 114 mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR) 115 return -EIO; 116 117 iwl_mvm_enter_ctkill(mvm); 118 119 return count; 120 } 121 122 static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf, 123 size_t count, loff_t *ppos) 124 { 125 int ret; 126 u32 flush_arg; 127 128 if (!iwl_mvm_firmware_running(mvm) || 129 mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR) 130 return -EIO; 131 132 if (kstrtou32(buf, 0, &flush_arg)) 133 return -EINVAL; 134 135 if (iwl_mvm_has_new_tx_api(mvm)) { 136 IWL_DEBUG_TX_QUEUES(mvm, 137 "FLUSHING all tids queues on sta_id = %d\n", 138 flush_arg); 139 mutex_lock(&mvm->mutex); 140 ret = iwl_mvm_flush_sta_tids(mvm, flush_arg, 0xFFFF) 141 ? : count; 142 mutex_unlock(&mvm->mutex); 143 return ret; 144 } 145 146 IWL_DEBUG_TX_QUEUES(mvm, "FLUSHING queues mask to flush = 0x%x\n", 147 flush_arg); 148 149 mutex_lock(&mvm->mutex); 150 ret = iwl_mvm_flush_tx_path(mvm, flush_arg) ? : count; 151 mutex_unlock(&mvm->mutex); 152 153 return ret; 154 } 155 156 static ssize_t iwl_dbgfs_set_nic_temperature_read(struct file *file, 157 char __user *user_buf, 158 size_t count, loff_t *ppos) 159 { 160 struct iwl_mvm *mvm = file->private_data; 161 char buf[16]; 162 int pos; 163 164 if (!mvm->temperature_test) 165 pos = scnprintf(buf, sizeof(buf), "disabled\n"); 166 else 167 pos = scnprintf(buf, sizeof(buf), "%d\n", mvm->temperature); 168 169 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 170 } 171 172 /* 173 * Set NIC Temperature 174 * Cause the driver to ignore the actual NIC temperature reported by the FW 175 * Enable: any value between IWL_MVM_DEBUG_SET_TEMPERATURE_MIN - 176 * IWL_MVM_DEBUG_SET_TEMPERATURE_MAX 177 * Disable: IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE 178 */ 179 static ssize_t iwl_dbgfs_set_nic_temperature_write(struct iwl_mvm *mvm, 180 char *buf, size_t count, 181 loff_t *ppos) 182 { 183 int temperature; 184 185 if (!iwl_mvm_firmware_running(mvm) && !mvm->temperature_test) 186 return -EIO; 187 188 if (kstrtoint(buf, 10, &temperature)) 189 return -EINVAL; 190 /* not a legal temperature */ 191 if ((temperature > IWL_MVM_DEBUG_SET_TEMPERATURE_MAX && 192 temperature != IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) || 193 temperature < IWL_MVM_DEBUG_SET_TEMPERATURE_MIN) 194 return -EINVAL; 195 196 mutex_lock(&mvm->mutex); 197 if (temperature == IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) { 198 if (!mvm->temperature_test) 199 goto out; 200 201 mvm->temperature_test = false; 202 /* Since we can't read the temp while awake, just set 203 * it to zero until we get the next RX stats from the 204 * firmware. 205 */ 206 mvm->temperature = 0; 207 } else { 208 mvm->temperature_test = true; 209 mvm->temperature = temperature; 210 } 211 IWL_DEBUG_TEMP(mvm, "%sabling debug set temperature (temp = %d)\n", 212 mvm->temperature_test ? "En" : "Dis", 213 mvm->temperature); 214 /* handle the temperature change */ 215 iwl_mvm_tt_handler(mvm); 216 217 out: 218 mutex_unlock(&mvm->mutex); 219 220 return count; 221 } 222 223 static ssize_t iwl_dbgfs_nic_temp_read(struct file *file, 224 char __user *user_buf, 225 size_t count, loff_t *ppos) 226 { 227 struct iwl_mvm *mvm = file->private_data; 228 char buf[16]; 229 int pos, ret; 230 s32 temp; 231 232 if (!iwl_mvm_firmware_running(mvm)) 233 return -EIO; 234 235 mutex_lock(&mvm->mutex); 236 ret = iwl_mvm_get_temp(mvm, &temp); 237 mutex_unlock(&mvm->mutex); 238 239 if (ret) 240 return -EIO; 241 242 pos = scnprintf(buf, sizeof(buf), "%d\n", temp); 243 244 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 245 } 246 247 #ifdef CONFIG_ACPI 248 static ssize_t iwl_dbgfs_sar_geo_profile_read(struct file *file, 249 char __user *user_buf, 250 size_t count, loff_t *ppos) 251 { 252 struct iwl_mvm *mvm = file->private_data; 253 char buf[256]; 254 int pos = 0; 255 int bufsz = sizeof(buf); 256 int tbl_idx; 257 258 if (!iwl_mvm_firmware_running(mvm)) 259 return -EIO; 260 261 mutex_lock(&mvm->mutex); 262 tbl_idx = iwl_mvm_get_sar_geo_profile(mvm); 263 if (tbl_idx < 0) { 264 mutex_unlock(&mvm->mutex); 265 return tbl_idx; 266 } 267 268 if (!tbl_idx) { 269 pos = scnprintf(buf, bufsz, 270 "SAR geographic profile disabled\n"); 271 } else { 272 pos += scnprintf(buf + pos, bufsz - pos, 273 "Use geographic profile %d\n", tbl_idx); 274 pos += scnprintf(buf + pos, bufsz - pos, 275 "2.4GHz:\n\tChain A offset: %u dBm\n\tChain B offset: %u dBm\n\tmax tx power: %u dBm\n", 276 mvm->fwrt.geo_profiles[tbl_idx - 1].bands[0].chains[0], 277 mvm->fwrt.geo_profiles[tbl_idx - 1].bands[0].chains[1], 278 mvm->fwrt.geo_profiles[tbl_idx - 1].bands[0].max); 279 pos += scnprintf(buf + pos, bufsz - pos, 280 "5.2GHz:\n\tChain A offset: %u dBm\n\tChain B offset: %u dBm\n\tmax tx power: %u dBm\n", 281 mvm->fwrt.geo_profiles[tbl_idx - 1].bands[1].chains[0], 282 mvm->fwrt.geo_profiles[tbl_idx - 1].bands[1].chains[1], 283 mvm->fwrt.geo_profiles[tbl_idx - 1].bands[1].max); 284 } 285 mutex_unlock(&mvm->mutex); 286 287 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 288 } 289 290 static ssize_t iwl_dbgfs_wifi_6e_enable_read(struct file *file, 291 char __user *user_buf, 292 size_t count, loff_t *ppos) 293 { 294 struct iwl_mvm *mvm = file->private_data; 295 int err, pos; 296 char buf[12]; 297 u32 value; 298 299 err = iwl_bios_get_dsm(&mvm->fwrt, DSM_FUNC_ENABLE_6E, &value); 300 if (err) 301 return err; 302 303 pos = sprintf(buf, "0x%08x\n", value); 304 305 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 306 } 307 #endif 308 309 static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, 310 size_t count, loff_t *ppos) 311 { 312 struct iwl_mvm *mvm = file->private_data; 313 struct ieee80211_sta *sta; 314 char buf[400]; 315 int i, pos = 0, bufsz = sizeof(buf); 316 317 mutex_lock(&mvm->mutex); 318 319 for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) { 320 pos += scnprintf(buf + pos, bufsz - pos, "%.2d: ", i); 321 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i], 322 lockdep_is_held(&mvm->mutex)); 323 if (!sta) 324 pos += scnprintf(buf + pos, bufsz - pos, "N/A\n"); 325 else if (IS_ERR(sta)) 326 pos += scnprintf(buf + pos, bufsz - pos, "%ld\n", 327 PTR_ERR(sta)); 328 else 329 pos += scnprintf(buf + pos, bufsz - pos, "%pM\n", 330 sta->addr); 331 } 332 333 mutex_unlock(&mvm->mutex); 334 335 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 336 } 337 338 static ssize_t iwl_dbgfs_rs_data_read(struct ieee80211_link_sta *link_sta, 339 struct iwl_mvm_sta *mvmsta, 340 struct iwl_mvm *mvm, 341 struct iwl_mvm_link_sta *mvm_link_sta, 342 char __user *user_buf, 343 size_t count, loff_t *ppos) 344 { 345 struct iwl_lq_sta_rs_fw *lq_sta = &mvm_link_sta->lq_sta.rs_fw; 346 static const size_t bufsz = 2048; 347 char *buff; 348 int desc = 0; 349 ssize_t ret; 350 351 buff = kmalloc(bufsz, GFP_KERNEL); 352 if (!buff) 353 return -ENOMEM; 354 355 desc += scnprintf(buff + desc, bufsz - desc, "sta_id %d\n", 356 lq_sta->pers.sta_id); 357 desc += scnprintf(buff + desc, bufsz - desc, 358 "fixed rate 0x%X\n", 359 lq_sta->pers.dbg_fixed_rate); 360 desc += scnprintf(buff + desc, bufsz - desc, 361 "A-MPDU size limit %d\n", 362 lq_sta->pers.dbg_agg_frame_count_lim); 363 desc += scnprintf(buff + desc, bufsz - desc, 364 "valid_tx_ant %s%s\n", 365 (iwl_mvm_get_valid_tx_ant(mvm) & ANT_A) ? "ANT_A," : "", 366 (iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : ""); 367 desc += scnprintf(buff + desc, bufsz - desc, 368 "last tx rate=0x%X ", 369 lq_sta->last_rate_n_flags); 370 371 desc += rs_pretty_print_rate(buff + desc, bufsz - desc, 372 lq_sta->last_rate_n_flags); 373 if (desc < bufsz - 1) 374 buff[desc++] = '\n'; 375 376 ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); 377 kfree(buff); 378 return ret; 379 } 380 381 static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_link_sta *link_sta, 382 struct iwl_mvm_sta *mvmsta, 383 struct iwl_mvm *mvm, 384 struct iwl_mvm_link_sta *mvm_link_sta, 385 char *buf, size_t count, 386 loff_t *ppos) 387 { 388 int i; 389 u16 amsdu_len; 390 391 if (kstrtou16(buf, 0, &amsdu_len)) 392 return -EINVAL; 393 394 /* only change from debug set <-> debug unset */ 395 if (amsdu_len && mvm_link_sta->orig_amsdu_len) 396 return -EBUSY; 397 398 if (amsdu_len) { 399 mvm_link_sta->orig_amsdu_len = link_sta->agg.max_amsdu_len; 400 link_sta->agg.max_amsdu_len = amsdu_len; 401 for (i = 0; i < ARRAY_SIZE(link_sta->agg.max_tid_amsdu_len); i++) 402 link_sta->agg.max_tid_amsdu_len[i] = amsdu_len; 403 } else { 404 link_sta->agg.max_amsdu_len = mvm_link_sta->orig_amsdu_len; 405 mvm_link_sta->orig_amsdu_len = 0; 406 } 407 408 ieee80211_sta_recalc_aggregates(link_sta->sta); 409 410 return count; 411 } 412 413 static ssize_t iwl_dbgfs_amsdu_len_read(struct ieee80211_link_sta *link_sta, 414 struct iwl_mvm_sta *mvmsta, 415 struct iwl_mvm *mvm, 416 struct iwl_mvm_link_sta *mvm_link_sta, 417 char __user *user_buf, 418 size_t count, loff_t *ppos) 419 { 420 char buf[32]; 421 int pos; 422 423 pos = scnprintf(buf, sizeof(buf), "current %d ", 424 link_sta->agg.max_amsdu_len); 425 pos += scnprintf(buf + pos, sizeof(buf) - pos, "stored %d\n", 426 mvm_link_sta->orig_amsdu_len); 427 428 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 429 } 430 431 static ssize_t iwl_dbgfs_disable_power_off_read(struct file *file, 432 char __user *user_buf, 433 size_t count, loff_t *ppos) 434 { 435 struct iwl_mvm *mvm = file->private_data; 436 char buf[64]; 437 int bufsz = sizeof(buf); 438 int pos = 0; 439 440 pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d0=%d\n", 441 mvm->disable_power_off); 442 pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d3=%d\n", 443 mvm->disable_power_off_d3); 444 445 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 446 } 447 448 static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf, 449 size_t count, loff_t *ppos) 450 { 451 int ret, val; 452 453 if (!iwl_mvm_firmware_running(mvm)) 454 return -EIO; 455 456 if (!strncmp("disable_power_off_d0=", buf, 21)) { 457 if (sscanf(buf + 21, "%d", &val) != 1) 458 return -EINVAL; 459 mvm->disable_power_off = val; 460 } else if (!strncmp("disable_power_off_d3=", buf, 21)) { 461 if (sscanf(buf + 21, "%d", &val) != 1) 462 return -EINVAL; 463 mvm->disable_power_off_d3 = val; 464 } else { 465 return -EINVAL; 466 } 467 468 mutex_lock(&mvm->mutex); 469 ret = iwl_mvm_power_update_device(mvm); 470 mutex_unlock(&mvm->mutex); 471 472 return ret ?: count; 473 } 474 475 static ssize_t iwl_dbgfs_tas_get_status_read(struct file *file, 476 char __user *user_buf, 477 size_t count, loff_t *ppos) 478 { 479 struct iwl_mvm *mvm = file->private_data; 480 struct iwl_tas_status_resp *rsp = NULL; 481 static const size_t bufsz = 1024; 482 char *buff, *pos, *endpos; 483 const char * const tas_dis_reason[TAS_DISABLED_REASON_MAX] = { 484 [TAS_DISABLED_DUE_TO_BIOS] = 485 "Due To BIOS", 486 [TAS_DISABLED_DUE_TO_SAR_6DBM] = 487 "Due To SAR Limit Less Than 6 dBm", 488 [TAS_DISABLED_REASON_INVALID] = 489 "N/A", 490 [TAS_DISABLED_DUE_TO_TABLE_SOURCE_INVALID] = 491 "Due to table source invalid", 492 }; 493 const char * const tas_current_status[TAS_DYNA_STATUS_MAX] = { 494 [TAS_DYNA_INACTIVE] = "INACTIVE", 495 [TAS_DYNA_INACTIVE_MVM_MODE] = 496 "inactive due to mvm mode", 497 [TAS_DYNA_INACTIVE_TRIGGER_MODE] = 498 "inactive due to trigger mode", 499 [TAS_DYNA_INACTIVE_BLOCK_LISTED] = 500 "inactive due to block listed", 501 [TAS_DYNA_INACTIVE_UHB_NON_US] = 502 "inactive due to uhb non US", 503 [TAS_DYNA_ACTIVE] = "ACTIVE", 504 }; 505 struct iwl_host_cmd hcmd = { 506 .id = WIDE_ID(DEBUG_GROUP, GET_TAS_STATUS), 507 .flags = CMD_WANT_SKB, 508 .len = { 0, }, 509 .data = { NULL, }, 510 }; 511 int ret, i, tmp; 512 bool tas_enabled = false; 513 unsigned long dyn_status; 514 515 if (!iwl_mvm_firmware_running(mvm)) 516 return -ENODEV; 517 518 if (iwl_fw_lookup_notif_ver(mvm->fw, DEBUG_GROUP, GET_TAS_STATUS, 519 0) != 3) 520 return -EOPNOTSUPP; 521 522 mutex_lock(&mvm->mutex); 523 ret = iwl_mvm_send_cmd(mvm, &hcmd); 524 mutex_unlock(&mvm->mutex); 525 if (ret < 0) 526 return ret; 527 528 if (iwl_rx_packet_payload_len(hcmd.resp_pkt) != sizeof(*rsp)) { 529 iwl_free_resp(&hcmd); 530 return -EIO; 531 } 532 533 buff = kzalloc(bufsz, GFP_KERNEL); 534 if (!buff) { 535 iwl_free_resp(&hcmd); 536 return -ENOMEM; 537 } 538 pos = buff; 539 endpos = pos + bufsz; 540 541 rsp = (void *)hcmd.resp_pkt->data; 542 543 pos += scnprintf(pos, endpos - pos, "TAS Conclusion:\n"); 544 for (i = 0; i < min_t(int, rsp->in_dual_radio + 1, 545 ARRAY_SIZE(rsp->tas_status_mac)); i++) { 546 if (rsp->tas_status_mac[i].dynamic_status & 547 BIT(TAS_DYNA_ACTIVE)) { 548 pos += scnprintf(pos, endpos - pos, "\tON for "); 549 switch (rsp->tas_status_mac[i].band) { 550 case PHY_BAND_5: 551 pos += scnprintf(pos, endpos - pos, "HB\n"); 552 break; 553 case PHY_BAND_24: 554 pos += scnprintf(pos, endpos - pos, "LB\n"); 555 break; 556 case PHY_BAND_6: 557 pos += scnprintf(pos, endpos - pos, "UHB\n"); 558 break; 559 default: 560 pos += scnprintf(pos, endpos - pos, 561 "Unsupported band (%d)\n", 562 rsp->tas_status_mac[i].band); 563 goto out; 564 } 565 tas_enabled = true; 566 } 567 } 568 if (!tas_enabled) 569 pos += scnprintf(pos, endpos - pos, "\tOFF\n"); 570 571 pos += scnprintf(pos, endpos - pos, "TAS Report\n"); 572 pos += scnprintf(pos, endpos - pos, "TAS FW version: %d\n", 573 rsp->tas_fw_version); 574 pos += scnprintf(pos, endpos - pos, "Is UHB enabled for USA?: %s\n", 575 rsp->is_uhb_for_usa_enable ? "True" : "False"); 576 577 if (fw_has_capa(&mvm->fw->ucode_capa, 578 IWL_UCODE_TLV_CAPA_UHB_CANADA_TAS_SUPPORT)) 579 pos += scnprintf(pos, endpos - pos, 580 "Is UHB enabled for CANADA?: %s\n", 581 rsp->uhb_allowed_flags & 582 TAS_UHB_ALLOWED_CANADA ? "True" : "False"); 583 584 pos += scnprintf(pos, endpos - pos, "Current MCC: 0x%x\n", 585 le16_to_cpu(rsp->curr_mcc)); 586 587 pos += scnprintf(pos, endpos - pos, "Block list entries:"); 588 for (i = 0; i < IWL_WTAS_BLACK_LIST_MAX; i++) 589 pos += scnprintf(pos, endpos - pos, " 0x%x", 590 le16_to_cpu(rsp->block_list[i])); 591 592 pos += scnprintf(pos, endpos - pos, "\nOEM name: %s\n", 593 dmi_get_system_info(DMI_SYS_VENDOR) ?: "<unknown>"); 594 pos += scnprintf(pos, endpos - pos, "\tVendor In Approved List: %s\n", 595 iwl_is_tas_approved() ? "YES" : "NO"); 596 pos += scnprintf(pos, endpos - pos, 597 "\tDo TAS Support Dual Radio?: %s\n", 598 rsp->in_dual_radio ? "TRUE" : "FALSE"); 599 600 for (i = 0; i < min_t(int, rsp->in_dual_radio + 1, 601 ARRAY_SIZE(rsp->tas_status_mac)); i++) { 602 if (rsp->tas_status_mac[i].static_status == 0) { 603 pos += scnprintf(pos, endpos - pos, 604 "Static status: disabled\n"); 605 pos += scnprintf(pos, endpos - pos, 606 "Static disabled reason: %s (0)\n", 607 tas_dis_reason[0]); 608 goto out; 609 } 610 611 pos += scnprintf(pos, endpos - pos, "TAS status for "); 612 switch (rsp->tas_status_mac[i].band) { 613 case PHY_BAND_5: 614 pos += scnprintf(pos, endpos - pos, "High band\n"); 615 break; 616 case PHY_BAND_24: 617 pos += scnprintf(pos, endpos - pos, "Low band\n"); 618 break; 619 case PHY_BAND_6: 620 pos += scnprintf(pos, endpos - pos, 621 "Ultra high band\n"); 622 break; 623 default: 624 pos += scnprintf(pos, endpos - pos, 625 "Unsupported band (%d)\n", 626 rsp->tas_status_mac[i].band); 627 goto out; 628 } 629 pos += scnprintf(pos, endpos - pos, "Static status: %sabled\n", 630 rsp->tas_status_mac[i].static_status ? 631 "En" : "Dis"); 632 pos += scnprintf(pos, endpos - pos, 633 "\tStatic Disabled Reason: "); 634 if (rsp->tas_status_mac[i].static_dis_reason < TAS_DISABLED_REASON_MAX) 635 pos += scnprintf(pos, endpos - pos, "%s (%d)\n", 636 tas_dis_reason[rsp->tas_status_mac[i].static_dis_reason], 637 rsp->tas_status_mac[i].static_dis_reason); 638 else 639 pos += scnprintf(pos, endpos - pos, 640 "unsupported value (%d)\n", 641 rsp->tas_status_mac[i].static_dis_reason); 642 643 pos += scnprintf(pos, endpos - pos, "Dynamic status:\n"); 644 dyn_status = (rsp->tas_status_mac[i].dynamic_status); 645 for_each_set_bit(tmp, &dyn_status, TAS_DYNA_STATUS_MAX) { 646 pos += scnprintf(pos, endpos - pos, "\t%s (%d)\n", 647 tas_current_status[tmp], tmp); 648 } 649 650 pos += scnprintf(pos, endpos - pos, 651 "Is near disconnection?: %s\n", 652 rsp->tas_status_mac[i].near_disconnection ? 653 "True" : "False"); 654 tmp = le16_to_cpu(rsp->tas_status_mac[i].max_reg_pwr_limit); 655 pos += scnprintf(pos, endpos - pos, 656 "Max. regulatory pwr limit (dBm): %d.%03d\n", 657 tmp / 8, 125 * (tmp % 8)); 658 tmp = le16_to_cpu(rsp->tas_status_mac[i].sar_limit); 659 pos += scnprintf(pos, endpos - pos, 660 "SAR limit (dBm): %d.%03d\n", 661 tmp / 8, 125 * (tmp % 8)); 662 } 663 664 out: 665 ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff); 666 kfree(buff); 667 iwl_free_resp(&hcmd); 668 return ret; 669 } 670 671 static ssize_t iwl_dbgfs_phy_integration_ver_read(struct file *file, 672 char __user *user_buf, 673 size_t count, loff_t *ppos) 674 { 675 struct iwl_mvm *mvm = file->private_data; 676 char *buf; 677 size_t bufsz; 678 int pos; 679 ssize_t ret; 680 681 bufsz = mvm->fw->phy_integration_ver_len + 2; 682 buf = kmalloc(bufsz, GFP_KERNEL); 683 if (!buf) 684 return -ENOMEM; 685 686 pos = scnprintf(buf, bufsz, "%.*s\n", mvm->fw->phy_integration_ver_len, 687 mvm->fw->phy_integration_ver); 688 689 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 690 691 kfree(buf); 692 return ret; 693 } 694 695 #define PRINT_STATS_LE32(_struct, _memb) \ 696 pos += scnprintf(buf + pos, bufsz - pos, \ 697 fmt_table, #_memb, \ 698 le32_to_cpu(_struct->_memb)) 699 700 static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file, 701 char __user *user_buf, size_t count, 702 loff_t *ppos) 703 { 704 struct iwl_mvm *mvm = file->private_data; 705 static const char *fmt_table = "\t%-30s %10u\n"; 706 static const char *fmt_header = "%-32s\n"; 707 int pos = 0; 708 char *buf; 709 int ret; 710 size_t bufsz; 711 u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, 712 WIDE_ID(SYSTEM_GROUP, 713 SYSTEM_STATISTICS_CMD), 714 IWL_FW_CMD_VER_UNKNOWN); 715 716 if (cmd_ver != IWL_FW_CMD_VER_UNKNOWN) 717 return -EOPNOTSUPP; 718 719 if (iwl_mvm_has_new_rx_stats_api(mvm)) 720 bufsz = ((sizeof(struct mvm_statistics_rx) / 721 sizeof(__le32)) * 43) + (4 * 33) + 1; 722 else 723 /* 43 = size of each data line; 33 = size of each header */ 724 bufsz = ((sizeof(struct mvm_statistics_rx_v3) / 725 sizeof(__le32)) * 43) + (4 * 33) + 1; 726 727 buf = kzalloc(bufsz, GFP_KERNEL); 728 if (!buf) 729 return -ENOMEM; 730 731 mutex_lock(&mvm->mutex); 732 733 if (iwl_mvm_firmware_running(mvm)) 734 iwl_mvm_request_statistics(mvm, false); 735 736 pos += scnprintf(buf + pos, bufsz - pos, fmt_header, 737 "Statistics_Rx - OFDM"); 738 if (!iwl_mvm_has_new_rx_stats_api(mvm)) { 739 struct mvm_statistics_rx_phy_v2 *ofdm = &mvm->rx_stats_v3.ofdm; 740 741 PRINT_STATS_LE32(ofdm, ina_cnt); 742 PRINT_STATS_LE32(ofdm, fina_cnt); 743 PRINT_STATS_LE32(ofdm, plcp_err); 744 PRINT_STATS_LE32(ofdm, crc32_err); 745 PRINT_STATS_LE32(ofdm, overrun_err); 746 PRINT_STATS_LE32(ofdm, early_overrun_err); 747 PRINT_STATS_LE32(ofdm, crc32_good); 748 PRINT_STATS_LE32(ofdm, false_alarm_cnt); 749 PRINT_STATS_LE32(ofdm, fina_sync_err_cnt); 750 PRINT_STATS_LE32(ofdm, sfd_timeout); 751 PRINT_STATS_LE32(ofdm, fina_timeout); 752 PRINT_STATS_LE32(ofdm, unresponded_rts); 753 PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun); 754 PRINT_STATS_LE32(ofdm, sent_ack_cnt); 755 PRINT_STATS_LE32(ofdm, sent_cts_cnt); 756 PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt); 757 PRINT_STATS_LE32(ofdm, dsp_self_kill); 758 PRINT_STATS_LE32(ofdm, mh_format_err); 759 PRINT_STATS_LE32(ofdm, re_acq_main_rssi_sum); 760 PRINT_STATS_LE32(ofdm, reserved); 761 } else { 762 struct mvm_statistics_rx_phy *ofdm = &mvm->rx_stats.ofdm; 763 764 PRINT_STATS_LE32(ofdm, unresponded_rts); 765 PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun); 766 PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt); 767 PRINT_STATS_LE32(ofdm, dsp_self_kill); 768 PRINT_STATS_LE32(ofdm, reserved); 769 } 770 771 pos += scnprintf(buf + pos, bufsz - pos, fmt_header, 772 "Statistics_Rx - CCK"); 773 if (!iwl_mvm_has_new_rx_stats_api(mvm)) { 774 struct mvm_statistics_rx_phy_v2 *cck = &mvm->rx_stats_v3.cck; 775 776 PRINT_STATS_LE32(cck, ina_cnt); 777 PRINT_STATS_LE32(cck, fina_cnt); 778 PRINT_STATS_LE32(cck, plcp_err); 779 PRINT_STATS_LE32(cck, crc32_err); 780 PRINT_STATS_LE32(cck, overrun_err); 781 PRINT_STATS_LE32(cck, early_overrun_err); 782 PRINT_STATS_LE32(cck, crc32_good); 783 PRINT_STATS_LE32(cck, false_alarm_cnt); 784 PRINT_STATS_LE32(cck, fina_sync_err_cnt); 785 PRINT_STATS_LE32(cck, sfd_timeout); 786 PRINT_STATS_LE32(cck, fina_timeout); 787 PRINT_STATS_LE32(cck, unresponded_rts); 788 PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun); 789 PRINT_STATS_LE32(cck, sent_ack_cnt); 790 PRINT_STATS_LE32(cck, sent_cts_cnt); 791 PRINT_STATS_LE32(cck, sent_ba_rsp_cnt); 792 PRINT_STATS_LE32(cck, dsp_self_kill); 793 PRINT_STATS_LE32(cck, mh_format_err); 794 PRINT_STATS_LE32(cck, re_acq_main_rssi_sum); 795 PRINT_STATS_LE32(cck, reserved); 796 } else { 797 struct mvm_statistics_rx_phy *cck = &mvm->rx_stats.cck; 798 799 PRINT_STATS_LE32(cck, unresponded_rts); 800 PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun); 801 PRINT_STATS_LE32(cck, sent_ba_rsp_cnt); 802 PRINT_STATS_LE32(cck, dsp_self_kill); 803 PRINT_STATS_LE32(cck, reserved); 804 } 805 806 pos += scnprintf(buf + pos, bufsz - pos, fmt_header, 807 "Statistics_Rx - GENERAL"); 808 if (!iwl_mvm_has_new_rx_stats_api(mvm)) { 809 struct mvm_statistics_rx_non_phy_v3 *general = 810 &mvm->rx_stats_v3.general; 811 812 PRINT_STATS_LE32(general, bogus_cts); 813 PRINT_STATS_LE32(general, bogus_ack); 814 PRINT_STATS_LE32(general, non_bssid_frames); 815 PRINT_STATS_LE32(general, filtered_frames); 816 PRINT_STATS_LE32(general, non_channel_beacons); 817 PRINT_STATS_LE32(general, channel_beacons); 818 PRINT_STATS_LE32(general, num_missed_bcon); 819 PRINT_STATS_LE32(general, adc_rx_saturation_time); 820 PRINT_STATS_LE32(general, ina_detection_search_time); 821 PRINT_STATS_LE32(general, beacon_silence_rssi_a); 822 PRINT_STATS_LE32(general, beacon_silence_rssi_b); 823 PRINT_STATS_LE32(general, beacon_silence_rssi_c); 824 PRINT_STATS_LE32(general, interference_data_flag); 825 PRINT_STATS_LE32(general, channel_load); 826 PRINT_STATS_LE32(general, dsp_false_alarms); 827 PRINT_STATS_LE32(general, beacon_rssi_a); 828 PRINT_STATS_LE32(general, beacon_rssi_b); 829 PRINT_STATS_LE32(general, beacon_rssi_c); 830 PRINT_STATS_LE32(general, beacon_energy_a); 831 PRINT_STATS_LE32(general, beacon_energy_b); 832 PRINT_STATS_LE32(general, beacon_energy_c); 833 PRINT_STATS_LE32(general, num_bt_kills); 834 PRINT_STATS_LE32(general, mac_id); 835 PRINT_STATS_LE32(general, directed_data_mpdu); 836 } else { 837 struct mvm_statistics_rx_non_phy *general = 838 &mvm->rx_stats.general; 839 840 PRINT_STATS_LE32(general, bogus_cts); 841 PRINT_STATS_LE32(general, bogus_ack); 842 PRINT_STATS_LE32(general, non_channel_beacons); 843 PRINT_STATS_LE32(general, channel_beacons); 844 PRINT_STATS_LE32(general, num_missed_bcon); 845 PRINT_STATS_LE32(general, adc_rx_saturation_time); 846 PRINT_STATS_LE32(general, ina_detection_search_time); 847 PRINT_STATS_LE32(general, beacon_silence_rssi_a); 848 PRINT_STATS_LE32(general, beacon_silence_rssi_b); 849 PRINT_STATS_LE32(general, beacon_silence_rssi_c); 850 PRINT_STATS_LE32(general, interference_data_flag); 851 PRINT_STATS_LE32(general, channel_load); 852 PRINT_STATS_LE32(general, beacon_rssi_a); 853 PRINT_STATS_LE32(general, beacon_rssi_b); 854 PRINT_STATS_LE32(general, beacon_rssi_c); 855 PRINT_STATS_LE32(general, beacon_energy_a); 856 PRINT_STATS_LE32(general, beacon_energy_b); 857 PRINT_STATS_LE32(general, beacon_energy_c); 858 PRINT_STATS_LE32(general, num_bt_kills); 859 PRINT_STATS_LE32(general, mac_id); 860 } 861 862 pos += scnprintf(buf + pos, bufsz - pos, fmt_header, 863 "Statistics_Rx - HT"); 864 if (!iwl_mvm_has_new_rx_stats_api(mvm)) { 865 struct mvm_statistics_rx_ht_phy_v1 *ht = 866 &mvm->rx_stats_v3.ofdm_ht; 867 868 PRINT_STATS_LE32(ht, plcp_err); 869 PRINT_STATS_LE32(ht, overrun_err); 870 PRINT_STATS_LE32(ht, early_overrun_err); 871 PRINT_STATS_LE32(ht, crc32_good); 872 PRINT_STATS_LE32(ht, crc32_err); 873 PRINT_STATS_LE32(ht, mh_format_err); 874 PRINT_STATS_LE32(ht, agg_crc32_good); 875 PRINT_STATS_LE32(ht, agg_mpdu_cnt); 876 PRINT_STATS_LE32(ht, agg_cnt); 877 PRINT_STATS_LE32(ht, unsupport_mcs); 878 } else { 879 struct mvm_statistics_rx_ht_phy *ht = 880 &mvm->rx_stats.ofdm_ht; 881 882 PRINT_STATS_LE32(ht, mh_format_err); 883 PRINT_STATS_LE32(ht, agg_mpdu_cnt); 884 PRINT_STATS_LE32(ht, agg_cnt); 885 PRINT_STATS_LE32(ht, unsupport_mcs); 886 } 887 888 mutex_unlock(&mvm->mutex); 889 890 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 891 kfree(buf); 892 893 return ret; 894 } 895 #undef PRINT_STAT_LE32 896 897 static ssize_t iwl_dbgfs_fw_system_stats_read(struct file *file, 898 char __user *user_buf, 899 size_t count, loff_t *ppos) 900 { 901 char *buff, *pos, *endpos; 902 int ret; 903 size_t bufsz; 904 int i; 905 struct iwl_mvm_vif *mvmvif; 906 struct ieee80211_vif *vif; 907 struct iwl_mvm *mvm = file->private_data; 908 u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, 909 WIDE_ID(SYSTEM_GROUP, 910 SYSTEM_STATISTICS_CMD), 911 IWL_FW_CMD_VER_UNKNOWN); 912 913 /* in case of a wrong cmd version, allocate buffer only for error msg */ 914 bufsz = (cmd_ver == 1) ? 4096 : 64; 915 916 buff = kzalloc(bufsz, GFP_KERNEL); 917 if (!buff) 918 return -ENOMEM; 919 920 pos = buff; 921 endpos = pos + bufsz; 922 923 if (cmd_ver != 1) { 924 pos += scnprintf(pos, endpos - pos, 925 "System stats not supported:%d\n", cmd_ver); 926 goto send_out; 927 } 928 929 mutex_lock(&mvm->mutex); 930 if (iwl_mvm_firmware_running(mvm)) 931 iwl_mvm_request_statistics(mvm, false); 932 933 for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) { 934 vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, false); 935 if (!vif) 936 continue; 937 938 if (vif->type == NL80211_IFTYPE_STATION) 939 break; 940 } 941 942 if (i == NUM_MAC_INDEX_DRIVER || !vif) { 943 pos += scnprintf(pos, endpos - pos, "vif is NULL\n"); 944 goto release_send_out; 945 } 946 947 mvmvif = iwl_mvm_vif_from_mac80211(vif); 948 if (!mvmvif) { 949 pos += scnprintf(pos, endpos - pos, "mvmvif is NULL\n"); 950 goto release_send_out; 951 } 952 953 for_each_mvm_vif_valid_link(mvmvif, i) { 954 struct iwl_mvm_vif_link_info *link_info = mvmvif->link[i]; 955 956 pos += scnprintf(pos, endpos - pos, 957 "link_id %d", i); 958 pos += scnprintf(pos, endpos - pos, 959 " num_beacons %d", 960 link_info->beacon_stats.num_beacons); 961 pos += scnprintf(pos, endpos - pos, 962 " accu_num_beacons %d", 963 link_info->beacon_stats.accu_num_beacons); 964 pos += scnprintf(pos, endpos - pos, 965 " avg_signal %d\n", 966 link_info->beacon_stats.avg_signal); 967 } 968 969 pos += scnprintf(pos, endpos - pos, 970 "radio_stats.rx_time %lld\n", 971 mvm->radio_stats.rx_time); 972 pos += scnprintf(pos, endpos - pos, 973 "radio_stats.tx_time %lld\n", 974 mvm->radio_stats.tx_time); 975 pos += scnprintf(pos, endpos - pos, 976 "accu_radio_stats.rx_time %lld\n", 977 mvm->accu_radio_stats.rx_time); 978 pos += scnprintf(pos, endpos - pos, 979 "accu_radio_stats.tx_time %lld\n", 980 mvm->accu_radio_stats.tx_time); 981 982 release_send_out: 983 mutex_unlock(&mvm->mutex); 984 985 send_out: 986 ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff); 987 kfree(buff); 988 989 return ret; 990 } 991 992 static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm, 993 char __user *user_buf, size_t count, 994 loff_t *ppos, 995 struct iwl_mvm_frame_stats *stats) 996 { 997 char *buff, *pos, *endpos; 998 int idx, i; 999 int ret; 1000 static const size_t bufsz = 1024; 1001 1002 buff = kmalloc(bufsz, GFP_KERNEL); 1003 if (!buff) 1004 return -ENOMEM; 1005 1006 spin_lock_bh(&mvm->drv_stats_lock); 1007 1008 pos = buff; 1009 endpos = pos + bufsz; 1010 1011 pos += scnprintf(pos, endpos - pos, 1012 "Legacy/HT/VHT\t:\t%d/%d/%d\n", 1013 stats->legacy_frames, 1014 stats->ht_frames, 1015 stats->vht_frames); 1016 pos += scnprintf(pos, endpos - pos, "20/40/80\t:\t%d/%d/%d\n", 1017 stats->bw_20_frames, 1018 stats->bw_40_frames, 1019 stats->bw_80_frames); 1020 pos += scnprintf(pos, endpos - pos, "NGI/SGI\t\t:\t%d/%d\n", 1021 stats->ngi_frames, 1022 stats->sgi_frames); 1023 pos += scnprintf(pos, endpos - pos, "SISO/MIMO2\t:\t%d/%d\n", 1024 stats->siso_frames, 1025 stats->mimo2_frames); 1026 pos += scnprintf(pos, endpos - pos, "FAIL/SCSS\t:\t%d/%d\n", 1027 stats->fail_frames, 1028 stats->success_frames); 1029 pos += scnprintf(pos, endpos - pos, "MPDUs agg\t:\t%d\n", 1030 stats->agg_frames); 1031 pos += scnprintf(pos, endpos - pos, "A-MPDUs\t\t:\t%d\n", 1032 stats->ampdu_count); 1033 pos += scnprintf(pos, endpos - pos, "Avg MPDUs/A-MPDU:\t%d\n", 1034 stats->ampdu_count > 0 ? 1035 (stats->agg_frames / stats->ampdu_count) : 0); 1036 1037 pos += scnprintf(pos, endpos - pos, "Last Rates\n"); 1038 1039 idx = stats->last_frame_idx - 1; 1040 for (i = 0; i < ARRAY_SIZE(stats->last_rates); i++) { 1041 idx = (idx + 1) % ARRAY_SIZE(stats->last_rates); 1042 if (stats->last_rates[idx] == 0) 1043 continue; 1044 pos += scnprintf(pos, endpos - pos, "Rate[%d]: ", 1045 (int)(ARRAY_SIZE(stats->last_rates) - i)); 1046 pos += rs_pretty_print_rate_v1(pos, endpos - pos, 1047 stats->last_rates[idx]); 1048 if (pos < endpos - 1) 1049 *pos++ = '\n'; 1050 } 1051 spin_unlock_bh(&mvm->drv_stats_lock); 1052 1053 ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff); 1054 kfree(buff); 1055 1056 return ret; 1057 } 1058 1059 static ssize_t iwl_dbgfs_drv_rx_stats_read(struct file *file, 1060 char __user *user_buf, size_t count, 1061 loff_t *ppos) 1062 { 1063 struct iwl_mvm *mvm = file->private_data; 1064 1065 return iwl_dbgfs_frame_stats_read(mvm, user_buf, count, ppos, 1066 &mvm->drv_rx_stats); 1067 } 1068 1069 static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf, 1070 size_t count, loff_t *ppos) 1071 { 1072 int __maybe_unused ret; 1073 1074 if (!iwl_mvm_firmware_running(mvm)) 1075 return -EIO; 1076 1077 mutex_lock(&mvm->mutex); 1078 1079 if (count == 6 && !strcmp(buf, "nolog\n")) { 1080 set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status); 1081 mvm->trans->suppress_cmd_error_once = true; 1082 } 1083 1084 /* take the return value to make compiler happy - it will fail anyway */ 1085 ret = iwl_mvm_send_cmd_pdu(mvm, 1086 WIDE_ID(LONG_GROUP, REPLY_ERROR), 1087 0, 0, NULL); 1088 1089 mutex_unlock(&mvm->mutex); 1090 1091 return count; 1092 } 1093 1094 static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf, 1095 size_t count, loff_t *ppos) 1096 { 1097 if (!iwl_mvm_firmware_running(mvm)) 1098 return -EIO; 1099 1100 IWL_ERR(mvm, "Triggering an NMI from debugfs\n"); 1101 1102 if (count == 6 && !strcmp(buf, "nolog\n")) 1103 set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status); 1104 1105 iwl_trans_force_nmi(mvm->trans); 1106 1107 return count; 1108 } 1109 1110 static ssize_t 1111 iwl_dbgfs_scan_ant_rxchain_read(struct file *file, 1112 char __user *user_buf, 1113 size_t count, loff_t *ppos) 1114 { 1115 struct iwl_mvm *mvm = file->private_data; 1116 int pos = 0; 1117 char buf[32]; 1118 const size_t bufsz = sizeof(buf); 1119 1120 /* print which antennas were set for the scan command by the user */ 1121 pos += scnprintf(buf + pos, bufsz - pos, "Antennas for scan: "); 1122 if (mvm->scan_rx_ant & ANT_A) 1123 pos += scnprintf(buf + pos, bufsz - pos, "A"); 1124 if (mvm->scan_rx_ant & ANT_B) 1125 pos += scnprintf(buf + pos, bufsz - pos, "B"); 1126 pos += scnprintf(buf + pos, bufsz - pos, " (%x)\n", mvm->scan_rx_ant); 1127 1128 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1129 } 1130 1131 static ssize_t 1132 iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf, 1133 size_t count, loff_t *ppos) 1134 { 1135 u8 scan_rx_ant; 1136 1137 if (!iwl_mvm_firmware_running(mvm)) 1138 return -EIO; 1139 1140 if (sscanf(buf, "%hhx", &scan_rx_ant) != 1) 1141 return -EINVAL; 1142 if (scan_rx_ant > ANT_ABC) 1143 return -EINVAL; 1144 if (scan_rx_ant & ~(iwl_mvm_get_valid_rx_ant(mvm))) 1145 return -EINVAL; 1146 1147 if (mvm->scan_rx_ant != scan_rx_ant) { 1148 mvm->scan_rx_ant = scan_rx_ant; 1149 if (fw_has_capa(&mvm->fw->ucode_capa, 1150 IWL_UCODE_TLV_CAPA_UMAC_SCAN)) 1151 iwl_mvm_config_scan(mvm); 1152 } 1153 1154 return count; 1155 } 1156 1157 static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm, 1158 char *buf, size_t count, 1159 loff_t *ppos) 1160 { 1161 struct iwl_op_mode *opmode = container_of((void *)mvm, 1162 struct iwl_op_mode, 1163 op_mode_specific); 1164 struct iwl_rx_cmd_buffer rxb = { 1165 ._rx_page_order = 0, 1166 .truesize = 0, /* not used */ 1167 ._offset = 0, 1168 }; 1169 struct iwl_rx_packet *pkt; 1170 int bin_len = count / 2; 1171 int ret = -EINVAL; 1172 1173 if (!iwl_mvm_firmware_running(mvm)) 1174 return -EIO; 1175 1176 /* supporting only MQ RX */ 1177 if (!mvm->trans->mac_cfg->mq_rx_supported) 1178 return -EOPNOTSUPP; 1179 1180 rxb._page = alloc_pages(GFP_ATOMIC, 0); 1181 if (!rxb._page) 1182 return -ENOMEM; 1183 pkt = rxb_addr(&rxb); 1184 1185 ret = hex2bin(page_address(rxb._page), buf, bin_len); 1186 if (ret) 1187 goto out; 1188 1189 /* avoid invalid memory access and malformed packet */ 1190 if (bin_len < sizeof(*pkt) || 1191 bin_len != sizeof(*pkt) + iwl_rx_packet_payload_len(pkt)) 1192 goto out; 1193 1194 local_bh_disable(); 1195 iwl_mvm_rx_mq(opmode, NULL, &rxb); 1196 local_bh_enable(); 1197 ret = 0; 1198 1199 out: 1200 iwl_free_rxb(&rxb); 1201 1202 return ret ?: count; 1203 } 1204 1205 static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len) 1206 { 1207 struct ieee80211_vif *vif; 1208 struct iwl_mvm_vif *mvmvif; 1209 struct sk_buff *beacon; 1210 struct ieee80211_tx_info *info; 1211 struct iwl_mac_beacon_cmd beacon_cmd = {}; 1212 unsigned int link_id; 1213 u8 rate; 1214 int i; 1215 1216 len /= 2; 1217 1218 /* Element len should be represented by u8 */ 1219 if (len >= U8_MAX) 1220 return -EINVAL; 1221 1222 if (!iwl_mvm_firmware_running(mvm)) 1223 return -EIO; 1224 1225 if (!iwl_mvm_has_new_tx_api(mvm) && 1226 !fw_has_api(&mvm->fw->ucode_capa, 1227 IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE)) 1228 return -EINVAL; 1229 1230 mutex_lock(&mvm->mutex); 1231 1232 for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) { 1233 vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, false); 1234 if (!vif) 1235 continue; 1236 1237 if (vif->type == NL80211_IFTYPE_AP) 1238 break; 1239 } 1240 1241 if (i == NUM_MAC_INDEX_DRIVER || !vif) 1242 goto out_err; 1243 1244 mvm->hw->extra_beacon_tailroom = len; 1245 1246 beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL, 0); 1247 if (!beacon) 1248 goto out_err; 1249 1250 if (len && hex2bin(skb_put_zero(beacon, len), bin, len)) { 1251 dev_kfree_skb(beacon); 1252 goto out_err; 1253 } 1254 1255 mvm->beacon_inject_active = true; 1256 1257 mvmvif = iwl_mvm_vif_from_mac80211(vif); 1258 info = IEEE80211_SKB_CB(beacon); 1259 rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif); 1260 1261 for_each_mvm_vif_valid_link(mvmvif, link_id) { 1262 beacon_cmd.flags = 1263 cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, 1264 rate)); 1265 beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len); 1266 if (iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD, 0) > 12) 1267 beacon_cmd.link_id = 1268 cpu_to_le32(mvmvif->link[link_id]->fw_link_id); 1269 else 1270 beacon_cmd.link_id = cpu_to_le32((u32)mvmvif->id); 1271 1272 iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx, 1273 &beacon_cmd.tim_size, 1274 beacon->data, beacon->len); 1275 1276 if (iwl_fw_lookup_cmd_ver(mvm->fw, 1277 BEACON_TEMPLATE_CMD, 0) >= 14) { 1278 u32 offset = iwl_find_ie_offset(beacon->data, 1279 WLAN_EID_S1G_TWT, 1280 beacon->len); 1281 1282 beacon_cmd.btwt_offset = cpu_to_le32(offset); 1283 } 1284 1285 iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd, 1286 sizeof(beacon_cmd)); 1287 } 1288 mutex_unlock(&mvm->mutex); 1289 1290 dev_kfree_skb(beacon); 1291 1292 return 0; 1293 1294 out_err: 1295 mutex_unlock(&mvm->mutex); 1296 return -EINVAL; 1297 } 1298 1299 static ssize_t iwl_dbgfs_inject_beacon_ie_write(struct iwl_mvm *mvm, 1300 char *buf, size_t count, 1301 loff_t *ppos) 1302 { 1303 int ret = _iwl_dbgfs_inject_beacon_ie(mvm, buf, count); 1304 1305 mvm->hw->extra_beacon_tailroom = 0; 1306 return ret ?: count; 1307 } 1308 1309 static ssize_t iwl_dbgfs_inject_beacon_ie_restore_write(struct iwl_mvm *mvm, 1310 char *buf, 1311 size_t count, 1312 loff_t *ppos) 1313 { 1314 int ret = _iwl_dbgfs_inject_beacon_ie(mvm, NULL, 0); 1315 1316 mvm->hw->extra_beacon_tailroom = 0; 1317 mvm->beacon_inject_active = false; 1318 return ret ?: count; 1319 } 1320 1321 static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file, 1322 char __user *user_buf, 1323 size_t count, loff_t *ppos) 1324 { 1325 struct iwl_mvm *mvm = file->private_data; 1326 int conf; 1327 char buf[8]; 1328 const size_t bufsz = sizeof(buf); 1329 int pos = 0; 1330 1331 mutex_lock(&mvm->mutex); 1332 conf = mvm->fwrt.dump.conf; 1333 mutex_unlock(&mvm->mutex); 1334 1335 pos += scnprintf(buf + pos, bufsz - pos, "%d\n", conf); 1336 1337 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1338 } 1339 1340 static ssize_t iwl_dbgfs_fw_dbg_conf_write(struct iwl_mvm *mvm, 1341 char *buf, size_t count, 1342 loff_t *ppos) 1343 { 1344 unsigned int conf_id; 1345 int ret; 1346 1347 if (!iwl_mvm_firmware_running(mvm)) 1348 return -EIO; 1349 1350 ret = kstrtouint(buf, 0, &conf_id); 1351 if (ret) 1352 return ret; 1353 1354 if (WARN_ON(conf_id >= FW_DBG_CONF_MAX)) 1355 return -EINVAL; 1356 1357 mutex_lock(&mvm->mutex); 1358 ret = iwl_fw_start_dbg_conf(&mvm->fwrt, conf_id); 1359 mutex_unlock(&mvm->mutex); 1360 1361 return ret ?: count; 1362 } 1363 1364 static ssize_t iwl_dbgfs_fw_dbg_clear_write(struct iwl_mvm *mvm, 1365 char *buf, size_t count, 1366 loff_t *ppos) 1367 { 1368 if (mvm->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_9000) 1369 return -EOPNOTSUPP; 1370 1371 /* 1372 * If the firmware is not running, silently succeed since there is 1373 * no data to clear. 1374 */ 1375 if (!iwl_mvm_firmware_running(mvm)) 1376 return count; 1377 1378 mutex_lock(&mvm->mutex); 1379 iwl_fw_dbg_clear_monitor_buf(&mvm->fwrt); 1380 mutex_unlock(&mvm->mutex); 1381 1382 return count; 1383 } 1384 1385 static ssize_t iwl_dbgfs_dbg_time_point_write(struct iwl_mvm *mvm, 1386 char *buf, size_t count, 1387 loff_t *ppos) 1388 { 1389 u32 timepoint; 1390 1391 if (kstrtou32(buf, 0, &timepoint)) 1392 return -EINVAL; 1393 1394 if (timepoint == IWL_FW_INI_TIME_POINT_INVALID || 1395 timepoint >= IWL_FW_INI_TIME_POINT_NUM) 1396 return -EINVAL; 1397 1398 iwl_dbg_tlv_time_point(&mvm->fwrt, timepoint, NULL); 1399 1400 return count; 1401 } 1402 1403 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \ 1404 _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm) 1405 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ 1406 _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm) 1407 #define MVM_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do { \ 1408 debugfs_create_file(alias, mode, parent, mvm, \ 1409 &iwl_dbgfs_##name##_ops); \ 1410 } while (0) 1411 #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \ 1412 MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode) 1413 1414 static ssize_t 1415 _iwl_dbgfs_link_sta_wrap_write(ssize_t (*real)(struct ieee80211_link_sta *, 1416 struct iwl_mvm_sta *, 1417 struct iwl_mvm *, 1418 struct iwl_mvm_link_sta *, 1419 char *, 1420 size_t, loff_t *), 1421 struct file *file, 1422 char *buf, size_t buf_size, loff_t *ppos) 1423 { 1424 struct ieee80211_link_sta *link_sta = file->private_data; 1425 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(link_sta->sta); 1426 struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(mvmsta->vif)->mvm; 1427 struct iwl_mvm_link_sta *mvm_link_sta; 1428 ssize_t ret; 1429 1430 mutex_lock(&mvm->mutex); 1431 1432 mvm_link_sta = rcu_dereference_protected(mvmsta->link[link_sta->link_id], 1433 lockdep_is_held(&mvm->mutex)); 1434 if (WARN_ON(!mvm_link_sta)) { 1435 mutex_unlock(&mvm->mutex); 1436 return -ENODEV; 1437 } 1438 1439 ret = real(link_sta, mvmsta, mvm, mvm_link_sta, buf, buf_size, ppos); 1440 1441 mutex_unlock(&mvm->mutex); 1442 1443 return ret; 1444 } 1445 1446 static ssize_t 1447 _iwl_dbgfs_link_sta_wrap_read(ssize_t (*real)(struct ieee80211_link_sta *, 1448 struct iwl_mvm_sta *, 1449 struct iwl_mvm *, 1450 struct iwl_mvm_link_sta *, 1451 char __user *, 1452 size_t, loff_t *), 1453 struct file *file, 1454 char __user *user_buf, size_t count, loff_t *ppos) 1455 { 1456 struct ieee80211_link_sta *link_sta = file->private_data; 1457 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(link_sta->sta); 1458 struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(mvmsta->vif)->mvm; 1459 struct iwl_mvm_link_sta *mvm_link_sta; 1460 ssize_t ret; 1461 1462 mutex_lock(&mvm->mutex); 1463 1464 mvm_link_sta = rcu_dereference_protected(mvmsta->link[link_sta->link_id], 1465 lockdep_is_held(&mvm->mutex)); 1466 if (WARN_ON(!mvm_link_sta)) { 1467 mutex_unlock(&mvm->mutex); 1468 return -ENODEV; 1469 } 1470 1471 ret = real(link_sta, mvmsta, mvm, mvm_link_sta, user_buf, count, ppos); 1472 1473 mutex_unlock(&mvm->mutex); 1474 1475 return ret; 1476 } 1477 1478 #define MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, buflen) \ 1479 static ssize_t _iwl_dbgfs_link_sta_##name##_write(struct file *file, \ 1480 const char __user *user_buf, \ 1481 size_t count, loff_t *ppos) \ 1482 { \ 1483 char buf[buflen] = {}; \ 1484 size_t buf_size = min(count, sizeof(buf) - 1); \ 1485 \ 1486 if (copy_from_user(buf, user_buf, buf_size)) \ 1487 return -EFAULT; \ 1488 \ 1489 return _iwl_dbgfs_link_sta_wrap_write(iwl_dbgfs_##name##_write, \ 1490 file, \ 1491 buf, buf_size, ppos); \ 1492 } \ 1493 1494 #define MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name) \ 1495 static ssize_t _iwl_dbgfs_link_sta_##name##_read(struct file *file, \ 1496 char __user *user_buf, \ 1497 size_t count, loff_t *ppos) \ 1498 { \ 1499 return _iwl_dbgfs_link_sta_wrap_read(iwl_dbgfs_##name##_read, \ 1500 file, \ 1501 user_buf, count, ppos); \ 1502 } \ 1503 1504 #define MVM_DEBUGFS_WRITE_LINK_STA_FILE_OPS(name, bufsz) \ 1505 MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, bufsz) \ 1506 static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = { \ 1507 .write = _iwl_dbgfs_link_sta_##name##_write, \ 1508 .open = simple_open, \ 1509 .llseek = generic_file_llseek, \ 1510 } 1511 1512 #define MVM_DEBUGFS_READ_LINK_STA_FILE_OPS(name) \ 1513 MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name) \ 1514 static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = { \ 1515 .read = _iwl_dbgfs_link_sta_##name##_read, \ 1516 .open = simple_open, \ 1517 .llseek = generic_file_llseek, \ 1518 } 1519 1520 #define MVM_DEBUGFS_READ_WRITE_LINK_STA_FILE_OPS(name, bufsz) \ 1521 MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name) \ 1522 MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, bufsz) \ 1523 static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = { \ 1524 .read = _iwl_dbgfs_link_sta_##name##_read, \ 1525 .write = _iwl_dbgfs_link_sta_##name##_write, \ 1526 .open = simple_open, \ 1527 .llseek = generic_file_llseek, \ 1528 } 1529 1530 #define MVM_DEBUGFS_ADD_LINK_STA_FILE_ALIAS(alias, name, parent, mode) \ 1531 debugfs_create_file(alias, mode, parent, link_sta, \ 1532 &iwl_dbgfs_link_sta_##name##_ops) 1533 #define MVM_DEBUGFS_ADD_LINK_STA_FILE(name, parent, mode) \ 1534 MVM_DEBUGFS_ADD_LINK_STA_FILE_ALIAS(#name, name, parent, mode) 1535 1536 static ssize_t 1537 iwl_dbgfs_prph_reg_read(struct file *file, 1538 char __user *user_buf, 1539 size_t count, loff_t *ppos) 1540 { 1541 struct iwl_mvm *mvm = file->private_data; 1542 int pos = 0; 1543 char buf[32]; 1544 const size_t bufsz = sizeof(buf); 1545 1546 if (!mvm->dbgfs_prph_reg_addr) 1547 return -EINVAL; 1548 1549 pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n", 1550 mvm->dbgfs_prph_reg_addr, 1551 iwl_trans_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr)); 1552 1553 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1554 } 1555 1556 static ssize_t 1557 iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf, 1558 size_t count, loff_t *ppos) 1559 { 1560 u8 args; 1561 u32 value; 1562 1563 args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value); 1564 /* if we only want to set the reg address - nothing more to do */ 1565 if (args == 1) 1566 goto out; 1567 1568 /* otherwise, make sure we have both address and value */ 1569 if (args != 2) 1570 return -EINVAL; 1571 1572 iwl_trans_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value); 1573 1574 out: 1575 return count; 1576 } 1577 1578 static ssize_t 1579 iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf, 1580 size_t count, loff_t *ppos) 1581 { 1582 int ret; 1583 1584 if (!iwl_mvm_firmware_running(mvm)) 1585 return -EIO; 1586 1587 mutex_lock(&mvm->mutex); 1588 ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL); 1589 mutex_unlock(&mvm->mutex); 1590 1591 return ret ?: count; 1592 } 1593 1594 struct iwl_mvm_sniffer_apply { 1595 struct iwl_mvm *mvm; 1596 u8 *bssid; 1597 u16 aid; 1598 }; 1599 1600 static bool iwl_mvm_sniffer_apply(struct iwl_notif_wait_data *notif_data, 1601 struct iwl_rx_packet *pkt, void *data) 1602 { 1603 struct iwl_mvm_sniffer_apply *apply = data; 1604 1605 apply->mvm->cur_aid = cpu_to_le16(apply->aid); 1606 memcpy(apply->mvm->cur_bssid, apply->bssid, 1607 sizeof(apply->mvm->cur_bssid)); 1608 1609 return true; 1610 } 1611 1612 static ssize_t 1613 iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf, 1614 size_t count, loff_t *ppos) 1615 { 1616 struct iwl_notification_wait wait; 1617 struct iwl_he_monitor_cmd he_mon_cmd = {}; 1618 struct iwl_mvm_sniffer_apply apply = { 1619 .mvm = mvm, 1620 }; 1621 u16 wait_cmds[] = { 1622 WIDE_ID(DATA_PATH_GROUP, HE_AIR_SNIFFER_CONFIG_CMD), 1623 }; 1624 u32 aid; 1625 int ret; 1626 1627 if (!iwl_mvm_firmware_running(mvm)) 1628 return -EIO; 1629 1630 ret = sscanf(buf, "%x %2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx", &aid, 1631 &he_mon_cmd.bssid[0], &he_mon_cmd.bssid[1], 1632 &he_mon_cmd.bssid[2], &he_mon_cmd.bssid[3], 1633 &he_mon_cmd.bssid[4], &he_mon_cmd.bssid[5]); 1634 if (ret != 7) 1635 return -EINVAL; 1636 1637 he_mon_cmd.aid = cpu_to_le16(aid); 1638 1639 apply.aid = aid; 1640 apply.bssid = (void *)he_mon_cmd.bssid; 1641 1642 mutex_lock(&mvm->mutex); 1643 1644 /* 1645 * Use the notification waiter to get our function triggered 1646 * in sequence with other RX. This ensures that frames we get 1647 * on the RX queue _before_ the new configuration is applied 1648 * still have mvm->cur_aid pointing to the old AID, and that 1649 * frames on the RX queue _after_ the firmware processed the 1650 * new configuration (and sent the response, synchronously) 1651 * get mvm->cur_aid correctly set to the new AID. 1652 */ 1653 iwl_init_notification_wait(&mvm->notif_wait, &wait, 1654 wait_cmds, ARRAY_SIZE(wait_cmds), 1655 iwl_mvm_sniffer_apply, &apply); 1656 1657 ret = iwl_mvm_send_cmd_pdu(mvm, 1658 WIDE_ID(DATA_PATH_GROUP, HE_AIR_SNIFFER_CONFIG_CMD), 1659 0, 1660 sizeof(he_mon_cmd), &he_mon_cmd); 1661 1662 /* no need to really wait, we already did anyway */ 1663 iwl_remove_notification(&mvm->notif_wait, &wait); 1664 1665 mutex_unlock(&mvm->mutex); 1666 1667 return ret ?: count; 1668 } 1669 1670 static ssize_t 1671 iwl_dbgfs_he_sniffer_params_read(struct file *file, char __user *user_buf, 1672 size_t count, loff_t *ppos) 1673 { 1674 struct iwl_mvm *mvm = file->private_data; 1675 u8 buf[32]; 1676 int len; 1677 1678 len = scnprintf(buf, sizeof(buf), 1679 "%d %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", 1680 le16_to_cpu(mvm->cur_aid), mvm->cur_bssid[0], 1681 mvm->cur_bssid[1], mvm->cur_bssid[2], mvm->cur_bssid[3], 1682 mvm->cur_bssid[4], mvm->cur_bssid[5]); 1683 1684 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1685 } 1686 1687 static ssize_t 1688 iwl_dbgfs_uapsd_noagg_bssids_read(struct file *file, char __user *user_buf, 1689 size_t count, loff_t *ppos) 1690 { 1691 struct iwl_mvm *mvm = file->private_data; 1692 u8 buf[IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM * ETH_ALEN * 3 + 1]; 1693 unsigned int pos = 0; 1694 size_t bufsz = sizeof(buf); 1695 int i; 1696 1697 mutex_lock(&mvm->mutex); 1698 1699 for (i = 0; i < IWL_MVM_UAPSD_NOAGG_LIST_LEN; i++) 1700 pos += scnprintf(buf + pos, bufsz - pos, "%pM\n", 1701 mvm->uapsd_noagg_bssids[i].addr); 1702 1703 mutex_unlock(&mvm->mutex); 1704 1705 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1706 } 1707 1708 static ssize_t 1709 iwl_dbgfs_ltr_config_write(struct iwl_mvm *mvm, 1710 char *buf, size_t count, loff_t *ppos) 1711 { 1712 int ret; 1713 struct iwl_ltr_config_cmd ltr_config = {0}; 1714 1715 if (!iwl_mvm_firmware_running(mvm)) 1716 return -EIO; 1717 1718 if (sscanf(buf, "%x,%x,%x,%x,%x,%x,%x", 1719 <r_config.flags, 1720 <r_config.static_long, 1721 <r_config.static_short, 1722 <r_config.ltr_cfg_values[0], 1723 <r_config.ltr_cfg_values[1], 1724 <r_config.ltr_cfg_values[2], 1725 <r_config.ltr_cfg_values[3]) != 7) { 1726 return -EINVAL; 1727 } 1728 1729 mutex_lock(&mvm->mutex); 1730 ret = iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, sizeof(ltr_config), 1731 <r_config); 1732 mutex_unlock(&mvm->mutex); 1733 1734 if (ret) 1735 IWL_ERR(mvm, "failed to send ltr configuration cmd\n"); 1736 1737 return ret ?: count; 1738 } 1739 1740 static ssize_t iwl_dbgfs_rfi_freq_table_write(struct iwl_mvm *mvm, char *buf, 1741 size_t count, loff_t *ppos) 1742 { 1743 int ret = 0; 1744 u16 op_id; 1745 1746 if (kstrtou16(buf, 10, &op_id)) 1747 return -EINVAL; 1748 1749 /* value zero triggers re-sending the default table to the device */ 1750 if (!op_id) { 1751 mutex_lock(&mvm->mutex); 1752 ret = iwl_rfi_send_config_cmd(mvm, NULL); 1753 mutex_unlock(&mvm->mutex); 1754 } else { 1755 ret = -EOPNOTSUPP; /* in the future a new table will be added */ 1756 } 1757 1758 return ret ?: count; 1759 } 1760 1761 /* The size computation is as follows: 1762 * each number needs at most 3 characters, number of rows is the size of 1763 * the table; So, need 5 chars for the "freq: " part and each tuple afterwards 1764 * needs 6 characters for numbers and 5 for the punctuation around. 1765 */ 1766 #define IWL_RFI_BUF_SIZE (IWL_RFI_LUT_INSTALLED_SIZE *\ 1767 (5 + IWL_RFI_LUT_ENTRY_CHANNELS_NUM * (6 + 5))) 1768 1769 static ssize_t iwl_dbgfs_rfi_freq_table_read(struct file *file, 1770 char __user *user_buf, 1771 size_t count, loff_t *ppos) 1772 { 1773 struct iwl_mvm *mvm = file->private_data; 1774 struct iwl_rfi_freq_table_resp_cmd *resp; 1775 u32 status; 1776 char buf[IWL_RFI_BUF_SIZE]; 1777 int i, j, pos = 0; 1778 1779 resp = iwl_rfi_get_freq_table(mvm); 1780 if (IS_ERR(resp)) 1781 return PTR_ERR(resp); 1782 1783 status = le32_to_cpu(resp->status); 1784 if (status != RFI_FREQ_TABLE_OK) { 1785 scnprintf(buf, IWL_RFI_BUF_SIZE, "status = %d\n", status); 1786 goto out; 1787 } 1788 1789 for (i = 0; i < ARRAY_SIZE(resp->table); i++) { 1790 pos += scnprintf(buf + pos, IWL_RFI_BUF_SIZE - pos, "%d: ", 1791 resp->table[i].freq); 1792 1793 for (j = 0; j < ARRAY_SIZE(resp->table[i].channels); j++) 1794 pos += scnprintf(buf + pos, IWL_RFI_BUF_SIZE - pos, 1795 "(%d, %d) ", 1796 resp->table[i].channels[j], 1797 resp->table[i].bands[j]); 1798 pos += scnprintf(buf + pos, IWL_RFI_BUF_SIZE - pos, "\n"); 1799 } 1800 1801 out: 1802 kfree(resp); 1803 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1804 } 1805 1806 MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64); 1807 1808 /* Device wide debugfs entries */ 1809 MVM_DEBUGFS_READ_FILE_OPS(ctdp_budget); 1810 MVM_DEBUGFS_WRITE_FILE_OPS(stop_ctdp, 8); 1811 MVM_DEBUGFS_WRITE_FILE_OPS(start_ctdp, 8); 1812 MVM_DEBUGFS_WRITE_FILE_OPS(force_ctkill, 8); 1813 MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16); 1814 MVM_DEBUGFS_WRITE_FILE_OPS(send_echo_cmd, 8); 1815 MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64); 1816 MVM_DEBUGFS_READ_FILE_OPS(nic_temp); 1817 MVM_DEBUGFS_READ_FILE_OPS(stations); 1818 MVM_DEBUGFS_READ_LINK_STA_FILE_OPS(rs_data); 1819 MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64); 1820 MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats); 1821 MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats); 1822 MVM_DEBUGFS_READ_FILE_OPS(fw_system_stats); 1823 MVM_DEBUGFS_READ_FILE_OPS(phy_integration_ver); 1824 MVM_DEBUGFS_READ_FILE_OPS(tas_get_status); 1825 MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10); 1826 MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10); 1827 MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); 1828 MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8); 1829 MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_clear, 64); 1830 MVM_DEBUGFS_WRITE_FILE_OPS(dbg_time_point, 64); 1831 MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512); 1832 MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie, 512); 1833 MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie_restore, 512); 1834 1835 MVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids); 1836 1837 #ifdef CONFIG_ACPI 1838 MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile); 1839 MVM_DEBUGFS_READ_FILE_OPS(wifi_6e_enable); 1840 #endif 1841 1842 MVM_DEBUGFS_READ_WRITE_LINK_STA_FILE_OPS(amsdu_len, 16); 1843 1844 MVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32); 1845 1846 MVM_DEBUGFS_WRITE_FILE_OPS(ltr_config, 512); 1847 MVM_DEBUGFS_READ_WRITE_FILE_OPS(rfi_freq_table, 16); 1848 1849 static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf, 1850 size_t count, loff_t *ppos) 1851 { 1852 struct iwl_mvm *mvm = file->private_data; 1853 struct iwl_dbg_mem_access_cmd cmd = {}; 1854 struct iwl_dbg_mem_access_rsp *rsp; 1855 struct iwl_host_cmd hcmd = { 1856 .flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL, 1857 .data = { &cmd, }, 1858 .len = { sizeof(cmd) }, 1859 }; 1860 size_t delta; 1861 ssize_t ret, len; 1862 1863 if (!iwl_mvm_firmware_running(mvm)) 1864 return -EIO; 1865 1866 hcmd.id = WIDE_ID(DEBUG_GROUP, *ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR); 1867 cmd.op = cpu_to_le32(DEBUG_MEM_OP_READ); 1868 1869 /* Take care of alignment of both the position and the length */ 1870 delta = *ppos & 0x3; 1871 cmd.addr = cpu_to_le32(*ppos - delta); 1872 cmd.len = cpu_to_le32(min(ALIGN(count + delta, 4) / 4, 1873 (size_t)DEBUG_MEM_MAX_SIZE_DWORDS)); 1874 1875 mutex_lock(&mvm->mutex); 1876 ret = iwl_mvm_send_cmd(mvm, &hcmd); 1877 mutex_unlock(&mvm->mutex); 1878 1879 if (ret < 0) 1880 return ret; 1881 1882 if (iwl_rx_packet_payload_len(hcmd.resp_pkt) < sizeof(*rsp)) { 1883 ret = -EIO; 1884 goto out; 1885 } 1886 1887 rsp = (void *)hcmd.resp_pkt->data; 1888 if (le32_to_cpu(rsp->status) != DEBUG_MEM_STATUS_SUCCESS) { 1889 ret = -ENXIO; 1890 goto out; 1891 } 1892 1893 len = min((size_t)le32_to_cpu(rsp->len) << 2, 1894 iwl_rx_packet_payload_len(hcmd.resp_pkt) - sizeof(*rsp)); 1895 len = min(len - delta, count); 1896 if (len < 0) { 1897 ret = -EFAULT; 1898 goto out; 1899 } 1900 1901 ret = len - copy_to_user(user_buf, (u8 *)rsp->data + delta, len); 1902 *ppos += ret; 1903 1904 out: 1905 iwl_free_resp(&hcmd); 1906 return ret; 1907 } 1908 1909 static ssize_t iwl_dbgfs_mem_write(struct file *file, 1910 const char __user *user_buf, size_t count, 1911 loff_t *ppos) 1912 { 1913 struct iwl_mvm *mvm = file->private_data; 1914 struct iwl_dbg_mem_access_cmd *cmd; 1915 struct iwl_dbg_mem_access_rsp *rsp; 1916 struct iwl_host_cmd hcmd = {}; 1917 size_t cmd_size; 1918 size_t data_size; 1919 u32 op, len; 1920 ssize_t ret; 1921 1922 if (!iwl_mvm_firmware_running(mvm)) 1923 return -EIO; 1924 1925 hcmd.id = WIDE_ID(DEBUG_GROUP, *ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR); 1926 1927 if (*ppos & 0x3 || count < 4) { 1928 op = DEBUG_MEM_OP_WRITE_BYTES; 1929 len = min(count, (size_t)(4 - (*ppos & 0x3))); 1930 data_size = len; 1931 } else { 1932 op = DEBUG_MEM_OP_WRITE; 1933 len = min(count >> 2, (size_t)DEBUG_MEM_MAX_SIZE_DWORDS); 1934 data_size = len << 2; 1935 } 1936 1937 cmd_size = sizeof(*cmd) + ALIGN(data_size, 4); 1938 cmd = kzalloc(cmd_size, GFP_KERNEL); 1939 if (!cmd) 1940 return -ENOMEM; 1941 1942 cmd->op = cpu_to_le32(op); 1943 cmd->len = cpu_to_le32(len); 1944 cmd->addr = cpu_to_le32(*ppos); 1945 if (copy_from_user((void *)cmd->data, user_buf, data_size)) { 1946 kfree(cmd); 1947 return -EFAULT; 1948 } 1949 1950 hcmd.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL, 1951 hcmd.data[0] = (void *)cmd; 1952 hcmd.len[0] = cmd_size; 1953 1954 mutex_lock(&mvm->mutex); 1955 ret = iwl_mvm_send_cmd(mvm, &hcmd); 1956 mutex_unlock(&mvm->mutex); 1957 1958 kfree(cmd); 1959 1960 if (ret < 0) 1961 return ret; 1962 1963 if (iwl_rx_packet_payload_len(hcmd.resp_pkt) < sizeof(*rsp)) { 1964 ret = -EIO; 1965 goto out; 1966 } 1967 1968 rsp = (void *)hcmd.resp_pkt->data; 1969 if (rsp->status != DEBUG_MEM_STATUS_SUCCESS) { 1970 ret = -ENXIO; 1971 goto out; 1972 } 1973 1974 ret = data_size; 1975 *ppos += ret; 1976 1977 out: 1978 iwl_free_resp(&hcmd); 1979 return ret; 1980 } 1981 1982 static const struct file_operations iwl_dbgfs_mem_ops = { 1983 .read = iwl_dbgfs_mem_read, 1984 .write = iwl_dbgfs_mem_write, 1985 .open = simple_open, 1986 .llseek = default_llseek, 1987 }; 1988 1989 void iwl_mvm_link_sta_add_debugfs(struct ieee80211_hw *hw, 1990 struct ieee80211_vif *vif, 1991 struct ieee80211_link_sta *link_sta, 1992 struct dentry *dir) 1993 { 1994 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1995 1996 if (iwl_mvm_has_tlc_offload(mvm)) { 1997 MVM_DEBUGFS_ADD_LINK_STA_FILE(rs_data, dir, 0400); 1998 } 1999 2000 MVM_DEBUGFS_ADD_LINK_STA_FILE(amsdu_len, dir, 0600); 2001 } 2002 2003 void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm) 2004 { 2005 struct dentry *bcast_dir __maybe_unused; 2006 2007 spin_lock_init(&mvm->drv_stats_lock); 2008 2009 MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, 0200); 2010 MVM_DEBUGFS_ADD_FILE(set_nic_temperature, mvm->debugfs_dir, 0600); 2011 MVM_DEBUGFS_ADD_FILE(nic_temp, mvm->debugfs_dir, 0400); 2012 MVM_DEBUGFS_ADD_FILE(ctdp_budget, mvm->debugfs_dir, 0400); 2013 MVM_DEBUGFS_ADD_FILE(stop_ctdp, mvm->debugfs_dir, 0200); 2014 MVM_DEBUGFS_ADD_FILE(start_ctdp, mvm->debugfs_dir, 0200); 2015 MVM_DEBUGFS_ADD_FILE(force_ctkill, mvm->debugfs_dir, 0200); 2016 MVM_DEBUGFS_ADD_FILE(stations, mvm->debugfs_dir, 0400); 2017 MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, 0600); 2018 MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, 0400); 2019 MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, 0400); 2020 MVM_DEBUGFS_ADD_FILE(fw_system_stats, mvm->debugfs_dir, 0400); 2021 MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, 0200); 2022 MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, 0200); 2023 MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, 0600); 2024 MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, 0600); 2025 MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, 0600); 2026 MVM_DEBUGFS_ADD_FILE(fw_dbg_clear, mvm->debugfs_dir, 0200); 2027 MVM_DEBUGFS_ADD_FILE(dbg_time_point, mvm->debugfs_dir, 0200); 2028 MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200); 2029 MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200); 2030 MVM_DEBUGFS_ADD_FILE(inject_beacon_ie, mvm->debugfs_dir, 0200); 2031 MVM_DEBUGFS_ADD_FILE(inject_beacon_ie_restore, mvm->debugfs_dir, 0200); 2032 MVM_DEBUGFS_ADD_FILE(rfi_freq_table, mvm->debugfs_dir, 0600); 2033 2034 if (mvm->fw->phy_integration_ver) 2035 MVM_DEBUGFS_ADD_FILE(phy_integration_ver, mvm->debugfs_dir, 0400); 2036 MVM_DEBUGFS_ADD_FILE(tas_get_status, mvm->debugfs_dir, 0400); 2037 #ifdef CONFIG_ACPI 2038 MVM_DEBUGFS_ADD_FILE(sar_geo_profile, mvm->debugfs_dir, 0400); 2039 MVM_DEBUGFS_ADD_FILE(wifi_6e_enable, mvm->debugfs_dir, 0400); 2040 #endif 2041 MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600); 2042 2043 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_LTR_GEN2)) 2044 MVM_DEBUGFS_ADD_FILE(ltr_config, mvm->debugfs_dir, 0200); 2045 2046 debugfs_create_bool("enable_scan_iteration_notif", 0600, 2047 mvm->debugfs_dir, &mvm->scan_iter_notif_enabled); 2048 debugfs_create_bool("drop_bcn_ap_mode", 0600, mvm->debugfs_dir, 2049 &mvm->drop_bcn_ap_mode); 2050 2051 MVM_DEBUGFS_ADD_FILE(uapsd_noagg_bssids, mvm->debugfs_dir, S_IRUSR); 2052 2053 #ifdef CONFIG_PM_SLEEP 2054 debugfs_create_bool("d3_wake_sysassert", 0600, mvm->debugfs_dir, 2055 &mvm->d3_wake_sysassert); 2056 debugfs_create_u32("last_netdetect_scans", 0400, mvm->debugfs_dir, 2057 &mvm->last_netdetect_scans); 2058 #endif 2059 2060 debugfs_create_u8("ps_disabled", 0400, mvm->debugfs_dir, 2061 &mvm->ps_disabled); 2062 debugfs_create_blob("nvm_hw", 0400, mvm->debugfs_dir, 2063 &mvm->nvm_hw_blob); 2064 debugfs_create_blob("nvm_sw", 0400, mvm->debugfs_dir, 2065 &mvm->nvm_sw_blob); 2066 debugfs_create_blob("nvm_calib", 0400, mvm->debugfs_dir, 2067 &mvm->nvm_calib_blob); 2068 debugfs_create_blob("nvm_prod", 0400, mvm->debugfs_dir, 2069 &mvm->nvm_prod_blob); 2070 debugfs_create_blob("nvm_phy_sku", 0400, mvm->debugfs_dir, 2071 &mvm->nvm_phy_sku_blob); 2072 debugfs_create_blob("nvm_reg", S_IRUSR, 2073 mvm->debugfs_dir, &mvm->nvm_reg_blob); 2074 2075 debugfs_create_file("mem", 0600, mvm->debugfs_dir, mvm, 2076 &iwl_dbgfs_mem_ops); 2077 2078 debugfs_create_bool("rx_ts_ptp", 0600, mvm->debugfs_dir, 2079 &mvm->rx_ts_ptp); 2080 2081 /* 2082 * Create a symlink with mac80211. It will be removed when mac80211 2083 * exists (before the opmode exists which removes the target.) 2084 */ 2085 if (!IS_ERR(mvm->debugfs_dir)) { 2086 char buf[100]; 2087 2088 snprintf(buf, 100, "../../%pd2", mvm->debugfs_dir->d_parent); 2089 debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir, 2090 buf); 2091 } 2092 } 2093