diff options
author | Ivo van Doorn <ivdoorn@gmail.com> | 2009-04-26 10:09:32 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-05-06 15:14:50 -0400 |
commit | 35f00cfcc06bb85e0659f9847400518008d78145 (patch) | |
tree | dccebd4dd7cde975d857d1fb3f28dd1e467fa72f /drivers/net | |
parent | 9f1661718c7fcf82e25c6aed20b729ee372d9d65 (diff) |
rt2x00: Implement support for 802.11n
Extend rt2x00lib capabilities to support 802.11n,
it still lacks aggregation support, but that can
be added in the future.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/rt2x00/Kconfig | 3 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00config.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 92 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00ht.c | 69 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00lib.h | 24 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.h | 39 |
9 files changed, 211 insertions, 34 deletions
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index bfc5d9cf716e..4338c93d5b63 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -88,6 +88,9 @@ config RT2X00_LIB_USB | |||
88 | config RT2X00_LIB | 88 | config RT2X00_LIB |
89 | tristate | 89 | tristate |
90 | 90 | ||
91 | config RT2X00_LIB_HT | ||
92 | boolean | ||
93 | |||
91 | config RT2X00_LIB_FIRMWARE | 94 | config RT2X00_LIB_FIRMWARE |
92 | boolean | 95 | boolean |
93 | select FW_LOADER | 96 | select FW_LOADER |
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index f22d808d8c51..776ec2b8c4e7 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile | |||
@@ -8,6 +8,7 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o | |||
8 | rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL) += rt2x00rfkill.o | 8 | rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL) += rt2x00rfkill.o |
9 | rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o | 9 | rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o |
10 | rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o | 10 | rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o |
11 | rt2x00lib-$(CONFIG_RT2X00_LIB_HT) += rt2x00ht.o | ||
11 | 12 | ||
12 | obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o | 13 | obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o |
13 | obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o | 14 | obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 7c5cbb192a6c..ebe5f276679b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -366,6 +366,7 @@ static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) | |||
366 | * for @tx_power_a, @tx_power_bg and @channels. | 366 | * for @tx_power_a, @tx_power_bg and @channels. |
367 | * @channels: Device/chipset specific channel values (See &struct rf_channel). | 367 | * @channels: Device/chipset specific channel values (See &struct rf_channel). |
368 | * @channels_info: Additional information for channels (See &struct channel_info). | 368 | * @channels_info: Additional information for channels (See &struct channel_info). |
369 | * @ht: Driver HT Capabilities (See &ieee80211_sta_ht_cap). | ||
369 | */ | 370 | */ |
370 | struct hw_mode_spec { | 371 | struct hw_mode_spec { |
371 | unsigned int supported_bands; | 372 | unsigned int supported_bands; |
@@ -379,6 +380,8 @@ struct hw_mode_spec { | |||
379 | unsigned int num_channels; | 380 | unsigned int num_channels; |
380 | const struct rf_channel *channels; | 381 | const struct rf_channel *channels; |
381 | const struct channel_info *channels_info; | 382 | const struct channel_info *channels_info; |
383 | |||
384 | struct ieee80211_sta_ht_cap ht; | ||
382 | }; | 385 | }; |
383 | 386 | ||
384 | /* | 387 | /* |
@@ -616,6 +619,7 @@ enum rt2x00_flags { | |||
616 | CONFIG_EXTERNAL_LNA_BG, | 619 | CONFIG_EXTERNAL_LNA_BG, |
617 | CONFIG_DOUBLE_ANTENNA, | 620 | CONFIG_DOUBLE_ANTENNA, |
618 | CONFIG_DISABLE_LINK_TUNING, | 621 | CONFIG_DISABLE_LINK_TUNING, |
622 | CONFIG_CHANNEL_HT40, | ||
619 | }; | 623 | }; |
620 | 624 | ||
621 | /* | 625 | /* |
@@ -788,6 +792,13 @@ struct rt2x00_dev { | |||
788 | u8 freq_offset; | 792 | u8 freq_offset; |
789 | 793 | ||
790 | /* | 794 | /* |
795 | * Calibration information (for rt2800usb & rt2800pci). | ||
796 | * [0] -> BW20 | ||
797 | * [1] -> BW40 | ||
798 | */ | ||
799 | u8 calibration[2]; | ||
800 | |||
801 | /* | ||
791 | * Low level statistics which will have | 802 | * Low level statistics which will have |
792 | * to be kept up to date while device is running. | 803 | * to be kept up to date while device is running. |
793 | */ | 804 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 9c2f5517af2a..863e399d4fa6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c | |||
@@ -173,6 +173,11 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, | |||
173 | libconf.conf = conf; | 173 | libconf.conf = conf; |
174 | 174 | ||
175 | if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { | 175 | if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { |
176 | if (conf_is_ht40(conf)) | ||
177 | __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); | ||
178 | else | ||
179 | __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); | ||
180 | |||
176 | memcpy(&libconf.rf, | 181 | memcpy(&libconf.rf, |
177 | &rt2x00dev->spec.channels[conf->channel->hw_value], | 182 | &rt2x00dev->spec.channels[conf->channel->hw_value], |
178 | sizeof(libconf.rf)); | 183 | sizeof(libconf.rf)); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index e15086af7278..f2270845072a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -323,19 +323,54 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
323 | } | 323 | } |
324 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone); | 324 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone); |
325 | 325 | ||
326 | static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, | ||
327 | struct rxdone_entry_desc *rxdesc) | ||
328 | { | ||
329 | struct ieee80211_supported_band *sband; | ||
330 | const struct rt2x00_rate *rate; | ||
331 | unsigned int i; | ||
332 | int signal; | ||
333 | int type; | ||
334 | |||
335 | /* | ||
336 | * For non-HT rates the MCS value needs to contain the | ||
337 | * actually used rate modulation (CCK or OFDM). | ||
338 | */ | ||
339 | if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS) | ||
340 | signal = RATE_MCS(rxdesc->rate_mode, rxdesc->signal); | ||
341 | else | ||
342 | signal = rxdesc->signal; | ||
343 | |||
344 | type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK); | ||
345 | |||
346 | sband = &rt2x00dev->bands[rt2x00dev->curr_band]; | ||
347 | for (i = 0; i < sband->n_bitrates; i++) { | ||
348 | rate = rt2x00_get_rate(sband->bitrates[i].hw_value); | ||
349 | |||
350 | if (((type == RXDONE_SIGNAL_PLCP) && | ||
351 | (rate->plcp == signal)) || | ||
352 | ((type == RXDONE_SIGNAL_BITRATE) && | ||
353 | (rate->bitrate == signal)) || | ||
354 | ((type == RXDONE_SIGNAL_MCS) && | ||
355 | (rate->mcs == signal))) { | ||
356 | return i; | ||
357 | } | ||
358 | } | ||
359 | |||
360 | WARNING(rt2x00dev, "Frame received with unrecognized signal, " | ||
361 | "signal=0x%.4x, type=%d.\n", signal, type); | ||
362 | return 0; | ||
363 | } | ||
364 | |||
326 | void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | 365 | void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, |
327 | struct queue_entry *entry) | 366 | struct queue_entry *entry) |
328 | { | 367 | { |
329 | struct rxdone_entry_desc rxdesc; | 368 | struct rxdone_entry_desc rxdesc; |
330 | struct sk_buff *skb; | 369 | struct sk_buff *skb; |
331 | struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; | 370 | struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; |
332 | struct ieee80211_supported_band *sband; | ||
333 | const struct rt2x00_rate *rate; | ||
334 | unsigned int header_length; | 371 | unsigned int header_length; |
335 | bool l2pad; | 372 | bool l2pad; |
336 | unsigned int i; | 373 | int rate_idx; |
337 | int idx = -1; | ||
338 | |||
339 | /* | 374 | /* |
340 | * Allocate a new sk_buffer. If no new buffer available, drop the | 375 | * Allocate a new sk_buffer. If no new buffer available, drop the |
341 | * received frame and reuse the existing buffer. | 376 | * received frame and reuse the existing buffer. |
@@ -379,26 +414,17 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | |||
379 | rt2x00queue_payload_align(entry->skb, l2pad, header_length); | 414 | rt2x00queue_payload_align(entry->skb, l2pad, header_length); |
380 | 415 | ||
381 | /* | 416 | /* |
382 | * Update RX statistics. | 417 | * Check if the frame was received using HT. In that case, |
418 | * the rate is the MCS index and should be passed to mac80211 | ||
419 | * directly. Otherwise we need to translate the signal to | ||
420 | * the correct bitrate index. | ||
383 | */ | 421 | */ |
384 | sband = &rt2x00dev->bands[rt2x00dev->curr_band]; | 422 | if (rxdesc.rate_mode == RATE_MODE_CCK || |
385 | for (i = 0; i < sband->n_bitrates; i++) { | 423 | rxdesc.rate_mode == RATE_MODE_OFDM) { |
386 | rate = rt2x00_get_rate(sband->bitrates[i].hw_value); | 424 | rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc); |
387 | 425 | } else { | |
388 | if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && | 426 | rxdesc.flags |= RX_FLAG_HT; |
389 | (rate->plcp == rxdesc.signal)) || | 427 | rate_idx = rxdesc.signal; |
390 | ((rxdesc.dev_flags & RXDONE_SIGNAL_BITRATE) && | ||
391 | (rate->bitrate == rxdesc.signal))) { | ||
392 | idx = i; | ||
393 | break; | ||
394 | } | ||
395 | } | ||
396 | |||
397 | if (idx < 0) { | ||
398 | WARNING(rt2x00dev, "Frame received with unrecognized signal," | ||
399 | "signal=0x%.2x, type=%d.\n", rxdesc.signal, | ||
400 | (rxdesc.dev_flags & RXDONE_SIGNAL_MASK)); | ||
401 | idx = 0; | ||
402 | } | 428 | } |
403 | 429 | ||
404 | /* | 430 | /* |
@@ -408,7 +434,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | |||
408 | rt2x00debug_update_crypto(rt2x00dev, &rxdesc); | 434 | rt2x00debug_update_crypto(rt2x00dev, &rxdesc); |
409 | 435 | ||
410 | rx_status->mactime = rxdesc.timestamp; | 436 | rx_status->mactime = rxdesc.timestamp; |
411 | rx_status->rate_idx = idx; | 437 | rx_status->rate_idx = rate_idx; |
412 | rx_status->qual = rt2x00link_calculate_signal(rt2x00dev, rxdesc.rssi); | 438 | rx_status->qual = rt2x00link_calculate_signal(rt2x00dev, rxdesc.rssi); |
413 | rx_status->signal = rxdesc.rssi; | 439 | rx_status->signal = rxdesc.rssi; |
414 | rx_status->noise = rxdesc.noise; | 440 | rx_status->noise = rxdesc.noise; |
@@ -443,72 +469,84 @@ const struct rt2x00_rate rt2x00_supported_rates[12] = { | |||
443 | .bitrate = 10, | 469 | .bitrate = 10, |
444 | .ratemask = BIT(0), | 470 | .ratemask = BIT(0), |
445 | .plcp = 0x00, | 471 | .plcp = 0x00, |
472 | .mcs = RATE_MCS(RATE_MODE_CCK, 0), | ||
446 | }, | 473 | }, |
447 | { | 474 | { |
448 | .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, | 475 | .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, |
449 | .bitrate = 20, | 476 | .bitrate = 20, |
450 | .ratemask = BIT(1), | 477 | .ratemask = BIT(1), |
451 | .plcp = 0x01, | 478 | .plcp = 0x01, |
479 | .mcs = RATE_MCS(RATE_MODE_CCK, 1), | ||
452 | }, | 480 | }, |
453 | { | 481 | { |
454 | .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, | 482 | .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, |
455 | .bitrate = 55, | 483 | .bitrate = 55, |
456 | .ratemask = BIT(2), | 484 | .ratemask = BIT(2), |
457 | .plcp = 0x02, | 485 | .plcp = 0x02, |
486 | .mcs = RATE_MCS(RATE_MODE_CCK, 2), | ||
458 | }, | 487 | }, |
459 | { | 488 | { |
460 | .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, | 489 | .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, |
461 | .bitrate = 110, | 490 | .bitrate = 110, |
462 | .ratemask = BIT(3), | 491 | .ratemask = BIT(3), |
463 | .plcp = 0x03, | 492 | .plcp = 0x03, |
493 | .mcs = RATE_MCS(RATE_MODE_CCK, 3), | ||
464 | }, | 494 | }, |
465 | { | 495 | { |
466 | .flags = DEV_RATE_OFDM, | 496 | .flags = DEV_RATE_OFDM, |
467 | .bitrate = 60, | 497 | .bitrate = 60, |
468 | .ratemask = BIT(4), | 498 | .ratemask = BIT(4), |
469 | .plcp = 0x0b, | 499 | .plcp = 0x0b, |
500 | .mcs = RATE_MCS(RATE_MODE_OFDM, 0), | ||
470 | }, | 501 | }, |
471 | { | 502 | { |
472 | .flags = DEV_RATE_OFDM, | 503 | .flags = DEV_RATE_OFDM, |
473 | .bitrate = 90, | 504 | .bitrate = 90, |
474 | .ratemask = BIT(5), | 505 | .ratemask = BIT(5), |
475 | .plcp = 0x0f, | 506 | .plcp = 0x0f, |
507 | .mcs = RATE_MCS(RATE_MODE_OFDM, 1), | ||
476 | }, | 508 | }, |
477 | { | 509 | { |
478 | .flags = DEV_RATE_OFDM, | 510 | .flags = DEV_RATE_OFDM, |
479 | .bitrate = 120, | 511 | .bitrate = 120, |
480 | .ratemask = BIT(6), | 512 | .ratemask = BIT(6), |
481 | .plcp = 0x0a, | 513 | .plcp = 0x0a, |
514 | .mcs = RATE_MCS(RATE_MODE_OFDM, 2), | ||
482 | }, | 515 | }, |
483 | { | 516 | { |
484 | .flags = DEV_RATE_OFDM, | 517 | .flags = DEV_RATE_OFDM, |
485 | .bitrate = 180, | 518 | .bitrate = 180, |
486 | .ratemask = BIT(7), | 519 | .ratemask = BIT(7), |
487 | .plcp = 0x0e, | 520 | .plcp = 0x0e, |
521 | .mcs = RATE_MCS(RATE_MODE_OFDM, 3), | ||
488 | }, | 522 | }, |
489 | { | 523 | { |
490 | .flags = DEV_RATE_OFDM, | 524 | .flags = DEV_RATE_OFDM, |
491 | .bitrate = 240, | 525 | .bitrate = 240, |
492 | .ratemask = BIT(8), | 526 | .ratemask = BIT(8), |
493 | .plcp = 0x09, | 527 | .plcp = 0x09, |
528 | .mcs = RATE_MCS(RATE_MODE_OFDM, 4), | ||
494 | }, | 529 | }, |
495 | { | 530 | { |
496 | .flags = DEV_RATE_OFDM, | 531 | .flags = DEV_RATE_OFDM, |
497 | .bitrate = 360, | 532 | .bitrate = 360, |
498 | .ratemask = BIT(9), | 533 | .ratemask = BIT(9), |
499 | .plcp = 0x0d, | 534 | .plcp = 0x0d, |
535 | .mcs = RATE_MCS(RATE_MODE_OFDM, 5), | ||
500 | }, | 536 | }, |
501 | { | 537 | { |
502 | .flags = DEV_RATE_OFDM, | 538 | .flags = DEV_RATE_OFDM, |
503 | .bitrate = 480, | 539 | .bitrate = 480, |
504 | .ratemask = BIT(10), | 540 | .ratemask = BIT(10), |
505 | .plcp = 0x08, | 541 | .plcp = 0x08, |
542 | .mcs = RATE_MCS(RATE_MODE_OFDM, 6), | ||
506 | }, | 543 | }, |
507 | { | 544 | { |
508 | .flags = DEV_RATE_OFDM, | 545 | .flags = DEV_RATE_OFDM, |
509 | .bitrate = 540, | 546 | .bitrate = 540, |
510 | .ratemask = BIT(11), | 547 | .ratemask = BIT(11), |
511 | .plcp = 0x0c, | 548 | .plcp = 0x0c, |
549 | .mcs = RATE_MCS(RATE_MODE_OFDM, 7), | ||
512 | }, | 550 | }, |
513 | }; | 551 | }; |
514 | 552 | ||
@@ -584,6 +622,8 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, | |||
584 | rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates; | 622 | rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates; |
585 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | 623 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = |
586 | &rt2x00dev->bands[IEEE80211_BAND_2GHZ]; | 624 | &rt2x00dev->bands[IEEE80211_BAND_2GHZ]; |
625 | memcpy(&rt2x00dev->bands[IEEE80211_BAND_2GHZ].ht_cap, | ||
626 | &spec->ht, sizeof(spec->ht)); | ||
587 | } | 627 | } |
588 | 628 | ||
589 | /* | 629 | /* |
@@ -600,6 +640,8 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, | |||
600 | rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4]; | 640 | rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4]; |
601 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 641 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = |
602 | &rt2x00dev->bands[IEEE80211_BAND_5GHZ]; | 642 | &rt2x00dev->bands[IEEE80211_BAND_5GHZ]; |
643 | memcpy(&rt2x00dev->bands[IEEE80211_BAND_5GHZ].ht_cap, | ||
644 | &spec->ht, sizeof(spec->ht)); | ||
603 | } | 645 | } |
604 | 646 | ||
605 | return 0; | 647 | return 0; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c new file mode 100644 index 000000000000..e3cec839e540 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | Copyright (C) 2004 - 2009 rt2x00 SourceForge Project | ||
3 | <http://rt2x00.serialmonkey.com> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the | ||
17 | Free Software Foundation, Inc., | ||
18 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | Module: rt2x00lib | ||
23 | Abstract: rt2x00 HT specific routines. | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/module.h> | ||
28 | |||
29 | #include "rt2x00.h" | ||
30 | #include "rt2x00lib.h" | ||
31 | |||
32 | void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, | ||
33 | struct txentry_desc *txdesc, | ||
34 | const struct rt2x00_rate *hwrate) | ||
35 | { | ||
36 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); | ||
37 | struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; | ||
38 | |||
39 | if (tx_info->control.sta) | ||
40 | txdesc->mpdu_density = | ||
41 | tx_info->control.sta->ht_cap.ampdu_density; | ||
42 | else | ||
43 | txdesc->mpdu_density = 0; | ||
44 | |||
45 | txdesc->ba_size = 7; /* FIXME: What value is needed? */ | ||
46 | txdesc->stbc = 0; /* FIXME: What value is needed? */ | ||
47 | |||
48 | txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); | ||
49 | if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | ||
50 | txdesc->mcs |= 0x08; | ||
51 | |||
52 | /* | ||
53 | * Convert flags | ||
54 | */ | ||
55 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) | ||
56 | __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags); | ||
57 | |||
58 | /* | ||
59 | * Determine HT Mix/Greenfield rate mode | ||
60 | */ | ||
61 | if (txrate->flags & IEEE80211_TX_RC_MCS) | ||
62 | txdesc->rate_mode = RATE_MODE_HT_MIX; | ||
63 | if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) | ||
64 | txdesc->rate_mode = RATE_MODE_HT_GREENFIELD; | ||
65 | if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
66 | __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); | ||
67 | if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) | ||
68 | __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); | ||
69 | } | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index aa284e48d2c2..ccc7ba4f3181 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h | |||
@@ -48,6 +48,7 @@ struct rt2x00_rate { | |||
48 | unsigned short ratemask; | 48 | unsigned short ratemask; |
49 | 49 | ||
50 | unsigned short plcp; | 50 | unsigned short plcp; |
51 | unsigned short mcs; | ||
51 | }; | 52 | }; |
52 | 53 | ||
53 | extern const struct rt2x00_rate rt2x00_supported_rates[12]; | 54 | extern const struct rt2x00_rate rt2x00_supported_rates[12]; |
@@ -57,6 +58,14 @@ static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value) | |||
57 | return &rt2x00_supported_rates[hw_value & 0xff]; | 58 | return &rt2x00_supported_rates[hw_value & 0xff]; |
58 | } | 59 | } |
59 | 60 | ||
61 | #define RATE_MCS(__mode, __mcs) \ | ||
62 | ( (((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff) ) | ||
63 | |||
64 | static inline int rt2x00_get_rate_mcs(const u16 mcs_value) | ||
65 | { | ||
66 | return (mcs_value & 0x00ff); | ||
67 | } | ||
68 | |||
60 | /* | 69 | /* |
61 | * Radio control handlers. | 70 | * Radio control handlers. |
62 | */ | 71 | */ |
@@ -360,6 +369,21 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, | |||
360 | #endif /* CONFIG_RT2X00_LIB_CRYPTO */ | 369 | #endif /* CONFIG_RT2X00_LIB_CRYPTO */ |
361 | 370 | ||
362 | /* | 371 | /* |
372 | * HT handlers. | ||
373 | */ | ||
374 | #ifdef CONFIG_RT2X00_LIB_HT | ||
375 | void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, | ||
376 | struct txentry_desc *txdesc, | ||
377 | const struct rt2x00_rate *hwrate); | ||
378 | #else | ||
379 | static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, | ||
380 | struct txentry_desc *txdesc, | ||
381 | const struct rt2x00_rate *hwrate) | ||
382 | { | ||
383 | } | ||
384 | #endif /* CONFIG_RT2X00_LIB_HT */ | ||
385 | |||
386 | /* | ||
363 | * RFkill handlers. | 387 | * RFkill handlers. |
364 | */ | 388 | */ |
365 | #ifdef CONFIG_RT2X00_LIB_RFKILL | 389 | #ifdef CONFIG_RT2X00_LIB_RFKILL |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index bc1742c1d51c..44e5b3279ca7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -361,6 +361,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
361 | * Apply TX descriptor handling by components | 361 | * Apply TX descriptor handling by components |
362 | */ | 362 | */ |
363 | rt2x00crypto_create_tx_descriptor(entry, txdesc); | 363 | rt2x00crypto_create_tx_descriptor(entry, txdesc); |
364 | rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate); | ||
364 | rt2x00queue_create_tx_descriptor_seq(entry, txdesc); | 365 | rt2x00queue_create_tx_descriptor_seq(entry, txdesc); |
365 | rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); | 366 | rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); |
366 | } | 367 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 13e0ece176a1..b5e06347c8a7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -35,9 +35,12 @@ | |||
35 | * for USB devices this restriction does not apply, but the value of | 35 | * for USB devices this restriction does not apply, but the value of |
36 | * 2432 makes sense since it is big enough to contain the maximum fragment | 36 | * 2432 makes sense since it is big enough to contain the maximum fragment |
37 | * size according to the ieee802.11 specs. | 37 | * size according to the ieee802.11 specs. |
38 | * The aggregation size depends on support from the driver, but should | ||
39 | * be something around 3840 bytes. | ||
38 | */ | 40 | */ |
39 | #define DATA_FRAME_SIZE 2432 | 41 | #define DATA_FRAME_SIZE 2432 |
40 | #define MGMT_FRAME_SIZE 256 | 42 | #define MGMT_FRAME_SIZE 256 |
43 | #define AGGREGATION_SIZE 3840 | ||
41 | 44 | ||
42 | /** | 45 | /** |
43 | * DOC: Number of entries per queue | 46 | * DOC: Number of entries per queue |
@@ -148,18 +151,20 @@ static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb) | |||
148 | * | 151 | * |
149 | * @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value. | 152 | * @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value. |
150 | * @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value. | 153 | * @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value. |
154 | * @RXDONE_SIGNAL_MCS: Signal field contains the mcs value. | ||
151 | * @RXDONE_MY_BSS: Does this frame originate from device's BSS. | 155 | * @RXDONE_MY_BSS: Does this frame originate from device's BSS. |
152 | * @RXDONE_CRYPTO_IV: Driver provided IV/EIV data. | 156 | * @RXDONE_CRYPTO_IV: Driver provided IV/EIV data. |
153 | * @RXDONE_CRYPTO_ICV: Driver provided ICV data. | 157 | * @RXDONE_CRYPTO_ICV: Driver provided ICV data. |
154 | * @RXDONE_L2PAD: 802.11 payload has been padded to 4-byte boundary. | 158 | * @RXDONE_L2PAD: 802.11 payload has been padded to 4-byte boundary. |
155 | */ | 159 | */ |
156 | enum rxdone_entry_desc_flags { | 160 | enum rxdone_entry_desc_flags { |
157 | RXDONE_SIGNAL_PLCP = 1 << 0, | 161 | RXDONE_SIGNAL_PLCP = BIT(0), |
158 | RXDONE_SIGNAL_BITRATE = 1 << 1, | 162 | RXDONE_SIGNAL_BITRATE = BIT(1), |
159 | RXDONE_MY_BSS = 1 << 2, | 163 | RXDONE_SIGNAL_MCS = BIT(2), |
160 | RXDONE_CRYPTO_IV = 1 << 3, | 164 | RXDONE_MY_BSS = BIT(3), |
161 | RXDONE_CRYPTO_ICV = 1 << 4, | 165 | RXDONE_CRYPTO_IV = BIT(4), |
162 | RXDONE_L2PAD = 1 << 5, | 166 | RXDONE_CRYPTO_ICV = BIT(5), |
167 | RXDONE_L2PAD = BIT(6), | ||
163 | }; | 168 | }; |
164 | 169 | ||
165 | /** | 170 | /** |
@@ -168,7 +173,7 @@ enum rxdone_entry_desc_flags { | |||
168 | * from &rxdone_entry_desc to a signal value type. | 173 | * from &rxdone_entry_desc to a signal value type. |
169 | */ | 174 | */ |
170 | #define RXDONE_SIGNAL_MASK \ | 175 | #define RXDONE_SIGNAL_MASK \ |
171 | ( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE ) | 176 | ( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE | RXDONE_SIGNAL_MCS ) |
172 | 177 | ||
173 | /** | 178 | /** |
174 | * struct rxdone_entry_desc: RX Entry descriptor | 179 | * struct rxdone_entry_desc: RX Entry descriptor |
@@ -182,6 +187,7 @@ enum rxdone_entry_desc_flags { | |||
182 | * @size: Data size of the received frame. | 187 | * @size: Data size of the received frame. |
183 | * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags). | 188 | * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags). |
184 | * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags). | 189 | * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags). |
190 | * @rate_mode: Rate mode (See @enum rate_modulation). | ||
185 | * @cipher: Cipher type used during decryption. | 191 | * @cipher: Cipher type used during decryption. |
186 | * @cipher_status: Decryption status. | 192 | * @cipher_status: Decryption status. |
187 | * @iv: IV/EIV data used during decryption. | 193 | * @iv: IV/EIV data used during decryption. |
@@ -195,6 +201,7 @@ struct rxdone_entry_desc { | |||
195 | int size; | 201 | int size; |
196 | int flags; | 202 | int flags; |
197 | int dev_flags; | 203 | int dev_flags; |
204 | u16 rate_mode; | ||
198 | u8 cipher; | 205 | u8 cipher; |
199 | u8 cipher_status; | 206 | u8 cipher_status; |
200 | 207 | ||
@@ -248,6 +255,9 @@ struct txdone_entry_desc { | |||
248 | * @ENTRY_TXD_ENCRYPT_PAIRWISE: Use pairwise key table (instead of shared). | 255 | * @ENTRY_TXD_ENCRYPT_PAIRWISE: Use pairwise key table (instead of shared). |
249 | * @ENTRY_TXD_ENCRYPT_IV: Generate IV/EIV in hardware. | 256 | * @ENTRY_TXD_ENCRYPT_IV: Generate IV/EIV in hardware. |
250 | * @ENTRY_TXD_ENCRYPT_MMIC: Generate MIC in hardware. | 257 | * @ENTRY_TXD_ENCRYPT_MMIC: Generate MIC in hardware. |
258 | * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU. | ||
259 | * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth. | ||
260 | * @ENTRY_TXD_HT_SHORT_GI: Use short GI. | ||
251 | */ | 261 | */ |
252 | enum txentry_desc_flags { | 262 | enum txentry_desc_flags { |
253 | ENTRY_TXD_RTS_FRAME, | 263 | ENTRY_TXD_RTS_FRAME, |
@@ -263,6 +273,9 @@ enum txentry_desc_flags { | |||
263 | ENTRY_TXD_ENCRYPT_PAIRWISE, | 273 | ENTRY_TXD_ENCRYPT_PAIRWISE, |
264 | ENTRY_TXD_ENCRYPT_IV, | 274 | ENTRY_TXD_ENCRYPT_IV, |
265 | ENTRY_TXD_ENCRYPT_MMIC, | 275 | ENTRY_TXD_ENCRYPT_MMIC, |
276 | ENTRY_TXD_HT_AMPDU, | ||
277 | ENTRY_TXD_HT_BW_40, | ||
278 | ENTRY_TXD_HT_SHORT_GI, | ||
266 | }; | 279 | }; |
267 | 280 | ||
268 | /** | 281 | /** |
@@ -278,7 +291,11 @@ enum txentry_desc_flags { | |||
278 | * @length_low: PLCP length low word. | 291 | * @length_low: PLCP length low word. |
279 | * @signal: PLCP signal. | 292 | * @signal: PLCP signal. |
280 | * @service: PLCP service. | 293 | * @service: PLCP service. |
294 | * @msc: MCS. | ||
295 | * @stbc: STBC. | ||
296 | * @ba_size: BA size. | ||
281 | * @rate_mode: Rate mode (See @enum rate_modulation). | 297 | * @rate_mode: Rate mode (See @enum rate_modulation). |
298 | * @mpdu_density: MDPU density. | ||
282 | * @retry_limit: Max number of retries. | 299 | * @retry_limit: Max number of retries. |
283 | * @aifs: AIFS value. | 300 | * @aifs: AIFS value. |
284 | * @ifs: IFS value. | 301 | * @ifs: IFS value. |
@@ -302,7 +319,11 @@ struct txentry_desc { | |||
302 | u16 signal; | 319 | u16 signal; |
303 | u16 service; | 320 | u16 service; |
304 | 321 | ||
322 | u16 mcs; | ||
323 | u16 stbc; | ||
324 | u16 ba_size; | ||
305 | u16 rate_mode; | 325 | u16 rate_mode; |
326 | u16 mpdu_density; | ||
306 | 327 | ||
307 | short retry_limit; | 328 | short retry_limit; |
308 | short aifs; | 329 | short aifs; |