diff options
-rw-r--r-- | drivers/net/wireless/ath/ath9k/Kconfig | 22 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/debug.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/debug.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/dfs.c | 215 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/dfs.h | 43 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/dfs_debug.c | 81 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/dfs_debug.h | 57 |
8 files changed, 425 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 7b4c074e12fa..1b4786ae00ac 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
@@ -2,6 +2,9 @@ config ATH9K_HW | |||
2 | tristate | 2 | tristate |
3 | config ATH9K_COMMON | 3 | config ATH9K_COMMON |
4 | tristate | 4 | tristate |
5 | config ATH9K_DFS_DEBUGFS | ||
6 | def_bool y | ||
7 | depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED | ||
5 | 8 | ||
6 | config ATH9K | 9 | config ATH9K |
7 | tristate "Atheros 802.11n wireless cards support" | 10 | tristate "Atheros 802.11n wireless cards support" |
@@ -51,6 +54,25 @@ config ATH9K_DEBUGFS | |||
51 | 54 | ||
52 | Also required for changing debug message flags at run time. | 55 | Also required for changing debug message flags at run time. |
53 | 56 | ||
57 | config ATH9K_DFS_CERTIFIED | ||
58 | bool "Atheros DFS support for certified platforms" | ||
59 | depends on ATH9K && EXPERT | ||
60 | default n | ||
61 | ---help--- | ||
62 | This option enables DFS support for initiating radiation on | ||
63 | ath9k. There is no way to dynamically detect if a card was DFS | ||
64 | certified and as such this is left as a build time option. This | ||
65 | option should only be enabled by system integrators that can | ||
66 | guarantee that all the platforms that their kernel will run on | ||
67 | have obtained appropriate regulatory body certification for a | ||
68 | respective Atheros card by using ath9k on the target shipping | ||
69 | platforms. | ||
70 | |||
71 | This is currently only a placeholder for future DFS support, | ||
72 | as DFS support requires more components that still need to be | ||
73 | developed. At this point enabling this option won't do anything | ||
74 | except increase code size. | ||
75 | |||
54 | config ATH9K_RATE_CONTROL | 76 | config ATH9K_RATE_CONTROL |
55 | bool "Atheros ath9k rate control" | 77 | bool "Atheros ath9k rate control" |
56 | depends on ATH9K | 78 | depends on ATH9K |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 390797db5273..da02242499af 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -10,6 +10,8 @@ ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o | |||
10 | ath9k-$(CONFIG_ATH9K_PCI) += pci.o | 10 | ath9k-$(CONFIG_ATH9K_PCI) += pci.o |
11 | ath9k-$(CONFIG_ATH9K_AHB) += ahb.o | 11 | ath9k-$(CONFIG_ATH9K_AHB) += ahb.o |
12 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o | 12 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o |
13 | ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o | ||
14 | ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o | ||
13 | 15 | ||
14 | obj-$(CONFIG_ATH9K) += ath9k.o | 16 | obj-$(CONFIG_ATH9K) += ath9k.o |
15 | 17 | ||
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 5cb8cceffd0b..68d972bf232d 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -1630,6 +1630,9 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
1630 | debugfs_create_file("debug", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, | 1630 | debugfs_create_file("debug", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, |
1631 | sc, &fops_debug); | 1631 | sc, &fops_debug); |
1632 | #endif | 1632 | #endif |
1633 | |||
1634 | ath9k_dfs_init_debug(sc); | ||
1635 | |||
1633 | debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, | 1636 | debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, |
1634 | &fops_dma); | 1637 | &fops_dma); |
1635 | debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc, | 1638 | debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc, |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 356352ac2d6e..776a24ada600 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include "hw.h" | 20 | #include "hw.h" |
21 | #include "rc.h" | 21 | #include "rc.h" |
22 | #include "dfs_debug.h" | ||
22 | 23 | ||
23 | struct ath_txq; | 24 | struct ath_txq; |
24 | struct ath_buf; | 25 | struct ath_buf; |
@@ -187,6 +188,7 @@ struct ath_stats { | |||
187 | struct ath_interrupt_stats istats; | 188 | struct ath_interrupt_stats istats; |
188 | struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES]; | 189 | struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES]; |
189 | struct ath_rx_stats rxstats; | 190 | struct ath_rx_stats rxstats; |
191 | struct ath_dfs_stats dfs_stats; | ||
190 | u32 reset[__RESET_TYPE_MAX]; | 192 | u32 reset[__RESET_TYPE_MAX]; |
191 | }; | 193 | }; |
192 | 194 | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c new file mode 100644 index 000000000000..e4e84a9e6273 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/dfs.c | |||
@@ -0,0 +1,215 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2011 Atheros Communications Inc. | ||
3 | * Copyright (c) 2011 Neratec Solutions AG | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include "hw.h" | ||
19 | #include "hw-ops.h" | ||
20 | #include "ath9k.h" | ||
21 | #include "dfs.h" | ||
22 | #include "dfs_debug.h" | ||
23 | |||
24 | /* | ||
25 | * TODO: move into or synchronize this with generic header | ||
26 | * as soon as IF is defined | ||
27 | */ | ||
28 | struct dfs_radar_pulse { | ||
29 | u16 freq; | ||
30 | u64 ts; | ||
31 | u32 width; | ||
32 | u8 rssi; | ||
33 | }; | ||
34 | |||
35 | /* internal struct to pass radar data */ | ||
36 | struct ath_radar_data { | ||
37 | u8 pulse_bw_info; | ||
38 | u8 rssi; | ||
39 | u8 ext_rssi; | ||
40 | u8 pulse_length_ext; | ||
41 | u8 pulse_length_pri; | ||
42 | }; | ||
43 | |||
44 | /* convert pulse duration to usecs, considering clock mode */ | ||
45 | static u32 dur_to_usecs(struct ath_hw *ah, u32 dur) | ||
46 | { | ||
47 | const u32 AR93X_NSECS_PER_DUR = 800; | ||
48 | const u32 AR93X_NSECS_PER_DUR_FAST = (8000 / 11); | ||
49 | u32 nsecs; | ||
50 | |||
51 | if (IS_CHAN_A_FAST_CLOCK(ah, ah->curchan)) | ||
52 | nsecs = dur * AR93X_NSECS_PER_DUR_FAST; | ||
53 | else | ||
54 | nsecs = dur * AR93X_NSECS_PER_DUR; | ||
55 | |||
56 | return (nsecs + 500) / 1000; | ||
57 | } | ||
58 | |||
59 | #define PRI_CH_RADAR_FOUND 0x01 | ||
60 | #define EXT_CH_RADAR_FOUND 0x02 | ||
61 | static bool | ||
62 | ath9k_postprocess_radar_event(struct ath_softc *sc, | ||
63 | struct ath_radar_data *are, | ||
64 | struct dfs_radar_pulse *drp) | ||
65 | { | ||
66 | u8 rssi; | ||
67 | u16 dur; | ||
68 | |||
69 | ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_DFS, | ||
70 | "pulse_bw_info=0x%x, pri,ext len/rssi=(%u/%u, %u/%u)\n", | ||
71 | are->pulse_bw_info, | ||
72 | are->pulse_length_pri, are->rssi, | ||
73 | are->pulse_length_ext, are->ext_rssi); | ||
74 | |||
75 | /* | ||
76 | * Only the last 2 bits of the BW info are relevant, they indicate | ||
77 | * which channel the radar was detected in. | ||
78 | */ | ||
79 | are->pulse_bw_info &= 0x03; | ||
80 | |||
81 | switch (are->pulse_bw_info) { | ||
82 | case PRI_CH_RADAR_FOUND: | ||
83 | /* radar in ctrl channel */ | ||
84 | dur = are->pulse_length_pri; | ||
85 | DFS_STAT_INC(sc, pri_phy_errors); | ||
86 | /* | ||
87 | * cannot use ctrl channel RSSI | ||
88 | * if extension channel is stronger | ||
89 | */ | ||
90 | rssi = (are->ext_rssi >= (are->rssi + 3)) ? 0 : are->rssi; | ||
91 | break; | ||
92 | case EXT_CH_RADAR_FOUND: | ||
93 | /* radar in extension channel */ | ||
94 | dur = are->pulse_length_ext; | ||
95 | DFS_STAT_INC(sc, ext_phy_errors); | ||
96 | /* | ||
97 | * cannot use extension channel RSSI | ||
98 | * if control channel is stronger | ||
99 | */ | ||
100 | rssi = (are->rssi >= (are->ext_rssi + 12)) ? 0 : are->ext_rssi; | ||
101 | break; | ||
102 | case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND): | ||
103 | /* | ||
104 | * Conducted testing, when pulse is on DC, both pri and ext | ||
105 | * durations are reported to be same | ||
106 | * | ||
107 | * Radiated testing, when pulse is on DC, different pri and | ||
108 | * ext durations are reported, so take the larger of the two | ||
109 | */ | ||
110 | if (are->pulse_length_ext >= are->pulse_length_pri) | ||
111 | dur = are->pulse_length_ext; | ||
112 | else | ||
113 | dur = are->pulse_length_pri; | ||
114 | DFS_STAT_INC(sc, dc_phy_errors); | ||
115 | |||
116 | /* when both are present use stronger one */ | ||
117 | rssi = (are->rssi < are->ext_rssi) ? are->ext_rssi : are->rssi; | ||
118 | break; | ||
119 | default: | ||
120 | /* | ||
121 | * Bogus bandwidth info was received in descriptor, | ||
122 | * so ignore this PHY error | ||
123 | */ | ||
124 | DFS_STAT_INC(sc, bwinfo_discards); | ||
125 | return false; | ||
126 | } | ||
127 | |||
128 | if (rssi == 0) { | ||
129 | DFS_STAT_INC(sc, rssi_discards); | ||
130 | return false; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * TODO: check chirping pulses | ||
135 | * checks for chirping are dependent on the DFS regulatory domain | ||
136 | * used, which is yet TBD | ||
137 | */ | ||
138 | |||
139 | /* convert duration to usecs */ | ||
140 | drp->width = dur_to_usecs(sc->sc_ah, dur); | ||
141 | drp->rssi = rssi; | ||
142 | |||
143 | DFS_STAT_INC(sc, pulses_detected); | ||
144 | return true; | ||
145 | } | ||
146 | #undef PRI_CH_RADAR_FOUND | ||
147 | #undef EXT_CH_RADAR_FOUND | ||
148 | |||
149 | /* | ||
150 | * DFS: check PHY-error for radar pulse and feed the detector | ||
151 | */ | ||
152 | void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | ||
153 | struct ath_rx_status *rs, u64 mactime) | ||
154 | { | ||
155 | struct ath_radar_data ard; | ||
156 | u16 datalen; | ||
157 | char *vdata_end; | ||
158 | struct dfs_radar_pulse drp; | ||
159 | struct ath_hw *ah = sc->sc_ah; | ||
160 | struct ath_common *common = ath9k_hw_common(ah); | ||
161 | |||
162 | if ((!(rs->rs_phyerr != ATH9K_PHYERR_RADAR)) && | ||
163 | (!(rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT))) { | ||
164 | ath_dbg(common, ATH_DBG_DFS, | ||
165 | "Error: rs_phyer=0x%x not a radar error\n", | ||
166 | rs->rs_phyerr); | ||
167 | return; | ||
168 | } | ||
169 | |||
170 | datalen = rs->rs_datalen; | ||
171 | if (datalen == 0) { | ||
172 | DFS_STAT_INC(sc, datalen_discards); | ||
173 | return; | ||
174 | } | ||
175 | |||
176 | ard.rssi = rs->rs_rssi_ctl0; | ||
177 | ard.ext_rssi = rs->rs_rssi_ext0; | ||
178 | |||
179 | /* | ||
180 | * hardware stores this as 8 bit signed value. | ||
181 | * we will cap it at 0 if it is a negative number | ||
182 | */ | ||
183 | if (ard.rssi & 0x80) | ||
184 | ard.rssi = 0; | ||
185 | if (ard.ext_rssi & 0x80) | ||
186 | ard.ext_rssi = 0; | ||
187 | |||
188 | vdata_end = (char *)data + datalen; | ||
189 | ard.pulse_bw_info = vdata_end[-1]; | ||
190 | ard.pulse_length_ext = vdata_end[-2]; | ||
191 | ard.pulse_length_pri = vdata_end[-3]; | ||
192 | |||
193 | ath_dbg(common, ATH_DBG_DFS, | ||
194 | "bw_info=%d, length_pri=%d, length_ext=%d, " | ||
195 | "rssi_pri=%d, rssi_ext=%d\n", | ||
196 | ard.pulse_bw_info, ard.pulse_length_pri, ard.pulse_length_ext, | ||
197 | ard.rssi, ard.ext_rssi); | ||
198 | |||
199 | drp.freq = ah->curchan->channel; | ||
200 | drp.ts = mactime; | ||
201 | if (ath9k_postprocess_radar_event(sc, &ard, &drp)) { | ||
202 | static u64 last_ts; | ||
203 | ath_dbg(common, ATH_DBG_DFS, | ||
204 | "ath9k_dfs_process_phyerr: channel=%d, ts=%llu, " | ||
205 | "width=%d, rssi=%d, delta_ts=%llu\n", | ||
206 | drp.freq, drp.ts, drp.width, drp.rssi, drp.ts-last_ts); | ||
207 | last_ts = drp.ts; | ||
208 | /* | ||
209 | * TODO: forward pulse to pattern detector | ||
210 | * | ||
211 | * ieee80211_add_radar_pulse(drp.freq, drp.ts, | ||
212 | * drp.width, drp.rssi); | ||
213 | */ | ||
214 | } | ||
215 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs.h b/drivers/net/wireless/ath/ath9k/dfs.h new file mode 100644 index 000000000000..c2412857f122 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/dfs.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2011 Atheros Communications Inc. | ||
3 | * Copyright (c) 2011 Neratec Solutions AG | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #ifndef ATH9K_DFS_H | ||
19 | #define ATH9K_DFS_H | ||
20 | |||
21 | #if defined(CONFIG_ATH9K_DFS_CERTIFIED) | ||
22 | /** | ||
23 | * ath9k_dfs_process_phyerr - process radar PHY error | ||
24 | * @sc: ath_softc | ||
25 | * @data: RX payload data | ||
26 | * @rs: RX status after processing descriptor | ||
27 | * @mactime: receive time | ||
28 | * | ||
29 | * This function is called whenever the HW DFS module detects a radar | ||
30 | * pulse and reports it as a PHY error. | ||
31 | * | ||
32 | * The radar information provided as raw payload data is validated and | ||
33 | * filtered for false pulses. Events passing all tests are forwarded to | ||
34 | * the upper layer for pattern detection. | ||
35 | */ | ||
36 | void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | ||
37 | struct ath_rx_status *rs, u64 mactime); | ||
38 | #else | ||
39 | static inline void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | ||
40 | struct ath_rx_status *rs, u64 mactime) { } | ||
41 | #endif | ||
42 | |||
43 | #endif /* ATH9K_DFS_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.c b/drivers/net/wireless/ath/ath9k/dfs_debug.c new file mode 100644 index 000000000000..106d031d834a --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2011 Atheros Communications Inc. | ||
3 | * Copyright (c) 2011 Neratec Solutions AG | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include <linux/debugfs.h> | ||
19 | #include <linux/export.h> | ||
20 | |||
21 | #include "ath9k.h" | ||
22 | #include "dfs_debug.h" | ||
23 | |||
24 | #define ATH9K_DFS_STAT(s, p) \ | ||
25 | len += snprintf(buf + len, size - len, "%28s : %10u\n", s, \ | ||
26 | sc->debug.stats.dfs_stats.p); | ||
27 | |||
28 | static ssize_t read_file_dfs(struct file *file, char __user *user_buf, | ||
29 | size_t count, loff_t *ppos) | ||
30 | { | ||
31 | struct ath_softc *sc = file->private_data; | ||
32 | struct ath9k_hw_version *hw_ver = &sc->sc_ah->hw_version; | ||
33 | char *buf; | ||
34 | unsigned int len = 0, size = 8000; | ||
35 | ssize_t retval = 0; | ||
36 | |||
37 | buf = kzalloc(size, GFP_KERNEL); | ||
38 | if (buf == NULL) | ||
39 | return -ENOMEM; | ||
40 | |||
41 | len += snprintf(buf + len, size - len, "DFS support for " | ||
42 | "macVersion = 0x%x, macRev = 0x%x: %s\n", | ||
43 | hw_ver->macVersion, hw_ver->macRev, | ||
44 | (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_DFS) ? | ||
45 | "enabled" : "disabled"); | ||
46 | ATH9K_DFS_STAT("DFS pulses detected ", pulses_detected); | ||
47 | ATH9K_DFS_STAT("Datalen discards ", datalen_discards); | ||
48 | ATH9K_DFS_STAT("RSSI discards ", rssi_discards); | ||
49 | ATH9K_DFS_STAT("BW info discards ", bwinfo_discards); | ||
50 | ATH9K_DFS_STAT("Primary channel pulses ", pri_phy_errors); | ||
51 | ATH9K_DFS_STAT("Secondary channel pulses", ext_phy_errors); | ||
52 | ATH9K_DFS_STAT("Dual channel pulses ", dc_phy_errors); | ||
53 | |||
54 | if (len > size) | ||
55 | len = size; | ||
56 | |||
57 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
58 | kfree(buf); | ||
59 | |||
60 | return retval; | ||
61 | } | ||
62 | |||
63 | static int ath9k_dfs_debugfs_open(struct inode *inode, struct file *file) | ||
64 | { | ||
65 | file->private_data = inode->i_private; | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static const struct file_operations fops_dfs_stats = { | ||
71 | .read = read_file_dfs, | ||
72 | .open = ath9k_dfs_debugfs_open, | ||
73 | .owner = THIS_MODULE, | ||
74 | .llseek = default_llseek, | ||
75 | }; | ||
76 | |||
77 | void ath9k_dfs_init_debug(struct ath_softc *sc) | ||
78 | { | ||
79 | debugfs_create_file("dfs_stats", S_IRUSR, | ||
80 | sc->debug.debugfs_phy, sc, &fops_dfs_stats); | ||
81 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.h b/drivers/net/wireless/ath/ath9k/dfs_debug.h new file mode 100644 index 000000000000..6e1e2a71659e --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2011 Atheros Communications Inc. | ||
3 | * Copyright (c) 2011 Neratec Solutions AG | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | |||
19 | #ifndef DFS_DEBUG_H | ||
20 | #define DFS_DEBUG_H | ||
21 | |||
22 | #include "hw.h" | ||
23 | |||
24 | /** | ||
25 | * struct ath_dfs_stats - DFS Statistics | ||
26 | * | ||
27 | * @pulses_detected: No. of pulses detected so far | ||
28 | * @datalen_discards: No. of pulses discarded due to invalid datalen | ||
29 | * @rssi_discards: No. of pulses discarded due to invalid RSSI | ||
30 | * @bwinfo_discards: No. of pulses discarded due to invalid BW info | ||
31 | * @pri_phy_errors: No. of pulses reported for primary channel | ||
32 | * @ext_phy_errors: No. of pulses reported for extension channel | ||
33 | * @dc_phy_errors: No. of pulses reported for primary + extension channel | ||
34 | */ | ||
35 | struct ath_dfs_stats { | ||
36 | u32 pulses_detected; | ||
37 | u32 datalen_discards; | ||
38 | u32 rssi_discards; | ||
39 | u32 bwinfo_discards; | ||
40 | u32 pri_phy_errors; | ||
41 | u32 ext_phy_errors; | ||
42 | u32 dc_phy_errors; | ||
43 | }; | ||
44 | |||
45 | #if defined(CONFIG_ATH9K_DFS_DEBUGFS) | ||
46 | |||
47 | #define DFS_STAT_INC(sc, c) (sc->debug.stats.dfs_stats.c++) | ||
48 | void ath9k_dfs_init_debug(struct ath_softc *sc); | ||
49 | |||
50 | #else | ||
51 | |||
52 | #define DFS_STAT_INC(sc, c) do { } while (0) | ||
53 | static inline void ath9k_dfs_init_debug(struct ath_softc *sc) { } | ||
54 | |||
55 | #endif /* CONFIG_ATH9K_DFS_DEBUGFS */ | ||
56 | |||
57 | #endif /* DFS_DEBUG_H */ | ||