mac80211: add experimental support for rt2800 devices (based on a patch by Hauke...
[oweals/openwrt.git] / package / mac80211 / patches / 310-rt2x00_implement_support_for_802.11n.patch
1 From: Ivo van Doorn <IvDoorn@gmail.com>
2 Date: Sun, 28 Dec 2008 12:48:46 +0000 (+0100)
3 Subject: rt2x00: Implement support for 802.11n
4 X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fivd%2Frt2x00.git;a=commitdiff_plain;h=1ddf4bdad5f51a799ee580e125dda19dd18daa39
5
6 rt2x00: Implement support for 802.11n
7
8 Extend rt2x00lib capabilities to support 802.11n,
9 it still lacks aggregation support, but that can
10 be added in the future.
11
12 Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
13 ---
14
15 --- a/drivers/net/wireless/rt2x00/Makefile
16 +++ b/drivers/net/wireless/rt2x00/Makefile
17 @@ -8,6 +8,7 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO)   +=
18  rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL)  += rt2x00rfkill.o
19  rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE)        += rt2x00firmware.o
20  rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS)    += rt2x00leds.o
21 +rt2x00lib-$(CONFIG_RT2X00_LIB_HT)      += rt2x00ht.o
22  
23  obj-$(CONFIG_RT2X00_LIB)               += rt2x00lib.o
24  obj-$(CONFIG_RT2X00_LIB_PCI)           += rt2x00pci.o
25 --- a/drivers/net/wireless/rt2x00/rt2x00.h
26 +++ b/drivers/net/wireless/rt2x00/rt2x00.h
27 @@ -107,6 +107,7 @@
28   */
29  #define ACK_SIZE               14
30  #define IEEE80211_HEADER       24
31 +#define AGGREGATION_SIZE       3840
32  #define PLCP                   48
33  #define BEACON                 100
34  #define PREAMBLE               144
35 @@ -356,6 +357,7 @@ static inline struct rt2x00_intf* vif_to
36   *     for @tx_power_a, @tx_power_bg and @channels.
37   * @channels: Device/chipset specific channel values (See &struct rf_channel).
38   * @channels_info: Additional information for channels (See &struct channel_info).
39 + * @ht: Driver HT Capabilities (See &ieee80211_sta_ht_cap).
40   */
41  struct hw_mode_spec {
42         unsigned int supported_bands;
43 @@ -369,6 +371,8 @@ struct hw_mode_spec {
44         unsigned int num_channels;
45         const struct rf_channel *channels;
46         const struct channel_info *channels_info;
47 +
48 +       struct ieee80211_sta_ht_cap ht;
49  };
50  
51  /*
52 @@ -603,6 +607,7 @@ enum rt2x00_flags {
53         CONFIG_EXTERNAL_LNA_BG,
54         CONFIG_DOUBLE_ANTENNA,
55         CONFIG_DISABLE_LINK_TUNING,
56 +       CONFIG_CHANNEL_HT40,
57  };
58  
59  /*
60 --- a/drivers/net/wireless/rt2x00/rt2x00config.c
61 +++ b/drivers/net/wireless/rt2x00/rt2x00config.c
62 @@ -173,6 +173,12 @@ void rt2x00lib_config(struct rt2x00_dev 
63         libconf.conf = conf;
64  
65         if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {
66 +               if ((conf->ht.channel_type == NL80211_CHAN_HT40MINUS) ||
67 +                   (conf->ht.channel_type == NL80211_CHAN_HT40PLUS))
68 +                       __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
69 +               else
70 +                       __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
71 +
72                 memcpy(&libconf.rf,
73                        &rt2x00dev->spec.channels[conf->channel->hw_value],
74                        sizeof(libconf.rf));
75 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
76 +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
77 @@ -384,7 +384,9 @@ void rt2x00lib_rxdone(struct rt2x00_dev 
78                 if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) &&
79                      (rate->plcp == rxdesc.signal)) ||
80                     ((rxdesc.dev_flags & RXDONE_SIGNAL_BITRATE) &&
81 -                     (rate->bitrate == rxdesc.signal))) {
82 +                     (rate->bitrate == rxdesc.signal)) ||
83 +                   ((rxdesc.dev_flags & RXDONE_SIGNAL_MCS) &&
84 +                     (rate->mcs == rxdesc.signal))) {
85                         idx = i;
86                         break;
87                 }
88 @@ -439,72 +441,84 @@ const struct rt2x00_rate rt2x00_supporte
89                 .bitrate = 10,
90                 .ratemask = BIT(0),
91                 .plcp = 0x00,
92 +               .mcs = RATE_MCS(RATE_MODE_CCK, 0),
93         },
94         {
95                 .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
96                 .bitrate = 20,
97                 .ratemask = BIT(1),
98                 .plcp = 0x01,
99 +               .mcs = RATE_MCS(RATE_MODE_CCK, 1),
100         },
101         {
102                 .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
103                 .bitrate = 55,
104                 .ratemask = BIT(2),
105                 .plcp = 0x02,
106 +               .mcs = RATE_MCS(RATE_MODE_CCK, 2),
107         },
108         {
109                 .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
110                 .bitrate = 110,
111                 .ratemask = BIT(3),
112                 .plcp = 0x03,
113 +               .mcs = RATE_MCS(RATE_MODE_CCK, 3),
114         },
115         {
116                 .flags = DEV_RATE_OFDM,
117                 .bitrate = 60,
118                 .ratemask = BIT(4),
119                 .plcp = 0x0b,
120 +               .mcs = RATE_MCS(RATE_MODE_OFDM, 0),
121         },
122         {
123                 .flags = DEV_RATE_OFDM,
124                 .bitrate = 90,
125                 .ratemask = BIT(5),
126                 .plcp = 0x0f,
127 +               .mcs = RATE_MCS(RATE_MODE_OFDM, 1),
128         },
129         {
130                 .flags = DEV_RATE_OFDM,
131                 .bitrate = 120,
132                 .ratemask = BIT(6),
133                 .plcp = 0x0a,
134 +               .mcs = RATE_MCS(RATE_MODE_OFDM, 2),
135         },
136         {
137                 .flags = DEV_RATE_OFDM,
138                 .bitrate = 180,
139                 .ratemask = BIT(7),
140                 .plcp = 0x0e,
141 +               .mcs = RATE_MCS(RATE_MODE_OFDM, 3),
142         },
143         {
144                 .flags = DEV_RATE_OFDM,
145                 .bitrate = 240,
146                 .ratemask = BIT(8),
147                 .plcp = 0x09,
148 +               .mcs = RATE_MCS(RATE_MODE_OFDM, 4),
149         },
150         {
151                 .flags = DEV_RATE_OFDM,
152                 .bitrate = 360,
153                 .ratemask = BIT(9),
154                 .plcp = 0x0d,
155 +               .mcs = RATE_MCS(RATE_MODE_OFDM, 5),
156         },
157         {
158                 .flags = DEV_RATE_OFDM,
159                 .bitrate = 480,
160                 .ratemask = BIT(10),
161                 .plcp = 0x08,
162 +               .mcs = RATE_MCS(RATE_MODE_OFDM, 6),
163         },
164         {
165                 .flags = DEV_RATE_OFDM,
166                 .bitrate = 540,
167                 .ratemask = BIT(11),
168                 .plcp = 0x0c,
169 +               .mcs = RATE_MCS(RATE_MODE_OFDM, 7),
170         },
171  };
172  
173 @@ -582,6 +596,8 @@ static int rt2x00lib_probe_hw_modes(stru
174                 rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates;
175                 hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
176                     &rt2x00dev->bands[IEEE80211_BAND_2GHZ];
177 +               memcpy(&rt2x00dev->bands[IEEE80211_BAND_2GHZ].ht_cap,
178 +                      &spec->ht, sizeof(spec->ht));
179         }
180  
181         /*
182 @@ -598,6 +614,8 @@ static int rt2x00lib_probe_hw_modes(stru
183                 rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4];
184                 hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
185                     &rt2x00dev->bands[IEEE80211_BAND_5GHZ];
186 +               memcpy(&rt2x00dev->bands[IEEE80211_BAND_5GHZ].ht_cap,
187 +                      &spec->ht, sizeof(spec->ht));
188         }
189  
190         return 0;
191 --- /dev/null
192 +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c
193 @@ -0,0 +1,69 @@
194 +/*
195 +       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
196 +       <http://rt2x00.serialmonkey.com>
197 +
198 +       This program is free software; you can redistribute it and/or modify
199 +       it under the terms of the GNU General Public License as published by
200 +       the Free Software Foundation; either version 2 of the License, or
201 +       (at your option) any later version.
202 +
203 +       This program is distributed in the hope that it will be useful,
204 +       but WITHOUT ANY WARRANTY; without even the implied warranty of
205 +       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
206 +       GNU General Public License for more details.
207 +
208 +       You should have received a copy of the GNU General Public License
209 +       along with this program; if not, write to the
210 +       Free Software Foundation, Inc.,
211 +       59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
212 + */
213 +
214 +/*
215 +       Module: rt2x00lib
216 +       Abstract: rt2x00 HT specific routines.
217 + */
218 +
219 +#include <linux/kernel.h>
220 +#include <linux/module.h>
221 +
222 +#include "rt2x00.h"
223 +#include "rt2x00lib.h"
224 +
225 +void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
226 +                                  struct txentry_desc *txdesc,
227 +                                  struct ieee80211_rate *rate)
228 +{
229 +       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
230 +       const struct rt2x00_rate *hwrate = rt2x00_get_rate(rate->hw_value);
231 +
232 +       if (tx_info->control.sta)
233 +               txdesc->mpdu_density =
234 +                   tx_info->control.sta->ht_cap.ampdu_density;
235 +       else
236 +               txdesc->mpdu_density = 0;
237 +
238 +       txdesc->ba_size = 0;    /* FIXME: What value is needed? */
239 +       txdesc->stbc = 0;       /* FIXME: What value is needed? */
240 +
241 +       txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs);
242 +       if (rt2x00_get_rate_preamble(rate->hw_value))
243 +               txdesc->mcs |= 0x08;
244 +
245 +       /*
246 +        * Convert flags
247 +        */
248 +       if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
249 +               __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
250 +
251 +       /*
252 +        * Determine HT Mix/Greenfield rate mode
253 +        */
254 +       if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
255 +               txdesc->rate_mode = RATE_MODE_HT_MIX;
256 +       if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)
257 +               txdesc->rate_mode = RATE_MODE_HT_GREENFIELD;
258 +       if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
259 +               __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags);
260 +       if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
261 +               __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags);
262 +}
263 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h
264 +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
265 @@ -48,6 +48,7 @@ struct rt2x00_rate {
266         unsigned short ratemask;
267  
268         unsigned short plcp;
269 +       unsigned short mcs;
270  };
271  
272  extern const struct rt2x00_rate rt2x00_supported_rates[12];
273 @@ -68,6 +69,14 @@ static inline int rt2x00_get_rate_preamb
274         return (hw_value & 0xff00);
275  }
276  
277 +#define RATE_MCS(__mode, __mcs) \
278 +       ( (((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff) )
279 +
280 +static inline int rt2x00_get_rate_mcs(const u16 mcs_value)
281 +{
282 +       return (mcs_value & 0x00ff);
283 +}
284 +
285  /*
286   * Radio control handlers.
287   */
288 @@ -341,6 +350,21 @@ static inline void rt2x00crypto_rx_inser
289  #endif /* CONFIG_RT2X00_LIB_CRYPTO */
290  
291  /*
292 + * HT handlers.
293 + */
294 +#ifdef CONFIG_RT2X00_LIB_HT
295 +void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
296 +                                  struct txentry_desc *txdesc,
297 +                                  struct ieee80211_rate *rate);
298 +#else
299 +static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
300 +                                                struct txentry_desc *txdesc,
301 +                                                struct ieee80211_rate *rate)
302 +{
303 +}
304 +#endif /* CONFIG_RT2X00_LIB_HT */
305 +
306 +/*
307   * RFkill handlers.
308   */
309  #ifdef CONFIG_RT2X00_LIB_RFKILL
310 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c
311 +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
312 @@ -325,6 +325,7 @@ static void rt2x00queue_create_tx_descri
313          * Apply TX descriptor handling by components
314          */
315         rt2x00crypto_create_tx_descriptor(entry, txdesc);
316 +       rt2x00ht_create_tx_descriptor(entry, txdesc, rate);
317         rt2x00queue_create_tx_descriptor_seq(entry, txdesc);
318         rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, rate);
319  }
320 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h
321 +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
322 @@ -145,6 +145,7 @@ static inline struct skb_frame_desc* get
323   *
324   * @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value.
325   * @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value.
326 + * @RXDONE_SIGNAL_MCS: Signal field contains the mcs value.
327   * @RXDONE_MY_BSS: Does this frame originate from device's BSS.
328   * @RXDONE_CRYPTO_IV: Driver provided IV/EIV data.
329   * @RXDONE_CRYPTO_ICV: Driver provided ICV data.
330 @@ -152,9 +153,10 @@ static inline struct skb_frame_desc* get
331  enum rxdone_entry_desc_flags {
332         RXDONE_SIGNAL_PLCP = 1 << 0,
333         RXDONE_SIGNAL_BITRATE = 1 << 1,
334 -       RXDONE_MY_BSS = 1 << 2,
335 -       RXDONE_CRYPTO_IV = 1 << 3,
336 -       RXDONE_CRYPTO_ICV = 1 << 4,
337 +       RXDONE_SIGNAL_MCS = 1 << 2,
338 +       RXDONE_MY_BSS = 1 << 3,
339 +       RXDONE_CRYPTO_IV = 1 << 4,
340 +       RXDONE_CRYPTO_ICV = 1 << 5,
341  };
342  
343  /**
344 @@ -163,7 +165,7 @@ enum rxdone_entry_desc_flags {
345   * from &rxdone_entry_desc to a signal value type.
346   */
347  #define RXDONE_SIGNAL_MASK \
348 -       ( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE )
349 +       ( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE | RXDONE_SIGNAL_MCS )
350  
351  /**
352   * struct rxdone_entry_desc: RX Entry descriptor
353 @@ -243,6 +245,9 @@ struct txdone_entry_desc {
354   * @ENTRY_TXD_ENCRYPT_PAIRWISE: Use pairwise key table (instead of shared).
355   * @ENTRY_TXD_ENCRYPT_IV: Generate IV/EIV in hardware.
356   * @ENTRY_TXD_ENCRYPT_MMIC: Generate MIC in hardware.
357 + * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU.
358 + * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth.
359 + * @ENTRY_TXD_HT_SHORT_GI: Use short GI.
360   */
361  enum txentry_desc_flags {
362         ENTRY_TXD_RTS_FRAME,
363 @@ -258,6 +263,9 @@ enum txentry_desc_flags {
364         ENTRY_TXD_ENCRYPT_PAIRWISE,
365         ENTRY_TXD_ENCRYPT_IV,
366         ENTRY_TXD_ENCRYPT_MMIC,
367 +       ENTRY_TXD_HT_AMPDU,
368 +       ENTRY_TXD_HT_BW_40,
369 +       ENTRY_TXD_HT_SHORT_GI,
370  };
371  
372  /**
373 @@ -271,7 +279,11 @@ enum txentry_desc_flags {
374   * @length_low: PLCP length low word.
375   * @signal: PLCP signal.
376   * @service: PLCP service.
377 + * @msc: MCS.
378 + * @stbc: STBC.
379 + * @ba_size: BA size.
380   * @rate_mode: Rate mode (See @enum rate_modulation).
381 + * @mpdu_density: MDPU density.
382   * @retry_limit: Max number of retries.
383   * @aifs: AIFS value.
384   * @ifs: IFS value.
385 @@ -291,7 +303,11 @@ struct txentry_desc {
386         u16 signal;
387         u16 service;
388  
389 +       u16 mcs;
390 +       u16 stbc;
391 +       u16 ba_size;
392         u16 rate_mode;
393 +       u16 mpdu_density;
394  
395         short retry_limit;
396         short aifs;