aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/carl9170/tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/carl9170/tx.c')
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c290
1 files changed, 222 insertions, 68 deletions
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index e94084fcf6f5..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
@@ -1438,3 +1441,154 @@ void carl9170_tx_scheduler(struct ar9170 *ar)
1438 if (ar->tx_schedule) 1441 if (ar->tx_schedule)
1439 carl9170_tx(ar); 1442 carl9170_tx(ar);
1440} 1443}
1444
1445int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
1446{
1447 struct sk_buff *skb = NULL;
1448 struct carl9170_vif_info *cvif;
1449 struct ieee80211_tx_info *txinfo;
1450 struct ieee80211_tx_rate *rate;
1451 __le32 *data, *old = NULL;
1452 unsigned int plcp, power, chains;
1453 u32 word, ht1, off, addr, len;
1454 int i = 0, err = 0;
1455
1456 rcu_read_lock();
1457 cvif = rcu_dereference(ar->beacon_iter);
1458retry:
1459 if (ar->vifs == 0 || !cvif)
1460 goto out_unlock;
1461
1462 list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) {
1463 if (cvif->active && cvif->enable_beacon)
1464 goto found;
1465 }
1466
1467 if (!ar->beacon_enabled || i++)
1468 goto out_unlock;
1469
1470 goto retry;
1471
1472found:
1473 rcu_assign_pointer(ar->beacon_iter, cvif);
1474
1475 skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif),
1476 NULL, NULL);
1477
1478 if (!skb) {
1479 err = -ENOMEM;
1480 goto err_free;
1481 }
1482
1483 txinfo = IEEE80211_SKB_CB(skb);
1484 spin_lock_bh(&ar->beacon_lock);
1485 data = (__le32 *)skb->data;
1486 if (cvif->beacon)
1487 old = (__le32 *)cvif->beacon->data;
1488
1489 off = cvif->id * AR9170_MAC_BCN_LENGTH_MAX;
1490 addr = ar->fw.beacon_addr + off;
1491 len = roundup(skb->len + FCS_LEN, 4);
1492
1493 if ((off + len) > ar->fw.beacon_max_len) {
1494 if (net_ratelimit()) {
1495 wiphy_err(ar->hw->wiphy, "beacon does not "
1496 "fit into device memory!\n");
1497 }
1498 err = -EINVAL;
1499 goto err_unlock;
1500 }
1501
1502 if (len > AR9170_MAC_BCN_LENGTH_MAX) {
1503 if (net_ratelimit()) {
1504 wiphy_err(ar->hw->wiphy, "no support for beacons "
1505 "bigger than %d (yours:%d).\n",
1506 AR9170_MAC_BCN_LENGTH_MAX, len);
1507 }
1508
1509 err = -EMSGSIZE;
1510 goto err_unlock;
1511 }
1512
1513 ht1 = AR9170_MAC_BCN_HT1_TX_ANT0;
1514 rate = &txinfo->control.rates[0];
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;
1525
1526 if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
1527 ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_SHARED;
1528 plcp |= AR9170_MAC_BCN_HT2_BW40;
1529 }
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;
1543
1544 carl9170_async_regwrite_begin(ar);
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);
1550
1551 for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
1552 /*
1553 * XXX: This accesses beyond skb data for up
1554 * to the last 3 bytes!!
1555 */
1556
1557 if (old && (data[i] == old[i]))
1558 continue;
1559
1560 word = le32_to_cpu(data[i]);
1561 carl9170_async_regwrite(addr + 4 * i, word);
1562 }
1563 carl9170_async_regwrite_finish();
1564
1565 dev_kfree_skb_any(cvif->beacon);
1566 cvif->beacon = NULL;
1567
1568 err = carl9170_async_regwrite_result();
1569 if (!err)
1570 cvif->beacon = skb;
1571 spin_unlock_bh(&ar->beacon_lock);
1572 if (err)
1573 goto err_free;
1574
1575 if (submit) {
1576 err = carl9170_bcn_ctrl(ar, cvif->id,
1577 CARL9170_BCN_CTRL_CAB_TRIGGER,
1578 addr, skb->len + FCS_LEN);
1579
1580 if (err)
1581 goto err_free;
1582 }
1583out_unlock:
1584 rcu_read_unlock();
1585 return 0;
1586
1587err_unlock:
1588 spin_unlock_bh(&ar->beacon_lock);
1589
1590err_free:
1591 rcu_read_unlock();
1592 dev_kfree_skb_any(skb);
1593 return err;
1594}