提交 686b9cb9 编写于 作者: B Ben Greear 提交者: John W. Linville

mac80211/ath9k: Support AMPDU with multiple VIFs.

The old ieee80211_find_sta_by_hw method didn't properly
find VIFS when there was more than one per AP.  This caused
AMPDU logic in ath9k to get the wrong VIF when trying to
account for transmitted SKBs.

This patch changes ieee80211_find_sta_by_hw to take a
localaddr argument to distinguish between VIFs with the
same AP but different local addresses.  The method name
is changed to ieee80211_find_sta_by_ifaddr.
Signed-off-by: NBen Greear <greearb@candelatech.com>
Acked-by: NJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: NJohn W. Linville <linville@tuxdriver.com>
上级 295bafb4
...@@ -977,7 +977,11 @@ static void ath9k_process_rssi(struct ath_common *common, ...@@ -977,7 +977,11 @@ static void ath9k_process_rssi(struct ath_common *common,
* at least one sdata of a wiphy on mac80211 but with ath9k virtual * at least one sdata of a wiphy on mac80211 but with ath9k virtual
* wiphy you'd have to iterate over every wiphy and each sdata. * wiphy you'd have to iterate over every wiphy and each sdata.
*/ */
sta = ieee80211_find_sta_by_hw(hw, hdr->addr2); if (is_multicast_ether_addr(hdr->addr1))
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
else
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1);
if (sta) { if (sta) {
an = (struct ath_node *) sta->drv_priv; an = (struct ath_node *) sta->drv_priv;
if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
......
...@@ -328,8 +328,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ...@@ -328,8 +328,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
rcu_read_lock(); rcu_read_lock();
/* XXX: use ieee80211_find_sta! */ sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
sta = ieee80211_find_sta_by_hw(hw, hdr->addr1);
if (!sta) { if (!sta) {
rcu_read_unlock(); rcu_read_unlock();
......
...@@ -2432,25 +2432,28 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, ...@@ -2432,25 +2432,28 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
const u8 *addr); const u8 *addr);
/** /**
* ieee80211_find_sta_by_hw - find a station on hardware * ieee80211_find_sta_by_ifaddr - find a station on hardware
* *
* @hw: pointer as obtained from ieee80211_alloc_hw() * @hw: pointer as obtained from ieee80211_alloc_hw()
* @addr: station's address * @addr: remote station's address
* @localaddr: local address (vif->sdata->vif.addr). Use NULL for 'any'.
* *
* This function must be called under RCU lock and the * This function must be called under RCU lock and the
* resulting pointer is only valid under RCU lock as well. * resulting pointer is only valid under RCU lock as well.
* *
* NOTE: This function should not be used! When mac80211 is converted * NOTE: You may pass NULL for localaddr, but then you will just get
* internally to properly keep track of stations on multiple * the first STA that matches the remote address 'addr'.
* virtual interfaces, it will not always know which station to * We can have multiple STA associated with multiple
* return here since a single address might be used by multiple * logical stations (e.g. consider a station connecting to another
* logical stations (e.g. consider a station connecting to another * BSSID on the same AP hardware without disconnecting first).
* BSSID on the same AP hardware without disconnecting first). * In this case, the result of this method with localaddr NULL
* is not reliable.
* *
* DO NOT USE THIS FUNCTION. * DO NOT USE THIS FUNCTION with localaddr NULL if at all possible.
*/ */
struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
const u8 *addr); const u8 *addr,
const u8 *localaddr);
/** /**
* ieee80211_sta_block_awake - block station from waking up * ieee80211_sta_block_awake - block station from waking up
......
...@@ -838,13 +838,20 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, ...@@ -838,13 +838,20 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
mutex_unlock(&local->sta_mtx); mutex_unlock(&local->sta_mtx);
} }
struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
const u8 *addr) const u8 *addr,
const u8 *localaddr)
{ {
struct sta_info *sta, *nxt; struct sta_info *sta, *nxt;
/* Just return a random station ... first in list ... */ /*
* Just return a random station if localaddr is NULL
* ... first in list.
*/
for_each_sta_info(hw_to_local(hw), addr, sta, nxt) { for_each_sta_info(hw_to_local(hw), addr, sta, nxt) {
if (localaddr &&
compare_ether_addr(sta->sdata->vif.addr, localaddr) != 0)
continue;
if (!sta->uploaded) if (!sta->uploaded)
return NULL; return NULL;
return &sta->sta; return &sta->sta;
...@@ -852,7 +859,7 @@ struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, ...@@ -852,7 +859,7 @@ struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
return NULL; return NULL;
} }
EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_ifaddr);
struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
const u8 *addr) const u8 *addr)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册