2 * Copyright (c) 2013 Qualcomm Atheros, 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.
23 static ssize_t
read_file_node_aggr(struct file
*file
, char __user
*user_buf
,
24 size_t count
, loff_t
*ppos
)
26 struct ath_node
*an
= file
->private_data
;
27 struct ath_softc
*sc
= an
->sc
;
28 struct ath_atx_tid
*tid
;
29 struct ath_atx_ac
*ac
;
31 u32 len
= 0, size
= 4096;
36 buf
= kzalloc(size
, GFP_KERNEL
);
40 if (!an
->sta
->ht_cap
.ht_supported
) {
41 len
= scnprintf(buf
, size
, "%s\n",
46 len
= scnprintf(buf
, size
, "Max-AMPDU: %d\n",
48 len
+= scnprintf(buf
+ len
, size
- len
, "MPDU Density: %d\n\n",
51 len
+= scnprintf(buf
+ len
, size
- len
,
52 "%2s%7s\n", "AC", "SCHED");
54 for (acno
= 0, ac
= &an
->ac
[acno
];
55 acno
< IEEE80211_NUM_ACS
; acno
++, ac
++) {
57 ath_txq_lock(sc
, txq
);
58 len
+= scnprintf(buf
+ len
, size
- len
,
61 ath_txq_unlock(sc
, txq
);
64 len
+= scnprintf(buf
+ len
, size
- len
,
65 "\n%3s%11s%10s%10s%10s%10s%9s%6s%8s\n",
66 "TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE",
67 "BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED");
69 for (tidno
= 0, tid
= &an
->tid
[tidno
];
70 tidno
< IEEE80211_NUM_TIDS
; tidno
++, tid
++) {
72 ath_txq_lock(sc
, txq
);
74 len
+= scnprintf(buf
+ len
, size
- len
,
75 "%3d%11d%10d%10d%10d%10d%9d%6d%8d\n",
86 ath_txq_unlock(sc
, txq
);
89 retval
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
95 static const struct file_operations fops_node_aggr
= {
96 .read
= read_file_node_aggr
,
99 .llseek
= default_llseek
,
106 void ath_debug_rate_stats(struct ath_softc
*sc
,
107 struct ath_rx_status
*rs
,
110 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*) skb
->data
;
111 struct ath_hw
*ah
= sc
->sc_ah
;
112 struct ieee80211_rx_status
*rxs
;
113 struct ath_rx_rate_stats
*rstats
;
114 struct ieee80211_sta
*sta
;
117 if (!ieee80211_is_data(hdr
->frame_control
))
122 sta
= ieee80211_find_sta_by_ifaddr(sc
->hw
, hdr
->addr2
, NULL
);
126 an
= (struct ath_node
*) sta
->drv_priv
;
127 rstats
= &an
->rx_rate_stats
;
128 rxs
= IEEE80211_SKB_RXCB(skb
);
130 if (IS_HT_RATE(rs
->rs_rate
)) {
131 if (rxs
->rate_idx
>= ARRAY_SIZE(rstats
->ht_stats
))
134 if (rxs
->flag
& RX_FLAG_40MHZ
)
135 rstats
->ht_stats
[rxs
->rate_idx
].ht40_cnt
++;
137 rstats
->ht_stats
[rxs
->rate_idx
].ht20_cnt
++;
139 if (rxs
->flag
& RX_FLAG_SHORT_GI
)
140 rstats
->ht_stats
[rxs
->rate_idx
].sgi_cnt
++;
142 rstats
->ht_stats
[rxs
->rate_idx
].lgi_cnt
++;
147 if (IS_CCK_RATE(rs
->rs_rate
)) {
148 if (rxs
->flag
& RX_FLAG_SHORTPRE
)
149 rstats
->cck_stats
[rxs
->rate_idx
].cck_sp_cnt
++;
151 rstats
->cck_stats
[rxs
->rate_idx
].cck_lp_cnt
++;
156 if (IS_OFDM_RATE(rs
->rs_rate
)) {
157 if (ah
->curchan
->chan
->band
== IEEE80211_BAND_2GHZ
)
158 rstats
->ofdm_stats
[rxs
->rate_idx
- 4].ofdm_cnt
++;
160 rstats
->ofdm_stats
[rxs
->rate_idx
].ofdm_cnt
++;
166 #define PRINT_CCK_RATE(str, i, sp) \
168 len += scnprintf(buf + len, size - len, \
171 (sp) ? rstats->cck_stats[i].cck_sp_cnt : \
172 rstats->cck_stats[i].cck_lp_cnt); \
175 #define PRINT_OFDM_RATE(str, i) \
177 len += scnprintf(buf + len, size - len, \
180 rstats->ofdm_stats[i].ofdm_cnt); \
183 static ssize_t
read_file_node_recv(struct file
*file
, char __user
*user_buf
,
184 size_t count
, loff_t
*ppos
)
186 struct ath_node
*an
= file
->private_data
;
187 struct ath_softc
*sc
= an
->sc
;
188 struct ath_hw
*ah
= sc
->sc_ah
;
189 struct ath_rx_rate_stats
*rstats
;
190 struct ieee80211_sta
*sta
= an
->sta
;
191 enum ieee80211_band band
;
192 u32 len
= 0, size
= 4096;
197 buf
= kzalloc(size
, GFP_KERNEL
);
201 band
= ah
->curchan
->chan
->band
;
202 rstats
= &an
->rx_rate_stats
;
204 if (!sta
->ht_cap
.ht_supported
)
207 len
+= scnprintf(buf
+ len
, size
- len
,
208 "%24s%10s%10s%10s\n",
209 "HT20", "HT40", "SGI", "LGI");
211 for (i
= 0; i
< 24; i
++) {
212 len
+= scnprintf(buf
+ len
, size
- len
,
213 "%8s%3u : %10u%10u%10u%10u\n",
215 rstats
->ht_stats
[i
].ht20_cnt
,
216 rstats
->ht_stats
[i
].ht40_cnt
,
217 rstats
->ht_stats
[i
].sgi_cnt
,
218 rstats
->ht_stats
[i
].lgi_cnt
);
221 len
+= scnprintf(buf
+ len
, size
- len
, "\n");
224 if (band
== IEEE80211_BAND_2GHZ
) {
225 PRINT_CCK_RATE("CCK-1M/LP", 0, false);
226 PRINT_CCK_RATE("CCK-2M/LP", 1, false);
227 PRINT_CCK_RATE("CCK-5.5M/LP", 2, false);
228 PRINT_CCK_RATE("CCK-11M/LP", 3, false);
230 PRINT_CCK_RATE("CCK-2M/SP", 1, true);
231 PRINT_CCK_RATE("CCK-5.5M/SP", 2, true);
232 PRINT_CCK_RATE("CCK-11M/SP", 3, true);
235 PRINT_OFDM_RATE("OFDM-6M", 0);
236 PRINT_OFDM_RATE("OFDM-9M", 1);
237 PRINT_OFDM_RATE("OFDM-12M", 2);
238 PRINT_OFDM_RATE("OFDM-18M", 3);
239 PRINT_OFDM_RATE("OFDM-24M", 4);
240 PRINT_OFDM_RATE("OFDM-36M", 5);
241 PRINT_OFDM_RATE("OFDM-48M", 6);
242 PRINT_OFDM_RATE("OFDM-54M", 7);
244 retval
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
250 #undef PRINT_OFDM_RATE
251 #undef PRINT_CCK_RATE
253 static const struct file_operations fops_node_recv
= {
254 .read
= read_file_node_recv
,
256 .owner
= THIS_MODULE
,
257 .llseek
= default_llseek
,
260 void ath9k_sta_add_debugfs(struct ieee80211_hw
*hw
,
261 struct ieee80211_vif
*vif
,
262 struct ieee80211_sta
*sta
,
265 struct ath_node
*an
= (struct ath_node
*)sta
->drv_priv
;
267 debugfs_create_file("node_aggr", S_IRUGO
, dir
, an
, &fops_node_aggr
);
268 debugfs_create_file("node_recv", S_IRUGO
, dir
, an
, &fops_node_recv
);