ieee80211: share 802.11 unit conversion helpers
[carl9170fw.git] / carlfw / src / wlan.c
1 /*
2  * carl9170 firmware - used by the ar9170 wireless device
3  *
4  * Interface to the WLAN part of the chip
5  *
6  * Copyright (c) 2000-2005 ZyDAS Technology Corporation
7  * Copyright (c) 2007-2009 Atheros Communications, Inc.
8  * Copyright    2009    Johannes Berg <johannes@sipsolutions.net>
9  * Copyright 2009-2012  Christian Lamparter <chunkeey@googlemail.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; If not, see <http://www.gnu.org/licenses/>.
23  */
24
25 #include "carl9170.h"
26 #include "shared/phy.h"
27 #include "hostif.h"
28 #include "timer.h"
29 #include "wl.h"
30 #include "printf.h"
31 #include "rf.h"
32 #include "linux/ieee80211.h"
33 #include "wol.h"
34
35 #ifdef CONFIG_CARL9170FW_DEBUG
36 static void wlan_dump_queue(unsigned int qidx)
37 {
38
39         struct dma_desc *desc;
40         struct carl9170_tx_superframe *super;
41         int entries = 0;
42
43         __for_each_desc(desc, &fw.wlan.tx_queue[qidx]) {
44                 super = get_super(desc);
45                 DBG("%d: %p s:%x c:%x tl:%x ds:%x n:%p l:%p ", entries, desc,
46                     desc->status, desc->ctrl, desc->totalLen,
47                     desc->dataSize, desc->nextAddr, desc->lastAddr);
48
49                 DBG("c:%x tr:%d ri:%d l:%x m:%x p:%x fc:%x",
50                     super->s.cookie, super->s.cnt, super->s.rix,
51                     super->f.hdr.length, super->f.hdr.mac.set,
52                     (unsigned int) le32_to_cpu(super->f.hdr.phy.set),
53                     super->f.data.i3e.frame_control);
54
55                 entries++;
56         }
57
58         desc = (struct dma_desc *)get_wlan_txq_addr(qidx);
59
60         DBG("Queue: %d: te:%d td:%d h:%p c:%p t:%p",
61             qidx, entries, queue_len(&fw.wlan.tx_queue[qidx]),
62             fw.wlan.tx_queue[qidx].head,
63             desc, fw.wlan.tx_queue[qidx].terminator);
64
65         DBG("HW: t:%x s:%x ac:%x c:%x",
66             (unsigned int) get(AR9170_MAC_REG_DMA_TRIGGER),
67             (unsigned int) get(AR9170_MAC_REG_DMA_STATUS),
68             (unsigned int) get(AR9170_MAC_REG_AMPDU_COUNT),
69             (unsigned int) get(AR9170_MAC_REG_DMA_TXQX_ADDR_CURR));
70 }
71 #endif /* CONFIG_CARL9170FW_DEBUG */
72
73 static void wlan_check_rx_overrun(void)
74 {
75         uint32_t overruns, total;
76
77         fw.tally.rx_total += total = get(AR9170_MAC_REG_RX_TOTAL);
78         fw.tally.rx_overrun += overruns = get(AR9170_MAC_REG_RX_OVERRUN);
79         if (unlikely(overruns)) {
80                 if (overruns == total) {
81                         DBG("RX Overrun");
82                         fw.wlan.mac_reset++;
83                 }
84
85                 wlan_trigger(AR9170_DMA_TRIGGER_RXQ);
86         }
87 }
88
89 static void handle_beacon_config(void)
90 {
91         uint32_t bcn_count;
92
93         bcn_count = get(AR9170_MAC_REG_BCN_COUNT);
94         send_cmd_to_host(4, CARL9170_RSP_BEACON_CONFIG, 0x00,
95                          (uint8_t *) &bcn_count);
96 }
97
98 static void handle_pretbtt(void)
99 {
100         fw.wlan.cab_flush_time = get_clock_counter();
101
102 #ifdef CONFIG_CARL9170FW_RADIO_FUNCTIONS
103         rf_psm();
104
105         send_cmd_to_host(4, CARL9170_RSP_PRETBTT, 0x00,
106                          (uint8_t *) &fw.phy.psm.state);
107 #endif /* CONFIG_CARL9170FW_RADIO_FUNCTIONS */
108 }
109
110 static void handle_atim(void)
111 {
112         send_cmd_to_host(0, CARL9170_RSP_ATIM, 0x00, NULL);
113 }
114
115 #ifdef CONFIG_CARL9170FW_DEBUG
116 static void handle_qos(void)
117 {
118         /*
119          * What is the QoS Bit used for?
120          * Is it only an indicator for TXOP & Burst, or
121          * should we do something here?
122          */
123 }
124
125 static void handle_radar(void)
126 {
127         send_cmd_to_host(0, CARL9170_RSP_RADAR, 0x00, NULL);
128 }
129 #endif /* CONFIG_CARL9170FW_DEBUG */
130
131 static void wlan_janitor(void)
132 {
133         wlan_send_buffered_cab();
134
135         wlan_send_buffered_tx_status();
136
137         wlan_send_buffered_ba();
138
139         wol_janitor();
140 }
141
142 void handle_wlan(void)
143 {
144         uint32_t intr;
145
146         intr = get(AR9170_MAC_REG_INT_CTRL);
147         /* ACK Interrupt */
148         set(AR9170_MAC_REG_INT_CTRL, intr);
149
150 #define HANDLER(intr, flag, func)                       \
151         do {                                            \
152                 if ((intr & flag) != 0) {               \
153                         func();                         \
154                 }                                       \
155         } while (0)
156
157         intr |= fw.wlan.soft_int;
158         fw.wlan.soft_int = 0;
159
160         HANDLER(intr, AR9170_MAC_INT_PRETBTT, handle_pretbtt);
161
162         HANDLER(intr, AR9170_MAC_INT_ATIM, handle_atim);
163
164         HANDLER(intr, AR9170_MAC_INT_RXC, handle_wlan_rx);
165
166         HANDLER(intr, (AR9170_MAC_INT_TXC | AR9170_MAC_INT_RETRY_FAIL),
167                 handle_wlan_tx_completion);
168
169 #ifdef CONFIG_CARL9170FW_DEBUG
170         HANDLER(intr, AR9170_MAC_INT_QOS, handle_qos);
171
172         HANDLER(intr, AR9170_MAC_INT_RADAR, handle_radar);
173 #endif /* CONFIG_CARL9170FW_DEBUG */
174
175         HANDLER(intr, AR9170_MAC_INT_CFG_BCN, handle_beacon_config);
176
177         if (unlikely(intr))
178                 DBG("Unhandled Interrupt %x\n", (unsigned int) intr);
179
180         wlan_janitor();
181
182 #undef HANDLER
183 }
184
185 enum {
186         CARL9170FW_TX_MAC_BUMP = 4,
187         CARL9170FW_TX_MAC_DEBUG = 6,
188         CARL9170FW_TX_MAC_RESET = 7,
189 };
190
191 static void wlan_check_hang(void)
192 {
193         struct dma_desc *desc;
194         int i;
195
196         for (i = AR9170_TXQ_SPECIAL; i >= AR9170_TXQ0; i--) {
197                 if (queue_empty(&fw.wlan.tx_queue[i])) {
198                         /* Nothing to do here... move along */
199                         continue;
200                 }
201
202                 /* fetch the current DMA queue position */
203                 desc = (struct dma_desc *)get_wlan_txq_addr(i);
204
205                 /* Stuck frame detection */
206                 if (unlikely(DESC_PAYLOAD(desc) == fw.wlan.last_super[i])) {
207                         fw.wlan.last_super_num[i]++;
208
209                         if (unlikely(fw.wlan.last_super_num[i] >= CARL9170FW_TX_MAC_RESET)) {
210                                 /*
211                                  * schedule MAC reset (aka OFF/ON => dead)
212                                  *
213                                  * This will almost certainly kill
214                                  * the device for good, but it's the
215                                  * recommended thing to do...
216                                  */
217
218                                 fw.wlan.mac_reset++;
219                         }
220
221 #ifdef CONFIG_CARL9170FW_DEBUG
222                         if (unlikely(fw.wlan.last_super_num[i] >= CARL9170FW_TX_MAC_DEBUG)) {
223                                 /*
224                                  * Sigh, the queue is almost certainly
225                                  * dead. Dump the queue content to the
226                                  * user, maybe we find out why it got
227                                  * so stuck.
228                                  */
229
230                                 wlan_dump_queue(i);
231                         }
232 #endif /* CONFIG_CARL9170FW_DEBUG */
233
234 #ifdef CONFIG_CARL9170FW_DMA_QUEUE_BUMP
235                         if (unlikely(fw.wlan.last_super_num[i] >= CARL9170FW_TX_MAC_BUMP)) {
236                                 /*
237                                  * Hrrm, bump the queue a bit.
238                                  * maybe this will get it going again.
239                                  */
240
241                                 wlan_dma_bump(i);
242                                 wlan_trigger(BIT(i));
243                         }
244 #endif /* CONFIG_CARL9170FW_DMA_QUEUE_BUMP */
245                 } else {
246                         /* Nothing stuck */
247                         fw.wlan.last_super[i] = DESC_PAYLOAD(desc);
248                         fw.wlan.last_super_num[i] = 0;
249                 }
250         }
251 }
252
253 #ifdef CONFIG_CARL9170FW_FW_MAC_RESET
254 /*
255  * NB: Resetting the MAC is a two-edged sword.
256  * On most occasions, it does what it is supposed to do.
257  * But there is a chance that this will make it
258  * even worse and the radio dies silently.
259  */
260 static void wlan_mac_reset(void)
261 {
262         uint32_t val;
263         uint32_t agg_wait_counter;
264         uint32_t agg_density;
265         uint32_t bcn_start_addr;
266         uint32_t rctl, rcth;
267         uint32_t cam_mode;
268         uint32_t ack_power;
269         uint32_t rts_cts_tpc;
270         uint32_t rts_cts_rate;
271         int i;
272
273 #ifdef CONFIG_CARL9170FW_RADIO_FUNCTIONS
274         uint32_t rx_BB;
275 #endif /* CONFIG_CARL9170FW_RADIO_FUNCTIONS */
276
277 #ifdef CONFIG_CARL9170FW_NOISY_MAC_RESET
278         INFO("MAC RESET");
279 #endif /* CONFIG_CARL9170FW_NOISY_MAC_RESET */
280
281         /* Save aggregation parameters */
282         agg_wait_counter = get(AR9170_MAC_REG_AMPDU_FACTOR);
283         agg_density = get(AR9170_MAC_REG_AMPDU_DENSITY);
284
285         bcn_start_addr = get(AR9170_MAC_REG_BCN_ADDR);
286
287         cam_mode = get(AR9170_MAC_REG_CAM_MODE);
288         rctl = get(AR9170_MAC_REG_CAM_ROLL_CALL_TBL_L);
289         rcth = get(AR9170_MAC_REG_CAM_ROLL_CALL_TBL_H);
290
291         ack_power = get(AR9170_MAC_REG_ACK_TPC);
292         rts_cts_tpc = get(AR9170_MAC_REG_RTS_CTS_TPC);
293         rts_cts_rate = get(AR9170_MAC_REG_RTS_CTS_RATE);
294
295 #ifdef CONFIG_CARL9170FW_RADIO_FUNCTIONS
296         /* 0x1c8960 write only */
297         rx_BB = get(AR9170_PHY_REG_SWITCH_CHAIN_0);
298 #endif /* CONFIG_CARL9170FW_RADIO_FUNCTIONS */
299
300         /* TX/RX must be stopped by now */
301         val = get(AR9170_MAC_REG_POWER_STATE_CTRL);
302
303         val |= AR9170_MAC_POWER_STATE_CTRL_RESET;
304
305         /*
306          * Manipulate CCA threshold to stop transmission
307          *
308          * set(AR9170_PHY_REG_CCA_THRESHOLD, 0x300);
309          */
310
311         /*
312          * check Rx state in 0(idle) 9(disable)
313          *
314          * chState = (get(AR9170_MAC_REG_MISC_684) >> 16) & 0xf;
315          * while( (chState != 0) && (chState != 9)) {
316          *      chState = (get(AR9170_MAC_REG_MISC_684) >> 16) & 0xf;
317          * }
318          */
319
320         set(AR9170_MAC_REG_POWER_STATE_CTRL, val);
321
322         delay(2);
323
324         /* Restore aggregation parameters */
325         set(AR9170_MAC_REG_AMPDU_FACTOR, agg_wait_counter);
326         set(AR9170_MAC_REG_AMPDU_DENSITY, agg_density);
327
328         set(AR9170_MAC_REG_BCN_ADDR, bcn_start_addr);
329         set(AR9170_MAC_REG_CAM_MODE, cam_mode);
330         set(AR9170_MAC_REG_CAM_ROLL_CALL_TBL_L, rctl);
331         set(AR9170_MAC_REG_CAM_ROLL_CALL_TBL_H, rcth);
332
333         set(AR9170_MAC_REG_RTS_CTS_TPC, rts_cts_tpc);
334         set(AR9170_MAC_REG_ACK_TPC, ack_power);
335         set(AR9170_MAC_REG_RTS_CTS_RATE, rts_cts_rate);
336
337 #ifdef CONFIG_CARL9170FW_RADIO_FUNCTIONS
338         set(AR9170_PHY_REG_SWITCH_CHAIN_2, rx_BB);
339 #endif /* CONFIG_CARL9170FW_RADIO_FUNCTIONS */
340
341         /*
342          * Manipulate CCA threshold to resume transmission
343          *
344          * set(AR9170_PHY_REG_CCA_THRESHOLD, 0x0);
345          */
346
347         val = AR9170_DMA_TRIGGER_RXQ;
348         /* Reinitialize all WLAN TX DMA queues. */
349         for (i = AR9170_TXQ_SPECIAL; i >= AR9170_TXQ0; i--) {
350                 struct dma_desc *iter;
351
352                 __for_each_desc_bits(iter, &fw.wlan.tx_queue[i], AR9170_OWN_BITS_SW);
353
354                 /* kill the stuck frame */
355                 if (!is_terminator(&fw.wlan.tx_queue[i], iter) &&
356                     fw.wlan.last_super_num[i] >= CARL9170FW_TX_MAC_RESET &&
357                     fw.wlan.last_super[i] == DESC_PAYLOAD(iter)) {
358                         struct carl9170_tx_superframe *super = get_super(iter);
359
360                         iter->status = AR9170_OWN_BITS_SW;
361                         /*
362                          * Mark the frame as failed.
363                          * The BAFAIL flag allows the frame to sail through
364                          * wlan_tx_status without much "unstuck" trouble.
365                          */
366                         iter->ctrl &= ~(AR9170_CTRL_FAIL);
367                         iter->ctrl |= AR9170_CTRL_BAFAIL;
368
369                         super->s.cnt = CARL9170_TX_MAX_RATE_TRIES;
370                         super->s.rix = CARL9170_TX_MAX_RETRY_RATES;
371
372                         fw.wlan.last_super_num[i] = 0;
373                         fw.wlan.last_super[i] = NULL;
374                         iter = iter->lastAddr->nextAddr;
375                 }
376
377                 set_wlan_txq_dma_addr(i, (uint32_t) iter);
378                 if (!is_terminator(&fw.wlan.tx_queue[i], iter))
379                         val |= BIT(i);
380
381                 DBG("Q:%d l:%d h:%p t:%p cu:%p it:%p ct:%x st:%x\n", i, queue_len(&fw.wlan.tx_queue[i]),
382                      fw.wlan.tx_queue[i].head, fw.wlan.tx_queue[i].terminator,
383                      get_wlan_txq_addr(i), iter, iter->ctrl, iter->status);
384         }
385
386         fw.wlan.soft_int |= AR9170_MAC_INT_RXC | AR9170_MAC_INT_TXC |
387                             AR9170_MAC_INT_RETRY_FAIL;
388
389         set(AR9170_MAC_REG_DMA_RXQ_ADDR, (uint32_t) fw.wlan.rx_queue.head);
390         wlan_trigger(val);
391 }
392 #else
393 static void wlan_mac_reset(void)
394 {
395         /* The driver takes care of reinitializing the device */
396         BUG("MAC RESET");
397 }
398 #endif /* CONFIG_CARL9170FW_FW_MAC_RESET */
399
400 void __cold wlan_timer(void)
401 {
402         unsigned int cached_mac_reset;
403
404         cached_mac_reset = fw.wlan.mac_reset;
405
406         /* TX Queue Hang check */
407         wlan_check_hang();
408
409         /* RX Overrun check */
410         wlan_check_rx_overrun();
411
412         if (unlikely(fw.wlan.mac_reset >= CARL9170_MAC_RESET_RESET)) {
413                 wlan_mac_reset();
414                 fw.wlan.mac_reset = CARL9170_MAC_RESET_OFF;
415         } else {
416                 if (fw.wlan.mac_reset && cached_mac_reset == fw.wlan.mac_reset)
417                         fw.wlan.mac_reset--;
418         }
419 }