iwlwifi: add Intel Mobile Communications copyright
[deliverable/linux.git] / drivers / net / wireless / iwlwifi / mvm / debugfs-vif.c
CommitLineData
820a1a50
JB
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 *
51368bf7 8 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
8b4139dc 9 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
820a1a50
JB
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of version 2 of the GNU General Public License as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
23 * USA
24 *
25 * The full GNU General Public License is included in this distribution
26 * in the file called COPYING.
27 *
28 * Contact Information:
29 * Intel Linux Wireless <ilw@linux.intel.com>
30 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
31 *
32 * BSD LICENSE
33 *
51368bf7 34 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
8b4139dc 35 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
820a1a50
JB
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 *
42 * * Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * * Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in
46 * the documentation and/or other materials provided with the
47 * distribution.
48 * * Neither the name Intel Corporation nor the names of its
49 * contributors may be used to endorse or promote products derived
50 * from this software without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
53 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
54 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
55 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
56 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
57 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
58 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
59 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
60 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
61 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
62 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63 *
64 *****************************************************************************/
65#include "mvm.h"
66#include "debugfs.h"
67
e45a941d
AB
68static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
69 struct ieee80211_vif *vif,
70 enum iwl_dbgfs_pm_mask param, int val)
71{
72 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
73 struct iwl_dbgfs_pm *dbgfs_pm = &mvmvif->dbgfs_pm;
74
75 dbgfs_pm->mask |= param;
76
77 switch (param) {
78 case MVM_DEBUGFS_PM_KEEP_ALIVE: {
79 struct ieee80211_hw *hw = mvm->hw;
80 int dtimper = hw->conf.ps_dtim_period ?: 1;
81 int dtimper_msec = dtimper * vif->bss_conf.beacon_int;
82
83 IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val);
84 if (val * MSEC_PER_SEC < 3 * dtimper_msec)
85 IWL_WARN(mvm,
86 "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n",
87 val * MSEC_PER_SEC, 3 * dtimper_msec);
88 dbgfs_pm->keep_alive_seconds = val;
89 break;
90 }
91 case MVM_DEBUGFS_PM_SKIP_OVER_DTIM:
92 IWL_DEBUG_POWER(mvm, "skip_over_dtim %s\n",
93 val ? "enabled" : "disabled");
94 dbgfs_pm->skip_over_dtim = val;
95 break;
96 case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS:
97 IWL_DEBUG_POWER(mvm, "skip_dtim_periods=%d\n", val);
98 dbgfs_pm->skip_dtim_periods = val;
99 break;
100 case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT:
101 IWL_DEBUG_POWER(mvm, "rx_data_timeout=%d\n", val);
102 dbgfs_pm->rx_data_timeout = val;
103 break;
104 case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT:
105 IWL_DEBUG_POWER(mvm, "tx_data_timeout=%d\n", val);
106 dbgfs_pm->tx_data_timeout = val;
107 break;
e45a941d
AB
108 case MVM_DEBUGFS_PM_LPRX_ENA:
109 IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled");
110 dbgfs_pm->lprx_ena = val;
111 break;
112 case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD:
113 IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val);
114 dbgfs_pm->lprx_rssi_threshold = val;
115 break;
116 case MVM_DEBUGFS_PM_SNOOZE_ENABLE:
117 IWL_DEBUG_POWER(mvm, "snooze_enable=%d\n", val);
118 dbgfs_pm->snooze_ena = val;
119 break;
120 case MVM_DEBUGFS_PM_UAPSD_MISBEHAVING:
121 IWL_DEBUG_POWER(mvm, "uapsd_misbehaving_enable=%d\n", val);
122 dbgfs_pm->uapsd_misbehaving = val;
123 break;
84fd7608
EP
124 case MVM_DEBUGFS_PM_USE_PS_POLL:
125 IWL_DEBUG_POWER(mvm, "use_ps_poll=%d\n", val);
126 dbgfs_pm->use_ps_poll = val;
127 break;
e45a941d
AB
128 }
129}
130
131static ssize_t iwl_dbgfs_pm_params_write(struct ieee80211_vif *vif, char *buf,
132 size_t count, loff_t *ppos)
133{
134 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
135 struct iwl_mvm *mvm = mvmvif->mvm;
136 enum iwl_dbgfs_pm_mask param;
137 int val, ret;
138
139 if (!strncmp("keep_alive=", buf, 11)) {
140 if (sscanf(buf + 11, "%d", &val) != 1)
141 return -EINVAL;
142 param = MVM_DEBUGFS_PM_KEEP_ALIVE;
143 } else if (!strncmp("skip_over_dtim=", buf, 15)) {
144 if (sscanf(buf + 15, "%d", &val) != 1)
145 return -EINVAL;
146 param = MVM_DEBUGFS_PM_SKIP_OVER_DTIM;
147 } else if (!strncmp("skip_dtim_periods=", buf, 18)) {
148 if (sscanf(buf + 18, "%d", &val) != 1)
149 return -EINVAL;
150 param = MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS;
151 } else if (!strncmp("rx_data_timeout=", buf, 16)) {
152 if (sscanf(buf + 16, "%d", &val) != 1)
153 return -EINVAL;
154 param = MVM_DEBUGFS_PM_RX_DATA_TIMEOUT;
155 } else if (!strncmp("tx_data_timeout=", buf, 16)) {
156 if (sscanf(buf + 16, "%d", &val) != 1)
157 return -EINVAL;
158 param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT;
e45a941d
AB
159 } else if (!strncmp("lprx=", buf, 5)) {
160 if (sscanf(buf + 5, "%d", &val) != 1)
161 return -EINVAL;
162 param = MVM_DEBUGFS_PM_LPRX_ENA;
163 } else if (!strncmp("lprx_rssi_threshold=", buf, 20)) {
164 if (sscanf(buf + 20, "%d", &val) != 1)
165 return -EINVAL;
166 if (val > POWER_LPRX_RSSI_THRESHOLD_MAX || val <
167 POWER_LPRX_RSSI_THRESHOLD_MIN)
168 return -EINVAL;
169 param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD;
170 } else if (!strncmp("snooze_enable=", buf, 14)) {
171 if (sscanf(buf + 14, "%d", &val) != 1)
172 return -EINVAL;
173 param = MVM_DEBUGFS_PM_SNOOZE_ENABLE;
174 } else if (!strncmp("uapsd_misbehaving=", buf, 18)) {
175 if (sscanf(buf + 18, "%d", &val) != 1)
176 return -EINVAL;
177 param = MVM_DEBUGFS_PM_UAPSD_MISBEHAVING;
84fd7608
EP
178 } else if (!strncmp("use_ps_poll=", buf, 12)) {
179 if (sscanf(buf + 12, "%d", &val) != 1)
180 return -EINVAL;
181 param = MVM_DEBUGFS_PM_USE_PS_POLL;
e45a941d
AB
182 } else {
183 return -EINVAL;
184 }
185
186 mutex_lock(&mvm->mutex);
187 iwl_dbgfs_update_pm(mvm, vif, param, val);
999609f1 188 ret = iwl_mvm_power_update_mac(mvm);
e45a941d
AB
189 mutex_unlock(&mvm->mutex);
190
191 return ret ?: count;
192}
193
194static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
195 char __user *user_buf,
196 size_t count, loff_t *ppos)
197{
198 struct ieee80211_vif *vif = file->private_data;
199 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
200 struct iwl_mvm *mvm = mvmvif->mvm;
201 char buf[512];
202 int bufsz = sizeof(buf);
203 int pos;
204
c1cb92fc 205 pos = iwl_mvm_power_mac_dbgfs_read(mvm, vif, buf, bufsz);
e45a941d
AB
206
207 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
208}
209
820a1a50
JB
210static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
211 char __user *user_buf,
212 size_t count, loff_t *ppos)
213{
214 struct ieee80211_vif *vif = file->private_data;
215 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
7f09d704 216 struct iwl_mvm *mvm = mvmvif->mvm;
820a1a50
JB
217 u8 ap_sta_id;
218 struct ieee80211_chanctx_conf *chanctx_conf;
219 char buf[512];
220 int bufsz = sizeof(buf);
221 int pos = 0;
222 int i;
223
224 mutex_lock(&mvm->mutex);
225
226 ap_sta_id = mvmvif->ap_sta_id;
227
2284b951
EG
228 switch (ieee80211_vif_type_p2p(vif)) {
229 case NL80211_IFTYPE_ADHOC:
230 pos += scnprintf(buf+pos, bufsz-pos, "type: ibss\n");
231 break;
232 case NL80211_IFTYPE_STATION:
233 pos += scnprintf(buf+pos, bufsz-pos, "type: bss\n");
234 break;
235 case NL80211_IFTYPE_AP:
236 pos += scnprintf(buf+pos, bufsz-pos, "type: ap\n");
237 break;
238 case NL80211_IFTYPE_P2P_CLIENT:
239 pos += scnprintf(buf+pos, bufsz-pos, "type: p2p client\n");
240 break;
241 case NL80211_IFTYPE_P2P_GO:
242 pos += scnprintf(buf+pos, bufsz-pos, "type: p2p go\n");
243 break;
244 case NL80211_IFTYPE_P2P_DEVICE:
245 pos += scnprintf(buf+pos, bufsz-pos, "type: p2p dev\n");
246 break;
247 default:
248 break;
249 }
250
820a1a50
JB
251 pos += scnprintf(buf+pos, bufsz-pos, "mac id/color: %d / %d\n",
252 mvmvif->id, mvmvif->color);
253 pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n",
254 vif->bss_conf.bssid);
255 pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n");
256 for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++)
257 pos += scnprintf(buf+pos, bufsz-pos,
258 "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
259 i, mvmvif->queue_params[i].txop,
260 mvmvif->queue_params[i].cw_min,
261 mvmvif->queue_params[i].cw_max,
262 mvmvif->queue_params[i].aifs,
263 mvmvif->queue_params[i].uapsd);
264
265 if (vif->type == NL80211_IFTYPE_STATION &&
266 ap_sta_id != IWL_MVM_STATION_COUNT) {
267 struct ieee80211_sta *sta;
820a1a50
JB
268
269 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id],
270 lockdep_is_held(&mvm->mutex));
1ddbbb0c
JB
271 if (!IS_ERR_OR_NULL(sta)) {
272 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
273
274 pos += scnprintf(buf+pos, bufsz-pos,
1fa477c6 275 "ap_sta_id %d - reduced Tx power %d\n",
1ddbbb0c 276 ap_sta_id,
1fa477c6 277 mvm_sta->bt_reduced_txpower);
1ddbbb0c 278 }
820a1a50
JB
279 }
280
281 rcu_read_lock();
282 chanctx_conf = rcu_dereference(vif->chanctx_conf);
283 if (chanctx_conf)
284 pos += scnprintf(buf+pos, bufsz-pos,
285 "idle rx chains %d, active rx chains: %d\n",
286 chanctx_conf->rx_chains_static,
287 chanctx_conf->rx_chains_dynamic);
288 rcu_read_unlock();
289
290 mutex_unlock(&mvm->mutex);
291
292 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
293}
294
e45a941d
AB
295static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif,
296 enum iwl_dbgfs_bf_mask param, int value)
297{
298 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
299 struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
300
301 dbgfs_bf->mask |= param;
302
303 switch (param) {
304 case MVM_DEBUGFS_BF_ENERGY_DELTA:
305 dbgfs_bf->bf_energy_delta = value;
306 break;
307 case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA:
308 dbgfs_bf->bf_roaming_energy_delta = value;
309 break;
310 case MVM_DEBUGFS_BF_ROAMING_STATE:
311 dbgfs_bf->bf_roaming_state = value;
312 break;
313 case MVM_DEBUGFS_BF_TEMP_THRESHOLD:
314 dbgfs_bf->bf_temp_threshold = value;
315 break;
316 case MVM_DEBUGFS_BF_TEMP_FAST_FILTER:
317 dbgfs_bf->bf_temp_fast_filter = value;
318 break;
319 case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER:
320 dbgfs_bf->bf_temp_slow_filter = value;
321 break;
322 case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER:
323 dbgfs_bf->bf_enable_beacon_filter = value;
324 break;
325 case MVM_DEBUGFS_BF_DEBUG_FLAG:
326 dbgfs_bf->bf_debug_flag = value;
327 break;
328 case MVM_DEBUGFS_BF_ESCAPE_TIMER:
329 dbgfs_bf->bf_escape_timer = value;
330 break;
331 case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT:
332 dbgfs_bf->ba_enable_beacon_abort = value;
333 break;
334 case MVM_DEBUGFS_BA_ESCAPE_TIMER:
335 dbgfs_bf->ba_escape_timer = value;
336 break;
337 }
338}
339
340static ssize_t iwl_dbgfs_bf_params_write(struct ieee80211_vif *vif, char *buf,
341 size_t count, loff_t *ppos)
342{
343 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
344 struct iwl_mvm *mvm = mvmvif->mvm;
345 enum iwl_dbgfs_bf_mask param;
346 int value, ret = 0;
347
348 if (!strncmp("bf_energy_delta=", buf, 16)) {
349 if (sscanf(buf+16, "%d", &value) != 1)
350 return -EINVAL;
351 if (value < IWL_BF_ENERGY_DELTA_MIN ||
352 value > IWL_BF_ENERGY_DELTA_MAX)
353 return -EINVAL;
354 param = MVM_DEBUGFS_BF_ENERGY_DELTA;
355 } else if (!strncmp("bf_roaming_energy_delta=", buf, 24)) {
356 if (sscanf(buf+24, "%d", &value) != 1)
357 return -EINVAL;
358 if (value < IWL_BF_ROAMING_ENERGY_DELTA_MIN ||
359 value > IWL_BF_ROAMING_ENERGY_DELTA_MAX)
360 return -EINVAL;
361 param = MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA;
362 } else if (!strncmp("bf_roaming_state=", buf, 17)) {
363 if (sscanf(buf+17, "%d", &value) != 1)
364 return -EINVAL;
365 if (value < IWL_BF_ROAMING_STATE_MIN ||
366 value > IWL_BF_ROAMING_STATE_MAX)
367 return -EINVAL;
368 param = MVM_DEBUGFS_BF_ROAMING_STATE;
369 } else if (!strncmp("bf_temp_threshold=", buf, 18)) {
370 if (sscanf(buf+18, "%d", &value) != 1)
371 return -EINVAL;
372 if (value < IWL_BF_TEMP_THRESHOLD_MIN ||
373 value > IWL_BF_TEMP_THRESHOLD_MAX)
374 return -EINVAL;
375 param = MVM_DEBUGFS_BF_TEMP_THRESHOLD;
376 } else if (!strncmp("bf_temp_fast_filter=", buf, 20)) {
377 if (sscanf(buf+20, "%d", &value) != 1)
378 return -EINVAL;
379 if (value < IWL_BF_TEMP_FAST_FILTER_MIN ||
380 value > IWL_BF_TEMP_FAST_FILTER_MAX)
381 return -EINVAL;
382 param = MVM_DEBUGFS_BF_TEMP_FAST_FILTER;
383 } else if (!strncmp("bf_temp_slow_filter=", buf, 20)) {
384 if (sscanf(buf+20, "%d", &value) != 1)
385 return -EINVAL;
386 if (value < IWL_BF_TEMP_SLOW_FILTER_MIN ||
387 value > IWL_BF_TEMP_SLOW_FILTER_MAX)
388 return -EINVAL;
389 param = MVM_DEBUGFS_BF_TEMP_SLOW_FILTER;
390 } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) {
391 if (sscanf(buf+24, "%d", &value) != 1)
392 return -EINVAL;
393 if (value < 0 || value > 1)
394 return -EINVAL;
395 param = MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER;
396 } else if (!strncmp("bf_debug_flag=", buf, 14)) {
397 if (sscanf(buf+14, "%d", &value) != 1)
398 return -EINVAL;
399 if (value < 0 || value > 1)
400 return -EINVAL;
401 param = MVM_DEBUGFS_BF_DEBUG_FLAG;
402 } else if (!strncmp("bf_escape_timer=", buf, 16)) {
403 if (sscanf(buf+16, "%d", &value) != 1)
404 return -EINVAL;
405 if (value < IWL_BF_ESCAPE_TIMER_MIN ||
406 value > IWL_BF_ESCAPE_TIMER_MAX)
407 return -EINVAL;
408 param = MVM_DEBUGFS_BF_ESCAPE_TIMER;
409 } else if (!strncmp("ba_escape_timer=", buf, 16)) {
410 if (sscanf(buf+16, "%d", &value) != 1)
411 return -EINVAL;
412 if (value < IWL_BA_ESCAPE_TIMER_MIN ||
413 value > IWL_BA_ESCAPE_TIMER_MAX)
414 return -EINVAL;
415 param = MVM_DEBUGFS_BA_ESCAPE_TIMER;
416 } else if (!strncmp("ba_enable_beacon_abort=", buf, 23)) {
417 if (sscanf(buf+23, "%d", &value) != 1)
418 return -EINVAL;
419 if (value < 0 || value > 1)
420 return -EINVAL;
421 param = MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT;
422 } else {
423 return -EINVAL;
424 }
425
426 mutex_lock(&mvm->mutex);
427 iwl_dbgfs_update_bf(vif, param, value);
428 if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value)
a1022927 429 ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
e45a941d 430 else
a1022927 431 ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
e45a941d
AB
432 mutex_unlock(&mvm->mutex);
433
434 return ret ?: count;
435}
436
437static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
438 char __user *user_buf,
439 size_t count, loff_t *ppos)
440{
441 struct ieee80211_vif *vif = file->private_data;
442 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
443 char buf[256];
444 int pos = 0;
445 const size_t bufsz = sizeof(buf);
446 struct iwl_beacon_filter_cmd cmd = {
447 IWL_BF_CMD_CONFIG_DEFAULTS,
448 .bf_enable_beacon_filter =
449 cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT),
450 .ba_enable_beacon_abort =
451 cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT),
452 };
453
454 iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
455 if (mvmvif->bf_data.bf_enabled)
456 cmd.bf_enable_beacon_filter = cpu_to_le32(1);
457 else
458 cmd.bf_enable_beacon_filter = 0;
459
460 pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n",
461 le32_to_cpu(cmd.bf_energy_delta));
462 pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n",
463 le32_to_cpu(cmd.bf_roaming_energy_delta));
464 pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n",
465 le32_to_cpu(cmd.bf_roaming_state));
466 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_threshold = %d\n",
467 le32_to_cpu(cmd.bf_temp_threshold));
468 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_fast_filter = %d\n",
469 le32_to_cpu(cmd.bf_temp_fast_filter));
470 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_slow_filter = %d\n",
471 le32_to_cpu(cmd.bf_temp_slow_filter));
472 pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n",
473 le32_to_cpu(cmd.bf_enable_beacon_filter));
474 pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n",
475 le32_to_cpu(cmd.bf_debug_flag));
476 pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n",
477 le32_to_cpu(cmd.bf_escape_timer));
478 pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n",
479 le32_to_cpu(cmd.ba_escape_timer));
480 pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n",
481 le32_to_cpu(cmd.ba_enable_beacon_abort));
482
483 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
484}
485
a21d7bcb
JB
486static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf,
487 size_t count, loff_t *ppos)
488{
489 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
490 struct iwl_mvm *mvm = mvmvif->mvm;
491 u8 value;
492 int ret;
493
494 ret = kstrtou8(buf, 0, &value);
495 if (ret)
496 return ret;
497 if (value > 1)
498 return -EINVAL;
499
500 mutex_lock(&mvm->mutex);
501 iwl_mvm_update_low_latency(mvm, vif, value);
502 mutex_unlock(&mvm->mutex);
503
504 return count;
505}
506
507static ssize_t iwl_dbgfs_low_latency_read(struct file *file,
508 char __user *user_buf,
509 size_t count, loff_t *ppos)
510{
511 struct ieee80211_vif *vif = file->private_data;
512 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
513 char buf[3];
514
515 buf[0] = mvmvif->low_latency ? '1' : '0';
516 buf[1] = '\n';
517 buf[2] = '\0';
518 return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf));
519}
520
e45a941d
AB
521#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
522 _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
523#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
524 _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
820a1a50
JB
525#define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \
526 if (!debugfs_create_file(#name, mode, parent, vif, \
527 &iwl_dbgfs_##name##_ops)) \
528 goto err; \
529 } while (0)
530
531MVM_DEBUGFS_READ_FILE_OPS(mac_params);
e45a941d
AB
532MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32);
533MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256);
a21d7bcb 534MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10);
820a1a50
JB
535
536void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
537{
538 struct dentry *dbgfs_dir = vif->debugfs_dir;
539 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
540 char buf[100];
541
542 /*
543 * Check if debugfs directory already exist before creating it.
544 * This may happen when, for example, resetting hw or suspend-resume
545 */
546 if (!dbgfs_dir || mvmvif->dbgfs_dir)
547 return;
548
549 mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
7f09d704 550 mvmvif->mvm = mvm;
820a1a50
JB
551
552 if (!mvmvif->dbgfs_dir) {
553 IWL_ERR(mvm, "Failed to create debugfs directory under %s\n",
554 dbgfs_dir->d_name.name);
555 return;
556 }
557
ad2549d8 558 if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
e45a941d
AB
559 ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) ||
560 (vif->type == NL80211_IFTYPE_STATION && vif->p2p &&
7303dd7f 561 mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)))
e45a941d
AB
562 MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR |
563 S_IRUSR);
564
32a65c34 565 MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, S_IRUSR);
a21d7bcb
JB
566 MVM_DEBUGFS_ADD_FILE_VIF(low_latency, mvmvif->dbgfs_dir,
567 S_IRUSR | S_IWUSR);
820a1a50 568
e45a941d
AB
569 if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
570 mvmvif == mvm->bf_allowed_vif)
571 MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir,
572 S_IRUSR | S_IWUSR);
573
820a1a50
JB
574 /*
575 * Create symlink for convenience pointing to interface specific
576 * debugfs entries for the driver. For example, under
577 * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
578 * find
579 * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
580 */
581 snprintf(buf, 100, "../../../%s/%s/%s/%s",
582 dbgfs_dir->d_parent->d_parent->d_name.name,
583 dbgfs_dir->d_parent->d_name.name,
584 dbgfs_dir->d_name.name,
585 mvmvif->dbgfs_dir->d_name.name);
586
587 mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name,
588 mvm->debugfs_dir, buf);
589 if (!mvmvif->dbgfs_slink)
590 IWL_ERR(mvm, "Can't create debugfs symbolic link under %s\n",
591 dbgfs_dir->d_name.name);
592 return;
593err:
594 IWL_ERR(mvm, "Can't create debugfs entity\n");
595}
596
597void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
598{
599 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
600
601 debugfs_remove(mvmvif->dbgfs_slink);
602 mvmvif->dbgfs_slink = NULL;
603
604 debugfs_remove_recursive(mvmvif->dbgfs_dir);
605 mvmvif->dbgfs_dir = NULL;
606}
This page took 0.120501 seconds and 5 git commands to generate.