diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/htc_drv_debug.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 505 |
1 files changed, 505 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c new file mode 100644 index 00000000000..eca777497fe --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c | |||
@@ -0,0 +1,505 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010-2011 Atheros Communications Inc. | ||
3 | * | ||
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. | ||
7 | * | ||
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. | ||
15 | */ | ||
16 | |||
17 | #include "htc.h" | ||
18 | |||
19 | static int ath9k_debugfs_open(struct inode *inode, struct file *file) | ||
20 | { | ||
21 | file->private_data = inode->i_private; | ||
22 | return 0; | ||
23 | } | ||
24 | |||
25 | static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf, | ||
26 | size_t count, loff_t *ppos) | ||
27 | { | ||
28 | struct ath9k_htc_priv *priv = file->private_data; | ||
29 | struct ath9k_htc_target_int_stats cmd_rsp; | ||
30 | char buf[512]; | ||
31 | unsigned int len = 0; | ||
32 | int ret = 0; | ||
33 | |||
34 | memset(&cmd_rsp, 0, sizeof(cmd_rsp)); | ||
35 | |||
36 | WMI_CMD(WMI_INT_STATS_CMDID); | ||
37 | if (ret) | ||
38 | return -EINVAL; | ||
39 | |||
40 | len += snprintf(buf + len, sizeof(buf) - len, | ||
41 | "%20s : %10u\n", "RX", | ||
42 | be32_to_cpu(cmd_rsp.rx)); | ||
43 | |||
44 | len += snprintf(buf + len, sizeof(buf) - len, | ||
45 | "%20s : %10u\n", "RXORN", | ||
46 | be32_to_cpu(cmd_rsp.rxorn)); | ||
47 | |||
48 | len += snprintf(buf + len, sizeof(buf) - len, | ||
49 | "%20s : %10u\n", "RXEOL", | ||
50 | be32_to_cpu(cmd_rsp.rxeol)); | ||
51 | |||
52 | len += snprintf(buf + len, sizeof(buf) - len, | ||
53 | "%20s : %10u\n", "TXURN", | ||
54 | be32_to_cpu(cmd_rsp.txurn)); | ||
55 | |||
56 | len += snprintf(buf + len, sizeof(buf) - len, | ||
57 | "%20s : %10u\n", "TXTO", | ||
58 | be32_to_cpu(cmd_rsp.txto)); | ||
59 | |||
60 | len += snprintf(buf + len, sizeof(buf) - len, | ||
61 | "%20s : %10u\n", "CST", | ||
62 | be32_to_cpu(cmd_rsp.cst)); | ||
63 | |||
64 | if (len > sizeof(buf)) | ||
65 | len = sizeof(buf); | ||
66 | |||
67 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
68 | } | ||
69 | |||
70 | static const struct file_operations fops_tgt_int_stats = { | ||
71 | .read = read_file_tgt_int_stats, | ||
72 | .open = ath9k_debugfs_open, | ||
73 | .owner = THIS_MODULE, | ||
74 | .llseek = default_llseek, | ||
75 | }; | ||
76 | |||
77 | static ssize_t read_file_tgt_tx_stats(struct file *file, char __user *user_buf, | ||
78 | size_t count, loff_t *ppos) | ||
79 | { | ||
80 | struct ath9k_htc_priv *priv = file->private_data; | ||
81 | struct ath9k_htc_target_tx_stats cmd_rsp; | ||
82 | char buf[512]; | ||
83 | unsigned int len = 0; | ||
84 | int ret = 0; | ||
85 | |||
86 | memset(&cmd_rsp, 0, sizeof(cmd_rsp)); | ||
87 | |||
88 | WMI_CMD(WMI_TX_STATS_CMDID); | ||
89 | if (ret) | ||
90 | return -EINVAL; | ||
91 | |||
92 | len += snprintf(buf + len, sizeof(buf) - len, | ||
93 | "%20s : %10u\n", "Xretries", | ||
94 | be32_to_cpu(cmd_rsp.xretries)); | ||
95 | |||
96 | len += snprintf(buf + len, sizeof(buf) - len, | ||
97 | "%20s : %10u\n", "FifoErr", | ||
98 | be32_to_cpu(cmd_rsp.fifoerr)); | ||
99 | |||
100 | len += snprintf(buf + len, sizeof(buf) - len, | ||
101 | "%20s : %10u\n", "Filtered", | ||
102 | be32_to_cpu(cmd_rsp.filtered)); | ||
103 | |||
104 | len += snprintf(buf + len, sizeof(buf) - len, | ||
105 | "%20s : %10u\n", "TimerExp", | ||
106 | be32_to_cpu(cmd_rsp.timer_exp)); | ||
107 | |||
108 | len += snprintf(buf + len, sizeof(buf) - len, | ||
109 | "%20s : %10u\n", "ShortRetries", | ||
110 | be32_to_cpu(cmd_rsp.shortretries)); | ||
111 | |||
112 | len += snprintf(buf + len, sizeof(buf) - len, | ||
113 | "%20s : %10u\n", "LongRetries", | ||
114 | be32_to_cpu(cmd_rsp.longretries)); | ||
115 | |||
116 | len += snprintf(buf + len, sizeof(buf) - len, | ||
117 | "%20s : %10u\n", "QueueNull", | ||
118 | be32_to_cpu(cmd_rsp.qnull)); | ||
119 | |||
120 | len += snprintf(buf + len, sizeof(buf) - len, | ||
121 | "%20s : %10u\n", "EncapFail", | ||
122 | be32_to_cpu(cmd_rsp.encap_fail)); | ||
123 | |||
124 | len += snprintf(buf + len, sizeof(buf) - len, | ||
125 | "%20s : %10u\n", "NoBuf", | ||
126 | be32_to_cpu(cmd_rsp.nobuf)); | ||
127 | |||
128 | if (len > sizeof(buf)) | ||
129 | len = sizeof(buf); | ||
130 | |||
131 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
132 | } | ||
133 | |||
134 | static const struct file_operations fops_tgt_tx_stats = { | ||
135 | .read = read_file_tgt_tx_stats, | ||
136 | .open = ath9k_debugfs_open, | ||
137 | .owner = THIS_MODULE, | ||
138 | .llseek = default_llseek, | ||
139 | }; | ||
140 | |||
141 | static ssize_t read_file_tgt_rx_stats(struct file *file, char __user *user_buf, | ||
142 | size_t count, loff_t *ppos) | ||
143 | { | ||
144 | struct ath9k_htc_priv *priv = file->private_data; | ||
145 | struct ath9k_htc_target_rx_stats cmd_rsp; | ||
146 | char buf[512]; | ||
147 | unsigned int len = 0; | ||
148 | int ret = 0; | ||
149 | |||
150 | memset(&cmd_rsp, 0, sizeof(cmd_rsp)); | ||
151 | |||
152 | WMI_CMD(WMI_RX_STATS_CMDID); | ||
153 | if (ret) | ||
154 | return -EINVAL; | ||
155 | |||
156 | len += snprintf(buf + len, sizeof(buf) - len, | ||
157 | "%20s : %10u\n", "NoBuf", | ||
158 | be32_to_cpu(cmd_rsp.nobuf)); | ||
159 | |||
160 | len += snprintf(buf + len, sizeof(buf) - len, | ||
161 | "%20s : %10u\n", "HostSend", | ||
162 | be32_to_cpu(cmd_rsp.host_send)); | ||
163 | |||
164 | len += snprintf(buf + len, sizeof(buf) - len, | ||
165 | "%20s : %10u\n", "HostDone", | ||
166 | be32_to_cpu(cmd_rsp.host_done)); | ||
167 | |||
168 | if (len > sizeof(buf)) | ||
169 | len = sizeof(buf); | ||
170 | |||
171 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
172 | } | ||
173 | |||
174 | static const struct file_operations fops_tgt_rx_stats = { | ||
175 | .read = read_file_tgt_rx_stats, | ||
176 | .open = ath9k_debugfs_open, | ||
177 | .owner = THIS_MODULE, | ||
178 | .llseek = default_llseek, | ||
179 | }; | ||
180 | |||
181 | static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | ||
182 | size_t count, loff_t *ppos) | ||
183 | { | ||
184 | struct ath9k_htc_priv *priv = file->private_data; | ||
185 | char buf[512]; | ||
186 | unsigned int len = 0; | ||
187 | |||
188 | len += snprintf(buf + len, sizeof(buf) - len, | ||
189 | "%20s : %10u\n", "Buffers queued", | ||
190 | priv->debug.tx_stats.buf_queued); | ||
191 | len += snprintf(buf + len, sizeof(buf) - len, | ||
192 | "%20s : %10u\n", "Buffers completed", | ||
193 | priv->debug.tx_stats.buf_completed); | ||
194 | len += snprintf(buf + len, sizeof(buf) - len, | ||
195 | "%20s : %10u\n", "SKBs queued", | ||
196 | priv->debug.tx_stats.skb_queued); | ||
197 | len += snprintf(buf + len, sizeof(buf) - len, | ||
198 | "%20s : %10u\n", "SKBs success", | ||
199 | priv->debug.tx_stats.skb_success); | ||
200 | len += snprintf(buf + len, sizeof(buf) - len, | ||
201 | "%20s : %10u\n", "SKBs failed", | ||
202 | priv->debug.tx_stats.skb_failed); | ||
203 | len += snprintf(buf + len, sizeof(buf) - len, | ||
204 | "%20s : %10u\n", "CAB queued", | ||
205 | priv->debug.tx_stats.cab_queued); | ||
206 | |||
207 | len += snprintf(buf + len, sizeof(buf) - len, | ||
208 | "%20s : %10u\n", "BE queued", | ||
209 | priv->debug.tx_stats.queue_stats[WME_AC_BE]); | ||
210 | len += snprintf(buf + len, sizeof(buf) - len, | ||
211 | "%20s : %10u\n", "BK queued", | ||
212 | priv->debug.tx_stats.queue_stats[WME_AC_BK]); | ||
213 | len += snprintf(buf + len, sizeof(buf) - len, | ||
214 | "%20s : %10u\n", "VI queued", | ||
215 | priv->debug.tx_stats.queue_stats[WME_AC_VI]); | ||
216 | len += snprintf(buf + len, sizeof(buf) - len, | ||
217 | "%20s : %10u\n", "VO queued", | ||
218 | priv->debug.tx_stats.queue_stats[WME_AC_VO]); | ||
219 | |||
220 | if (len > sizeof(buf)) | ||
221 | len = sizeof(buf); | ||
222 | |||
223 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
224 | } | ||
225 | |||
226 | static const struct file_operations fops_xmit = { | ||
227 | .read = read_file_xmit, | ||
228 | .open = ath9k_debugfs_open, | ||
229 | .owner = THIS_MODULE, | ||
230 | .llseek = default_llseek, | ||
231 | }; | ||
232 | |||
233 | void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, | ||
234 | struct ath_htc_rx_status *rxs) | ||
235 | { | ||
236 | #define RX_PHY_ERR_INC(c) priv->debug.rx_stats.err_phy_stats[c]++ | ||
237 | |||
238 | if (rxs->rs_status & ATH9K_RXERR_CRC) | ||
239 | priv->debug.rx_stats.err_crc++; | ||
240 | if (rxs->rs_status & ATH9K_RXERR_DECRYPT) | ||
241 | priv->debug.rx_stats.err_decrypt_crc++; | ||
242 | if (rxs->rs_status & ATH9K_RXERR_MIC) | ||
243 | priv->debug.rx_stats.err_mic++; | ||
244 | if (rxs->rs_status & ATH9K_RX_DELIM_CRC_PRE) | ||
245 | priv->debug.rx_stats.err_pre_delim++; | ||
246 | if (rxs->rs_status & ATH9K_RX_DELIM_CRC_POST) | ||
247 | priv->debug.rx_stats.err_post_delim++; | ||
248 | if (rxs->rs_status & ATH9K_RX_DECRYPT_BUSY) | ||
249 | priv->debug.rx_stats.err_decrypt_busy++; | ||
250 | |||
251 | if (rxs->rs_status & ATH9K_RXERR_PHY) { | ||
252 | priv->debug.rx_stats.err_phy++; | ||
253 | if (rxs->rs_phyerr < ATH9K_PHYERR_MAX) | ||
254 | RX_PHY_ERR_INC(rxs->rs_phyerr); | ||
255 | } | ||
256 | |||
257 | #undef RX_PHY_ERR_INC | ||
258 | } | ||
259 | |||
260 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, | ||
261 | size_t count, loff_t *ppos) | ||
262 | { | ||
263 | #define PHY_ERR(s, p) \ | ||
264 | len += snprintf(buf + len, size - len, "%20s : %10u\n", s, \ | ||
265 | priv->debug.rx_stats.err_phy_stats[p]); | ||
266 | |||
267 | struct ath9k_htc_priv *priv = file->private_data; | ||
268 | char *buf; | ||
269 | unsigned int len = 0, size = 1500; | ||
270 | ssize_t retval = 0; | ||
271 | |||
272 | buf = kzalloc(size, GFP_KERNEL); | ||
273 | if (buf == NULL) | ||
274 | return -ENOMEM; | ||
275 | |||
276 | len += snprintf(buf + len, size - len, | ||
277 | "%20s : %10u\n", "SKBs allocated", | ||
278 | priv->debug.rx_stats.skb_allocated); | ||
279 | len += snprintf(buf + len, size - len, | ||
280 | "%20s : %10u\n", "SKBs completed", | ||
281 | priv->debug.rx_stats.skb_completed); | ||
282 | len += snprintf(buf + len, size - len, | ||
283 | "%20s : %10u\n", "SKBs Dropped", | ||
284 | priv->debug.rx_stats.skb_dropped); | ||
285 | |||
286 | len += snprintf(buf + len, size - len, | ||
287 | "%20s : %10u\n", "CRC ERR", | ||
288 | priv->debug.rx_stats.err_crc); | ||
289 | len += snprintf(buf + len, size - len, | ||
290 | "%20s : %10u\n", "DECRYPT CRC ERR", | ||
291 | priv->debug.rx_stats.err_decrypt_crc); | ||
292 | len += snprintf(buf + len, size - len, | ||
293 | "%20s : %10u\n", "MIC ERR", | ||
294 | priv->debug.rx_stats.err_mic); | ||
295 | len += snprintf(buf + len, size - len, | ||
296 | "%20s : %10u\n", "PRE-DELIM CRC ERR", | ||
297 | priv->debug.rx_stats.err_pre_delim); | ||
298 | len += snprintf(buf + len, size - len, | ||
299 | "%20s : %10u\n", "POST-DELIM CRC ERR", | ||
300 | priv->debug.rx_stats.err_post_delim); | ||
301 | len += snprintf(buf + len, size - len, | ||
302 | "%20s : %10u\n", "DECRYPT BUSY ERR", | ||
303 | priv->debug.rx_stats.err_decrypt_busy); | ||
304 | len += snprintf(buf + len, size - len, | ||
305 | "%20s : %10u\n", "TOTAL PHY ERR", | ||
306 | priv->debug.rx_stats.err_phy); | ||
307 | |||
308 | |||
309 | PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); | ||
310 | PHY_ERR("TIMING", ATH9K_PHYERR_TIMING); | ||
311 | PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); | ||
312 | PHY_ERR("RATE", ATH9K_PHYERR_RATE); | ||
313 | PHY_ERR("LENGTH", ATH9K_PHYERR_LENGTH); | ||
314 | PHY_ERR("RADAR", ATH9K_PHYERR_RADAR); | ||
315 | PHY_ERR("SERVICE", ATH9K_PHYERR_SERVICE); | ||
316 | PHY_ERR("TOR", ATH9K_PHYERR_TOR); | ||
317 | PHY_ERR("OFDM-TIMING", ATH9K_PHYERR_OFDM_TIMING); | ||
318 | PHY_ERR("OFDM-SIGNAL-PARITY", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); | ||
319 | PHY_ERR("OFDM-RATE", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); | ||
320 | PHY_ERR("OFDM-LENGTH", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL); | ||
321 | PHY_ERR("OFDM-POWER-DROP", ATH9K_PHYERR_OFDM_POWER_DROP); | ||
322 | PHY_ERR("OFDM-SERVICE", ATH9K_PHYERR_OFDM_SERVICE); | ||
323 | PHY_ERR("OFDM-RESTART", ATH9K_PHYERR_OFDM_RESTART); | ||
324 | PHY_ERR("FALSE-RADAR-EXT", ATH9K_PHYERR_FALSE_RADAR_EXT); | ||
325 | PHY_ERR("CCK-TIMING", ATH9K_PHYERR_CCK_TIMING); | ||
326 | PHY_ERR("CCK-HEADER-CRC", ATH9K_PHYERR_CCK_HEADER_CRC); | ||
327 | PHY_ERR("CCK-RATE", ATH9K_PHYERR_CCK_RATE_ILLEGAL); | ||
328 | PHY_ERR("CCK-SERVICE", ATH9K_PHYERR_CCK_SERVICE); | ||
329 | PHY_ERR("CCK-RESTART", ATH9K_PHYERR_CCK_RESTART); | ||
330 | PHY_ERR("CCK-LENGTH", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); | ||
331 | PHY_ERR("CCK-POWER-DROP", ATH9K_PHYERR_CCK_POWER_DROP); | ||
332 | PHY_ERR("HT-CRC", ATH9K_PHYERR_HT_CRC_ERROR); | ||
333 | PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); | ||
334 | PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); | ||
335 | |||
336 | if (len > size) | ||
337 | len = size; | ||
338 | |||
339 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
340 | kfree(buf); | ||
341 | |||
342 | return retval; | ||
343 | |||
344 | #undef PHY_ERR | ||
345 | } | ||
346 | |||
347 | static const struct file_operations fops_recv = { | ||
348 | .read = read_file_recv, | ||
349 | .open = ath9k_debugfs_open, | ||
350 | .owner = THIS_MODULE, | ||
351 | .llseek = default_llseek, | ||
352 | }; | ||
353 | |||
354 | static ssize_t read_file_slot(struct file *file, char __user *user_buf, | ||
355 | size_t count, loff_t *ppos) | ||
356 | { | ||
357 | struct ath9k_htc_priv *priv = file->private_data; | ||
358 | char buf[512]; | ||
359 | unsigned int len = 0; | ||
360 | |||
361 | spin_lock_bh(&priv->tx.tx_lock); | ||
362 | |||
363 | len += snprintf(buf + len, sizeof(buf) - len, "TX slot bitmap : "); | ||
364 | |||
365 | len += bitmap_scnprintf(buf + len, sizeof(buf) - len, | ||
366 | priv->tx.tx_slot, MAX_TX_BUF_NUM); | ||
367 | |||
368 | len += snprintf(buf + len, sizeof(buf) - len, "\n"); | ||
369 | |||
370 | len += snprintf(buf + len, sizeof(buf) - len, | ||
371 | "Used slots : %d\n", | ||
372 | bitmap_weight(priv->tx.tx_slot, MAX_TX_BUF_NUM)); | ||
373 | |||
374 | spin_unlock_bh(&priv->tx.tx_lock); | ||
375 | |||
376 | if (len > sizeof(buf)) | ||
377 | len = sizeof(buf); | ||
378 | |||
379 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
380 | } | ||
381 | |||
382 | static const struct file_operations fops_slot = { | ||
383 | .read = read_file_slot, | ||
384 | .open = ath9k_debugfs_open, | ||
385 | .owner = THIS_MODULE, | ||
386 | .llseek = default_llseek, | ||
387 | }; | ||
388 | |||
389 | static ssize_t read_file_queue(struct file *file, char __user *user_buf, | ||
390 | size_t count, loff_t *ppos) | ||
391 | { | ||
392 | struct ath9k_htc_priv *priv = file->private_data; | ||
393 | char buf[512]; | ||
394 | unsigned int len = 0; | ||
395 | |||
396 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
397 | "Mgmt endpoint", skb_queue_len(&priv->tx.mgmt_ep_queue)); | ||
398 | |||
399 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
400 | "Cab endpoint", skb_queue_len(&priv->tx.cab_ep_queue)); | ||
401 | |||
402 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
403 | "Data BE endpoint", skb_queue_len(&priv->tx.data_be_queue)); | ||
404 | |||
405 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
406 | "Data BK endpoint", skb_queue_len(&priv->tx.data_bk_queue)); | ||
407 | |||
408 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
409 | "Data VI endpoint", skb_queue_len(&priv->tx.data_vi_queue)); | ||
410 | |||
411 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
412 | "Data VO endpoint", skb_queue_len(&priv->tx.data_vo_queue)); | ||
413 | |||
414 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
415 | "Failed queue", skb_queue_len(&priv->tx.tx_failed)); | ||
416 | |||
417 | spin_lock_bh(&priv->tx.tx_lock); | ||
418 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
419 | "Queued count", priv->tx.queued_cnt); | ||
420 | spin_unlock_bh(&priv->tx.tx_lock); | ||
421 | |||
422 | if (len > sizeof(buf)) | ||
423 | len = sizeof(buf); | ||
424 | |||
425 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
426 | |||
427 | } | ||
428 | |||
429 | static const struct file_operations fops_queue = { | ||
430 | .read = read_file_queue, | ||
431 | .open = ath9k_debugfs_open, | ||
432 | .owner = THIS_MODULE, | ||
433 | .llseek = default_llseek, | ||
434 | }; | ||
435 | |||
436 | static ssize_t read_file_debug(struct file *file, char __user *user_buf, | ||
437 | size_t count, loff_t *ppos) | ||
438 | { | ||
439 | struct ath9k_htc_priv *priv = file->private_data; | ||
440 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
441 | char buf[32]; | ||
442 | unsigned int len; | ||
443 | |||
444 | len = sprintf(buf, "0x%08x\n", common->debug_mask); | ||
445 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
446 | } | ||
447 | |||
448 | static ssize_t write_file_debug(struct file *file, const char __user *user_buf, | ||
449 | size_t count, loff_t *ppos) | ||
450 | { | ||
451 | struct ath9k_htc_priv *priv = file->private_data; | ||
452 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
453 | unsigned long mask; | ||
454 | char buf[32]; | ||
455 | ssize_t len; | ||
456 | |||
457 | len = min(count, sizeof(buf) - 1); | ||
458 | if (copy_from_user(buf, user_buf, len)) | ||
459 | return -EFAULT; | ||
460 | |||
461 | buf[len] = '\0'; | ||
462 | if (strict_strtoul(buf, 0, &mask)) | ||
463 | return -EINVAL; | ||
464 | |||
465 | common->debug_mask = mask; | ||
466 | return count; | ||
467 | } | ||
468 | |||
469 | static const struct file_operations fops_debug = { | ||
470 | .read = read_file_debug, | ||
471 | .write = write_file_debug, | ||
472 | .open = ath9k_debugfs_open, | ||
473 | .owner = THIS_MODULE, | ||
474 | .llseek = default_llseek, | ||
475 | }; | ||
476 | |||
477 | int ath9k_htc_init_debug(struct ath_hw *ah) | ||
478 | { | ||
479 | struct ath_common *common = ath9k_hw_common(ah); | ||
480 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
481 | |||
482 | priv->debug.debugfs_phy = debugfs_create_dir(KBUILD_MODNAME, | ||
483 | priv->hw->wiphy->debugfsdir); | ||
484 | if (!priv->debug.debugfs_phy) | ||
485 | return -ENOMEM; | ||
486 | |||
487 | debugfs_create_file("tgt_int_stats", S_IRUSR, priv->debug.debugfs_phy, | ||
488 | priv, &fops_tgt_int_stats); | ||
489 | debugfs_create_file("tgt_tx_stats", S_IRUSR, priv->debug.debugfs_phy, | ||
490 | priv, &fops_tgt_tx_stats); | ||
491 | debugfs_create_file("tgt_rx_stats", S_IRUSR, priv->debug.debugfs_phy, | ||
492 | priv, &fops_tgt_rx_stats); | ||
493 | debugfs_create_file("xmit", S_IRUSR, priv->debug.debugfs_phy, | ||
494 | priv, &fops_xmit); | ||
495 | debugfs_create_file("recv", S_IRUSR, priv->debug.debugfs_phy, | ||
496 | priv, &fops_recv); | ||
497 | debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy, | ||
498 | priv, &fops_slot); | ||
499 | debugfs_create_file("queue", S_IRUSR, priv->debug.debugfs_phy, | ||
500 | priv, &fops_queue); | ||
501 | debugfs_create_file("debug", S_IRUSR | S_IWUSR, priv->debug.debugfs_phy, | ||
502 | priv, &fops_debug); | ||
503 | |||
504 | return 0; | ||
505 | } | ||