diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/htc_drv_main.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 95 |
1 files changed, 82 insertions, 13 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 4de38643cb53..5aa104fe7eeb 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -332,6 +332,11 @@ static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) | |||
332 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); | 332 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); |
333 | hvif.index = priv->mon_vif_idx; | 333 | hvif.index = priv->mon_vif_idx; |
334 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); | 334 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); |
335 | if (ret) { | ||
336 | ath_err(common, "Unable to remove monitor interface at idx: %d\n", | ||
337 | priv->mon_vif_idx); | ||
338 | } | ||
339 | |||
335 | priv->nvifs--; | 340 | priv->nvifs--; |
336 | priv->vif_slot &= ~(1 << priv->mon_vif_idx); | 341 | priv->vif_slot &= ~(1 << priv->mon_vif_idx); |
337 | } | 342 | } |
@@ -462,6 +467,7 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, | |||
462 | struct ath9k_htc_sta *ista; | 467 | struct ath9k_htc_sta *ista; |
463 | int ret, sta_idx; | 468 | int ret, sta_idx; |
464 | u8 cmd_rsp; | 469 | u8 cmd_rsp; |
470 | u16 maxampdu; | ||
465 | 471 | ||
466 | if (priv->nstations >= ATH9K_HTC_MAX_STA) | 472 | if (priv->nstations >= ATH9K_HTC_MAX_STA) |
467 | return -ENOBUFS; | 473 | return -ENOBUFS; |
@@ -485,7 +491,15 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, | |||
485 | 491 | ||
486 | tsta.sta_index = sta_idx; | 492 | tsta.sta_index = sta_idx; |
487 | tsta.vif_index = avp->index; | 493 | tsta.vif_index = avp->index; |
488 | tsta.maxampdu = cpu_to_be16(0xffff); | 494 | |
495 | if (!sta) { | ||
496 | tsta.maxampdu = cpu_to_be16(0xffff); | ||
497 | } else { | ||
498 | maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + | ||
499 | sta->ht_cap.ampdu_factor); | ||
500 | tsta.maxampdu = cpu_to_be16(maxampdu); | ||
501 | } | ||
502 | |||
489 | if (sta && sta->ht_cap.ht_supported) | 503 | if (sta && sta->ht_cap.ht_supported) |
490 | tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); | 504 | tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); |
491 | 505 | ||
@@ -558,7 +572,8 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv, | |||
558 | return 0; | 572 | return 0; |
559 | } | 573 | } |
560 | 574 | ||
561 | int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) | 575 | int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, |
576 | u8 enable_coex) | ||
562 | { | 577 | { |
563 | struct ath9k_htc_cap_target tcap; | 578 | struct ath9k_htc_cap_target tcap; |
564 | int ret; | 579 | int ret; |
@@ -566,13 +581,9 @@ int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) | |||
566 | 581 | ||
567 | memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target)); | 582 | memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target)); |
568 | 583 | ||
569 | /* FIXME: Values are hardcoded */ | 584 | tcap.ampdu_limit = cpu_to_be32(0xffff); |
570 | tcap.flags = 0x240c40; | 585 | tcap.ampdu_subframes = priv->hw->max_tx_aggregation_subframes; |
571 | tcap.flags_ext = 0x80601000; | 586 | tcap.enable_coex = enable_coex; |
572 | tcap.ampdu_limit = 0xffff0000; | ||
573 | tcap.ampdu_subframes = 20; | ||
574 | tcap.tx_chainmask_legacy = priv->ah->caps.tx_chainmask; | ||
575 | tcap.protmode = 1; | ||
576 | tcap.tx_chainmask = priv->ah->caps.tx_chainmask; | 587 | tcap.tx_chainmask = priv->ah->caps.tx_chainmask; |
577 | 588 | ||
578 | WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap); | 589 | WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap); |
@@ -931,7 +942,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
931 | 942 | ||
932 | ath9k_host_rx_init(priv); | 943 | ath9k_host_rx_init(priv); |
933 | 944 | ||
934 | ret = ath9k_htc_update_cap_target(priv); | 945 | ret = ath9k_htc_update_cap_target(priv, 0); |
935 | if (ret) | 946 | if (ret) |
936 | ath_dbg(common, ATH_DBG_CONFIG, | 947 | ath_dbg(common, ATH_DBG_CONFIG, |
937 | "Failed to update capability in target\n"); | 948 | "Failed to update capability in target\n"); |
@@ -964,7 +975,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
964 | struct ath9k_htc_priv *priv = hw->priv; | 975 | struct ath9k_htc_priv *priv = hw->priv; |
965 | struct ath_hw *ah = priv->ah; | 976 | struct ath_hw *ah = priv->ah; |
966 | struct ath_common *common = ath9k_hw_common(ah); | 977 | struct ath_common *common = ath9k_hw_common(ah); |
967 | int ret = 0; | 978 | int ret __attribute__ ((unused)); |
968 | u8 cmd_rsp; | 979 | u8 cmd_rsp; |
969 | 980 | ||
970 | mutex_lock(&priv->mutex); | 981 | mutex_lock(&priv->mutex); |
@@ -992,9 +1003,11 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
992 | /* Cancel all the running timers/work .. */ | 1003 | /* Cancel all the running timers/work .. */ |
993 | cancel_work_sync(&priv->fatal_work); | 1004 | cancel_work_sync(&priv->fatal_work); |
994 | cancel_work_sync(&priv->ps_work); | 1005 | cancel_work_sync(&priv->ps_work); |
995 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | 1006 | |
1007 | #ifdef CONFIG_MAC80211_LEDS | ||
1008 | cancel_work_sync(&priv->led_work); | ||
1009 | #endif | ||
996 | ath9k_htc_stop_ani(priv); | 1010 | ath9k_htc_stop_ani(priv); |
997 | ath9k_led_stop_brightness(priv); | ||
998 | 1011 | ||
999 | mutex_lock(&priv->mutex); | 1012 | mutex_lock(&priv->mutex); |
1000 | 1013 | ||
@@ -1135,6 +1148,10 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, | |||
1135 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); | 1148 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); |
1136 | hvif.index = avp->index; | 1149 | hvif.index = avp->index; |
1137 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); | 1150 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); |
1151 | if (ret) { | ||
1152 | ath_err(common, "Unable to remove interface at idx: %d\n", | ||
1153 | avp->index); | ||
1154 | } | ||
1138 | priv->nvifs--; | 1155 | priv->nvifs--; |
1139 | priv->vif_slot &= ~(1 << avp->index); | 1156 | priv->vif_slot &= ~(1 << avp->index); |
1140 | 1157 | ||
@@ -1567,6 +1584,7 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1567 | int ret = 0; | 1584 | int ret = 0; |
1568 | 1585 | ||
1569 | mutex_lock(&priv->mutex); | 1586 | mutex_lock(&priv->mutex); |
1587 | ath9k_htc_ps_wakeup(priv); | ||
1570 | 1588 | ||
1571 | switch (action) { | 1589 | switch (action) { |
1572 | case IEEE80211_AMPDU_RX_START: | 1590 | case IEEE80211_AMPDU_RX_START: |
@@ -1592,6 +1610,7 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1592 | ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n"); | 1610 | ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n"); |
1593 | } | 1611 | } |
1594 | 1612 | ||
1613 | ath9k_htc_ps_restore(priv); | ||
1595 | mutex_unlock(&priv->mutex); | 1614 | mutex_unlock(&priv->mutex); |
1596 | 1615 | ||
1597 | return ret; | 1616 | return ret; |
@@ -1642,6 +1661,55 @@ static void ath9k_htc_set_coverage_class(struct ieee80211_hw *hw, | |||
1642 | mutex_unlock(&priv->mutex); | 1661 | mutex_unlock(&priv->mutex); |
1643 | } | 1662 | } |
1644 | 1663 | ||
1664 | /* | ||
1665 | * Currently, this is used only for selecting the minimum rate | ||
1666 | * for management frames, rate selection for data frames remain | ||
1667 | * unaffected. | ||
1668 | */ | ||
1669 | static int ath9k_htc_set_bitrate_mask(struct ieee80211_hw *hw, | ||
1670 | struct ieee80211_vif *vif, | ||
1671 | const struct cfg80211_bitrate_mask *mask) | ||
1672 | { | ||
1673 | struct ath9k_htc_priv *priv = hw->priv; | ||
1674 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
1675 | struct ath9k_htc_target_rate_mask tmask; | ||
1676 | struct ath9k_htc_vif *avp = (void *)vif->drv_priv; | ||
1677 | int ret = 0; | ||
1678 | u8 cmd_rsp; | ||
1679 | |||
1680 | memset(&tmask, 0, sizeof(struct ath9k_htc_target_rate_mask)); | ||
1681 | |||
1682 | tmask.vif_index = avp->index; | ||
1683 | tmask.band = IEEE80211_BAND_2GHZ; | ||
1684 | tmask.mask = cpu_to_be32(mask->control[IEEE80211_BAND_2GHZ].legacy); | ||
1685 | |||
1686 | WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask); | ||
1687 | if (ret) { | ||
1688 | ath_err(common, | ||
1689 | "Unable to set 2G rate mask for " | ||
1690 | "interface at idx: %d\n", avp->index); | ||
1691 | goto out; | ||
1692 | } | ||
1693 | |||
1694 | tmask.band = IEEE80211_BAND_5GHZ; | ||
1695 | tmask.mask = cpu_to_be32(mask->control[IEEE80211_BAND_5GHZ].legacy); | ||
1696 | |||
1697 | WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask); | ||
1698 | if (ret) { | ||
1699 | ath_err(common, | ||
1700 | "Unable to set 5G rate mask for " | ||
1701 | "interface at idx: %d\n", avp->index); | ||
1702 | goto out; | ||
1703 | } | ||
1704 | |||
1705 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1706 | "Set bitrate masks: 0x%x, 0x%x\n", | ||
1707 | mask->control[IEEE80211_BAND_2GHZ].legacy, | ||
1708 | mask->control[IEEE80211_BAND_5GHZ].legacy); | ||
1709 | out: | ||
1710 | return ret; | ||
1711 | } | ||
1712 | |||
1645 | struct ieee80211_ops ath9k_htc_ops = { | 1713 | struct ieee80211_ops ath9k_htc_ops = { |
1646 | .tx = ath9k_htc_tx, | 1714 | .tx = ath9k_htc_tx, |
1647 | .start = ath9k_htc_start, | 1715 | .start = ath9k_htc_start, |
@@ -1664,4 +1732,5 @@ struct ieee80211_ops ath9k_htc_ops = { | |||
1664 | .set_rts_threshold = ath9k_htc_set_rts_threshold, | 1732 | .set_rts_threshold = ath9k_htc_set_rts_threshold, |
1665 | .rfkill_poll = ath9k_htc_rfkill_poll_state, | 1733 | .rfkill_poll = ath9k_htc_rfkill_poll_state, |
1666 | .set_coverage_class = ath9k_htc_set_coverage_class, | 1734 | .set_coverage_class = ath9k_htc_set_coverage_class, |
1735 | .set_bitrate_mask = ath9k_htc_set_bitrate_mask, | ||
1667 | }; | 1736 | }; |