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