aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/carl9170
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2011-07-16 11:30:19 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-07-18 14:29:44 -0400
commit582965672831180b2e1f5e15ea1f7dc6f5b93018 (patch)
treea24d169de9d5bf389b053b16342696cc61517c0a /drivers/net/wireless/ath/carl9170
parent943c33996f9b0851c4122dc96cae08d4ba8debf0 (diff)
carl9170: set beacon xmit power to the max
Harshal Chhaya discovered during network tests, that several of his clients dropped-off the network. The captured packets shows that the beacons sent by the AP are at a much lower power than the other data packets. The reason for this mishap: The driver never updated the beacon phy register, so all beacons were always sent at the lowest power. Reference: http://marc.info/?l=linux-wireless&m=131067225105801 Reported-by: Harshal Chhaya <harshal@gmail.com> Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/carl9170')
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c191
1 files changed, 108 insertions, 83 deletions
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index 0f8cdeffd645..d20946939cd8 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -661,11 +661,67 @@ void carl9170_tx_process_status(struct ar9170 *ar,
661 } 661 }
662} 662}
663 663
664static void carl9170_tx_rate_tpc_chains(struct ar9170 *ar,
665 struct ieee80211_tx_info *info, struct ieee80211_tx_rate *txrate,
666 unsigned int *phyrate, unsigned int *tpc, unsigned int *chains)
667{
668 struct ieee80211_rate *rate = NULL;
669 u8 *txpower;
670 unsigned int idx;
671
672 idx = txrate->idx;
673 *tpc = 0;
674 *phyrate = 0;
675
676 if (txrate->flags & IEEE80211_TX_RC_MCS) {
677 if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
678 /* +1 dBm for HT40 */
679 *tpc += 2;
680
681 if (info->band == IEEE80211_BAND_2GHZ)
682 txpower = ar->power_2G_ht40;
683 else
684 txpower = ar->power_5G_ht40;
685 } else {
686 if (info->band == IEEE80211_BAND_2GHZ)
687 txpower = ar->power_2G_ht20;
688 else
689 txpower = ar->power_5G_ht20;
690 }
691
692 *phyrate = txrate->idx;
693 *tpc += txpower[idx & 7];
694 } else {
695 if (info->band == IEEE80211_BAND_2GHZ) {
696 if (idx < 4)
697 txpower = ar->power_2G_cck;
698 else
699 txpower = ar->power_2G_ofdm;
700 } else {
701 txpower = ar->power_5G_leg;
702 idx += 4;
703 }
704
705 rate = &__carl9170_ratetable[idx];
706 *tpc += txpower[(rate->hw_value & 0x30) >> 4];
707 *phyrate = rate->hw_value & 0xf;
708 }
709
710 if (ar->eeprom.tx_mask == 1) {
711 *chains = AR9170_TX_PHY_TXCHAIN_1;
712 } else {
713 if (!(txrate->flags & IEEE80211_TX_RC_MCS) &&
714 rate && rate->bitrate >= 360)
715 *chains = AR9170_TX_PHY_TXCHAIN_1;
716 else
717 *chains = AR9170_TX_PHY_TXCHAIN_2;
718 }
719}
720
664static __le32 carl9170_tx_physet(struct ar9170 *ar, 721static __le32 carl9170_tx_physet(struct ar9170 *ar,
665 struct ieee80211_tx_info *info, struct ieee80211_tx_rate *txrate) 722 struct ieee80211_tx_info *info, struct ieee80211_tx_rate *txrate)
666{ 723{
667 struct ieee80211_rate *rate = NULL; 724 unsigned int power = 0, chains = 0, phyrate = 0;
668 u32 power, chains;
669 __le32 tmp; 725 __le32 tmp;
670 726
671 tmp = cpu_to_le32(0); 727 tmp = cpu_to_le32(0);
@@ -682,35 +738,12 @@ static __le32 carl9170_tx_physet(struct ar9170 *ar,
682 tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI); 738 tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI);
683 739
684 if (txrate->flags & IEEE80211_TX_RC_MCS) { 740 if (txrate->flags & IEEE80211_TX_RC_MCS) {
685 u32 r = txrate->idx; 741 SET_VAL(AR9170_TX_PHY_MCS, phyrate, txrate->idx);
686 u8 *txpower;
687 742
688 /* heavy clip control */ 743 /* heavy clip control */
689 tmp |= cpu_to_le32((r & 0x7) << 744 tmp |= cpu_to_le32((txrate->idx & 0x7) <<
690 AR9170_TX_PHY_TX_HEAVY_CLIP_S); 745 AR9170_TX_PHY_TX_HEAVY_CLIP_S);
691 746
692 if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
693 if (info->band == IEEE80211_BAND_5GHZ)
694 txpower = ar->power_5G_ht40;
695 else
696 txpower = ar->power_2G_ht40;
697 } else {
698 if (info->band == IEEE80211_BAND_5GHZ)
699 txpower = ar->power_5G_ht20;
700 else
701 txpower = ar->power_2G_ht20;
702 }
703
704 power = txpower[r & 7];
705
706 /* +1 dBm for HT40 */
707 if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
708 power += 2;
709
710 r <<= AR9170_TX_PHY_MCS_S;
711 BUG_ON(r & ~AR9170_TX_PHY_MCS);
712
713 tmp |= cpu_to_le32(r & AR9170_TX_PHY_MCS);
714 tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_HT); 747 tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_HT);
715 748
716 /* 749 /*
@@ -720,34 +753,15 @@ static __le32 carl9170_tx_physet(struct ar9170 *ar,
720 * tmp |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD); 753 * tmp |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD);
721 */ 754 */
722 } else { 755 } else {
723 u8 *txpower; 756 if (info->band == IEEE80211_BAND_2GHZ) {
724 u32 mod; 757 if (txrate->idx <= AR9170_TX_PHY_RATE_CCK_11M)
725 u32 phyrate; 758 tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_CCK);
726 u8 idx = txrate->idx; 759 else
727 760 tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_OFDM);
728 if (info->band != IEEE80211_BAND_2GHZ) {
729 idx += 4;
730 txpower = ar->power_5G_leg;
731 mod = AR9170_TX_PHY_MOD_OFDM;
732 } else { 761 } else {
733 if (idx < 4) { 762 tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_OFDM);
734 txpower = ar->power_2G_cck;
735 mod = AR9170_TX_PHY_MOD_CCK;
736 } else {
737 mod = AR9170_TX_PHY_MOD_OFDM;
738 txpower = ar->power_2G_ofdm;
739 }
740 } 763 }
741 764
742 rate = &__carl9170_ratetable[idx];
743
744 phyrate = rate->hw_value & 0xF;
745 power = txpower[(rate->hw_value & 0x30) >> 4];
746 phyrate <<= AR9170_TX_PHY_MCS_S;
747
748 tmp |= cpu_to_le32(mod);
749 tmp |= cpu_to_le32(phyrate);
750
751 /* 765 /*
752 * short preamble seems to be broken too. 766 * short preamble seems to be broken too.
753 * 767 *
@@ -755,23 +769,12 @@ static __le32 carl9170_tx_physet(struct ar9170 *ar,
755 * tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE); 769 * tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE);
756 */ 770 */
757 } 771 }
758 power <<= AR9170_TX_PHY_TX_PWR_S; 772 carl9170_tx_rate_tpc_chains(ar, info, txrate,
759 power &= AR9170_TX_PHY_TX_PWR; 773 &phyrate, &power, &chains);
760 tmp |= cpu_to_le32(power);
761
762 /* set TX chains */
763 if (ar->eeprom.tx_mask == 1) {
764 chains = AR9170_TX_PHY_TXCHAIN_1;
765 } else {
766 chains = AR9170_TX_PHY_TXCHAIN_2;
767
768 /* >= 36M legacy OFDM - use only one chain */
769 if (rate && rate->bitrate >= 360 &&
770 !(txrate->flags & IEEE80211_TX_RC_MCS))
771 chains = AR9170_TX_PHY_TXCHAIN_1;
772 }
773 tmp |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_S);
774 774
775 tmp |= cpu_to_le32(SET_CONSTVAL(AR9170_TX_PHY_MCS, phyrate));
776 tmp |= cpu_to_le32(SET_CONSTVAL(AR9170_TX_PHY_TX_PWR, power));
777 tmp |= cpu_to_le32(SET_CONSTVAL(AR9170_TX_PHY_TXCHAIN, chains));
775 return tmp; 778 return tmp;
776} 779}
777 780
@@ -1444,8 +1447,10 @@ int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
1444 struct sk_buff *skb = NULL; 1447 struct sk_buff *skb = NULL;
1445 struct carl9170_vif_info *cvif; 1448 struct carl9170_vif_info *cvif;
1446 struct ieee80211_tx_info *txinfo; 1449 struct ieee80211_tx_info *txinfo;
1450 struct ieee80211_tx_rate *rate;
1447 __le32 *data, *old = NULL; 1451 __le32 *data, *old = NULL;
1448 u32 word, off, addr, len; 1452 unsigned int plcp, power, chains;
1453 u32 word, ht1, off, addr, len;
1449 int i = 0, err = 0; 1454 int i = 0, err = 0;
1450 1455
1451 rcu_read_lock(); 1456 rcu_read_lock();
@@ -1476,11 +1481,6 @@ found:
1476 } 1481 }
1477 1482
1478 txinfo = IEEE80211_SKB_CB(skb); 1483 txinfo = IEEE80211_SKB_CB(skb);
1479 if (txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS) {
1480 err = -EINVAL;
1481 goto err_free;
1482 }
1483
1484 spin_lock_bh(&ar->beacon_lock); 1484 spin_lock_bh(&ar->beacon_lock);
1485 data = (__le32 *)skb->data; 1485 data = (__le32 *)skb->data;
1486 if (cvif->beacon) 1486 if (cvif->beacon)
@@ -1510,18 +1510,43 @@ found:
1510 goto err_unlock; 1510 goto err_unlock;
1511 } 1511 }
1512 1512
1513 i = txinfo->control.rates[0].idx; 1513 ht1 = AR9170_MAC_BCN_HT1_TX_ANT0;
1514 if (txinfo->band != IEEE80211_BAND_2GHZ) 1514 rate = &txinfo->control.rates[0];
1515 i += 4; 1515 carl9170_tx_rate_tpc_chains(ar, txinfo, rate, &plcp, &power, &chains);
1516 if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS)) {
1517 if (plcp <= AR9170_TX_PHY_RATE_CCK_11M)
1518 plcp |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
1519 else
1520 plcp |= ((skb->len + FCS_LEN) << 16) + 0x0010;
1521 } else {
1522 ht1 |= AR9170_MAC_BCN_HT1_HT_EN;
1523 if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
1524 plcp |= AR9170_MAC_BCN_HT2_SGI;
1516 1525
1517 word = __carl9170_ratetable[i].hw_value & 0xf; 1526 if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
1518 if (i < 4) 1527 ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_SHARED;
1519 word |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400; 1528 plcp |= AR9170_MAC_BCN_HT2_BW40;
1520 else 1529 }
1521 word |= ((skb->len + FCS_LEN) << 16) + 0x0010; 1530 if (rate->flags & IEEE80211_TX_RC_DUP_DATA) {
1531 ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_DUP;
1532 plcp |= AR9170_MAC_BCN_HT2_BW40;
1533 }
1534
1535 SET_VAL(AR9170_MAC_BCN_HT2_LEN, plcp, skb->len + FCS_LEN);
1536 }
1537
1538 SET_VAL(AR9170_MAC_BCN_HT1_PWR_CTRL, ht1, 7);
1539 SET_VAL(AR9170_MAC_BCN_HT1_TPC, ht1, power);
1540 SET_VAL(AR9170_MAC_BCN_HT1_CHAIN_MASK, ht1, chains);
1541 if (chains == AR9170_TX_PHY_TXCHAIN_2)
1542 ht1 |= AR9170_MAC_BCN_HT1_TX_ANT1;
1522 1543
1523 carl9170_async_regwrite_begin(ar); 1544 carl9170_async_regwrite_begin(ar);
1524 carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, word); 1545 carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT1, ht1);
1546 if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS))
1547 carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, plcp);
1548 else
1549 carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT2, plcp);
1525 1550
1526 for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { 1551 for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
1527 /* 1552 /*