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\n",
85 ath_txq_unlock(sc
, txq
);
88 retval
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
94 static const struct file_operations fops_node_aggr
= {
95 .read
= read_file_node_aggr
,
98 .llseek
= default_llseek
,
105 void ath_debug_rate_stats(struct ath_softc
*sc
,
106 struct ath_rx_status
*rs
,
109 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*) skb
->data
;
110 struct ath_hw
*ah
= sc
->sc_ah
;
111 struct ieee80211_rx_status
*rxs
;
112 struct ath_rx_rate_stats
*rstats
;
113 struct ieee80211_sta
*sta
;
116 if (!ieee80211_is_data(hdr
->frame_control
))
121 sta
= ieee80211_find_sta_by_ifaddr(sc
->hw
, hdr
->addr2
, NULL
);
125 an
= (struct ath_node
*) sta
->drv_priv
;
126 rstats
= &an
->rx_rate_stats
;
127 rxs
= IEEE80211_SKB_RXCB(skb
);
129 if (IS_HT_RATE(rs
->rs_rate
)) {
130 if (rxs
->rate_idx
>= ARRAY_SIZE(rstats
->ht_stats
))
133 if (rxs
->flag
& RX_FLAG_40MHZ
)
134 rstats
->ht_stats
[rxs
->rate_idx
].ht40_cnt
++;
136 rstats
->ht_stats
[rxs
->rate_idx
].ht20_cnt
++;
138 if (rxs
->flag
& RX_FLAG_SHORT_GI
)
139 rstats
->ht_stats
[rxs
->rate_idx
].sgi_cnt
++;
141 rstats
->ht_stats
[rxs
->rate_idx
].lgi_cnt
++;
146 if (IS_CCK_RATE(rs
->rs_rate
)) {
147 if (rxs
->flag
& RX_FLAG_SHORTPRE
)
148 rstats
->cck_stats
[rxs
->rate_idx
].cck_sp_cnt
++;
150 rstats
->cck_stats
[rxs
->rate_idx
].cck_lp_cnt
++;
155 if (IS_OFDM_RATE(rs
->rs_rate
)) {
156 if (ah
->curchan
->chan
->band
== IEEE80211_BAND_2GHZ
)
157 rstats
->ofdm_stats
[rxs
->rate_idx
- 4].ofdm_cnt
++;
159 rstats
->ofdm_stats
[rxs
->rate_idx
].ofdm_cnt
++;
165 #define PRINT_CCK_RATE(str, i, sp) \
167 len += scnprintf(buf + len, size - len, \
170 (sp) ? rstats->cck_stats[i].cck_sp_cnt : \
171 rstats->cck_stats[i].cck_lp_cnt); \
174 #define PRINT_OFDM_RATE(str, i) \
176 len += scnprintf(buf + len, size - len, \
179 rstats->ofdm_stats[i].ofdm_cnt); \
182 static ssize_t
read_file_node_recv(struct file
*file
, char __user
*user_buf
,
183 size_t count
, loff_t
*ppos
)
185 struct ath_node
*an
= file
->private_data
;
186 struct ath_softc
*sc
= an
->sc
;
187 struct ath_hw
*ah
= sc
->sc_ah
;
188 struct ath_rx_rate_stats
*rstats
;
189 struct ieee80211_sta
*sta
= an
->sta
;
190 enum ieee80211_band band
;
191 u32 len
= 0, size
= 4096;
196 buf
= kzalloc(size
, GFP_KERNEL
);
200 band
= ah
->curchan
->chan
->band
;
201 rstats
= &an
->rx_rate_stats
;
203 if (!sta
->ht_cap
.ht_supported
)
206 len
+= scnprintf(buf
+ len
, size
- len
,
207 "%24s%10s%10s%10s\n",
208 "HT20", "HT40", "SGI", "LGI");
210 for (i
= 0; i
< 24; i
++) {
211 len
+= scnprintf(buf
+ len
, size
- len
,
212 "%8s%3u : %10u%10u%10u%10u\n",
214 rstats
->ht_stats
[i
].ht20_cnt
,
215 rstats
->ht_stats
[i
].ht40_cnt
,
216 rstats
->ht_stats
[i
].sgi_cnt
,
217 rstats
->ht_stats
[i
].lgi_cnt
);
220 len
+= scnprintf(buf
+ len
, size
- len
, "\n");
223 if (band
== IEEE80211_BAND_2GHZ
) {
224 PRINT_CCK_RATE("CCK-1M/LP", 0, false);
225 PRINT_CCK_RATE("CCK-2M/LP", 1, false);
226 PRINT_CCK_RATE("CCK-5.5M/LP", 2, false);
227 PRINT_CCK_RATE("CCK-11M/LP", 3, false);
229 PRINT_CCK_RATE("CCK-2M/SP", 1, true);
230 PRINT_CCK_RATE("CCK-5.5M/SP", 2, true);
231 PRINT_CCK_RATE("CCK-11M/SP", 3, true);
234 PRINT_OFDM_RATE("OFDM-6M", 0);
235 PRINT_OFDM_RATE("OFDM-9M", 1);
236 PRINT_OFDM_RATE("OFDM-12M", 2);
237 PRINT_OFDM_RATE("OFDM-18M", 3);
238 PRINT_OFDM_RATE("OFDM-24M", 4);
239 PRINT_OFDM_RATE("OFDM-36M", 5);
240 PRINT_OFDM_RATE("OFDM-48M", 6);
241 PRINT_OFDM_RATE("OFDM-54M", 7);
243 retval
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
249 #undef PRINT_OFDM_RATE
250 #undef PRINT_CCK_RATE
252 static const struct file_operations fops_node_recv
= {
253 .read
= read_file_node_recv
,
255 .owner
= THIS_MODULE
,
256 .llseek
= default_llseek
,
259 void ath9k_sta_add_debugfs(struct ieee80211_hw
*hw
,
260 struct ieee80211_vif
*vif
,
261 struct ieee80211_sta
*sta
,
264 struct ath_node
*an
= (struct ath_node
*)sta
->drv_priv
;
266 debugfs_create_file("node_aggr", S_IRUGO
, dir
, an
, &fops_node_aggr
);
267 debugfs_create_file("node_recv", S_IRUGO
, dir
, an
, &fops_node_recv
);