1 /*
2 * Debug code for XRadio drivers
3 *
4 * Copyright (c) 2013
5 * Xradio Technology Co., Ltd. <www.xradiotech.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12 /*Linux version 3.4.0 compilation*/
13 /*#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))*/
14 #include<linux/module.h>
15 /*#endif*/
16 #include <linux/debugfs.h>
17 #include <linux/seq_file.h>
18 #include <linux/rtc.h>
19 #include <linux/time.h>
20
21 #include "xradio.h"
22 #include "hwio.h"
23 #include "bh.h"
24 #include "debug.h"
25 #ifdef SUPPORT_FW_DBG_INF
26 #include "fw_dbg_inf.h"
27 #endif
28
29 /*for host debuglevel*/
30 #define XRADIO_DBG_DEFAULT (XRADIO_DBG_ALWY|XRADIO_DBG_ERROR|XRADIO_DBG_WARN)
31
32 u8 dbg_common = XRADIO_DBG_DEFAULT;
33 u8 dbg_sbus = XRADIO_DBG_DEFAULT;
34 u8 dbg_bh = XRADIO_DBG_DEFAULT;
35 u8 dbg_txrx = XRADIO_DBG_DEFAULT;
36 u8 dbg_wsm = XRADIO_DBG_DEFAULT;
37 u8 dbg_sta = XRADIO_DBG_DEFAULT;
38 u8 dbg_scan = XRADIO_DBG_DEFAULT;
39 u8 dbg_ap = XRADIO_DBG_DEFAULT;
40 u8 dbg_pm = XRADIO_DBG_DEFAULT;
41 u8 dbg_itp = XRADIO_DBG_DEFAULT;
42 u8 dbg_etf = XRADIO_DBG_DEFAULT;
43 u8 dbg_logfile = XRADIO_DBG_ERROR;
44
45 #ifdef ERROR_HANG_DRIVER
46 u8 error_hang_driver;
47 #endif
48
49
50 #if (DBG_XRADIO_HIF)
51 u16 hif_test_rw; /*0: nothing to do; 1: write only; 2: write and read*/
52 u16 hif_test_data_mode; /* hif test data mode, such as 0x55, 0xff etc*/
53 u16 hif_test_data_len; /* hif test data len, every data len pre round*/
54 u16 hif_test_data_round;
55 u16 hif_test_oper_delta; /* hif test operation delta time, give more time to analyze data tranx*/
56 #endif
57
58 #ifdef CONFIG_XRADIO_DEBUGFS
59 /* join_status */
60 static const char *const xradio_debug_join_status[] = {
61 "passive",
62 "monitor",
63 "station",
64 "access point",
65 };
66
67 /* WSM_JOIN_PREAMBLE_... */
68 static const char *const xradio_debug_preamble[] = {
69 "long",
70 "short",
71 "long on 1 and 2 Mbps",
72 };
73
74 static const char *const xradio_debug_fw_types[] = {
75 "ETF",
76 "WFM",
77 "WSM",
78 "HI test",
79 "Platform test",
80 };
81
82 static const char *const xradio_debug_link_id[] = {
83 "OFF",
84 "REQ",
85 "SOFT",
86 "HARD",
87 };
88
xradio_debug_mode(int mode)89 static const char *xradio_debug_mode(int mode)
90 {
91 switch (mode) {
92 case NL80211_IFTYPE_UNSPECIFIED:
93 return "unspecified";
94 case NL80211_IFTYPE_MONITOR:
95 return "monitor";
96 case NL80211_IFTYPE_STATION:
97 return "station";
98 case NL80211_IFTYPE_ADHOC:
99 return "ad-hok";
100 case NL80211_IFTYPE_MESH_POINT:
101 return "mesh point";
102 case NL80211_IFTYPE_AP:
103 return "access point";
104 case NL80211_IFTYPE_P2P_CLIENT:
105 return "p2p client";
106 case NL80211_IFTYPE_P2P_GO:
107 return "p2p go";
108 default:
109 return "unsupported";
110 }
111 }
112
xradio_queue_status_show(struct seq_file * seq,struct xradio_queue * q)113 static void xradio_queue_status_show(struct seq_file *seq,
114 struct xradio_queue *q)
115 {
116 int i, if_id;
117 seq_printf(seq, "Queue %d:\n", q->queue_id);
118 seq_printf(seq, " capacity: %zu\n", q->capacity);
119 seq_printf(seq, " queued: %zu\n", q->num_queued);
120 seq_printf(seq, " pending: %zu\n", q->num_pending);
121 seq_printf(seq, " sent: %zu\n", q->num_sent);
122 seq_printf(seq, " locked: %s\n", q->tx_locked_cnt ? "yes" : "no");
123 seq_printf(seq, " overfull: %s\n", q->overfull ? "yes" : "no");
124 seq_puts(seq, " link map: 0-> ");
125 for (if_id = 0; if_id < XRWL_MAX_VIFS; if_id++) {
126 for (i = 0; i < q->stats->map_capacity; ++i)
127 seq_printf(seq, "%.2d ", q->link_map_cache[if_id][i]);
128 seq_printf(seq, "<-%zu\n", q->stats->map_capacity);
129 }
130 }
131
xradio_debug_print_map(struct seq_file * seq,struct xradio_vif * priv,const char * label,u32 map)132 static void xradio_debug_print_map(struct seq_file *seq,
133 struct xradio_vif *priv,
134 const char *label, u32 map)
135 {
136 int i;
137 seq_printf(seq, "%s0-> ", label);
138 for (i = 0; i < priv->hw_priv->tx_queue_stats.map_capacity; ++i)
139 seq_printf(seq, "%s ", (map & BIT(i)) ? "**" : "..");
140 seq_printf(seq, "<-%zu\n",
141 priv->hw_priv->tx_queue_stats.map_capacity - 1);
142 }
143
xradio_version_show(struct seq_file * seq,void * v)144 static int xradio_version_show(struct seq_file *seq, void *v)
145 {
146 struct xradio_common *hw_priv = seq->private;
147 seq_printf(seq, "Driver Label:%s %s\n", DRV_VERSION, DRV_BUILDTIME);
148 seq_printf(seq, "Firmware Label:%s\n", &hw_priv->wsm_caps.fw_label[0]);
149 return 0;
150 }
151
xradio_version_open(struct inode * inode,struct file * file)152 static int xradio_version_open(struct inode *inode, struct file *file)
153 {
154 return single_open(file, &xradio_version_show, inode->i_private);
155 }
156
157 static const struct file_operations fops_version = {
158 .open = xradio_version_open,
159 .read = seq_read,
160 .llseek = seq_lseek,
161 .release = single_release,
162 .owner = THIS_MODULE,
163 };
164
165 #if (DGB_XRADIO_QC)
xradio_hwinfo_show(struct seq_file * seq,void * v)166 static int xradio_hwinfo_show(struct seq_file *seq, void *v)
167 {
168 struct xradio_common *hw_priv = seq->private;
169 u32 hw_arry[8] = { 0 };
170
171 wsm_read_mib(hw_priv, WSM_MIB_ID_HW_INFO, (void *)&hw_arry,
172 sizeof(hw_arry), 4);
173
174 /*
175 get_random_bytes((u8 *)&hw_arry[0], 8*sizeof(u32));
176 hw_arry[0] = 0x0B140D4;
177 hw_arry[1] &= ~0xF803FFFF;
178 hw_arry[2] &= ~0xC0001FFF;
179 hw_arry[5] &= ~0xFFFFF000;
180 hw_arry[7] &= ~0xFFFC07C0;
181 */
182
183 seq_printf(seq, "0x%08x, 0x%08x, 0x%08x, 0x%08x, "
184 "0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
185 hw_arry[0], hw_arry[1], hw_arry[2], hw_arry[3],
186 hw_arry[4], hw_arry[5], hw_arry[6], hw_arry[7]);
187 return 0;
188 }
189
xradio_hwinfo_open(struct inode * inode,struct file * file)190 static int xradio_hwinfo_open(struct inode *inode, struct file *file)
191 {
192 return single_open(file, &xradio_hwinfo_show, inode->i_private);
193 }
194
195 static const struct file_operations fops_hwinfo = {
196 .open = xradio_hwinfo_open,
197 .read = seq_read,
198 .llseek = seq_lseek,
199 .release = single_release,
200 .owner = THIS_MODULE,
201 };
202
203
xradio_temperature_show(struct seq_file * seq,void * v)204 static int xradio_temperature_show(struct seq_file *seq, void *v)
205 {
206 struct xradio_common *hw_priv = seq->private;
207 s32 s32tempQ4;
208
209 wsm_read_mib(hw_priv, WSM_MIB_ID_GET_TEMPERATURE, (void *)&s32tempQ4,
210 sizeof(s32tempQ4), 4);
211 seq_printf(seq, "%d\n", (s32tempQ4 >> 4));
212 return 0;
213 }
214
xradio_temperature_open(struct inode * inode,struct file * file)215 static int xradio_temperature_open(struct inode *inode, struct file *file)
216 {
217 return single_open(file, &xradio_temperature_show, inode->i_private);
218 }
219
220 static const struct file_operations fops_temperature = {
221 .open = xradio_temperature_open,
222 .read = seq_read,
223 .llseek = seq_lseek,
224 .release = single_release,
225 .owner = THIS_MODULE,
226 };
227 #endif
228
xradio_status_show_common(struct seq_file * seq,void * v)229 static int xradio_status_show_common(struct seq_file *seq, void *v)
230 {
231 int i;
232 struct list_head *item;
233 struct xradio_common *hw_priv = seq->private;
234 struct xradio_debug_common *d = hw_priv->debug;
235 int ba_cnt, ba_acc, ba_cnt_rx, ba_acc_rx, ba_avg = 0, ba_avg_rx = 0;
236 bool ba_ena;
237
238 spin_lock_bh(&hw_priv->ba_lock);
239 ba_cnt = hw_priv->debug->ba_cnt;
240 ba_acc = hw_priv->debug->ba_acc;
241 ba_cnt_rx = hw_priv->debug->ba_cnt_rx;
242 ba_acc_rx = hw_priv->debug->ba_acc_rx;
243 ba_ena = hw_priv->ba_ena;
244 if (ba_cnt)
245 ba_avg = ba_acc / ba_cnt;
246 if (ba_cnt_rx)
247 ba_avg_rx = ba_acc_rx / ba_cnt_rx;
248 spin_unlock_bh(&hw_priv->ba_lock);
249
250 seq_puts(seq, "XRADIO Wireless LAN driver status\n");
251 seq_printf(seq, "Hardware: %d.%d\n",
252 hw_priv->wsm_caps.hardwareId,
253 hw_priv->wsm_caps.hardwareSubId);
254 seq_printf(seq, "Firmware: %s %d.%d\n",
255 xradio_debug_fw_types[hw_priv->wsm_caps.firmwareType],
256 hw_priv->wsm_caps.firmwareVersion,
257 hw_priv->wsm_caps.firmwareBuildNumber);
258 seq_printf(seq, "FW API: %d\n",
259 hw_priv->wsm_caps.firmwareApiVer);
260 seq_printf(seq, "FW caps: 0x%.4X\n",
261 hw_priv->wsm_caps.firmwareCap);
262 if (hw_priv->channel) {
263 seq_printf(seq, "Channel: %d%s\n",
264 hw_priv->channel->hw_value,
265 hw_priv->channel_switch_in_progress ?
266 " (switching)" : "");
267
268 seq_printf(seq, " flags: 0x%08x\n",
269 hw_priv->channel->flags);
270 }
271 seq_printf(seq, "HT: %s\n",
272 xradio_is_ht(&hw_priv->ht_info) ? "on" : "off");
273 if (xradio_is_ht(&hw_priv->ht_info)) {
274
275 #ifdef SUPPORT_HT40
276
277 seq_printf(seq, "2040BSS: %s\n",
278 xradio_is_2040BSS(&hw_priv->ht_info) ? "yes" : "no");
279
280 if (xradio_is_2040BSS(&hw_priv->ht_info)) {
281 switch (hw_priv->ht_info.channel_type) {
282 case NL80211_CHAN_HT40MINUS:
283 seq_printf(seq, "Second Chan:Below\n");
284 break;
285 case NL80211_CHAN_HT40PLUS:
286 seq_printf(seq, "Second Chan:Above\n");
287 break;
288 default:
289 break;
290 }
291 }
292
293 seq_printf(seq, "ShortGI: %s\n",
294 xradio_ht_ShortGI(&hw_priv->ht_info) ? "yes" : "no");
295
296 #endif
297
298 seq_printf(seq, "Greenfield: %s\n",
299 xradio_ht_greenfield(&hw_priv->ht_info) ? "yes" : "no");
300 seq_printf(seq, "AMPDU dens: %d\n",
301 xradio_ht_ampdu_density(&hw_priv->ht_info));
302 }
303 spin_lock_bh(&hw_priv->tx_policy_cache.lock);
304 i = 0;
305 list_for_each(item, &hw_priv->tx_policy_cache.used)
306 ++i;
307 spin_unlock_bh(&hw_priv->tx_policy_cache.lock);
308 seq_printf(seq, "RC in use: %d\n", i);
309 seq_printf(seq, "BA stat: %d, %d (%d)\n",
310 ba_cnt, ba_acc, ba_avg);
311 seq_printf(seq, "BA RX stat: %d, %d (%d)\n",
312 ba_cnt_rx, ba_acc_rx, ba_avg_rx);
313 seq_printf(seq, "Block ACK: %s\n", ba_ena ? "on" : "off");
314
315 seq_puts(seq, "\n");
316 for (i = 0; i < 4; ++i) {
317 xradio_queue_status_show(seq, &hw_priv->tx_queue[i]);
318 seq_puts(seq, "\n");
319 }
320 seq_printf(seq, "TX burst: %d\n",
321 d->tx_burst);
322 seq_printf(seq, "RX burst: %d\n",
323 d->rx_burst);
324 seq_printf(seq, "TX miss: %d\n",
325 d->tx_cache_miss);
326 seq_printf(seq, "Long retr: %d\n",
327 hw_priv->long_frame_max_tx_count);
328 seq_printf(seq, "Short retr: %d\n",
329 hw_priv->short_frame_max_tx_count);
330
331 seq_printf(seq, "BH status: %s, errcode=%d\n",
332 atomic_read(&hw_priv->bh_term) ? "terminated" : "alive",
333 hw_priv->bh_error);
334 seq_printf(seq, "Pending RX: %d\n",
335 atomic_read(&hw_priv->bh_rx));
336 seq_printf(seq, "Pending TX: %d\n",
337 atomic_read(&hw_priv->bh_tx));
338
339 seq_printf(seq, "TX bufs: %d x %d bytes\n",
340 hw_priv->wsm_caps.numInpChBufs,
341 hw_priv->wsm_caps.sizeInpChBuf);
342 seq_printf(seq, "Used bufs: %d\n",
343 hw_priv->hw_bufs_used);
344 #ifdef BH_PROC_THREAD
345 seq_printf(seq, "tx_queued: %d\n",
346 atomic_read(&hw_priv->proc.tx_queued));
347 seq_printf(seq, "rx_queued: %d\n",
348 atomic_read(&hw_priv->proc.rx_queued));
349 #endif
350 seq_printf(seq, "Powersavemode:%s\n",
351 hw_priv->powersave_enabled ? "enable" : "disable");
352 seq_printf(seq, "Device: %s\n",
353 hw_priv->device_can_sleep ? "alseep" : "awake");
354
355 spin_lock(&hw_priv->wsm_cmd.lock);
356 seq_printf(seq, "WSM status: %s\n",
357 hw_priv->wsm_cmd.done ? "idle" : "active");
358 seq_printf(seq, "WSM cmd: 0x%.4X (%zu bytes)\n",
359 hw_priv->wsm_cmd.cmd, hw_priv->wsm_cmd.len);
360 seq_printf(seq, "WSM retval: %d\n",
361 hw_priv->wsm_cmd.ret);
362 spin_unlock(&hw_priv->wsm_cmd.lock);
363
364 seq_printf(seq, "Datapath: %s\n",
365 atomic_read(&hw_priv->tx_lock) ? "locked" : "unlocked");
366 if (atomic_read(&hw_priv->tx_lock))
367 seq_printf(seq, "TXlock cnt: %d\n",
368 atomic_read(&hw_priv->tx_lock));
369
370 seq_printf(seq, "Scan: %s\n",
371 atomic_read(&hw_priv->scan.in_progress) ? "active" : "idle");
372 seq_printf(seq, "Led state: 0x%.2X\n",
373 hw_priv->softled_state);
374
375 return 0;
376 }
377
xradio_status_open_common(struct inode * inode,struct file * file)378 static int xradio_status_open_common(struct inode *inode, struct file *file)
379 {
380 return single_open(file, &xradio_status_show_common,
381 inode->i_private);
382 }
383
384 static const struct file_operations fops_status_common = {
385 .open = xradio_status_open_common,
386 .read = seq_read,
387 .llseek = seq_lseek,
388 .release = single_release,
389 .owner = THIS_MODULE,
390 };
391
xradio_counters_show(struct seq_file * seq,void * v)392 static int xradio_counters_show(struct seq_file *seq, void *v)
393 {
394 int ret;
395 struct xradio_common *hw_priv = seq->private;
396 struct wsm_counters_table counters;
397
398 ret = wsm_get_counters_table(hw_priv, &counters);
399 if (ret)
400 return ret;
401
402 #define CAT_STR(x, y) x ## y
403 #define PUT_COUNTER(tab, name) \
404 seq_printf(seq, "%s:" tab "%d\n", #name, \
405 __le32_to_cpu(counters.CAT_STR(count, name)))
406
407 PUT_COUNTER("\t\t\t\t", PlcpErrors);
408 PUT_COUNTER("\t\t\t\t", FcsErrors);
409 PUT_COUNTER("\t\t\t\t", TxPackets);
410 PUT_COUNTER("\t\t\t\t", RxPackets);
411 PUT_COUNTER("\t\t\t", RxPacketErrors);
412 PUT_COUNTER("\t\t\t\t", RtsSuccess);
413 PUT_COUNTER("\t\t\t", RtsFailures);
414 PUT_COUNTER("\t\t", RxFramesSuccess);
415 PUT_COUNTER("\t", RxDecryptionFailures);
416 PUT_COUNTER("\t\t\t", RxMicFailures);
417 PUT_COUNTER("\t\t", RxNoKeyFailures);
418 PUT_COUNTER("\t\t", TxMulticastFrames);
419 PUT_COUNTER("\t\t", TxFramesSuccess);
420 PUT_COUNTER("\t\t", TxFrameFailures);
421 PUT_COUNTER("\t\t", TxFramesRetried);
422 PUT_COUNTER("\t", TxFramesMultiRetried);
423 PUT_COUNTER("\t\t", RxFrameDuplicates);
424 PUT_COUNTER("\t\t\t", AckFailures);
425 PUT_COUNTER("\t\t", RxMulticastFrames);
426 PUT_COUNTER("\t\t", RxCMACICVErrors);
427 PUT_COUNTER("\t\t\t", RxCMACReplays);
428 PUT_COUNTER("\t\t", RxMgmtCCMPReplays);
429 PUT_COUNTER("\t\t\t", RxBIPMICErrors);
430
431 PUT_COUNTER("\t\t\t", AllBeacons);
432 PUT_COUNTER("\t\t\t", ScanBeacons);
433 PUT_COUNTER("\t\t\t", ScanProbeRsps);
434 PUT_COUNTER("\t\t\t", OutChanBeacons);
435 PUT_COUNTER("\t\t", OutChanProbeRsps);
436 PUT_COUNTER("\t\t\t", BssBeacons);
437 PUT_COUNTER("\t\t\t", HostBeacons);
438 PUT_COUNTER("\t\t\t", MissBeacons);
439 PUT_COUNTER("\t\t\t", DTIMBeacons);
440
441
442 #undef PUT_COUNTER
443 #undef CAT_STR
444
445 return 0;
446 }
447
xradio_counters_open(struct inode * inode,struct file * file)448 static int xradio_counters_open(struct inode *inode, struct file *file)
449 {
450 return single_open(file, &xradio_counters_show,
451 inode->i_private);
452 }
453
454 static const struct file_operations fops_counters = {
455 .open = xradio_counters_open,
456 .read = seq_read,
457 .llseek = seq_lseek,
458 .release = single_release,
459 .owner = THIS_MODULE,
460 };
461
xradio_backoff_show(struct seq_file * seq,void * v)462 static int xradio_backoff_show(struct seq_file *seq, void *v)
463 {
464 int ret;
465 struct xradio_common *hw_priv = seq->private;
466 struct wsm_backoff_counter counters;
467
468 ret = wsm_get_backoff_dbg(hw_priv, &counters);
469 if (ret)
470 return ret;
471
472 #define CAT_STR(x, y) x ## y
473 #define PUT_COUNTER(tab, name) \
474 seq_printf(seq, tab"%s:\t%d\n", #name, \
475 (__le32_to_cpu(counters.CAT_STR(count, name))&0xffff))
476
477 PUT_COUNTER("backoff_max ", 0);
478 PUT_COUNTER("[0, 7] ", 1);
479 PUT_COUNTER("[~, 15] ", 2);
480 PUT_COUNTER("[~, 31] ", 3);
481 PUT_COUNTER("[~, 63] ", 4);
482 PUT_COUNTER("[~, 127] ", 5);
483 PUT_COUNTER("[~, 255] ", 6);
484 PUT_COUNTER("[~, 511] ", 7);
485 PUT_COUNTER("[~, 1023] ", 8);
486
487
488 #undef PUT_COUNTER
489 #undef CAT_STR
490
491 return 0;
492 }
493
xradio_backoff_open(struct inode * inode,struct file * file)494 static int xradio_backoff_open(struct inode *inode, struct file *file)
495 {
496 return single_open(file, &xradio_backoff_show,
497 inode->i_private);
498 }
499
500 static const struct file_operations fops_backoff = {
501 .open = xradio_backoff_open,
502 .read = seq_read,
503 .llseek = seq_lseek,
504 .release = single_release,
505 .owner = THIS_MODULE,
506 };
507
508 #ifdef SUPPORT_HT40
509
xradio_ratemap_show(struct seq_file * seq,void * v)510 static int xradio_ratemap_show(struct seq_file *seq, void *v)
511 {
512 /* int ret; */
513 /* struct xradio_common *hw_priv = seq->private; */
514
515 #define PUT_TXRATE_COUNT(idx, bdsss, aofdm) do { \
516 seq_printf(seq, "MCS%d:" "[%8d][%8d] [%8d][%8d] %4s:" \
517 "[%8d] %3s:[%8d]\n", idx, \
518 __le32_to_cpu(TxedHtofdmRateMap[0][idx]), \
519 __le32_to_cpu(TxedHtofdmRateMap[1][idx]), \
520 __le32_to_cpu(TxedHtofdmRateMap[2][idx]), \
521 __le32_to_cpu(TxedHtofdmRateMap[3][idx]), \
522 #bdsss, __le32_to_cpu(TxedLegacyRateMap[0][idx]), \
523 #aofdm, __le32_to_cpu(TxedLegacyRateMap[1][idx]));\
524 TxedHtofdmRateMap[0][idx] = 0;\
525 TxedHtofdmRateMap[1][idx] = 0;\
526 TxedHtofdmRateMap[2][idx] = 0;\
527 TxedHtofdmRateMap[3][idx] = 0;\
528 TxedLegacyRateMap[0][idx] = 0;\
529 TxedLegacyRateMap[1][idx] = 0;\
530 } while (0)
531
532 seq_printf(seq, "\nTxRateMap:\n");
533 seq_printf(seq, " " "[20SGI TX][20LGI TX] " \
534 "[40SGI TX][40LGI TX] " \
535 " [DSSS TX] " \
536 " [OFDM TX]\n");
537
538 PUT_TXRATE_COUNT(7, 11MS, 54M);
539 PUT_TXRATE_COUNT(6, 11ML, 48M);
540 PUT_TXRATE_COUNT(5, 5M5S, 36M);
541 PUT_TXRATE_COUNT(4, 5M5L, 24M);
542 PUT_TXRATE_COUNT(3, 2MS, 18M);
543 PUT_TXRATE_COUNT(2, 2ML, 12M);
544 PUT_TXRATE_COUNT(1, ----, 9M);
545 PUT_TXRATE_COUNT(0, 1ML, 6M);
546
547 #undef PUT_TXRATE_COUNT
548
549 #define PUT_RXRATE_COUNT(idx, bdsss, aofdm) do { \
550 seq_printf(seq, "MCS%d:" "[%8d][%8d] [%8d][%8d] %4s:" \
551 "[%8d] %3s:[%8d]\n", idx, \
552 __le32_to_cpu(RxedHtofdmRateMap[0][idx]), \
553 __le32_to_cpu(RxedHtofdmRateMap[1][idx]), \
554 __le32_to_cpu(RxedHtofdmRateMap[2][idx]), \
555 __le32_to_cpu(RxedHtofdmRateMap[3][idx]), \
556 #bdsss, __le32_to_cpu(RxedLegacyRateMap[0][idx]), \
557 #aofdm, __le32_to_cpu(RxedLegacyRateMap[1][idx]));\
558 RxedHtofdmRateMap[0][idx] = 0;\
559 RxedHtofdmRateMap[1][idx] = 0;\
560 RxedHtofdmRateMap[2][idx] = 0;\
561 RxedHtofdmRateMap[3][idx] = 0;\
562 RxedLegacyRateMap[0][idx] = 0;\
563 RxedLegacyRateMap[1][idx] = 0;\
564 } while (0)
565
566 seq_printf(seq, "\nRxRateMap:\n");
567 seq_printf(seq, " " "[20SGI RX][20LGI RX] " \
568 "[40SGI RX][40LGI RX] " \
569 " [DSSS RX] " \
570 " [OFDM RX]\n");
571
572 PUT_RXRATE_COUNT(7, 11MS, 54M);
573 PUT_RXRATE_COUNT(6, 11ML, 48M);
574 PUT_RXRATE_COUNT(5, 5M5S, 36M);
575 PUT_RXRATE_COUNT(4, 5M5L, 24M);
576 PUT_RXRATE_COUNT(3, 2MS, 18M);
577 PUT_RXRATE_COUNT(2, 2ML, 12M);
578 PUT_RXRATE_COUNT(1, ----, 9M);
579 PUT_RXRATE_COUNT(0, 1ML, 6M);
580
581 #undef PUT_RXRATE_COUNT
582
583 return 0;
584 }
585
586 #else
587
xradio_ratemap_show(struct seq_file * seq,void * v)588 static int xradio_ratemap_show(struct seq_file *seq, void *v)
589 {
590 /* int ret; */
591 /* struct xradio_common *hw_priv = seq->private; */
592
593 seq_printf(seq, "\nRateMap for Tx & RX:\n");
594 #define PUT_RATE_COUNT(name, idx) do { \
595 seq_printf(seq, "%s\t" "%d, %d\n", #name, \
596 __le32_to_cpu(TxedRateIdx_Map[idx]), \
597 __le32_to_cpu(RxedRateIdx_Map[idx])); \
598 TxedRateIdx_Map[idx] = 0; \
599 RxedRateIdx_Map[idx] = 0; \
600 } while (0)
601
602 PUT_RATE_COUNT("65 Mbps:", 21);
603 PUT_RATE_COUNT("58.5 Mbps:", 20);
604 PUT_RATE_COUNT("52 Mbps:", 19);
605 PUT_RATE_COUNT("39 Mbps:", 18);
606 PUT_RATE_COUNT("26 Mbps:", 17);
607 PUT_RATE_COUNT("19.5 Mbps:", 16);
608 PUT_RATE_COUNT("13 Mbps:", 15);
609 PUT_RATE_COUNT("6.5 Mbps:", 14);
610
611 PUT_RATE_COUNT("54 Mbps:", 13);
612 PUT_RATE_COUNT("48 Mbps:", 12);
613 PUT_RATE_COUNT("36 Mbps:", 11);
614 PUT_RATE_COUNT("24 Mbps:", 10);
615 PUT_RATE_COUNT("18 Mbps:", 9);
616 PUT_RATE_COUNT("12 Mbps:", 8);
617 PUT_RATE_COUNT("9 Mbps:", 7);
618 PUT_RATE_COUNT("6 Mbps:", 6);
619
620 PUT_RATE_COUNT("11 Mbps:", 3);
621 PUT_RATE_COUNT("5.5 Mbps:", 2);
622 PUT_RATE_COUNT("2 Mbps:", 1);
623 PUT_RATE_COUNT("1 Mbps:", 0);
624
625 #undef PUT_RATE_COUNT
626
627 return 0;
628 }
629
630 #endif
631
xradio_ratemap_open(struct inode * inode,struct file * file)632 static int xradio_ratemap_open(struct inode *inode, struct file *file)
633 {
634 return single_open(file, &xradio_ratemap_show,
635 inode->i_private);
636 }
637
638 static const struct file_operations fops_ratemap = {
639 .open = xradio_ratemap_open,
640 .read = seq_read,
641 .llseek = seq_lseek,
642 .release = single_release,
643 .owner = THIS_MODULE,
644 };
645
xradio_ampducounters_show(struct seq_file * seq,void * v)646 static int xradio_ampducounters_show(struct seq_file *seq, void *v)
647 {
648 int ret;
649 struct xradio_common *hw_priv = seq->private;
650 struct wsm_ampducounters_table counters;
651
652 ret = wsm_get_ampducounters_table(hw_priv, &counters);
653 if (ret)
654 return ret;
655
656 #define CAT_STR(x, y) x ## y
657 #define PUT_COUNTER(tab, name) \
658 seq_printf(seq, "%s:" tab "%d\n", #name, \
659 __le32_to_cpu(counters.CAT_STR(count, name)))
660
661 PUT_COUNTER("\t\t\t", TxAMPDUs);
662 PUT_COUNTER("\t\t", TxMPDUsInAMPDUs);
663 PUT_COUNTER("\t\t", TxOctetsInAMPDUs_l32);
664 PUT_COUNTER("\t\t", TxOctetsInAMPDUs_h32);
665 PUT_COUNTER("\t\t\t", RxAMPDUs);
666 PUT_COUNTER("\t\t", RxMPDUsInAMPDUs);
667 PUT_COUNTER("\t\t", RxOctetsInAMPDUs_l32);
668 PUT_COUNTER("\t\t", RxOctetsInAMPDUs_h32);
669 PUT_COUNTER("\t", RxDelimeterCRCErrorCount);
670 PUT_COUNTER("\t\t", ImplictBARFailures);
671 PUT_COUNTER("\t\t", ExplictBARFailures);
672
673
674
675 #undef PUT_COUNTER
676 #undef CAT_STR
677
678 return 0;
679 }
680
xradio_ampducounters_open(struct inode * inode,struct file * file)681 static int xradio_ampducounters_open(struct inode *inode, struct file *file)
682 {
683 return single_open(file, &xradio_ampducounters_show,
684 inode->i_private);
685 }
686
687 static const struct file_operations fops_ampducounters = {
688 .open = xradio_ampducounters_open,
689 .read = seq_read,
690 .llseek = seq_lseek,
691 .release = single_release,
692 .owner = THIS_MODULE,
693 };
694
xradio_txpipe_show(struct seq_file * seq,void * v)695 static int xradio_txpipe_show(struct seq_file *seq, void *v)
696 {
697 int ret;
698 struct xradio_common *hw_priv = seq->private;
699 struct wsm_txpipe_counter counters;
700
701 ret = wsm_get_txpipe_table(hw_priv, &counters);
702 if (ret)
703 return ret;
704
705 #define CAT_STR(x, y) x ## y
706 #define PUT_COUNTER(tab, name) \
707 seq_printf(seq, tab":\t%d\n", \
708 __le32_to_cpu(counters.CAT_STR(count, name)))
709
710 PUT_COUNTER("tx-aggr ", 1);
711 PUT_COUNTER("retx-aggr ", 2);
712 PUT_COUNTER("retry_type1 ", 3);
713 PUT_COUNTER("retry_type2 ", 4);
714 PUT_COUNTER("retry_type3 ", 5);
715 PUT_COUNTER("rx-aggr-event ", 6);
716 PUT_COUNTER("rx-aggr-end ", 7);
717 PUT_COUNTER("rx-ba ", 8);
718 PUT_COUNTER("tx_ampdu_len ", 9);
719 PUT_COUNTER("fail_by_rts ", a);
720
721
722 #undef PUT_COUNTER
723 #undef CAT_STR
724
725 return 0;
726 }
727
xradio_txpipe_open(struct inode * inode,struct file * file)728 static int xradio_txpipe_open(struct inode *inode, struct file *file)
729 {
730 return single_open(file, &xradio_txpipe_show,
731 inode->i_private);
732 }
733
734 static const struct file_operations fops_txpipe = {
735 .open = xradio_txpipe_open,
736 .read = seq_read,
737 .llseek = seq_lseek,
738 .release = single_release,
739 .owner = THIS_MODULE,
740 };
741
742 #if (SUPPORT_EPTA)
743
744 u32 epta_stat_dbg_ctrl = 0x484;
745 char *med_state_str[4] = {
746 "bt inactive",
747 "with bt and wlan not waiting",
748 "with wlan",
749 "with bt and wlan waiting"
750 };
751 char *req_type_str[11] = {
752 "rx_recovery", "rx_mcast", "rx_bcn", "tx_bcn", "tx_cts", "tx_high", "tx_uapsd", "fastps",
753 "scan", "pspoll", "tx_low"
754 };
755
xradio_epta_stat_show(struct seq_file * seq,void * v)756 static int xradio_epta_stat_show(struct seq_file *seq, void *v)
757 {
758 int ret, i;
759 struct xradio_epta_stat epta_stat;
760 struct xradio_common *hw_priv = seq->private;
761
762 // memset(&epta_stat, 0, sizeof(epta_stat));
763 ret = wsm_get_epta_statistics(hw_priv, &epta_stat);
764 #if 0
765 seq_printf(seq, "\n================\n");
766 for (i = 0; i < sizeof(epta_stat); i++) {
767 if (i % 4 == 0)
768 seq_printf(seq, "%d:\t ", i);
769 seq_printf(seq, "%2x ", *((u8 *)&epta_stat+i));
770 if ((i+1) % 4 == 0)
771 seq_printf(seq, "\n");
772 }
773 seq_printf(seq, "\n================\n");
774 #endif
775 if (ret)
776 return ret;
777
778 seq_printf(seq, "\n[epta statistics]\n");
779 seq_printf(seq, "medium state: %s\n", med_state_str[epta_stat.medium_state]);
780 if (epta_stat.medium_state == 0)
781 return 0;
782 if (epta_stat.wlan_req_ongoing) {
783 //req got into epta from lmc_epta but not granted or aborted yet
784 }
785 if (epta_stat.medium_state == 2) {
786 seq_printf(seq, "current req :[type:%s][prio_sw:%u][prio_hw:%u][req dur:%u]\n", req_type_str[epta_stat.wlan_req_type],
787 epta_stat.wlan_req_priority & 0xf, (epta_stat.wlan_req_priority >> 4) & 0xf, __le32_to_cpu(epta_stat.wlan_req_request_dur));
788 // seq_printf(seq, "current req granted time: \t %u\n", __le32_to_cpu(epta_stat.grant_or_wait_time));
789 } else if (epta_stat.medium_state == 3) {
790 seq_printf(seq, "current req :[type:%s][prio_sw:%u][prio_hw:%u][req dur:%u]\n", req_type_str[epta_stat.wlan_req_type],
791 epta_stat.wlan_req_priority & 0xf, (epta_stat.wlan_req_priority >> 4) & 0xf, __le32_to_cpu(epta_stat.wlan_req_request_dur));
792 // seq_printf(seq, "wlan is waiting for bt: \t\t %u\n", __le32_to_cpu(epta_stat.grant_or_wait_time));
793 } else {
794 seq_printf(seq, "current req :\n");
795 }
796
797 seq_printf(seq, "=========================wlan req info========================\n");
798
799 seq_printf(seq, " %10s ", "all");
800 for (i = 0; i < 11; i++)
801 if (epta_stat_dbg_ctrl & (1<<i))
802 seq_printf(seq, "%10s ", req_type_str[i]);
803 seq_printf(seq, "\n");
804 seq_printf(seq, "req win cnt: %10u %10u %10u %10u\n", __le32_to_cpu(epta_stat.wl_req_info[0].cnt_win), __le32_to_cpu(epta_stat.wl_req_info[1].cnt_win),
805 __le32_to_cpu(epta_stat.wl_req_info[2].cnt_win), __le32_to_cpu(epta_stat.wl_req_info[3].cnt_win));
806 seq_printf(seq, "req lose cnt: %10u %10u %10u %10u\n", __le32_to_cpu(epta_stat.wl_req_info[0].cnt_lose), __le32_to_cpu(epta_stat.wl_req_info[1].cnt_lose),
807 __le32_to_cpu(epta_stat.wl_req_info[2].cnt_lose), __le32_to_cpu(epta_stat.wl_req_info[3].cnt_lose));
808
809 seq_printf(seq, "grant med ret cnt: %10u %10u %10u %10u\n", __le16_to_cpu(epta_stat.wl_req_info[0].cnt_grant_med_ret), __le16_to_cpu(epta_stat.wl_req_info[1].cnt_grant_med_ret),
810 __le16_to_cpu(epta_stat.wl_req_info[2].cnt_grant_med_ret), __le16_to_cpu(epta_stat.wl_req_info[3].cnt_grant_med_ret));
811 seq_printf(seq, "grant timeout cnt: %10u %10u %10u %10u\n", __le16_to_cpu(epta_stat.wl_req_info[0].cnt_grant_timeout), __le16_to_cpu(epta_stat.wl_req_info[1].cnt_grant_timeout),
812 __le16_to_cpu(epta_stat.wl_req_info[2].cnt_grant_timeout), __le16_to_cpu(epta_stat.wl_req_info[3].cnt_grant_timeout));
813 seq_printf(seq, "abort misss rx cnt:%10u %10u %10u %10u\n", __le16_to_cpu(epta_stat.wl_req_info[0].cnt_abort_miss_rx), __le16_to_cpu(epta_stat.wl_req_info[1].cnt_abort_miss_rx),
814 __le16_to_cpu(epta_stat.wl_req_info[2].cnt_abort_miss_rx), __le16_to_cpu(epta_stat.wl_req_info[3].cnt_abort_miss_rx));
815 seq_printf(seq, "abort expired cnt: %10u %10u %10u %10u\n", __le16_to_cpu(epta_stat.wl_req_info[0].cnt_abort_expired), __le16_to_cpu(epta_stat.wl_req_info[1].cnt_abort_expired),
816 __le16_to_cpu(epta_stat.wl_req_info[2].cnt_abort_expired), __le16_to_cpu(epta_stat.wl_req_info[3].cnt_abort_expired));
817
818 seq_printf(seq, "granted time: %10u %10u %10u %10u\n", __le32_to_cpu(epta_stat.wl_req_info[0].granted_time), __le32_to_cpu(epta_stat.wl_req_info[1].granted_time),
819 __le32_to_cpu(epta_stat.wl_req_info[2].granted_time), __le32_to_cpu(epta_stat.wl_req_info[3].granted_time));
820 seq_printf(seq, "granted used time: %10u %10u %10u %10u\n", __le32_to_cpu(epta_stat.wl_req_info[0].gr_used_time), __le32_to_cpu(epta_stat.wl_req_info[1].gr_used_time),
821 __le32_to_cpu(epta_stat.wl_req_info[2].gr_used_time), __le32_to_cpu(epta_stat.wl_req_info[3].gr_used_time));
822
823 seq_printf(seq, "\n");
824 seq_printf(seq, "%25s %17s %18s\n", "[req ext cnt] grant_uapsd", "abort_rx_bcn", "abort_pspoll");
825 seq_printf(seq, "%25u %17u %18u\n", __le16_to_cpu(epta_stat.cnt_ex_grant_uapsd),
826 __le16_to_cpu(epta_stat.cnt_ex_abort_rx_bcn), __le16_to_cpu(epta_stat.cnt_ex_abort_pspoll));
827
828 seq_printf(seq, "%25s %17s %18s\n", "[bt abort cnt] total", "abort_tx", "abort_tx_fix");
829 seq_printf(seq, "%25u %17u %18u\n", __le16_to_cpu(epta_stat.cnt_bt_abort),
830 __le16_to_cpu(epta_stat.cnt_bt_abort_tx), __le16_to_cpu(epta_stat.cnt_bt_abort_tx_fix));
831
832 seq_printf(seq, "========================bt tx req type========================\n");
833 seq_printf(seq, "%4s %13s %13s %14s %14s\n", "poll", "dm1", "br", "edr", "sco");
834 seq_printf(seq, "%4u %13u %13u %14u %14u\n", __le16_to_cpu(epta_stat.cnt_bt_tx_poll_pkt_req),
835 __le16_to_cpu(epta_stat.cnt_bt_tx_dm1_pkt_req), __le16_to_cpu(epta_stat.cnt_bt_tx_br_pkt_req),
836 __le16_to_cpu(epta_stat.cnt_bt_tx_edr_pkt_req), __le16_to_cpu(epta_stat.cnt_bt_tx_sco_pkt_req));
837
838 seq_printf(seq, "=======================wlan/bt nrt info=======================\n");
839 seq_printf(seq, "%13s %14s %7s %10s %14s\n", "wl_quota_used", " bt_quota_used", "bt_req", "gr_bt_req", "gr_bt_max_gap");
840 seq_printf(seq, "%13u %14u %7u %10u %14u\n", __le32_to_cpu(epta_stat.nrt_wlan_quota_used), __le32_to_cpu(epta_stat.nrt_bt_quota_used),
841 __le32_to_cpu(epta_stat.nrt_bt_requests), __le32_to_cpu(epta_stat.nrt_bt_granted_requestd), __le32_to_cpu(epta_stat.nrt_bt_granted_req_max_gap));
842 seq_printf(seq, "\n");
843
844 for (i = 0; i < epta_stat.num_active_rt_bt_links; i++) {
845 struct xradio_epta_bt_link_info *bt_link_info = &epta_stat.bt_link_info[i];
846 seq_printf(seq, "=======================rt bt link idx %u=======================\n", i);
847 seq_printf(seq, "%6s: %-3u %12s: %-2u %13s: %-3u %9s: %-1u\n", "linkid", bt_link_info->link_id, "type ", bt_link_info->traffic_type,
848 "master", bt_link_info->master_or_slave, "prio_sw ", bt_link_info->traffic_priority);
849 seq_printf(seq, "%6s: %7u %8s: %7u %8s: %-3u %9s: %-1u\n", "rt_si ", __le32_to_cpu(bt_link_info->rt_si), "rt_sw ", __le32_to_cpu(bt_link_info->rt_sw),
850 "req ", __le32_to_cpu(bt_link_info->requests), "prio_hw_rt ", ((__le32_to_cpu(bt_link_info->time_diff_req_start)) >> 4) & 0xf);
851 seq_printf(seq, "%6s: %7u %8s: %7u %8s: %-3u %9s: %-1u\n", "msg_si", __le32_to_cpu(bt_link_info->msg_si), "msg_sw", __le32_to_cpu(bt_link_info->msg_sw),
852 "gr_req", __le32_to_cpu(bt_link_info->granted_requests), "prio_hw_nrt", (__le32_to_cpu(bt_link_info->time_diff_req_start)) & 0xf);
853
854 seq_printf(seq, "%6s: %-3u %14s: %-3u\n", "caton ", __le32_to_cpu(bt_link_info->bt_caton_num), "tx_retry", __le32_to_cpu(bt_link_info->bt_tx_retry_num));
855
856 /*if (bt_link_info->curr_req_ongoing)
857 seq_printf(seq, "time_from_cur_req_start : %7d\n", __le32_to_cpu(bt_link_info->time_diff_req_start));
858 else
859 seq_printf(seq, "time_to_next_req_start : %7d\n", __le32_to_cpu(bt_link_info->time_diff_req_start)); //unuse */
860 }
861
862 return 0;
863 }
864
xradio_epta_stat_open(struct inode * inode,struct file * file)865 static int xradio_epta_stat_open(struct inode *inode, struct file *file)
866 {
867 return single_open(file, &xradio_epta_stat_show,
868 inode->i_private);
869 }
870
871 static const struct file_operations fops_epta_stat = {
872 .open = xradio_epta_stat_open,
873 .read = seq_read,
874 .llseek = seq_lseek,
875 .release = single_release,
876 .owner = THIS_MODULE,
877 };
878
xradio_epta_stat_dbg_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)879 static ssize_t xradio_epta_stat_dbg_write(struct file *file,
880 const char __user *user_buf, size_t count, loff_t *ppos)
881 {
882 struct xradio_common *hw_priv = file->private_data;
883 char buf[12] = {0};
884 char *endptr = NULL;
885 u32 dbg_val = 0;
886
887 count = (count > 11 ? 11 : count);
888
889 if (!count)
890 return -EINVAL;
891 if (copy_from_user(buf, user_buf, count))
892 return -EFAULT;
893 dbg_val = simple_strtoul(buf, &endptr, 16);
894 if (count_ones(dbg_val) > 3 || dbg_val > 0x7ff) {
895 SYS_WARN(1);
896 return count;
897 }
898 epta_stat_dbg_ctrl = dbg_val;
899 xradio_dbg(XRADIO_DBG_ALWY, "epta_stat_dbg_ctrl = 0x%x\n", epta_stat_dbg_ctrl);
900 SYS_WARN(wsm_set_epta_stat_dbg_ctrl(hw_priv, epta_stat_dbg_ctrl));
901
902 return count;
903 }
904
xradio_epta_stat_dbg_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)905 static ssize_t xradio_epta_stat_dbg_read(struct file *file,
906 char __user *user_buf, size_t count, loff_t *ppos)
907 {
908 /* struct xradio_common *hw_priv = file->private_data; */
909 char buf[50];
910 size_t size = 0;
911
912 sprintf(buf, "epta_stat_dbg_ctrl = 0x%x\n", epta_stat_dbg_ctrl);
913 size = strlen(buf);
914
915 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
916 }
917 #endif
918
919 static int count_idx;
920
921 #ifdef SUPPORT_HT40
922
xradio_dbgstats_show(struct seq_file * seq,void * v)923 static int xradio_dbgstats_show(struct seq_file *seq, void *v)
924 {
925 int ret;
926 int avg_ampdu_len = 0;
927 int FrameFail_ratio = 0;
928 int FailByRts_ratio = 0;
929 int FrameRetry_ratio = 0;
930 int AMPDURetry_ratio = 0;
931 int Retry1_ratio = 0;
932 int Retry2_ratio = 0;
933 int Retry3_ratio = 0;
934 struct xradio_common *hw_priv = seq->private;
935 struct wsm_counters_table counters;
936 struct wsm_ampducounters_table ampdu_counters;
937 struct wsm_txpipe_counter txpipe;
938
939 ret = wsm_get_counters_table(hw_priv, &counters);
940 if (ret)
941 return ret;
942
943 ret = wsm_get_txpipe_table(hw_priv, &txpipe);
944 if (ret)
945 return ret;
946
947 ret = wsm_get_ampducounters_table(hw_priv, &du_counters);
948 if (ret)
949 return ret;
950
951 #define CAT_STR(x, y) x ## y
952
953 #define PUT_COUNTER(tab, name) \
954 seq_printf(seq, tab "%d\n", \
955 __le32_to_cpu(counters.CAT_STR(count, name)))
956
957 #define PUT_AMPDU_COUNTER(tab, name) \
958 seq_printf(seq, tab "%d\n", \
959 __le32_to_cpu(ampdu_counters.CAT_STR(count, name)))
960
961 #define PUT_TXPIPE(tab, name) \
962 seq_printf(seq, tab "%d\n", \
963 __le32_to_cpu(txpipe.CAT_STR(count, name)))
964
965 if (ampdu_counters.countTxAMPDUs) {
966 avg_ampdu_len = (int)((ampdu_counters.countTxMPDUsInAMPDUs + \
967 (ampdu_counters.countTxAMPDUs>>1)) \
968 /ampdu_counters.countTxAMPDUs);
969 AMPDURetry_ratio = (int)(ampdu_counters.countImplictBARFailures * \
970 100/ampdu_counters.countTxAMPDUs);
971 }
972 if (counters.countAckFailures) {
973 Retry1_ratio = (int)(txpipe.count3*100/counters.countAckFailures);
974 Retry2_ratio = (int)(txpipe.count4*100/counters.countAckFailures);
975 Retry3_ratio = (int)(txpipe.count5*100/counters.countAckFailures);
976 }
977 if (ampdu_counters.countTxMPDUsInAMPDUs) {
978 FrameFail_ratio = (int)(counters.countTxFrameFailures * \
979 1000/ampdu_counters.countTxMPDUsInAMPDUs);
980 FrameRetry_ratio = (int)(counters.countAckFailures * \
981 100/ampdu_counters.countTxMPDUsInAMPDUs);
982 }
983
984 if (counters.countTxFrameFailures)
985 FailByRts_ratio = (int)(txpipe.counta * \
986 100/counters.countTxFrameFailures);
987
988 seq_printf(seq, "===========================================\n");
989 seq_printf(seq, " %02d\n", count_idx);
990 seq_printf(seq, "===========================================\n");
991 count_idx++;
992 count_idx = count_idx % 100;
993 PUT_COUNTER("RtsSuccess: ", RtsSuccess);
994 PUT_COUNTER("RtsFailures: ", RtsFailures);
995 seq_printf(seq, "Avg_AMPDU_Len: %d\n", __le32_to_cpu(avg_ampdu_len));
996 PUT_AMPDU_COUNTER("TxAMPDUs: ", TxAMPDUs);
997 PUT_AMPDU_COUNTER("TxMPDUsInAMPDUs: ", TxMPDUsInAMPDUs);
998 /* PUT_COUNTER ("TxFrameRetries: ", AckFailures); */
999 /* PUT_COUNTER ("TxFrameFailures: ", TxFrameFailures); */
1000 PUT_TXPIPE("Failure_By_Rts: ", a);
1001 /* PUT_AMPDU_COUNTER("BA-RX-Fails ", ImplictBARFailures);
1002 PUT_AMPDU_COUNTER("TxAMPDUs ", TxAMPDUs);
1003 PUT_TXPIPE ("ReTx-AMPDUs ", 2);
1004 PUT_TXPIPE ("Retry_type1 ", 3);
1005 PUT_TXPIPE ("Retry_type2 ", 4);
1006 PUT_TXPIPE ("Retry_type3 ", 5); */
1007 seq_printf(seq, "==============\n");
1008 seq_printf(seq, "FrameFail_ratio: %d%%%%\n",
1009 __le32_to_cpu(FrameFail_ratio));
1010 seq_printf(seq, "FailByRts_ratio: %d%%\n",
1011 __le32_to_cpu(FailByRts_ratio));
1012 seq_printf(seq, "FrameRetry_ratio: %d%%\n",
1013 __le32_to_cpu(FrameRetry_ratio));
1014 seq_printf(seq, "AMPDURetry_ratio: %d%%\n",
1015 __le32_to_cpu(AMPDURetry_ratio));
1016 seq_printf(seq, "Retry1_ratio: %d%%\n",
1017 __le32_to_cpu(Retry1_ratio));
1018 seq_printf(seq, "Retry2_ratio: %d%%\n",
1019 __le32_to_cpu(Retry2_ratio));
1020 seq_printf(seq, "Retry3_ratio: %d%%\n",
1021 __le32_to_cpu(Retry3_ratio));
1022
1023 seq_printf(seq, "==============\n");
1024
1025
1026
1027 #define PUT_TXRATE_COUNT(idx, bdsss, aofdm) do { \
1028 seq_printf(seq, "MCS%d:" "[%8d][%8d] [%8d][%8d] %4s:" \
1029 "[%8d] %3s:[%8d]\n", idx, \
1030 __le32_to_cpu(TxedHtofdmRateMap[0][idx]), \
1031 __le32_to_cpu(TxedHtofdmRateMap[1][idx]), \
1032 __le32_to_cpu(TxedHtofdmRateMap[2][idx]), \
1033 __le32_to_cpu(TxedHtofdmRateMap[3][idx]), \
1034 #bdsss, __le32_to_cpu(TxedLegacyRateMap[0][idx]), \
1035 #aofdm, __le32_to_cpu(TxedLegacyRateMap[1][idx]));\
1036 TxedHtofdmRateMap[0][idx] = 0;\
1037 TxedHtofdmRateMap[1][idx] = 0;\
1038 TxedHtofdmRateMap[2][idx] = 0;\
1039 TxedHtofdmRateMap[3][idx] = 0;\
1040 TxedLegacyRateMap[0][idx] = 0;\
1041 TxedLegacyRateMap[1][idx] = 0;\
1042 } while (0)
1043
1044 seq_printf(seq, "\nTxRateMap:\n");
1045 seq_printf(seq, " " "[20SGI TX][20LGI TX] " \
1046 "[40SGI TX][40LGI TX] " \
1047 " [DSSS TX] " \
1048 " [OFDM TX]\n");
1049
1050 PUT_TXRATE_COUNT(7, 11MS, 54M);
1051 PUT_TXRATE_COUNT(6, 11ML, 48M);
1052 PUT_TXRATE_COUNT(5, 5M5S, 36M);
1053 PUT_TXRATE_COUNT(4, 5M5L, 24M);
1054 PUT_TXRATE_COUNT(3, 2MS, 18M);
1055 PUT_TXRATE_COUNT(2, 2ML, 12M);
1056 PUT_TXRATE_COUNT(1, ----, 9M);
1057 PUT_TXRATE_COUNT(0, 1ML, 6M);
1058
1059 #undef PUT_TXRATE_COUNT
1060
1061 #define PUT_RXRATE_COUNT(idx, bdsss, aofdm) do { \
1062 seq_printf(seq, "MCS%d:" "[%8d][%8d] [%8d][%8d] %4s:" \
1063 "[%8d] %3s:[%8d]\n", idx, \
1064 __le32_to_cpu(RxedHtofdmRateMap[0][idx]), \
1065 __le32_to_cpu(RxedHtofdmRateMap[1][idx]), \
1066 __le32_to_cpu(RxedHtofdmRateMap[2][idx]), \
1067 __le32_to_cpu(RxedHtofdmRateMap[3][idx]), \
1068 #bdsss, __le32_to_cpu(RxedLegacyRateMap[0][idx]), \
1069 #aofdm, __le32_to_cpu(RxedLegacyRateMap[1][idx]));\
1070 RxedHtofdmRateMap[0][idx] = 0;\
1071 RxedHtofdmRateMap[1][idx] = 0;\
1072 RxedHtofdmRateMap[2][idx] = 0;\
1073 RxedHtofdmRateMap[3][idx] = 0;\
1074 RxedLegacyRateMap[0][idx] = 0;\
1075 RxedLegacyRateMap[1][idx] = 0;\
1076 } while (0)
1077
1078 seq_printf(seq, "\nRxRateMap:\n");
1079 seq_printf(seq, " " "[20SGI RX][20LGI RX] " \
1080 "[40SGI RX][40LGI RX] " \
1081 " [DSSS RX] " \
1082 " [OFDM RX]\n");
1083
1084 PUT_RXRATE_COUNT(7, 11MS, 54M);
1085 PUT_RXRATE_COUNT(6, 11ML, 48M);
1086 PUT_RXRATE_COUNT(5, 5M5S, 36M);
1087 PUT_RXRATE_COUNT(4, 5M5L, 24M);
1088 PUT_RXRATE_COUNT(3, 2MS, 18M);
1089 PUT_RXRATE_COUNT(2, 2ML, 12M);
1090 PUT_RXRATE_COUNT(1, ----, 9M);
1091 PUT_RXRATE_COUNT(0, 1ML, 6M);
1092
1093 #undef PUT_RXRATE_COUNT
1094
1095 #undef PUT_COUNTER
1096 #undef PUT_AMPDU_COUNTER
1097 #undef PUT_TXPIPE
1098 #undef CAT_STR
1099
1100 return 0;
1101 }
1102
1103 #else
1104
xradio_dbgstats_show(struct seq_file * seq,void * v)1105 static int xradio_dbgstats_show(struct seq_file *seq, void *v)
1106 {
1107 int ret;
1108 int avg_ampdu_len = 0;
1109 int FrameFail_ratio = 0;
1110 int FailByRts_ratio = 0;
1111 int FrameRetry_ratio = 0;
1112 int AMPDURetry_ratio = 0;
1113 int Retry1_ratio = 0;
1114 int Retry2_ratio = 0;
1115 int Retry3_ratio = 0;
1116 struct xradio_common *hw_priv = seq->private;
1117 struct wsm_counters_table counters;
1118 struct wsm_ampducounters_table ampdu_counters;
1119 struct wsm_txpipe_counter txpipe;
1120
1121 ret = wsm_get_counters_table(hw_priv, &counters);
1122 if (ret)
1123 return ret;
1124
1125 ret = wsm_get_txpipe_table(hw_priv, &txpipe);
1126 if (ret)
1127 return ret;
1128
1129 ret = wsm_get_ampducounters_table(hw_priv, &du_counters);
1130 if (ret)
1131 return ret;
1132
1133 #define CAT_STR(x, y) x ## y
1134
1135 #define PUT_COUNTER(tab, name) \
1136 seq_printf(seq, tab "%d\n", \
1137 __le32_to_cpu(counters.CAT_STR(count, name)))
1138
1139 #define PUT_AMPDU_COUNTER(tab, name) \
1140 seq_printf(seq, tab "%d\n", \
1141 __le32_to_cpu(ampdu_counters.CAT_STR(count, name)))
1142
1143 #define PUT_TXPIPE(tab, name) \
1144 seq_printf(seq, tab "%d\n", \
1145 __le32_to_cpu(txpipe.CAT_STR(count, name)))
1146
1147 #define PUT_RATE_COUNT(name, idx) do { \
1148 seq_printf(seq, "%s\t%d\n", #name, \
1149 __le32_to_cpu(TxedRateIdx_Map[idx])); \
1150 TxedRateIdx_Map[idx] = 0; \
1151 } while (0)
1152
1153 if (ampdu_counters.countTxAMPDUs) {
1154 avg_ampdu_len = (int)((ampdu_counters.countTxMPDUsInAMPDUs + \
1155 (ampdu_counters.countTxAMPDUs>>1)) \
1156 /ampdu_counters.countTxAMPDUs);
1157 AMPDURetry_ratio = (int)(ampdu_counters.countImplictBARFailures * \
1158 100/ampdu_counters.countTxAMPDUs);
1159 }
1160 if (counters.countAckFailures) {
1161 Retry1_ratio = (int)(txpipe.count3*100/counters.countAckFailures);
1162 Retry2_ratio = (int)(txpipe.count4*100/counters.countAckFailures);
1163 Retry3_ratio = (int)(txpipe.count5*100/counters.countAckFailures);
1164 }
1165 if (ampdu_counters.countTxMPDUsInAMPDUs) {
1166 FrameFail_ratio = (int)(counters.countTxFrameFailures * \
1167 1000/ampdu_counters.countTxMPDUsInAMPDUs);
1168 FrameRetry_ratio = (int)(counters.countAckFailures * \
1169 100/ampdu_counters.countTxMPDUsInAMPDUs);
1170 }
1171
1172 if (counters.countTxFrameFailures)
1173 FailByRts_ratio = (int)(txpipe.counta * \
1174 100/counters.countTxFrameFailures);
1175
1176 seq_printf(seq, "===========================================\n");
1177 seq_printf(seq, " %02d\n", count_idx);
1178 seq_printf(seq, "===========================================\n");
1179 count_idx++;
1180 count_idx = count_idx%100;
1181 PUT_COUNTER ("RtsSuccess: ", RtsSuccess);
1182 PUT_COUNTER ("RtsFailures: ", RtsFailures);
1183 seq_printf(seq, "Avg_AMPDU_Len: %d\n", __le32_to_cpu(avg_ampdu_len));
1184 PUT_AMPDU_COUNTER("TxAMPDUs: ", TxAMPDUs);
1185 PUT_AMPDU_COUNTER("TxMPDUsInAMPDUs: ", TxMPDUsInAMPDUs);
1186 /* PUT_COUNTER ("TxFrameRetries: ", AckFailures); */
1187 /* PUT_COUNTER ("TxFrameFailures: ", TxFrameFailures); */
1188 PUT_TXPIPE ("Failure_By_Rts: ", a);
1189 /* PUT_AMPDU_COUNTER("BA-RX-Fails ", ImplictBARFailures);
1190 PUT_AMPDU_COUNTER("TxAMPDUs ", TxAMPDUs);
1191 PUT_TXPIPE ("ReTx-AMPDUs ", 2);
1192 PUT_TXPIPE ("Retry_type1 ", 3);
1193 PUT_TXPIPE ("Retry_type2 ", 4);
1194 PUT_TXPIPE ("Retry_type3 ", 5); */
1195 seq_printf(seq, "==============\n");
1196 seq_printf(seq, "FrameFail_ratio: %d%%%%\n",
1197 __le32_to_cpu(FrameFail_ratio));
1198 seq_printf(seq, "FailByRts_ratio: %d%%\n",
1199 __le32_to_cpu(FailByRts_ratio));
1200 seq_printf(seq, "FrameRetry_ratio: %d%%\n",
1201 __le32_to_cpu(FrameRetry_ratio));
1202 seq_printf(seq, "AMPDURetry_ratio: %d%%\n",
1203 __le32_to_cpu(AMPDURetry_ratio));
1204 seq_printf(seq, "Retry1_ratio: %d%%\n",
1205 __le32_to_cpu(Retry1_ratio));
1206 seq_printf(seq, "Retry2_ratio: %d%%\n",
1207 __le32_to_cpu(Retry2_ratio));
1208 seq_printf(seq, "Retry3_ratio: %d%%\n",
1209 __le32_to_cpu(Retry3_ratio));
1210
1211 seq_printf(seq, "==============\n");
1212 PUT_RATE_COUNT("65 Mbps:", 21);
1213 PUT_RATE_COUNT("58.5 Mbps:", 20);
1214 PUT_RATE_COUNT("52 Mbps:", 19);
1215 PUT_RATE_COUNT("39 Mbps:", 18);
1216 PUT_RATE_COUNT("26 Mbps:", 17);
1217 PUT_RATE_COUNT("19.5 Mbps:", 16);
1218 PUT_RATE_COUNT("13 Mbps:", 15);
1219 PUT_RATE_COUNT("6.5 Mbps:", 14);
1220
1221 #undef PUT_COUNTER
1222 #undef PUT_AMPDU_COUNTER
1223 #undef PUT_TXPIPE
1224 #undef PUT_RATE_COUNT
1225 #undef CAT_STR
1226
1227 return 0;
1228 }
1229
1230 #endif
1231
xradio_dbgstats_open(struct inode * inode,struct file * file)1232 static int xradio_dbgstats_open(struct inode *inode, struct file *file)
1233 {
1234 return single_open(file, &xradio_dbgstats_show, inode->i_private);
1235 }
1236
1237 static const struct file_operations fops_dbgstats = {
1238 .open = xradio_dbgstats_open,
1239 .read = seq_read,
1240 .llseek = seq_lseek,
1241 .release = single_release,
1242 .owner = THIS_MODULE,
1243 };
1244
xradio_generic_open(struct inode * inode,struct file * file)1245 static int xradio_generic_open(struct inode *inode, struct file *file)
1246 {
1247 file->private_data = inode->i_private;
1248 return 0;
1249 }
1250
xradio_11n_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)1251 static ssize_t xradio_11n_read(struct file *file,
1252 char __user *user_buf, size_t count, loff_t *ppos)
1253 {
1254 struct xradio_common *hw_priv = file->private_data;
1255 struct ieee80211_supported_band *band =
1256 hw_priv->hw->wiphy->bands[NL80211_BAND_2GHZ];
1257 return simple_read_from_buffer(user_buf, count, ppos,
1258 band->ht_cap.ht_supported ? "1\n" : "0\n", 2);
1259 }
1260
xradio_11n_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1261 static ssize_t xradio_11n_write(struct file *file,
1262 const char __user *user_buf, size_t count, loff_t *ppos)
1263 {
1264 struct xradio_common *hw_priv = file->private_data;
1265 struct ieee80211_supported_band *band[2] = {
1266 hw_priv->hw->wiphy->bands[NL80211_BAND_2GHZ],
1267 hw_priv->hw->wiphy->bands[NL80211_BAND_5GHZ],
1268 };
1269 char buf[1];
1270 int ena = 0;
1271
1272 if (!count)
1273 return -EINVAL;
1274 if (copy_from_user(buf, user_buf, 1))
1275 return -EFAULT;
1276 if (buf[0] == 1)
1277 ena = 1;
1278
1279 band[0]->ht_cap.ht_supported = ena;
1280 #ifdef CONFIG_XRADIO_5GHZ_SUPPORT
1281 band[1]->ht_cap.ht_supported = ena;
1282 #endif /* CONFIG_XRADIO_5GHZ_SUPPORT */
1283
1284 return count;
1285 }
1286
1287 static const struct file_operations fops_11n = {
1288 .open = xradio_generic_open,
1289 .read = xradio_11n_read,
1290 .write = xradio_11n_write,
1291 .llseek = default_llseek,
1292 };
1293
1294
1295 static u32 fwdbg_ctrl;
1296
xradio_fwdbg_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1297 static ssize_t xradio_fwdbg_write(struct file *file,
1298 const char __user *user_buf, size_t count, loff_t *ppos)
1299 {
1300 struct xradio_common *hw_priv = file->private_data;
1301 char buf[12] = {0};
1302 char *endptr = NULL;
1303
1304 count = (count > 11 ? 11 : count);
1305
1306 if (!count)
1307 return -EINVAL;
1308 if (copy_from_user(buf, user_buf, count))
1309 return -EFAULT;
1310 fwdbg_ctrl = simple_strtoul(buf, &endptr, 16);
1311 xradio_dbg(XRADIO_DBG_ALWY, "fwdbg_ctrl = %d\n", fwdbg_ctrl);
1312 SYS_WARN(wsm_set_fw_debug_control(hw_priv, fwdbg_ctrl, 0));
1313
1314 return count;
1315 }
1316
xradio_fwdbg_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)1317 static ssize_t xradio_fwdbg_read(struct file *file,
1318 char __user *user_buf, size_t count, loff_t *ppos)
1319 {
1320 /* struct xradio_common *hw_priv = file->private_data; */
1321 char buf[50];
1322 size_t size = 0;
1323
1324 sprintf(buf, "fwdbg_ctrl = %u\n", fwdbg_ctrl);
1325 size = strlen(buf);
1326
1327 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
1328 }
1329 static const struct file_operations fops_fwdbg = {
1330 .open = xradio_generic_open,
1331 .write = xradio_fwdbg_write,
1332 .read = xradio_fwdbg_read,
1333 .llseek = default_llseek,
1334 };
1335
1336 /* read/write fw registers */
xradio_fwreg_rw(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1337 static ssize_t xradio_fwreg_rw(struct file *file,
1338 const char __user *user_buf, size_t count, loff_t *ppos)
1339 {
1340 struct xradio_common *hw_priv = file->private_data;
1341 char buf[256] = {0};
1342 u16 buf_size = (count > 255 ? 255 : count);
1343 char *startptr = &buf[0];
1344 char *endptr = NULL;
1345 u16 flag = 0;
1346 int i, end = 16;
1347
1348 if (!count)
1349 return -EINVAL;
1350 if (copy_from_user(buf, user_buf, buf_size))
1351 return -EFAULT;
1352
1353 flag = simple_strtoul(startptr, &endptr, 16);
1354 startptr = endptr+1;
1355 if (flag & WSM_REG_RW_F) { /* write */
1356 WSM_REG_W reg_w;
1357 reg_w.flag = flag;
1358 reg_w.data_size = 0;
1359 if (flag & WSM_REG_BK_F)
1360 end = 2;
1361
1362 for (i = 0; (i < end) && ((buf + buf_size - 12) > endptr); i++) {
1363 reg_w.arg[i].reg_addr = simple_strtoul(startptr, &endptr, 16);
1364 startptr = endptr + 1;
1365 reg_w.arg[i].reg_val = simple_strtoul(startptr, &endptr, 16);
1366 startptr = endptr + 1;
1367 }
1368 if (i)
1369 reg_w.data_size = 4 + i * 8;
1370 xradio_dbg(XRADIO_DBG_ALWY, "W:flag=0x%x, size=%d\n",
1371 reg_w.flag, reg_w.data_size);
1372 wsm_write_mib(hw_priv, WSM_MIB_ID_RW_FW_REG,
1373 (void *)®_w, reg_w.data_size, 0);
1374
1375 } else { /* read */
1376 WSM_REG_R reg_r;
1377 reg_r.flag = flag;
1378 reg_r.data_size = 0;
1379 if (flag & WSM_REG_BK_F)
1380 end = 2;
1381
1382 for (i = 0; (i < end) && ((buf + buf_size - 6) > endptr); i++) {
1383 reg_r.arg[i] = simple_strtoul(startptr, &endptr, 16);
1384 startptr = endptr + 1;
1385 }
1386 if (i)
1387 reg_r.data_size = 4 + i * 4;
1388
1389 wsm_read_mib(hw_priv, WSM_MIB_ID_RW_FW_REG, (void *)®_r,
1390 sizeof(WSM_REG_R), reg_r.data_size);
1391
1392 xradio_dbg(XRADIO_DBG_ALWY, "R:flag=0x%x, size=%d\n",
1393 reg_r.flag, reg_r.data_size);
1394
1395 end = (reg_r.data_size >> 2) - 1;
1396 if (!end || !(reg_r.flag & WSM_REG_RET_F))
1397 return count;
1398
1399 for (i = 0; i < end; i++) {
1400 xradio_dbg(XRADIO_DBG_ALWY, "0x%08x ", reg_r.arg[i]);
1401 if ((i & 3) == 3)
1402 xradio_dbg(XRADIO_DBG_ALWY, "\n");
1403 }
1404 xradio_dbg(XRADIO_DBG_ALWY, "\n");
1405 }
1406 return count;
1407 }
1408
1409 static const struct file_operations fops_rw_fwreg = {
1410 .open = xradio_generic_open,
1411 .write = xradio_fwreg_rw,
1412 .llseek = default_llseek,
1413 };
1414
1415 /* This ops only used in bh error occured already.
1416 * It can be dangerous to use it in normal status. */
xradio_fwreg_rw_direct(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1417 static ssize_t xradio_fwreg_rw_direct(struct file *file,
1418 const char __user *user_buf, size_t count, loff_t *ppos)
1419 {
1420 /* for H64 HIF test */
1421 struct xradio_common *hw_priv = file->private_data;
1422 char buf[256] = { 0 };
1423 u16 buf_size = (count > 255 ? 255 : count);
1424 char *startptr = &buf[0];
1425 char *endptr = NULL;
1426 u16 flag = 0;
1427 int i, end = 16;
1428
1429 if (!count)
1430 return -EINVAL;
1431 if (copy_from_user(buf, user_buf, buf_size))
1432 return -EFAULT;
1433
1434 flag = simple_strtoul(startptr, &endptr, 16);
1435 startptr = endptr + 1;
1436 if (flag & WSM_REG_RW_F) { /* write */
1437 int ret = 0;
1438 u32 val32 = 0;
1439 WSM_REG_W reg_w;
1440 reg_w.flag = flag;
1441 reg_w.data_size = 0;
1442 if (flag & WSM_REG_BK_F)
1443 end = 2;
1444
1445 for (i = 0; (i < end) && ((buf + buf_size - 12) > endptr); i++) {
1446 reg_w.arg[i].reg_addr = simple_strtoul(startptr, &endptr, 16);
1447 startptr = endptr + 1;
1448 reg_w.arg[i].reg_val = simple_strtoul(startptr, &endptr, 16);
1449 startptr = endptr + 1;
1450 }
1451
1452 if (!(reg_w.arg[0].reg_addr & 0xffff0000)) { /* means write register */
1453 ret = xradio_reg_write_32(hw_priv,
1454 reg_w.arg[0].reg_addr, reg_w.arg[0].reg_val);
1455 if (ret < 0) {
1456 xradio_dbg(XRADIO_DBG_ERROR, "%s:test HIF R/W [register]-- " \
1457 "write CONFIG err, ret is %d! \n",
1458 __func__, ret);
1459 } else {
1460 xradio_dbg(XRADIO_DBG_ALWY, "%s:test HIF R/W [register]]-- " \
1461 "write register @0x%x, val is 0x%x\n",
1462 __func__, reg_w.arg[0].reg_addr,
1463 reg_w.arg[0].reg_val);
1464 }
1465 } else { /* means write memory */
1466 /* change to direct mode */
1467 ret = xradio_reg_read_32(hw_priv, HIF_CONFIG_REG_ID, &val32);
1468 if (ret < 0) {
1469 xradio_dbg(XRADIO_DBG_ERROR, "%s:test HIF R/W -- " \
1470 "reading CONFIG err, ret is %d! \n", __func__, ret);
1471 }
1472 ret = xradio_reg_write_32(hw_priv, HIF_CONFIG_REG_ID,
1473 val32 | HIF_CONFIG_ACCESS_MODE_BIT);
1474 if (ret < 0) {
1475 xradio_dbg(XRADIO_DBG_ERROR, "%s:test HIF R/W -- " \
1476 "setting direct mode err, ret is %d! \n",
1477 __func__, ret);
1478 }
1479
1480 ret = xradio_ahb_write_32(hw_priv, reg_w.arg[0].reg_addr,
1481 reg_w.arg[0].reg_val);
1482 if (ret < 0) {
1483 xradio_dbg(XRADIO_DBG_ERROR,
1484 "%s:AHB write test, val of addr %x is %x! \n",
1485 __func__, reg_w.arg[0].reg_addr, reg_w.arg[0].reg_val);
1486 }
1487
1488 /* return to queue mode */
1489 ret = xradio_reg_write_32(hw_priv, HIF_CONFIG_REG_ID,
1490 val32 & ~HIF_CONFIG_ACCESS_MODE_BIT);
1491 if (ret < 0) {
1492 xradio_dbg(XRADIO_DBG_ERROR, "%s:test HIF R/W -- " \
1493 "setting queue mode err, ret is %d! \n", __func__, ret);
1494 }
1495 }
1496 } else { /* read */
1497 WSM_REG_R reg_r;
1498 u32 val32 = 0;
1499 u32 mem_val = 0;
1500 int ret = 0;
1501 reg_r.flag = flag;
1502 reg_r.data_size = 0;
1503 if (flag & WSM_REG_BK_F)
1504 end = 2;
1505
1506 for (i = 0; (i < end) && ((buf + buf_size - 6) > endptr); i++) {
1507 reg_r.arg[i] = simple_strtoul(startptr, &endptr, 16);
1508 startptr = endptr + 1;
1509 }
1510 /* if (i) reg_r.data_size = 4+i*4; */
1511 if (!(reg_r.arg[0] & 0xffff0000)) { /* means read register */
1512 ret = xradio_reg_read_32(hw_priv, (u16)reg_r.arg[0], &val32);
1513 if (ret < 0) {
1514 xradio_dbg(XRADIO_DBG_ERROR, "%s:test HIF R/W [register]-- " \
1515 "reading CONFIG err, ret is %d! \n",
1516 __func__, ret);
1517 }
1518 xradio_dbg(XRADIO_DBG_ALWY, "%s:test HIF R/W [register]]-- " \
1519 "reading register @0x%x, val is 0x%x\n",
1520 __func__, reg_r.arg[0], val32);
1521 } else { /* means read memory */
1522
1523 /* change to direct mode */
1524 ret = xradio_reg_read_32(hw_priv, HIF_CONFIG_REG_ID, &val32);
1525 if (ret < 0) {
1526 xradio_dbg(XRADIO_DBG_ERROR, "%s:test HIF R/W -- " \
1527 "reading CONFIG err, ret is %d! \n",
1528 __func__, ret);
1529 }
1530 ret = xradio_reg_write_32(hw_priv, HIF_CONFIG_REG_ID,
1531 val32 | HIF_CONFIG_ACCESS_MODE_BIT);
1532 if (ret < 0) {
1533 xradio_dbg(XRADIO_DBG_ERROR, "%s:test HIF R/W -- " \
1534 "setting direct mode err, ret is %d! \n",
1535 __func__, ret);
1536 }
1537
1538 if (reg_r.arg[0] & 0x08000000) {
1539 ret = xradio_ahb_read_32(hw_priv, reg_r.arg[0], &mem_val);
1540 if (ret < 0) {
1541 xradio_dbg(XRADIO_DBG_ERROR, "%s:AHB read test err, " \
1542 "val of addr %08x is %08x \n",
1543 __func__, reg_r.arg[0], mem_val);
1544 }
1545 xradio_dbg(XRADIO_DBG_ALWY, "[%08x] = 0x%08x\n",
1546 reg_r.arg[0], mem_val);
1547 } else if (reg_r.arg[0] & 0x09000000) {
1548 ret = xradio_apb_read_32(hw_priv, reg_r.arg[0], &mem_val);
1549 if (ret < 0) {
1550 xradio_dbg(XRADIO_DBG_ERROR, "%s:APB read test err, " \
1551 "val of addr %08x is %08x \n",
1552 __func__, reg_r.arg[0], mem_val);
1553 }
1554 xradio_dbg(XRADIO_DBG_ALWY, "[%08x] = 0x%08x\n",
1555 reg_r.arg[0], mem_val);
1556 }
1557
1558 /* return to queue mode */
1559 ret = xradio_reg_write_32(hw_priv, HIF_CONFIG_REG_ID,
1560 val32 & ~HIF_CONFIG_ACCESS_MODE_BIT);
1561 if (ret < 0) {
1562 xradio_dbg(XRADIO_DBG_ERROR, "%s:test HIF R/W -- " \
1563 "setting queue mode err, ret is %d! \n",
1564 __func__, ret);
1565 }
1566 }
1567 }
1568 return count;
1569 }
1570 static const struct file_operations fops_rw_fwreg_direct = {
1571 .open = xradio_generic_open,
1572 .write = xradio_fwreg_rw_direct,
1573 .llseek = default_llseek,
1574 };
1575 /* setting ampdu_len */
1576 u16 ampdu_len[2] = {16, 16};
xradio_ampdu_len_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1577 static ssize_t xradio_ampdu_len_write(struct file *file,
1578 const char __user *user_buf, size_t count, loff_t *ppos)
1579 {
1580 struct xradio_common *hw_priv = file->private_data;
1581 char buf[12] = { 0 };
1582 char *endptr = NULL;
1583 u8 if_id = 0;
1584
1585 count = (count > 11 ? 11 : count);
1586
1587 if (!count)
1588 return -EINVAL;
1589 if (copy_from_user(buf, user_buf, count))
1590 return -EFAULT;
1591 if_id = simple_strtoul(buf, &endptr, 10);
1592 ampdu_len[if_id] = simple_strtoul(endptr + 1, NULL, 10);
1593
1594 xradio_dbg(XRADIO_DBG_ALWY, "vif=%d, ampdu_len = %d\n",
1595 if_id, ampdu_len[if_id]);
1596 wsm_write_mib(hw_priv, WSM_MIB_ID_SET_AMPDU_NUM,
1597 &du_len[if_id], sizeof(u16), if_id);
1598
1599 return count;
1600 }
1601
xradio_ampdu_len_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)1602 static ssize_t xradio_ampdu_len_read(struct file *file,
1603 char __user *user_buf, size_t count, loff_t *ppos)
1604 {
1605 /* struct xradio_common *hw_priv = file->private_data; */
1606 char buf[100];
1607 size_t size = 0;
1608
1609 sprintf(buf, "ampdu_len(0)=%d, (1)=%d\n", ampdu_len[0], ampdu_len[1]);
1610 size = strlen(buf);
1611
1612 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
1613 }
1614
1615 static const struct file_operations fops_ampdu_len = {
1616 .open = xradio_generic_open,
1617 .write = xradio_ampdu_len_write,
1618 .read = xradio_ampdu_len_read,
1619 .llseek = default_llseek,
1620 };
1621
1622
1623 /* setting rts threshold. */
1624 u32 rts_threshold[2] = {3000, 3000};
xradio_rts_threshold_get(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)1625 static ssize_t xradio_rts_threshold_get(struct file *file,
1626 char __user *user_buf, size_t count, loff_t *ppos)
1627 {
1628 /* struct xradio_common *hw_priv = file->private_data; */
1629 char buf[100];
1630 size_t size = 0;
1631
1632 sprintf(buf, "rts_threshold(0)=%d, (1)=%d\n",
1633 rts_threshold[0], rts_threshold[1]);
1634 size = strlen(buf);
1635
1636 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
1637 }
1638
xradio_rts_threshold_set(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1639 static ssize_t xradio_rts_threshold_set(struct file *file,
1640 const char __user *user_buf, size_t count, loff_t *ppos)
1641 {
1642 struct xradio_common *hw_priv = file->private_data;
1643 char buf[12] = { 0 };
1644 char *endptr = NULL;
1645 u8 if_id = 0;
1646
1647 count = (count > 11 ? 11 : count);
1648 if (!count)
1649 return -EINVAL;
1650 if (copy_from_user(buf, user_buf, count))
1651 return -EFAULT;
1652 if_id = simple_strtoul(buf, &endptr, 10);
1653 rts_threshold[if_id] = simple_strtoul(endptr + 1, NULL, 10);
1654
1655 xradio_dbg(XRADIO_DBG_ALWY, "vif=%d, rts_threshold = %d\n",
1656 if_id, rts_threshold[if_id]);
1657 wsm_write_mib(hw_priv, WSM_MIB_ID_DOT11_RTS_THRESHOLD,
1658 &rts_threshold[if_id], sizeof(u32), if_id);
1659
1660 return count;
1661 }
1662
1663 static const struct file_operations fops_rts_threshold = {
1664 .open = xradio_generic_open,
1665 .write = xradio_rts_threshold_set,
1666 .read = xradio_rts_threshold_get,
1667 .llseek = default_llseek,
1668 };
1669
1670 /* disable low power mode. */
1671 u8 low_pwr_disable;
xradio_low_pwr_get(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)1672 static ssize_t xradio_low_pwr_get(struct file *file,
1673 char __user *user_buf, size_t count, loff_t *ppos)
1674 {
1675 /* struct xradio_common *hw_priv = file->private_data; */
1676 char buf[100];
1677 size_t size = 0;
1678
1679 sprintf(buf, "low_pwr_disable=%d\n", low_pwr_disable);
1680 size = strlen(buf);
1681
1682 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
1683 }
1684
xradio_low_pwr_set(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1685 static ssize_t xradio_low_pwr_set(struct file *file,
1686 const char __user *user_buf, size_t count, loff_t *ppos)
1687 {
1688 struct xradio_common *hw_priv = file->private_data;
1689 char buf[12] = { 0 };
1690 char *endptr = NULL;
1691 int if_id = 0;
1692 u32 val = wsm_power_mode_quiescent;
1693
1694 count = (count > 11 ? 11 : count);
1695 if (!count)
1696 return -EINVAL;
1697 if (copy_from_user(buf, user_buf, count))
1698 return -EFAULT;
1699 low_pwr_disable = simple_strtoul(buf, &endptr, 16);
1700 xradio_dbg(XRADIO_DBG_ALWY, "low_pwr_disable=%d\n", low_pwr_disable);
1701
1702 if (low_pwr_disable)
1703 val = wsm_power_mode_active;
1704
1705 val |= BIT(4); /* disableMoreFlagUsage */
1706
1707 for (if_id = 0; if_id < xrwl_get_nr_hw_ifaces(hw_priv); if_id++)
1708 wsm_write_mib(hw_priv, WSM_MIB_ID_OPERATIONAL_POWER_MODE, &val,
1709 sizeof(val), if_id);
1710
1711 return count;
1712 }
1713
1714 static const struct file_operations fops_low_pwr = {
1715 .open = xradio_generic_open,
1716 .write = xradio_low_pwr_set,
1717 .read = xradio_low_pwr_get,
1718 .llseek = default_llseek,
1719 };
1720
1721 /* disable ps mode(80211 protol). */
xradio_ps_get(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)1722 static ssize_t xradio_ps_get(struct file *file,
1723 char __user *user_buf, size_t count, loff_t *ppos)
1724 {
1725 /* struct xradio_common *hw_priv = file->private_data; */
1726 char buf[100];
1727 size_t size = 0;
1728
1729 sprintf(buf, "ps_disable=%d, idleperiod=%d, changeperiod=%d\n",
1730 ps_disable, ps_idleperiod, ps_changeperiod);
1731 size = strlen(buf);
1732
1733 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
1734 }
1735
xradio_ps_set(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1736 static ssize_t xradio_ps_set(struct file *file,
1737 const char __user *user_buf, size_t count, loff_t *ppos)
1738 {
1739 struct xradio_common *hw_priv = file->private_data;
1740 char buf[20] = { 0 };
1741 char *start = &buf[0];
1742 char *endptr = NULL;
1743 struct wsm_set_pm ps = {
1744 .pmMode = WSM_PSM_FAST_PS,
1745 .fastPsmIdlePeriod = 0xC8 /* defaut 100ms */
1746 };
1747
1748 count = (count > 19 ? 19 : count);
1749 if (!count)
1750 return -EINVAL;
1751 if (copy_from_user(buf, user_buf, count))
1752 return -EFAULT;
1753
1754 ps_disable = simple_strtoul(start, &endptr, 10);
1755 start = endptr + 1;
1756 if (start < buf + count)
1757 ps_idleperiod = simple_strtoul(start, &endptr, 10) & 0xff;
1758 start = endptr + 1;
1759 if (start < buf + count)
1760 ps_changeperiod = simple_strtoul(start, &endptr, 10) & 0xff;
1761
1762 xradio_dbg(XRADIO_DBG_ALWY,
1763 "ps_disable=%d, idleperiod=%d, changeperiod=%d\n",
1764 ps_disable, ps_idleperiod, ps_changeperiod);
1765
1766 /* set pm for debug */
1767 if (ps_disable)
1768 ps.pmMode = WSM_PSM_ACTIVE;
1769 if (ps_idleperiod)
1770 ps.fastPsmIdlePeriod = ps_idleperiod << 1;
1771 if (ps_changeperiod)
1772 ps.apPsmChangePeriod = ps_changeperiod << 1;
1773
1774 wsm_set_pm(hw_priv, &ps, 0);
1775 if (hw_priv->vif_list[1])
1776 wsm_set_pm(hw_priv, &ps, 1);
1777
1778 return count;
1779 }
1780
1781 static const struct file_operations fops_ps_ctrl = {
1782 .open = xradio_generic_open,
1783 .write = xradio_ps_set,
1784 .read = xradio_ps_get,
1785 .llseek = default_llseek,
1786 };
1787
1788 /* for retry debug. */
1789 u8 retry_dbg;
1790 u8 tx_short; /* save orgin value. */
1791 u8 tx_long; /* save orgin value. */
1792
xradio_retry_get(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)1793 static ssize_t xradio_retry_get(struct file *file,
1794 char __user *user_buf, size_t count, loff_t *ppos)
1795 {
1796 struct xradio_common *hw_priv = file->private_data;
1797 char buf[100];
1798 size_t size = 0;
1799
1800 sprintf(buf, "retry_dbg=%d, short=%d, long=%d\n", retry_dbg,
1801 hw_priv->short_frame_max_tx_count,
1802 hw_priv->long_frame_max_tx_count);
1803 size = strlen(buf);
1804
1805 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
1806 }
1807
xradio_retry_set(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1808 static ssize_t xradio_retry_set(struct file *file,
1809 const char __user *user_buf, size_t count, loff_t *ppos)
1810 {
1811 struct xradio_common *hw_priv = file->private_data;
1812 char buf[20] = { 0 };
1813 char *start = &buf[0];
1814 char *endptr = NULL;
1815
1816 count = (count > 19 ? 19 : count);
1817 if (!count)
1818 return -EINVAL;
1819 if (copy_from_user(buf, user_buf, count))
1820 return -EFAULT;
1821 retry_dbg = (simple_strtoul(start, &endptr, 10) & 0x1);
1822 if (retry_dbg) { /* change retry.*/
1823 if (!tx_short)
1824 tx_short = hw_priv->short_frame_max_tx_count;
1825 if (!tx_long)
1826 tx_long = hw_priv->long_frame_max_tx_count;
1827 start = endptr + 1;
1828 if (start < buf + count) {
1829 hw_priv->short_frame_max_tx_count =
1830 simple_strtoul(start, &endptr, 10) & 0xf;
1831 start = endptr + 1;
1832 if (start < buf + count)
1833 hw_priv->long_frame_max_tx_count =
1834 simple_strtoul(start, &endptr, 10) & 0xf;
1835 }
1836 xradio_dbg(XRADIO_DBG_ALWY, "retry_dbg on, s=%d, l=%d\n",
1837 hw_priv->short_frame_max_tx_count,
1838 hw_priv->long_frame_max_tx_count);
1839 } else { /* restore retry. */
1840 if (tx_short) {
1841 hw_priv->short_frame_max_tx_count = tx_short;
1842 tx_short = 0;
1843 }
1844 if (tx_long) {
1845 hw_priv->long_frame_max_tx_count = tx_long;
1846 tx_long = 0;
1847 }
1848 xradio_dbg(XRADIO_DBG_ALWY, "retry_dbg off, s=%d, l=%d\n",
1849 hw_priv->short_frame_max_tx_count,
1850 hw_priv->long_frame_max_tx_count);
1851 }
1852 retry_dbg |= 0x2;
1853 return count;
1854 }
1855
1856 static const struct file_operations fops_retry_ctrl = {
1857 .open = xradio_generic_open,
1858 .write = xradio_retry_set,
1859 .read = xradio_retry_get,
1860 .llseek = default_llseek,
1861 };
1862
1863 /* for rates debug. */
1864
1865 #ifdef SUPPORT_HT40
1866
1867 u8 rates_dbg_en;
1868 u16 rates_debug[6] = {0x0};
1869 u8 Ratecnt_dbg;
1870
xradio_rates_get(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)1871 static ssize_t xradio_rates_get(struct file *file,
1872 char __user *user_buf, size_t count, loff_t *ppos)
1873 {
1874 /* struct xradio_common *hw_priv = file->private_data; */
1875 char buf[200];
1876 size_t size = 0;
1877 sprintf(buf, "rates_dbg_en=%d, [0]=0x%04x, [1]=0x%04x, [2]=0x%04x " \
1878 "[3]=0x%04x, [4]=0x%04x, [5]=0x%04x\n", (rates_dbg_en & 0x1),
1879 rates_debug[0], rates_debug[1], rates_debug[2],
1880 rates_debug[3], rates_debug[4], rates_debug[5]);
1881 size = strlen(buf);
1882
1883 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
1884 }
1885
xradio_rates_set(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1886 static ssize_t xradio_rates_set(struct file *file,
1887 const char __user *user_buf, size_t count, loff_t *ppos)
1888 {
1889 /* struct xradio_common *hw_priv = file->private_data; */
1890 char buf[50] = {0};
1891 char *start = &buf[0];
1892 char *endptr = NULL;
1893 int i = 0;
1894 count = (count > 49 ? 49 : count);
1895
1896 if (!count)
1897 return -EINVAL;
1898 if (copy_from_user(buf, user_buf, count))
1899 return -EFAULT;
1900
1901 rates_dbg_en &= ~0x1;
1902 if (simple_strtoul(start, &endptr, 10)) {
1903 for (i = 0; i < 6; i++) {
1904 start = endptr+1;
1905 if (start < buf+count)
1906 rates_debug[i] = simple_strtoul(start, &endptr, 16);
1907 else
1908 break;
1909 }
1910
1911 Ratecnt_dbg = i;
1912 rates_dbg_en = 0x1;
1913
1914 if (Ratecnt_dbg)
1915 xradio_dbg(XRADIO_DBG_ERROR, "rates_dbg on, entry_cnt=%d!\n", Ratecnt_dbg);
1916 else
1917 xradio_dbg(XRADIO_DBG_ERROR, "rates_dbg fail, invaid params!\n");
1918
1919 } else {
1920 xradio_dbg(XRADIO_DBG_ERROR, "rates_dbg off\n");
1921 }
1922 return count;
1923 }
1924
1925 #else
1926
1927 u8 rates_dbg_en;
1928 u32 rates_debug[3];
1929 u8 maxRate_dbg;
1930
xradio_rates_get(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)1931 static ssize_t xradio_rates_get(struct file *file,
1932 char __user *user_buf, size_t count, loff_t *ppos)
1933 {
1934 /* struct xradio_common *hw_priv = file->private_data; */
1935 char buf[100];
1936 size_t size = 0;
1937 sprintf(buf, "rates_dbg_en=%d, [0]=0x%08x, [1]=0x%08x, [2]=0x%08x\n",
1938 (rates_dbg_en & 0x1), rates_debug[2],
1939 rates_debug[1], rates_debug[0]);
1940 size = strlen(buf);
1941
1942 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
1943 }
1944
xradio_rates_set(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1945 static ssize_t xradio_rates_set(struct file *file,
1946 const char __user *user_buf, size_t count, loff_t *ppos)
1947 {
1948 /* struct xradio_common *hw_priv = file->private_data; */
1949 char buf[50] = { 0 };
1950 char *start = &buf[0];
1951 char *endptr = NULL;
1952 int i = 0;
1953 count = (count > 49 ? 49 : count);
1954
1955 if (!count)
1956 return -EINVAL;
1957 if (copy_from_user(buf, user_buf, count))
1958 return -EFAULT;
1959
1960 rates_dbg_en &= ~0x1;
1961 if (simple_strtoul(start, &endptr, 10)) {
1962 start = endptr + 1;
1963 if (start < buf + count)
1964 rates_debug[2] = simple_strtoul(start, &endptr, 16);
1965
1966 start = endptr + 1;
1967 if (start < buf + count)
1968 rates_debug[1] = simple_strtoul(start, &endptr, 16);
1969
1970 start = endptr + 1;
1971 if (start < buf + count)
1972 rates_debug[0] = simple_strtoul(start, &endptr, 16);
1973
1974 for (i = 21; i >= 0; i--) {
1975 if ((rates_debug[i >> 3] >> ((i & 0x7) << 2)) & 0xf) {
1976 maxRate_dbg = i;
1977 rates_dbg_en |= 0x1;
1978 break;
1979 }
1980 }
1981 if (rates_dbg_en & 0x1) {
1982 xradio_dbg(XRADIO_DBG_ALWY,
1983 "rates_dbg on, maxrate=%d!\n", maxRate_dbg);
1984 } else {
1985 xradio_dbg(XRADIO_DBG_ALWY, "rates_dbg fail, invaid params!\n");
1986 }
1987 } else {
1988 xradio_dbg(XRADIO_DBG_ALWY, "rates_dbg off\n");
1989 }
1990 return count;
1991 }
1992
1993 #endif
1994
1995 static const struct file_operations fops_rates_ctrl = {
1996 .open = xradio_generic_open,
1997 .write = xradio_rates_set,
1998 .read = xradio_rates_get,
1999 .llseek = default_llseek,
2000 };
2001
2002
2003 /* for backoff setting. */
2004 struct wsm_backoff_ctrl backoff_ctrl;
2005
xradio_backoff_ctrl_get(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)2006 static ssize_t xradio_backoff_ctrl_get(struct file *file,
2007 char __user *user_buf, size_t count, loff_t *ppos)
2008 {
2009 /* struct xradio_common *hw_priv = file->private_data; */
2010 char buf[100];
2011 size_t size = 0;
2012 sprintf(buf, "backoff_ctrl_en=%d, min=%d, max=%d\n",
2013 backoff_ctrl.enable,
2014 backoff_ctrl.min,
2015 backoff_ctrl.max);
2016 size = strlen(buf);
2017
2018 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
2019 }
2020
xradio_backoff_ctrl_set(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)2021 static ssize_t xradio_backoff_ctrl_set(struct file *file,
2022 const char __user *user_buf, size_t count, loff_t *ppos)
2023 {
2024 struct xradio_common *hw_priv = file->private_data;
2025 char buf[20] = { 0 };
2026 char *start = &buf[0];
2027 char *endptr = NULL;
2028 count = (count > 19 ? 19 : count);
2029
2030 if (!count)
2031 return -EINVAL;
2032 if (copy_from_user(buf, user_buf, count))
2033 return -EFAULT;
2034 backoff_ctrl.enable = simple_strtoul(start, &endptr, 10);
2035 if (backoff_ctrl.enable) {
2036 start = endptr + 1;
2037 if (start < buf + count)
2038 backoff_ctrl.min = simple_strtoul(start, &endptr, 10);
2039 start = endptr + 1;
2040 if (start < buf + count)
2041 backoff_ctrl.max = simple_strtoul(start, &endptr, 10);
2042
2043 xradio_dbg(XRADIO_DBG_ALWY, "backoff_ctrl on\n");
2044 } else {
2045 xradio_dbg(XRADIO_DBG_ALWY, "backoff_ctrl off\n");
2046 }
2047 wsm_set_backoff_ctrl(hw_priv, &backoff_ctrl);
2048 return count;
2049 }
2050
2051 static const struct file_operations fops_backoff_ctrl = {
2052 .open = xradio_generic_open,
2053 .write = xradio_backoff_ctrl_set,
2054 .read = xradio_backoff_ctrl_get,
2055 .llseek = default_llseek,
2056 };
2057
2058 /* for TALA(Tx-Ampdu-Len-Adaption) setting. */
2059 struct wsm_tala_para tala_para;
xradio_tala_get(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)2060 static ssize_t xradio_tala_get(struct file *file,
2061 char __user *user_buf, size_t count, loff_t *ppos)
2062 {
2063 /* struct xradio_common *hw_priv = file->private_data; */
2064 char buf[100];
2065 size_t size = 0;
2066 sprintf(buf, "tala_para=0x%08x, tala_thresh=0x%08x\n",
2067 tala_para.para, tala_para.thresh);
2068 size = strlen(buf);
2069
2070 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
2071 }
2072
xradio_tala_set(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)2073 static ssize_t xradio_tala_set(struct file *file,
2074 const char __user *user_buf, size_t count, loff_t *ppos)
2075 {
2076 struct xradio_common *hw_priv = file->private_data;
2077 char buf[30] = { 0 };
2078 char *start = &buf[0];
2079 char *endptr = NULL;
2080 count = (count > 29 ? 29 : count);
2081
2082 if (!count)
2083 return -EINVAL;
2084 if (copy_from_user(buf, user_buf, count))
2085 return -EFAULT;
2086
2087 if (start < buf + count)
2088 tala_para.para = simple_strtoul(start, &endptr, 16);
2089 start = endptr + 1;
2090 if (start < buf + count)
2091 tala_para.thresh = simple_strtoul(start, &endptr, 16);
2092
2093 wsm_set_tala(hw_priv, &tala_para);
2094 return count;
2095 }
2096
2097 static const struct file_operations fops_tala_ctrl = {
2098 .open = xradio_generic_open,
2099 .write = xradio_tala_set,
2100 .read = xradio_tala_get,
2101 .llseek = default_llseek,
2102 };
2103
2104 /* Tx power debug */
2105 char buf_show[1024] = { 0 };
2106
2107 typedef struct _PWR_INFO_TBL {
2108 u8 Index;
2109 u8 u8Complete;
2110 s16 s16TargetPwr;
2111 s16 s16AdjustedPower;
2112 s16 s16SmthErrTerm;
2113 u32 u32Count;
2114 u16 u16PpaVal;
2115 u16 u16DigVal;
2116 } PWR_CTRL_TBL;
2117 struct _TX_PWR_SHOW {
2118 u8 InfoID;
2119 u8 Status;
2120 u16 reserved;
2121 PWR_CTRL_TBL table[16];
2122 } pwr_ctrl;
xradio_tx_pwr_show(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)2123 static ssize_t xradio_tx_pwr_show(struct file *file,
2124 char __user *user_buf, size_t count, loff_t *ppos)
2125 {
2126 struct xradio_common *hw_priv = file->private_data;
2127
2128 int pos = 0, i = 0;
2129 pwr_ctrl.InfoID = 0x1;
2130 wsm_read_mib(hw_priv, WSM_MIB_ID_TX_POWER_INFO,
2131 (void *)&pwr_ctrl, sizeof(pwr_ctrl), 4);
2132
2133 if (pwr_ctrl.Status) {
2134 pos += sprintf(&buf_show[pos],
2135 "read TX_POWER_INFO error=%x\n",
2136 pwr_ctrl.Status);
2137 } else {
2138 for (i = 0; i < 16; i++) {
2139 pos += sprintf(&buf_show[pos], "M%d:%d, ALG=%d, DIG=%d\n", i,
2140 pwr_ctrl.table[i].s16AdjustedPower,
2141 pwr_ctrl.table[i].u16PpaVal,
2142 pwr_ctrl.table[i].u16DigVal);
2143 }
2144 }
2145 return simple_read_from_buffer(user_buf, count, ppos, buf_show, pos);
2146 }
2147
xradio_tx_pwr_set(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)2148 static ssize_t xradio_tx_pwr_set(struct file *file,
2149 const char __user *user_buf, size_t count, loff_t *ppos)
2150 {
2151 /* struct xradio_common *hw_priv = file->private_data; */
2152 return count;
2153 }
2154
2155 static const struct file_operations fops_tx_pwr_ctrl = {
2156 .open = xradio_generic_open,
2157 .write = xradio_tx_pwr_set,
2158 .read = xradio_tx_pwr_show,
2159 .llseek = default_llseek,
2160 };
2161
2162 /* TPA debug */
2163 #define CASE_NUM 9
2164 #define MAX_POINTS 4
2165 #define PWR_LEVEL_NUM 40
2166 #define MODULN_NUM 11
2167 typedef struct tag_pwr_modulation {
2168 u8 def_pwr_idx; /* default power index of modulation.*/
2169 u8 max_pwr_idx; /* max power index of modulation.*/
2170 u8 mid_pwr_idx; /* power index of middle point.*/
2171 u8 cur_point; /* current sample point.*/
2172
2173 u8 max_point; /* the point has max q value.*/
2174 u8 max_stable; /* counter of stable max of the same point.*/
2175 u8 exception; /* the counter of exception case.*/
2176 u8 listen_def; /* whether to listen to default point.*/
2177
2178 u16 mod_smp_cnt; /* total sample of the modulation.*/
2179 u16 update_cnt; /* counter of power update.*/
2180 u32 update_time; /* last time of power update.*/
2181 u16 smp_points[MAX_POINTS*2];
2182
2183 u8 reserved;
2184 u8 last_rate;
2185 u16 last_max_Q;
2186 } PWR_MODULN;
2187
2188 typedef struct tag_tpa_debug {
2189 u32 update_total[MODULN_NUM];
2190 u32 power_sum[MODULN_NUM];
2191
2192 u16 smp_case[CASE_NUM]; /* counter of every case.*/
2193 u16 reserved0;
2194 u16 smp_move_cnt[MAX_POINTS]; /* counter of movement of update power.*/
2195 u16 max_point_cnt[MAX_POINTS]; /* counter of max point.*/
2196
2197 u16 smp_thresh_q_cnt;
2198 u16 smp_timeout;
2199 u16 smp_listdef_cnt;
2200 u16 smp_excep_cnt;
2201 u16 smp_stable_cnt;
2202
2203 u8 reserved2;
2204 u8 smp_last_moduln;
2205 u16 point_last_smp[MAX_POINTS*2]; /* Q value of point last update.*/
2206 } TPA_DEBUG_INFO;
2207
2208 typedef struct tag_tpa_control {
2209 u8 tpa_enable;
2210 u8 tpa_initialized;
2211 u8 point_interval;
2212 u8 point_step;
2213
2214 u16 thresh_q;
2215 u16 thresh_time;
2216 u16 thresh_update;
2217 u8 thresh_def_lstn;
2218 u8 thresh_stable;
2219 u8 pwr_level[PWR_LEVEL_NUM];
2220 } TPA_CONTROL;
2221
2222 struct _TPA_INFO {
2223 u8 InfoID;
2224 u8 Status;
2225 u8 node;
2226 u8 reserved;
2227 union {
2228 TPA_DEBUG_INFO debug;
2229 TPA_CONTROL ctrl;
2230 PWR_MODULN moduln[MODULN_NUM];
2231 } u;
2232 } tpa_info;
xradio_tpa_ctrl_get(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)2233 static ssize_t xradio_tpa_ctrl_get(struct file *file,
2234 char __user *user_buf, size_t count, loff_t *ppos)
2235 {
2236 struct xradio_common *hw_priv = file->private_data;
2237 int pos = 0, i = 0;
2238 memset(&tpa_info, 0, sizeof(tpa_info));
2239 tpa_info.InfoID = 0x03;
2240 tpa_info.node = 0;
2241 wsm_read_mib(hw_priv, WSM_MIB_ID_TPA_DEBUG_INFO,
2242 (void *)&tpa_info, sizeof(tpa_info), 4);
2243
2244 if (tpa_info.Status && tpa_info.InfoID != 0x43) {
2245 pos += sprintf(&buf_show[pos],
2246 "read TPA_DEBUG_INFO error=%x\n",
2247 tpa_info.Status);
2248 } else {
2249 u8 *pwr = &tpa_info.u.ctrl.pwr_level[0];
2250
2251 pos += sprintf(&buf_show[pos],
2252 "en=%d, init=%d, intvl=%d, step=%d\n",
2253 tpa_info.u.ctrl.tpa_enable,
2254 tpa_info.u.ctrl.tpa_initialized,
2255 tpa_info.u.ctrl.point_interval,
2256 tpa_info.u.ctrl.point_step);
2257 pos += sprintf(&buf_show[pos], "th_q=%d, th_tm=%d, th_updt=%d, " \
2258 "th_def_lstn=%d, th_stbl=%d\n",
2259 tpa_info.u.ctrl.thresh_q,
2260 tpa_info.u.ctrl.thresh_time,
2261 tpa_info.u.ctrl.thresh_update,
2262 tpa_info.u.ctrl.thresh_def_lstn,
2263 tpa_info.u.ctrl.thresh_stable);
2264 for (i = 0; i < 4; i++) {
2265 pos += sprintf(&buf_show[pos],
2266 "pwr lvl=%d.%d, %d.%d, %d.%d, %d.%d\n",
2267 pwr[0]>>3, ((pwr[0]%8)*100)>>3,
2268 pwr[1]>>3, ((pwr[1]%8)*100)>>3,
2269 pwr[2]>>3, ((pwr[2]%8)*100)>>3,
2270 pwr[3]>>3, ((pwr[3]%8)*100)>>3);
2271 pwr += 4;
2272 }
2273 }
2274 return simple_read_from_buffer(user_buf, count, ppos, buf_show, pos);
2275 }
2276
2277 struct TPA_CONTROL_SET {
2278 u8 tpa_enable;
2279 u8 reserved;
2280 u8 point_interval;
2281 u8 point_step;
2282
2283 u16 thresh_q;
2284 u16 thresh_time;
2285 u16 thresh_update;
2286 u8 thresh_def_lstn;
2287 u8 thresh_stable;
2288 } tpa_ctrl_set;
xradio_tpa_ctrl_set(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)2289 static ssize_t xradio_tpa_ctrl_set(struct file *file,
2290 const char __user *user_buf, size_t count, loff_t *ppos)
2291 {
2292 struct xradio_common *hw_priv = file->private_data;
2293 char buffer[256] = { 0 };
2294 char *buf = &buffer[0];
2295 u16 buf_size = (count > 255 ? 255 : count);
2296 char *startptr = &buffer[0];
2297 char *endptr = NULL;
2298
2299 if (!count)
2300 return -EINVAL;
2301 if (copy_from_user(buf, user_buf, buf_size))
2302 return -EFAULT;
2303
2304
2305 if ((buf + buf_size) > endptr) {
2306 tpa_ctrl_set.tpa_enable = simple_strtoul(startptr, &endptr, 10);
2307 startptr = endptr + 1;
2308 }
2309 if ((buf + buf_size) > endptr) {
2310 tpa_ctrl_set.point_interval = simple_strtoul(startptr, &endptr, 10);
2311 startptr = endptr + 1;
2312 }
2313 if ((buf + buf_size) > endptr) {
2314 tpa_ctrl_set.point_step = simple_strtoul(startptr, &endptr, 10);
2315 startptr = endptr + 1;
2316 }
2317
2318 if ((buf + buf_size) > endptr) {
2319 tpa_ctrl_set.thresh_q = simple_strtoul(startptr, &endptr, 10);
2320 startptr = endptr + 1;
2321 }
2322 if ((buf + buf_size) > endptr) {
2323 tpa_ctrl_set.thresh_time = simple_strtoul(startptr, &endptr, 10);
2324 startptr = endptr + 1;
2325 }
2326 if ((buf + buf_size) > endptr) {
2327 tpa_ctrl_set.thresh_update = simple_strtoul(startptr, &endptr, 10);
2328 startptr = endptr + 1;
2329 }
2330 if ((buf + buf_size) > endptr) {
2331 tpa_ctrl_set.thresh_def_lstn = simple_strtoul(startptr, &endptr, 10);
2332 startptr = endptr + 1;
2333 }
2334 if ((buf + buf_size) > endptr) {
2335 tpa_ctrl_set.thresh_stable = simple_strtoul(startptr, &endptr, 10);
2336 startptr = endptr + 1;
2337 }
2338 wsm_write_mib(hw_priv, WSM_MIB_ID_SET_TPA_PARAM,
2339 (void *)&tpa_ctrl_set, sizeof(tpa_ctrl_set), 0);
2340
2341 return count;
2342 }
2343
2344 static const struct file_operations fops_tpa_ctrl = {
2345 .open = xradio_generic_open,
2346 .write = xradio_tpa_ctrl_set,
2347 .read = xradio_tpa_ctrl_get,
2348 .llseek = default_llseek,
2349 };
2350
2351 u8 tpa_node_dbg;
xradio_tpa_debug(struct seq_file * seq,void * v)2352 static int xradio_tpa_debug(struct seq_file *seq, void *v)
2353 {
2354 int ret, i;
2355 struct xradio_common *hw_priv = seq->private;
2356
2357 #define PUT_TPA_MODULN(tab, name) \
2358 seq_printf(seq, tab":\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", \
2359 __le32_to_cpu(tpa_info.u.moduln[0].name), \
2360 __le32_to_cpu(tpa_info.u.moduln[1].name), \
2361 __le32_to_cpu(tpa_info.u.moduln[2].name), \
2362 __le32_to_cpu(tpa_info.u.moduln[3].name), \
2363 __le32_to_cpu(tpa_info.u.moduln[4].name), \
2364 __le32_to_cpu(tpa_info.u.moduln[5].name), \
2365 __le32_to_cpu(tpa_info.u.moduln[6].name), \
2366 __le32_to_cpu(tpa_info.u.moduln[7].name), \
2367 __le32_to_cpu(tpa_info.u.moduln[8].name), \
2368 __le32_to_cpu(tpa_info.u.moduln[9].name), \
2369 __le32_to_cpu(tpa_info.u.moduln[10].name))
2370
2371 tpa_info.InfoID = 0x01;
2372 tpa_info.node = tpa_node_dbg;
2373 ret = wsm_read_mib(hw_priv, WSM_MIB_ID_TPA_DEBUG_INFO,
2374 (void *)&tpa_info, sizeof(tpa_info), 4);
2375
2376 if (tpa_info.Status && tpa_info.InfoID != 0x41) {
2377 seq_printf(seq, "read TPA_DEBUG_INFO error=%x\n", tpa_info.Status);
2378 } else {
2379 seq_printf(seq, "\t\tm0\tm1\tm2\tm3\tm4\tm5\tm6\tm7\tm8\tm9\tm10\t\n");
2380
2381 PUT_TPA_MODULN("max_idx", max_pwr_idx);
2382 PUT_TPA_MODULN("def_idx", def_pwr_idx);
2383 PUT_TPA_MODULN("mid_idx", mid_pwr_idx);
2384 PUT_TPA_MODULN("cur_pt ", cur_point);
2385 PUT_TPA_MODULN("max_pt ", max_point);
2386 PUT_TPA_MODULN("stable ", max_stable);
2387 PUT_TPA_MODULN("exceptn", exception);
2388 PUT_TPA_MODULN("listen ", listen_def);
2389 PUT_TPA_MODULN("smp_cnt", mod_smp_cnt);
2390 PUT_TPA_MODULN("update ", update_cnt);
2391
2392 PUT_TPA_MODULN("pt[0] ", smp_points[0]);
2393 PUT_TPA_MODULN("pt[0] ", smp_points[1]);
2394 PUT_TPA_MODULN("pt[1] ", smp_points[2]);
2395 PUT_TPA_MODULN("pt[1] ", smp_points[3]);
2396 PUT_TPA_MODULN("pt[2] ", smp_points[4]);
2397 PUT_TPA_MODULN("pt[2] ", smp_points[5]);
2398 PUT_TPA_MODULN("pt[3] ", smp_points[6]);
2399 PUT_TPA_MODULN("pt[3] ", smp_points[7]);
2400
2401 PUT_TPA_MODULN("rate ", last_rate);
2402 PUT_TPA_MODULN("Max Q ", last_max_Q);
2403 }
2404 #undef PUT_TPA_MODULN
2405
2406 #define SMP_CASE(i) __le32_to_cpu(tpa_info.u.debug.smp_case[i])
2407 #define PWR_LVL_S(n) (tpa_info.u.debug.power_sum[n]>>3)
2408
2409
2410 tpa_info.InfoID = 0x02;
2411 tpa_info.node = tpa_node_dbg;
2412 ret = wsm_read_mib(hw_priv, WSM_MIB_ID_TPA_DEBUG_INFO,
2413 (void *)&tpa_info, sizeof(tpa_info), 4);
2414
2415 if (tpa_info.Status && tpa_info.InfoID != 0x42) {
2416 seq_printf(seq, "read TPA_DEBUG_INFO error=%x\n", tpa_info.Status);
2417 } else {
2418 for (i = 0; i < MODULN_NUM; i++) {
2419 if (tpa_info.u.debug.update_total[i])
2420 tpa_info.u.debug.power_sum[i] /=
2421 tpa_info.u.debug.update_total[i];
2422 else
2423 tpa_info.u.debug.power_sum[i] = 0;
2424 }
2425 seq_printf(seq, "\nupdate_total:\t%d\t%d\t%d\t%d\t" \
2426 "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", \
2427 __le32_to_cpu(tpa_info.u.debug.update_total[0]), \
2428 __le32_to_cpu(tpa_info.u.debug.update_total[1]), \
2429 __le32_to_cpu(tpa_info.u.debug.update_total[2]), \
2430 __le32_to_cpu(tpa_info.u.debug.update_total[3]), \
2431 __le32_to_cpu(tpa_info.u.debug.update_total[4]), \
2432 __le32_to_cpu(tpa_info.u.debug.update_total[5]), \
2433 __le32_to_cpu(tpa_info.u.debug.update_total[6]), \
2434 __le32_to_cpu(tpa_info.u.debug.update_total[7]), \
2435 __le32_to_cpu(tpa_info.u.debug.update_total[8]), \
2436 __le32_to_cpu(tpa_info.u.debug.update_total[9]), \
2437 __le32_to_cpu(tpa_info.u.debug.update_total[10]));
2438
2439 seq_printf(seq, "pwr_avrg:\t%d\t%d\t%d\t%d\t%d\t%d\t"
2440 "%d\t%d\t%d\t%d\t%d\n", \
2441 PWR_LVL_S(0), \
2442 PWR_LVL_S(1), \
2443 PWR_LVL_S(2), \
2444 PWR_LVL_S(3), \
2445 PWR_LVL_S(4), \
2446 PWR_LVL_S(5), \
2447 PWR_LVL_S(6), \
2448 PWR_LVL_S(7), \
2449 PWR_LVL_S(8), \
2450 PWR_LVL_S(9), \
2451 PWR_LVL_S(10));
2452
2453 seq_printf(seq, "SMP_CASE: %d, %d, %d, %d(E), " \
2454 "%d, %d, %d(E), %d(E), %d\n",
2455 SMP_CASE(0), SMP_CASE(1), SMP_CASE(2), SMP_CASE(3),
2456 SMP_CASE(4), SMP_CASE(5), SMP_CASE(6), SMP_CASE(7),
2457 SMP_CASE(8));
2458 seq_printf(seq, "MAX: M=%d, L=%d, R=%d, D=%d\n",
2459 tpa_info.u.debug.max_point_cnt[0],
2460 tpa_info.u.debug.max_point_cnt[1],
2461 tpa_info.u.debug.max_point_cnt[2],
2462 tpa_info.u.debug.max_point_cnt[3]);
2463 seq_printf(seq, "MOVE: M=%d, L=%d, R=%d, D=%d\n",
2464 tpa_info.u.debug.smp_move_cnt[0],
2465 tpa_info.u.debug.smp_move_cnt[1],
2466 tpa_info.u.debug.smp_move_cnt[2],
2467 tpa_info.u.debug.smp_move_cnt[3]);
2468 seq_printf(seq, "listen=%d, timeout=%d, thresh_q=%d, " \
2469 "excep=%d, stable=%d\n",
2470 tpa_info.u.debug.smp_listdef_cnt,
2471 tpa_info.u.debug.smp_timeout,
2472 tpa_info.u.debug.smp_thresh_q_cnt,
2473 tpa_info.u.debug.smp_excep_cnt,
2474 tpa_info.u.debug.smp_stable_cnt);
2475
2476 seq_printf(seq, "lsat Moduln=%d, M=%d, %d; " \
2477 "L=%d, %d; R=%d, %d; D=%d, %d\n",
2478 tpa_info.u.debug.smp_last_moduln,
2479 tpa_info.u.debug.point_last_smp[0],
2480 tpa_info.u.debug.point_last_smp[1],
2481 tpa_info.u.debug.point_last_smp[2],
2482 tpa_info.u.debug.point_last_smp[3],
2483 tpa_info.u.debug.point_last_smp[4],
2484 tpa_info.u.debug.point_last_smp[5],
2485 tpa_info.u.debug.point_last_smp[6],
2486 tpa_info.u.debug.point_last_smp[7]);
2487 }
2488
2489 #undef PWR_LVL_S
2490 #undef SMP_CASE
2491
2492 return 0;
2493 }
2494
xradio_tpa_debug_open(struct inode * inode,struct file * file)2495 static int xradio_tpa_debug_open(struct inode *inode, struct file *file)
2496 {
2497 return single_open(file, &xradio_tpa_debug,
2498 inode->i_private);
2499 }
2500
2501 static const struct file_operations fops_tpa_debug = {
2502 .open = xradio_tpa_debug_open,
2503 .read = seq_read,
2504 .llseek = seq_lseek,
2505 .release = single_release,
2506 .owner = THIS_MODULE,
2507 };
2508
2509 /* policy_info */
2510 u32 tx_retrylimit;
2511 u32 tx_lower_limit;
2512 u32 tx_over_limit;
2513 int retry_mis;
2514 u32 policy_upload;
2515 u32 policy_num;
2516
xradio_policy_info(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)2517 static ssize_t xradio_policy_info(struct file *file,
2518 char __user *user_buf, size_t count, loff_t *ppos)
2519 {
2520 /* struct xradio_common *hw_priv = file->private_data; */
2521 char buf[256];
2522 size_t size = 0;
2523 sprintf(buf, "tx_retrylimit=%d, tx_lower_limit=%d, " \
2524 "tx_over_limit=%d, retry_mis=%d\n" \
2525 "policy_upload=%d, policy_num=%d\n",
2526 tx_retrylimit, tx_lower_limit, tx_over_limit, retry_mis,
2527 policy_upload, policy_num);
2528 size = strlen(buf);
2529
2530 /* clear counters */
2531 tx_retrylimit = 0;
2532 tx_lower_limit = 0;
2533 tx_over_limit = 0;
2534 retry_mis = 0;
2535 policy_upload = 0;
2536 policy_num = 0;
2537
2538 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
2539 }
2540
2541 static const struct file_operations fops_policy_info = {
2542 .open = xradio_generic_open,
2543 .read = xradio_policy_info,
2544 .llseek = default_llseek,
2545 };
2546
2547 /* info of interruption */
2548 u32 irq_count;
2549 u32 int_miss_cnt;
2550 u32 fix_miss_cnt;
2551 u32 next_rx_cnt;
2552 u32 rx_total_cnt;
2553 u32 tx_total_cnt;
2554 u32 tx_buf_limit;
2555 u32 tx_limit;
2556 u32 tx_rx_idle;
2557 u32 bh_idle;
2558 u32 queue_lock_cnt;
2559 u32 overfull_lock_cnt;
2560 u32 policy_lock_cnt;
2561
xradio_bh_statistic(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)2562 static ssize_t xradio_bh_statistic(struct file *file,
2563 char __user *user_buf, size_t count, loff_t *ppos)
2564 {
2565 struct xradio_common *hw_priv = file->private_data;
2566 char buf[512];
2567 size_t size = 0;
2568 sprintf(buf, "irq_count=%u, rx_total=%u, rx_miss=%u, "
2569 "rx_fix=%u, rx_next=%u, rx_burst=%d, irq/rx=%u%%\n"
2570 "tx_total=%u, tx_burst=%d, tx_limit=%u, tx_buf_limit=%u, "
2571 "limit/tx=%u%%, buf_limit/limit=%u%%, tx_rx_idle=%u, bh_idle=%u\n"
2572 "queue_lock_cnt=%u, overfull_lock_cnt=%u, policy_lock_cnt=%u\n",
2573 irq_count, rx_total_cnt, int_miss_cnt, fix_miss_cnt,
2574 next_rx_cnt, hw_priv->debug->rx_burst,
2575 (rx_total_cnt ? irq_count*100/rx_total_cnt : 0),
2576 tx_total_cnt, hw_priv->debug->tx_burst, tx_limit, tx_buf_limit,
2577 (tx_total_cnt ? tx_limit*100/tx_total_cnt : 0),
2578 (tx_limit ? tx_buf_limit*100/tx_limit : 0),
2579 tx_rx_idle, bh_idle, queue_lock_cnt, overfull_lock_cnt,
2580 policy_lock_cnt);
2581 size = strlen(buf);
2582
2583 /*clear counters*/
2584 irq_count = 0;
2585 int_miss_cnt = 0;
2586 fix_miss_cnt = 0;
2587 next_rx_cnt = 0;
2588 rx_total_cnt = 0;
2589 tx_total_cnt = 0;
2590 tx_buf_limit = 0;
2591 tx_limit = 0;
2592 tx_rx_idle = 0;
2593 bh_idle = 0;
2594 queue_lock_cnt = 0;
2595 overfull_lock_cnt = 0;
2596 policy_lock_cnt = 0;
2597 hw_priv->debug->rx_burst = 0;
2598 hw_priv->debug->tx_burst = 0;
2599
2600 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
2601 }
2602
2603 static const struct file_operations fops_bh_stat = {
2604 .open = xradio_generic_open,
2605 .read = xradio_bh_statistic,
2606 .llseek = default_llseek,
2607 };
2608
2609 /* time info of bh tx and rx */
2610 #if PERF_INFO_TEST
perf_info_reset(struct perf_info * info)2611 static inline void perf_info_reset(struct perf_info *info)
2612 {
2613 memset(info, 0, sizeof(struct perf_info));
2614 info->min_time = (u32)-1;
2615 }
2616 struct perf_info data_tx;
2617 struct perf_info data_rx;
2618 struct perf_info bh_others;
2619 struct perf_info bh_wait;
2620 struct perf_info sdio_reg;
2621 struct perf_info prepare_tx;
2622 struct perf_info sdio_write;
2623 struct perf_info dev_wake;
2624 struct perf_info prepare_rx;
2625 struct perf_info sdio_read;
2626 struct perf_info handle_rx;
2627
2628 #ifdef BH_PROC_THREAD
2629 struct perf_info get_item;
2630 struct perf_info wake_proc;
2631 struct perf_info proc_rx;
2632 struct perf_info proc_tx;
2633 struct perf_info proc_wait;
2634 #endif
2635 struct perf_info ind_rx;
2636 struct perf_info mac_rx;
2637 struct perf_info mac_tx;
2638
2639 #if TEST_GETTIME
2640 struct perf_info get_time;
2641 #endif
2642
2643 struct timespec64 last_showtime;
xradio_show_intv(struct timespec64 * showtime)2644 static inline u32 xradio_show_intv(struct timespec64 *showtime)
2645 {
2646 u32 time_int;
2647 struct timespec64 time_now;
2648 xr_do_gettimeofday(&time_now);
2649 time_int = (time_now.tv_sec - showtime->tv_sec) * 100000 + \
2650 (time_now.tv_usec - showtime->tv_usec) / 10;
2651 xr_do_gettimeofday(showtime);
2652 return time_int; /*10us*/
2653 }
2654 /*mac(26) + IV(8) + LLC(8) + IP(20) + TCP(20) or UDP(8)*/
2655 #define TX_OVERHEAD (sizeof(struct wsm_tx)+26+8+20+20)
2656 #define RX_OVERHEAD (12+26+8+20+20)
xradio_perf_info(struct seq_file * seq,void * v)2657 static int xradio_perf_info(struct seq_file *seq, void *v)
2658 {
2659 /* struct xradio_common *hw_priv = seq->private; */
2660 u32 time_int = xradio_show_intv(&last_showtime);
2661 u32 txrx_time = data_tx.totaltime + data_rx.totaltime;
2662 u32 real_tx = (data_tx.totalsize<<3)/107*10;
2663 u32 real_rx = (data_rx.totalsize<<3)/106*10;
2664 if (bh_others.totaltime > bh_wait.totaltime)
2665 txrx_time += (bh_others.totaltime - bh_wait.totaltime);
2666 else
2667 txrx_time += sdio_reg.totaltime;
2668
2669
2670 #define PUT_PERF_INFO(tab, name) \
2671 seq_printf(seq, "%s" tab "%d\t%d\t%d\t%d\t%d\t%d\t%d.%d\t%d.%02d%%\n", #name, \
2672 name.count, name.totaltime, (name.totalsize>>3), name.min_time, name.max_time, \
2673 name.count ? (name.totaltime/name.count) : 0, \
2674 name.totaltime ? ((name.totalsize<<3)/name.totaltime) : 0, \
2675 name.totaltime ? (((name.totalsize<<3)%name.totaltime)*10/name.totaltime) : 0, \
2676 time_int ? (name.totaltime*10/time_int) : 0, \
2677 time_int ? (((name.totaltime*10)%time_int)*100/time_int) : 0)
2678
2679 seq_printf(seq, "\nTime_int=%d, Tx=%d.%02dMbps, Rx=%d.%02dMbps, "
2680 "RealTx=%d.%02dMbps, RealRx=%d.%02dMbps\n", time_int*10,
2681 txrx_time ? ((data_tx.totalsize<<3)/txrx_time) : 0,
2682 txrx_time ? ((data_tx.totalsize<<3)%txrx_time)*100/txrx_time : 0,
2683 txrx_time ? ((data_rx.totalsize<<3)/txrx_time) : 0,
2684 txrx_time ? ((data_rx.totalsize<<3)%txrx_time)*100/txrx_time : 0,
2685 time_int ? (real_tx/time_int) : 0,
2686 time_int ? (real_tx%time_int)*100/time_int : 0,
2687 time_int ? (real_rx/time_int) : 0,
2688 time_int ? (real_rx%time_int)*100/time_int : 0);
2689 seq_printf(seq, "Items\t\tcnt\ttime\tsize(8)\tmin\tmax\tavg\tperf(M)\tduty\n");
2690 PUT_PERF_INFO("\t\t", data_tx);
2691 PUT_PERF_INFO("\t\t", data_rx);
2692 PUT_PERF_INFO("\t\t", bh_wait);
2693 PUT_PERF_INFO("\t", sdio_reg);
2694 PUT_PERF_INFO("\t", prepare_tx);
2695 PUT_PERF_INFO("\t", sdio_write);
2696 PUT_PERF_INFO("\t", dev_wake);
2697 PUT_PERF_INFO("\t", prepare_rx);
2698 PUT_PERF_INFO("\t", sdio_read);
2699 PUT_PERF_INFO("\t", handle_rx);
2700 #ifdef BH_PROC_THREAD
2701 PUT_PERF_INFO("\t", get_item);
2702 PUT_PERF_INFO("\t", wake_proc);
2703 PUT_PERF_INFO("\t\t", proc_rx);
2704 PUT_PERF_INFO("\t\t", proc_tx);
2705 PUT_PERF_INFO("\t", proc_wait);
2706 #endif
2707 PUT_PERF_INFO("\t\t", ind_rx);
2708 PUT_PERF_INFO("\t\t", mac_rx);
2709 PUT_PERF_INFO("\t\t", mac_tx);
2710 PUT_PERF_INFO("\t", bh_others);
2711
2712 #if TEST_GETTIME
2713 PUT_PERF_INFO("\t", get_time);
2714 #endif
2715
2716 seq_printf(seq, "reg_cnt1=%d, reg_cnt2=%d, reg_cnt3=%d, reg_cnt4=%d, "
2717 "reg_fail1=%d, reg_fail2=%d\n",
2718 sdio_reg_cnt1, sdio_reg_cnt2, sdio_reg_cnt3, sdio_reg_cnt4,
2719 sdio_reg_cnt5, sdio_reg_cnt6);
2720 seq_printf(seq, "limit_cnt1=%d, limit_cnt2=%d, "
2721 "limit_cnt3=%d, limit_cnt4=%d, limit_cnt5=%d, limit_cnt6=%d\n",
2722 tx_limit_cnt1, tx_limit_cnt2, tx_limit_cnt3,
2723 tx_limit_cnt4, tx_limit_cnt5, tx_limit_cnt6);
2724
2725 #if BH_PROC_DPA
2726 seq_printf(seq, "proc_dpa_cnt=%d, proc_up_cnt=%d, proc_down_cnt=%d, prio=%d\n",
2727 proc_dpa_cnt, proc_up_cnt, proc_down_cnt, hw_priv->proc.proc_prio);
2728 proc_dpa_cnt = 0;
2729 proc_up_cnt = 0;
2730 proc_down_cnt = 0;
2731 #endif
2732
2733 sdio_reg_cnt1 = 0;
2734 sdio_reg_cnt2 = 0;
2735 sdio_reg_cnt3 = 0;
2736 sdio_reg_cnt4 = 0;
2737 sdio_reg_cnt5 = 0;
2738 sdio_reg_cnt6 = 0;
2739
2740 tx_limit_cnt1 = 0;
2741 tx_limit_cnt2 = 0;
2742 tx_limit_cnt3 = 0;
2743 tx_limit_cnt4 = 0;
2744 tx_limit_cnt5 = 0;
2745 tx_limit_cnt6 = 0;
2746
2747
2748 #undef PUT_PERF_INFO
2749
2750 perf_info_reset(&data_tx);
2751 perf_info_reset(&data_rx);
2752 perf_info_reset(&bh_wait);
2753 perf_info_reset(&sdio_reg);
2754 perf_info_reset(&prepare_tx);
2755 perf_info_reset(&sdio_write);
2756 perf_info_reset(&dev_wake);
2757 perf_info_reset(&prepare_rx);
2758 perf_info_reset(&sdio_read);
2759 perf_info_reset(&handle_rx);
2760 #ifdef BH_PROC_THREAD
2761 perf_info_reset(&get_item);
2762 perf_info_reset(&wake_proc);
2763 perf_info_reset(&proc_rx);
2764 perf_info_reset(&proc_tx);
2765 perf_info_reset(&proc_wait);
2766 #endif
2767 perf_info_reset(&ind_rx);
2768 perf_info_reset(&mac_rx);
2769 perf_info_reset(&mac_tx);
2770 perf_info_reset(&bh_others);
2771
2772 #if TEST_GETTIME
2773 if (get_time.count > 10000)
2774 perf_info_reset(&get_time);
2775 #endif
2776
2777 return 0;
2778 }
2779
xradio_perf_info_open(struct inode * inode,struct file * file)2780 static int xradio_perf_info_open(struct inode *inode, struct file *file)
2781 {
2782 return single_open(file, &xradio_perf_info, inode->i_private);
2783 }
2784
2785 static const struct file_operations fops_perf_info = {
2786 .open = xradio_perf_info_open,
2787 .read = seq_read,
2788 .llseek = seq_lseek,
2789 .release = single_release,
2790 .owner = THIS_MODULE,
2791 };
2792 #endif /* #if PERF_INFO_TEST */
2793
2794
2795 u32 dbg_txconfirm[32];
xradio_txconfirm_show(struct seq_file * seq,void * v)2796 static int xradio_txconfirm_show(struct seq_file *seq, void *v)
2797 {
2798 int i;
2799
2800 for (i = 0; i < 8; i++) {
2801 seq_printf(seq, "Txcfm%d:%d\t", i+1, dbg_txconfirm[i]);
2802 seq_printf(seq, "Txcfm%d:%d\t", i+1+8, dbg_txconfirm[i+8]);
2803 seq_printf(seq, "Txcfm%d:%d\t", i+1+16, dbg_txconfirm[i+16]);
2804 seq_printf(seq, "Txcfm%d:%d\t\n", i+1+24, dbg_txconfirm[i+24]);
2805 dbg_txconfirm[i] = 0;
2806 dbg_txconfirm[i+8] = 0;
2807 dbg_txconfirm[i+16] = 0;
2808 dbg_txconfirm[i+24] = 0;
2809 }
2810 return 0;
2811 }
2812
xradio_txconfirm_open(struct inode * inode,struct file * file)2813 static int xradio_txconfirm_open(struct inode *inode, struct file *file)
2814 {
2815 return single_open(file, &xradio_txconfirm_show,
2816 inode->i_private);
2817 }
2818
2819 static const struct file_operations fops_txconfirm = {
2820 .open = xradio_txconfirm_open,
2821 .read = seq_read,
2822 .llseek = seq_lseek,
2823 .release = single_release,
2824 .owner = THIS_MODULE,
2825 };
2826
2827 u32 dbg_tx_delay_min = 0xffffffff;
2828 u32 dbg_tx_delay_max;
2829 u32 dbg_tx_media_delay[16];
xradio_debug_tx_delay(u32 media_delay,u32 queue_delay)2830 void xradio_debug_tx_delay(u32 media_delay, u32 queue_delay)
2831 {
2832 if (media_delay < dbg_tx_delay_min)
2833 dbg_tx_delay_min = media_delay;
2834 if (media_delay > dbg_tx_delay_max)
2835 dbg_tx_delay_max = media_delay;
2836 if (media_delay <= 500)
2837 dbg_tx_media_delay[0]++;
2838 else if (media_delay <= 1000)
2839 dbg_tx_media_delay[1]++;
2840 else if (media_delay <= 10000)
2841 dbg_tx_media_delay[2]++;
2842 else if (media_delay <= 20000)
2843 dbg_tx_media_delay[3]++;
2844 else if (media_delay <= 30000)
2845 dbg_tx_media_delay[4]++;
2846 else if (media_delay <= 40000)
2847 dbg_tx_media_delay[5]++;
2848 else if (media_delay <= 50000)
2849 dbg_tx_media_delay[6]++;
2850 else if (media_delay <= 100000)
2851 dbg_tx_media_delay[7]++;
2852 else if (media_delay <= 150000)
2853 dbg_tx_media_delay[8]++;
2854 else if (media_delay <= 200000)
2855 dbg_tx_media_delay[9]++;
2856 else if (media_delay <= 300000)
2857 dbg_tx_media_delay[10]++;
2858 else if (media_delay <= 500000)
2859 dbg_tx_media_delay[11]++;
2860 else if (media_delay <= 1000000)
2861 dbg_tx_media_delay[12]++;
2862 else if (media_delay <= 3000000)
2863 dbg_tx_media_delay[13]++;
2864 else if (media_delay <= 15000000)
2865 dbg_tx_media_delay[14]++;
2866 else
2867 xradio_dbg(XRADIO_DBG_WARN, "media_delay=%d, queue_delay=%d\n",
2868 media_delay, queue_delay);
2869 if (media_delay >= 30000)
2870 xradio_dbg(XRADIO_DBG_NIY, "media_delay=%d, queue_delay=%d\n",
2871 media_delay, queue_delay);
2872 }
xradio_tx_delay_show(struct seq_file * seq,void * v)2873 static int xradio_tx_delay_show(struct seq_file *seq, void *v)
2874 {
2875 seq_printf(seq, "MinDelay %dus, MaxDelay=%dus\n", dbg_tx_delay_min, dbg_tx_delay_max);
2876 seq_printf(seq, "Delay (0~0.5ms] :%d\n", dbg_tx_media_delay[0]);
2877 seq_printf(seq, "Delay (0.5~1ms] :%d\n", dbg_tx_media_delay[1]);
2878 seq_printf(seq, "Delay (1~10ms] :%d\n", dbg_tx_media_delay[2]);
2879 seq_printf(seq, "Delay (10~20ms] :%d\n", dbg_tx_media_delay[3]);
2880 seq_printf(seq, "Delay (20~30ms] :%d\n", dbg_tx_media_delay[4]);
2881 seq_printf(seq, "Delay (30~40ms] :%d\n", dbg_tx_media_delay[5]);
2882 seq_printf(seq, "Delay (40~50ms] :%d\n", dbg_tx_media_delay[6]);
2883 seq_printf(seq, "Delay (50~100ms] :%d\n", dbg_tx_media_delay[7]);
2884 seq_printf(seq, "Delay (100~150ms] :%d\n", dbg_tx_media_delay[8]);
2885 seq_printf(seq, "Delay (150~200ms] :%d\n", dbg_tx_media_delay[9]);
2886 seq_printf(seq, "Delay (200~300ms] :%d\n", dbg_tx_media_delay[10]);
2887 seq_printf(seq, "Delay (300~500ms] :%d\n", dbg_tx_media_delay[11]);
2888 seq_printf(seq, "Delay (500~1000ms]:%d\n", dbg_tx_media_delay[12]);
2889 seq_printf(seq, "Delay (1~3s] :%d\n", dbg_tx_media_delay[13]);
2890 seq_printf(seq, "Delay (3~15s] :%d\n", dbg_tx_media_delay[14]);
2891
2892 dbg_tx_delay_min = 0xffffffff;
2893 dbg_tx_delay_max = 0;
2894 memset(dbg_tx_media_delay, 0, sizeof(dbg_tx_media_delay));
2895 return 0;
2896 }
2897
xradio_tx_delay_open(struct inode * inode,struct file * file)2898 static int xradio_tx_delay_open(struct inode *inode, struct file *file)
2899 {
2900 return single_open(file, &xradio_tx_delay_show,
2901 inode->i_private);
2902 }
2903
2904 static const struct file_operations fops_txdelay = {
2905 .open = xradio_tx_delay_open,
2906 .read = seq_read,
2907 .llseek = seq_lseek,
2908 .release = single_release,
2909 .owner = THIS_MODULE,
2910 };
2911
2912 /*for disable low power mode.*/
2913 extern u16 txparse_flags;
2914 extern u16 rxparse_flags;
xradio_parse_flags_get(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)2915 static ssize_t xradio_parse_flags_get(struct file *file,
2916 char __user *user_buf, size_t count, loff_t *ppos)
2917 {
2918 /*struct xradio_common *hw_priv = file->private_data;*/
2919 char buf[100];
2920 size_t size = 0;
2921
2922 sprintf(buf, "txparse=0x%04x, rxparse=0x%04x\n",
2923 txparse_flags, rxparse_flags);
2924 size = strlen(buf);
2925
2926 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
2927 }
2928
xradio_parse_flags_set(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)2929 static ssize_t xradio_parse_flags_set(struct file *file,
2930 const char __user *user_buf,
2931 size_t count, loff_t *ppos)
2932 {
2933 /*struct xradio_common *hw_priv = file->private_data;*/
2934 char buf[30] = { 0 };
2935 char *start = &buf[0];
2936 char *endptr = NULL;
2937
2938 count = (count > 29 ? 29 : count);
2939
2940 if (!count)
2941 return -EINVAL;
2942 if (copy_from_user(buf, user_buf, count))
2943 return -EFAULT;
2944
2945 txparse_flags = simple_strtoul(buf, &endptr, 16);
2946 start = endptr + 1;
2947 if (start < buf + count)
2948 rxparse_flags = simple_strtoul(start, &endptr, 16);
2949
2950 txparse_flags &= 0x7fff;
2951 rxparse_flags &= 0x7fff;
2952
2953 xradio_dbg(XRADIO_DBG_ALWY, "txparse=0x%04x, rxparse=0x%04x\n",
2954 txparse_flags, rxparse_flags);
2955 return count;
2956 }
2957
2958 static const struct file_operations fops_parse_flags = {
2959 .open = xradio_generic_open,
2960 .write = xradio_parse_flags_set,
2961 .read = xradio_parse_flags_get,
2962 .llseek = default_llseek,
2963 };
2964
2965 #if (DGB_XRADIO_HWT)
2966 u8 hwt_testing;
2967 /*HIF TX test*/
2968 u8 hwt_tx_en;
2969 u8 hwt_tx_cfm; /*confirm interval*/
2970 u16 hwt_tx_len;
2971 u16 hwt_tx_num;
2972 struct timespec64 hwt_start_time = { 0 };
2973 struct timespec64 hwt_end_time = { 0 };
2974
2975 int wsm_hwt_cmd(struct xradio_common *hw_priv, void *arg,
2976 size_t arg_size);
2977
xradio_hwt_hif_tx(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)2978 static ssize_t xradio_hwt_hif_tx(struct file *file,
2979 const char __user *user_buf, size_t count, loff_t *ppos)
2980 {
2981 struct xradio_common *hw_priv = file->private_data;
2982 char buf[100] = { 0 };
2983 char *start = &buf[0];
2984 char *endptr = NULL;
2985
2986 if (hwt_testing) {
2987 xradio_dbg(XRADIO_DBG_ALWY, "cmd refuse, hwt is testing!\n");
2988 return count;
2989 }
2990
2991 count = (count > 99 ? 99 : count);
2992 if (!count)
2993 return -EINVAL;
2994 if (copy_from_user(buf, user_buf, count))
2995 return -EFAULT;
2996
2997 if (simple_strtoul(start, &endptr, 10)) {
2998 start = endptr + 1;
2999 if (start < buf + count)
3000 hwt_tx_len = simple_strtoul(start, &endptr, 10);
3001 start = endptr + 1;
3002 if (start < buf + count)
3003 hwt_tx_num = simple_strtoul(start, &endptr, 10);
3004 start = endptr + 1;
3005 if (start < buf + count)
3006 hwt_tx_cfm = simple_strtoul(start, &endptr, 10);
3007 hwt_tx_en = 1;
3008 hwt_testing = 1;
3009 } else {
3010 hwt_tx_en = 0;
3011 }
3012 xradio_dbg(XRADIO_DBG_ALWY,
3013 "hwt_tx_en=%d, hwt_tx_len=%d, hwt_tx_num=%d, hwt_tx_cfm=%d\n",
3014 hwt_tx_en, hwt_tx_len, hwt_tx_num, hwt_tx_cfm);
3015
3016 if (!hw_priv->bh_error &&
3017 atomic_add_return(1, &hw_priv->bh_tx) == 1)
3018 wake_up(&hw_priv->bh_wq);
3019 return count;
3020 }
3021
3022 static const struct file_operations fops_hwt_hif_tx = {
3023 .open = xradio_generic_open,
3024 .write = xradio_hwt_hif_tx,
3025 .llseek = default_llseek,
3026 };
3027
3028 /*HIF RX test*/
3029 u8 hwt_rx_en;
3030 u16 hwt_rx_len;
3031 u16 hwt_rx_num;
xradio_hwt_hif_rx(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)3032 static ssize_t xradio_hwt_hif_rx(struct file *file,
3033 const char __user *user_buf, size_t count, loff_t *ppos)
3034 {
3035 struct xradio_common *hw_priv = file->private_data;
3036 char buf[100] = { 0 };
3037 char *start = &buf[0];
3038 char *endptr = NULL;
3039
3040 if (hwt_testing) {
3041 xradio_dbg(XRADIO_DBG_ALWY, "cmd refuse, hwt is testing!\n");
3042 return count;
3043 }
3044
3045 count = (count > 99 ? 99 : count);
3046 if (!count)
3047 return -EINVAL;
3048 if (copy_from_user(buf, user_buf, count))
3049 return -EFAULT;
3050
3051 if (simple_strtoul(start, &endptr, 10)) {
3052 start = endptr + 1;
3053 if (start < buf + count)
3054 hwt_rx_len = simple_strtoul(start, &endptr, 10);
3055 start = endptr + 1;
3056 if (start < buf + count)
3057 hwt_rx_num = simple_strtoul(start, &endptr, 10);
3058
3059 hwt_rx_en = 1;
3060 } else {
3061 hwt_rx_en = 0;
3062 }
3063 xradio_dbg(XRADIO_DBG_ALWY,
3064 "hwt_rx_en=%d, hwt_rx_len=%d, hwt_rx_num=%d\n", hwt_rx_en,
3065 hwt_rx_len, hwt_rx_num);
3066
3067 /*check the parameters.*/
3068 if (hwt_rx_len < 100 || hwt_rx_len > 1500)
3069 hwt_rx_len = 1500;
3070 if (hwt_rx_en && hwt_rx_num) {
3071 HWT_PARAMETERS hwt_hdr = {
3072 .TestID = 0x0002,
3073 .Params = hwt_rx_num,
3074 .Data = hwt_rx_len
3075 };
3076 hwt_testing = 1;
3077 wsm_hwt_cmd(hw_priv, (void *)&hwt_hdr.TestID, sizeof(hwt_hdr)-4);
3078 xr_do_gettimeofday(&hwt_start_time);
3079 }
3080
3081 return count;
3082 }
3083
3084 static const struct file_operations fops_hwt_hif_rx = {
3085 .open = xradio_generic_open,
3086 .write = xradio_hwt_hif_rx,
3087 .llseek = default_llseek,
3088 };
3089
3090 /*ENC test*/
3091 u8 hwt_enc_type;
3092 u8 hwt_key_len;
3093 u16 hwt_enc_len;
3094 u16 hwt_enc_cnt;
xradio_hwt_enc(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)3095 static ssize_t xradio_hwt_enc(struct file *file,
3096 const char __user *user_buf, size_t count, loff_t *ppos)
3097 {
3098 struct xradio_common *hw_priv = file->private_data;
3099 char buf[100] = { 0 };
3100 char *start = &buf[0];
3101 char *endptr = NULL;
3102
3103 if (hwt_testing) {
3104 xradio_dbg(XRADIO_DBG_ALWY, "cmd refuse, hwt is testing!\n");
3105 return count;
3106 }
3107
3108 count = (count > 99 ? 99 : count);
3109 if (!count)
3110 return -EINVAL;
3111 if (copy_from_user(buf, user_buf, count))
3112 return -EFAULT;
3113
3114 hwt_enc_type = simple_strtoul(start, &endptr, 10);
3115 start = endptr + 1;
3116 if (start < buf + count)
3117 hwt_key_len = simple_strtoul(start, &endptr, 10);
3118 start = endptr + 1;
3119 if (start < buf + count)
3120 hwt_enc_len = simple_strtoul(start, &endptr, 10);
3121 start = endptr + 1;
3122 if (start < buf + count)
3123 hwt_enc_cnt = simple_strtoul(start, &endptr, 10);
3124
3125 xradio_dbg(XRADIO_DBG_ALWY,
3126 "enc_type=%d, key_len=%d, enc_len=%d, enc_cnt=%d\n",
3127 hwt_enc_type, hwt_key_len, hwt_enc_len, hwt_enc_cnt);
3128
3129 /*check the parameters.*/
3130 if (hwt_enc_type < 10 && hwt_key_len <= 16 &&
3131 hwt_enc_len <= 1500 && hwt_enc_cnt > 0) {
3132 HWT_PARAMETERS hwt_hdr = {
3133 .TestID = 0x0003,
3134 .Params = (hwt_key_len<<8) | hwt_enc_type,
3135 .Datalen = hwt_enc_len,
3136 .Data = hwt_enc_cnt
3137 };
3138 hwt_testing = 1;
3139 wsm_hwt_cmd(hw_priv, (void *)&hwt_hdr.TestID, sizeof(hwt_hdr)-4);
3140 }
3141
3142 return count;
3143 }
3144
3145 static const struct file_operations fops_hwt_enc = {
3146 .open = xradio_generic_open,
3147 .write = xradio_hwt_enc,
3148 .llseek = default_llseek,
3149 };
3150
3151 /*MIC test*/
3152 u16 hwt_mic_len;
3153 u16 hwt_mic_cnt;
xradio_hwt_mic(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)3154 static ssize_t xradio_hwt_mic(struct file *file,
3155 const char __user *user_buf, size_t count, loff_t *ppos)
3156 {
3157 struct xradio_common *hw_priv = file->private_data;
3158 char buf[100] = { 0 };
3159 char *start = &buf[0];
3160 char *endptr = NULL;
3161
3162 if (hwt_testing) {
3163 xradio_dbg(XRADIO_DBG_ALWY, "cmd refuse, hwt is testing!\n");
3164 return count;
3165 }
3166
3167 count = (count > 99 ? 99 : count);
3168 if (!count)
3169 return -EINVAL;
3170 if (copy_from_user(buf, user_buf, count))
3171 return -EFAULT;
3172
3173 hwt_mic_len = simple_strtoul(start, &endptr, 10);
3174 start = endptr + 1;
3175 if (start < buf + count)
3176 hwt_mic_cnt = simple_strtoul(start, &endptr, 10);
3177
3178 xradio_dbg(XRADIO_DBG_ALWY, "mic_len=%d, mic_cnt=%d\n",
3179 hwt_mic_len, hwt_mic_cnt);
3180
3181 /*check the parameters.*/
3182 if (hwt_mic_len <= 1500 && hwt_mic_cnt > 0) {
3183 HWT_PARAMETERS hwt_hdr = {
3184 .TestID = 0x0004,
3185 .Params = 0,
3186 .Datalen = hwt_mic_len,
3187 .Data = hwt_mic_cnt
3188 };
3189 hwt_testing = 1;
3190 wsm_hwt_cmd(hw_priv, (void *)&hwt_hdr.TestID, sizeof(hwt_hdr)-4);
3191 }
3192
3193 return count;
3194 }
3195
3196 static const struct file_operations fops_hwt_mic = {
3197 .open = xradio_generic_open,
3198 .write = xradio_hwt_mic,
3199 .llseek = default_llseek,
3200 };
3201
xradio_hwt_hif_rx_burn(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)3202 static ssize_t xradio_hwt_hif_rx_burn(struct file *file,
3203 const char __user *user_buf, size_t count, loff_t *ppos)
3204 {
3205 struct xradio_common *hw_priv = file->private_data;
3206 char buf[100] = { 0 };
3207 char *start = &buf[0];
3208 char *endptr = NULL;
3209
3210 u16 hw_inf_cmd = 0;
3211
3212 HWT_PARAMETERS hwt_hdr = {
3213 .TestID = 0x0005,
3214 .Params = hw_inf_cmd,
3215 .Data = 10000
3216 };
3217
3218
3219 count = (count > 99 ? 99 : count);
3220 if (!count)
3221 return -EINVAL;
3222 if (copy_from_user(buf, user_buf, count))
3223 return -EFAULT;
3224
3225
3226 hw_inf_cmd = simple_strtoul(start, &endptr, 10);
3227
3228 xradio_dbg(XRADIO_DBG_ALWY, "hw_inf_cmd=%d\n", hw_inf_cmd);
3229
3230 hwt_hdr.Params = hw_inf_cmd;
3231
3232 wsm_hwt_cmd(hw_priv, (void *)&hwt_hdr.TestID, sizeof(hwt_hdr)-4);
3233
3234 return count;
3235 }
3236
3237 static const struct file_operations fops_hwt_hif_rx_burn = {
3238 .open = xradio_generic_open,
3239 .write = xradio_hwt_hif_rx_burn,
3240 .llseek = default_llseek,
3241 };
3242
3243 #endif /*DGB_XRADIO_HWT*/
3244
3245 static u32 measure_type;
3246
xradio_measure_type_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)3247 static ssize_t xradio_measure_type_write(struct file *file,
3248 const char __user *user_buf, size_t count, loff_t *ppos)
3249 {
3250 struct xradio_common *hw_priv = file->private_data;
3251 char buf[12] = { 0 };
3252 char *endptr = NULL;
3253 count = (count > 11 ? 11 : count);
3254 if (!count)
3255 return -EINVAL;
3256 if (copy_from_user(buf, user_buf, count))
3257 return -EFAULT;
3258 measure_type = simple_strtoul(buf, &endptr, 16);
3259
3260 xradio_dbg(XRADIO_DBG_ALWY, "measure_type = %08x\n", measure_type);
3261 SYS_WARN(wsm_11k_measure_requset(hw_priv, (measure_type & 0xff),
3262 ((measure_type & 0xff00) >> 8),
3263 ((measure_type & 0xffff0000) >> 16)));
3264 return count;
3265 }
3266
xradio_measure_type_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)3267 static ssize_t xradio_measure_type_read(struct file *file,
3268 char __user *user_buf, size_t count, loff_t *ppos)
3269 {
3270 /*struct xradio_common *hw_priv = file->private_data;*/
3271 char buf[20];
3272 size_t size = 0;
3273
3274 sprintf(buf, "measure_type = %u\n", measure_type);
3275 size = strlen(buf);
3276
3277 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
3278 }
3279
3280 static const struct file_operations fops_11k = {
3281 .open = xradio_generic_open,
3282 .write = xradio_measure_type_write,
3283 .read = xradio_measure_type_read,
3284 .llseek = default_llseek,
3285 };
3286
xradio_wsm_dumps(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)3287 static ssize_t xradio_wsm_dumps(struct file *file,
3288 const char __user *user_buf, size_t count, loff_t *ppos)
3289 {
3290 struct xradio_common *hw_priv = file->private_data;
3291 char buf[1];
3292
3293 if (!count)
3294 return -EINVAL;
3295 if (copy_from_user(buf, user_buf, 1))
3296 return -EFAULT;
3297
3298 if (buf[0] == '1')
3299 hw_priv->wsm_enable_wsm_dumps = 1;
3300 else
3301 hw_priv->wsm_enable_wsm_dumps = 0;
3302
3303 return count;
3304 }
3305
3306 static const struct file_operations fops_wsm_dumps = {
3307 .open = xradio_generic_open,
3308 .write = xradio_wsm_dumps,
3309 .llseek = default_llseek,
3310 };
3311
xradio_short_dump_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)3312 static ssize_t xradio_short_dump_read(struct file *file,
3313 char __user *user_buf, size_t count, loff_t *ppos)
3314 {
3315 struct xradio_common *hw_priv = file->private_data;
3316 char buf[20];
3317 size_t size = 0;
3318
3319 sprintf(buf, "Size: %u\n", hw_priv->wsm_dump_max_size);
3320 size = strlen(buf);
3321
3322 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
3323 }
3324
xradio_short_dump_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)3325 static ssize_t xradio_short_dump_write(struct file *file,
3326 const char __user *user_buf, size_t count, loff_t *ppos)
3327 {
3328 struct xradio_common *priv = file->private_data;
3329 char buf[20];
3330 unsigned long dump_size = 0;
3331
3332 if (!count || count > 20)
3333 return -EINVAL;
3334 if (copy_from_user(buf, user_buf, count))
3335 return -EFAULT;
3336
3337 if (kstrtoul(buf, 10, &dump_size))
3338 return -EINVAL;
3339 xradio_dbg(XRADIO_DBG_ALWY, "%s get %lu\n", __func__, dump_size);
3340
3341 priv->wsm_dump_max_size = dump_size;
3342
3343 return count;
3344 }
3345
3346 static const struct file_operations fops_short_dump = {
3347 .open = xradio_generic_open,
3348 .write = xradio_short_dump_write,
3349 .read = xradio_short_dump_read,
3350 .llseek = default_llseek,
3351 };
3352
3353 #ifdef SUPPORT_HT40
3354
xradio_status_show_priv(struct seq_file * seq,void * v)3355 static int xradio_status_show_priv(struct seq_file *seq, void *v)
3356 {
3357 int i;
3358 struct xradio_vif *priv = seq->private;
3359 struct xradio_debug_priv *d = priv->debug;
3360
3361 seq_printf(seq, "Mode: %s%s\n",
3362 xradio_debug_mode(priv->mode),
3363 priv->listening ? " (listening)" : "");
3364 seq_printf(seq, "Assoc: %s\n",
3365 xradio_debug_join_status[priv->join_status]);
3366 if (priv->rx_filter.promiscuous)
3367 seq_puts(seq, "Filter: promisc\n");
3368 else if (priv->rx_filter.fcs)
3369 seq_puts(seq, "Filter: fcs\n");
3370 if (priv->rx_filter.bssid)
3371 seq_puts(seq, "Filter: bssid\n");
3372 if (priv->bf_control.bcn_count)
3373 seq_puts(seq, "Filter: beacons\n");
3374
3375 if (priv->enable_beacon ||
3376 priv->mode == NL80211_IFTYPE_AP ||
3377 priv->mode == NL80211_IFTYPE_ADHOC ||
3378 priv->mode == NL80211_IFTYPE_MESH_POINT ||
3379 priv->mode == NL80211_IFTYPE_P2P_GO)
3380 seq_printf(seq, "Beaconing: %s\n",
3381 priv->enable_beacon ? "enabled" : "disabled");
3382 if (priv->ssid_length ||
3383 priv->mode == NL80211_IFTYPE_AP ||
3384 priv->mode == NL80211_IFTYPE_ADHOC ||
3385 priv->mode == NL80211_IFTYPE_MESH_POINT ||
3386 priv->mode == NL80211_IFTYPE_P2P_GO)
3387 seq_printf(seq, "SSID: %.*s\n",
3388 (int)priv->ssid_length, priv->ssid);
3389
3390 for (i = 0; i < 4; ++i) {
3391 seq_printf(seq, "EDCA(%d): %d, %d, %d, %d, %d\n", i,
3392 priv->edca.params[i].cwMin,
3393 priv->edca.params[i].cwMax,
3394 priv->edca.params[i].aifns,
3395 priv->edca.params[i].txOpLimit,
3396 priv->edca.params[i].maxReceiveLifetime);
3397 }
3398 if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
3399 static const char *pmMode = "unknown";
3400 switch (priv->powersave_mode.pmMode) {
3401 case WSM_PSM_ACTIVE:
3402 pmMode = "off";
3403 break;
3404 case WSM_PSM_PS:
3405 pmMode = "on";
3406 break;
3407 case WSM_PSM_FAST_PS:
3408 pmMode = "dynamic";
3409 break;
3410 }
3411 seq_printf(seq, "Preamble: %s\n",
3412 xradio_debug_preamble[
3413 priv->association_mode.PhyModeCfg.PreambleCfg]);
3414 seq_printf(seq, "AMPDU spcn: %d\n",
3415 priv->association_mode.mpduStartSpacing);
3416 seq_printf(seq, "Basic rate: 0x%.8X\n",
3417 le32_to_cpu(priv->association_mode.basicRateSet));
3418 seq_printf(seq, "Bss lost: %d beacons\n",
3419 priv->bss_params.beaconLostCount);
3420 seq_printf(seq, "AID: %d\n",
3421 priv->bss_params.aid);
3422 seq_printf(seq, "Rates: 0x%.8X\n",
3423 priv->bss_params.operationalRateSet);
3424 seq_printf(seq, "Powersave: %s\n", pmMode);
3425 }
3426 seq_printf(seq, "RSSI thold: %d\n",
3427 priv->cqm_rssi_thold);
3428 seq_printf(seq, "RSSI hyst: %d\n",
3429 priv->cqm_rssi_hyst);
3430 seq_printf(seq, "TXFL thold: %d\n",
3431 priv->cqm_tx_failure_thold);
3432 seq_printf(seq, "Linkloss: %d\n",
3433 priv->cqm_link_loss_count);
3434 seq_printf(seq, "Bcnloss: %d\n",
3435 priv->cqm_beacon_loss_count);
3436
3437 xradio_debug_print_map(seq, priv, "Link map: ",
3438 priv->link_id_map);
3439 xradio_debug_print_map(seq, priv, "Asleep map: ",
3440 priv->sta_asleep_mask);
3441 xradio_debug_print_map(seq, priv, "PSPOLL map: ",
3442 priv->pspoll_mask);
3443
3444 seq_puts(seq, "\n");
3445
3446 for (i = 0; i < MAX_STA_IN_AP_MODE; ++i) {
3447 if (priv->link_id_db[i].status) {
3448 seq_printf(seq, "Link %d: %s, %pM\n",
3449 i + 1, xradio_debug_link_id[
3450 priv->link_id_db[i].status],
3451 priv->link_id_db[i].mac);
3452 }
3453 }
3454
3455 seq_puts(seq, "\n");
3456
3457 seq_printf(seq, "Powermgmt: %s\n",
3458 priv->powersave_enabled ? "on" : "off");
3459
3460 seq_printf(seq, "TXed: %d\n",
3461 d->tx);
3462 seq_printf(seq, "AGG TXed: %d\n",
3463 d->tx_agg);
3464 seq_printf(seq, "MULTI TXed: %d (%d)\n",
3465 d->tx_multi, d->tx_multi_frames);
3466 seq_printf(seq, "RXed: %d\n",
3467 d->rx);
3468 seq_printf(seq, "AGG RXed: %d\n",
3469 d->rx_agg);
3470 seq_printf(seq, "TX align: %d\n",
3471 d->tx_align);
3472 seq_printf(seq, "TX TTL: %d\n",
3473 d->tx_ttl);
3474 return 0;
3475 }
3476
3477 #else
3478
xradio_status_show_priv(struct seq_file * seq,void * v)3479 static int xradio_status_show_priv(struct seq_file *seq, void *v)
3480 {
3481 int i;
3482 struct xradio_vif *priv = seq->private;
3483 struct xradio_debug_priv *d = priv->debug;
3484
3485 seq_printf(seq, "Mode: %s%s\n",
3486 xradio_debug_mode(priv->mode),
3487 priv->listening ? " (listening)" : "");
3488 seq_printf(seq, "Assoc: %s\n",
3489 xradio_debug_join_status[priv->join_status]);
3490 if (priv->rx_filter.promiscuous)
3491 seq_puts(seq, "Filter: promisc\n");
3492 else if (priv->rx_filter.fcs)
3493 seq_puts(seq, "Filter: fcs\n");
3494 if (priv->rx_filter.bssid)
3495 seq_puts(seq, "Filter: bssid\n");
3496 if (priv->bf_control.bcn_count)
3497 seq_puts(seq, "Filter: beacons\n");
3498
3499 if (priv->enable_beacon ||
3500 priv->mode == NL80211_IFTYPE_AP ||
3501 priv->mode == NL80211_IFTYPE_ADHOC ||
3502 priv->mode == NL80211_IFTYPE_MESH_POINT ||
3503 priv->mode == NL80211_IFTYPE_P2P_GO)
3504 seq_printf(seq, "Beaconing: %s\n",
3505 priv->enable_beacon ? "enabled" : "disabled");
3506 if (priv->ssid_length ||
3507 priv->mode == NL80211_IFTYPE_AP ||
3508 priv->mode == NL80211_IFTYPE_ADHOC ||
3509 priv->mode == NL80211_IFTYPE_MESH_POINT ||
3510 priv->mode == NL80211_IFTYPE_P2P_GO)
3511 seq_printf(seq, "SSID: %.*s\n",
3512 (int)priv->ssid_length, priv->ssid);
3513
3514 for (i = 0; i < 4; ++i) {
3515 seq_printf(seq, "EDCA(%d): %d, %d, %d, %d, %d\n", i,
3516 priv->edca.params[i].cwMin,
3517 priv->edca.params[i].cwMax,
3518 priv->edca.params[i].aifns,
3519 priv->edca.params[i].txOpLimit,
3520 priv->edca.params[i].maxReceiveLifetime);
3521 }
3522 if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
3523 static const char *pmMode = "unknown";
3524 switch (priv->powersave_mode.pmMode) {
3525 case WSM_PSM_ACTIVE:
3526 pmMode = "off";
3527 break;
3528 case WSM_PSM_PS:
3529 pmMode = "on";
3530 break;
3531 case WSM_PSM_FAST_PS:
3532 pmMode = "dynamic";
3533 break;
3534 }
3535 seq_printf(seq, "Preamble: %s\n",
3536 xradio_debug_preamble[
3537 priv->association_mode.preambleType]);
3538 seq_printf(seq, "AMPDU spcn: %d\n",
3539 priv->association_mode.mpduStartSpacing);
3540 seq_printf(seq, "Basic rate: 0x%.8X\n",
3541 le32_to_cpu(priv->association_mode.basicRateSet));
3542 seq_printf(seq, "Bss lost: %d beacons\n",
3543 priv->bss_params.beaconLostCount);
3544 seq_printf(seq, "AID: %d\n", priv->bss_params.aid);
3545 seq_printf(seq, "Rates: 0x%.8X\n",
3546 priv->bss_params.operationalRateSet);
3547 seq_printf(seq, "Powersave: %s\n", pmMode);
3548 }
3549 seq_printf(seq, "RSSI thold: %d\n", priv->cqm_rssi_thold);
3550 seq_printf(seq, "RSSI hyst: %d\n", priv->cqm_rssi_hyst);
3551 seq_printf(seq, "TXFL thold: %d\n", priv->cqm_tx_failure_thold);
3552 seq_printf(seq, "Linkloss: %d\n", priv->cqm_link_loss_count);
3553 seq_printf(seq, "Bcnloss: %d\n", priv->cqm_beacon_loss_count);
3554
3555 xradio_debug_print_map(seq, priv, "Link map: ", priv->link_id_map);
3556 xradio_debug_print_map(seq, priv, "Asleep map: ",
3557 priv->sta_asleep_mask);
3558 xradio_debug_print_map(seq, priv, "PSPOLL map: ", priv->pspoll_mask);
3559
3560 seq_puts(seq, "\n");
3561
3562 for (i = 0; i < MAX_STA_IN_AP_MODE; ++i) {
3563 if (priv->link_id_db[i].status) {
3564 seq_printf(seq, "Link %d: %s, %pM\n",
3565 i + 1, xradio_debug_link_id[
3566 priv->link_id_db[i].status],
3567 priv->link_id_db[i].mac);
3568 }
3569 }
3570
3571 seq_puts(seq, "\n");
3572
3573 seq_printf(seq, "Powermgmt: %s\n",
3574 priv->powersave_enabled ? "on" : "off");
3575
3576 seq_printf(seq, "TXed: %d\n", d->tx);
3577 seq_printf(seq, "AGG TXed: %d\n", d->tx_agg);
3578 seq_printf(seq, "MULTI TXed: %d (%d)\n",
3579 d->tx_multi, d->tx_multi_frames);
3580 seq_printf(seq, "RXed: %d\n", d->rx);
3581 seq_printf(seq, "AGG RXed: %d\n", d->rx_agg);
3582 seq_printf(seq, "TX align: %d\n", d->tx_align);
3583 seq_printf(seq, "TX TTL: %d\n", d->tx_ttl);
3584 return 0;
3585 }
3586
3587 #endif
3588
xradio_status_open_priv(struct inode * inode,struct file * file)3589 static int xradio_status_open_priv(struct inode *inode,
3590 struct file *file)
3591 {
3592 return single_open(file, &xradio_status_show_priv, inode->i_private);
3593 }
3594
3595 static const struct file_operations fops_status_priv = {
3596 .open = xradio_status_open_priv,
3597 .read = seq_read,
3598 .llseek = seq_lseek,
3599 .release = single_release,
3600 .owner = THIS_MODULE,
3601 };
3602
3603 #if defined(CONFIG_XRADIO_USE_EXTENSIONS)
3604
xradio_hang_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)3605 static ssize_t xradio_hang_write(struct file *file,
3606 const char __user *user_buf, size_t count, loff_t *ppos)
3607 {
3608 struct xradio_vif *priv = file->private_data;
3609 struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
3610 char buf[1];
3611
3612 if (!count)
3613 return -EINVAL;
3614 if (copy_from_user(buf, user_buf, 1))
3615 return -EFAULT;
3616
3617 if (priv->vif) {
3618 #ifdef CONFIG_PM
3619 xradio_pm_stay_awake(&hw_priv->pm_state, 3 * HZ);
3620 #endif
3621
3622 wsm_send_deauth_to_self(hw_priv, priv);
3623
3624 /* ieee80211_driver_hang_notify(priv->vif, GFP_KERNEL); */
3625 } else
3626 return -ENODEV;
3627
3628 return count;
3629 }
3630
3631 static const struct file_operations fops_hang = {
3632 .open = xradio_generic_open,
3633 .write = xradio_hang_write,
3634 .llseek = default_llseek,
3635 };
3636 #endif
3637
3638 #ifdef AP_HT_COMPAT_FIX
3639 extern u8 ap_compat_bssid[ETH_ALEN];
xradio_ht_compat_show(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)3640 static ssize_t xradio_ht_compat_show(struct file *file,
3641 char __user *user_buf, size_t count, loff_t *ppos)
3642 {
3643 struct xradio_vif *priv = file->private_data;
3644 char buf[100];
3645 size_t size = 0;
3646 sprintf(buf, "ht_compat_det=0x%x, BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n",
3647 priv->ht_compat_det,
3648 ap_compat_bssid[0], ap_compat_bssid[1],
3649 ap_compat_bssid[2], ap_compat_bssid[3],
3650 ap_compat_bssid[4], ap_compat_bssid[5]);
3651 size = strlen(buf);
3652
3653 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
3654 }
3655
xradio_ht_compat_disalbe(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)3656 static ssize_t xradio_ht_compat_disalbe(struct file *file,
3657 const char __user *user_buf, size_t count, loff_t *ppos)
3658 {
3659 struct xradio_vif *priv = file->private_data;
3660 char buf[2];
3661 char *endptr = NULL;
3662
3663 if (!count)
3664 return -EINVAL;
3665 if (copy_from_user(buf, user_buf, 2))
3666 return -EFAULT;
3667
3668 if (simple_strtoul(buf, &endptr, 10))
3669 priv->ht_compat_det |= 0x10;
3670 else
3671 priv->ht_compat_det &= ~0x10;
3672 return count;
3673 }
3674
3675 static const struct file_operations fops_ht_compat_dis = {
3676 .open = xradio_generic_open,
3677 .read = xradio_ht_compat_show,
3678 .write = xradio_ht_compat_disalbe,
3679 .llseek = default_llseek,
3680 };
3681 #endif
3682
3683 #define VIF_DEBUGFS_NAME_S 10
xradio_debug_init_priv(struct xradio_common * hw_priv,struct xradio_vif * priv)3684 int xradio_debug_init_priv(struct xradio_common *hw_priv,
3685 struct xradio_vif *priv)
3686 {
3687 int ret = -ENOMEM;
3688 struct xradio_debug_priv *d;
3689 char name[VIF_DEBUGFS_NAME_S];
3690 xradio_dbg(XRADIO_DBG_TRC, "%s\n", __func__);
3691
3692 if (SYS_WARN(!hw_priv))
3693 return ret;
3694
3695 if (SYS_WARN(!hw_priv->debug))
3696 return ret;
3697
3698 d = xr_kzalloc(sizeof(struct xradio_debug_priv), false);
3699 priv->debug = d;
3700 if (SYS_WARN(!d))
3701 return ret;
3702
3703 memset(name, 0, VIF_DEBUGFS_NAME_S);
3704 ret = snprintf(name, VIF_DEBUGFS_NAME_S, "vif_%d", priv->if_id);
3705 if (SYS_WARN(ret < 0))
3706 goto err;
3707
3708 d->debugfs_phy = debugfs_create_dir(name,
3709 hw_priv->debug->debugfs_phy);
3710 if (SYS_WARN(!d->debugfs_phy))
3711 goto err;
3712
3713 #if defined(CONFIG_XRADIO_USE_EXTENSIONS)
3714 if (SYS_WARN(!debugfs_create_file("hang", S_IWUSR, d->debugfs_phy,
3715 priv, &fops_hang)))
3716 goto err;
3717 #endif
3718
3719 #if defined(AP_HT_COMPAT_FIX)
3720 if (SYS_WARN(!debugfs_create_file("htcompat_disable",
3721 S_IWUSR, d->debugfs_phy, priv, &fops_ht_compat_dis)))
3722 goto err;
3723 #endif
3724
3725 if (!debugfs_create_file("status", S_IRUSR, d->debugfs_phy,
3726 priv, &fops_status_priv))
3727 goto err;
3728
3729 return 0;
3730 err:
3731 priv->debug = NULL;
3732 debugfs_remove_recursive(d->debugfs_phy);
3733 kfree(d);
3734 return ret;
3735
3736 }
3737
xradio_debug_release_priv(struct xradio_vif * priv)3738 void xradio_debug_release_priv(struct xradio_vif *priv)
3739 {
3740 struct xradio_debug_priv *d = priv->debug;
3741 xradio_dbg(XRADIO_DBG_TRC, "%s\n", __func__);
3742 if (d) {
3743 priv->debug = NULL;
3744 debugfs_remove_recursive(d->debugfs_phy);
3745 kfree(d);
3746 }
3747 }
3748
xradio_print_fw_version(struct xradio_common * hw_priv,u8 * buf,size_t len)3749 int xradio_print_fw_version(struct xradio_common *hw_priv,
3750 u8 *buf, size_t len)
3751 {
3752 return snprintf(buf, len, "%s %d.%d",
3753 xradio_debug_fw_types[hw_priv->wsm_caps.firmwareType],
3754 hw_priv->wsm_caps.firmwareVersion,
3755 hw_priv->wsm_caps.firmwareBuildNumber);
3756 }
3757 #if (SUPPORT_EPTA)
3758 static const struct file_operations fops_epta_stat_dbg_ctrl = {
3759 .open = xradio_generic_open,
3760 .write = xradio_epta_stat_dbg_write,
3761 .read = xradio_epta_stat_dbg_read,
3762 .llseek = default_llseek,
3763 };
3764 #endif
3765
3766 #if (DBG_XRADIO_HIF)
3767
xradio_hif_test_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)3768 static ssize_t xradio_hif_test_write(struct file *file,
3769 const char __user *user_buf, size_t count, loff_t *ppos)
3770 {
3771 char buf[50] = {0};
3772 char *start = &buf[0];
3773 char *endptr = NULL;
3774
3775 count = (count > 50 ? 50 : count);
3776
3777 printk(KERN_ERR"set value\n");
3778 if (!count)
3779 return -EINVAL;
3780 if (copy_from_user(buf, user_buf, count))
3781 return -EFAULT;
3782 hif_test_rw = simple_strtoul(start, &endptr, 16);
3783 start = endptr + 1;
3784
3785 if (start < buf + count)
3786 hif_test_data_mode = simple_strtoul(start, &endptr, 16);
3787
3788 start = endptr + 1;
3789 if (start < buf + count)
3790 hif_test_data_len = simple_strtoul(start, &endptr, 16);
3791
3792 start = endptr + 1;
3793 if (start < buf + count)
3794 hif_test_data_round = simple_strtoul(start, &endptr, 16);
3795
3796 start = endptr + 1;
3797 if (start < buf + count)
3798 hif_test_oper_delta = simple_strtoul(start, &endptr, 16);
3799
3800 xradio_dbg(XRADIO_DBG_ALWY, "[HIF test] configuration %s, val is 0x%x, "
3801 "round is %u, data size is %u per round delay %u ms per round\n",
3802 hif_test_rw ? (hif_test_rw > 1 ? "R & W" : "W") : "Not Test",
3803 hif_test_data_round,
3804 hif_test_data_mode,
3805 hif_test_data_len*4,
3806 hif_test_oper_delta);
3807 return count;
3808 }
3809
xradio_hif_test_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)3810 static ssize_t xradio_hif_test_read(struct file *file,
3811 char __user *user_buf, size_t count, loff_t *ppos)
3812 {
3813 /* struct xradio_common *hw_priv = file->private_data;
3814 char buf[50];
3815 size_t size = 0;
3816
3817 sprintf(buf, "fwdbg_ctrl = %u\n", fwdbg_ctrl);
3818 size = strlen(buf);
3819
3820 return simple_read_from_buffer(user_buf, count, ppos, buf, size);
3821 */
3822 return 0;
3823 }
3824 static const struct file_operations fops_hif_test = {
3825 .open = xradio_generic_open,
3826 .write = xradio_hif_test_write,
3827 .read = xradio_hif_test_read,
3828 .llseek = default_llseek,
3829 };
3830
3831 #endif
3832
3833 #ifdef ERROR_HANG_DRIVER
xradio_hang_driver_for_debug(struct xradio_common * hw_priv,int error)3834 void xradio_hang_driver_for_debug(struct xradio_common *hw_priv, int error)
3835 {
3836 int cnt = 0;
3837 if (!error_hang_driver || !error)
3838 return ; /*do nothing.*/
3839
3840 if (!hw_priv->debug) { /*have not setup debugfs yet, just do it.*/
3841 xradio_debug_init_common(hw_priv);
3842 }
3843 while (error_hang_driver) {
3844 msleep(5000);
3845 cnt++;
3846 xradio_dbg(XRADIO_DBG_ALWY, "err=%d, hang driver for %ds.\n",
3847 error, cnt*5);
3848 }
3849 xradio_debug_release_common(hw_priv);
3850 xradio_dbg(XRADIO_DBG_ALWY, "%s exit.\n", __func__);
3851 }
3852 #endif
3853
3854 /*for host debuglevel*/
3855 struct dentry *debugfs_host;
3856 #if (DGB_XRADIO_QC)
3857 struct dentry *debugfs_hwinfo;
3858 #endif
xradio_host_dbg_init(void)3859 int xradio_host_dbg_init(void)
3860 {
3861 int line = 0;
3862 xradio_dbg(XRADIO_DBG_TRC, "%s\n", __func__);
3863
3864 if (!debugfs_initialized()) {
3865 xradio_dbg(XRADIO_DBG_ERROR, "debugfs isnot initialized\n");
3866 return 0;
3867 }
3868 #define ERR_LINE do { line = __LINE__; goto err; } while (0)
3869
3870 debugfs_host = debugfs_create_dir("xradio_host_dbg", NULL);
3871 if (!debugfs_host)
3872 ERR_LINE;
3873
3874 debugfs_create_x8("dbg_common", S_IRUSR | S_IWUSR,
3875 debugfs_host, &dbg_common);
3876
3877 debugfs_create_x8("dbg_sbus", S_IRUSR | S_IWUSR,
3878 debugfs_host, &dbg_sbus);
3879
3880 debugfs_create_x8("dbg_ap", S_IRUSR | S_IWUSR,
3881 debugfs_host, &dbg_ap);
3882
3883 debugfs_create_x8("dbg_sta", S_IRUSR | S_IWUSR,
3884 debugfs_host, &dbg_sta);
3885
3886 debugfs_create_x8("dbg_scan", S_IRUSR | S_IWUSR,
3887 debugfs_host, &dbg_scan);
3888
3889 debugfs_create_x8("dbg_bh", S_IRUSR | S_IWUSR,
3890 debugfs_host, &dbg_bh);
3891
3892 debugfs_create_x8("dbg_txrx", S_IRUSR | S_IWUSR,
3893 debugfs_host, &dbg_txrx);
3894
3895 debugfs_create_x8("dbg_wsm", S_IRUSR | S_IWUSR,
3896 debugfs_host, &dbg_wsm);
3897
3898 debugfs_create_x8("dbg_pm", S_IRUSR | S_IWUSR,
3899 debugfs_host, &dbg_pm);
3900
3901 #ifdef CONFIG_XRADIO_ITP
3902 debugfs_create_x8("dbg_itp", S_IRUSR | S_IWUSR,
3903 debugfs_host, &dbg_itp);
3904 #endif
3905
3906 #ifdef CONFIG_XRADIO_ETF
3907 debugfs_create_x8("dbg_etf", S_IRUSR | S_IWUSR,
3908 debugfs_host, &dbg_etf);
3909 #endif
3910
3911 debugfs_create_x8("dbg_logfile", S_IRUSR | S_IWUSR,
3912 debugfs_host, &dbg_logfile);
3913
3914 debugfs_create_x8("dbg_tpa_node", S_IRUSR | S_IWUSR,
3915 debugfs_host, &tpa_node_dbg);
3916
3917 debugfs_create_u32("set_sdio_clk", S_IRUSR | S_IWUSR,
3918 debugfs_host, &dbg_sdio_clk);
3919
3920 debugfs_create_u32("tx_burst_limit", S_IRUSR | S_IWUSR,
3921 debugfs_host, &tx_burst_limit);
3922
3923 #ifdef ERROR_HANG_DRIVER
3924 debugfs_create_u8("error_hang_driver", S_IRUSR | S_IWUSR,
3925 debugfs_host, &error_hang_driver);
3926 #endif
3927
3928 return 0;
3929
3930 #undef ERR_LINE
3931 err:
3932 xradio_dbg(XRADIO_DBG_ERROR, "xradio_host_dbg_init failed=%d\n", line);
3933 if (debugfs_host)
3934 debugfs_remove_recursive(debugfs_host);
3935 #if (DGB_XRADIO_QC)
3936 debugfs_hwinfo = NULL;
3937 #endif
3938 debugfs_host = NULL;
3939 return 0;
3940 }
3941
xradio_host_dbg_deinit(void)3942 void xradio_host_dbg_deinit(void)
3943 {
3944 xradio_dbg(XRADIO_DBG_TRC, "%s\n", __func__);
3945 if (debugfs_host)
3946 debugfs_remove_recursive(debugfs_host);
3947 #if (DGB_XRADIO_QC)
3948 debugfs_hwinfo = NULL;
3949 #endif
3950 debugfs_host = NULL;
3951 }
3952
xradio_debug_init_common(struct xradio_common * hw_priv)3953 int xradio_debug_init_common(struct xradio_common *hw_priv)
3954 {
3955 int ret = -ENOMEM;
3956 int line = 0;
3957 struct xradio_debug_common *d = NULL;
3958 xradio_dbg(XRADIO_DBG_TRC, "%s\n", __func__);
3959
3960 /*init some debug variables here.*/
3961 retry_dbg = 0;
3962 tpa_node_dbg = 0;
3963
3964 #define ERR_LINE do { line = __LINE__; goto err; } while (0)
3965
3966 d = xr_kzalloc(sizeof(struct xradio_debug_common), false);
3967 hw_priv->debug = d;
3968 if (!d) {
3969 xradio_dbg(XRADIO_DBG_ERROR, "%s, xr_kzalloc failed!\n", __func__);
3970 return ret;
3971 }
3972
3973 #ifdef ERROR_HANG_DRIVER
3974 d->debugfs_phy = debugfs_create_dir("xradio", NULL);
3975 #else
3976 d->debugfs_phy = debugfs_create_dir("xradio",
3977 hw_priv->hw->wiphy->debugfsdir);
3978 #endif
3979
3980 if (!d->debugfs_phy)
3981 ERR_LINE;
3982
3983 if (!debugfs_create_file("version", S_IRUSR, d->debugfs_phy,
3984 hw_priv, &fops_version))
3985 ERR_LINE;
3986
3987 if (!debugfs_create_file("status", S_IRUSR, d->debugfs_phy,
3988 hw_priv, &fops_status_common))
3989 ERR_LINE;
3990
3991 if (!debugfs_create_file("counters", S_IRUSR, d->debugfs_phy,
3992 hw_priv, &fops_counters))
3993 ERR_LINE;
3994
3995 if (!debugfs_create_file("backoff", S_IRUSR, d->debugfs_phy,
3996 hw_priv, &fops_backoff))
3997 ERR_LINE;
3998
3999 if (!debugfs_create_file("txpipe", S_IRUSR, d->debugfs_phy,
4000 hw_priv, &fops_txpipe))
4001 ERR_LINE;
4002
4003 if (!debugfs_create_file("ampdu", S_IRUSR, d->debugfs_phy,
4004 hw_priv, &fops_ampducounters))
4005 ERR_LINE;
4006
4007 if (!debugfs_create_file("ratemap", S_IRUSR, d->debugfs_phy,
4008 hw_priv, &fops_ratemap))
4009 ERR_LINE;
4010
4011 if (!debugfs_create_file("dbgstats", S_IRUSR, d->debugfs_phy,
4012 hw_priv, &fops_dbgstats))
4013 ERR_LINE;
4014
4015 if (!debugfs_create_file("11n", S_IRUSR | S_IWUSR,
4016 d->debugfs_phy, hw_priv, &fops_11n))
4017 ERR_LINE;
4018
4019 if (!debugfs_create_file("wsm_dumps", S_IWUSR, d->debugfs_phy,
4020 hw_priv, &fops_wsm_dumps))
4021 ERR_LINE;
4022
4023 if (!debugfs_create_file("set_fwdbg", S_IRUSR | S_IWUSR, d->debugfs_phy,
4024 hw_priv, &fops_fwdbg))
4025 ERR_LINE;
4026
4027 if (!debugfs_create_file("rw_fwreg", S_IWUSR, d->debugfs_phy, hw_priv,
4028 &fops_rw_fwreg))
4029 ERR_LINE;
4030
4031 if (!debugfs_create_file("rw_fwreg_direct", S_IWUSR, d->debugfs_phy,
4032 hw_priv, &fops_rw_fwreg_direct))
4033 ERR_LINE;
4034
4035 if (!debugfs_create_file("set_ampdu_len", S_IRUSR | S_IWUSR,
4036 d->debugfs_phy, hw_priv, &fops_ampdu_len))
4037 ERR_LINE;
4038
4039 if (!debugfs_create_file("set_rts_threshold", S_IRUSR | S_IWUSR,
4040 d->debugfs_phy, hw_priv, &fops_rts_threshold))
4041 ERR_LINE;
4042
4043 if (!debugfs_create_file("low_pwr_disable", S_IRUSR | S_IWUSR,
4044 d->debugfs_phy, hw_priv, &fops_low_pwr))
4045 ERR_LINE;
4046
4047 if (!debugfs_create_file("ps_disable", S_IRUSR | S_IWUSR, d->debugfs_phy,
4048 hw_priv, &fops_ps_ctrl))
4049 ERR_LINE;
4050
4051 if (!debugfs_create_file("retry_ctrl", S_IRUSR | S_IWUSR, d->debugfs_phy,
4052 hw_priv, &fops_retry_ctrl))
4053 ERR_LINE;
4054
4055 if (!debugfs_create_file("rates_ctrl", S_IRUSR | S_IWUSR, d->debugfs_phy,
4056 hw_priv, &fops_rates_ctrl))
4057 ERR_LINE;
4058
4059 if (!debugfs_create_file("backoff_ctrl", S_IRUSR | S_IWUSR, d->debugfs_phy,
4060 hw_priv, &fops_backoff_ctrl))
4061 ERR_LINE;
4062
4063 if (!debugfs_create_file("tala_ctrl", S_IRUSR | S_IWUSR, d->debugfs_phy,
4064 hw_priv, &fops_tala_ctrl))
4065 ERR_LINE;
4066
4067 if (!debugfs_create_file("tx_pwr_ctrl", S_IRUSR | S_IWUSR, d->debugfs_phy,
4068 hw_priv, &fops_tx_pwr_ctrl))
4069 ERR_LINE;
4070
4071 if (!debugfs_create_file("tpa_ctrl", S_IRUSR | S_IWUSR, d->debugfs_phy,
4072 hw_priv, &fops_tpa_ctrl))
4073 ERR_LINE;
4074
4075 if (!debugfs_create_file("tpa_debug", S_IRUSR, d->debugfs_phy,
4076 hw_priv, &fops_tpa_debug))
4077 ERR_LINE;
4078
4079 if (!debugfs_create_file("policy_info", S_IRUSR, d->debugfs_phy,
4080 hw_priv, &fops_policy_info))
4081 ERR_LINE;
4082
4083 if (!debugfs_create_file("bh_stat", S_IRUSR, d->debugfs_phy,
4084 hw_priv, &fops_bh_stat))
4085 ERR_LINE;
4086
4087 #if PERF_INFO_TEST
4088 if (!debugfs_create_file("perf_info", S_IRUSR, d->debugfs_phy,
4089 hw_priv, &fops_perf_info))
4090 ERR_LINE;
4091 #endif
4092
4093 if (!debugfs_create_file("txconfirm", S_IRUSR, d->debugfs_phy,
4094 hw_priv, &fops_txconfirm))
4095 ERR_LINE;
4096
4097 if (!debugfs_create_file("tx_delay", S_IRUSR, d->debugfs_phy,
4098 hw_priv, &fops_txdelay))
4099 ERR_LINE;
4100
4101 if (!debugfs_create_file("parse_flags", S_IRUSR | S_IWUSR,
4102 d->debugfs_phy, hw_priv, &fops_parse_flags))
4103 ERR_LINE;
4104
4105 if (!debugfs_create_file("set_measure_type", S_IRUSR | S_IWUSR,
4106 d->debugfs_phy, hw_priv, &fops_11k))
4107 ERR_LINE;
4108
4109 if (!debugfs_create_file("wsm_dump_size", S_IRUSR | S_IWUSR,
4110 d->debugfs_phy, hw_priv, &fops_short_dump))
4111 ERR_LINE;
4112
4113 #if (SUPPORT_EPTA)
4114 if (!debugfs_create_file("epta_stat", S_IRUSR, d->debugfs_phy,
4115 hw_priv, &fops_epta_stat))
4116 ERR_LINE;
4117
4118 if (!debugfs_create_file("epta_stat_ctrl", S_IRUSR | S_IWUSR, d->debugfs_phy,
4119 hw_priv, &fops_epta_stat_dbg_ctrl))
4120 ERR_LINE;
4121 #endif
4122
4123 #if (DGB_XRADIO_HWT)
4124 /*hardware test*/
4125 if (!debugfs_create_file("hwt_hif_tx", S_IWUSR, d->debugfs_phy,
4126 hw_priv, &fops_hwt_hif_tx))
4127 ERR_LINE;
4128
4129 if (!debugfs_create_file("hwt_hif_rx", S_IWUSR, d->debugfs_phy,
4130 hw_priv, &fops_hwt_hif_rx))
4131 ERR_LINE;
4132
4133 if (!debugfs_create_file("hwt_enc", S_IWUSR, d->debugfs_phy,
4134 hw_priv, &fops_hwt_enc))
4135 ERR_LINE;
4136
4137 if (!debugfs_create_file("hwt_mic", S_IWUSR, d->debugfs_phy,
4138 hw_priv, &fops_hwt_mic))
4139 ERR_LINE;
4140
4141 if (!debugfs_create_file("hwt_hif_rx_burn", S_IWUSR, d->debugfs_phy,
4142 hw_priv, &fops_hwt_hif_rx_burn))
4143 ERR_LINE;
4144
4145 #endif /*DGB_XRADIO_HWT*/
4146
4147 #if (DGB_XRADIO_QC)
4148 /*for QC apk read.*/
4149 if (debugfs_host && !debugfs_hwinfo) {
4150 debugfs_hwinfo = debugfs_create_file("hwinfo", S_IRUSR | S_IWUSR,
4151 debugfs_host, hw_priv, &fops_hwinfo);
4152 if (!debugfs_hwinfo)
4153 ERR_LINE;
4154 }
4155
4156 if (!debugfs_create_file("temperature", S_IRUSR, d->debugfs_phy,
4157 hw_priv, &fops_temperature))
4158 ERR_LINE;
4159 #endif
4160 ret = xradio_itp_init(hw_priv);
4161 if (ret)
4162 ERR_LINE;
4163
4164 #ifdef SUPPORT_FW_DBG_INF
4165 xradio_fw_dbg_init(hw_priv);
4166 #endif
4167
4168 return 0;
4169
4170 #undef ERR_LINE
4171
4172 err:
4173 xradio_dbg(XRADIO_DBG_ERROR,
4174 "xradio_debug_init_common failed=%d\n", line);
4175 hw_priv->debug = NULL;
4176 debugfs_remove_recursive(d->debugfs_phy);
4177 kfree(d);
4178 return ret;
4179 }
4180
xradio_debug_release_common(struct xradio_common * hw_priv)4181 void xradio_debug_release_common(struct xradio_common *hw_priv)
4182 {
4183 struct xradio_debug_common *d = hw_priv->debug;
4184 xradio_dbg(XRADIO_DBG_TRC, "%s\n", __func__);
4185
4186 #if (DGB_XRADIO_QC)
4187 if (debugfs_hwinfo) {
4188 debugfs_remove(debugfs_hwinfo);
4189 debugfs_hwinfo = NULL;
4190 }
4191 #endif
4192 if (d) {
4193 #ifdef SUPPORT_FW_DBG_INF
4194 xradio_fw_dbg_deinit();
4195 #endif
4196 xradio_itp_release(hw_priv);
4197 hw_priv->debug = NULL;
4198
4199 #ifdef ERROR_HANG_DRIVER
4200 debugfs_remove_recursive(d->debugfs_phy);
4201 #else
4202 /* removed by mac80211, don't remove it again,
4203 * fixed wifi on/off.*/
4204 /*
4205 debugfs_remove_recursive(d->debugfs_phy);
4206 */
4207 #endif
4208 kfree(d);
4209 }
4210 }
4211
4212 #define FRAME_TYPE(xx) ieee80211_is_ ## xx(fctl)
4213 #define FT_MSG_PUT(f, ...) do { \
4214 if (flags&f) \
4215 frame_msg += sprintf(frame_msg, __VA_ARGS__); \
4216 } while (0)
4217
4218 #define PT_MSG_PUT(f, ...) do { \
4219 if (flags&f) \
4220 proto_msg += sprintf(proto_msg, __VA_ARGS__); \
4221 } while (0)
4222
4223 #define FRAME_PARSE(f, name) do { \
4224 if (FRAME_TYPE(name)) { \
4225 FT_MSG_PUT(f, "%s", #name); goto outprint; } \
4226 } while (0)
4227
4228 #define IS_FRAME_PRINT (frame_msg != (char *)&framebuf[0])
4229 #define IS_PROTO_PRINT (proto_msg != (char *)&protobuf[0])
4230
4231
4232 char framebuf[512] = { 0 };
4233 char protobuf[512] = { 0 };
4234
4235 char *p2p_frame_type[] = {
4236 "GO Negotiation Request",
4237 "GO Negotiation Response",
4238 "GO Negotiation Confirmation",
4239 "P2P Invitation Request",
4240 "P2P Invitation Response",
4241 "Device Discoverability Request",
4242 "Device Discoverability Response",
4243 "Provision Discovery Request",
4244 "Provision Discovery Response",
4245 "Reserved"
4246 };
4247
xradio_parse_frame(u8 * mac_data,u8 iv_len,u16 flags,u8 if_id)4248 void xradio_parse_frame(u8 *mac_data, u8 iv_len, u16 flags, u8 if_id)
4249 {
4250 char *frame_msg = &framebuf[0];
4251 char *proto_msg = &protobuf[0];
4252 struct ieee80211_hdr *frame = (struct ieee80211_hdr *)mac_data;
4253 u16 fctl = frame->frame_control;
4254
4255 memset(frame_msg, 0, sizeof(framebuf));
4256 memset(proto_msg, 0, sizeof(protobuf));
4257
4258 if (ieee80211_is_data(fctl)) {
4259 u8 machdrlen = ieee80211_hdrlen(fctl);
4260 u8 *llc_data = mac_data + machdrlen + iv_len;
4261
4262 if (ieee80211_is_qos_nullfunc(fctl) ||
4263 ieee80211_is_data_qos(fctl))
4264 FT_MSG_PUT(PF_DATA, "QoS");
4265 if (ieee80211_is_nullfunc(fctl)) {
4266 FT_MSG_PUT(PF_DATA, "NULL(ps=%d)", !!(fctl&IEEE80211_FCTL_PM));
4267 goto outprint;
4268 }
4269 FT_MSG_PUT(PF_DATA, "data(TDFD=%d%d, R=%d, P=%d)",
4270 !!(fctl & IEEE80211_FCTL_TODS),
4271 !!(fctl & IEEE80211_FCTL_FROMDS),
4272 !!(fctl & IEEE80211_FCTL_RETRY),
4273 !!(fctl & IEEE80211_FCTL_PROTECTED));
4274
4275 if (is_SNAP(llc_data)) {
4276 if (is_ip(llc_data)) {
4277 u8 *ip_hdr = llc_data + LLC_LEN;
4278 u8 *ipaddr_s = ip_hdr + IP_S_ADD_OFF;
4279 u8 *ipaddr_d = ip_hdr + IP_D_ADD_OFF;
4280 u8 *proto_hdr = ip_hdr + ((ip_hdr[0] & 0xf) << 2); /*ihl:words*/
4281
4282 if (is_tcp(llc_data)) {
4283 PT_MSG_PUT(PF_TCP,
4284 "TCP%s%s, src=%d, dest=%d, seq=0x%08x, ack=0x%08x",
4285 (proto_hdr[13]&0x01) ? "(S)" : "",
4286 (proto_hdr[13]&0x02) ? "(F)" : "",
4287 (proto_hdr[0]<<8) | proto_hdr[1],
4288 (proto_hdr[2]<<8) | proto_hdr[3],
4289 (proto_hdr[4]<<24) | (proto_hdr[5]<<16) |
4290 (proto_hdr[6]<<8) | proto_hdr[7],
4291 (proto_hdr[8]<<24) | (proto_hdr[9]<<16) |
4292 (proto_hdr[10]<<8) | proto_hdr[11]);
4293
4294 } else if (is_udp(llc_data)) {
4295 if (is_dhcp(llc_data)) {
4296 u8 Options_len = BOOTP_OPS_LEN;
4297 u32 dhcp_magic = cpu_to_be32(DHCP_MAGIC);
4298 u8 *dhcphdr = proto_hdr + UDP_LEN+UDP_BOOTP_LEN;
4299 while (Options_len) {
4300 if (*(u32 *)dhcphdr == dhcp_magic)
4301 break;
4302 dhcphdr++;
4303 Options_len--;
4304 }
4305 PT_MSG_PUT(PF_DHCP, "DHCP, Opt=%d, MsgType=%d",
4306 *(dhcphdr+4), *(dhcphdr+6));
4307 } else {
4308 PT_MSG_PUT(PF_UDP, "UDP, source=%d, dest=%d",
4309 (proto_hdr[0]<<8) | proto_hdr[1],
4310 (proto_hdr[2]<<8) | proto_hdr[3]);
4311 }
4312 } else if (is_icmp(llc_data)) {
4313 PT_MSG_PUT(PF_ICMP, "ICMP%s%s, Seq=%d",
4314 (8 == proto_hdr[0]) ? "(ping)" : "",
4315 (0 == proto_hdr[0]) ? "(reply)" : "",
4316 (proto_hdr[6]<<8) | proto_hdr[7]);
4317 } else if (is_igmp(llc_data)) {
4318 PT_MSG_PUT(PF_UNKNWN, "IGMP, type=0x%x", proto_hdr[0]);
4319 } else {
4320 PT_MSG_PUT(PF_UNKNWN, "unknown IP type=%d",
4321 *(ip_hdr + IP_PROTO_OFF));
4322 }
4323 if (IS_PROTO_PRINT) {
4324 PT_MSG_PUT(PF_IPADDR, "-%d.%d.%d.%d(s)", \
4325 ipaddr_s[0], ipaddr_s[1],
4326 ipaddr_s[2], ipaddr_s[3]);
4327 PT_MSG_PUT(PF_IPADDR, "-%d.%d.%d.%d(d)", \
4328 ipaddr_d[0], ipaddr_d[1],
4329 ipaddr_d[2], ipaddr_d[3]);
4330 }
4331
4332 } else if (is_8021x(llc_data)) {
4333 PT_MSG_PUT(PF_8021X, "8021X");
4334 } else { /*other protol, no detail.*/
4335 switch (cpu_to_be16(*(u16 *)(llc_data+LLC_TYPE_OFF))) {
4336 case ETH_P_IPV6: /*0x08dd*/
4337 PT_MSG_PUT(PF_UNKNWN, "IPv6");
4338 break;
4339 case ETH_P_ARP: /*0x0806*/
4340 PT_MSG_PUT(PF_UNKNWN, "ARP");
4341 break;
4342 case ETH_P_RARP: /*0x8035*/
4343 PT_MSG_PUT(PF_UNKNWN, "RARP");
4344 break;
4345 case ETH_P_DNA_RC: /*0x6002*/
4346 PT_MSG_PUT(PF_UNKNWN, "DNA Remote Console");
4347 break;
4348 case ETH_P_DNA_RT: /*0x6003*/
4349 PT_MSG_PUT(PF_UNKNWN, "DNA Routing");
4350 break;
4351 case ETH_P_8021Q: /*0x8100*/
4352 PT_MSG_PUT(PF_UNKNWN, "802.1Q VLAN");
4353 break;
4354 case ETH_P_LINK_CTL: /*0x886c*/
4355 PT_MSG_PUT(PF_UNKNWN, "wlan link local tunnel(HPNA)");
4356 break;
4357 case ETH_P_PPP_DISC: /*0x8863*/
4358 PT_MSG_PUT(PF_UNKNWN, "PPPoE discovery");
4359 break;
4360 case ETH_P_PPP_SES: /*0x8864*/
4361 PT_MSG_PUT(PF_UNKNWN, "PPPoE session");
4362 break;
4363 case ETH_P_MPLS_UC: /*0x8847*/
4364 PT_MSG_PUT(PF_UNKNWN, "MPLS Unicast");
4365 break;
4366 case ETH_P_MPLS_MC: /*0x8848*/
4367 PT_MSG_PUT(PF_UNKNWN, "MPLS Multicast");
4368 break;
4369 default:
4370 PT_MSG_PUT(PF_UNKNWN, "unknown Ethernet type=0x%04x",
4371 cpu_to_be16(*(u16 *)(llc_data+LLC_TYPE_OFF)));
4372 break;
4373 }
4374 }
4375 } else if (is_STP(llc_data)) {
4376 /*spanning tree proto.*/
4377 PT_MSG_PUT(PF_UNKNWN, "spanning tree");
4378 } else {
4379 PT_MSG_PUT(PF_UNKNWN, "unknown LLC type=0x%08x, 0x%08x",
4380 *(u32 *)(llc_data), *((u32 *)(llc_data)+1));
4381 }
4382
4383 } else if (ieee80211_is_mgmt(fctl) && (PF_MGMT & flags)) {
4384
4385 FRAME_PARSE(PF_MGMT, auth);
4386 FRAME_PARSE(PF_MGMT, deauth);
4387 FRAME_PARSE(PF_MGMT, assoc_req);
4388 FRAME_PARSE(PF_MGMT, assoc_resp);
4389 FRAME_PARSE(PF_MGMT, reassoc_req);
4390 FRAME_PARSE(PF_MGMT, reassoc_resp);
4391 FRAME_PARSE(PF_MGMT, disassoc);
4392 FRAME_PARSE(PF_MGMT, atim);
4393
4394 /*for more information about action frames.*/
4395 if (FRAME_TYPE(action)) {
4396 u8 *encrypt_frame = NULL;
4397 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)frame;
4398 if (frame->frame_control & __cpu_to_le32(IEEE80211_FCTL_PROTECTED) && (flags & PF_RX)) {
4399 encrypt_frame = (u8 *)frame + IEEE80211_CCMP_256_HDR_LEN;
4400 mgmt = (struct ieee80211_mgmt *)encrypt_frame;
4401 }
4402 FT_MSG_PUT(PF_MGMT, "%s", "action");
4403
4404 if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
4405 u8 *action = (u8 *) &mgmt->u.action.category;
4406 u32 oui = *(u32 *) &action[2];
4407 u8 oui_subtype = action[6] > 8 ? 9 : action[6];
4408 if (action[1] == 0x09 && oui == 0x099A6F50)
4409 FT_MSG_PUT(PF_MGMT, "(%s)", p2p_frame_type[oui_subtype]);
4410 } else if (mgmt->u.action.category == WLAN_CATEGORY_BACK &&
4411 mgmt->u.action.u.addba_req.action_code ==
4412 WLAN_ACTION_ADDBA_REQ) {
4413 FT_MSG_PUT(PF_MGMT, "(ADDBA_REQ-%d)",
4414 mgmt->u.action.u.addba_req.start_seq_num);
4415 } else if (mgmt->u.action.category == WLAN_CATEGORY_BACK &&
4416 mgmt->u.action.u.addba_req.action_code ==
4417 WLAN_ACTION_ADDBA_RESP) {
4418 FT_MSG_PUT(PF_MGMT, "(ADDBA_RESP-%d)",
4419 mgmt->u.action.u.addba_resp.status);
4420 } else if (mgmt->u.action.category == WLAN_CATEGORY_SA_QUERY &&
4421 mgmt->u.action.u.sa_query.action ==
4422 WLAN_ACTION_SA_QUERY_REQUEST) {
4423 FT_MSG_PUT(PF_MGMT, "(SA_Query_Req)");
4424 } else if (mgmt->u.action.category == WLAN_CATEGORY_SA_QUERY &&
4425 mgmt->u.action.u.sa_query.action ==
4426 WLAN_ACTION_SA_QUERY_RESPONSE) {
4427 FT_MSG_PUT(PF_MGMT, "(SA_Query_Resp)");
4428 } else {
4429 FT_MSG_PUT(PF_MGMT, "(%d)", mgmt->u.action.category);
4430 }
4431 goto outprint;
4432 }
4433 /*too much scan results, don't print if no need.*/
4434 FRAME_PARSE(PF_SCAN, probe_req);
4435 FRAME_PARSE(PF_SCAN, probe_resp);
4436 FRAME_PARSE(PF_SCAN, beacon);
4437 /*must be last.*/
4438 FT_MSG_PUT(PF_UNKNWN, "unknown mgmt");
4439
4440 } else if (ieee80211_is_ctl(fctl) && (PF_CTRL & flags)) {
4441
4442 flags &= (~PF_MAC_SN); /*no seq ctrl in ctrl frames.*/
4443 FRAME_PARSE(PF_CTRL, back);
4444 FRAME_PARSE(PF_CTRL, back_req);
4445 FRAME_PARSE(PF_CTRL, ack);
4446 FRAME_PARSE(PF_CTRL, rts);
4447 FRAME_PARSE(PF_CTRL, cts);
4448 FRAME_PARSE(PF_CTRL, pspoll);
4449 /*must be last.*/
4450 FT_MSG_PUT(PF_UNKNWN, "unknown ctrl");
4451 } else {
4452 FT_MSG_PUT(PF_UNKNWN, "unknown mac frame, fctl=0x%04x\n", fctl);
4453 }
4454
4455 outprint:
4456
4457 FT_MSG_PUT(PF_MAC_SN, "-SN=%d(%d)",
4458 (frame->seq_ctrl>>4), (frame->seq_ctrl&0xf));
4459
4460 /*output all msg.*/
4461 if (IS_FRAME_PRINT || IS_PROTO_PRINT) {
4462 u8 *related = NULL;
4463 u8 *own = NULL;
4464 char *r_type = NULL;
4465 char *o_type = NULL;
4466 u8 machdrlen = ieee80211_hdrlen(fctl);
4467 u8 *sa = ieee80211_get_SA(frame);
4468 u8 *da = ieee80211_get_DA(frame);
4469
4470 if (flags & PF_RX) {
4471 related = frame->addr2;
4472 own = frame->addr1;
4473 r_type = "TA";
4474 o_type = "RA";
4475 } else {
4476 related = frame->addr1;
4477 own = frame->addr2;
4478 r_type = "RA";
4479 o_type = "TA";
4480 }
4481
4482 if (machdrlen >= 16) { /*if ACK or BA, don't print.*/
4483 FT_MSG_PUT(PF_MACADDR, "-%02x:%02x:%02x:%02x:%02x:%02x(%s)",
4484 related[0], related[1], related[2],
4485 related[3], related[4], related[5],
4486 r_type);
4487 FT_MSG_PUT(PF_OWNMAC, "-%02x:%02x:%02x:%02x:%02x:%02x(%s)",
4488 own[0], own[1], own[2], own[3], own[4], own[5],
4489 o_type);
4490 FT_MSG_PUT(PF_SA_DA, "-%02x:%02x:%02x:%02x:%02x:%02x(DA)",
4491 da[0], da[1], da[2], da[3], da[4], da[5]);
4492 FT_MSG_PUT(PF_SA_DA, "-%02x:%02x:%02x:%02x:%02x:%02x(SA)",
4493 sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
4494 }
4495
4496 xradio_dbg(XRADIO_DBG_ALWY, "if%d-%s%s--%s\n", if_id,
4497 (PF_RX & flags) ? "RX-" : "TX-", framebuf, protobuf);
4498 }
4499 }
4500
4501 #undef FT_MSG_PUT
4502 #undef PT_MSG_PUT
4503 #undef FRAME_PARSE
4504 #undef FRAME_TYPE
4505
4506 #if DGB_LOG_FILE
4507 u8 log_buffer[DGB_LOG_BUF_LEN];
4508 u16 log_pos;
4509 struct file *fp_log;
4510 atomic_t file_ref = { 0 };
4511
4512 #define T_LABEL_LEN 32
4513 char last_time_label[T_LABEL_LEN] = { 0 };
4514
xradio_logfile(char * buffer,int buf_len,u8 b_time)4515 int xradio_logfile(char *buffer, int buf_len, u8 b_time)
4516 {
4517 int ret = -1;
4518 int size = buf_len;
4519 mm_segment_t old_fs = get_fs();
4520
4521 if (!buffer)
4522 return ret;
4523
4524 if (buf_len < 0)
4525 size = strlen(buffer);
4526 if (!size)
4527 return ret;
4528
4529 if (atomic_add_return(1, &file_ref) == 1) {
4530 fp_log = filp_open(DGB_LOG_PATH0, O_CREAT | O_WRONLY, 0666);
4531 if (IS_ERR(fp_log)) {
4532 printk(KERN_ERR "[XRADIO] ERR, can't open %s(%d).\n",
4533 DGB_LOG_PATH0, (int)fp_log);
4534 goto exit;
4535 }
4536 }
4537 /*printk(KERN_ERR "[XRADIO] file_ref=%d\n", atomic_read(&file_ref));*/
4538
4539 if (fp_log->f_op->write == NULL) {
4540 printk(KERN_ERR "[XRADIO] ERR, %s:File is not allow to write!\n",
4541 __func__);
4542 goto exit;
4543 } else {
4544 set_fs(KERNEL_DS);
4545 if (fp_log->f_op->llseek != NULL) {
4546 vfs_llseek(fp_log, 0, SEEK_END);
4547 } else {
4548 fp_log->f_pos = 0;
4549 }
4550 set_fs(old_fs);
4551 if (b_time) {
4552 struct timespec64 time_now = { 0 };
4553 struct rtc_time tm;
4554 char time_label[T_LABEL_LEN] = { 0 };
4555 xr_do_gettimeofday(&time_now);
4556 time_now.tv_sec -= sys_tz.tz_minuteswest * 60;
4557 rtc_time_to_tm(time_now.tv_sec, &tm);
4558 sprintf(time_label, "\n%d-%02d-%02d_%02d-%02d-%02d\n",
4559 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
4560 tm.tm_hour, tm.tm_min, tm.tm_sec);
4561 if (memcmp(last_time_label, time_label, T_LABEL_LEN)) {
4562 memcpy(last_time_label, time_label, T_LABEL_LEN);
4563 ret = kernel_write(fp_log, time_label, strlen(time_label),
4564 &fp_log->f_pos);
4565 }
4566 }
4567 ret = kernel_write(fp_log, buffer, size, &fp_log->f_pos);
4568 }
4569
4570 exit:
4571 if (atomic_read(&file_ref) == 1) {
4572 if (!IS_ERR(fp_log)) {
4573 filp_close(fp_log, NULL);
4574 fp_log = (struct file *)-ENOENT;
4575 }
4576 }
4577 atomic_sub(1, &file_ref);
4578 return ret;
4579 }
4580 #endif
4581
4582 #if (DGB_XRADIO_HWT)
4583 /***************************for HWT********************************/
4584 struct sk_buff *hwt_skb;
4585 int sent_num;
get_hwt_hif_tx(struct xradio_common * hw_priv,u8 ** data,size_t * tx_len,int * burst,int * vif_selected)4586 int get_hwt_hif_tx(struct xradio_common *hw_priv, u8 **data,
4587 size_t *tx_len, int *burst, int *vif_selected)
4588 {
4589
4590 HWT_PARAMETERS *hwt_tx_hdr = NULL;
4591 if (!hwt_tx_en || !hwt_tx_len || !hwt_tx_num ||
4592 sent_num >= hwt_tx_num) {
4593 if (hwt_skb) {
4594 dev_kfree_skb(hwt_skb);
4595 hwt_skb = NULL;
4596 }
4597 return 0;
4598 }
4599
4600 if (!hwt_skb) {
4601 hwt_skb = xr_alloc_skb(1504);
4602 if (!hwt_skb) {
4603 xradio_dbg(XRADIO_DBG_ERROR, "%s:skb is NULL!\n", __func__);
4604 return 0;
4605 }
4606 if ((unsigned long)hwt_skb->data & 3) {
4607 u8 align = 4 - ((unsigned long)hwt_skb->data & 3);
4608 skb_reserve(hwt_skb, align);
4609 }
4610 skb_put(hwt_skb, 1500);
4611 }
4612 /*fill the header info*/
4613 if (hwt_tx_len < sizeof(HWT_PARAMETERS))
4614 hwt_tx_len = sizeof(HWT_PARAMETERS);
4615 if (hwt_tx_len > 1500)
4616 hwt_tx_len = 1500;
4617 hwt_tx_hdr = (HWT_PARAMETERS *)hwt_skb->data;
4618 hwt_tx_hdr->MsgID = 0x0004;
4619 hwt_tx_hdr->Msglen = hwt_tx_len;
4620 hwt_tx_hdr->TestID = 0x0001;
4621 hwt_tx_hdr->Data = 0x1234;
4622
4623 /*send the packet*/
4624 *data = hwt_skb->data;
4625 *tx_len = hwt_tx_hdr->Msglen;
4626 *vif_selected = 0;
4627 *burst = 2; /*burst > 1 for continuous tx.*/
4628 sent_num++;
4629
4630 /*first packet.*/
4631 if (sent_num == 1) {
4632 xr_do_gettimeofday(&hwt_start_time);
4633 }
4634 /*set confirm*/
4635 hwt_tx_hdr->Params = 0;
4636 if (sent_num >= hwt_tx_num) {
4637 hwt_tx_hdr->Params = 0x101; /*last packet*/
4638 hwt_tx_en = 0; /*disable hwt_tx_en*/
4639 xradio_dbg(XRADIO_DBG_ALWY, "%s:sent last packet!\n", __func__);
4640 } else if (hwt_tx_cfm) {
4641 hwt_tx_hdr->Params = !(sent_num % hwt_tx_cfm);
4642 }
4643
4644 return 1;
4645 }
4646 #endif
4647
4648 #endif /* CONFIG_XRADIO_DEBUGFS */
4649