diff options
Diffstat (limited to 'drivers/net/wireless/ath/carl9170/tx.c')
-rw-r--r-- | drivers/net/wireless/ath/carl9170/tx.c | 290 |
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 | ||
664 | static 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 | |||
664 | static __le32 carl9170_tx_physet(struct ar9170 *ar, | 721 | static __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 | |||
1445 | int 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); | ||
1458 | retry: | ||
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 | |||
1472 | found: | ||
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 | } | ||
1583 | out_unlock: | ||
1584 | rcu_read_unlock(); | ||
1585 | return 0; | ||
1586 | |||
1587 | err_unlock: | ||
1588 | spin_unlock_bh(&ar->beacon_lock); | ||
1589 | |||
1590 | err_free: | ||
1591 | rcu_read_unlock(); | ||
1592 | dev_kfree_skb_any(skb); | ||
1593 | return err; | ||
1594 | } | ||