iwlwifi: mvm: add d0i3_refs debugfs file
[pandora-kernel.git] / drivers / net / wireless / iwlwifi / mvm / debugfs.c
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  *
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.
13  *
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.
18  *
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,
22  * USA
23  *
24  * The full GNU General Public License is included in this distribution
25  * in the file called COPYING.
26  *
27  * Contact Information:
28  *  Intel Linux Wireless <ilw@linux.intel.com>
29  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30  *
31  * BSD LICENSE
32  *
33  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
34  * All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  *
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
45  *    distribution.
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.
49  *
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.
61  *
62  *****************************************************************************/
63 #include "mvm.h"
64 #include "sta.h"
65 #include "iwl-io.h"
66 #include "iwl-prph.h"
67 #include "debugfs.h"
68
69 static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
70                                         size_t count, loff_t *ppos)
71 {
72         int ret;
73         u32 scd_q_msk;
74
75         if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
76                 return -EIO;
77
78         if (sscanf(buf, "%x", &scd_q_msk) != 1)
79                 return -EINVAL;
80
81         IWL_ERR(mvm, "FLUSHING queues: scd_q_msk = 0x%x\n", scd_q_msk);
82
83         mutex_lock(&mvm->mutex);
84         ret =  iwl_mvm_flush_tx_path(mvm, scd_q_msk, true) ? : count;
85         mutex_unlock(&mvm->mutex);
86
87         return ret;
88 }
89
90 static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
91                                          size_t count, loff_t *ppos)
92 {
93         struct iwl_mvm_sta *mvmsta;
94         int sta_id, drain, ret;
95
96         if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
97                 return -EIO;
98
99         if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
100                 return -EINVAL;
101         if (sta_id < 0 || sta_id >= IWL_MVM_STATION_COUNT)
102                 return -EINVAL;
103         if (drain < 0 || drain > 1)
104                 return -EINVAL;
105
106         mutex_lock(&mvm->mutex);
107
108         mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
109
110         if (!mvmsta)
111                 ret = -ENOENT;
112         else
113                 ret = iwl_mvm_drain_sta(mvm, mvmsta, drain) ? : count;
114
115         mutex_unlock(&mvm->mutex);
116
117         return ret;
118 }
119
120 static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
121                                    size_t count, loff_t *ppos)
122 {
123         struct iwl_mvm *mvm = file->private_data;
124         const struct fw_img *img;
125         unsigned int ofs, len;
126         size_t ret;
127         u8 *ptr;
128
129         if (!mvm->ucode_loaded)
130                 return -EINVAL;
131
132         /* default is to dump the entire data segment */
133         img = &mvm->fw->img[mvm->cur_ucode];
134         ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
135         len = img->sec[IWL_UCODE_SECTION_DATA].len;
136
137         if (mvm->dbgfs_sram_len) {
138                 ofs = mvm->dbgfs_sram_offset;
139                 len = mvm->dbgfs_sram_len;
140         }
141
142         ptr = kzalloc(len, GFP_KERNEL);
143         if (!ptr)
144                 return -ENOMEM;
145
146         iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len);
147
148         ret = simple_read_from_buffer(user_buf, count, ppos, ptr, len);
149
150         kfree(ptr);
151
152         return ret;
153 }
154
155 static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf,
156                                     size_t count, loff_t *ppos)
157 {
158         const struct fw_img *img;
159         u32 offset, len;
160         u32 img_offset, img_len;
161
162         if (!mvm->ucode_loaded)
163                 return -EINVAL;
164
165         img = &mvm->fw->img[mvm->cur_ucode];
166         img_offset = img->sec[IWL_UCODE_SECTION_DATA].offset;
167         img_len = img->sec[IWL_UCODE_SECTION_DATA].len;
168
169         if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
170                 if ((offset & 0x3) || (len & 0x3))
171                         return -EINVAL;
172
173                 if (offset + len > img_offset + img_len)
174                         return -EINVAL;
175
176                 mvm->dbgfs_sram_offset = offset;
177                 mvm->dbgfs_sram_len = len;
178         } else {
179                 mvm->dbgfs_sram_offset = 0;
180                 mvm->dbgfs_sram_len = 0;
181         }
182
183         return count;
184 }
185
186 static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
187                                        size_t count, loff_t *ppos)
188 {
189         struct iwl_mvm *mvm = file->private_data;
190         struct ieee80211_sta *sta;
191         char buf[400];
192         int i, pos = 0, bufsz = sizeof(buf);
193
194         mutex_lock(&mvm->mutex);
195
196         for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
197                 pos += scnprintf(buf + pos, bufsz - pos, "%.2d: ", i);
198                 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
199                                                 lockdep_is_held(&mvm->mutex));
200                 if (!sta)
201                         pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
202                 else if (IS_ERR(sta))
203                         pos += scnprintf(buf + pos, bufsz - pos, "%ld\n",
204                                          PTR_ERR(sta));
205                 else
206                         pos += scnprintf(buf + pos, bufsz - pos, "%pM\n",
207                                          sta->addr);
208         }
209
210         mutex_unlock(&mvm->mutex);
211
212         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
213 }
214
215 static ssize_t iwl_dbgfs_disable_power_off_read(struct file *file,
216                                                 char __user *user_buf,
217                                                 size_t count, loff_t *ppos)
218 {
219         struct iwl_mvm *mvm = file->private_data;
220         char buf[64];
221         int bufsz = sizeof(buf);
222         int pos = 0;
223
224         pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d0=%d\n",
225                          mvm->disable_power_off);
226         pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d3=%d\n",
227                          mvm->disable_power_off_d3);
228
229         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
230 }
231
232 static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf,
233                                                  size_t count, loff_t *ppos)
234 {
235         int ret, val;
236
237         if (!mvm->ucode_loaded)
238                 return -EIO;
239
240         if (!strncmp("disable_power_off_d0=", buf, 21)) {
241                 if (sscanf(buf + 21, "%d", &val) != 1)
242                         return -EINVAL;
243                 mvm->disable_power_off = val;
244         } else if (!strncmp("disable_power_off_d3=", buf, 21)) {
245                 if (sscanf(buf + 21, "%d", &val) != 1)
246                         return -EINVAL;
247                 mvm->disable_power_off_d3 = val;
248         } else {
249                 return -EINVAL;
250         }
251
252         mutex_lock(&mvm->mutex);
253         ret = iwl_mvm_power_update_device_mode(mvm);
254         mutex_unlock(&mvm->mutex);
255
256         return ret ?: count;
257 }
258
259 #define BT_MBOX_MSG(_notif, _num, _field)                                    \
260         ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
261         >> BT_MBOX##_num##_##_field##_POS)
262
263
264 #define BT_MBOX_PRINT(_num, _field, _end)                                   \
265                         pos += scnprintf(buf + pos, bufsz - pos,            \
266                                          "\t%s: %d%s",                      \
267                                          #_field,                           \
268                                          BT_MBOX_MSG(notif, _num, _field),  \
269                                          true ? "\n" : ", ");
270
271 static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
272                                        size_t count, loff_t *ppos)
273 {
274         struct iwl_mvm *mvm = file->private_data;
275         struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
276         char *buf;
277         int ret, pos = 0, bufsz = sizeof(char) * 1024;
278
279         buf = kmalloc(bufsz, GFP_KERNEL);
280         if (!buf)
281                 return -ENOMEM;
282
283         mutex_lock(&mvm->mutex);
284
285         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n");
286
287         BT_MBOX_PRINT(0, LE_SLAVE_LAT, false);
288         BT_MBOX_PRINT(0, LE_PROF1, false);
289         BT_MBOX_PRINT(0, LE_PROF2, false);
290         BT_MBOX_PRINT(0, LE_PROF_OTHER, false);
291         BT_MBOX_PRINT(0, CHL_SEQ_N, false);
292         BT_MBOX_PRINT(0, INBAND_S, false);
293         BT_MBOX_PRINT(0, LE_MIN_RSSI, false);
294         BT_MBOX_PRINT(0, LE_SCAN, false);
295         BT_MBOX_PRINT(0, LE_ADV, false);
296         BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false);
297         BT_MBOX_PRINT(0, OPEN_CON_1, true);
298
299         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n");
300
301         BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false);
302         BT_MBOX_PRINT(1, IP_SR, false);
303         BT_MBOX_PRINT(1, LE_MSTR, false);
304         BT_MBOX_PRINT(1, AGGR_TRFC_LD, false);
305         BT_MBOX_PRINT(1, MSG_TYPE, false);
306         BT_MBOX_PRINT(1, SSN, true);
307
308         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n");
309
310         BT_MBOX_PRINT(2, SNIFF_ACT, false);
311         BT_MBOX_PRINT(2, PAG, false);
312         BT_MBOX_PRINT(2, INQUIRY, false);
313         BT_MBOX_PRINT(2, CONN, false);
314         BT_MBOX_PRINT(2, SNIFF_INTERVAL, false);
315         BT_MBOX_PRINT(2, DISC, false);
316         BT_MBOX_PRINT(2, SCO_TX_ACT, false);
317         BT_MBOX_PRINT(2, SCO_RX_ACT, false);
318         BT_MBOX_PRINT(2, ESCO_RE_TX, false);
319         BT_MBOX_PRINT(2, SCO_DURATION, true);
320
321         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n");
322
323         BT_MBOX_PRINT(3, SCO_STATE, false);
324         BT_MBOX_PRINT(3, SNIFF_STATE, false);
325         BT_MBOX_PRINT(3, A2DP_STATE, false);
326         BT_MBOX_PRINT(3, ACL_STATE, false);
327         BT_MBOX_PRINT(3, MSTR_STATE, false);
328         BT_MBOX_PRINT(3, OBX_STATE, false);
329         BT_MBOX_PRINT(3, OPEN_CON_2, false);
330         BT_MBOX_PRINT(3, TRAFFIC_LOAD, false);
331         BT_MBOX_PRINT(3, CHL_SEQN_LSB, false);
332         BT_MBOX_PRINT(3, INBAND_P, false);
333         BT_MBOX_PRINT(3, MSG_TYPE_2, false);
334         BT_MBOX_PRINT(3, SSN_2, false);
335         BT_MBOX_PRINT(3, UPDATE_REQUEST, true);
336
337         pos += scnprintf(buf+pos, bufsz-pos, "bt_status = %d\n",
338                          notif->bt_status);
339         pos += scnprintf(buf+pos, bufsz-pos, "bt_open_conn = %d\n",
340                          notif->bt_open_conn);
341         pos += scnprintf(buf+pos, bufsz-pos, "bt_traffic_load = %d\n",
342                          notif->bt_traffic_load);
343         pos += scnprintf(buf+pos, bufsz-pos, "bt_agg_traffic_load = %d\n",
344                          notif->bt_agg_traffic_load);
345         pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n",
346                          notif->bt_ci_compliance);
347         pos += scnprintf(buf+pos, bufsz-pos, "primary_ch_lut = %d\n",
348                          le32_to_cpu(notif->primary_ch_lut));
349         pos += scnprintf(buf+pos, bufsz-pos, "secondary_ch_lut = %d\n",
350                          le32_to_cpu(notif->secondary_ch_lut));
351         pos += scnprintf(buf+pos, bufsz-pos, "bt_activity_grading = %d\n",
352                          le32_to_cpu(notif->bt_activity_grading));
353
354         mutex_unlock(&mvm->mutex);
355
356         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
357         kfree(buf);
358
359         return ret;
360 }
361 #undef BT_MBOX_PRINT
362
363 static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
364                                      size_t count, loff_t *ppos)
365 {
366         struct iwl_mvm *mvm = file->private_data;
367         struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
368         char buf[256];
369         int bufsz = sizeof(buf);
370         int pos = 0;
371
372         mutex_lock(&mvm->mutex);
373
374         pos += scnprintf(buf+pos, bufsz-pos, "Channel inhibition CMD\n");
375         pos += scnprintf(buf+pos, bufsz-pos,
376                        "\tPrimary Channel Bitmap 0x%016llx Fat: %d\n",
377                        le64_to_cpu(cmd->bt_primary_ci),
378                        !!cmd->co_run_bw_primary);
379         pos += scnprintf(buf+pos, bufsz-pos,
380                        "\tSecondary Channel Bitmap 0x%016llx Fat: %d\n",
381                        le64_to_cpu(cmd->bt_secondary_ci),
382                        !!cmd->co_run_bw_secondary);
383
384         pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n");
385         pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n",
386                          iwl_bt_ack_kill_msk[mvm->bt_kill_msk]);
387         pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n",
388                          iwl_bt_cts_kill_msk[mvm->bt_kill_msk]);
389
390         mutex_unlock(&mvm->mutex);
391
392         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
393 }
394
395 #define PRINT_STATS_LE32(_str, _val)                                    \
396                          pos += scnprintf(buf + pos, bufsz - pos,       \
397                                           fmt_table, _str,              \
398                                           le32_to_cpu(_val))
399
400 static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
401                                           char __user *user_buf, size_t count,
402                                           loff_t *ppos)
403 {
404         struct iwl_mvm *mvm = file->private_data;
405         static const char *fmt_table = "\t%-30s %10u\n";
406         static const char *fmt_header = "%-32s\n";
407         int pos = 0;
408         char *buf;
409         int ret;
410         /* 43 is the size of each data line, 33 is the size of each header */
411         size_t bufsz =
412                 ((sizeof(struct mvm_statistics_rx) / sizeof(__le32)) * 43) +
413                 (4 * 33) + 1;
414
415         struct mvm_statistics_rx_phy *ofdm;
416         struct mvm_statistics_rx_phy *cck;
417         struct mvm_statistics_rx_non_phy *general;
418         struct mvm_statistics_rx_ht_phy *ht;
419
420         buf = kzalloc(bufsz, GFP_KERNEL);
421         if (!buf)
422                 return -ENOMEM;
423
424         mutex_lock(&mvm->mutex);
425
426         ofdm = &mvm->rx_stats.ofdm;
427         cck = &mvm->rx_stats.cck;
428         general = &mvm->rx_stats.general;
429         ht = &mvm->rx_stats.ofdm_ht;
430
431         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
432                          "Statistics_Rx - OFDM");
433         PRINT_STATS_LE32("ina_cnt", ofdm->ina_cnt);
434         PRINT_STATS_LE32("fina_cnt", ofdm->fina_cnt);
435         PRINT_STATS_LE32("plcp_err", ofdm->plcp_err);
436         PRINT_STATS_LE32("crc32_err", ofdm->crc32_err);
437         PRINT_STATS_LE32("overrun_err", ofdm->overrun_err);
438         PRINT_STATS_LE32("early_overrun_err", ofdm->early_overrun_err);
439         PRINT_STATS_LE32("crc32_good", ofdm->crc32_good);
440         PRINT_STATS_LE32("false_alarm_cnt", ofdm->false_alarm_cnt);
441         PRINT_STATS_LE32("fina_sync_err_cnt", ofdm->fina_sync_err_cnt);
442         PRINT_STATS_LE32("sfd_timeout", ofdm->sfd_timeout);
443         PRINT_STATS_LE32("fina_timeout", ofdm->fina_timeout);
444         PRINT_STATS_LE32("unresponded_rts", ofdm->unresponded_rts);
445         PRINT_STATS_LE32("rxe_frame_lmt_overrun",
446                          ofdm->rxe_frame_limit_overrun);
447         PRINT_STATS_LE32("sent_ack_cnt", ofdm->sent_ack_cnt);
448         PRINT_STATS_LE32("sent_cts_cnt", ofdm->sent_cts_cnt);
449         PRINT_STATS_LE32("sent_ba_rsp_cnt", ofdm->sent_ba_rsp_cnt);
450         PRINT_STATS_LE32("dsp_self_kill", ofdm->dsp_self_kill);
451         PRINT_STATS_LE32("mh_format_err", ofdm->mh_format_err);
452         PRINT_STATS_LE32("re_acq_main_rssi_sum", ofdm->re_acq_main_rssi_sum);
453         PRINT_STATS_LE32("reserved", ofdm->reserved);
454
455         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
456                          "Statistics_Rx - CCK");
457         PRINT_STATS_LE32("ina_cnt", cck->ina_cnt);
458         PRINT_STATS_LE32("fina_cnt", cck->fina_cnt);
459         PRINT_STATS_LE32("plcp_err", cck->plcp_err);
460         PRINT_STATS_LE32("crc32_err", cck->crc32_err);
461         PRINT_STATS_LE32("overrun_err", cck->overrun_err);
462         PRINT_STATS_LE32("early_overrun_err", cck->early_overrun_err);
463         PRINT_STATS_LE32("crc32_good", cck->crc32_good);
464         PRINT_STATS_LE32("false_alarm_cnt", cck->false_alarm_cnt);
465         PRINT_STATS_LE32("fina_sync_err_cnt", cck->fina_sync_err_cnt);
466         PRINT_STATS_LE32("sfd_timeout", cck->sfd_timeout);
467         PRINT_STATS_LE32("fina_timeout", cck->fina_timeout);
468         PRINT_STATS_LE32("unresponded_rts", cck->unresponded_rts);
469         PRINT_STATS_LE32("rxe_frame_lmt_overrun",
470                          cck->rxe_frame_limit_overrun);
471         PRINT_STATS_LE32("sent_ack_cnt", cck->sent_ack_cnt);
472         PRINT_STATS_LE32("sent_cts_cnt", cck->sent_cts_cnt);
473         PRINT_STATS_LE32("sent_ba_rsp_cnt", cck->sent_ba_rsp_cnt);
474         PRINT_STATS_LE32("dsp_self_kill", cck->dsp_self_kill);
475         PRINT_STATS_LE32("mh_format_err", cck->mh_format_err);
476         PRINT_STATS_LE32("re_acq_main_rssi_sum", cck->re_acq_main_rssi_sum);
477         PRINT_STATS_LE32("reserved", cck->reserved);
478
479         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
480                          "Statistics_Rx - GENERAL");
481         PRINT_STATS_LE32("bogus_cts", general->bogus_cts);
482         PRINT_STATS_LE32("bogus_ack", general->bogus_ack);
483         PRINT_STATS_LE32("non_bssid_frames", general->non_bssid_frames);
484         PRINT_STATS_LE32("filtered_frames", general->filtered_frames);
485         PRINT_STATS_LE32("non_channel_beacons", general->non_channel_beacons);
486         PRINT_STATS_LE32("channel_beacons", general->channel_beacons);
487         PRINT_STATS_LE32("num_missed_bcon", general->num_missed_bcon);
488         PRINT_STATS_LE32("adc_rx_saturation_time",
489                          general->adc_rx_saturation_time);
490         PRINT_STATS_LE32("ina_detection_search_time",
491                          general->ina_detection_search_time);
492         PRINT_STATS_LE32("beacon_silence_rssi_a",
493                          general->beacon_silence_rssi_a);
494         PRINT_STATS_LE32("beacon_silence_rssi_b",
495                          general->beacon_silence_rssi_b);
496         PRINT_STATS_LE32("beacon_silence_rssi_c",
497                          general->beacon_silence_rssi_c);
498         PRINT_STATS_LE32("interference_data_flag",
499                          general->interference_data_flag);
500         PRINT_STATS_LE32("channel_load", general->channel_load);
501         PRINT_STATS_LE32("dsp_false_alarms", general->dsp_false_alarms);
502         PRINT_STATS_LE32("beacon_rssi_a", general->beacon_rssi_a);
503         PRINT_STATS_LE32("beacon_rssi_b", general->beacon_rssi_b);
504         PRINT_STATS_LE32("beacon_rssi_c", general->beacon_rssi_c);
505         PRINT_STATS_LE32("beacon_energy_a", general->beacon_energy_a);
506         PRINT_STATS_LE32("beacon_energy_b", general->beacon_energy_b);
507         PRINT_STATS_LE32("beacon_energy_c", general->beacon_energy_c);
508         PRINT_STATS_LE32("num_bt_kills", general->num_bt_kills);
509         PRINT_STATS_LE32("mac_id", general->mac_id);
510         PRINT_STATS_LE32("directed_data_mpdu", general->directed_data_mpdu);
511
512         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
513                          "Statistics_Rx - HT");
514         PRINT_STATS_LE32("plcp_err", ht->plcp_err);
515         PRINT_STATS_LE32("overrun_err", ht->overrun_err);
516         PRINT_STATS_LE32("early_overrun_err", ht->early_overrun_err);
517         PRINT_STATS_LE32("crc32_good", ht->crc32_good);
518         PRINT_STATS_LE32("crc32_err", ht->crc32_err);
519         PRINT_STATS_LE32("mh_format_err", ht->mh_format_err);
520         PRINT_STATS_LE32("agg_crc32_good", ht->agg_crc32_good);
521         PRINT_STATS_LE32("agg_mpdu_cnt", ht->agg_mpdu_cnt);
522         PRINT_STATS_LE32("agg_cnt", ht->agg_cnt);
523         PRINT_STATS_LE32("unsupport_mcs", ht->unsupport_mcs);
524
525         mutex_unlock(&mvm->mutex);
526
527         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
528         kfree(buf);
529
530         return ret;
531 }
532 #undef PRINT_STAT_LE32
533
534 static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
535                                           size_t count, loff_t *ppos)
536 {
537         int ret;
538
539         mutex_lock(&mvm->mutex);
540
541         /* allow one more restart that we're provoking here */
542         if (mvm->restart_fw >= 0)
543                 mvm->restart_fw++;
544
545         /* take the return value to make compiler happy - it will fail anyway */
546         ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, CMD_SYNC, 0, NULL);
547
548         mutex_unlock(&mvm->mutex);
549
550         return count;
551 }
552
553 static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
554                                       size_t count, loff_t *ppos)
555 {
556         iwl_write_prph(mvm->trans, DEVICE_SET_NMI_REG, 1);
557
558         return count;
559 }
560
561 static ssize_t
562 iwl_dbgfs_scan_ant_rxchain_read(struct file *file,
563                                 char __user *user_buf,
564                                 size_t count, loff_t *ppos)
565 {
566         struct iwl_mvm *mvm = file->private_data;
567         int pos = 0;
568         char buf[32];
569         const size_t bufsz = sizeof(buf);
570
571         /* print which antennas were set for the scan command by the user */
572         pos += scnprintf(buf + pos, bufsz - pos, "Antennas for scan: ");
573         if (mvm->scan_rx_ant & ANT_A)
574                 pos += scnprintf(buf + pos, bufsz - pos, "A");
575         if (mvm->scan_rx_ant & ANT_B)
576                 pos += scnprintf(buf + pos, bufsz - pos, "B");
577         if (mvm->scan_rx_ant & ANT_C)
578                 pos += scnprintf(buf + pos, bufsz - pos, "C");
579         pos += scnprintf(buf + pos, bufsz - pos, " (%hhx)\n", mvm->scan_rx_ant);
580
581         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
582 }
583
584 static ssize_t
585 iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
586                                  size_t count, loff_t *ppos)
587 {
588         u8 scan_rx_ant;
589
590         if (sscanf(buf, "%hhx", &scan_rx_ant) != 1)
591                 return -EINVAL;
592         if (scan_rx_ant > ANT_ABC)
593                 return -EINVAL;
594         if (scan_rx_ant & ~iwl_fw_valid_rx_ant(mvm->fw))
595                 return -EINVAL;
596
597         mvm->scan_rx_ant = scan_rx_ant;
598
599         return count;
600 }
601
602 #define ADD_TEXT(...) pos += scnprintf(buf + pos, bufsz - pos, __VA_ARGS__)
603 #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
604 static ssize_t iwl_dbgfs_bcast_filters_read(struct file *file,
605                                             char __user *user_buf,
606                                             size_t count, loff_t *ppos)
607 {
608         struct iwl_mvm *mvm = file->private_data;
609         struct iwl_bcast_filter_cmd cmd;
610         const struct iwl_fw_bcast_filter *filter;
611         char *buf;
612         int bufsz = 1024;
613         int i, j, pos = 0;
614         ssize_t ret;
615
616         buf = kzalloc(bufsz, GFP_KERNEL);
617         if (!buf)
618                 return -ENOMEM;
619
620         mutex_lock(&mvm->mutex);
621         if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) {
622                 ADD_TEXT("None\n");
623                 mutex_unlock(&mvm->mutex);
624                 goto out;
625         }
626         mutex_unlock(&mvm->mutex);
627
628         for (i = 0; cmd.filters[i].attrs[0].mask; i++) {
629                 filter = &cmd.filters[i];
630
631                 ADD_TEXT("Filter [%d]:\n", i);
632                 ADD_TEXT("\tDiscard=%d\n", filter->discard);
633                 ADD_TEXT("\tFrame Type: %s\n",
634                          filter->frame_type ? "IPv4" : "Generic");
635
636                 for (j = 0; j < ARRAY_SIZE(filter->attrs); j++) {
637                         const struct iwl_fw_bcast_filter_attr *attr;
638
639                         attr = &filter->attrs[j];
640                         if (!attr->mask)
641                                 break;
642
643                         ADD_TEXT("\tAttr [%d]: offset=%d (from %s), mask=0x%x, value=0x%x reserved=0x%x\n",
644                                  j, attr->offset,
645                                  attr->offset_type ? "IP End" :
646                                                      "Payload Start",
647                                  be32_to_cpu(attr->mask),
648                                  be32_to_cpu(attr->val),
649                                  le16_to_cpu(attr->reserved1));
650                 }
651         }
652 out:
653         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
654         kfree(buf);
655         return ret;
656 }
657
658 static ssize_t iwl_dbgfs_bcast_filters_write(struct iwl_mvm *mvm, char *buf,
659                                              size_t count, loff_t *ppos)
660 {
661         int pos, next_pos;
662         struct iwl_fw_bcast_filter filter = {};
663         struct iwl_bcast_filter_cmd cmd;
664         u32 filter_id, attr_id, mask, value;
665         int err = 0;
666
667         if (sscanf(buf, "%d %hhi %hhi %n", &filter_id, &filter.discard,
668                    &filter.frame_type, &pos) != 3)
669                 return -EINVAL;
670
671         if (filter_id >= ARRAY_SIZE(mvm->dbgfs_bcast_filtering.cmd.filters) ||
672             filter.frame_type > BCAST_FILTER_FRAME_TYPE_IPV4)
673                 return -EINVAL;
674
675         for (attr_id = 0; attr_id < ARRAY_SIZE(filter.attrs);
676              attr_id++) {
677                 struct iwl_fw_bcast_filter_attr *attr =
678                                 &filter.attrs[attr_id];
679
680                 if (pos >= count)
681                         break;
682
683                 if (sscanf(&buf[pos], "%hhi %hhi %i %i %n",
684                            &attr->offset, &attr->offset_type,
685                            &mask, &value, &next_pos) != 4)
686                         return -EINVAL;
687
688                 attr->mask = cpu_to_be32(mask);
689                 attr->val = cpu_to_be32(value);
690                 if (mask)
691                         filter.num_attrs++;
692
693                 pos += next_pos;
694         }
695
696         mutex_lock(&mvm->mutex);
697         memcpy(&mvm->dbgfs_bcast_filtering.cmd.filters[filter_id],
698                &filter, sizeof(filter));
699
700         /* send updated bcast filtering configuration */
701         if (mvm->dbgfs_bcast_filtering.override &&
702             iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
703                 err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, CMD_SYNC,
704                                            sizeof(cmd), &cmd);
705         mutex_unlock(&mvm->mutex);
706
707         return err ?: count;
708 }
709
710 static ssize_t iwl_dbgfs_bcast_filters_macs_read(struct file *file,
711                                                  char __user *user_buf,
712                                                  size_t count, loff_t *ppos)
713 {
714         struct iwl_mvm *mvm = file->private_data;
715         struct iwl_bcast_filter_cmd cmd;
716         char *buf;
717         int bufsz = 1024;
718         int i, pos = 0;
719         ssize_t ret;
720
721         buf = kzalloc(bufsz, GFP_KERNEL);
722         if (!buf)
723                 return -ENOMEM;
724
725         mutex_lock(&mvm->mutex);
726         if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) {
727                 ADD_TEXT("None\n");
728                 mutex_unlock(&mvm->mutex);
729                 goto out;
730         }
731         mutex_unlock(&mvm->mutex);
732
733         for (i = 0; i < ARRAY_SIZE(cmd.macs); i++) {
734                 const struct iwl_fw_bcast_mac *mac = &cmd.macs[i];
735
736                 ADD_TEXT("Mac [%d]: discard=%d attached_filters=0x%x\n",
737                          i, mac->default_discard, mac->attached_filters);
738         }
739 out:
740         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
741         kfree(buf);
742         return ret;
743 }
744
745 static ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm,
746                                                   char *buf, size_t count,
747                                                   loff_t *ppos)
748 {
749         struct iwl_bcast_filter_cmd cmd;
750         struct iwl_fw_bcast_mac mac = {};
751         u32 mac_id, attached_filters;
752         int err = 0;
753
754         if (!mvm->bcast_filters)
755                 return -ENOENT;
756
757         if (sscanf(buf, "%d %hhi %i", &mac_id, &mac.default_discard,
758                    &attached_filters) != 3)
759                 return -EINVAL;
760
761         if (mac_id >= ARRAY_SIZE(cmd.macs) ||
762             mac.default_discard > 1 ||
763             attached_filters >= BIT(ARRAY_SIZE(cmd.filters)))
764                 return -EINVAL;
765
766         mac.attached_filters = cpu_to_le16(attached_filters);
767
768         mutex_lock(&mvm->mutex);
769         memcpy(&mvm->dbgfs_bcast_filtering.cmd.macs[mac_id],
770                &mac, sizeof(mac));
771
772         /* send updated bcast filtering configuration */
773         if (mvm->dbgfs_bcast_filtering.override &&
774             iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
775                 err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, CMD_SYNC,
776                                            sizeof(cmd), &cmd);
777         mutex_unlock(&mvm->mutex);
778
779         return err ?: count;
780 }
781 #endif
782
783 #ifdef CONFIG_PM_SLEEP
784 static ssize_t iwl_dbgfs_d3_sram_write(struct iwl_mvm *mvm, char *buf,
785                                        size_t count, loff_t *ppos)
786 {
787         int store;
788
789         if (sscanf(buf, "%d", &store) != 1)
790                 return -EINVAL;
791
792         mvm->store_d3_resume_sram = store;
793
794         return count;
795 }
796
797 static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
798                                       size_t count, loff_t *ppos)
799 {
800         struct iwl_mvm *mvm = file->private_data;
801         const struct fw_img *img;
802         int ofs, len, pos = 0;
803         size_t bufsz, ret;
804         char *buf;
805         u8 *ptr = mvm->d3_resume_sram;
806
807         img = &mvm->fw->img[IWL_UCODE_WOWLAN];
808         len = img->sec[IWL_UCODE_SECTION_DATA].len;
809
810         bufsz = len * 4 + 256;
811         buf = kzalloc(bufsz, GFP_KERNEL);
812         if (!buf)
813                 return -ENOMEM;
814
815         pos += scnprintf(buf, bufsz, "D3 SRAM capture: %sabled\n",
816                          mvm->store_d3_resume_sram ? "en" : "dis");
817
818         if (ptr) {
819                 for (ofs = 0; ofs < len; ofs += 16) {
820                         pos += scnprintf(buf + pos, bufsz - pos,
821                                          "0x%.4x ", ofs);
822                         hex_dump_to_buffer(ptr + ofs, 16, 16, 1, buf + pos,
823                                            bufsz - pos, false);
824                         pos += strlen(buf + pos);
825                         if (bufsz - pos > 0)
826                                 buf[pos++] = '\n';
827                 }
828         } else {
829                 pos += scnprintf(buf + pos, bufsz - pos,
830                                  "(no data captured)\n");
831         }
832
833         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
834
835         kfree(buf);
836
837         return ret;
838 }
839 #endif
840
841 #define PRINT_MVM_REF(ref) do {                                 \
842         if (test_bit(ref, mvm->ref_bitmap))                     \
843                 pos += scnprintf(buf + pos, bufsz - pos,        \
844                                  "\t(0x%lx) %s\n",              \
845                                  BIT(ref), #ref);               \
846 } while (0)
847
848 static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
849                                         char __user *user_buf,
850                                         size_t count, loff_t *ppos)
851 {
852         struct iwl_mvm *mvm = file->private_data;
853         int pos = 0;
854         char buf[256];
855         const size_t bufsz = sizeof(buf);
856
857         pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%lx\n",
858                          mvm->ref_bitmap[0]);
859
860         PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN);
861         PRINT_MVM_REF(IWL_MVM_REF_SCAN);
862         PRINT_MVM_REF(IWL_MVM_REF_ROC);
863         PRINT_MVM_REF(IWL_MVM_REF_P2P_CLIENT);
864         PRINT_MVM_REF(IWL_MVM_REF_AP_IBSS);
865
866         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
867 }
868
869 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
870         _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
871 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
872         _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
873 #define MVM_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do {      \
874                 if (!debugfs_create_file(alias, mode, parent, mvm,      \
875                                          &iwl_dbgfs_##name##_ops))      \
876                         goto err;                                       \
877         } while (0)
878 #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \
879         MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
880
881 /* Device wide debugfs entries */
882 MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
883 MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8);
884 MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64);
885 MVM_DEBUGFS_READ_FILE_OPS(stations);
886 MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
887 MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
888 MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
889 MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
890 MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
891 MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
892 MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
893 MVM_DEBUGFS_READ_FILE_OPS(d0i3_refs);
894
895 #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
896 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
897 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
898 #endif
899
900 #ifdef CONFIG_PM_SLEEP
901 MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
902 #endif
903
904 int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
905 {
906         struct dentry *bcast_dir __maybe_unused;
907         char buf[100];
908
909         mvm->debugfs_dir = dbgfs_dir;
910
911         MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, S_IWUSR);
912         MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR);
913         MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
914         MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR);
915         MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR);
916         MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR);
917         if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)
918                 MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir,
919                                      S_IRUSR | S_IWUSR);
920         MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR);
921         MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
922         MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR);
923         MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir,
924                              S_IWUSR | S_IRUSR);
925         MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR);
926
927 #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
928         if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) {
929                 bcast_dir = debugfs_create_dir("bcast_filtering",
930                                                mvm->debugfs_dir);
931                 if (!bcast_dir)
932                         goto err;
933
934                 if (!debugfs_create_bool("override", S_IRUSR | S_IWUSR,
935                                 bcast_dir,
936                                 &mvm->dbgfs_bcast_filtering.override))
937                         goto err;
938
939                 MVM_DEBUGFS_ADD_FILE_ALIAS("filters", bcast_filters,
940                                            bcast_dir, S_IWUSR | S_IRUSR);
941                 MVM_DEBUGFS_ADD_FILE_ALIAS("macs", bcast_filters_macs,
942                                            bcast_dir, S_IWUSR | S_IRUSR);
943         }
944 #endif
945
946 #ifdef CONFIG_PM_SLEEP
947         MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
948         MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR);
949         if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR | S_IWUSR,
950                                  mvm->debugfs_dir, &mvm->d3_wake_sysassert))
951                 goto err;
952 #endif
953
954         if (!debugfs_create_blob("nvm_hw", S_IRUSR,
955                                   mvm->debugfs_dir, &mvm->nvm_hw_blob))
956                 goto err;
957         if (!debugfs_create_blob("nvm_sw", S_IRUSR,
958                                   mvm->debugfs_dir, &mvm->nvm_sw_blob))
959                 goto err;
960         if (!debugfs_create_blob("nvm_calib", S_IRUSR,
961                                   mvm->debugfs_dir, &mvm->nvm_calib_blob))
962                 goto err;
963         if (!debugfs_create_blob("nvm_prod", S_IRUSR,
964                                   mvm->debugfs_dir, &mvm->nvm_prod_blob))
965                 goto err;
966
967         /*
968          * Create a symlink with mac80211. It will be removed when mac80211
969          * exists (before the opmode exists which removes the target.)
970          */
971         snprintf(buf, 100, "../../%s/%s",
972                  dbgfs_dir->d_parent->d_parent->d_name.name,
973                  dbgfs_dir->d_parent->d_name.name);
974         if (!debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir, buf))
975                 goto err;
976
977         return 0;
978 err:
979         IWL_ERR(mvm, "Can't create the mvm debugfs directory\n");
980         return -ENOMEM;
981 }