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