diff options
author | Christian Lamparter <chunkeey@googlemail.com> | 2010-10-29 18:36:53 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-11-15 13:25:35 -0500 |
commit | 3eedb6f436858f3e864139dc184adc9a51440c92 (patch) | |
tree | 85367b42ac609cffd673c18940a498bf9a4af3cb | |
parent | 2a6cef513fab525399e484edc9bfb39b6d462f76 (diff) |
carl9170: configurable beacon rates
Previously, the beacon rate was fixed to either:
* 1Mb/s [2.4GHz band]
* 6Mb/s [5GHz band]
This limitation has been addressed and now the
beacon rate is selected by ieee80211_tx_info's
rate control info, almost like any ordinary
data frame.
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/carl9170/mac.c | 52 |
1 files changed, 32 insertions, 20 deletions
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c index c34eeeeb8af3..385cf508479b 100644 --- a/drivers/net/wireless/ath/carl9170/mac.c +++ b/drivers/net/wireless/ath/carl9170/mac.c | |||
@@ -457,8 +457,9 @@ int carl9170_set_beacon_timers(struct ar9170 *ar) | |||
457 | 457 | ||
458 | int carl9170_update_beacon(struct ar9170 *ar, const bool submit) | 458 | int carl9170_update_beacon(struct ar9170 *ar, const bool submit) |
459 | { | 459 | { |
460 | struct sk_buff *skb; | 460 | struct sk_buff *skb = NULL; |
461 | struct carl9170_vif_info *cvif; | 461 | struct carl9170_vif_info *cvif; |
462 | struct ieee80211_tx_info *txinfo; | ||
462 | __le32 *data, *old = NULL; | 463 | __le32 *data, *old = NULL; |
463 | u32 word, off, addr, len; | 464 | u32 word, off, addr, len; |
464 | int i = 0, err = 0; | 465 | int i = 0, err = 0; |
@@ -487,7 +488,13 @@ found: | |||
487 | 488 | ||
488 | if (!skb) { | 489 | if (!skb) { |
489 | err = -ENOMEM; | 490 | err = -ENOMEM; |
490 | goto out_unlock; | 491 | goto err_free; |
492 | } | ||
493 | |||
494 | txinfo = IEEE80211_SKB_CB(skb); | ||
495 | if (txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS) { | ||
496 | err = -EINVAL; | ||
497 | goto err_free; | ||
491 | } | 498 | } |
492 | 499 | ||
493 | spin_lock_bh(&ar->beacon_lock); | 500 | spin_lock_bh(&ar->beacon_lock); |
@@ -504,11 +511,8 @@ found: | |||
504 | wiphy_err(ar->hw->wiphy, "beacon does not " | 511 | wiphy_err(ar->hw->wiphy, "beacon does not " |
505 | "fit into device memory!\n"); | 512 | "fit into device memory!\n"); |
506 | } | 513 | } |
507 | |||
508 | spin_unlock_bh(&ar->beacon_lock); | ||
509 | dev_kfree_skb_any(skb); | ||
510 | err = -EINVAL; | 514 | err = -EINVAL; |
511 | goto out_unlock; | 515 | goto err_unlock; |
512 | } | 516 | } |
513 | 517 | ||
514 | if (len > AR9170_MAC_BCN_LENGTH_MAX) { | 518 | if (len > AR9170_MAC_BCN_LENGTH_MAX) { |
@@ -518,22 +522,22 @@ found: | |||
518 | AR9170_MAC_BCN_LENGTH_MAX, len); | 522 | AR9170_MAC_BCN_LENGTH_MAX, len); |
519 | } | 523 | } |
520 | 524 | ||
521 | spin_unlock_bh(&ar->beacon_lock); | ||
522 | dev_kfree_skb_any(skb); | ||
523 | err = -EMSGSIZE; | 525 | err = -EMSGSIZE; |
524 | goto out_unlock; | 526 | goto err_unlock; |
525 | } | 527 | } |
526 | 528 | ||
527 | carl9170_async_regwrite_begin(ar); | 529 | i = txinfo->control.rates[0].idx; |
530 | if (txinfo->band != IEEE80211_BAND_2GHZ) | ||
531 | i += 4; | ||
528 | 532 | ||
529 | /* XXX: use skb->cb info */ | 533 | word = __carl9170_ratetable[i].hw_value & 0xf; |
530 | if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) { | 534 | if (i < 4) |
531 | carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, | 535 | word |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400; |
532 | ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400); | 536 | else |
533 | } else { | 537 | word |= ((skb->len + FCS_LEN) << 16) + 0x0010; |
534 | carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, | 538 | |
535 | ((skb->len + FCS_LEN) << 16) + 0x001b); | 539 | carl9170_async_regwrite_begin(ar); |
536 | } | 540 | carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, word); |
537 | 541 | ||
538 | for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { | 542 | for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { |
539 | /* | 543 | /* |
@@ -557,7 +561,7 @@ found: | |||
557 | cvif->beacon = skb; | 561 | cvif->beacon = skb; |
558 | spin_unlock_bh(&ar->beacon_lock); | 562 | spin_unlock_bh(&ar->beacon_lock); |
559 | if (err) | 563 | if (err) |
560 | goto out_unlock; | 564 | goto err_free; |
561 | 565 | ||
562 | if (submit) { | 566 | if (submit) { |
563 | err = carl9170_bcn_ctrl(ar, cvif->id, | 567 | err = carl9170_bcn_ctrl(ar, cvif->id, |
@@ -565,10 +569,18 @@ found: | |||
565 | addr, skb->len + FCS_LEN); | 569 | addr, skb->len + FCS_LEN); |
566 | 570 | ||
567 | if (err) | 571 | if (err) |
568 | goto out_unlock; | 572 | goto err_free; |
569 | } | 573 | } |
570 | out_unlock: | 574 | out_unlock: |
571 | rcu_read_unlock(); | 575 | rcu_read_unlock(); |
576 | return 0; | ||
577 | |||
578 | err_unlock: | ||
579 | spin_unlock_bh(&ar->beacon_lock); | ||
580 | |||
581 | err_free: | ||
582 | rcu_read_unlock(); | ||
583 | dev_kfree_skb_any(skb); | ||
572 | return err; | 584 | return err; |
573 | } | 585 | } |
574 | 586 | ||