1 | /* |
2 | * Copyright (c) 2008-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 "common.h" |
18 | |
19 | static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf, |
20 | size_t count, loff_t *ppos) |
21 | { |
22 | struct ath_hw *ah = file->private_data; |
23 | u32 len = 0, size = 6000; |
24 | char *buf; |
25 | size_t retval; |
26 | |
27 | buf = kzalloc(size, GFP_KERNEL); |
28 | if (buf == NULL) |
29 | return -ENOMEM; |
30 | |
31 | len = ah->eep_ops->dump_eeprom(ah, false, buf, len, size); |
32 | |
33 | retval = simple_read_from_buffer(to: user_buf, count, ppos, from: buf, available: len); |
34 | kfree(objp: buf); |
35 | |
36 | return retval; |
37 | } |
38 | |
39 | static const struct file_operations fops_modal_eeprom = { |
40 | .read = read_file_modal_eeprom, |
41 | .open = simple_open, |
42 | .owner = THIS_MODULE, |
43 | .llseek = default_llseek, |
44 | }; |
45 | |
46 | |
47 | void ath9k_cmn_debug_modal_eeprom(struct dentry *debugfs_phy, |
48 | struct ath_hw *ah) |
49 | { |
50 | debugfs_create_file(name: "modal_eeprom" , mode: 0400, parent: debugfs_phy, data: ah, |
51 | fops: &fops_modal_eeprom); |
52 | } |
53 | EXPORT_SYMBOL(ath9k_cmn_debug_modal_eeprom); |
54 | |
55 | static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf, |
56 | size_t count, loff_t *ppos) |
57 | { |
58 | struct ath_hw *ah = file->private_data; |
59 | u32 len = 0, size = 1500; |
60 | ssize_t retval = 0; |
61 | char *buf; |
62 | |
63 | buf = kzalloc(size, GFP_KERNEL); |
64 | if (!buf) |
65 | return -ENOMEM; |
66 | |
67 | len = ah->eep_ops->dump_eeprom(ah, true, buf, len, size); |
68 | |
69 | retval = simple_read_from_buffer(to: user_buf, count, ppos, from: buf, available: len); |
70 | kfree(objp: buf); |
71 | |
72 | return retval; |
73 | } |
74 | |
75 | static const struct file_operations fops_base_eeprom = { |
76 | .read = read_file_base_eeprom, |
77 | .open = simple_open, |
78 | .owner = THIS_MODULE, |
79 | .llseek = default_llseek, |
80 | }; |
81 | |
82 | void ath9k_cmn_debug_base_eeprom(struct dentry *debugfs_phy, |
83 | struct ath_hw *ah) |
84 | { |
85 | debugfs_create_file(name: "base_eeprom" , mode: 0400, parent: debugfs_phy, data: ah, |
86 | fops: &fops_base_eeprom); |
87 | } |
88 | EXPORT_SYMBOL(ath9k_cmn_debug_base_eeprom); |
89 | |
90 | void ath9k_cmn_debug_stat_rx(struct ath_rx_stats *rxstats, |
91 | struct ath_rx_status *rs) |
92 | { |
93 | #define RX_PHY_ERR_INC(c) rxstats->phy_err_stats[c]++ |
94 | #define RX_CMN_STAT_INC(c) (rxstats->c++) |
95 | |
96 | RX_CMN_STAT_INC(rx_pkts_all); |
97 | rxstats->rx_bytes_all += rs->rs_datalen; |
98 | |
99 | if (rs->rs_status & ATH9K_RXERR_CRC) |
100 | RX_CMN_STAT_INC(crc_err); |
101 | if (rs->rs_status & ATH9K_RXERR_DECRYPT) |
102 | RX_CMN_STAT_INC(decrypt_crc_err); |
103 | if (rs->rs_status & ATH9K_RXERR_MIC) |
104 | RX_CMN_STAT_INC(mic_err); |
105 | if (rs->rs_status & ATH9K_RX_DELIM_CRC_PRE) |
106 | RX_CMN_STAT_INC(pre_delim_crc_err); |
107 | if (rs->rs_status & ATH9K_RX_DELIM_CRC_POST) |
108 | RX_CMN_STAT_INC(post_delim_crc_err); |
109 | if (rs->rs_status & ATH9K_RX_DECRYPT_BUSY) |
110 | RX_CMN_STAT_INC(decrypt_busy_err); |
111 | |
112 | if (rs->rs_status & ATH9K_RXERR_PHY) { |
113 | RX_CMN_STAT_INC(phy_err); |
114 | if (rs->rs_phyerr < ATH9K_PHYERR_MAX) |
115 | RX_PHY_ERR_INC(rs->rs_phyerr); |
116 | } |
117 | |
118 | #undef RX_CMN_STAT_INC |
119 | #undef RX_PHY_ERR_INC |
120 | } |
121 | EXPORT_SYMBOL(ath9k_cmn_debug_stat_rx); |
122 | |
123 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, |
124 | size_t count, loff_t *ppos) |
125 | { |
126 | #define RXS_ERR(s, e) \ |
127 | do { \ |
128 | len += scnprintf(buf + len, size - len, \ |
129 | "%18s : %10u\n", s, \ |
130 | rxstats->e); \ |
131 | } while (0) |
132 | |
133 | struct ath_rx_stats *rxstats = file->private_data; |
134 | char *buf; |
135 | unsigned int len = 0, size = 1600; |
136 | ssize_t retval = 0; |
137 | |
138 | buf = kzalloc(size, GFP_KERNEL); |
139 | if (buf == NULL) |
140 | return -ENOMEM; |
141 | |
142 | RXS_ERR("PKTS-ALL" , rx_pkts_all); |
143 | RXS_ERR("BYTES-ALL" , rx_bytes_all); |
144 | RXS_ERR("BEACONS" , rx_beacons); |
145 | RXS_ERR("FRAGS" , rx_frags); |
146 | RXS_ERR("SPECTRAL" , rx_spectral); |
147 | RXS_ERR("SPECTRAL SMPL GOOD" , rx_spectral_sample_good); |
148 | RXS_ERR("SPECTRAL SMPL ERR" , rx_spectral_sample_err); |
149 | |
150 | RXS_ERR("CRC ERR" , crc_err); |
151 | RXS_ERR("DECRYPT CRC ERR" , decrypt_crc_err); |
152 | RXS_ERR("PHY ERR" , phy_err); |
153 | RXS_ERR("MIC ERR" , mic_err); |
154 | RXS_ERR("PRE-DELIM CRC ERR" , pre_delim_crc_err); |
155 | RXS_ERR("POST-DELIM CRC ERR" , post_delim_crc_err); |
156 | RXS_ERR("DECRYPT BUSY ERR" , decrypt_busy_err); |
157 | RXS_ERR("LENGTH-ERR" , rx_len_err); |
158 | RXS_ERR("OOM-ERR" , rx_oom_err); |
159 | RXS_ERR("RATE-ERR" , rx_rate_err); |
160 | RXS_ERR("TOO-MANY-FRAGS" , rx_too_many_frags_err); |
161 | |
162 | if (len > size) |
163 | len = size; |
164 | |
165 | retval = simple_read_from_buffer(to: user_buf, count, ppos, from: buf, available: len); |
166 | kfree(objp: buf); |
167 | |
168 | return retval; |
169 | |
170 | #undef RXS_ERR |
171 | } |
172 | |
173 | static const struct file_operations fops_recv = { |
174 | .read = read_file_recv, |
175 | .open = simple_open, |
176 | .owner = THIS_MODULE, |
177 | .llseek = default_llseek, |
178 | }; |
179 | |
180 | void ath9k_cmn_debug_recv(struct dentry *debugfs_phy, |
181 | struct ath_rx_stats *rxstats) |
182 | { |
183 | debugfs_create_file(name: "recv" , mode: 0400, parent: debugfs_phy, data: rxstats, fops: &fops_recv); |
184 | } |
185 | EXPORT_SYMBOL(ath9k_cmn_debug_recv); |
186 | |
187 | static ssize_t read_file_phy_err(struct file *file, char __user *user_buf, |
188 | size_t count, loff_t *ppos) |
189 | { |
190 | #define PHY_ERR(s, p) \ |
191 | len += scnprintf(buf + len, size - len, "%22s : %10u\n", s, \ |
192 | rxstats->phy_err_stats[p]) |
193 | |
194 | struct ath_rx_stats *rxstats = file->private_data; |
195 | char *buf; |
196 | unsigned int len = 0, size = 1600; |
197 | ssize_t retval = 0; |
198 | |
199 | buf = kzalloc(size, GFP_KERNEL); |
200 | if (buf == NULL) |
201 | return -ENOMEM; |
202 | |
203 | PHY_ERR("UNDERRUN ERR" , ATH9K_PHYERR_UNDERRUN); |
204 | PHY_ERR("TIMING ERR" , ATH9K_PHYERR_TIMING); |
205 | PHY_ERR("PARITY ERR" , ATH9K_PHYERR_PARITY); |
206 | PHY_ERR("RATE ERR" , ATH9K_PHYERR_RATE); |
207 | PHY_ERR("LENGTH ERR" , ATH9K_PHYERR_LENGTH); |
208 | PHY_ERR("RADAR ERR" , ATH9K_PHYERR_RADAR); |
209 | PHY_ERR("SERVICE ERR" , ATH9K_PHYERR_SERVICE); |
210 | PHY_ERR("TOR ERR" , ATH9K_PHYERR_TOR); |
211 | |
212 | PHY_ERR("OFDM-TIMING ERR" , ATH9K_PHYERR_OFDM_TIMING); |
213 | PHY_ERR("OFDM-SIGNAL-PARITY ERR" , ATH9K_PHYERR_OFDM_SIGNAL_PARITY); |
214 | PHY_ERR("OFDM-RATE ERR" , ATH9K_PHYERR_OFDM_RATE_ILLEGAL); |
215 | PHY_ERR("OFDM-LENGTH ERR" , ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL); |
216 | PHY_ERR("OFDM-POWER-DROP ERR" , ATH9K_PHYERR_OFDM_POWER_DROP); |
217 | PHY_ERR("OFDM-SERVICE ERR" , ATH9K_PHYERR_OFDM_SERVICE); |
218 | PHY_ERR("OFDM-RESTART ERR" , ATH9K_PHYERR_OFDM_RESTART); |
219 | |
220 | PHY_ERR("CCK-BLOCKER ERR" , ATH9K_PHYERR_CCK_BLOCKER); |
221 | PHY_ERR("CCK-TIMING ERR" , ATH9K_PHYERR_CCK_TIMING); |
222 | PHY_ERR("CCK-HEADER-CRC ERR" , ATH9K_PHYERR_CCK_HEADER_CRC); |
223 | PHY_ERR("CCK-RATE ERR" , ATH9K_PHYERR_CCK_RATE_ILLEGAL); |
224 | PHY_ERR("CCK-LENGTH ERR" , ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); |
225 | PHY_ERR("CCK-POWER-DROP ERR" , ATH9K_PHYERR_CCK_POWER_DROP); |
226 | PHY_ERR("CCK-SERVICE ERR" , ATH9K_PHYERR_CCK_SERVICE); |
227 | PHY_ERR("CCK-RESTART ERR" , ATH9K_PHYERR_CCK_RESTART); |
228 | |
229 | PHY_ERR("HT-CRC ERR" , ATH9K_PHYERR_HT_CRC_ERROR); |
230 | PHY_ERR("HT-LENGTH ERR" , ATH9K_PHYERR_HT_LENGTH_ILLEGAL); |
231 | PHY_ERR("HT-RATE ERR" , ATH9K_PHYERR_HT_RATE_ILLEGAL); |
232 | PHY_ERR("HT-ZLF ERR" , ATH9K_PHYERR_HT_ZLF); |
233 | |
234 | PHY_ERR("FALSE-RADAR-EXT ERR" , ATH9K_PHYERR_FALSE_RADAR_EXT); |
235 | PHY_ERR("GREEN-FIELD ERR" , ATH9K_PHYERR_GREEN_FIELD); |
236 | PHY_ERR("SPECTRAL ERR" , ATH9K_PHYERR_SPECTRAL); |
237 | |
238 | if (len > size) |
239 | len = size; |
240 | |
241 | retval = simple_read_from_buffer(to: user_buf, count, ppos, from: buf, available: len); |
242 | kfree(objp: buf); |
243 | |
244 | return retval; |
245 | |
246 | #undef PHY_ERR |
247 | } |
248 | |
249 | static const struct file_operations fops_phy_err = { |
250 | .read = read_file_phy_err, |
251 | .open = simple_open, |
252 | .owner = THIS_MODULE, |
253 | .llseek = default_llseek, |
254 | }; |
255 | |
256 | void ath9k_cmn_debug_phy_err(struct dentry *debugfs_phy, |
257 | struct ath_rx_stats *rxstats) |
258 | { |
259 | debugfs_create_file(name: "phy_err" , mode: 0400, parent: debugfs_phy, data: rxstats, |
260 | fops: &fops_phy_err); |
261 | } |
262 | EXPORT_SYMBOL(ath9k_cmn_debug_phy_err); |
263 | |