carl9170 firmware: drop failed frames faster
[carl9170fw.git] / carlfw / include / wl.h
1 /*
2  * carl9170 firmware - used by the ar9170 wireless device
3  *
4  * WLAN
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-2011  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 #ifndef __CARL9170FW_WLAN_H
27 #define __CARL9170FW_WLAN_H
28
29 #include "config.h"
30 #include "carl9170.h"
31 #include "io.h"
32
33 struct ieee80211_hdr;
34
35 static inline __inline void set_wlan_txq_dma_addr(const unsigned int q, const uint32_t v)
36 {
37         set(AR9170_MAC_REG_DMA_TXQ_ADDR + (q << 3), v);
38 }
39
40 static inline __inline void set_wlan_txq_dma_curr_addr(const unsigned int q, const uint32_t v)
41 {
42         set(AR9170_MAC_REG_DMA_TXQ_CURR_ADDR + (q << 3), v);
43 }
44
45 static inline __inline struct dma_desc *get_wlan_txq_dma_addr(const unsigned int q)
46 {
47         return getp(AR9170_MAC_REG_DMA_TXQ_ADDR + (q << 3));
48 }
49
50 static inline __inline struct dma_desc *get_wlan_txq_addr(const unsigned int q)
51 {
52         return getp(AR9170_MAC_REG_DMA_TXQ_CURR_ADDR + (q << 3));
53 }
54
55 static inline __inline void wlan_trigger(const uint32_t queue_bit)
56 {
57         set(AR9170_MAC_REG_DMA_TRIGGER, queue_bit);
58 }
59
60 static inline __inline uint8_t ar9170_get_rx_macstatus_status(struct dma_desc *desc)
61 {
62         return *((uint8_t *) DESC_PAYLOAD_OFF(desc->lastAddr,
63                 (unsigned int) desc->lastAddr->dataSize - 1));
64 }
65
66 static inline __inline uint8_t ar9170_get_rx_macstatus_error(struct dma_desc *desc)
67 {
68         unsigned int offset;
69
70         if (desc->lastAddr->dataSize == 1) {
71                 while (desc->lastAddr != desc->nextAddr)
72                         desc = desc->nextAddr;
73
74                 offset = (unsigned int) (desc->dataSize - 1);
75         } else {
76                 desc = desc->lastAddr;
77                 offset = desc->dataSize -
78                         (sizeof(struct ar9170_rx_macstatus) -
79                          offsetof(struct ar9170_rx_macstatus, error));
80         }
81
82         return *((uint8_t *) DESC_PAYLOAD_OFF(desc, offset));
83 }
84
85 static inline __inline struct ieee80211_hdr *ar9170_get_rx_i3e(struct dma_desc *desc)
86 {
87         if (!((ar9170_get_rx_macstatus_status(desc) &
88                 AR9170_RX_STATUS_MPDU) & AR9170_RX_STATUS_MPDU_LAST)) {
89                 return (void *)(DESC_PAYLOAD_OFF(desc,
90                         offsetof(struct ar9170_rx_frame_head, i3e)));
91         } else {
92                 return (void *)(DESC_PAYLOAD_OFF(desc,
93                         offsetof(struct ar9170_rx_frame_tail, i3e)));
94         }
95 }
96
97 static inline __inline struct ar9170_rx_head *ar9170_get_rx_head(struct dma_desc *desc)
98 {
99         if (!((ar9170_get_rx_macstatus_status(desc) &
100                 AR9170_RX_STATUS_MPDU) & AR9170_RX_STATUS_MPDU_LAST)) {
101                 return (void *)((uint8_t *)DESC_PAYLOAD(desc) +
102                         offsetof(struct ar9170_rx_frame_head, phy_head));
103         } else {
104                 return (void *) NULL;
105         }
106 }
107
108 static inline __inline uint32_t ar9170_rx_to_phy(struct dma_desc *rx)
109 {
110         struct ar9170_tx_hw_phy_control phy;
111         struct ar9170_rx_head *head;
112         uint8_t mac_status;
113
114         phy.set = 0;
115
116         head = ar9170_get_rx_head(rx);
117         if (!head)
118                 return le32_to_cpu(phy.set);
119
120         mac_status = ar9170_get_rx_macstatus_status(rx);
121
122         phy.modulation = mac_status & AR9170_RX_STATUS_MODULATION;
123         phy.chains = AR9170_TX_PHY_TXCHAIN_1;
124
125         switch (phy.modulation) {
126         case AR9170_RX_STATUS_MODULATION_CCK:
127                 if (mac_status & AR9170_RX_STATUS_SHORT_PREAMBLE)
128                         phy.preamble = 1;
129
130                 switch (head->plcp[0]) {
131                 case AR9170_RX_PHY_RATE_CCK_2M:
132                         phy.mcs = AR9170_TX_PHY_RATE_CCK_2M;
133                         break;
134
135                 case AR9170_RX_PHY_RATE_CCK_5M:
136                         phy.mcs = AR9170_TX_PHY_RATE_CCK_5M;
137                         break;
138
139                 case AR9170_RX_PHY_RATE_CCK_11M:
140                         phy.mcs = AR9170_TX_PHY_RATE_CCK_11M;
141                         break;
142
143                 case AR9170_RX_PHY_RATE_CCK_1M:
144                 default:
145                         phy.mcs = AR9170_TX_PHY_RATE_CCK_1M;
146                         break;
147
148                 }
149                 break;
150
151         case AR9170_RX_STATUS_MODULATION_DUPOFDM:
152         case AR9170_RX_STATUS_MODULATION_OFDM:
153                 phy.mcs = head->plcp[0] & 0xf;
154                 break;
155
156         case AR9170_RX_STATUS_MODULATION_HT:
157                 if (head->plcp[3] & 0x80)
158                         phy.bandwidth = 2;
159
160                 if (head->plcp[6] & 0x80)
161                         phy.short_gi = 1;
162
163                 /* TODO: Enable both chains for MCS > 7 */
164                 phy.mcs = head->plcp[6] & 0x7;
165                 break;
166         }
167
168         return le32_to_cpu(phy.set);
169 }
170
171 static inline __inline unsigned int ar9170_get_rx_mpdu_len(struct dma_desc *desc)
172 {
173         /*
174          * WARNING: you have to check the error bits in macstatus first!
175          */
176
177         unsigned int mpdu_len = desc->totalLen;
178
179         mpdu_len -= sizeof(struct ar9170_rx_macstatus);
180
181         switch (ar9170_get_rx_macstatus_status(desc) & AR9170_RX_STATUS_MPDU) {
182         case AR9170_RX_STATUS_MPDU_LAST:
183                 mpdu_len -= sizeof(struct ar9170_rx_phystatus);
184                 break;
185
186         case AR9170_RX_STATUS_MPDU_SINGLE:
187                 mpdu_len -= sizeof(struct ar9170_rx_phystatus);
188
189         case AR9170_RX_STATUS_MPDU_FIRST:
190                 mpdu_len -= sizeof(struct ar9170_rx_head);
191                 break;
192
193         case AR9170_RX_STATUS_MPDU_MIDDLE:
194         default:
195                 break;
196         }
197
198         return mpdu_len;
199 }
200
201 static inline __inline bool ar9170_tx_length_check(const uint16_t len)
202 {
203         return len > (sizeof(struct carl9170_tx_superframe) + 24 +
204                          FCS_LEN);
205 }
206
207 static inline __inline struct carl9170_tx_superframe *get_super(struct dma_desc *desc)
208 {
209         return container_of(DESC_PAYLOAD(desc), struct carl9170_tx_superframe,
210                             f);
211 }
212
213 static inline __inline struct carl9170_tx_superframe *__get_super(struct dma_desc *desc)
214 {
215         return DESC_PAYLOAD(desc);
216 }
217
218 static inline __inline void hide_super(struct dma_desc *desc)
219 {
220         desc->dataAddr = (uint8_t *)
221                 (((unsigned long)(DESC_PAYLOAD(desc)) +
222                 offsetof(struct carl9170_tx_superframe, f)));
223
224         desc->dataSize -= sizeof(struct carl9170_tx_superdesc);
225         desc->totalLen -= sizeof(struct carl9170_tx_superdesc);
226 }
227
228 static inline __inline void unhide_super(struct dma_desc *desc)
229 {
230         desc->dataAddr = (uint8_t *) get_super(desc);
231         desc->dataSize += sizeof(struct carl9170_tx_superdesc);
232         desc->totalLen += sizeof(struct carl9170_tx_superdesc);
233 }
234
235 static inline __inline __hot void read_tsf(uint32_t *tsf)
236 {
237         /*
238          * "According to the [hardware] documentation:
239          *  > when TSF_LOW is read, TSF_HI is automatically concurrently
240          *  > copied into a temporary register so that an immediate read
241          *  > of TSF_HI will get the value that was present when TSF_LOW
242          *  > was read. "
243          *
244          * (David H. Lynch Jr. - mail from 2010-05-22)
245          * http://permalink.gmane.org/gmane.linux.kernel.wireless.general/51249
246          */
247
248         tsf[0] = get(AR9170_MAC_REG_TSF_L);
249         tsf[1] = get(AR9170_MAC_REG_TSF_H);
250 }
251
252 void wlan_tx(struct dma_desc *desc);
253 void wlan_timer(void);
254 void handle_wlan(void);
255
256 void wlan_cab_flush_queue(const unsigned int vif);
257 void wlan_modify_beacon(const unsigned int vif,
258                         const unsigned int bcn_addr,
259                         const unsigned int bcn_len);
260
261 void wlan_tx_complete(struct carl9170_tx_superframe *super,
262                       bool txs);
263
264 static inline void wlan_prepare_wol(void)
265 {
266         /* set filter policy to: discard everything */
267         fw.wlan.rx_filter = CARL9170_RX_FILTER_EVERYTHING;
268
269         /* reenable rx dma */
270         wlan_trigger(AR9170_DMA_TRIGGER_RXQ);
271 }
272
273 static inline void __check_wlantx(void)
274 {
275         BUILD_BUG_ON(CARL9170_TX_SUPERDESC_LEN & 3);
276         BUILD_BUG_ON(sizeof(struct carl9170_tx_superdesc) != CARL9170_TX_SUPERDESC_LEN);
277         BUILD_BUG_ON(sizeof(struct _carl9170_tx_superdesc) != CARL9170_TX_SUPERDESC_LEN);
278         BUILD_BUG_ON(sizeof(struct _carl9170_tx_superframe) != CARL9170_TX_SUPERFRAME_LEN);
279         BUILD_BUG_ON((offsetof(struct carl9170_tx_superframe, f) & 3) != 0);
280         BUILD_BUG_ON(offsetof(struct _carl9170_tx_superframe, f) !=
281                      (offsetof(struct _carl9170_tx_superframe, f)));
282         BUILD_BUG_ON(sizeof(struct ar9170_tx_hwdesc) != AR9170_TX_HWDESC_LEN);
283         BUILD_BUG_ON(sizeof(struct _ar9170_tx_hwdesc) != AR9170_TX_HWDESC_LEN);
284         BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != AR9170_RX_HEAD_LEN);
285         BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != AR9170_RX_PHYSTATUS_LEN);
286         BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != AR9170_RX_MACSTATUS_LEN);
287 }
288
289 #endif /* __CARL9170FW_WLAN_H */