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 | 67 |
1 files changed, 51 insertions, 16 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 7b77968..b6cd36c 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -139,21 +139,26 @@ static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif) struct ath9k_vif_iter_data *iter_data = data; int i; - for (i = 0; i < ETH_ALEN; i++) - iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]); + if (iter_data->hw_macaddr != NULL) { + for (i = 0; i < ETH_ALEN; i++) + iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]); + } else { + iter_data->hw_macaddr = mac; + } } -static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv, +static void ath9k_htc_set_mac_bssid_mask(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif) { struct ath_common *common = ath9k_hw_common(priv->ah); struct ath9k_vif_iter_data iter_data; /* - * Use the hardware MAC address as reference, the hardware uses it - * together with the BSSID mask when matching addresses. + * Pick the MAC address of the first interface as the new hardware + * MAC address. The hardware will use it together with the BSSID mask + * when matching addresses. */ - iter_data.hw_macaddr = common->macaddr; + iter_data.hw_macaddr = NULL; memset(&iter_data.mask, 0xff, ETH_ALEN); if (vif) @@ -164,6 +169,10 @@ static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv, &iter_data); memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); + + if (iter_data.hw_macaddr) + memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN); + ath_hw_setbssidmask(common); } @@ -826,8 +835,7 @@ void ath9k_htc_ani_work(struct work_struct *work) if (longcal || shortcal) common->ani.caldone = ath9k_hw_calibrate(ah, ah->curchan, - common->rx_chainmask, - longcal); + ah->rxchainmask, longcal); ath9k_htc_ps_restore(priv); } @@ -1101,7 +1109,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, goto out; } - ath9k_htc_set_bssid_mask(priv, vif); + ath9k_htc_set_mac_bssid_mask(priv, vif); priv->vif_slot |= (1 << avp->index); priv->nvifs++; @@ -1164,7 +1172,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, ath9k_htc_set_opmode(priv); - ath9k_htc_set_bssid_mask(priv, vif); + ath9k_htc_set_mac_bssid_mask(priv, vif); /* * Stop ANI only if there are no associated station interfaces. @@ -1294,11 +1302,17 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, u32 rfilt; mutex_lock(&priv->mutex); - ath9k_htc_ps_wakeup(priv); - changed_flags &= SUPPORTED_FILTERS; *total_flags &= SUPPORTED_FILTERS; + if (priv->op_flags & OP_INVALID) { + ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_ANY, + "Unable to configure filter on invalid state\n"); + mutex_unlock(&priv->mutex); + return; + } + ath9k_htc_ps_wakeup(priv); + priv->rxfilter = *total_flags; rfilt = ath9k_htc_calcrxfilter(priv); ath9k_hw_setrxfilter(priv->ah, rfilt); @@ -1347,7 +1361,8 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw, return ret; } -static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, +static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u16 queue, const struct ieee80211_tx_queue_params *params) { struct ath9k_htc_priv *priv = hw->priv; @@ -1558,7 +1573,8 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, mutex_unlock(&priv->mutex); } -static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw) +static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct ath9k_htc_priv *priv = hw->priv; u64 tsf; @@ -1572,7 +1588,8 @@ static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw) return tsf; } -static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf) +static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u64 tsf) { struct ath9k_htc_priv *priv = hw->priv; @@ -1583,7 +1600,8 @@ static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf) mutex_unlock(&priv->mutex); } -static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw) +static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct ath9k_htc_priv *priv = hw->priv; @@ -1731,6 +1749,22 @@ out: return ret; } + +static int ath9k_htc_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ath_hw *ah = priv->ah; + struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats; + + stats->dot11ACKFailureCount = mib_stats->ackrcv_bad; + stats->dot11RTSFailureCount = mib_stats->rts_bad; + stats->dot11FCSErrorCount = mib_stats->fcs_bad; + stats->dot11RTSSuccessCount = mib_stats->rts_good; + + return 0; +} + struct ieee80211_ops ath9k_htc_ops = { .tx = ath9k_htc_tx, .start = ath9k_htc_start, @@ -1754,4 +1788,5 @@ struct ieee80211_ops ath9k_htc_ops = { .rfkill_poll = ath9k_htc_rfkill_poll_state, .set_coverage_class = ath9k_htc_set_coverage_class, .set_bitrate_mask = ath9k_htc_set_bitrate_mask, + .get_stats = ath9k_htc_get_stats, }; |