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) 2012 - 2014 Intel Corporation. All rights reserved. 9 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH 10 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of version 2 of the GNU General Public License as 14 * published by the Free Software Foundation. 15 * 16 * This program is distributed in the hope that it will be useful, but 17 * WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * General Public License for more details. 20 * 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 * The full GNU General Public License is included in this distribution 27 * in the file called COPYING. 28 * 29 * Contact Information: 30 * Intel Linux Wireless <linuxwifi@intel.com> 31 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 32 * 33 * BSD LICENSE 34 * 35 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. 36 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH 37 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH 38 * All rights reserved. 39 * 40 * Redistribution and use in source and binary forms, with or without 41 * modification, are permitted provided that the following conditions 42 * are met: 43 * 44 * * Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * * Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in 48 * the documentation and/or other materials provided with the 49 * distribution. 50 * * Neither the name Intel Corporation nor the names of its 51 * contributors may be used to endorse or promote products derived 52 * from this software without specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 55 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 56 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 57 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 58 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 59 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 60 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 61 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 62 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 63 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 64 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 65 * 66 *****************************************************************************/ 67 #include <linux/vmalloc.h> 68 #include <linux/ieee80211.h> 69 #include <linux/netdevice.h> 70 71 #include "mvm.h" 72 #include "sta.h" 73 #include "iwl-io.h" 74 #include "debugfs.h" 75 #include "fw/error-dump.h" 76 77 static ssize_t iwl_dbgfs_ctdp_budget_read(struct file *file, 78 char __user *user_buf, 79 size_t count, loff_t *ppos) 80 { 81 struct iwl_mvm *mvm = file->private_data; 82 char buf[16]; 83 int pos, budget; 84 85 if (!iwl_mvm_firmware_running(mvm) || 86 mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR) 87 return -EIO; 88 89 mutex_lock(&mvm->mutex); 90 budget = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_REPORT, 0); 91 mutex_unlock(&mvm->mutex); 92 93 if (budget < 0) 94 return budget; 95 96 pos = scnprintf(buf, sizeof(buf), "%d\n", budget); 97 98 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 99 } 100 101 static ssize_t iwl_dbgfs_stop_ctdp_write(struct iwl_mvm *mvm, char *buf, 102 size_t count, loff_t *ppos) 103 { 104 int ret; 105 106 if (!iwl_mvm_firmware_running(mvm) || 107 mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR) 108 return -EIO; 109 110 mutex_lock(&mvm->mutex); 111 ret = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_STOP, 0); 112 mutex_unlock(&mvm->mutex); 113 114 return ret ?: count; 115 } 116 117 static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf, 118 size_t count, loff_t *ppos) 119 { 120 int ret; 121 u32 flush_arg; 122 123 if (!iwl_mvm_firmware_running(mvm) || 124 mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR) 125 return -EIO; 126 127 if (kstrtou32(buf, 0, &flush_arg)) 128 return -EINVAL; 129 130 if (iwl_mvm_has_new_tx_api(mvm)) { 131 IWL_DEBUG_TX_QUEUES(mvm, 132 "FLUSHING all tids queues on sta_id = %d\n", 133 flush_arg); 134 mutex_lock(&mvm->mutex); 135 ret = iwl_mvm_flush_sta_tids(mvm, flush_arg, 0xFF, 0) ? : count; 136 mutex_unlock(&mvm->mutex); 137 return ret; 138 } 139 140 IWL_DEBUG_TX_QUEUES(mvm, "FLUSHING queues mask to flush = 0x%x\n", 141 flush_arg); 142 143 mutex_lock(&mvm->mutex); 144 ret = iwl_mvm_flush_tx_path(mvm, flush_arg, 0) ? : count; 145 mutex_unlock(&mvm->mutex); 146 147 return ret; 148 } 149 150 static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf, 151 size_t count, loff_t *ppos) 152 { 153 struct iwl_mvm_sta *mvmsta; 154 int sta_id, drain, ret; 155 156 if (!iwl_mvm_firmware_running(mvm) || 157 mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR) 158 return -EIO; 159 160 if (sscanf(buf, "%d %d", &sta_id, &drain) != 2) 161 return -EINVAL; 162 if (sta_id < 0 || sta_id >= IWL_MVM_STATION_COUNT) 163 return -EINVAL; 164 if (drain < 0 || drain > 1) 165 return -EINVAL; 166 167 mutex_lock(&mvm->mutex); 168 169 mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id); 170 171 if (!mvmsta) 172 ret = -ENOENT; 173 else 174 ret = iwl_mvm_drain_sta(mvm, mvmsta, drain) ? : count; 175 176 mutex_unlock(&mvm->mutex); 177 178 return ret; 179 } 180 181 static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, 182 size_t count, loff_t *ppos) 183 { 184 struct iwl_mvm *mvm = file->private_data; 185 const struct fw_img *img; 186 unsigned int ofs, len; 187 size_t ret; 188 u8 *ptr; 189 190 if (!iwl_mvm_firmware_running(mvm)) 191 return -EINVAL; 192 193 /* default is to dump the entire data segment */ 194 img = &mvm->fw->img[mvm->fwrt.cur_fw_img]; 195 ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; 196 len = img->sec[IWL_UCODE_SECTION_DATA].len; 197 198 if (mvm->dbgfs_sram_len) { 199 ofs = mvm->dbgfs_sram_offset; 200 len = mvm->dbgfs_sram_len; 201 } 202 203 ptr = kzalloc(len, GFP_KERNEL); 204 if (!ptr) 205 return -ENOMEM; 206 207 iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len); 208 209 ret = simple_read_from_buffer(user_buf, count, ppos, ptr, len); 210 211 kfree(ptr); 212 213 return ret; 214 } 215 216 static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf, 217 size_t count, loff_t *ppos) 218 { 219 const struct fw_img *img; 220 u32 offset, len; 221 u32 img_offset, img_len; 222 223 if (!iwl_mvm_firmware_running(mvm)) 224 return -EINVAL; 225 226 img = &mvm->fw->img[mvm->fwrt.cur_fw_img]; 227 img_offset = img->sec[IWL_UCODE_SECTION_DATA].offset; 228 img_len = img->sec[IWL_UCODE_SECTION_DATA].len; 229 230 if (sscanf(buf, "%x,%x", &offset, &len) == 2) { 231 if ((offset & 0x3) || (len & 0x3)) 232 return -EINVAL; 233 234 if (offset + len > img_offset + img_len) 235 return -EINVAL; 236 237 mvm->dbgfs_sram_offset = offset; 238 mvm->dbgfs_sram_len = len; 239 } else { 240 mvm->dbgfs_sram_offset = 0; 241 mvm->dbgfs_sram_len = 0; 242 } 243 244 return count; 245 } 246 247 static ssize_t iwl_dbgfs_set_nic_temperature_read(struct file *file, 248 char __user *user_buf, 249 size_t count, loff_t *ppos) 250 { 251 struct iwl_mvm *mvm = file->private_data; 252 char buf[16]; 253 int pos; 254 255 if (!mvm->temperature_test) 256 pos = scnprintf(buf , sizeof(buf), "disabled\n"); 257 else 258 pos = scnprintf(buf , sizeof(buf), "%d\n", mvm->temperature); 259 260 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 261 } 262 263 /* 264 * Set NIC Temperature 265 * Cause the driver to ignore the actual NIC temperature reported by the FW 266 * Enable: any value between IWL_MVM_DEBUG_SET_TEMPERATURE_MIN - 267 * IWL_MVM_DEBUG_SET_TEMPERATURE_MAX 268 * Disable: IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE 269 */ 270 static ssize_t iwl_dbgfs_set_nic_temperature_write(struct iwl_mvm *mvm, 271 char *buf, size_t count, 272 loff_t *ppos) 273 { 274 int temperature; 275 276 if (!iwl_mvm_firmware_running(mvm) && !mvm->temperature_test) 277 return -EIO; 278 279 if (kstrtoint(buf, 10, &temperature)) 280 return -EINVAL; 281 /* not a legal temperature */ 282 if ((temperature > IWL_MVM_DEBUG_SET_TEMPERATURE_MAX && 283 temperature != IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) || 284 temperature < IWL_MVM_DEBUG_SET_TEMPERATURE_MIN) 285 return -EINVAL; 286 287 mutex_lock(&mvm->mutex); 288 if (temperature == IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) { 289 if (!mvm->temperature_test) 290 goto out; 291 292 mvm->temperature_test = false; 293 /* Since we can't read the temp while awake, just set 294 * it to zero until we get the next RX stats from the 295 * firmware. 296 */ 297 mvm->temperature = 0; 298 } else { 299 mvm->temperature_test = true; 300 mvm->temperature = temperature; 301 } 302 IWL_DEBUG_TEMP(mvm, "%sabling debug set temperature (temp = %d)\n", 303 mvm->temperature_test ? "En" : "Dis" , 304 mvm->temperature); 305 /* handle the temperature change */ 306 iwl_mvm_tt_handler(mvm); 307 308 out: 309 mutex_unlock(&mvm->mutex); 310 311 return count; 312 } 313 314 static ssize_t iwl_dbgfs_nic_temp_read(struct file *file, 315 char __user *user_buf, 316 size_t count, loff_t *ppos) 317 { 318 struct iwl_mvm *mvm = file->private_data; 319 char buf[16]; 320 int pos, ret; 321 s32 temp; 322 323 if (!iwl_mvm_firmware_running(mvm)) 324 return -EIO; 325 326 mutex_lock(&mvm->mutex); 327 ret = iwl_mvm_get_temp(mvm, &temp); 328 mutex_unlock(&mvm->mutex); 329 330 if (ret) 331 return -EIO; 332 333 pos = scnprintf(buf , sizeof(buf), "%d\n", temp); 334 335 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 336 } 337 338 #ifdef CONFIG_ACPI 339 static ssize_t iwl_dbgfs_sar_geo_profile_read(struct file *file, 340 char __user *user_buf, 341 size_t count, loff_t *ppos) 342 { 343 struct iwl_mvm *mvm = file->private_data; 344 char buf[256]; 345 int pos = 0; 346 int bufsz = sizeof(buf); 347 int tbl_idx; 348 u8 *value; 349 350 if (!iwl_mvm_firmware_running(mvm)) 351 return -EIO; 352 353 mutex_lock(&mvm->mutex); 354 tbl_idx = iwl_mvm_get_sar_geo_profile(mvm); 355 if (tbl_idx < 0) { 356 mutex_unlock(&mvm->mutex); 357 return tbl_idx; 358 } 359 360 if (!tbl_idx) { 361 pos = scnprintf(buf, bufsz, 362 "SAR geographic profile disabled\n"); 363 } else { 364 value = &mvm->geo_profiles[tbl_idx - 1].values[0]; 365 366 pos += scnprintf(buf + pos, bufsz - pos, 367 "Use geographic profile %d\n", tbl_idx); 368 pos += scnprintf(buf + pos, bufsz - pos, 369 "2.4GHz:\n\tChain A offset: %hhd dBm\n\tChain B offset: %hhd dBm\n\tmax tx power: %hhd dBm\n", 370 value[1], value[2], value[0]); 371 pos += scnprintf(buf + pos, bufsz - pos, 372 "5.2GHz:\n\tChain A offset: %hhd dBm\n\tChain B offset: %hhd dBm\n\tmax tx power: %hhd dBm\n", 373 value[4], value[5], value[3]); 374 } 375 mutex_unlock(&mvm->mutex); 376 377 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 378 } 379 #endif 380 381 static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, 382 size_t count, loff_t *ppos) 383 { 384 struct iwl_mvm *mvm = file->private_data; 385 struct ieee80211_sta *sta; 386 char buf[400]; 387 int i, pos = 0, bufsz = sizeof(buf); 388 389 mutex_lock(&mvm->mutex); 390 391 for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) { 392 pos += scnprintf(buf + pos, bufsz - pos, "%.2d: ", i); 393 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i], 394 lockdep_is_held(&mvm->mutex)); 395 if (!sta) 396 pos += scnprintf(buf + pos, bufsz - pos, "N/A\n"); 397 else if (IS_ERR(sta)) 398 pos += scnprintf(buf + pos, bufsz - pos, "%ld\n", 399 PTR_ERR(sta)); 400 else 401 pos += scnprintf(buf + pos, bufsz - pos, "%pM\n", 402 sta->addr); 403 } 404 405 mutex_unlock(&mvm->mutex); 406 407 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 408 } 409 410 static ssize_t iwl_dbgfs_disable_power_off_read(struct file *file, 411 char __user *user_buf, 412 size_t count, loff_t *ppos) 413 { 414 struct iwl_mvm *mvm = file->private_data; 415 char buf[64]; 416 int bufsz = sizeof(buf); 417 int pos = 0; 418 419 pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d0=%d\n", 420 mvm->disable_power_off); 421 pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d3=%d\n", 422 mvm->disable_power_off_d3); 423 424 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 425 } 426 427 static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf, 428 size_t count, loff_t *ppos) 429 { 430 int ret, val; 431 432 if (!iwl_mvm_firmware_running(mvm)) 433 return -EIO; 434 435 if (!strncmp("disable_power_off_d0=", buf, 21)) { 436 if (sscanf(buf + 21, "%d", &val) != 1) 437 return -EINVAL; 438 mvm->disable_power_off = val; 439 } else if (!strncmp("disable_power_off_d3=", buf, 21)) { 440 if (sscanf(buf + 21, "%d", &val) != 1) 441 return -EINVAL; 442 mvm->disable_power_off_d3 = val; 443 } else { 444 return -EINVAL; 445 } 446 447 mutex_lock(&mvm->mutex); 448 ret = iwl_mvm_power_update_device(mvm); 449 mutex_unlock(&mvm->mutex); 450 451 return ret ?: count; 452 } 453 454 #define BT_MBOX_MSG(_notif, _num, _field) \ 455 ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\ 456 >> BT_MBOX##_num##_##_field##_POS) 457 458 459 #define BT_MBOX_PRINT(_num, _field, _end) \ 460 pos += scnprintf(buf + pos, bufsz - pos, \ 461 "\t%s: %d%s", \ 462 #_field, \ 463 BT_MBOX_MSG(notif, _num, _field), \ 464 true ? "\n" : ", "); 465 466 static 467 int iwl_mvm_coex_dump_mbox(struct iwl_bt_coex_profile_notif *notif, char *buf, 468 int pos, int bufsz) 469 { 470 pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n"); 471 472 BT_MBOX_PRINT(0, LE_SLAVE_LAT, false); 473 BT_MBOX_PRINT(0, LE_PROF1, false); 474 BT_MBOX_PRINT(0, LE_PROF2, false); 475 BT_MBOX_PRINT(0, LE_PROF_OTHER, false); 476 BT_MBOX_PRINT(0, CHL_SEQ_N, false); 477 BT_MBOX_PRINT(0, INBAND_S, false); 478 BT_MBOX_PRINT(0, LE_MIN_RSSI, false); 479 BT_MBOX_PRINT(0, LE_SCAN, false); 480 BT_MBOX_PRINT(0, LE_ADV, false); 481 BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false); 482 BT_MBOX_PRINT(0, OPEN_CON_1, true); 483 484 pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n"); 485 486 BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false); 487 BT_MBOX_PRINT(1, IP_SR, false); 488 BT_MBOX_PRINT(1, LE_MSTR, false); 489 BT_MBOX_PRINT(1, AGGR_TRFC_LD, false); 490 BT_MBOX_PRINT(1, MSG_TYPE, false); 491 BT_MBOX_PRINT(1, SSN, true); 492 493 pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n"); 494 495 BT_MBOX_PRINT(2, SNIFF_ACT, false); 496 BT_MBOX_PRINT(2, PAG, false); 497 BT_MBOX_PRINT(2, INQUIRY, false); 498 BT_MBOX_PRINT(2, CONN, false); 499 BT_MBOX_PRINT(2, SNIFF_INTERVAL, false); 500 BT_MBOX_PRINT(2, DISC, false); 501 BT_MBOX_PRINT(2, SCO_TX_ACT, false); 502 BT_MBOX_PRINT(2, SCO_RX_ACT, false); 503 BT_MBOX_PRINT(2, ESCO_RE_TX, false); 504 BT_MBOX_PRINT(2, SCO_DURATION, true); 505 506 pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n"); 507 508 BT_MBOX_PRINT(3, SCO_STATE, false); 509 BT_MBOX_PRINT(3, SNIFF_STATE, false); 510 BT_MBOX_PRINT(3, A2DP_STATE, false); 511 BT_MBOX_PRINT(3, ACL_STATE, false); 512 BT_MBOX_PRINT(3, MSTR_STATE, false); 513 BT_MBOX_PRINT(3, OBX_STATE, false); 514 BT_MBOX_PRINT(3, OPEN_CON_2, false); 515 BT_MBOX_PRINT(3, TRAFFIC_LOAD, false); 516 BT_MBOX_PRINT(3, CHL_SEQN_LSB, false); 517 BT_MBOX_PRINT(3, INBAND_P, false); 518 BT_MBOX_PRINT(3, MSG_TYPE_2, false); 519 BT_MBOX_PRINT(3, SSN_2, false); 520 BT_MBOX_PRINT(3, UPDATE_REQUEST, true); 521 522 return pos; 523 } 524 525 static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf, 526 size_t count, loff_t *ppos) 527 { 528 struct iwl_mvm *mvm = file->private_data; 529 struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif; 530 char *buf; 531 int ret, pos = 0, bufsz = sizeof(char) * 1024; 532 533 buf = kmalloc(bufsz, GFP_KERNEL); 534 if (!buf) 535 return -ENOMEM; 536 537 mutex_lock(&mvm->mutex); 538 539 pos += iwl_mvm_coex_dump_mbox(notif, buf, pos, bufsz); 540 541 pos += scnprintf(buf + pos, bufsz - pos, "bt_ci_compliance = %d\n", 542 notif->bt_ci_compliance); 543 pos += scnprintf(buf + pos, bufsz - pos, "primary_ch_lut = %d\n", 544 le32_to_cpu(notif->primary_ch_lut)); 545 pos += scnprintf(buf + pos, bufsz - pos, "secondary_ch_lut = %d\n", 546 le32_to_cpu(notif->secondary_ch_lut)); 547 pos += scnprintf(buf + pos, 548 bufsz - pos, "bt_activity_grading = %d\n", 549 le32_to_cpu(notif->bt_activity_grading)); 550 pos += scnprintf(buf + pos, bufsz - pos, 551 "antenna isolation = %d CORUN LUT index = %d\n", 552 mvm->last_ant_isol, mvm->last_corun_lut); 553 pos += scnprintf(buf + pos, bufsz - pos, "bt_rrc = %d\n", 554 (notif->ttc_rrc_status >> 4) & 0xF); 555 pos += scnprintf(buf + pos, bufsz - pos, "bt_ttc = %d\n", 556 notif->ttc_rrc_status & 0xF); 557 558 pos += scnprintf(buf + pos, bufsz - pos, "sync_sco = %d\n", 559 IWL_MVM_BT_COEX_SYNC2SCO); 560 pos += scnprintf(buf + pos, bufsz - pos, "mplut = %d\n", 561 IWL_MVM_BT_COEX_MPLUT); 562 pos += scnprintf(buf + pos, bufsz - pos, "corunning = %d\n", 563 IWL_MVM_BT_COEX_CORUNNING); 564 565 mutex_unlock(&mvm->mutex); 566 567 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 568 kfree(buf); 569 570 return ret; 571 } 572 #undef BT_MBOX_PRINT 573 574 static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf, 575 size_t count, loff_t *ppos) 576 { 577 struct iwl_mvm *mvm = file->private_data; 578 struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd; 579 char buf[256]; 580 int bufsz = sizeof(buf); 581 int pos = 0; 582 583 mutex_lock(&mvm->mutex); 584 585 pos += scnprintf(buf + pos, bufsz - pos, "Channel inhibition CMD\n"); 586 pos += scnprintf(buf + pos, bufsz - pos, 587 "\tPrimary Channel Bitmap 0x%016llx\n", 588 le64_to_cpu(cmd->bt_primary_ci)); 589 pos += scnprintf(buf + pos, bufsz - pos, 590 "\tSecondary Channel Bitmap 0x%016llx\n", 591 le64_to_cpu(cmd->bt_secondary_ci)); 592 593 mutex_unlock(&mvm->mutex); 594 595 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 596 } 597 598 static ssize_t 599 iwl_dbgfs_bt_tx_prio_write(struct iwl_mvm *mvm, char *buf, 600 size_t count, loff_t *ppos) 601 { 602 u32 bt_tx_prio; 603 604 if (sscanf(buf, "%u", &bt_tx_prio) != 1) 605 return -EINVAL; 606 if (bt_tx_prio > 4) 607 return -EINVAL; 608 609 mvm->bt_tx_prio = bt_tx_prio; 610 611 return count; 612 } 613 614 static ssize_t 615 iwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf, 616 size_t count, loff_t *ppos) 617 { 618 static const char * const modes_str[BT_FORCE_ANT_MAX] = { 619 [BT_FORCE_ANT_DIS] = "dis", 620 [BT_FORCE_ANT_AUTO] = "auto", 621 [BT_FORCE_ANT_BT] = "bt", 622 [BT_FORCE_ANT_WIFI] = "wifi", 623 }; 624 int ret, bt_force_ant_mode; 625 626 for (bt_force_ant_mode = 0; 627 bt_force_ant_mode < ARRAY_SIZE(modes_str); 628 bt_force_ant_mode++) { 629 if (!strcmp(buf, modes_str[bt_force_ant_mode])) 630 break; 631 } 632 633 if (bt_force_ant_mode >= ARRAY_SIZE(modes_str)) 634 return -EINVAL; 635 636 ret = 0; 637 mutex_lock(&mvm->mutex); 638 if (mvm->bt_force_ant_mode == bt_force_ant_mode) 639 goto out; 640 641 mvm->bt_force_ant_mode = bt_force_ant_mode; 642 IWL_DEBUG_COEX(mvm, "Force mode: %s\n", 643 modes_str[mvm->bt_force_ant_mode]); 644 645 if (iwl_mvm_firmware_running(mvm)) 646 ret = iwl_mvm_send_bt_init_conf(mvm); 647 else 648 ret = 0; 649 650 out: 651 mutex_unlock(&mvm->mutex); 652 return ret ?: count; 653 } 654 655 #define PRINT_STATS_LE32(_struct, _memb) \ 656 pos += scnprintf(buf + pos, bufsz - pos, \ 657 fmt_table, #_memb, \ 658 le32_to_cpu(_struct->_memb)) 659 660 static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file, 661 char __user *user_buf, size_t count, 662 loff_t *ppos) 663 { 664 struct iwl_mvm *mvm = file->private_data; 665 static const char *fmt_table = "\t%-30s %10u\n"; 666 static const char *fmt_header = "%-32s\n"; 667 int pos = 0; 668 char *buf; 669 int ret; 670 size_t bufsz; 671 672 if (iwl_mvm_has_new_rx_stats_api(mvm)) 673 bufsz = ((sizeof(struct mvm_statistics_rx) / 674 sizeof(__le32)) * 43) + (4 * 33) + 1; 675 else 676 /* 43 = size of each data line; 33 = size of each header */ 677 bufsz = ((sizeof(struct mvm_statistics_rx_v3) / 678 sizeof(__le32)) * 43) + (4 * 33) + 1; 679 680 buf = kzalloc(bufsz, GFP_KERNEL); 681 if (!buf) 682 return -ENOMEM; 683 684 mutex_lock(&mvm->mutex); 685 686 pos += scnprintf(buf + pos, bufsz - pos, fmt_header, 687 "Statistics_Rx - OFDM"); 688 if (!iwl_mvm_has_new_rx_stats_api(mvm)) { 689 struct mvm_statistics_rx_phy_v2 *ofdm = &mvm->rx_stats_v3.ofdm; 690 691 PRINT_STATS_LE32(ofdm, ina_cnt); 692 PRINT_STATS_LE32(ofdm, fina_cnt); 693 PRINT_STATS_LE32(ofdm, plcp_err); 694 PRINT_STATS_LE32(ofdm, crc32_err); 695 PRINT_STATS_LE32(ofdm, overrun_err); 696 PRINT_STATS_LE32(ofdm, early_overrun_err); 697 PRINT_STATS_LE32(ofdm, crc32_good); 698 PRINT_STATS_LE32(ofdm, false_alarm_cnt); 699 PRINT_STATS_LE32(ofdm, fina_sync_err_cnt); 700 PRINT_STATS_LE32(ofdm, sfd_timeout); 701 PRINT_STATS_LE32(ofdm, fina_timeout); 702 PRINT_STATS_LE32(ofdm, unresponded_rts); 703 PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun); 704 PRINT_STATS_LE32(ofdm, sent_ack_cnt); 705 PRINT_STATS_LE32(ofdm, sent_cts_cnt); 706 PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt); 707 PRINT_STATS_LE32(ofdm, dsp_self_kill); 708 PRINT_STATS_LE32(ofdm, mh_format_err); 709 PRINT_STATS_LE32(ofdm, re_acq_main_rssi_sum); 710 PRINT_STATS_LE32(ofdm, reserved); 711 } else { 712 struct mvm_statistics_rx_phy *ofdm = &mvm->rx_stats.ofdm; 713 714 PRINT_STATS_LE32(ofdm, unresponded_rts); 715 PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun); 716 PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt); 717 PRINT_STATS_LE32(ofdm, dsp_self_kill); 718 PRINT_STATS_LE32(ofdm, reserved); 719 } 720 721 pos += scnprintf(buf + pos, bufsz - pos, fmt_header, 722 "Statistics_Rx - CCK"); 723 if (!iwl_mvm_has_new_rx_stats_api(mvm)) { 724 struct mvm_statistics_rx_phy_v2 *cck = &mvm->rx_stats_v3.cck; 725 726 PRINT_STATS_LE32(cck, ina_cnt); 727 PRINT_STATS_LE32(cck, fina_cnt); 728 PRINT_STATS_LE32(cck, plcp_err); 729 PRINT_STATS_LE32(cck, crc32_err); 730 PRINT_STATS_LE32(cck, overrun_err); 731 PRINT_STATS_LE32(cck, early_overrun_err); 732 PRINT_STATS_LE32(cck, crc32_good); 733 PRINT_STATS_LE32(cck, false_alarm_cnt); 734 PRINT_STATS_LE32(cck, fina_sync_err_cnt); 735 PRINT_STATS_LE32(cck, sfd_timeout); 736 PRINT_STATS_LE32(cck, fina_timeout); 737 PRINT_STATS_LE32(cck, unresponded_rts); 738 PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun); 739 PRINT_STATS_LE32(cck, sent_ack_cnt); 740 PRINT_STATS_LE32(cck, sent_cts_cnt); 741 PRINT_STATS_LE32(cck, sent_ba_rsp_cnt); 742 PRINT_STATS_LE32(cck, dsp_self_kill); 743 PRINT_STATS_LE32(cck, mh_format_err); 744 PRINT_STATS_LE32(cck, re_acq_main_rssi_sum); 745 PRINT_STATS_LE32(cck, reserved); 746 } else { 747 struct mvm_statistics_rx_phy *cck = &mvm->rx_stats.cck; 748 749 PRINT_STATS_LE32(cck, unresponded_rts); 750 PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun); 751 PRINT_STATS_LE32(cck, sent_ba_rsp_cnt); 752 PRINT_STATS_LE32(cck, dsp_self_kill); 753 PRINT_STATS_LE32(cck, reserved); 754 } 755 756 pos += scnprintf(buf + pos, bufsz - pos, fmt_header, 757 "Statistics_Rx - GENERAL"); 758 if (!iwl_mvm_has_new_rx_stats_api(mvm)) { 759 struct mvm_statistics_rx_non_phy_v3 *general = 760 &mvm->rx_stats_v3.general; 761 762 PRINT_STATS_LE32(general, bogus_cts); 763 PRINT_STATS_LE32(general, bogus_ack); 764 PRINT_STATS_LE32(general, non_bssid_frames); 765 PRINT_STATS_LE32(general, filtered_frames); 766 PRINT_STATS_LE32(general, non_channel_beacons); 767 PRINT_STATS_LE32(general, channel_beacons); 768 PRINT_STATS_LE32(general, num_missed_bcon); 769 PRINT_STATS_LE32(general, adc_rx_saturation_time); 770 PRINT_STATS_LE32(general, ina_detection_search_time); 771 PRINT_STATS_LE32(general, beacon_silence_rssi_a); 772 PRINT_STATS_LE32(general, beacon_silence_rssi_b); 773 PRINT_STATS_LE32(general, beacon_silence_rssi_c); 774 PRINT_STATS_LE32(general, interference_data_flag); 775 PRINT_STATS_LE32(general, channel_load); 776 PRINT_STATS_LE32(general, dsp_false_alarms); 777 PRINT_STATS_LE32(general, beacon_rssi_a); 778 PRINT_STATS_LE32(general, beacon_rssi_b); 779 PRINT_STATS_LE32(general, beacon_rssi_c); 780 PRINT_STATS_LE32(general, beacon_energy_a); 781 PRINT_STATS_LE32(general, beacon_energy_b); 782 PRINT_STATS_LE32(general, beacon_energy_c); 783 PRINT_STATS_LE32(general, num_bt_kills); 784 PRINT_STATS_LE32(general, mac_id); 785 PRINT_STATS_LE32(general, directed_data_mpdu); 786 } else { 787 struct mvm_statistics_rx_non_phy *general = 788 &mvm->rx_stats.general; 789 790 PRINT_STATS_LE32(general, bogus_cts); 791 PRINT_STATS_LE32(general, bogus_ack); 792 PRINT_STATS_LE32(general, non_channel_beacons); 793 PRINT_STATS_LE32(general, channel_beacons); 794 PRINT_STATS_LE32(general, num_missed_bcon); 795 PRINT_STATS_LE32(general, adc_rx_saturation_time); 796 PRINT_STATS_LE32(general, ina_detection_search_time); 797 PRINT_STATS_LE32(general, beacon_silence_rssi_a); 798 PRINT_STATS_LE32(general, beacon_silence_rssi_b); 799 PRINT_STATS_LE32(general, beacon_silence_rssi_c); 800 PRINT_STATS_LE32(general, interference_data_flag); 801 PRINT_STATS_LE32(general, channel_load); 802 PRINT_STATS_LE32(general, beacon_rssi_a); 803 PRINT_STATS_LE32(general, beacon_rssi_b); 804 PRINT_STATS_LE32(general, beacon_rssi_c); 805 PRINT_STATS_LE32(general, beacon_energy_a); 806 PRINT_STATS_LE32(general, beacon_energy_b); 807 PRINT_STATS_LE32(general, beacon_energy_c); 808 PRINT_STATS_LE32(general, num_bt_kills); 809 PRINT_STATS_LE32(general, mac_id); 810 } 811 812 pos += scnprintf(buf + pos, bufsz - pos, fmt_header, 813 "Statistics_Rx - HT"); 814 if (!iwl_mvm_has_new_rx_stats_api(mvm)) { 815 struct mvm_statistics_rx_ht_phy_v1 *ht = 816 &mvm->rx_stats_v3.ofdm_ht; 817 818 PRINT_STATS_LE32(ht, plcp_err); 819 PRINT_STATS_LE32(ht, overrun_err); 820 PRINT_STATS_LE32(ht, early_overrun_err); 821 PRINT_STATS_LE32(ht, crc32_good); 822 PRINT_STATS_LE32(ht, crc32_err); 823 PRINT_STATS_LE32(ht, mh_format_err); 824 PRINT_STATS_LE32(ht, agg_crc32_good); 825 PRINT_STATS_LE32(ht, agg_mpdu_cnt); 826 PRINT_STATS_LE32(ht, agg_cnt); 827 PRINT_STATS_LE32(ht, unsupport_mcs); 828 } else { 829 struct mvm_statistics_rx_ht_phy *ht = 830 &mvm->rx_stats.ofdm_ht; 831 832 PRINT_STATS_LE32(ht, mh_format_err); 833 PRINT_STATS_LE32(ht, agg_mpdu_cnt); 834 PRINT_STATS_LE32(ht, agg_cnt); 835 PRINT_STATS_LE32(ht, unsupport_mcs); 836 } 837 838 mutex_unlock(&mvm->mutex); 839 840 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 841 kfree(buf); 842 843 return ret; 844 } 845 #undef PRINT_STAT_LE32 846 847 static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm, 848 char __user *user_buf, size_t count, 849 loff_t *ppos, 850 struct iwl_mvm_frame_stats *stats) 851 { 852 char *buff, *pos, *endpos; 853 int idx, i; 854 int ret; 855 static const size_t bufsz = 1024; 856 857 buff = kmalloc(bufsz, GFP_KERNEL); 858 if (!buff) 859 return -ENOMEM; 860 861 spin_lock_bh(&mvm->drv_stats_lock); 862 863 pos = buff; 864 endpos = pos + bufsz; 865 866 pos += scnprintf(pos, endpos - pos, 867 "Legacy/HT/VHT\t:\t%d/%d/%d\n", 868 stats->legacy_frames, 869 stats->ht_frames, 870 stats->vht_frames); 871 pos += scnprintf(pos, endpos - pos, "20/40/80\t:\t%d/%d/%d\n", 872 stats->bw_20_frames, 873 stats->bw_40_frames, 874 stats->bw_80_frames); 875 pos += scnprintf(pos, endpos - pos, "NGI/SGI\t\t:\t%d/%d\n", 876 stats->ngi_frames, 877 stats->sgi_frames); 878 pos += scnprintf(pos, endpos - pos, "SISO/MIMO2\t:\t%d/%d\n", 879 stats->siso_frames, 880 stats->mimo2_frames); 881 pos += scnprintf(pos, endpos - pos, "FAIL/SCSS\t:\t%d/%d\n", 882 stats->fail_frames, 883 stats->success_frames); 884 pos += scnprintf(pos, endpos - pos, "MPDUs agg\t:\t%d\n", 885 stats->agg_frames); 886 pos += scnprintf(pos, endpos - pos, "A-MPDUs\t\t:\t%d\n", 887 stats->ampdu_count); 888 pos += scnprintf(pos, endpos - pos, "Avg MPDUs/A-MPDU:\t%d\n", 889 stats->ampdu_count > 0 ? 890 (stats->agg_frames / stats->ampdu_count) : 0); 891 892 pos += scnprintf(pos, endpos - pos, "Last Rates\n"); 893 894 idx = stats->last_frame_idx - 1; 895 for (i = 0; i < ARRAY_SIZE(stats->last_rates); i++) { 896 idx = (idx + 1) % ARRAY_SIZE(stats->last_rates); 897 if (stats->last_rates[idx] == 0) 898 continue; 899 pos += scnprintf(pos, endpos - pos, "Rate[%d]: ", 900 (int)(ARRAY_SIZE(stats->last_rates) - i)); 901 pos += rs_pretty_print_rate(pos, stats->last_rates[idx]); 902 } 903 spin_unlock_bh(&mvm->drv_stats_lock); 904 905 ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff); 906 kfree(buff); 907 908 return ret; 909 } 910 911 static ssize_t iwl_dbgfs_drv_rx_stats_read(struct file *file, 912 char __user *user_buf, size_t count, 913 loff_t *ppos) 914 { 915 struct iwl_mvm *mvm = file->private_data; 916 917 return iwl_dbgfs_frame_stats_read(mvm, user_buf, count, ppos, 918 &mvm->drv_rx_stats); 919 } 920 921 static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf, 922 size_t count, loff_t *ppos) 923 { 924 int __maybe_unused ret; 925 926 if (!iwl_mvm_firmware_running(mvm)) 927 return -EIO; 928 929 mutex_lock(&mvm->mutex); 930 931 /* allow one more restart that we're provoking here */ 932 if (mvm->fw_restart >= 0) 933 mvm->fw_restart++; 934 935 /* take the return value to make compiler happy - it will fail anyway */ 936 ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, 0, 0, NULL); 937 938 mutex_unlock(&mvm->mutex); 939 940 return count; 941 } 942 943 static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf, 944 size_t count, loff_t *ppos) 945 { 946 int ret; 947 948 if (!iwl_mvm_firmware_running(mvm)) 949 return -EIO; 950 951 ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_NMI); 952 if (ret) 953 return ret; 954 955 iwl_force_nmi(mvm->trans); 956 957 iwl_mvm_unref(mvm, IWL_MVM_REF_NMI); 958 959 return count; 960 } 961 962 static ssize_t 963 iwl_dbgfs_scan_ant_rxchain_read(struct file *file, 964 char __user *user_buf, 965 size_t count, loff_t *ppos) 966 { 967 struct iwl_mvm *mvm = file->private_data; 968 int pos = 0; 969 char buf[32]; 970 const size_t bufsz = sizeof(buf); 971 972 /* print which antennas were set for the scan command by the user */ 973 pos += scnprintf(buf + pos, bufsz - pos, "Antennas for scan: "); 974 if (mvm->scan_rx_ant & ANT_A) 975 pos += scnprintf(buf + pos, bufsz - pos, "A"); 976 if (mvm->scan_rx_ant & ANT_B) 977 pos += scnprintf(buf + pos, bufsz - pos, "B"); 978 if (mvm->scan_rx_ant & ANT_C) 979 pos += scnprintf(buf + pos, bufsz - pos, "C"); 980 pos += scnprintf(buf + pos, bufsz - pos, " (%hhx)\n", mvm->scan_rx_ant); 981 982 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 983 } 984 985 static ssize_t 986 iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf, 987 size_t count, loff_t *ppos) 988 { 989 u8 scan_rx_ant; 990 991 if (!iwl_mvm_firmware_running(mvm)) 992 return -EIO; 993 994 if (sscanf(buf, "%hhx", &scan_rx_ant) != 1) 995 return -EINVAL; 996 if (scan_rx_ant > ANT_ABC) 997 return -EINVAL; 998 if (scan_rx_ant & ~(iwl_mvm_get_valid_rx_ant(mvm))) 999 return -EINVAL; 1000 1001 if (mvm->scan_rx_ant != scan_rx_ant) { 1002 mvm->scan_rx_ant = scan_rx_ant; 1003 if (fw_has_capa(&mvm->fw->ucode_capa, 1004 IWL_UCODE_TLV_CAPA_UMAC_SCAN)) 1005 iwl_mvm_config_scan(mvm); 1006 } 1007 1008 return count; 1009 } 1010 1011 static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm, 1012 char *buf, size_t count, 1013 loff_t *ppos) 1014 { 1015 struct iwl_rss_config_cmd cmd = { 1016 .flags = cpu_to_le32(IWL_RSS_ENABLE), 1017 .hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP | 1018 IWL_RSS_HASH_TYPE_IPV4_UDP | 1019 IWL_RSS_HASH_TYPE_IPV4_PAYLOAD | 1020 IWL_RSS_HASH_TYPE_IPV6_TCP | 1021 IWL_RSS_HASH_TYPE_IPV6_UDP | 1022 IWL_RSS_HASH_TYPE_IPV6_PAYLOAD, 1023 }; 1024 int ret, i, num_repeats, nbytes = count / 2; 1025 1026 ret = hex2bin(cmd.indirection_table, buf, nbytes); 1027 if (ret) 1028 return ret; 1029 1030 /* 1031 * The input is the redirection table, partial or full. 1032 * Repeat the pattern if needed. 1033 * For example, input of 01020F will be repeated 42 times, 1034 * indirecting RSS hash results to queues 1, 2, 15 (skipping 1035 * queues 3 - 14). 1036 */ 1037 num_repeats = ARRAY_SIZE(cmd.indirection_table) / nbytes; 1038 for (i = 1; i < num_repeats; i++) 1039 memcpy(&cmd.indirection_table[i * nbytes], 1040 cmd.indirection_table, nbytes); 1041 /* handle cut in the middle pattern for the last places */ 1042 memcpy(&cmd.indirection_table[i * nbytes], cmd.indirection_table, 1043 ARRAY_SIZE(cmd.indirection_table) % nbytes); 1044 1045 netdev_rss_key_fill(cmd.secret_key, sizeof(cmd.secret_key)); 1046 1047 mutex_lock(&mvm->mutex); 1048 if (iwl_mvm_firmware_running(mvm)) 1049 ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, 1050 sizeof(cmd), &cmd); 1051 else 1052 ret = 0; 1053 mutex_unlock(&mvm->mutex); 1054 1055 return ret ?: count; 1056 } 1057 1058 static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm, 1059 char *buf, size_t count, 1060 loff_t *ppos) 1061 { 1062 struct iwl_rx_cmd_buffer rxb = { 1063 ._rx_page_order = 0, 1064 .truesize = 0, /* not used */ 1065 ._offset = 0, 1066 }; 1067 struct iwl_rx_packet *pkt; 1068 struct iwl_rx_mpdu_desc *desc; 1069 int bin_len = count / 2; 1070 int ret = -EINVAL; 1071 1072 if (!iwl_mvm_firmware_running(mvm)) 1073 return -EIO; 1074 1075 /* supporting only 9000 descriptor */ 1076 if (!mvm->trans->cfg->mq_rx_supported) 1077 return -ENOTSUPP; 1078 1079 rxb._page = alloc_pages(GFP_ATOMIC, 0); 1080 if (!rxb._page) 1081 return -ENOMEM; 1082 pkt = rxb_addr(&rxb); 1083 1084 ret = hex2bin(page_address(rxb._page), buf, bin_len); 1085 if (ret) 1086 goto out; 1087 1088 /* avoid invalid memory access */ 1089 if (bin_len < sizeof(*pkt) + sizeof(*desc)) 1090 goto out; 1091 1092 /* check this is RX packet */ 1093 if (WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd) != 1094 WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD)) 1095 goto out; 1096 1097 /* check the length in metadata matches actual received length */ 1098 desc = (void *)pkt->data; 1099 if (le16_to_cpu(desc->mpdu_len) != 1100 (bin_len - sizeof(*desc) - sizeof(*pkt))) 1101 goto out; 1102 1103 local_bh_disable(); 1104 iwl_mvm_rx_mpdu_mq(mvm, NULL, &rxb, 0); 1105 local_bh_enable(); 1106 ret = 0; 1107 1108 out: 1109 iwl_free_rxb(&rxb); 1110 1111 return ret ?: count; 1112 } 1113 1114 static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file, 1115 char __user *user_buf, 1116 size_t count, loff_t *ppos) 1117 { 1118 struct iwl_mvm *mvm = file->private_data; 1119 int conf; 1120 char buf[8]; 1121 const size_t bufsz = sizeof(buf); 1122 int pos = 0; 1123 1124 mutex_lock(&mvm->mutex); 1125 conf = mvm->fwrt.dump.conf; 1126 mutex_unlock(&mvm->mutex); 1127 1128 pos += scnprintf(buf + pos, bufsz - pos, "%d\n", conf); 1129 1130 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1131 } 1132 1133 /* 1134 * Enable / Disable continuous recording. 1135 * Cause the FW to start continuous recording, by sending the relevant hcmd. 1136 * Enable: input of every integer larger than 0, ENABLE_CONT_RECORDING. 1137 * Disable: for 0 as input, DISABLE_CONT_RECORDING. 1138 */ 1139 static ssize_t iwl_dbgfs_cont_recording_write(struct iwl_mvm *mvm, 1140 char *buf, size_t count, 1141 loff_t *ppos) 1142 { 1143 struct iwl_trans *trans = mvm->trans; 1144 const struct iwl_fw_dbg_dest_tlv *dest = trans->dbg_dest_tlv; 1145 struct iwl_continuous_record_cmd cont_rec = {}; 1146 int ret, rec_mode; 1147 1148 if (!iwl_mvm_firmware_running(mvm)) 1149 return -EIO; 1150 1151 if (!dest) 1152 return -EOPNOTSUPP; 1153 1154 if (dest->monitor_mode != SMEM_MODE || 1155 trans->cfg->device_family < IWL_DEVICE_FAMILY_8000) 1156 return -EOPNOTSUPP; 1157 1158 ret = kstrtoint(buf, 0, &rec_mode); 1159 if (ret) 1160 return ret; 1161 1162 cont_rec.record_mode.enable_recording = rec_mode ? 1163 cpu_to_le16(ENABLE_CONT_RECORDING) : 1164 cpu_to_le16(DISABLE_CONT_RECORDING); 1165 1166 mutex_lock(&mvm->mutex); 1167 ret = iwl_mvm_send_cmd_pdu(mvm, LDBG_CONFIG_CMD, 0, 1168 sizeof(cont_rec), &cont_rec); 1169 mutex_unlock(&mvm->mutex); 1170 1171 return ret ?: count; 1172 } 1173 1174 static ssize_t iwl_dbgfs_fw_dbg_conf_write(struct iwl_mvm *mvm, 1175 char *buf, size_t count, 1176 loff_t *ppos) 1177 { 1178 unsigned int conf_id; 1179 int ret; 1180 1181 if (!iwl_mvm_firmware_running(mvm)) 1182 return -EIO; 1183 1184 ret = kstrtouint(buf, 0, &conf_id); 1185 if (ret) 1186 return ret; 1187 1188 if (WARN_ON(conf_id >= FW_DBG_CONF_MAX)) 1189 return -EINVAL; 1190 1191 mutex_lock(&mvm->mutex); 1192 ret = iwl_fw_start_dbg_conf(&mvm->fwrt, conf_id); 1193 mutex_unlock(&mvm->mutex); 1194 1195 return ret ?: count; 1196 } 1197 1198 static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm, 1199 char *buf, size_t count, 1200 loff_t *ppos) 1201 { 1202 int ret; 1203 1204 if (!iwl_mvm_firmware_running(mvm)) 1205 return -EIO; 1206 1207 ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE); 1208 if (ret) 1209 return ret; 1210 if (count == 0) 1211 return 0; 1212 1213 iwl_fw_dbg_collect(&mvm->fwrt, FW_DBG_TRIGGER_USER, buf, 1214 (count - 1), NULL); 1215 1216 iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE); 1217 1218 return count; 1219 } 1220 1221 static ssize_t iwl_dbgfs_max_amsdu_len_write(struct iwl_mvm *mvm, 1222 char *buf, size_t count, 1223 loff_t *ppos) 1224 { 1225 unsigned int max_amsdu_len; 1226 int ret; 1227 1228 ret = kstrtouint(buf, 0, &max_amsdu_len); 1229 if (ret) 1230 return ret; 1231 1232 if (max_amsdu_len > IEEE80211_MAX_MPDU_LEN_VHT_11454) 1233 return -EINVAL; 1234 mvm->max_amsdu_len = max_amsdu_len; 1235 1236 return count; 1237 } 1238 1239 #define ADD_TEXT(...) pos += scnprintf(buf + pos, bufsz - pos, __VA_ARGS__) 1240 #ifdef CONFIG_IWLWIFI_BCAST_FILTERING 1241 static ssize_t iwl_dbgfs_bcast_filters_read(struct file *file, 1242 char __user *user_buf, 1243 size_t count, loff_t *ppos) 1244 { 1245 struct iwl_mvm *mvm = file->private_data; 1246 struct iwl_bcast_filter_cmd cmd; 1247 const struct iwl_fw_bcast_filter *filter; 1248 char *buf; 1249 int bufsz = 1024; 1250 int i, j, pos = 0; 1251 ssize_t ret; 1252 1253 buf = kzalloc(bufsz, GFP_KERNEL); 1254 if (!buf) 1255 return -ENOMEM; 1256 1257 mutex_lock(&mvm->mutex); 1258 if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) { 1259 ADD_TEXT("None\n"); 1260 mutex_unlock(&mvm->mutex); 1261 goto out; 1262 } 1263 mutex_unlock(&mvm->mutex); 1264 1265 for (i = 0; cmd.filters[i].attrs[0].mask; i++) { 1266 filter = &cmd.filters[i]; 1267 1268 ADD_TEXT("Filter [%d]:\n", i); 1269 ADD_TEXT("\tDiscard=%d\n", filter->discard); 1270 ADD_TEXT("\tFrame Type: %s\n", 1271 filter->frame_type ? "IPv4" : "Generic"); 1272 1273 for (j = 0; j < ARRAY_SIZE(filter->attrs); j++) { 1274 const struct iwl_fw_bcast_filter_attr *attr; 1275 1276 attr = &filter->attrs[j]; 1277 if (!attr->mask) 1278 break; 1279 1280 ADD_TEXT("\tAttr [%d]: offset=%d (from %s), mask=0x%x, value=0x%x reserved=0x%x\n", 1281 j, attr->offset, 1282 attr->offset_type ? "IP End" : 1283 "Payload Start", 1284 be32_to_cpu(attr->mask), 1285 be32_to_cpu(attr->val), 1286 le16_to_cpu(attr->reserved1)); 1287 } 1288 } 1289 out: 1290 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1291 kfree(buf); 1292 return ret; 1293 } 1294 1295 static ssize_t iwl_dbgfs_bcast_filters_write(struct iwl_mvm *mvm, char *buf, 1296 size_t count, loff_t *ppos) 1297 { 1298 int pos, next_pos; 1299 struct iwl_fw_bcast_filter filter = {}; 1300 struct iwl_bcast_filter_cmd cmd; 1301 u32 filter_id, attr_id, mask, value; 1302 int err = 0; 1303 1304 if (sscanf(buf, "%d %hhi %hhi %n", &filter_id, &filter.discard, 1305 &filter.frame_type, &pos) != 3) 1306 return -EINVAL; 1307 1308 if (filter_id >= ARRAY_SIZE(mvm->dbgfs_bcast_filtering.cmd.filters) || 1309 filter.frame_type > BCAST_FILTER_FRAME_TYPE_IPV4) 1310 return -EINVAL; 1311 1312 for (attr_id = 0; attr_id < ARRAY_SIZE(filter.attrs); 1313 attr_id++) { 1314 struct iwl_fw_bcast_filter_attr *attr = 1315 &filter.attrs[attr_id]; 1316 1317 if (pos >= count) 1318 break; 1319 1320 if (sscanf(&buf[pos], "%hhi %hhi %i %i %n", 1321 &attr->offset, &attr->offset_type, 1322 &mask, &value, &next_pos) != 4) 1323 return -EINVAL; 1324 1325 attr->mask = cpu_to_be32(mask); 1326 attr->val = cpu_to_be32(value); 1327 if (mask) 1328 filter.num_attrs++; 1329 1330 pos += next_pos; 1331 } 1332 1333 mutex_lock(&mvm->mutex); 1334 memcpy(&mvm->dbgfs_bcast_filtering.cmd.filters[filter_id], 1335 &filter, sizeof(filter)); 1336 1337 /* send updated bcast filtering configuration */ 1338 if (iwl_mvm_firmware_running(mvm) && 1339 mvm->dbgfs_bcast_filtering.override && 1340 iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) 1341 err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0, 1342 sizeof(cmd), &cmd); 1343 mutex_unlock(&mvm->mutex); 1344 1345 return err ?: count; 1346 } 1347 1348 static ssize_t iwl_dbgfs_bcast_filters_macs_read(struct file *file, 1349 char __user *user_buf, 1350 size_t count, loff_t *ppos) 1351 { 1352 struct iwl_mvm *mvm = file->private_data; 1353 struct iwl_bcast_filter_cmd cmd; 1354 char *buf; 1355 int bufsz = 1024; 1356 int i, pos = 0; 1357 ssize_t ret; 1358 1359 buf = kzalloc(bufsz, GFP_KERNEL); 1360 if (!buf) 1361 return -ENOMEM; 1362 1363 mutex_lock(&mvm->mutex); 1364 if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) { 1365 ADD_TEXT("None\n"); 1366 mutex_unlock(&mvm->mutex); 1367 goto out; 1368 } 1369 mutex_unlock(&mvm->mutex); 1370 1371 for (i = 0; i < ARRAY_SIZE(cmd.macs); i++) { 1372 const struct iwl_fw_bcast_mac *mac = &cmd.macs[i]; 1373 1374 ADD_TEXT("Mac [%d]: discard=%d attached_filters=0x%x\n", 1375 i, mac->default_discard, mac->attached_filters); 1376 } 1377 out: 1378 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1379 kfree(buf); 1380 return ret; 1381 } 1382 1383 static ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm, 1384 char *buf, size_t count, 1385 loff_t *ppos) 1386 { 1387 struct iwl_bcast_filter_cmd cmd; 1388 struct iwl_fw_bcast_mac mac = {}; 1389 u32 mac_id, attached_filters; 1390 int err = 0; 1391 1392 if (!mvm->bcast_filters) 1393 return -ENOENT; 1394 1395 if (sscanf(buf, "%d %hhi %i", &mac_id, &mac.default_discard, 1396 &attached_filters) != 3) 1397 return -EINVAL; 1398 1399 if (mac_id >= ARRAY_SIZE(cmd.macs) || 1400 mac.default_discard > 1 || 1401 attached_filters >= BIT(ARRAY_SIZE(cmd.filters))) 1402 return -EINVAL; 1403 1404 mac.attached_filters = cpu_to_le16(attached_filters); 1405 1406 mutex_lock(&mvm->mutex); 1407 memcpy(&mvm->dbgfs_bcast_filtering.cmd.macs[mac_id], 1408 &mac, sizeof(mac)); 1409 1410 /* send updated bcast filtering configuration */ 1411 if (iwl_mvm_firmware_running(mvm) && 1412 mvm->dbgfs_bcast_filtering.override && 1413 iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) 1414 err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0, 1415 sizeof(cmd), &cmd); 1416 mutex_unlock(&mvm->mutex); 1417 1418 return err ?: count; 1419 } 1420 #endif 1421 1422 #ifdef CONFIG_PM_SLEEP 1423 static ssize_t iwl_dbgfs_d3_sram_write(struct iwl_mvm *mvm, char *buf, 1424 size_t count, loff_t *ppos) 1425 { 1426 int store; 1427 1428 if (sscanf(buf, "%d", &store) != 1) 1429 return -EINVAL; 1430 1431 mvm->store_d3_resume_sram = store; 1432 1433 return count; 1434 } 1435 1436 static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf, 1437 size_t count, loff_t *ppos) 1438 { 1439 struct iwl_mvm *mvm = file->private_data; 1440 const struct fw_img *img; 1441 int ofs, len, pos = 0; 1442 size_t bufsz, ret; 1443 char *buf; 1444 u8 *ptr = mvm->d3_resume_sram; 1445 1446 img = &mvm->fw->img[IWL_UCODE_WOWLAN]; 1447 len = img->sec[IWL_UCODE_SECTION_DATA].len; 1448 1449 bufsz = len * 4 + 256; 1450 buf = kzalloc(bufsz, GFP_KERNEL); 1451 if (!buf) 1452 return -ENOMEM; 1453 1454 pos += scnprintf(buf, bufsz, "D3 SRAM capture: %sabled\n", 1455 mvm->store_d3_resume_sram ? "en" : "dis"); 1456 1457 if (ptr) { 1458 for (ofs = 0; ofs < len; ofs += 16) { 1459 pos += scnprintf(buf + pos, bufsz - pos, 1460 "0x%.4x %16ph\n", ofs, ptr + ofs); 1461 } 1462 } else { 1463 pos += scnprintf(buf + pos, bufsz - pos, 1464 "(no data captured)\n"); 1465 } 1466 1467 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1468 1469 kfree(buf); 1470 1471 return ret; 1472 } 1473 #endif 1474 1475 #define PRINT_MVM_REF(ref) do { \ 1476 if (mvm->refs[ref]) \ 1477 pos += scnprintf(buf + pos, bufsz - pos, \ 1478 "\t(0x%lx): %d %s\n", \ 1479 BIT(ref), mvm->refs[ref], #ref); \ 1480 } while (0) 1481 1482 static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file, 1483 char __user *user_buf, 1484 size_t count, loff_t *ppos) 1485 { 1486 struct iwl_mvm *mvm = file->private_data; 1487 int i, pos = 0; 1488 char buf[256]; 1489 const size_t bufsz = sizeof(buf); 1490 u32 refs = 0; 1491 1492 for (i = 0; i < IWL_MVM_REF_COUNT; i++) 1493 if (mvm->refs[i]) 1494 refs |= BIT(i); 1495 1496 pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%x\n", 1497 refs); 1498 1499 PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN); 1500 PRINT_MVM_REF(IWL_MVM_REF_SCAN); 1501 PRINT_MVM_REF(IWL_MVM_REF_ROC); 1502 PRINT_MVM_REF(IWL_MVM_REF_ROC_AUX); 1503 PRINT_MVM_REF(IWL_MVM_REF_P2P_CLIENT); 1504 PRINT_MVM_REF(IWL_MVM_REF_AP_IBSS); 1505 PRINT_MVM_REF(IWL_MVM_REF_USER); 1506 PRINT_MVM_REF(IWL_MVM_REF_TX); 1507 PRINT_MVM_REF(IWL_MVM_REF_TX_AGG); 1508 PRINT_MVM_REF(IWL_MVM_REF_ADD_IF); 1509 PRINT_MVM_REF(IWL_MVM_REF_START_AP); 1510 PRINT_MVM_REF(IWL_MVM_REF_BSS_CHANGED); 1511 PRINT_MVM_REF(IWL_MVM_REF_PREPARE_TX); 1512 PRINT_MVM_REF(IWL_MVM_REF_PROTECT_TDLS); 1513 PRINT_MVM_REF(IWL_MVM_REF_CHECK_CTKILL); 1514 PRINT_MVM_REF(IWL_MVM_REF_PRPH_READ); 1515 PRINT_MVM_REF(IWL_MVM_REF_PRPH_WRITE); 1516 PRINT_MVM_REF(IWL_MVM_REF_NMI); 1517 PRINT_MVM_REF(IWL_MVM_REF_TM_CMD); 1518 PRINT_MVM_REF(IWL_MVM_REF_EXIT_WORK); 1519 PRINT_MVM_REF(IWL_MVM_REF_PROTECT_CSA); 1520 PRINT_MVM_REF(IWL_MVM_REF_FW_DBG_COLLECT); 1521 PRINT_MVM_REF(IWL_MVM_REF_INIT_UCODE); 1522 PRINT_MVM_REF(IWL_MVM_REF_SENDING_CMD); 1523 PRINT_MVM_REF(IWL_MVM_REF_RX); 1524 1525 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1526 } 1527 1528 static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf, 1529 size_t count, loff_t *ppos) 1530 { 1531 unsigned long value; 1532 int ret; 1533 bool taken; 1534 1535 ret = kstrtoul(buf, 10, &value); 1536 if (ret < 0) 1537 return ret; 1538 1539 mutex_lock(&mvm->mutex); 1540 1541 taken = mvm->refs[IWL_MVM_REF_USER]; 1542 if (value == 1 && !taken) 1543 iwl_mvm_ref(mvm, IWL_MVM_REF_USER); 1544 else if (value == 0 && taken) 1545 iwl_mvm_unref(mvm, IWL_MVM_REF_USER); 1546 else 1547 ret = -EINVAL; 1548 1549 mutex_unlock(&mvm->mutex); 1550 1551 if (ret < 0) 1552 return ret; 1553 return count; 1554 } 1555 1556 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \ 1557 _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm) 1558 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ 1559 _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm) 1560 #define MVM_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do { \ 1561 if (!debugfs_create_file(alias, mode, parent, mvm, \ 1562 &iwl_dbgfs_##name##_ops)) \ 1563 goto err; \ 1564 } while (0) 1565 #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \ 1566 MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode) 1567 1568 static ssize_t 1569 iwl_dbgfs_prph_reg_read(struct file *file, 1570 char __user *user_buf, 1571 size_t count, loff_t *ppos) 1572 { 1573 struct iwl_mvm *mvm = file->private_data; 1574 int pos = 0; 1575 char buf[32]; 1576 const size_t bufsz = sizeof(buf); 1577 int ret; 1578 1579 if (!mvm->dbgfs_prph_reg_addr) 1580 return -EINVAL; 1581 1582 ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_READ); 1583 if (ret) 1584 return ret; 1585 1586 pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n", 1587 mvm->dbgfs_prph_reg_addr, 1588 iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr)); 1589 1590 iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_READ); 1591 1592 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1593 } 1594 1595 static ssize_t 1596 iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf, 1597 size_t count, loff_t *ppos) 1598 { 1599 u8 args; 1600 u32 value; 1601 int ret; 1602 1603 args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value); 1604 /* if we only want to set the reg address - nothing more to do */ 1605 if (args == 1) 1606 goto out; 1607 1608 /* otherwise, make sure we have both address and value */ 1609 if (args != 2) 1610 return -EINVAL; 1611 1612 ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE); 1613 if (ret) 1614 return ret; 1615 1616 iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value); 1617 1618 iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE); 1619 out: 1620 return count; 1621 } 1622 1623 static ssize_t 1624 iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf, 1625 size_t count, loff_t *ppos) 1626 { 1627 int ret; 1628 1629 if (!iwl_mvm_firmware_running(mvm)) 1630 return -EIO; 1631 1632 mutex_lock(&mvm->mutex); 1633 ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL); 1634 mutex_unlock(&mvm->mutex); 1635 1636 return ret ?: count; 1637 } 1638 1639 MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64); 1640 1641 /* Device wide debugfs entries */ 1642 MVM_DEBUGFS_READ_FILE_OPS(ctdp_budget); 1643 MVM_DEBUGFS_WRITE_FILE_OPS(stop_ctdp, 8); 1644 MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16); 1645 MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8); 1646 MVM_DEBUGFS_WRITE_FILE_OPS(send_echo_cmd, 8); 1647 MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64); 1648 MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64); 1649 MVM_DEBUGFS_READ_FILE_OPS(nic_temp); 1650 MVM_DEBUGFS_READ_FILE_OPS(stations); 1651 MVM_DEBUGFS_READ_FILE_OPS(bt_notif); 1652 MVM_DEBUGFS_READ_FILE_OPS(bt_cmd); 1653 MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64); 1654 MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats); 1655 MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats); 1656 MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10); 1657 MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10); 1658 MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10); 1659 MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10); 1660 MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); 1661 MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); 1662 MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8); 1663 MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64); 1664 MVM_DEBUGFS_WRITE_FILE_OPS(cont_recording, 8); 1665 MVM_DEBUGFS_WRITE_FILE_OPS(max_amsdu_len, 8); 1666 MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl, 1667 (IWL_RSS_INDIRECTION_TABLE_SIZE * 2)); 1668 MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512); 1669 1670 #ifdef CONFIG_IWLWIFI_BCAST_FILTERING 1671 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); 1672 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256); 1673 #endif 1674 1675 #ifdef CONFIG_PM_SLEEP 1676 MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8); 1677 #endif 1678 #ifdef CONFIG_ACPI 1679 MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile); 1680 #endif 1681 1682 static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf, 1683 size_t count, loff_t *ppos) 1684 { 1685 struct iwl_mvm *mvm = file->private_data; 1686 struct iwl_dbg_mem_access_cmd cmd = {}; 1687 struct iwl_dbg_mem_access_rsp *rsp; 1688 struct iwl_host_cmd hcmd = { 1689 .flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL, 1690 .data = { &cmd, }, 1691 .len = { sizeof(cmd) }, 1692 }; 1693 size_t delta; 1694 ssize_t ret, len; 1695 1696 if (!iwl_mvm_firmware_running(mvm)) 1697 return -EIO; 1698 1699 hcmd.id = iwl_cmd_id(*ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR, 1700 DEBUG_GROUP, 0); 1701 cmd.op = cpu_to_le32(DEBUG_MEM_OP_READ); 1702 1703 /* Take care of alignment of both the position and the length */ 1704 delta = *ppos & 0x3; 1705 cmd.addr = cpu_to_le32(*ppos - delta); 1706 cmd.len = cpu_to_le32(min(ALIGN(count + delta, 4) / 4, 1707 (size_t)DEBUG_MEM_MAX_SIZE_DWORDS)); 1708 1709 mutex_lock(&mvm->mutex); 1710 ret = iwl_mvm_send_cmd(mvm, &hcmd); 1711 mutex_unlock(&mvm->mutex); 1712 1713 if (ret < 0) 1714 return ret; 1715 1716 rsp = (void *)hcmd.resp_pkt->data; 1717 if (le32_to_cpu(rsp->status) != DEBUG_MEM_STATUS_SUCCESS) { 1718 ret = -ENXIO; 1719 goto out; 1720 } 1721 1722 len = min((size_t)le32_to_cpu(rsp->len) << 2, 1723 iwl_rx_packet_payload_len(hcmd.resp_pkt) - sizeof(*rsp)); 1724 len = min(len - delta, count); 1725 if (len < 0) { 1726 ret = -EFAULT; 1727 goto out; 1728 } 1729 1730 ret = len - copy_to_user(user_buf, (void *)rsp->data + delta, len); 1731 *ppos += ret; 1732 1733 out: 1734 iwl_free_resp(&hcmd); 1735 return ret; 1736 } 1737 1738 static ssize_t iwl_dbgfs_mem_write(struct file *file, 1739 const char __user *user_buf, size_t count, 1740 loff_t *ppos) 1741 { 1742 struct iwl_mvm *mvm = file->private_data; 1743 struct iwl_dbg_mem_access_cmd *cmd; 1744 struct iwl_dbg_mem_access_rsp *rsp; 1745 struct iwl_host_cmd hcmd = {}; 1746 size_t cmd_size; 1747 size_t data_size; 1748 u32 op, len; 1749 ssize_t ret; 1750 1751 if (!iwl_mvm_firmware_running(mvm)) 1752 return -EIO; 1753 1754 hcmd.id = iwl_cmd_id(*ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR, 1755 DEBUG_GROUP, 0); 1756 1757 if (*ppos & 0x3 || count < 4) { 1758 op = DEBUG_MEM_OP_WRITE_BYTES; 1759 len = min(count, (size_t)(4 - (*ppos & 0x3))); 1760 data_size = len; 1761 } else { 1762 op = DEBUG_MEM_OP_WRITE; 1763 len = min(count >> 2, (size_t)DEBUG_MEM_MAX_SIZE_DWORDS); 1764 data_size = len << 2; 1765 } 1766 1767 cmd_size = sizeof(*cmd) + ALIGN(data_size, 4); 1768 cmd = kzalloc(cmd_size, GFP_KERNEL); 1769 if (!cmd) 1770 return -ENOMEM; 1771 1772 cmd->op = cpu_to_le32(op); 1773 cmd->len = cpu_to_le32(len); 1774 cmd->addr = cpu_to_le32(*ppos); 1775 if (copy_from_user((void *)cmd->data, user_buf, data_size)) { 1776 kfree(cmd); 1777 return -EFAULT; 1778 } 1779 1780 hcmd.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL, 1781 hcmd.data[0] = (void *)cmd; 1782 hcmd.len[0] = cmd_size; 1783 1784 mutex_lock(&mvm->mutex); 1785 ret = iwl_mvm_send_cmd(mvm, &hcmd); 1786 mutex_unlock(&mvm->mutex); 1787 1788 kfree(cmd); 1789 1790 if (ret < 0) 1791 return ret; 1792 1793 rsp = (void *)hcmd.resp_pkt->data; 1794 if (rsp->status != DEBUG_MEM_STATUS_SUCCESS) { 1795 ret = -ENXIO; 1796 goto out; 1797 } 1798 1799 ret = data_size; 1800 *ppos += ret; 1801 1802 out: 1803 iwl_free_resp(&hcmd); 1804 return ret; 1805 } 1806 1807 static const struct file_operations iwl_dbgfs_mem_ops = { 1808 .read = iwl_dbgfs_mem_read, 1809 .write = iwl_dbgfs_mem_write, 1810 .open = simple_open, 1811 .llseek = default_llseek, 1812 }; 1813 1814 int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) 1815 { 1816 struct dentry *bcast_dir __maybe_unused; 1817 char buf[100]; 1818 1819 spin_lock_init(&mvm->drv_stats_lock); 1820 1821 mvm->debugfs_dir = dbgfs_dir; 1822 1823 MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, S_IWUSR); 1824 MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR); 1825 MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR); 1826 MVM_DEBUGFS_ADD_FILE(set_nic_temperature, mvm->debugfs_dir, 1827 S_IWUSR | S_IRUSR); 1828 MVM_DEBUGFS_ADD_FILE(nic_temp, dbgfs_dir, S_IRUSR); 1829 MVM_DEBUGFS_ADD_FILE(ctdp_budget, dbgfs_dir, S_IRUSR); 1830 MVM_DEBUGFS_ADD_FILE(stop_ctdp, dbgfs_dir, S_IWUSR); 1831 MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); 1832 MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); 1833 MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR); 1834 MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, 1835 S_IRUSR | S_IWUSR); 1836 MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR); 1837 MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, S_IRUSR); 1838 MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); 1839 MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR); 1840 MVM_DEBUGFS_ADD_FILE(bt_tx_prio, mvm->debugfs_dir, S_IWUSR); 1841 MVM_DEBUGFS_ADD_FILE(bt_force_ant, mvm->debugfs_dir, S_IWUSR); 1842 MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, 1843 S_IWUSR | S_IRUSR); 1844 MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, S_IWUSR | S_IRUSR); 1845 MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR); 1846 MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, S_IRUSR | S_IWUSR); 1847 MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR); 1848 MVM_DEBUGFS_ADD_FILE(max_amsdu_len, mvm->debugfs_dir, S_IWUSR); 1849 MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, S_IWUSR); 1850 MVM_DEBUGFS_ADD_FILE(cont_recording, mvm->debugfs_dir, S_IWUSR); 1851 MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, S_IWUSR); 1852 MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, S_IWUSR); 1853 #ifdef CONFIG_ACPI 1854 MVM_DEBUGFS_ADD_FILE(sar_geo_profile, dbgfs_dir, S_IRUSR); 1855 #endif 1856 1857 if (!debugfs_create_bool("enable_scan_iteration_notif", 1858 S_IRUSR | S_IWUSR, 1859 mvm->debugfs_dir, 1860 &mvm->scan_iter_notif_enabled)) 1861 goto err; 1862 if (!debugfs_create_bool("drop_bcn_ap_mode", S_IRUSR | S_IWUSR, 1863 mvm->debugfs_dir, &mvm->drop_bcn_ap_mode)) 1864 goto err; 1865 1866 #ifdef CONFIG_IWLWIFI_BCAST_FILTERING 1867 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) { 1868 bcast_dir = debugfs_create_dir("bcast_filtering", 1869 mvm->debugfs_dir); 1870 if (!bcast_dir) 1871 goto err; 1872 1873 if (!debugfs_create_bool("override", S_IRUSR | S_IWUSR, 1874 bcast_dir, 1875 &mvm->dbgfs_bcast_filtering.override)) 1876 goto err; 1877 1878 MVM_DEBUGFS_ADD_FILE_ALIAS("filters", bcast_filters, 1879 bcast_dir, S_IWUSR | S_IRUSR); 1880 MVM_DEBUGFS_ADD_FILE_ALIAS("macs", bcast_filters_macs, 1881 bcast_dir, S_IWUSR | S_IRUSR); 1882 } 1883 #endif 1884 1885 #ifdef CONFIG_PM_SLEEP 1886 MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); 1887 MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR); 1888 if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR | S_IWUSR, 1889 mvm->debugfs_dir, &mvm->d3_wake_sysassert)) 1890 goto err; 1891 if (!debugfs_create_u32("last_netdetect_scans", S_IRUSR, 1892 mvm->debugfs_dir, &mvm->last_netdetect_scans)) 1893 goto err; 1894 #endif 1895 1896 if (!debugfs_create_u8("ps_disabled", S_IRUSR, 1897 mvm->debugfs_dir, &mvm->ps_disabled)) 1898 goto err; 1899 if (!debugfs_create_blob("nvm_hw", S_IRUSR, 1900 mvm->debugfs_dir, &mvm->nvm_hw_blob)) 1901 goto err; 1902 if (!debugfs_create_blob("nvm_sw", S_IRUSR, 1903 mvm->debugfs_dir, &mvm->nvm_sw_blob)) 1904 goto err; 1905 if (!debugfs_create_blob("nvm_calib", S_IRUSR, 1906 mvm->debugfs_dir, &mvm->nvm_calib_blob)) 1907 goto err; 1908 if (!debugfs_create_blob("nvm_prod", S_IRUSR, 1909 mvm->debugfs_dir, &mvm->nvm_prod_blob)) 1910 goto err; 1911 if (!debugfs_create_blob("nvm_phy_sku", S_IRUSR, 1912 mvm->debugfs_dir, &mvm->nvm_phy_sku_blob)) 1913 goto err; 1914 1915 debugfs_create_file("mem", S_IRUSR | S_IWUSR, dbgfs_dir, mvm, 1916 &iwl_dbgfs_mem_ops); 1917 1918 /* 1919 * Create a symlink with mac80211. It will be removed when mac80211 1920 * exists (before the opmode exists which removes the target.) 1921 */ 1922 snprintf(buf, 100, "../../%pd2", dbgfs_dir->d_parent); 1923 if (!debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir, buf)) 1924 goto err; 1925 1926 return 0; 1927 err: 1928 IWL_ERR(mvm, "Can't create the mvm debugfs directory\n"); 1929 return -ENOMEM; 1930 } 1931