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
;
30 u32 len
= 0, size
= 4096;
35 buf
= kzalloc(size
, GFP_KERNEL
);
39 if (!an
->sta
->ht_cap
.ht_supported
) {
40 len
= scnprintf(buf
, size
, "%s\n",
45 len
= scnprintf(buf
, size
, "Max-AMPDU: %d\n",
47 len
+= scnprintf(buf
+ len
, size
- len
, "MPDU Density: %d\n\n",
50 len
+= scnprintf(buf
+ len
, size
- len
,
51 "\n%3s%11s%10s%10s%10s%10s%9s%6s%8s\n",
52 "TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE",
53 "BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED");
55 for (tidno
= 0; tidno
< IEEE80211_NUM_TIDS
; tidno
++) {
56 tid
= ath_node_to_tid(an
, tidno
);
58 ath_txq_lock(sc
, txq
);
60 len
+= scnprintf(buf
+ len
, size
- len
,
61 "%3d%11d%10d%10d%10d%10d%9d%6d\n",
69 !list_empty(&tid
->list
));
71 ath_txq_unlock(sc
, txq
);
74 retval
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
80 static const struct file_operations fops_node_aggr
= {
81 .read
= read_file_node_aggr
,
84 .llseek
= default_llseek
,
91 void ath_debug_rate_stats(struct ath_softc
*sc
,
92 struct ath_rx_status
*rs
,
95 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*) skb
->data
;
96 struct ath_hw
*ah
= sc
->sc_ah
;
97 struct ieee80211_rx_status
*rxs
;
98 struct ath_rx_rate_stats
*rstats
;
99 struct ieee80211_sta
*sta
;
102 if (!ieee80211_is_data(hdr
->frame_control
))
107 sta
= ieee80211_find_sta_by_ifaddr(sc
->hw
, hdr
->addr2
, NULL
);
111 an
= (struct ath_node
*) sta
->drv_priv
;
112 rstats
= &an
->rx_rate_stats
;
113 rxs
= IEEE80211_SKB_RXCB(skb
);
115 if (IS_HT_RATE(rs
->rs_rate
)) {
116 if (rxs
->rate_idx
>= ARRAY_SIZE(rstats
->ht_stats
))
119 if (rxs
->bw
== RATE_INFO_BW_40
)
120 rstats
->ht_stats
[rxs
->rate_idx
].ht40_cnt
++;
122 rstats
->ht_stats
[rxs
->rate_idx
].ht20_cnt
++;
124 if (rxs
->enc_flags
& RX_ENC_FLAG_SHORT_GI
)
125 rstats
->ht_stats
[rxs
->rate_idx
].sgi_cnt
++;
127 rstats
->ht_stats
[rxs
->rate_idx
].lgi_cnt
++;
132 if (IS_CCK_RATE(rs
->rs_rate
)) {
133 if (rxs
->enc_flags
& RX_ENC_FLAG_SHORTPRE
)
134 rstats
->cck_stats
[rxs
->rate_idx
].cck_sp_cnt
++;
136 rstats
->cck_stats
[rxs
->rate_idx
].cck_lp_cnt
++;
141 if (IS_OFDM_RATE(rs
->rs_rate
)) {
142 if (ah
->curchan
->chan
->band
== NL80211_BAND_2GHZ
)
143 rstats
->ofdm_stats
[rxs
->rate_idx
- 4].ofdm_cnt
++;
145 rstats
->ofdm_stats
[rxs
->rate_idx
].ofdm_cnt
++;
151 #define PRINT_CCK_RATE(str, i, sp) \
153 len += scnprintf(buf + len, size - len, \
156 (sp) ? rstats->cck_stats[i].cck_sp_cnt : \
157 rstats->cck_stats[i].cck_lp_cnt); \
160 #define PRINT_OFDM_RATE(str, i) \
162 len += scnprintf(buf + len, size - len, \
165 rstats->ofdm_stats[i].ofdm_cnt); \
168 static ssize_t
read_file_node_recv(struct file
*file
, char __user
*user_buf
,
169 size_t count
, loff_t
*ppos
)
171 struct ath_node
*an
= file
->private_data
;
172 struct ath_softc
*sc
= an
->sc
;
173 struct ath_hw
*ah
= sc
->sc_ah
;
174 struct ath_rx_rate_stats
*rstats
;
175 struct ieee80211_sta
*sta
= an
->sta
;
176 enum nl80211_band band
;
177 u32 len
= 0, size
= 4096;
182 buf
= kzalloc(size
, GFP_KERNEL
);
186 band
= ah
->curchan
->chan
->band
;
187 rstats
= &an
->rx_rate_stats
;
189 if (!sta
->ht_cap
.ht_supported
)
192 len
+= scnprintf(buf
+ len
, size
- len
,
193 "%24s%10s%10s%10s\n",
194 "HT20", "HT40", "SGI", "LGI");
196 for (i
= 0; i
< 24; i
++) {
197 len
+= scnprintf(buf
+ len
, size
- len
,
198 "%8s%3u : %10u%10u%10u%10u\n",
200 rstats
->ht_stats
[i
].ht20_cnt
,
201 rstats
->ht_stats
[i
].ht40_cnt
,
202 rstats
->ht_stats
[i
].sgi_cnt
,
203 rstats
->ht_stats
[i
].lgi_cnt
);
206 len
+= scnprintf(buf
+ len
, size
- len
, "\n");
209 if (band
== NL80211_BAND_2GHZ
) {
210 PRINT_CCK_RATE("CCK-1M/LP", 0, false);
211 PRINT_CCK_RATE("CCK-2M/LP", 1, false);
212 PRINT_CCK_RATE("CCK-5.5M/LP", 2, false);
213 PRINT_CCK_RATE("CCK-11M/LP", 3, false);
215 PRINT_CCK_RATE("CCK-2M/SP", 1, true);
216 PRINT_CCK_RATE("CCK-5.5M/SP", 2, true);
217 PRINT_CCK_RATE("CCK-11M/SP", 3, true);
220 PRINT_OFDM_RATE("OFDM-6M", 0);
221 PRINT_OFDM_RATE("OFDM-9M", 1);
222 PRINT_OFDM_RATE("OFDM-12M", 2);
223 PRINT_OFDM_RATE("OFDM-18M", 3);
224 PRINT_OFDM_RATE("OFDM-24M", 4);
225 PRINT_OFDM_RATE("OFDM-36M", 5);
226 PRINT_OFDM_RATE("OFDM-48M", 6);
227 PRINT_OFDM_RATE("OFDM-54M", 7);
229 retval
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
235 #undef PRINT_OFDM_RATE
236 #undef PRINT_CCK_RATE
238 static const struct file_operations fops_node_recv
= {
239 .read
= read_file_node_recv
,
241 .owner
= THIS_MODULE
,
242 .llseek
= default_llseek
,
245 void ath9k_sta_add_debugfs(struct ieee80211_hw
*hw
,
246 struct ieee80211_vif
*vif
,
247 struct ieee80211_sta
*sta
,
250 struct ath_node
*an
= (struct ath_node
*)sta
->drv_priv
;
252 debugfs_create_file("node_aggr", 0444, dir
, an
, &fops_node_aggr
);
253 debugfs_create_file("node_recv", 0444, dir
, an
, &fops_node_recv
);