1 /******************************************************************************
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.
8 * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
24 * The full GNU General Public License is included in this distribution
25 * in the file called COPYING.
27 * Contact Information:
28 * Intel Linux Wireless <ilw@linux.intel.com>
29 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
33 * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
34 * All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
40 * * Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * * Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in
44 * the documentation and/or other materials provided with the
46 * * Neither the name Intel Corporation nor the names of its
47 * contributors may be used to endorse or promote products derived
48 * from this software without specific prior written permission.
50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62 *****************************************************************************/
67 struct iwl_dbgfs_mvm_ctx
{
69 struct ieee80211_vif
*vif
;
72 static ssize_t
iwl_dbgfs_tx_flush_write(struct file
*file
,
73 const char __user
*user_buf
,
74 size_t count
, loff_t
*ppos
)
76 struct iwl_mvm
*mvm
= file
->private_data
;
82 if (!mvm
->ucode_loaded
|| mvm
->cur_ucode
!= IWL_UCODE_REGULAR
)
85 memset(buf
, 0, sizeof(buf
));
86 buf_size
= min(count
, sizeof(buf
) - 1);
87 if (copy_from_user(buf
, user_buf
, buf_size
))
90 if (sscanf(buf
, "%x", &scd_q_msk
) != 1)
93 IWL_ERR(mvm
, "FLUSHING queues: scd_q_msk = 0x%x\n", scd_q_msk
);
95 mutex_lock(&mvm
->mutex
);
96 ret
= iwl_mvm_flush_tx_path(mvm
, scd_q_msk
, true) ? : count
;
97 mutex_unlock(&mvm
->mutex
);
102 static ssize_t
iwl_dbgfs_sta_drain_write(struct file
*file
,
103 const char __user
*user_buf
,
104 size_t count
, loff_t
*ppos
)
106 struct iwl_mvm
*mvm
= file
->private_data
;
107 struct ieee80211_sta
*sta
;
110 int buf_size
, sta_id
, drain
, ret
;
112 if (!mvm
->ucode_loaded
|| mvm
->cur_ucode
!= IWL_UCODE_REGULAR
)
115 memset(buf
, 0, sizeof(buf
));
116 buf_size
= min(count
, sizeof(buf
) - 1);
117 if (copy_from_user(buf
, user_buf
, buf_size
))
120 if (sscanf(buf
, "%d %d", &sta_id
, &drain
) != 2)
123 mutex_lock(&mvm
->mutex
);
125 sta
= rcu_dereference_protected(mvm
->fw_id_to_mac_id
[sta_id
],
126 lockdep_is_held(&mvm
->mutex
));
127 if (IS_ERR_OR_NULL(sta
))
130 ret
= iwl_mvm_drain_sta(mvm
, (void *)sta
->drv_priv
, drain
) ? :
133 mutex_unlock(&mvm
->mutex
);
138 static ssize_t
iwl_dbgfs_sram_read(struct file
*file
, char __user
*user_buf
,
139 size_t count
, loff_t
*ppos
)
141 struct iwl_mvm
*mvm
= file
->private_data
;
142 const struct fw_img
*img
;
143 int ofs
, len
, pos
= 0;
148 if (!mvm
->ucode_loaded
)
151 /* default is to dump the entire data segment */
152 if (!mvm
->dbgfs_sram_offset
&& !mvm
->dbgfs_sram_len
) {
153 img
= &mvm
->fw
->img
[mvm
->cur_ucode
];
154 ofs
= img
->sec
[IWL_UCODE_SECTION_DATA
].offset
;
155 len
= img
->sec
[IWL_UCODE_SECTION_DATA
].len
;
157 ofs
= mvm
->dbgfs_sram_offset
;
158 len
= mvm
->dbgfs_sram_len
;
161 bufsz
= len
* 4 + 256;
162 buf
= kzalloc(bufsz
, GFP_KERNEL
);
166 ptr
= kzalloc(len
, GFP_KERNEL
);
172 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "sram_len: 0x%x\n", len
);
173 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "sram_offset: 0x%x\n", ofs
);
175 iwl_trans_read_mem_bytes(mvm
->trans
, ofs
, ptr
, len
);
176 for (ofs
= 0; ofs
< len
; ofs
+= 16) {
177 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "0x%.4x ", ofs
);
178 hex_dump_to_buffer(ptr
+ ofs
, 16, 16, 1, buf
+ pos
,
180 pos
+= strlen(buf
+ pos
);
185 ret
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
193 static ssize_t
iwl_dbgfs_sram_write(struct file
*file
,
194 const char __user
*user_buf
, size_t count
,
197 struct iwl_mvm
*mvm
= file
->private_data
;
202 memset(buf
, 0, sizeof(buf
));
203 buf_size
= min(count
, sizeof(buf
) - 1);
204 if (copy_from_user(buf
, user_buf
, buf_size
))
207 if (sscanf(buf
, "%x,%x", &offset
, &len
) == 2) {
208 if ((offset
& 0x3) || (len
& 0x3))
210 mvm
->dbgfs_sram_offset
= offset
;
211 mvm
->dbgfs_sram_len
= len
;
213 mvm
->dbgfs_sram_offset
= 0;
214 mvm
->dbgfs_sram_len
= 0;
220 static ssize_t
iwl_dbgfs_stations_read(struct file
*file
, char __user
*user_buf
,
221 size_t count
, loff_t
*ppos
)
223 struct iwl_mvm
*mvm
= file
->private_data
;
224 struct ieee80211_sta
*sta
;
226 int i
, pos
= 0, bufsz
= sizeof(buf
);
228 mutex_lock(&mvm
->mutex
);
230 for (i
= 0; i
< IWL_MVM_STATION_COUNT
; i
++) {
231 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "%.2d: ", i
);
232 sta
= rcu_dereference_protected(mvm
->fw_id_to_mac_id
[i
],
233 lockdep_is_held(&mvm
->mutex
));
235 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "N/A\n");
236 else if (IS_ERR(sta
))
237 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "%ld\n",
240 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "%pM\n",
244 mutex_unlock(&mvm
->mutex
);
246 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
249 static ssize_t
iwl_dbgfs_power_down_allow_write(struct file
*file
,
250 const char __user
*user_buf
,
251 size_t count
, loff_t
*ppos
)
253 struct iwl_mvm
*mvm
= file
->private_data
;
257 if (!mvm
->ucode_loaded
)
260 if (copy_from_user(buf
, user_buf
, sizeof(buf
)))
263 if (sscanf(buf
, "%d", &allow
) != 1)
266 IWL_DEBUG_POWER(mvm
, "%s device power down\n",
267 allow
? "allow" : "prevent");
270 * TODO: Send REPLY_DEBUG_CMD (0xf0) when FW support it
276 static ssize_t
iwl_dbgfs_power_down_d3_allow_write(struct file
*file
,
277 const char __user
*user_buf
,
278 size_t count
, loff_t
*ppos
)
280 struct iwl_mvm
*mvm
= file
->private_data
;
284 if (copy_from_user(buf
, user_buf
, sizeof(buf
)))
287 if (sscanf(buf
, "%d", &allow
) != 1)
290 IWL_DEBUG_POWER(mvm
, "%s device power down in d3\n",
291 allow
? "allow" : "prevent");
294 * TODO: When WoWLAN FW alive notification happens, driver will send
295 * REPLY_DEBUG_CMD setting power_down_allow flag according to
296 * mvm->prevent_power_down_d3
298 mvm
->prevent_power_down_d3
= !allow
;
303 static void iwl_dbgfs_update_pm(struct iwl_mvm
*mvm
,
304 struct ieee80211_vif
*vif
,
305 enum iwl_dbgfs_pm_mask param
, int val
)
307 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
308 struct iwl_dbgfs_pm
*dbgfs_pm
= &mvmvif
->dbgfs_pm
;
310 dbgfs_pm
->mask
|= param
;
313 case MVM_DEBUGFS_PM_KEEP_ALIVE
: {
314 struct ieee80211_hw
*hw
= mvm
->hw
;
315 int dtimper
= hw
->conf
.ps_dtim_period
?: 1;
316 int dtimper_msec
= dtimper
* vif
->bss_conf
.beacon_int
;
318 IWL_DEBUG_POWER(mvm
, "debugfs: set keep_alive= %d sec\n", val
);
319 if (val
* MSEC_PER_SEC
< 3 * dtimper_msec
) {
321 "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n",
322 val
* MSEC_PER_SEC
, 3 * dtimper_msec
);
324 dbgfs_pm
->keep_alive_seconds
= val
;
327 case MVM_DEBUGFS_PM_SKIP_OVER_DTIM
:
328 IWL_DEBUG_POWER(mvm
, "skip_over_dtim %s\n",
329 val
? "enabled" : "disabled");
330 dbgfs_pm
->skip_over_dtim
= val
;
332 case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS
:
333 IWL_DEBUG_POWER(mvm
, "skip_dtim_periods=%d\n", val
);
334 dbgfs_pm
->skip_dtim_periods
= val
;
336 case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT
:
337 IWL_DEBUG_POWER(mvm
, "rx_data_timeout=%d\n", val
);
338 dbgfs_pm
->rx_data_timeout
= val
;
340 case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT
:
341 IWL_DEBUG_POWER(mvm
, "tx_data_timeout=%d\n", val
);
342 dbgfs_pm
->tx_data_timeout
= val
;
344 case MVM_DEBUGFS_PM_DISABLE_POWER_OFF
:
345 IWL_DEBUG_POWER(mvm
, "disable_power_off=%d\n", val
);
346 dbgfs_pm
->disable_power_off
= val
;
347 case MVM_DEBUGFS_PM_LPRX_ENA
:
348 IWL_DEBUG_POWER(mvm
, "lprx %s\n", val
? "enabled" : "disabled");
349 dbgfs_pm
->lprx_ena
= val
;
351 case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD
:
352 IWL_DEBUG_POWER(mvm
, "lprx_rssi_threshold=%d\n", val
);
353 dbgfs_pm
->lprx_rssi_threshold
= val
;
358 static ssize_t
iwl_dbgfs_pm_params_write(struct file
*file
,
359 const char __user
*user_buf
,
360 size_t count
, loff_t
*ppos
)
362 struct ieee80211_vif
*vif
= file
->private_data
;
363 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
364 struct iwl_mvm
*mvm
= mvmvif
->dbgfs_data
;
365 enum iwl_dbgfs_pm_mask param
;
370 if (copy_from_user(buf
, user_buf
, sizeof(buf
)))
373 if (!strncmp("keep_alive=", buf
, 11)) {
374 if (sscanf(buf
+ 11, "%d", &val
) != 1)
376 param
= MVM_DEBUGFS_PM_KEEP_ALIVE
;
377 } else if (!strncmp("skip_over_dtim=", buf
, 15)) {
378 if (sscanf(buf
+ 15, "%d", &val
) != 1)
380 param
= MVM_DEBUGFS_PM_SKIP_OVER_DTIM
;
381 } else if (!strncmp("skip_dtim_periods=", buf
, 18)) {
382 if (sscanf(buf
+ 18, "%d", &val
) != 1)
384 param
= MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS
;
385 } else if (!strncmp("rx_data_timeout=", buf
, 16)) {
386 if (sscanf(buf
+ 16, "%d", &val
) != 1)
388 param
= MVM_DEBUGFS_PM_RX_DATA_TIMEOUT
;
389 } else if (!strncmp("tx_data_timeout=", buf
, 16)) {
390 if (sscanf(buf
+ 16, "%d", &val
) != 1)
392 param
= MVM_DEBUGFS_PM_TX_DATA_TIMEOUT
;
393 } else if (!strncmp("disable_power_off=", buf
, 18)) {
394 if (sscanf(buf
+ 18, "%d", &val
) != 1)
396 param
= MVM_DEBUGFS_PM_DISABLE_POWER_OFF
;
397 } else if (!strncmp("lprx=", buf
, 5)) {
398 if (sscanf(buf
+ 5, "%d", &val
) != 1)
400 param
= MVM_DEBUGFS_PM_LPRX_ENA
;
401 } else if (!strncmp("lprx_rssi_threshold=", buf
, 20)) {
402 if (sscanf(buf
+ 20, "%d", &val
) != 1)
404 if (val
> POWER_LPRX_RSSI_THRESHOLD_MAX
|| val
<
405 POWER_LPRX_RSSI_THRESHOLD_MIN
)
407 param
= MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD
;
412 mutex_lock(&mvm
->mutex
);
413 iwl_dbgfs_update_pm(mvm
, vif
, param
, val
);
414 ret
= iwl_mvm_power_update_mode(mvm
, vif
);
415 mutex_unlock(&mvm
->mutex
);
420 static ssize_t
iwl_dbgfs_pm_params_read(struct file
*file
,
421 char __user
*user_buf
,
422 size_t count
, loff_t
*ppos
)
424 struct ieee80211_vif
*vif
= file
->private_data
;
425 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
426 struct iwl_mvm
*mvm
= mvmvif
->dbgfs_data
;
427 struct iwl_powertable_cmd cmd
= {};
429 int bufsz
= sizeof(buf
);
432 iwl_mvm_power_build_cmd(mvm
, vif
, &cmd
);
434 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "disable_power_off = %d\n",
436 cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK
)) ?
438 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "skip_dtim_periods = %d\n",
439 le32_to_cpu(cmd
.skip_dtim_periods
));
440 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "power_scheme = %d\n",
441 iwlmvm_mod_params
.power_scheme
);
442 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "flags = 0x%x\n",
443 le16_to_cpu(cmd
.flags
));
444 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "keep_alive = %d\n",
445 cmd
.keep_alive_seconds
);
447 if (cmd
.flags
& cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK
)) {
448 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "skip_over_dtim = %d\n",
450 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK
)) ?
452 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "rx_data_timeout = %d\n",
453 le32_to_cpu(cmd
.rx_data_timeout
));
454 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "tx_data_timeout = %d\n",
455 le32_to_cpu(cmd
.tx_data_timeout
));
456 if (cmd
.flags
& cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK
))
457 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
458 "lprx_rssi_threshold = %d\n",
459 le32_to_cpu(cmd
.lprx_rssi_threshold
));
462 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
465 static ssize_t
iwl_dbgfs_mac_params_read(struct file
*file
,
466 char __user
*user_buf
,
467 size_t count
, loff_t
*ppos
)
469 struct ieee80211_vif
*vif
= file
->private_data
;
470 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
471 struct iwl_mvm
*mvm
= mvmvif
->dbgfs_data
;
473 struct ieee80211_chanctx_conf
*chanctx_conf
;
475 int bufsz
= sizeof(buf
);
479 mutex_lock(&mvm
->mutex
);
481 ap_sta_id
= mvmvif
->ap_sta_id
;
483 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "mac id/color: %d / %d\n",
484 mvmvif
->id
, mvmvif
->color
);
485 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bssid: %pM\n",
486 vif
->bss_conf
.bssid
);
487 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "QoS:\n");
488 for (i
= 0; i
< ARRAY_SIZE(mvmvif
->queue_params
); i
++) {
489 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
490 "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
491 i
, mvmvif
->queue_params
[i
].txop
,
492 mvmvif
->queue_params
[i
].cw_min
,
493 mvmvif
->queue_params
[i
].cw_max
,
494 mvmvif
->queue_params
[i
].aifs
,
495 mvmvif
->queue_params
[i
].uapsd
);
498 if (vif
->type
== NL80211_IFTYPE_STATION
&&
499 ap_sta_id
!= IWL_MVM_STATION_COUNT
) {
500 struct ieee80211_sta
*sta
;
501 struct iwl_mvm_sta
*mvm_sta
;
503 sta
= rcu_dereference_protected(mvm
->fw_id_to_mac_id
[ap_sta_id
],
504 lockdep_is_held(&mvm
->mutex
));
505 mvm_sta
= (void *)sta
->drv_priv
;
506 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
507 "ap_sta_id %d - reduced Tx power %d\n",
508 ap_sta_id
, mvm_sta
->bt_reduced_txpower
);
512 chanctx_conf
= rcu_dereference(vif
->chanctx_conf
);
514 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
515 "idle rx chains %d, active rx chains: %d\n",
516 chanctx_conf
->rx_chains_static
,
517 chanctx_conf
->rx_chains_dynamic
);
521 mutex_unlock(&mvm
->mutex
);
523 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
526 #define BT_MBOX_MSG(_notif, _num, _field) \
527 ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
528 >> BT_MBOX##_num##_##_field##_POS)
531 #define BT_MBOX_PRINT(_num, _field, _end) \
532 pos += scnprintf(buf + pos, bufsz - pos, \
535 BT_MBOX_MSG(notif, _num, _field), \
538 static ssize_t
iwl_dbgfs_bt_notif_read(struct file
*file
, char __user
*user_buf
,
539 size_t count
, loff_t
*ppos
)
541 struct iwl_mvm
*mvm
= file
->private_data
;
542 struct iwl_bt_coex_profile_notif
*notif
= &mvm
->last_bt_notif
;
544 int ret
, pos
= 0, bufsz
= sizeof(char) * 1024;
546 buf
= kmalloc(bufsz
, GFP_KERNEL
);
550 mutex_lock(&mvm
->mutex
);
552 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "MBOX dw0:\n");
554 BT_MBOX_PRINT(0, LE_SLAVE_LAT
, false);
555 BT_MBOX_PRINT(0, LE_PROF1
, false);
556 BT_MBOX_PRINT(0, LE_PROF2
, false);
557 BT_MBOX_PRINT(0, LE_PROF_OTHER
, false);
558 BT_MBOX_PRINT(0, CHL_SEQ_N
, false);
559 BT_MBOX_PRINT(0, INBAND_S
, false);
560 BT_MBOX_PRINT(0, LE_MIN_RSSI
, false);
561 BT_MBOX_PRINT(0, LE_SCAN
, false);
562 BT_MBOX_PRINT(0, LE_ADV
, false);
563 BT_MBOX_PRINT(0, LE_MAX_TX_POWER
, false);
564 BT_MBOX_PRINT(0, OPEN_CON_1
, true);
566 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "MBOX dw1:\n");
568 BT_MBOX_PRINT(1, BR_MAX_TX_POWER
, false);
569 BT_MBOX_PRINT(1, IP_SR
, false);
570 BT_MBOX_PRINT(1, LE_MSTR
, false);
571 BT_MBOX_PRINT(1, AGGR_TRFC_LD
, false);
572 BT_MBOX_PRINT(1, MSG_TYPE
, false);
573 BT_MBOX_PRINT(1, SSN
, true);
575 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "MBOX dw2:\n");
577 BT_MBOX_PRINT(2, SNIFF_ACT
, false);
578 BT_MBOX_PRINT(2, PAG
, false);
579 BT_MBOX_PRINT(2, INQUIRY
, false);
580 BT_MBOX_PRINT(2, CONN
, false);
581 BT_MBOX_PRINT(2, SNIFF_INTERVAL
, false);
582 BT_MBOX_PRINT(2, DISC
, false);
583 BT_MBOX_PRINT(2, SCO_TX_ACT
, false);
584 BT_MBOX_PRINT(2, SCO_RX_ACT
, false);
585 BT_MBOX_PRINT(2, ESCO_RE_TX
, false);
586 BT_MBOX_PRINT(2, SCO_DURATION
, true);
588 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "MBOX dw3:\n");
590 BT_MBOX_PRINT(3, SCO_STATE
, false);
591 BT_MBOX_PRINT(3, SNIFF_STATE
, false);
592 BT_MBOX_PRINT(3, A2DP_STATE
, false);
593 BT_MBOX_PRINT(3, ACL_STATE
, false);
594 BT_MBOX_PRINT(3, MSTR_STATE
, false);
595 BT_MBOX_PRINT(3, OBX_STATE
, false);
596 BT_MBOX_PRINT(3, OPEN_CON_2
, false);
597 BT_MBOX_PRINT(3, TRAFFIC_LOAD
, false);
598 BT_MBOX_PRINT(3, CHL_SEQN_LSB
, false);
599 BT_MBOX_PRINT(3, INBAND_P
, false);
600 BT_MBOX_PRINT(3, MSG_TYPE_2
, false);
601 BT_MBOX_PRINT(3, SSN_2
, false);
602 BT_MBOX_PRINT(3, UPDATE_REQUEST
, true);
604 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bt_status = %d\n",
606 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bt_open_conn = %d\n",
607 notif
->bt_open_conn
);
608 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bt_traffic_load = %d\n",
609 notif
->bt_traffic_load
);
610 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bt_agg_traffic_load = %d\n",
611 notif
->bt_agg_traffic_load
);
612 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bt_ci_compliance = %d\n",
613 notif
->bt_ci_compliance
);
615 mutex_unlock(&mvm
->mutex
);
617 ret
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
624 static ssize_t
iwl_dbgfs_fw_restart_write(struct file
*file
,
625 const char __user
*user_buf
,
626 size_t count
, loff_t
*ppos
)
628 struct iwl_mvm
*mvm
= file
->private_data
;
629 bool restart_fw
= iwlwifi_mod_params
.restart_fw
;
632 iwlwifi_mod_params
.restart_fw
= true;
634 mutex_lock(&mvm
->mutex
);
636 /* take the return value to make compiler happy - it will fail anyway */
637 ret
= iwl_mvm_send_cmd_pdu(mvm
, REPLY_ERROR
, CMD_SYNC
, 0, NULL
);
639 mutex_unlock(&mvm
->mutex
);
641 iwlwifi_mod_params
.restart_fw
= restart_fw
;
646 static void iwl_dbgfs_update_bf(struct ieee80211_vif
*vif
,
647 enum iwl_dbgfs_bf_mask param
, int value
)
649 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
650 struct iwl_dbgfs_bf
*dbgfs_bf
= &mvmvif
->dbgfs_bf
;
652 dbgfs_bf
->mask
|= param
;
655 case MVM_DEBUGFS_BF_ENERGY_DELTA
:
656 dbgfs_bf
->bf_energy_delta
= value
;
658 case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA
:
659 dbgfs_bf
->bf_roaming_energy_delta
= value
;
661 case MVM_DEBUGFS_BF_ROAMING_STATE
:
662 dbgfs_bf
->bf_roaming_state
= value
;
664 case MVM_DEBUGFS_BF_TEMPERATURE_DELTA
:
665 dbgfs_bf
->bf_temperature_delta
= value
;
667 case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
:
668 dbgfs_bf
->bf_enable_beacon_filter
= value
;
670 case MVM_DEBUGFS_BF_DEBUG_FLAG
:
671 dbgfs_bf
->bf_debug_flag
= value
;
673 case MVM_DEBUGFS_BF_ESCAPE_TIMER
:
674 dbgfs_bf
->bf_escape_timer
= value
;
676 case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT
:
677 dbgfs_bf
->ba_enable_beacon_abort
= value
;
679 case MVM_DEBUGFS_BA_ESCAPE_TIMER
:
680 dbgfs_bf
->ba_escape_timer
= value
;
685 static ssize_t
iwl_dbgfs_bf_params_write(struct file
*file
,
686 const char __user
*user_buf
,
687 size_t count
, loff_t
*ppos
)
689 struct ieee80211_vif
*vif
= file
->private_data
;
690 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
691 struct iwl_mvm
*mvm
= mvmvif
->dbgfs_data
;
692 enum iwl_dbgfs_bf_mask param
;
698 memset(buf
, 0, sizeof(buf
));
699 buf_size
= min(count
, sizeof(buf
) - 1);
700 if (copy_from_user(buf
, user_buf
, buf_size
))
703 if (!strncmp("bf_energy_delta=", buf
, 16)) {
704 if (sscanf(buf
+16, "%d", &value
) != 1)
706 if (value
< IWL_BF_ENERGY_DELTA_MIN
||
707 value
> IWL_BF_ENERGY_DELTA_MAX
)
709 param
= MVM_DEBUGFS_BF_ENERGY_DELTA
;
710 } else if (!strncmp("bf_roaming_energy_delta=", buf
, 24)) {
711 if (sscanf(buf
+24, "%d", &value
) != 1)
713 if (value
< IWL_BF_ROAMING_ENERGY_DELTA_MIN
||
714 value
> IWL_BF_ROAMING_ENERGY_DELTA_MAX
)
716 param
= MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA
;
717 } else if (!strncmp("bf_roaming_state=", buf
, 17)) {
718 if (sscanf(buf
+17, "%d", &value
) != 1)
720 if (value
< IWL_BF_ROAMING_STATE_MIN
||
721 value
> IWL_BF_ROAMING_STATE_MAX
)
723 param
= MVM_DEBUGFS_BF_ROAMING_STATE
;
724 } else if (!strncmp("bf_temperature_delta=", buf
, 21)) {
725 if (sscanf(buf
+21, "%d", &value
) != 1)
727 if (value
< IWL_BF_TEMPERATURE_DELTA_MIN
||
728 value
> IWL_BF_TEMPERATURE_DELTA_MAX
)
730 param
= MVM_DEBUGFS_BF_TEMPERATURE_DELTA
;
731 } else if (!strncmp("bf_enable_beacon_filter=", buf
, 24)) {
732 if (sscanf(buf
+24, "%d", &value
) != 1)
734 if (value
< 0 || value
> 1)
736 param
= MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
;
737 } else if (!strncmp("bf_debug_flag=", buf
, 14)) {
738 if (sscanf(buf
+14, "%d", &value
) != 1)
740 if (value
< 0 || value
> 1)
742 param
= MVM_DEBUGFS_BF_DEBUG_FLAG
;
743 } else if (!strncmp("bf_escape_timer=", buf
, 16)) {
744 if (sscanf(buf
+16, "%d", &value
) != 1)
746 if (value
< IWL_BF_ESCAPE_TIMER_MIN
||
747 value
> IWL_BF_ESCAPE_TIMER_MAX
)
749 param
= MVM_DEBUGFS_BF_ESCAPE_TIMER
;
750 } else if (!strncmp("ba_escape_timer=", buf
, 16)) {
751 if (sscanf(buf
+16, "%d", &value
) != 1)
753 if (value
< IWL_BA_ESCAPE_TIMER_MIN
||
754 value
> IWL_BA_ESCAPE_TIMER_MAX
)
756 param
= MVM_DEBUGFS_BA_ESCAPE_TIMER
;
757 } else if (!strncmp("ba_enable_beacon_abort=", buf
, 23)) {
758 if (sscanf(buf
+23, "%d", &value
) != 1)
760 if (value
< 0 || value
> 1)
762 param
= MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT
;
767 mutex_lock(&mvm
->mutex
);
768 iwl_dbgfs_update_bf(vif
, param
, value
);
769 if (param
== MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
&& !value
) {
770 ret
= iwl_mvm_disable_beacon_filter(mvm
, vif
);
772 if (mvmvif
->bf_enabled
)
773 ret
= iwl_mvm_enable_beacon_filter(mvm
, vif
);
775 ret
= iwl_mvm_disable_beacon_filter(mvm
, vif
);
777 mutex_unlock(&mvm
->mutex
);
782 static ssize_t
iwl_dbgfs_bf_params_read(struct file
*file
,
783 char __user
*user_buf
,
784 size_t count
, loff_t
*ppos
)
786 struct ieee80211_vif
*vif
= file
->private_data
;
787 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
790 const size_t bufsz
= sizeof(buf
);
791 struct iwl_beacon_filter_cmd cmd
= {
792 .bf_energy_delta
= IWL_BF_ENERGY_DELTA_DEFAULT
,
793 .bf_roaming_energy_delta
= IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT
,
794 .bf_roaming_state
= IWL_BF_ROAMING_STATE_DEFAULT
,
795 .bf_temperature_delta
= IWL_BF_TEMPERATURE_DELTA_DEFAULT
,
796 .bf_enable_beacon_filter
= IWL_BF_ENABLE_BEACON_FILTER_DEFAULT
,
797 .bf_debug_flag
= IWL_BF_DEBUG_FLAG_DEFAULT
,
798 .bf_escape_timer
= cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT
),
799 .ba_escape_timer
= cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT
),
800 .ba_enable_beacon_abort
= IWL_BA_ENABLE_BEACON_ABORT_DEFAULT
,
803 iwl_mvm_beacon_filter_debugfs_parameters(vif
, &cmd
);
804 if (mvmvif
->bf_enabled
)
805 cmd
.bf_enable_beacon_filter
= 1;
807 cmd
.bf_enable_beacon_filter
= 0;
809 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_energy_delta = %d\n",
810 cmd
.bf_energy_delta
);
811 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_roaming_energy_delta = %d\n",
812 cmd
.bf_roaming_energy_delta
);
813 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_roaming_state = %d\n",
814 cmd
.bf_roaming_state
);
815 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temperature_delta = %d\n",
816 cmd
.bf_temperature_delta
);
817 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_enable_beacon_filter = %d\n",
818 cmd
.bf_enable_beacon_filter
);
819 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_debug_flag = %d\n",
821 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_escape_timer = %d\n",
822 cmd
.bf_escape_timer
);
823 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "ba_escape_timer = %d\n",
824 cmd
.ba_escape_timer
);
825 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "ba_enable_beacon_abort = %d\n",
826 cmd
.ba_enable_beacon_abort
);
828 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
831 #ifdef CONFIG_PM_SLEEP
832 static ssize_t
iwl_dbgfs_d3_sram_write(struct file
*file
,
833 const char __user
*user_buf
,
834 size_t count
, loff_t
*ppos
)
836 struct iwl_mvm
*mvm
= file
->private_data
;
840 if (copy_from_user(buf
, user_buf
, sizeof(buf
)))
843 if (sscanf(buf
, "%d", &store
) != 1)
846 mvm
->store_d3_resume_sram
= store
;
851 static ssize_t
iwl_dbgfs_d3_sram_read(struct file
*file
, char __user
*user_buf
,
852 size_t count
, loff_t
*ppos
)
854 struct iwl_mvm
*mvm
= file
->private_data
;
855 const struct fw_img
*img
;
856 int ofs
, len
, pos
= 0;
859 u8
*ptr
= mvm
->d3_resume_sram
;
861 img
= &mvm
->fw
->img
[IWL_UCODE_WOWLAN
];
862 len
= img
->sec
[IWL_UCODE_SECTION_DATA
].len
;
864 bufsz
= len
* 4 + 256;
865 buf
= kzalloc(bufsz
, GFP_KERNEL
);
869 pos
+= scnprintf(buf
, bufsz
, "D3 SRAM capture: %sabled\n",
870 mvm
->store_d3_resume_sram
? "en" : "dis");
873 for (ofs
= 0; ofs
< len
; ofs
+= 16) {
874 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
876 hex_dump_to_buffer(ptr
+ ofs
, 16, 16, 1, buf
+ pos
,
878 pos
+= strlen(buf
+ pos
);
883 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
884 "(no data captured)\n");
887 ret
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
895 #define MVM_DEBUGFS_READ_FILE_OPS(name) \
896 static const struct file_operations iwl_dbgfs_##name##_ops = { \
897 .read = iwl_dbgfs_##name##_read, \
898 .open = simple_open, \
899 .llseek = generic_file_llseek, \
902 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name) \
903 static const struct file_operations iwl_dbgfs_##name##_ops = { \
904 .write = iwl_dbgfs_##name##_write, \
905 .read = iwl_dbgfs_##name##_read, \
906 .open = simple_open, \
907 .llseek = generic_file_llseek, \
910 #define MVM_DEBUGFS_WRITE_FILE_OPS(name) \
911 static const struct file_operations iwl_dbgfs_##name##_ops = { \
912 .write = iwl_dbgfs_##name##_write, \
913 .open = simple_open, \
914 .llseek = generic_file_llseek, \
917 #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) do { \
918 if (!debugfs_create_file(#name, mode, parent, mvm, \
919 &iwl_dbgfs_##name##_ops)) \
923 #define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \
924 if (!debugfs_create_file(#name, mode, parent, vif, \
925 &iwl_dbgfs_##name##_ops)) \
929 /* Device wide debugfs entries */
930 MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush
);
931 MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain
);
932 MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram
);
933 MVM_DEBUGFS_READ_FILE_OPS(stations
);
934 MVM_DEBUGFS_READ_FILE_OPS(bt_notif
);
935 MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow
);
936 MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow
);
937 MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart
);
938 #ifdef CONFIG_PM_SLEEP
939 MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram
);
942 /* Interface specific debugfs entries */
943 MVM_DEBUGFS_READ_FILE_OPS(mac_params
);
944 MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params
);
945 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params
);
947 int iwl_mvm_dbgfs_register(struct iwl_mvm
*mvm
, struct dentry
*dbgfs_dir
)
951 mvm
->debugfs_dir
= dbgfs_dir
;
953 MVM_DEBUGFS_ADD_FILE(tx_flush
, mvm
->debugfs_dir
, S_IWUSR
);
954 MVM_DEBUGFS_ADD_FILE(sta_drain
, mvm
->debugfs_dir
, S_IWUSR
);
955 MVM_DEBUGFS_ADD_FILE(sram
, mvm
->debugfs_dir
, S_IWUSR
| S_IRUSR
);
956 MVM_DEBUGFS_ADD_FILE(stations
, dbgfs_dir
, S_IRUSR
);
957 MVM_DEBUGFS_ADD_FILE(bt_notif
, dbgfs_dir
, S_IRUSR
);
958 MVM_DEBUGFS_ADD_FILE(power_down_allow
, mvm
->debugfs_dir
, S_IWUSR
);
959 MVM_DEBUGFS_ADD_FILE(power_down_d3_allow
, mvm
->debugfs_dir
, S_IWUSR
);
960 MVM_DEBUGFS_ADD_FILE(fw_restart
, mvm
->debugfs_dir
, S_IWUSR
);
961 #ifdef CONFIG_PM_SLEEP
962 MVM_DEBUGFS_ADD_FILE(d3_sram
, mvm
->debugfs_dir
, S_IRUSR
| S_IWUSR
);
963 MVM_DEBUGFS_ADD_FILE(d3_test
, mvm
->debugfs_dir
, S_IRUSR
);
964 if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR
| S_IWUSR
,
965 mvm
->debugfs_dir
, &mvm
->d3_wake_sysassert
))
970 * Create a symlink with mac80211. It will be removed when mac80211
971 * exists (before the opmode exists which removes the target.)
973 snprintf(buf
, 100, "../../%s/%s",
974 dbgfs_dir
->d_parent
->d_parent
->d_name
.name
,
975 dbgfs_dir
->d_parent
->d_name
.name
);
976 if (!debugfs_create_symlink("iwlwifi", mvm
->hw
->wiphy
->debugfsdir
, buf
))
981 IWL_ERR(mvm
, "Can't create the mvm debugfs directory\n");
985 void iwl_mvm_vif_dbgfs_register(struct iwl_mvm
*mvm
, struct ieee80211_vif
*vif
)
987 struct dentry
*dbgfs_dir
= vif
->debugfs_dir
;
988 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
994 mvmvif
->dbgfs_dir
= debugfs_create_dir("iwlmvm", dbgfs_dir
);
995 mvmvif
->dbgfs_data
= mvm
;
997 if (!mvmvif
->dbgfs_dir
) {
998 IWL_ERR(mvm
, "Failed to create debugfs directory under %s\n",
999 dbgfs_dir
->d_name
.name
);
1003 if (iwlmvm_mod_params
.power_scheme
!= IWL_POWER_SCHEME_CAM
&&
1004 vif
->type
== NL80211_IFTYPE_STATION
&& !vif
->p2p
)
1005 MVM_DEBUGFS_ADD_FILE_VIF(pm_params
, mvmvif
->dbgfs_dir
, S_IWUSR
|
1008 MVM_DEBUGFS_ADD_FILE_VIF(mac_params
, mvmvif
->dbgfs_dir
,
1011 if (vif
->type
== NL80211_IFTYPE_STATION
&& !vif
->p2p
&&
1012 mvmvif
== mvm
->bf_allowed_vif
)
1013 MVM_DEBUGFS_ADD_FILE_VIF(bf_params
, mvmvif
->dbgfs_dir
,
1017 * Create symlink for convenience pointing to interface specific
1018 * debugfs entries for the driver. For example, under
1019 * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
1021 * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
1023 snprintf(buf
, 100, "../../../%s/%s/%s/%s",
1024 dbgfs_dir
->d_parent
->d_parent
->d_name
.name
,
1025 dbgfs_dir
->d_parent
->d_name
.name
,
1026 dbgfs_dir
->d_name
.name
,
1027 mvmvif
->dbgfs_dir
->d_name
.name
);
1029 mvmvif
->dbgfs_slink
= debugfs_create_symlink(dbgfs_dir
->d_name
.name
,
1030 mvm
->debugfs_dir
, buf
);
1031 if (!mvmvif
->dbgfs_slink
)
1032 IWL_ERR(mvm
, "Can't create debugfs symbolic link under %s\n",
1033 dbgfs_dir
->d_name
.name
);
1036 IWL_ERR(mvm
, "Can't create debugfs entity\n");
1039 void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm
*mvm
, struct ieee80211_vif
*vif
)
1041 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1043 debugfs_remove(mvmvif
->dbgfs_slink
);
1044 mvmvif
->dbgfs_slink
= NULL
;
1046 debugfs_remove_recursive(mvmvif
->dbgfs_dir
);
1047 mvmvif
->dbgfs_dir
= NULL
;