mac80211: Update to version 4.19.221
[librecmc/librecmc.git] / package / kernel / mac80211 / patches / ath / 551-ath9k_ubnt_uap_plus_hsr.patch
1 --- a/drivers/net/wireless/ath/ath9k/channel.c
2 +++ b/drivers/net/wireless/ath/ath9k/channel.c
3 @@ -15,6 +15,8 @@
4   */
5  
6  #include "ath9k.h"
7 +#include <linux/ath9k_platform.h>
8 +#include "hsr.h"
9  
10  /* Set/change channels.  If the channel is really being changed, it's done
11   * by reseting the chip.  To accomplish this we must first cleanup any pending
12 @@ -22,6 +24,7 @@
13   */
14  static int ath_set_channel(struct ath_softc *sc)
15  {
16 +       struct ath9k_platform_data *pdata = sc->dev->platform_data;
17         struct ath_hw *ah = sc->sc_ah;
18         struct ath_common *common = ath9k_hw_common(ah);
19         struct ieee80211_hw *hw = sc->hw;
20 @@ -42,6 +45,11 @@ static int ath_set_channel(struct ath_so
21         ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n",
22                 chan->center_freq, chandef->width);
23  
24 +       if (pdata && pdata->ubnt_hsr) {
25 +               ath9k_hsr_enable(ah, chandef->width, chan->center_freq);
26 +               ath9k_hsr_status(ah);
27 +       }
28 +
29         /* update survey stats for the old channel before switching */
30         spin_lock_irqsave(&common->cc_lock, flags);
31         ath_update_survey_stats(sc);
32 --- /dev/null
33 +++ b/drivers/net/wireless/ath/ath9k/hsr.c
34 @@ -0,0 +1,247 @@
35 +/*
36 + *
37 + * The MIT License (MIT)
38 + *
39 + * Copyright (c) 2015 Kirill Berezin
40 + *
41 + * Permission is hereby granted, free of charge, to any person obtaining a copy
42 + * of this software and associated documentation files (the "Software"), to deal
43 + * in the Software without restriction, including without limitation the rights
44 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
45 + * copies of the Software, and to permit persons to whom the Software is
46 + * furnished to do so, subject to the following conditions:
47 + *
48 + * The above copyright notice and this permission notice shall be included in
49 + * all copies or substantial portions of the Software.
50 + *
51 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
54 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
56 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
57 + * SOFTWARE.
58 + *
59 + */
60 +
61 +#include <linux/io.h>
62 +#include <linux/slab.h>
63 +#include <linux/module.h>
64 +#include <linux/time.h>
65 +#include <linux/bitops.h>
66 +#include <linux/etherdevice.h>
67 +#include <linux/rtnetlink.h>
68 +#include <asm/unaligned.h>
69 +
70 +#include "hw.h"
71 +#include "ath9k.h"
72 +
73 +#define HSR_GPIO_CSN 8
74 +#define HSR_GPIO_CLK 6
75 +#define HSR_GPIO_DOUT 7
76 +#define HSR_GPIO_DIN 5
77 +
78 +/* delays are in useconds */
79 +#define HSR_DELAY_HALF_TICK 100
80 +#define HSR_DELAY_PRE_WRITE 75
81 +#define HSR_DELAY_FINAL 20000
82 +#define HSR_DELAY_TRAILING 200
83 +
84 +void ath9k_hsr_init(struct ath_hw *ah)
85 +{
86 +       ath9k_hw_gpio_request_in(ah, HSR_GPIO_DIN, NULL);
87 +       ath9k_hw_gpio_request_out(ah, HSR_GPIO_CSN, NULL,
88 +                                 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
89 +       ath9k_hw_gpio_request_out(ah, HSR_GPIO_CLK, NULL,
90 +                                 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
91 +       ath9k_hw_gpio_request_out(ah, HSR_GPIO_DOUT, NULL,
92 +                                 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
93 +
94 +       ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1);
95 +       ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
96 +       ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, 0);
97 +
98 +       udelay(HSR_DELAY_TRAILING);
99 +}
100 +
101 +static u32 ath9k_hsr_write_byte(struct ath_hw *ah, int delay, u32 value)
102 +{
103 +       struct ath_common *common = ath9k_hw_common(ah);
104 +       int i;
105 +       u32 rval = 0;
106 +
107 +       udelay(delay);
108 +
109 +       ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
110 +       udelay(HSR_DELAY_HALF_TICK);
111 +
112 +       ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 0);
113 +       udelay(HSR_DELAY_HALF_TICK);
114 +
115 +       for (i = 0; i < 8; ++i) {
116 +               rval = rval << 1;
117 +
118 +               /* pattern is left to right, that is 7-th bit runs first */
119 +               ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, (value >> (7 - i)) & 0x1);
120 +               udelay(HSR_DELAY_HALF_TICK);
121 +
122 +               ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 1);
123 +               udelay(HSR_DELAY_HALF_TICK);
124 +
125 +               rval |= ath9k_hw_gpio_get(ah, HSR_GPIO_DIN);
126 +
127 +               ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
128 +               udelay(HSR_DELAY_HALF_TICK);
129 +       }
130 +
131 +       ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1);
132 +       udelay(HSR_DELAY_HALF_TICK);
133 +
134 +       ath_dbg(common, CONFIG, "ath9k_hsr_write_byte: write byte %d return value is %d %c\n",
135 +               value, rval, rval > 32 ? rval : '-');
136 +
137 +       return rval & 0xff;
138 +}
139 +
140 +static int ath9k_hsr_write_a_chain(struct ath_hw *ah, char *chain, int items)
141 +{
142 +       int status = 0;
143 +       int i = 0;
144 +       int err;
145 +
146 +       /* a preamble */
147 +       ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
148 +       status = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
149 +
150 +       /* clear HSR's reply buffer */
151 +       if (status) {
152 +               int loop = 0;
153 +
154 +               for (loop = 0; (loop < 42) && status; ++loop)
155 +                       status = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE,
156 +                                                     0);
157 +
158 +               if (loop >= 42) {
159 +                       ATH_DBG_WARN(1,
160 +                                    "ath9k_hsr_write_a_chain: can't clear an output buffer after a 42 cycles.\n");
161 +                       return -1;
162 +               }
163 +       }
164 +
165 +       for (i = 0; (i < items) && (chain[i] != 0); ++i)
166 +               ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, (u32)chain[i]);
167 +
168 +       ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
169 +       mdelay(HSR_DELAY_FINAL / 1000);
170 +
171 +       /* reply */
172 +       memset(chain, 0, items);
173 +
174 +       ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
175 +       udelay(HSR_DELAY_TRAILING);
176 +
177 +       for (i = 0; i < (items - 1); ++i) {
178 +               u32 ret;
179 +
180 +               ret = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
181 +               if (ret != 0)
182 +                       chain[i] = (char)ret;
183 +               else
184 +                       break;
185 +
186 +               udelay(HSR_DELAY_TRAILING);
187 +       }
188 +
189 +       if (i <= 1)
190 +               return 0;
191 +
192 +       err = kstrtoint(chain + 1, 10, &i);
193 +       if (err)
194 +               return err;
195 +
196 +       return i;
197 +}
198 +
199 +int ath9k_hsr_disable(struct ath_hw *ah)
200 +{
201 +       char cmd[10] = {'b', '4', '0', 0, 0, 0, 0, 0, 0, 0};
202 +       int ret;
203 +
204 +       ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
205 +       if ((ret > 0) && (*cmd == 'B'))
206 +               return 0;
207 +
208 +       return -1;
209 +}
210 +
211 +int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq)
212 +{
213 +       char cmd[10];
214 +       int ret;
215 +
216 +       /* Bandwidth argument is 0 sometimes. Assume default 802.11bgn
217 +        * 20MHz on invalid values
218 +        */
219 +       if ((bw != 5) && (bw != 10) && (bw != 20) && (bw != 40))
220 +               bw = 20;
221 +
222 +       memset(cmd, 0, sizeof(cmd));
223 +       *cmd = 'b';
224 +       snprintf(cmd + 1, 3, "%02d", bw);
225 +
226 +       ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
227 +       if ((*cmd != 'B') || (ret != bw)) {
228 +               ATH_DBG_WARN(1,
229 +                            "ath9k_hsr_enable: failed changing bandwidth -> set (%d,%d) reply (%d, %d)\n",
230 +                            'b', bw, *cmd, ret);
231 +               return -1;
232 +       }
233 +
234 +       memset(cmd, 0, sizeof(cmd));
235 +       *cmd = 'x';
236 +       ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
237 +       if (*cmd != 'X') {
238 +               ATH_DBG_WARN(1,
239 +                            "ath9k_hsr_enable: failed 'x' command -> reply (%d, %d)\n",
240 +                            *cmd, ret);
241 +               return -1;
242 +       }
243 +
244 +       memset(cmd, 0, sizeof(cmd));
245 +       *cmd = 'm';
246 +       ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
247 +       if (*cmd != 'M') {
248 +               ATH_DBG_WARN(1,
249 +                            "ath9k_hsr_enable: failed 'm' command -> reply (%d, %d)\n",
250 +                            *cmd, ret);
251 +               return  -1;
252 +       }
253 +
254 +       memset(cmd, 0, sizeof(cmd));
255 +       *cmd = 'f';
256 +       snprintf(cmd + 1, 6, "%05d", fq);
257 +       ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
258 +       if ((*cmd != 'F') && (ret != fq)) {
259 +               ATH_DBG_WARN(1,
260 +                            "ath9k_hsr_enable: failed set frequency -> reply (%d, %d)\n",
261 +                            *cmd, ret);
262 +               return -1;
263 +       }
264 +
265 +       return 0;
266 +}
267 +
268 +int ath9k_hsr_status(struct ath_hw *ah)
269 +{
270 +       char cmd[10] = {'s', 0, 0, 0, 0, 0, 0, 0, 0, 0};
271 +       int ret;
272 +
273 +       ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
274 +       if (*cmd != 'S') {
275 +               ATH_DBG_WARN(1, "ath9k_hsr_status: returned %d,%d\n", *cmd,
276 +                            ret);
277 +               return -1;
278 +       }
279 +
280 +       return 0;
281 +}
282 --- /dev/null
283 +++ b/drivers/net/wireless/ath/ath9k/hsr.h
284 @@ -0,0 +1,48 @@
285 +/*
286 + * The MIT License (MIT)
287 + *
288 + * Copyright (c) 2015 Kirill Berezin
289 + *
290 + * Permission is hereby granted, free of charge, to any person obtaining a copy
291 + * of this software and associated documentation files (the "Software"), to deal
292 + * in the Software without restriction, including without limitation the rights
293 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
294 + * copies of the Software, and to permit persons to whom the Software is
295 + * furnished to do so, subject to the following conditions:
296 + *
297 + * The above copyright notice and this permission notice shall be included in
298 + * all copies or substantial portions of the Software.
299 + *
300 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
301 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
302 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
303 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
304 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
305 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
306 + * SOFTWARE.
307 + */
308 +
309 +#ifndef HSR_H
310 +#define HSR_H
311 +
312 +#ifdef CPTCFG_ATH9K_UBNTHSR
313 +
314 +void ath9k_hsr_init(struct ath_hw *ah);
315 +int ath9k_hsr_disable(struct ath_hw *ah);
316 +int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq);
317 +int ath9k_hsr_status(struct ath_hw *ah);
318 +
319 +#else
320 +static inline void ath9k_hsr_init(struct ath_hw *ah) {}
321 +
322 +static inline int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq)
323 +{
324 +       return 0;
325 +}
326 +
327 +static inline int ath9k_hsr_disable(struct ath_hw *ah) { return 0; }
328 +static inline int ath9k_hsr_status(struct ath_hw *ah) { return 0; }
329 +
330 +#endif
331 +
332 +#endif /* HSR_H */
333 --- a/drivers/net/wireless/ath/ath9k/main.c
334 +++ b/drivers/net/wireless/ath/ath9k/main.c
335 @@ -16,8 +16,10 @@
336  
337  #include <linux/nl80211.h>
338  #include <linux/delay.h>
339 +#include <linux/ath9k_platform.h>
340  #include "ath9k.h"
341  #include "btcoex.h"
342 +#include "hsr.h"
343  
344  u8 ath9k_parse_mpdudensity(u8 mpdudensity)
345  {
346 @@ -656,6 +658,7 @@ void ath_reset_work(struct work_struct *
347  static int ath9k_start(struct ieee80211_hw *hw)
348  {
349         struct ath_softc *sc = hw->priv;
350 +       struct ath9k_platform_data *pdata = sc->dev->platform_data;
351         struct ath_hw *ah = sc->sc_ah;
352         struct ath_common *common = ath9k_hw_common(ah);
353         struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan;
354 @@ -734,6 +737,11 @@ static int ath9k_start(struct ieee80211_
355                                           AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
356         }
357  
358 +       if (pdata && pdata->ubnt_hsr) {
359 +               ath9k_hsr_init(ah);
360 +               ath9k_hsr_disable(ah);
361 +       }
362 +
363         /*
364          * Reset key cache to sane defaults (all entries cleared) instead of
365          * semi-random values after suspend/resume.
366 --- a/drivers/net/wireless/ath/ath9k/Makefile
367 +++ b/drivers/net/wireless/ath/ath9k/Makefile
368 @@ -17,6 +17,7 @@ ath9k-$(CPTCFG_ATH9K_DFS_CERTIFIED) += d
369  ath9k-$(CPTCFG_ATH9K_TX99) += tx99.o
370  ath9k-$(CPTCFG_ATH9K_WOW) += wow.o
371  ath9k-$(CPTCFG_ATH9K_HWRNG) += rng.o
372 +ath9k-$(CPTCFG_ATH9K_UBNTHSR) += hsr.o
373  
374  ath9k-$(CPTCFG_ATH9K_DEBUGFS) += debug.o
375  
376 --- a/include/linux/ath9k_platform.h
377 +++ b/include/linux/ath9k_platform.h
378 @@ -53,6 +53,8 @@ struct ath9k_platform_data {
379         unsigned num_btns;
380         const struct gpio_keys_button *btns;
381         unsigned btn_poll_interval;
382 +
383 +       bool ubnt_hsr;
384  };
385  
386  #endif /* _LINUX_ATH9K_PLATFORM_H */
387 --- a/local-symbols
388 +++ b/local-symbols
389 @@ -110,6 +110,7 @@ ATH9K_WOW=
390  ATH9K_RFKILL=
391  ATH9K_CHANNEL_CONTEXT=
392  ATH9K_PCOEM=
393 +ATH9K_UBNTHSR=
394  ATH9K_HTC=
395  ATH9K_HTC_DEBUGFS=
396  ATH9K_HWRNG=
397 --- a/drivers/net/wireless/ath/ath9k/Kconfig
398 +++ b/drivers/net/wireless/ath/ath9k/Kconfig
399 @@ -59,6 +59,19 @@ config ATH9K_AHB
400           Say Y, if you have a SoC with a compatible built-in
401           wireless MAC. Say N if unsure.
402  
403 +config ATH9K_UBNTHSR
404 +       bool "Ubiquiti UniFi Outdoor Plus HSR support"
405 +       depends on ATH9K
406 +       ---help---
407 +         This options enables code to control the HSR RF
408 +         filter in the receive path of the Ubiquiti UniFi
409 +         Outdoor Plus access point.
410 +
411 +         Say Y if you want to use the access point. The
412 +         code will only be used if the device is detected,
413 +         so it does not harm other setup other than occupying
414 +         a bit of memory.
415 +
416  config ATH9K_DEBUGFS
417         bool "Atheros ath9k debugging"
418         depends on ATH9K && DEBUG_FS