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/wireless/rt2x00/rt2x00dev.c | |
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/wireless/rt2x00/rt2x00dev.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 92 |
1 files changed, 67 insertions, 25 deletions
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; |