2 * Copyright (c) 2010-2011 Atheros Communications Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 static ssize_t
read_file_tgt_int_stats(struct file
*file
, char __user
*user_buf
,
20 size_t count
, loff_t
*ppos
)
22 struct ath9k_htc_priv
*priv
= file
->private_data
;
23 struct ath9k_htc_target_int_stats cmd_rsp
;
28 memset(&cmd_rsp
, 0, sizeof(cmd_rsp
));
30 ath9k_htc_ps_wakeup(priv
);
32 WMI_CMD(WMI_INT_STATS_CMDID
);
34 ath9k_htc_ps_restore(priv
);
38 ath9k_htc_ps_restore(priv
);
40 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
41 "%20s : %10u\n", "RX",
42 be32_to_cpu(cmd_rsp
.rx
));
44 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
45 "%20s : %10u\n", "RXORN",
46 be32_to_cpu(cmd_rsp
.rxorn
));
48 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
49 "%20s : %10u\n", "RXEOL",
50 be32_to_cpu(cmd_rsp
.rxeol
));
52 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
53 "%20s : %10u\n", "TXURN",
54 be32_to_cpu(cmd_rsp
.txurn
));
56 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
57 "%20s : %10u\n", "TXTO",
58 be32_to_cpu(cmd_rsp
.txto
));
60 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
61 "%20s : %10u\n", "CST",
62 be32_to_cpu(cmd_rsp
.cst
));
64 if (len
> sizeof(buf
))
67 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
70 static const struct file_operations fops_tgt_int_stats
= {
71 .read
= read_file_tgt_int_stats
,
74 .llseek
= default_llseek
,
77 static ssize_t
read_file_tgt_tx_stats(struct file
*file
, char __user
*user_buf
,
78 size_t count
, loff_t
*ppos
)
80 struct ath9k_htc_priv
*priv
= file
->private_data
;
81 struct ath9k_htc_target_tx_stats cmd_rsp
;
86 memset(&cmd_rsp
, 0, sizeof(cmd_rsp
));
88 ath9k_htc_ps_wakeup(priv
);
90 WMI_CMD(WMI_TX_STATS_CMDID
);
92 ath9k_htc_ps_restore(priv
);
96 ath9k_htc_ps_restore(priv
);
98 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
99 "%20s : %10u\n", "Xretries",
100 be32_to_cpu(cmd_rsp
.xretries
));
102 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
103 "%20s : %10u\n", "FifoErr",
104 be32_to_cpu(cmd_rsp
.fifoerr
));
106 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
107 "%20s : %10u\n", "Filtered",
108 be32_to_cpu(cmd_rsp
.filtered
));
110 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
111 "%20s : %10u\n", "TimerExp",
112 be32_to_cpu(cmd_rsp
.timer_exp
));
114 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
115 "%20s : %10u\n", "ShortRetries",
116 be32_to_cpu(cmd_rsp
.shortretries
));
118 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
119 "%20s : %10u\n", "LongRetries",
120 be32_to_cpu(cmd_rsp
.longretries
));
122 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
123 "%20s : %10u\n", "QueueNull",
124 be32_to_cpu(cmd_rsp
.qnull
));
126 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
127 "%20s : %10u\n", "EncapFail",
128 be32_to_cpu(cmd_rsp
.encap_fail
));
130 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
131 "%20s : %10u\n", "NoBuf",
132 be32_to_cpu(cmd_rsp
.nobuf
));
134 if (len
> sizeof(buf
))
137 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
140 static const struct file_operations fops_tgt_tx_stats
= {
141 .read
= read_file_tgt_tx_stats
,
143 .owner
= THIS_MODULE
,
144 .llseek
= default_llseek
,
147 static ssize_t
read_file_tgt_rx_stats(struct file
*file
, char __user
*user_buf
,
148 size_t count
, loff_t
*ppos
)
150 struct ath9k_htc_priv
*priv
= file
->private_data
;
151 struct ath9k_htc_target_rx_stats cmd_rsp
;
153 unsigned int len
= 0;
156 memset(&cmd_rsp
, 0, sizeof(cmd_rsp
));
158 ath9k_htc_ps_wakeup(priv
);
160 WMI_CMD(WMI_RX_STATS_CMDID
);
162 ath9k_htc_ps_restore(priv
);
166 ath9k_htc_ps_restore(priv
);
168 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
169 "%20s : %10u\n", "NoBuf",
170 be32_to_cpu(cmd_rsp
.nobuf
));
172 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
173 "%20s : %10u\n", "HostSend",
174 be32_to_cpu(cmd_rsp
.host_send
));
176 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
177 "%20s : %10u\n", "HostDone",
178 be32_to_cpu(cmd_rsp
.host_done
));
180 if (len
> sizeof(buf
))
183 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
186 static const struct file_operations fops_tgt_rx_stats
= {
187 .read
= read_file_tgt_rx_stats
,
189 .owner
= THIS_MODULE
,
190 .llseek
= default_llseek
,
193 static ssize_t
read_file_xmit(struct file
*file
, char __user
*user_buf
,
194 size_t count
, loff_t
*ppos
)
196 struct ath9k_htc_priv
*priv
= file
->private_data
;
198 unsigned int len
= 0;
200 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
201 "%20s : %10u\n", "Buffers queued",
202 priv
->debug
.tx_stats
.buf_queued
);
203 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
204 "%20s : %10u\n", "Buffers completed",
205 priv
->debug
.tx_stats
.buf_completed
);
206 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
207 "%20s : %10u\n", "SKBs queued",
208 priv
->debug
.tx_stats
.skb_queued
);
209 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
210 "%20s : %10u\n", "SKBs success",
211 priv
->debug
.tx_stats
.skb_success
);
212 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
213 "%20s : %10u\n", "SKBs failed",
214 priv
->debug
.tx_stats
.skb_failed
);
215 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
216 "%20s : %10u\n", "CAB queued",
217 priv
->debug
.tx_stats
.cab_queued
);
219 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
220 "%20s : %10u\n", "BE queued",
221 priv
->debug
.tx_stats
.queue_stats
[IEEE80211_AC_BE
]);
222 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
223 "%20s : %10u\n", "BK queued",
224 priv
->debug
.tx_stats
.queue_stats
[IEEE80211_AC_BK
]);
225 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
226 "%20s : %10u\n", "VI queued",
227 priv
->debug
.tx_stats
.queue_stats
[IEEE80211_AC_VI
]);
228 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
229 "%20s : %10u\n", "VO queued",
230 priv
->debug
.tx_stats
.queue_stats
[IEEE80211_AC_VO
]);
232 if (len
> sizeof(buf
))
235 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
238 static const struct file_operations fops_xmit
= {
239 .read
= read_file_xmit
,
241 .owner
= THIS_MODULE
,
242 .llseek
= default_llseek
,
245 void ath9k_htc_err_stat_rx(struct ath9k_htc_priv
*priv
,
246 struct ath_rx_status
*rs
)
248 ath9k_cmn_debug_stat_rx(&priv
->debug
.rx_stats
, rs
);
251 static ssize_t
read_file_skb_rx(struct file
*file
, char __user
*user_buf
,
252 size_t count
, loff_t
*ppos
)
254 struct ath9k_htc_priv
*priv
= file
->private_data
;
256 unsigned int len
= 0, size
= 1500;
259 buf
= kzalloc(size
, GFP_KERNEL
);
263 len
+= scnprintf(buf
+ len
, size
- len
,
264 "%20s : %10u\n", "SKBs allocated",
265 priv
->debug
.skbrx_stats
.skb_allocated
);
266 len
+= scnprintf(buf
+ len
, size
- len
,
267 "%20s : %10u\n", "SKBs completed",
268 priv
->debug
.skbrx_stats
.skb_completed
);
269 len
+= scnprintf(buf
+ len
, size
- len
,
270 "%20s : %10u\n", "SKBs Dropped",
271 priv
->debug
.skbrx_stats
.skb_dropped
);
276 retval
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
282 static const struct file_operations fops_skb_rx
= {
283 .read
= read_file_skb_rx
,
285 .owner
= THIS_MODULE
,
286 .llseek
= default_llseek
,
289 static ssize_t
read_file_slot(struct file
*file
, char __user
*user_buf
,
290 size_t count
, loff_t
*ppos
)
292 struct ath9k_htc_priv
*priv
= file
->private_data
;
296 spin_lock_bh(&priv
->tx
.tx_lock
);
297 len
= scnprintf(buf
, sizeof(buf
),
298 "TX slot bitmap : %*pb\n"
300 MAX_TX_BUF_NUM
, priv
->tx
.tx_slot
,
301 bitmap_weight(priv
->tx
.tx_slot
, MAX_TX_BUF_NUM
));
302 spin_unlock_bh(&priv
->tx
.tx_lock
);
303 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
306 static const struct file_operations fops_slot
= {
307 .read
= read_file_slot
,
309 .owner
= THIS_MODULE
,
310 .llseek
= default_llseek
,
313 static ssize_t
read_file_queue(struct file
*file
, char __user
*user_buf
,
314 size_t count
, loff_t
*ppos
)
316 struct ath9k_htc_priv
*priv
= file
->private_data
;
318 unsigned int len
= 0;
320 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
, "%20s : %10u\n",
321 "Mgmt endpoint", skb_queue_len(&priv
->tx
.mgmt_ep_queue
));
323 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
, "%20s : %10u\n",
324 "Cab endpoint", skb_queue_len(&priv
->tx
.cab_ep_queue
));
326 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
, "%20s : %10u\n",
327 "Data BE endpoint", skb_queue_len(&priv
->tx
.data_be_queue
));
329 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
, "%20s : %10u\n",
330 "Data BK endpoint", skb_queue_len(&priv
->tx
.data_bk_queue
));
332 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
, "%20s : %10u\n",
333 "Data VI endpoint", skb_queue_len(&priv
->tx
.data_vi_queue
));
335 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
, "%20s : %10u\n",
336 "Data VO endpoint", skb_queue_len(&priv
->tx
.data_vo_queue
));
338 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
, "%20s : %10u\n",
339 "Failed queue", skb_queue_len(&priv
->tx
.tx_failed
));
341 spin_lock_bh(&priv
->tx
.tx_lock
);
342 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
, "%20s : %10u\n",
343 "Queued count", priv
->tx
.queued_cnt
);
344 spin_unlock_bh(&priv
->tx
.tx_lock
);
346 if (len
> sizeof(buf
))
349 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
353 static const struct file_operations fops_queue
= {
354 .read
= read_file_queue
,
356 .owner
= THIS_MODULE
,
357 .llseek
= default_llseek
,
360 static ssize_t
read_file_debug(struct file
*file
, char __user
*user_buf
,
361 size_t count
, loff_t
*ppos
)
363 struct ath9k_htc_priv
*priv
= file
->private_data
;
364 struct ath_common
*common
= ath9k_hw_common(priv
->ah
);
368 len
= sprintf(buf
, "0x%08x\n", common
->debug_mask
);
369 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
372 static ssize_t
write_file_debug(struct file
*file
, const char __user
*user_buf
,
373 size_t count
, loff_t
*ppos
)
375 struct ath9k_htc_priv
*priv
= file
->private_data
;
376 struct ath_common
*common
= ath9k_hw_common(priv
->ah
);
381 len
= min(count
, sizeof(buf
) - 1);
382 if (copy_from_user(buf
, user_buf
, len
))
386 if (kstrtoul(buf
, 0, &mask
))
389 common
->debug_mask
= mask
;
393 static const struct file_operations fops_debug
= {
394 .read
= read_file_debug
,
395 .write
= write_file_debug
,
397 .owner
= THIS_MODULE
,
398 .llseek
= default_llseek
,
401 /* Ethtool support for get-stats */
402 #define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO"
403 static const char ath9k_htc_gstrings_stats
[][ETH_GSTRING_LEN
] = {
412 "d_rx_decrypt_crc_err",
415 "d_rx_pre_delim_crc_err",
416 "d_rx_post_delim_crc_err",
417 "d_rx_decrypt_busy_err",
420 "d_rx_phyerr_ofdm_timing",
421 "d_rx_phyerr_cck_timing",
424 #define ATH9K_HTC_SSTATS_LEN ARRAY_SIZE(ath9k_htc_gstrings_stats)
426 void ath9k_htc_get_et_strings(struct ieee80211_hw
*hw
,
427 struct ieee80211_vif
*vif
,
430 if (sset
== ETH_SS_STATS
)
431 memcpy(data
, *ath9k_htc_gstrings_stats
,
432 sizeof(ath9k_htc_gstrings_stats
));
435 int ath9k_htc_get_et_sset_count(struct ieee80211_hw
*hw
,
436 struct ieee80211_vif
*vif
, int sset
)
438 if (sset
== ETH_SS_STATS
)
439 return ATH9K_HTC_SSTATS_LEN
;
443 #define STXBASE priv->debug.tx_stats
444 #define SRXBASE priv->debug.rx_stats
445 #define SKBTXBASE priv->debug.tx_stats
446 #define SKBRXBASE priv->debug.skbrx_stats
448 data[i++] = STXBASE.a[IEEE80211_AC_BE]; \
449 data[i++] = STXBASE.a[IEEE80211_AC_BK]; \
450 data[i++] = STXBASE.a[IEEE80211_AC_VI]; \
451 data[i++] = STXBASE.a[IEEE80211_AC_VO]
453 void ath9k_htc_get_et_stats(struct ieee80211_hw
*hw
,
454 struct ieee80211_vif
*vif
,
455 struct ethtool_stats
*stats
, u64
*data
)
457 struct ath9k_htc_priv
*priv
= hw
->priv
;
460 data
[i
++] = SKBTXBASE
.skb_success
;
461 data
[i
++] = SKBTXBASE
.skb_success_bytes
;
462 data
[i
++] = SKBRXBASE
.skb_completed
;
463 data
[i
++] = SKBRXBASE
.skb_completed_bytes
;
467 data
[i
++] = SRXBASE
.crc_err
;
468 data
[i
++] = SRXBASE
.decrypt_crc_err
;
469 data
[i
++] = SRXBASE
.phy_err
;
470 data
[i
++] = SRXBASE
.mic_err
;
471 data
[i
++] = SRXBASE
.pre_delim_crc_err
;
472 data
[i
++] = SRXBASE
.post_delim_crc_err
;
473 data
[i
++] = SRXBASE
.decrypt_busy_err
;
475 data
[i
++] = SRXBASE
.phy_err_stats
[ATH9K_PHYERR_RADAR
];
476 data
[i
++] = SRXBASE
.phy_err_stats
[ATH9K_PHYERR_OFDM_TIMING
];
477 data
[i
++] = SRXBASE
.phy_err_stats
[ATH9K_PHYERR_CCK_TIMING
];
479 WARN_ON(i
!= ATH9K_HTC_SSTATS_LEN
);
482 void ath9k_htc_deinit_debug(struct ath9k_htc_priv
*priv
)
484 ath9k_cmn_spectral_deinit_debug(&priv
->spec_priv
);
487 int ath9k_htc_init_debug(struct ath_hw
*ah
)
489 struct ath_common
*common
= ath9k_hw_common(ah
);
490 struct ath9k_htc_priv
*priv
= (struct ath9k_htc_priv
*) common
->priv
;
492 priv
->debug
.debugfs_phy
= debugfs_create_dir(KBUILD_MODNAME
,
493 priv
->hw
->wiphy
->debugfsdir
);
494 if (!priv
->debug
.debugfs_phy
)
497 ath9k_cmn_spectral_init_debug(&priv
->spec_priv
, priv
->debug
.debugfs_phy
);
499 debugfs_create_file("tgt_int_stats", 0400, priv
->debug
.debugfs_phy
,
500 priv
, &fops_tgt_int_stats
);
501 debugfs_create_file("tgt_tx_stats", 0400, priv
->debug
.debugfs_phy
,
502 priv
, &fops_tgt_tx_stats
);
503 debugfs_create_file("tgt_rx_stats", 0400, priv
->debug
.debugfs_phy
,
504 priv
, &fops_tgt_rx_stats
);
505 debugfs_create_file("xmit", 0400, priv
->debug
.debugfs_phy
,
507 debugfs_create_file("skb_rx", 0400, priv
->debug
.debugfs_phy
,
510 ath9k_cmn_debug_recv(priv
->debug
.debugfs_phy
, &priv
->debug
.rx_stats
);
511 ath9k_cmn_debug_phy_err(priv
->debug
.debugfs_phy
, &priv
->debug
.rx_stats
);
513 debugfs_create_file("slot", 0400, priv
->debug
.debugfs_phy
,
515 debugfs_create_file("queue", 0400, priv
->debug
.debugfs_phy
,
517 debugfs_create_file("debug", 0600, priv
->debug
.debugfs_phy
,
520 ath9k_cmn_debug_base_eeprom(priv
->debug
.debugfs_phy
, priv
->ah
);
521 ath9k_cmn_debug_modal_eeprom(priv
->debug
.debugfs_phy
, priv
->ah
);