1 From 827327792c4b0d4d4909ec27bd56cb3ba8f2b754 Mon Sep 17 00:00:00 2001
2 From: Ivo van Doorn <IvDoorn@gmail.com>
3 Date: Sat, 14 Mar 2009 20:06:48 +0100
4 Subject: [PATCH] rt2x00: Implement support for 802.11n
6 Extend rt2x00lib capabilities to support 802.11n,
7 it still lacks aggregation support, but that can
8 be added in the future.
10 Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
12 drivers/net/wireless/rt2x00/Kconfig | 3 +
13 drivers/net/wireless/rt2x00/Makefile | 1 +
14 drivers/net/wireless/rt2x00/rt2x00.h | 4 +
15 drivers/net/wireless/rt2x00/rt2x00config.c | 5 ++
16 drivers/net/wireless/rt2x00/rt2x00dev.c | 91 ++++++++++++++++++++-------
17 drivers/net/wireless/rt2x00/rt2x00ht.c | 69 +++++++++++++++++++++
18 drivers/net/wireless/rt2x00/rt2x00lib.h | 24 +++++++
19 drivers/net/wireless/rt2x00/rt2x00queue.c | 1 +
20 drivers/net/wireless/rt2x00/rt2x00queue.h | 33 ++++++++--
21 9 files changed, 201 insertions(+), 30 deletions(-)
22 create mode 100644 drivers/net/wireless/rt2x00/rt2x00ht.c
24 --- a/drivers/net/wireless/rt2x00/Makefile
25 +++ b/drivers/net/wireless/rt2x00/Makefile
26 @@ -8,6 +8,7 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO) +=
27 rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL) += rt2x00rfkill.o
28 rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o
29 rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o
30 +rt2x00lib-$(CONFIG_RT2X00_LIB_HT) += rt2x00ht.o
32 obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o
33 obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o
34 --- a/drivers/net/wireless/rt2x00/rt2x00.h
35 +++ b/drivers/net/wireless/rt2x00/rt2x00.h
36 @@ -357,6 +357,7 @@ static inline struct rt2x00_intf* vif_to
37 * for @tx_power_a, @tx_power_bg and @channels.
38 * @channels: Device/chipset specific channel values (See &struct rf_channel).
39 * @channels_info: Additional information for channels (See &struct channel_info).
40 + * @ht: Driver HT Capabilities (See &ieee80211_sta_ht_cap).
43 unsigned int supported_bands;
44 @@ -370,6 +371,8 @@ struct hw_mode_spec {
45 unsigned int num_channels;
46 const struct rf_channel *channels;
47 const struct channel_info *channels_info;
49 + struct ieee80211_sta_ht_cap ht;
53 @@ -606,6 +609,7 @@ enum rt2x00_flags {
54 CONFIG_EXTERNAL_LNA_BG,
55 CONFIG_DOUBLE_ANTENNA,
56 CONFIG_DISABLE_LINK_TUNING,
57 + CONFIG_CHANNEL_HT40,
61 --- a/drivers/net/wireless/rt2x00/rt2x00config.c
62 +++ b/drivers/net/wireless/rt2x00/rt2x00config.c
63 @@ -173,6 +173,11 @@ void rt2x00lib_config(struct rt2x00_dev
66 if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {
67 + if (conf_is_ht40(conf))
68 + __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
70 + __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
73 &rt2x00dev->spec.channels[conf->channel->hw_value],
75 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
76 +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
77 @@ -316,18 +316,54 @@ void rt2x00lib_txdone(struct queue_entry
79 EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
81 +static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,
82 + struct rxdone_entry_desc *rxdesc)
84 + struct ieee80211_supported_band *sband;
85 + const struct rt2x00_rate *rate;
91 + * For non-HT rates the MCS value needs to contain the
92 + * actually used rate modulation (CCK or OFDM).
94 + if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS)
95 + signal = RATE_MCS(rxdesc->rate_mode, rxdesc->signal);
97 + signal = rxdesc->signal;
99 + type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK);
101 + sband = &rt2x00dev->bands[rt2x00dev->curr_band];
102 + for (i = 0; i < sband->n_bitrates; i++) {
103 + rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
105 + if (((type == RXDONE_SIGNAL_PLCP) &&
106 + (rate->plcp == signal)) ||
107 + ((type == RXDONE_SIGNAL_BITRATE) &&
108 + (rate->bitrate == signal)) ||
109 + ((type == RXDONE_SIGNAL_MCS) &&
110 + (rate->mcs == signal))) {
115 + WARNING(rt2x00dev, "Frame received with unrecognized signal, "
116 + "signal=0x%.4x, type=%d.\n", signal, type);
120 void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
121 struct queue_entry *entry)
123 struct rxdone_entry_desc rxdesc;
125 struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
126 - struct ieee80211_supported_band *sband;
127 - const struct rt2x00_rate *rate;
128 unsigned int header_length;
135 * Allocate a new sk_buffer. If no new buffer available, drop the
136 @@ -376,26 +412,17 @@ void rt2x00lib_rxdone(struct rt2x00_dev
137 skb_trim(entry->skb, rxdesc.size);
140 - * Update RX statistics.
142 - sband = &rt2x00dev->bands[rt2x00dev->curr_band];
143 - for (i = 0; i < sband->n_bitrates; i++) {
144 - rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
146 - if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) &&
147 - (rate->plcp == rxdesc.signal)) ||
148 - ((rxdesc.dev_flags & RXDONE_SIGNAL_BITRATE) &&
149 - (rate->bitrate == rxdesc.signal))) {
156 - WARNING(rt2x00dev, "Frame received with unrecognized signal,"
157 - "signal=0x%.2x, type=%d.\n", rxdesc.signal,
158 - (rxdesc.dev_flags & RXDONE_SIGNAL_MASK));
160 + * Check if the frame was received using HT. In that case,
161 + * the rate is the MCS index and should be passed to mac80211
162 + * directly. Otherwise we need to translate the signal to
163 + * the correct bitrate index.
165 + if (rxdesc.rate_mode == RATE_MODE_CCK ||
166 + rxdesc.rate_mode == RATE_MODE_OFDM) {
167 + rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc);
169 + rxdesc.flags |= RX_FLAG_HT;
170 + rate_idx = rxdesc.signal;
174 @@ -405,7 +432,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev
175 rt2x00debug_update_crypto(rt2x00dev, &rxdesc);
177 rx_status->mactime = rxdesc.timestamp;
178 - rx_status->rate_idx = idx;
179 + rx_status->rate_idx = rate_idx;
180 rx_status->qual = rt2x00link_calculate_signal(rt2x00dev, rxdesc.rssi);
181 rx_status->signal = rxdesc.rssi;
182 rx_status->noise = rxdesc.noise;
183 @@ -440,72 +467,84 @@ const struct rt2x00_rate rt2x00_supporte
187 + .mcs = RATE_MCS(RATE_MODE_CCK, 0),
190 .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
194 + .mcs = RATE_MCS(RATE_MODE_CCK, 1),
197 .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
201 + .mcs = RATE_MCS(RATE_MODE_CCK, 2),
204 .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
208 + .mcs = RATE_MCS(RATE_MODE_CCK, 3),
211 .flags = DEV_RATE_OFDM,
215 + .mcs = RATE_MCS(RATE_MODE_OFDM, 0),
218 .flags = DEV_RATE_OFDM,
222 + .mcs = RATE_MCS(RATE_MODE_OFDM, 1),
225 .flags = DEV_RATE_OFDM,
229 + .mcs = RATE_MCS(RATE_MODE_OFDM, 2),
232 .flags = DEV_RATE_OFDM,
236 + .mcs = RATE_MCS(RATE_MODE_OFDM, 3),
239 .flags = DEV_RATE_OFDM,
243 + .mcs = RATE_MCS(RATE_MODE_OFDM, 4),
246 .flags = DEV_RATE_OFDM,
250 + .mcs = RATE_MCS(RATE_MODE_OFDM, 5),
253 .flags = DEV_RATE_OFDM,
257 + .mcs = RATE_MCS(RATE_MODE_OFDM, 6),
260 .flags = DEV_RATE_OFDM,
264 + .mcs = RATE_MCS(RATE_MODE_OFDM, 7),
268 @@ -581,6 +620,8 @@ static int rt2x00lib_probe_hw_modes(stru
269 rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates;
270 hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
271 &rt2x00dev->bands[IEEE80211_BAND_2GHZ];
272 + memcpy(&rt2x00dev->bands[IEEE80211_BAND_2GHZ].ht_cap,
273 + &spec->ht, sizeof(spec->ht));
277 @@ -597,6 +638,8 @@ static int rt2x00lib_probe_hw_modes(stru
278 rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4];
279 hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
280 &rt2x00dev->bands[IEEE80211_BAND_5GHZ];
281 + memcpy(&rt2x00dev->bands[IEEE80211_BAND_5GHZ].ht_cap,
282 + &spec->ht, sizeof(spec->ht));
287 +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c
290 + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
291 + <http://rt2x00.serialmonkey.com>
293 + This program is free software; you can redistribute it and/or modify
294 + it under the terms of the GNU General Public License as published by
295 + the Free Software Foundation; either version 2 of the License, or
296 + (at your option) any later version.
298 + This program is distributed in the hope that it will be useful,
299 + but WITHOUT ANY WARRANTY; without even the implied warranty of
300 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
301 + GNU General Public License for more details.
303 + You should have received a copy of the GNU General Public License
304 + along with this program; if not, write to the
305 + Free Software Foundation, Inc.,
306 + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
311 + Abstract: rt2x00 HT specific routines.
314 +#include <linux/kernel.h>
315 +#include <linux/module.h>
318 +#include "rt2x00lib.h"
320 +void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
321 + struct txentry_desc *txdesc,
322 + const struct rt2x00_rate *hwrate)
324 + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
325 + struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
327 + if (tx_info->control.sta)
328 + txdesc->mpdu_density =
329 + tx_info->control.sta->ht_cap.ampdu_density;
331 + txdesc->mpdu_density = 0;
333 + txdesc->ba_size = 7; /* FIXME: What value is needed? */
334 + txdesc->stbc = 0; /* FIXME: What value is needed? */
336 + txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs);
337 + if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
338 + txdesc->mcs |= 0x08;
343 + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
344 + __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
347 + * Determine HT Mix/Greenfield rate mode
349 + if (txrate->flags & IEEE80211_TX_RC_MCS)
350 + txdesc->rate_mode = RATE_MODE_HT_MIX;
351 + if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
352 + txdesc->rate_mode = RATE_MODE_HT_GREENFIELD;
353 + if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
354 + __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags);
355 + if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
356 + __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags);
358 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h
359 +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
360 @@ -48,6 +48,7 @@ struct rt2x00_rate {
361 unsigned short ratemask;
364 + unsigned short mcs;
367 extern const struct rt2x00_rate rt2x00_supported_rates[12];
368 @@ -57,6 +58,14 @@ static inline const struct rt2x00_rate *
369 return &rt2x00_supported_rates[hw_value & 0xff];
372 +#define RATE_MCS(__mode, __mcs) \
373 + ( (((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff) )
375 +static inline int rt2x00_get_rate_mcs(const u16 mcs_value)
377 + return (mcs_value & 0x00ff);
381 * Radio control handlers.
383 @@ -341,6 +350,21 @@ static inline void rt2x00crypto_rx_inser
384 #endif /* CONFIG_RT2X00_LIB_CRYPTO */
389 +#ifdef CONFIG_RT2X00_LIB_HT
390 +void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
391 + struct txentry_desc *txdesc,
392 + const struct rt2x00_rate *hwrate);
394 +static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
395 + struct txentry_desc *txdesc,
396 + const struct rt2x00_rate *hwrate)
399 +#endif /* CONFIG_RT2X00_LIB_HT */
404 #ifdef CONFIG_RT2X00_LIB_RFKILL
405 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c
406 +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
407 @@ -326,6 +326,7 @@ static void rt2x00queue_create_tx_descri
408 * Apply TX descriptor handling by components
410 rt2x00crypto_create_tx_descriptor(entry, txdesc);
411 + rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate);
412 rt2x00queue_create_tx_descriptor_seq(entry, txdesc);
413 rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
415 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h
416 +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
418 * for USB devices this restriction does not apply, but the value of
419 * 2432 makes sense since it is big enough to contain the maximum fragment
420 * size according to the ieee802.11 specs.
421 + * The aggregation size depends on support from the driver, but should
422 + * be something around 3840 bytes.
424 -#define DATA_FRAME_SIZE 2432
425 -#define MGMT_FRAME_SIZE 256
426 +#define DATA_FRAME_SIZE 2432
427 +#define MGMT_FRAME_SIZE 256
428 +#define AGGREGATION_SIZE 3840
431 * DOC: Number of entries per queue
432 @@ -145,6 +148,7 @@ static inline struct skb_frame_desc* get
434 * @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value.
435 * @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value.
436 + * @RXDONE_SIGNAL_MCS: Signal field contains the mcs value.
437 * @RXDONE_MY_BSS: Does this frame originate from device's BSS.
438 * @RXDONE_CRYPTO_IV: Driver provided IV/EIV data.
439 * @RXDONE_CRYPTO_ICV: Driver provided ICV data.
440 @@ -152,9 +156,10 @@ static inline struct skb_frame_desc* get
441 enum rxdone_entry_desc_flags {
442 RXDONE_SIGNAL_PLCP = 1 << 0,
443 RXDONE_SIGNAL_BITRATE = 1 << 1,
444 - RXDONE_MY_BSS = 1 << 2,
445 - RXDONE_CRYPTO_IV = 1 << 3,
446 - RXDONE_CRYPTO_ICV = 1 << 4,
447 + RXDONE_SIGNAL_MCS = 1 << 2,
448 + RXDONE_MY_BSS = 1 << 3,
449 + RXDONE_CRYPTO_IV = 1 << 4,
450 + RXDONE_CRYPTO_ICV = 1 << 5,
454 @@ -163,7 +168,7 @@ enum rxdone_entry_desc_flags {
455 * from &rxdone_entry_desc to a signal value type.
457 #define RXDONE_SIGNAL_MASK \
458 - ( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE )
459 + ( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE | RXDONE_SIGNAL_MCS )
462 * struct rxdone_entry_desc: RX Entry descriptor
463 @@ -177,6 +182,7 @@ enum rxdone_entry_desc_flags {
464 * @size: Data size of the received frame.
465 * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags).
466 * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags).
467 + * @rate_mode: Rate mode (See @enum rate_modulation).
468 * @cipher: Cipher type used during decryption.
469 * @cipher_status: Decryption status.
470 * @iv: IV/EIV data used during decryption.
471 @@ -190,6 +196,7 @@ struct rxdone_entry_desc {
479 @@ -243,6 +250,9 @@ struct txdone_entry_desc {
480 * @ENTRY_TXD_ENCRYPT_PAIRWISE: Use pairwise key table (instead of shared).
481 * @ENTRY_TXD_ENCRYPT_IV: Generate IV/EIV in hardware.
482 * @ENTRY_TXD_ENCRYPT_MMIC: Generate MIC in hardware.
483 + * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU.
484 + * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth.
485 + * @ENTRY_TXD_HT_SHORT_GI: Use short GI.
487 enum txentry_desc_flags {
489 @@ -258,6 +268,9 @@ enum txentry_desc_flags {
490 ENTRY_TXD_ENCRYPT_PAIRWISE,
491 ENTRY_TXD_ENCRYPT_IV,
492 ENTRY_TXD_ENCRYPT_MMIC,
493 + ENTRY_TXD_HT_AMPDU,
494 + ENTRY_TXD_HT_BW_40,
495 + ENTRY_TXD_HT_SHORT_GI,
499 @@ -271,7 +284,11 @@ enum txentry_desc_flags {
500 * @length_low: PLCP length low word.
501 * @signal: PLCP signal.
502 * @service: PLCP service.
505 + * @ba_size: BA size.
506 * @rate_mode: Rate mode (See @enum rate_modulation).
507 + * @mpdu_density: MDPU density.
508 * @retry_limit: Max number of retries.
511 @@ -291,7 +308,11 @@ struct txentry_desc {