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