aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-11-12 10:58:41 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2013-12-09 15:29:03 -0500
commit820a1a50025550061b0d0ea15a760ecd183886f7 (patch)
treeff1762986d23fd9e4c78ff411627e8eac443299a
parent8a0bd168fa750d7c57d3494b331e9fb2b0bbd928 (diff)
iwlwifi: mvm: move interface-specific debugfs to a new file
The debugfs file is getting pretty large and mixed up between code for the hardware and code for each interface (the two aren't even clearly separated in the code). Make it easier to handle by splitting the per-interface code into a separate file called debugfs-vif.c. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/Makefile1
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c190
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c505
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.h84
4 files changed, 276 insertions, 504 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile
index 6d73817850ce..285d8c7486f5 100644
--- a/drivers/net/wireless/iwlwifi/mvm/Makefile
+++ b/drivers/net/wireless/iwlwifi/mvm/Makefile
@@ -5,6 +5,7 @@ iwlmvm-y += scan.o time-event.o rs.o
5iwlmvm-y += power.o power_legacy.o bt-coex.o 5iwlmvm-y += power.o power_legacy.o bt-coex.o
6iwlmvm-y += led.o tt.o 6iwlmvm-y += led.o tt.o
7iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o 7iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
8iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
8iwlmvm-$(CONFIG_PM_SLEEP) += d3.o 9iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
9 10
10ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../ 11ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
new file mode 100644
index 000000000000..a90dde0f8d6c
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
@@ -0,0 +1,190 @@
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 - 2013 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 - 2013 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 "debugfs.h"
65
66static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
67 char __user *user_buf,
68 size_t count, loff_t *ppos)
69{
70 struct ieee80211_vif *vif = file->private_data;
71 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
72 struct iwl_mvm *mvm = mvmvif->dbgfs_data;
73 u8 ap_sta_id;
74 struct ieee80211_chanctx_conf *chanctx_conf;
75 char buf[512];
76 int bufsz = sizeof(buf);
77 int pos = 0;
78 int i;
79
80 mutex_lock(&mvm->mutex);
81
82 ap_sta_id = mvmvif->ap_sta_id;
83
84 pos += scnprintf(buf+pos, bufsz-pos, "mac id/color: %d / %d\n",
85 mvmvif->id, mvmvif->color);
86 pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n",
87 vif->bss_conf.bssid);
88 pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n");
89 for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++)
90 pos += scnprintf(buf+pos, bufsz-pos,
91 "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
92 i, mvmvif->queue_params[i].txop,
93 mvmvif->queue_params[i].cw_min,
94 mvmvif->queue_params[i].cw_max,
95 mvmvif->queue_params[i].aifs,
96 mvmvif->queue_params[i].uapsd);
97
98 if (vif->type == NL80211_IFTYPE_STATION &&
99 ap_sta_id != IWL_MVM_STATION_COUNT) {
100 struct ieee80211_sta *sta;
101 struct iwl_mvm_sta *mvm_sta;
102
103 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id],
104 lockdep_is_held(&mvm->mutex));
105 mvm_sta = (void *)sta->drv_priv;
106 pos += scnprintf(buf+pos, bufsz-pos,
107 "ap_sta_id %d - reduced Tx power %d\n",
108 ap_sta_id, mvm_sta->bt_reduced_txpower);
109 }
110
111 rcu_read_lock();
112 chanctx_conf = rcu_dereference(vif->chanctx_conf);
113 if (chanctx_conf)
114 pos += scnprintf(buf+pos, bufsz-pos,
115 "idle rx chains %d, active rx chains: %d\n",
116 chanctx_conf->rx_chains_static,
117 chanctx_conf->rx_chains_dynamic);
118 rcu_read_unlock();
119
120 mutex_unlock(&mvm->mutex);
121
122 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
123}
124
125#define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \
126 if (!debugfs_create_file(#name, mode, parent, vif, \
127 &iwl_dbgfs_##name##_ops)) \
128 goto err; \
129 } while (0)
130
131MVM_DEBUGFS_READ_FILE_OPS(mac_params);
132
133void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
134{
135 struct dentry *dbgfs_dir = vif->debugfs_dir;
136 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
137 char buf[100];
138
139 /*
140 * Check if debugfs directory already exist before creating it.
141 * This may happen when, for example, resetting hw or suspend-resume
142 */
143 if (!dbgfs_dir || mvmvif->dbgfs_dir)
144 return;
145
146 mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
147 mvmvif->dbgfs_data = mvm;
148
149 if (!mvmvif->dbgfs_dir) {
150 IWL_ERR(mvm, "Failed to create debugfs directory under %s\n",
151 dbgfs_dir->d_name.name);
152 return;
153 }
154
155 MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir,
156 S_IRUSR);
157
158 /*
159 * Create symlink for convenience pointing to interface specific
160 * debugfs entries for the driver. For example, under
161 * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
162 * find
163 * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
164 */
165 snprintf(buf, 100, "../../../%s/%s/%s/%s",
166 dbgfs_dir->d_parent->d_parent->d_name.name,
167 dbgfs_dir->d_parent->d_name.name,
168 dbgfs_dir->d_name.name,
169 mvmvif->dbgfs_dir->d_name.name);
170
171 mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name,
172 mvm->debugfs_dir, buf);
173 if (!mvmvif->dbgfs_slink)
174 IWL_ERR(mvm, "Can't create debugfs symbolic link under %s\n",
175 dbgfs_dir->d_name.name);
176 return;
177err:
178 IWL_ERR(mvm, "Can't create debugfs entity\n");
179}
180
181void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
182{
183 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
184
185 debugfs_remove(mvmvif->dbgfs_slink);
186 mvmvif->dbgfs_slink = NULL;
187
188 debugfs_remove_recursive(mvmvif->dbgfs_dir);
189 mvmvif->dbgfs_dir = NULL;
190}
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index a34fb80422c0..6850a2d94bcb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -64,6 +64,7 @@
64#include "sta.h" 64#include "sta.h"
65#include "iwl-io.h" 65#include "iwl-io.h"
66#include "iwl-prph.h" 66#include "iwl-prph.h"
67#include "debugfs.h"
67 68
68static ssize_t iwl_dbgfs_tx_flush_write(struct file *file, 69static ssize_t iwl_dbgfs_tx_flush_write(struct file *file,
69 const char __user *user_buf, 70 const char __user *user_buf,
@@ -292,209 +293,6 @@ static ssize_t iwl_dbgfs_disable_power_off_write(struct file *file,
292 return ret ?: count; 293 return ret ?: count;
293} 294}
294 295
295static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
296 struct ieee80211_vif *vif,
297 enum iwl_dbgfs_pm_mask param, int val)
298{
299 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
300 struct iwl_dbgfs_pm *dbgfs_pm = &mvmvif->dbgfs_pm;
301
302 dbgfs_pm->mask |= param;
303
304 switch (param) {
305 case MVM_DEBUGFS_PM_KEEP_ALIVE: {
306 struct ieee80211_hw *hw = mvm->hw;
307 int dtimper = hw->conf.ps_dtim_period ?: 1;
308 int dtimper_msec = dtimper * vif->bss_conf.beacon_int;
309
310 IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val);
311 if (val * MSEC_PER_SEC < 3 * dtimper_msec)
312 IWL_WARN(mvm,
313 "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n",
314 val * MSEC_PER_SEC, 3 * dtimper_msec);
315 dbgfs_pm->keep_alive_seconds = val;
316 break;
317 }
318 case MVM_DEBUGFS_PM_SKIP_OVER_DTIM:
319 IWL_DEBUG_POWER(mvm, "skip_over_dtim %s\n",
320 val ? "enabled" : "disabled");
321 dbgfs_pm->skip_over_dtim = val;
322 break;
323 case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS:
324 IWL_DEBUG_POWER(mvm, "skip_dtim_periods=%d\n", val);
325 dbgfs_pm->skip_dtim_periods = val;
326 break;
327 case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT:
328 IWL_DEBUG_POWER(mvm, "rx_data_timeout=%d\n", val);
329 dbgfs_pm->rx_data_timeout = val;
330 break;
331 case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT:
332 IWL_DEBUG_POWER(mvm, "tx_data_timeout=%d\n", val);
333 dbgfs_pm->tx_data_timeout = val;
334 break;
335 case MVM_DEBUGFS_PM_DISABLE_POWER_OFF:
336 IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val);
337 dbgfs_pm->disable_power_off = val;
338 break;
339 case MVM_DEBUGFS_PM_LPRX_ENA:
340 IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled");
341 dbgfs_pm->lprx_ena = val;
342 break;
343 case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD:
344 IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val);
345 dbgfs_pm->lprx_rssi_threshold = val;
346 break;
347 case MVM_DEBUGFS_PM_SNOOZE_ENABLE:
348 IWL_DEBUG_POWER(mvm, "snooze_enable=%d\n", val);
349 dbgfs_pm->snooze_ena = val;
350 break;
351 }
352}
353
354static ssize_t iwl_dbgfs_pm_params_write(struct file *file,
355 const char __user *user_buf,
356 size_t count, loff_t *ppos)
357{
358 struct ieee80211_vif *vif = file->private_data;
359 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
360 struct iwl_mvm *mvm = mvmvif->dbgfs_data;
361 enum iwl_dbgfs_pm_mask param;
362 char buf[32] = {};
363 size_t buf_size = min(count, sizeof(buf) - 1);
364 int val;
365 int ret;
366
367 if (copy_from_user(buf, user_buf, buf_size))
368 return -EFAULT;
369
370 if (!strncmp("keep_alive=", buf, 11)) {
371 if (sscanf(buf + 11, "%d", &val) != 1)
372 return -EINVAL;
373 param = MVM_DEBUGFS_PM_KEEP_ALIVE;
374 } else if (!strncmp("skip_over_dtim=", buf, 15)) {
375 if (sscanf(buf + 15, "%d", &val) != 1)
376 return -EINVAL;
377 param = MVM_DEBUGFS_PM_SKIP_OVER_DTIM;
378 } else if (!strncmp("skip_dtim_periods=", buf, 18)) {
379 if (sscanf(buf + 18, "%d", &val) != 1)
380 return -EINVAL;
381 param = MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS;
382 } else if (!strncmp("rx_data_timeout=", buf, 16)) {
383 if (sscanf(buf + 16, "%d", &val) != 1)
384 return -EINVAL;
385 param = MVM_DEBUGFS_PM_RX_DATA_TIMEOUT;
386 } else if (!strncmp("tx_data_timeout=", buf, 16)) {
387 if (sscanf(buf + 16, "%d", &val) != 1)
388 return -EINVAL;
389 param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT;
390 } else if (!strncmp("disable_power_off=", buf, 18) &&
391 !(mvm->fw->ucode_capa.flags &
392 IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) {
393 if (sscanf(buf + 18, "%d", &val) != 1)
394 return -EINVAL;
395 param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF;
396 } else if (!strncmp("lprx=", buf, 5)) {
397 if (sscanf(buf + 5, "%d", &val) != 1)
398 return -EINVAL;
399 param = MVM_DEBUGFS_PM_LPRX_ENA;
400 } else if (!strncmp("lprx_rssi_threshold=", buf, 20)) {
401 if (sscanf(buf + 20, "%d", &val) != 1)
402 return -EINVAL;
403 if (val > POWER_LPRX_RSSI_THRESHOLD_MAX || val <
404 POWER_LPRX_RSSI_THRESHOLD_MIN)
405 return -EINVAL;
406 param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD;
407 } else if (!strncmp("snooze_enable=", buf, 14)) {
408 if (sscanf(buf + 14, "%d", &val) != 1)
409 return -EINVAL;
410 param = MVM_DEBUGFS_PM_SNOOZE_ENABLE;
411 } else {
412 return -EINVAL;
413 }
414
415 mutex_lock(&mvm->mutex);
416 iwl_dbgfs_update_pm(mvm, vif, param, val);
417 ret = iwl_mvm_power_update_mode(mvm, vif);
418 mutex_unlock(&mvm->mutex);
419
420 return ret ?: count;
421}
422
423static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
424 char __user *user_buf,
425 size_t count, loff_t *ppos)
426{
427 struct ieee80211_vif *vif = file->private_data;
428 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
429 struct iwl_mvm *mvm = mvmvif->dbgfs_data;
430 char buf[512];
431 int bufsz = sizeof(buf);
432 int pos;
433
434 pos = iwl_mvm_power_dbgfs_read(mvm, vif, buf, bufsz);
435
436 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
437}
438
439static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
440 char __user *user_buf,
441 size_t count, loff_t *ppos)
442{
443 struct ieee80211_vif *vif = file->private_data;
444 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
445 struct iwl_mvm *mvm = mvmvif->dbgfs_data;
446 u8 ap_sta_id;
447 struct ieee80211_chanctx_conf *chanctx_conf;
448 char buf[512];
449 int bufsz = sizeof(buf);
450 int pos = 0;
451 int i;
452
453 mutex_lock(&mvm->mutex);
454
455 ap_sta_id = mvmvif->ap_sta_id;
456
457 pos += scnprintf(buf+pos, bufsz-pos, "mac id/color: %d / %d\n",
458 mvmvif->id, mvmvif->color);
459 pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n",
460 vif->bss_conf.bssid);
461 pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n");
462 for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++)
463 pos += scnprintf(buf+pos, bufsz-pos,
464 "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
465 i, mvmvif->queue_params[i].txop,
466 mvmvif->queue_params[i].cw_min,
467 mvmvif->queue_params[i].cw_max,
468 mvmvif->queue_params[i].aifs,
469 mvmvif->queue_params[i].uapsd);
470
471 if (vif->type == NL80211_IFTYPE_STATION &&
472 ap_sta_id != IWL_MVM_STATION_COUNT) {
473 struct ieee80211_sta *sta;
474 struct iwl_mvm_sta *mvm_sta;
475
476 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id],
477 lockdep_is_held(&mvm->mutex));
478 mvm_sta = (void *)sta->drv_priv;
479 pos += scnprintf(buf+pos, bufsz-pos,
480 "ap_sta_id %d - reduced Tx power %d\n",
481 ap_sta_id, mvm_sta->bt_reduced_txpower);
482 }
483
484 rcu_read_lock();
485 chanctx_conf = rcu_dereference(vif->chanctx_conf);
486 if (chanctx_conf)
487 pos += scnprintf(buf+pos, bufsz-pos,
488 "idle rx chains %d, active rx chains: %d\n",
489 chanctx_conf->rx_chains_static,
490 chanctx_conf->rx_chains_dynamic);
491 rcu_read_unlock();
492
493 mutex_unlock(&mvm->mutex);
494
495 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
496}
497
498#define BT_MBOX_MSG(_notif, _num, _field) \ 296#define BT_MBOX_MSG(_notif, _num, _field) \
499 ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\ 297 ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
500 >> BT_MBOX##_num##_##_field##_POS) 298 >> BT_MBOX##_num##_##_field##_POS)
@@ -849,205 +647,6 @@ iwl_dbgfs_scan_ant_rxchain_write(struct file *file,
849 return count; 647 return count;
850} 648}
851 649
852
853static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif,
854 enum iwl_dbgfs_bf_mask param, int value)
855{
856 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
857 struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
858
859 dbgfs_bf->mask |= param;
860
861 switch (param) {
862 case MVM_DEBUGFS_BF_ENERGY_DELTA:
863 dbgfs_bf->bf_energy_delta = value;
864 break;
865 case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA:
866 dbgfs_bf->bf_roaming_energy_delta = value;
867 break;
868 case MVM_DEBUGFS_BF_ROAMING_STATE:
869 dbgfs_bf->bf_roaming_state = value;
870 break;
871 case MVM_DEBUGFS_BF_TEMP_THRESHOLD:
872 dbgfs_bf->bf_temp_threshold = value;
873 break;
874 case MVM_DEBUGFS_BF_TEMP_FAST_FILTER:
875 dbgfs_bf->bf_temp_fast_filter = value;
876 break;
877 case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER:
878 dbgfs_bf->bf_temp_slow_filter = value;
879 break;
880 case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER:
881 dbgfs_bf->bf_enable_beacon_filter = value;
882 break;
883 case MVM_DEBUGFS_BF_DEBUG_FLAG:
884 dbgfs_bf->bf_debug_flag = value;
885 break;
886 case MVM_DEBUGFS_BF_ESCAPE_TIMER:
887 dbgfs_bf->bf_escape_timer = value;
888 break;
889 case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT:
890 dbgfs_bf->ba_enable_beacon_abort = value;
891 break;
892 case MVM_DEBUGFS_BA_ESCAPE_TIMER:
893 dbgfs_bf->ba_escape_timer = value;
894 break;
895 }
896}
897
898static ssize_t iwl_dbgfs_bf_params_write(struct file *file,
899 const char __user *user_buf,
900 size_t count, loff_t *ppos)
901{
902 struct ieee80211_vif *vif = file->private_data;
903 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
904 struct iwl_mvm *mvm = mvmvif->dbgfs_data;
905 enum iwl_dbgfs_bf_mask param;
906 char buf[256] = {};
907 size_t buf_size = min(count, sizeof(buf) - 1);
908 int value, ret = 0;
909
910 if (copy_from_user(buf, user_buf, buf_size))
911 return -EFAULT;
912
913 if (!strncmp("bf_energy_delta=", buf, 16)) {
914 if (sscanf(buf+16, "%d", &value) != 1)
915 return -EINVAL;
916 if (value < IWL_BF_ENERGY_DELTA_MIN ||
917 value > IWL_BF_ENERGY_DELTA_MAX)
918 return -EINVAL;
919 param = MVM_DEBUGFS_BF_ENERGY_DELTA;
920 } else if (!strncmp("bf_roaming_energy_delta=", buf, 24)) {
921 if (sscanf(buf+24, "%d", &value) != 1)
922 return -EINVAL;
923 if (value < IWL_BF_ROAMING_ENERGY_DELTA_MIN ||
924 value > IWL_BF_ROAMING_ENERGY_DELTA_MAX)
925 return -EINVAL;
926 param = MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA;
927 } else if (!strncmp("bf_roaming_state=", buf, 17)) {
928 if (sscanf(buf+17, "%d", &value) != 1)
929 return -EINVAL;
930 if (value < IWL_BF_ROAMING_STATE_MIN ||
931 value > IWL_BF_ROAMING_STATE_MAX)
932 return -EINVAL;
933 param = MVM_DEBUGFS_BF_ROAMING_STATE;
934 } else if (!strncmp("bf_temp_threshold=", buf, 18)) {
935 if (sscanf(buf+18, "%d", &value) != 1)
936 return -EINVAL;
937 if (value < IWL_BF_TEMP_THRESHOLD_MIN ||
938 value > IWL_BF_TEMP_THRESHOLD_MAX)
939 return -EINVAL;
940 param = MVM_DEBUGFS_BF_TEMP_THRESHOLD;
941 } else if (!strncmp("bf_temp_fast_filter=", buf, 20)) {
942 if (sscanf(buf+20, "%d", &value) != 1)
943 return -EINVAL;
944 if (value < IWL_BF_TEMP_FAST_FILTER_MIN ||
945 value > IWL_BF_TEMP_FAST_FILTER_MAX)
946 return -EINVAL;
947 param = MVM_DEBUGFS_BF_TEMP_FAST_FILTER;
948 } else if (!strncmp("bf_temp_slow_filter=", buf, 20)) {
949 if (sscanf(buf+20, "%d", &value) != 1)
950 return -EINVAL;
951 if (value < IWL_BF_TEMP_SLOW_FILTER_MIN ||
952 value > IWL_BF_TEMP_SLOW_FILTER_MAX)
953 return -EINVAL;
954 param = MVM_DEBUGFS_BF_TEMP_SLOW_FILTER;
955 } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) {
956 if (sscanf(buf+24, "%d", &value) != 1)
957 return -EINVAL;
958 if (value < 0 || value > 1)
959 return -EINVAL;
960 param = MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER;
961 } else if (!strncmp("bf_debug_flag=", buf, 14)) {
962 if (sscanf(buf+14, "%d", &value) != 1)
963 return -EINVAL;
964 if (value < 0 || value > 1)
965 return -EINVAL;
966 param = MVM_DEBUGFS_BF_DEBUG_FLAG;
967 } else if (!strncmp("bf_escape_timer=", buf, 16)) {
968 if (sscanf(buf+16, "%d", &value) != 1)
969 return -EINVAL;
970 if (value < IWL_BF_ESCAPE_TIMER_MIN ||
971 value > IWL_BF_ESCAPE_TIMER_MAX)
972 return -EINVAL;
973 param = MVM_DEBUGFS_BF_ESCAPE_TIMER;
974 } else if (!strncmp("ba_escape_timer=", buf, 16)) {
975 if (sscanf(buf+16, "%d", &value) != 1)
976 return -EINVAL;
977 if (value < IWL_BA_ESCAPE_TIMER_MIN ||
978 value > IWL_BA_ESCAPE_TIMER_MAX)
979 return -EINVAL;
980 param = MVM_DEBUGFS_BA_ESCAPE_TIMER;
981 } else if (!strncmp("ba_enable_beacon_abort=", buf, 23)) {
982 if (sscanf(buf+23, "%d", &value) != 1)
983 return -EINVAL;
984 if (value < 0 || value > 1)
985 return -EINVAL;
986 param = MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT;
987 } else {
988 return -EINVAL;
989 }
990
991 mutex_lock(&mvm->mutex);
992 iwl_dbgfs_update_bf(vif, param, value);
993 if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value)
994 ret = iwl_mvm_disable_beacon_filter(mvm, vif);
995 else
996 ret = iwl_mvm_enable_beacon_filter(mvm, vif);
997 mutex_unlock(&mvm->mutex);
998
999 return ret ?: count;
1000}
1001
1002static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
1003 char __user *user_buf,
1004 size_t count, loff_t *ppos)
1005{
1006 struct ieee80211_vif *vif = file->private_data;
1007 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1008 char buf[256];
1009 int pos = 0;
1010 const size_t bufsz = sizeof(buf);
1011 struct iwl_beacon_filter_cmd cmd = {
1012 IWL_BF_CMD_CONFIG_DEFAULTS,
1013 .bf_enable_beacon_filter =
1014 cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT),
1015 .ba_enable_beacon_abort =
1016 cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT),
1017 };
1018
1019 iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
1020 if (mvmvif->bf_data.bf_enabled)
1021 cmd.bf_enable_beacon_filter = cpu_to_le32(1);
1022 else
1023 cmd.bf_enable_beacon_filter = 0;
1024
1025 pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n",
1026 le32_to_cpu(cmd.bf_energy_delta));
1027 pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n",
1028 le32_to_cpu(cmd.bf_roaming_energy_delta));
1029 pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n",
1030 le32_to_cpu(cmd.bf_roaming_state));
1031 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_threshold = %d\n",
1032 le32_to_cpu(cmd.bf_temp_threshold));
1033 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_fast_filter = %d\n",
1034 le32_to_cpu(cmd.bf_temp_fast_filter));
1035 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_slow_filter = %d\n",
1036 le32_to_cpu(cmd.bf_temp_slow_filter));
1037 pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n",
1038 le32_to_cpu(cmd.bf_enable_beacon_filter));
1039 pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n",
1040 le32_to_cpu(cmd.bf_debug_flag));
1041 pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n",
1042 le32_to_cpu(cmd.bf_escape_timer));
1043 pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n",
1044 le32_to_cpu(cmd.ba_escape_timer));
1045 pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n",
1046 le32_to_cpu(cmd.ba_enable_beacon_abort));
1047
1048 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1049}
1050
1051#ifdef CONFIG_PM_SLEEP 650#ifdef CONFIG_PM_SLEEP
1052static ssize_t iwl_dbgfs_d3_sram_write(struct file *file, 651static ssize_t iwl_dbgfs_d3_sram_write(struct file *file,
1053 const char __user *user_buf, 652 const char __user *user_buf,
@@ -1113,40 +712,12 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
1113} 712}
1114#endif 713#endif
1115 714
1116#define MVM_DEBUGFS_READ_FILE_OPS(name) \
1117static const struct file_operations iwl_dbgfs_##name##_ops = { \
1118 .read = iwl_dbgfs_##name##_read, \
1119 .open = simple_open, \
1120 .llseek = generic_file_llseek, \
1121}
1122
1123#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name) \
1124static const struct file_operations iwl_dbgfs_##name##_ops = { \
1125 .write = iwl_dbgfs_##name##_write, \
1126 .read = iwl_dbgfs_##name##_read, \
1127 .open = simple_open, \
1128 .llseek = generic_file_llseek, \
1129};
1130
1131#define MVM_DEBUGFS_WRITE_FILE_OPS(name) \
1132static const struct file_operations iwl_dbgfs_##name##_ops = { \
1133 .write = iwl_dbgfs_##name##_write, \
1134 .open = simple_open, \
1135 .llseek = generic_file_llseek, \
1136};
1137
1138#define MVM_DEBUGFS_ADD_FILE(name, parent, mode) do { \ 715#define MVM_DEBUGFS_ADD_FILE(name, parent, mode) do { \
1139 if (!debugfs_create_file(#name, mode, parent, mvm, \ 716 if (!debugfs_create_file(#name, mode, parent, mvm, \
1140 &iwl_dbgfs_##name##_ops)) \ 717 &iwl_dbgfs_##name##_ops)) \
1141 goto err; \ 718 goto err; \
1142 } while (0) 719 } while (0)
1143 720
1144#define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \
1145 if (!debugfs_create_file(#name, mode, parent, vif, \
1146 &iwl_dbgfs_##name##_ops)) \
1147 goto err; \
1148 } while (0)
1149
1150/* Device wide debugfs entries */ 721/* Device wide debugfs entries */
1151MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush); 722MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush);
1152MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain); 723MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain);
@@ -1164,11 +735,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain);
1164MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram); 735MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram);
1165#endif 736#endif
1166 737
1167/* Interface specific debugfs entries */
1168MVM_DEBUGFS_READ_FILE_OPS(mac_params);
1169MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params);
1170MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params);
1171
1172int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) 738int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
1173{ 739{
1174 char buf[100]; 740 char buf[100];
@@ -1212,72 +778,3 @@ err:
1212 IWL_ERR(mvm, "Can't create the mvm debugfs directory\n"); 778 IWL_ERR(mvm, "Can't create the mvm debugfs directory\n");
1213 return -ENOMEM; 779 return -ENOMEM;
1214} 780}
1215
1216void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1217{
1218 struct dentry *dbgfs_dir = vif->debugfs_dir;
1219 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1220 char buf[100];
1221
1222 /*
1223 * Check if debugfs directory already exist before creating it.
1224 * This may happen when, for example, resetting hw or suspend-resume
1225 */
1226 if (!dbgfs_dir || mvmvif->dbgfs_dir)
1227 return;
1228
1229 mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
1230 mvmvif->dbgfs_data = mvm;
1231
1232 if (!mvmvif->dbgfs_dir) {
1233 IWL_ERR(mvm, "Failed to create debugfs directory under %s\n",
1234 dbgfs_dir->d_name.name);
1235 return;
1236 }
1237
1238 if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
1239 vif->type == NL80211_IFTYPE_STATION && !vif->p2p)
1240 MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR |
1241 S_IRUSR);
1242
1243 MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir,
1244 S_IRUSR);
1245
1246 if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
1247 mvmvif == mvm->bf_allowed_vif)
1248 MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir,
1249 S_IRUSR | S_IWUSR);
1250
1251 /*
1252 * Create symlink for convenience pointing to interface specific
1253 * debugfs entries for the driver. For example, under
1254 * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
1255 * find
1256 * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
1257 */
1258 snprintf(buf, 100, "../../../%s/%s/%s/%s",
1259 dbgfs_dir->d_parent->d_parent->d_name.name,
1260 dbgfs_dir->d_parent->d_name.name,
1261 dbgfs_dir->d_name.name,
1262 mvmvif->dbgfs_dir->d_name.name);
1263
1264 mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name,
1265 mvm->debugfs_dir, buf);
1266 if (!mvmvif->dbgfs_slink)
1267 IWL_ERR(mvm, "Can't create debugfs symbolic link under %s\n",
1268 dbgfs_dir->d_name.name);
1269 return;
1270err:
1271 IWL_ERR(mvm, "Can't create debugfs entity\n");
1272}
1273
1274void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1275{
1276 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1277
1278 debugfs_remove(mvmvif->dbgfs_slink);
1279 mvmvif->dbgfs_slink = NULL;
1280
1281 debugfs_remove_recursive(mvmvif->dbgfs_dir);
1282 mvmvif->dbgfs_dir = NULL;
1283}
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.h b/drivers/net/wireless/iwlwifi/mvm/debugfs.h
new file mode 100644
index 000000000000..faa73b80b624
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.h
@@ -0,0 +1,84 @@
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 - 2013 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 - 2013 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
64#define MVM_DEBUGFS_READ_FILE_OPS(name) \
65static const struct file_operations iwl_dbgfs_##name##_ops = { \
66 .read = iwl_dbgfs_##name##_read, \
67 .open = simple_open, \
68 .llseek = generic_file_llseek, \
69}
70
71#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name) \
72static const struct file_operations iwl_dbgfs_##name##_ops = { \
73 .write = iwl_dbgfs_##name##_write, \
74 .read = iwl_dbgfs_##name##_read, \
75 .open = simple_open, \
76 .llseek = generic_file_llseek, \
77};
78
79#define MVM_DEBUGFS_WRITE_FILE_OPS(name) \
80static const struct file_operations iwl_dbgfs_##name##_ops = { \
81 .write = iwl_dbgfs_##name##_write, \
82 .open = simple_open, \
83 .llseek = generic_file_llseek, \
84};