aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Greear <greearb@candelatech.com>2010-09-23 12:44:36 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-09-27 15:57:45 -0400
commit686b9cb994f5f74be790df4cd12873dfdc8a6984 (patch)
tree960bae4d7613e4420c28d0c422e3c63c2a569ed3
parent295bafb47b0d365e1b4f747dffef29e590f13233 (diff)
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: Ben Greear <greearb@candelatech.com> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c3
-rw-r--r--include/net/mac80211.h25
-rw-r--r--net/mac80211/sta_info.c15
4 files changed, 31 insertions, 18 deletions
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 00140489becb..9c166f3804ab 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -977,7 +977,11 @@ static void ath9k_process_rssi(struct ath_common *common,
977 * at least one sdata of a wiphy on mac80211 but with ath9k virtual 977 * at least one sdata of a wiphy on mac80211 but with ath9k virtual
978 * wiphy you'd have to iterate over every wiphy and each sdata. 978 * wiphy you'd have to iterate over every wiphy and each sdata.
979 */ 979 */
980 sta = ieee80211_find_sta_by_hw(hw, hdr->addr2); 980 if (is_multicast_ether_addr(hdr->addr1))
981 sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
982 else
983 sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1);
984
981 if (sta) { 985 if (sta) {
982 an = (struct ath_node *) sta->drv_priv; 986 an = (struct ath_node *) sta->drv_priv;
983 if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && 987 if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 85a7323a04ef..f7da6b20a925 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -328,8 +328,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
328 328
329 rcu_read_lock(); 329 rcu_read_lock();
330 330
331 /* XXX: use ieee80211_find_sta! */ 331 sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
332 sta = ieee80211_find_sta_by_hw(hw, hdr->addr1);
333 if (!sta) { 332 if (!sta) {
334 rcu_read_unlock(); 333 rcu_read_unlock();
335 334
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 5d1187d7c5e5..73469d8b64bb 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2432,25 +2432,28 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
2432 const u8 *addr); 2432 const u8 *addr);
2433 2433
2434/** 2434/**
2435 * ieee80211_find_sta_by_hw - find a station on hardware 2435 * ieee80211_find_sta_by_ifaddr - find a station on hardware
2436 * 2436 *
2437 * @hw: pointer as obtained from ieee80211_alloc_hw() 2437 * @hw: pointer as obtained from ieee80211_alloc_hw()
2438 * @addr: station's address 2438 * @addr: remote station's address
2439 * @localaddr: local address (vif->sdata->vif.addr). Use NULL for 'any'.
2439 * 2440 *
2440 * This function must be called under RCU lock and the 2441 * This function must be called under RCU lock and the
2441 * resulting pointer is only valid under RCU lock as well. 2442 * resulting pointer is only valid under RCU lock as well.
2442 * 2443 *
2443 * NOTE: This function should not be used! When mac80211 is converted 2444 * NOTE: You may pass NULL for localaddr, but then you will just get
2444 * internally to properly keep track of stations on multiple 2445 * the first STA that matches the remote address 'addr'.
2445 * virtual interfaces, it will not always know which station to 2446 * We can have multiple STA associated with multiple
2446 * return here since a single address might be used by multiple 2447 * logical stations (e.g. consider a station connecting to another
2447 * logical stations (e.g. consider a station connecting to another 2448 * BSSID on the same AP hardware without disconnecting first).
2448 * BSSID on the same AP hardware without disconnecting first). 2449 * In this case, the result of this method with localaddr NULL
2450 * is not reliable.
2449 * 2451 *
2450 * DO NOT USE THIS FUNCTION. 2452 * DO NOT USE THIS FUNCTION with localaddr NULL if at all possible.
2451 */ 2453 */
2452struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, 2454struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
2453 const u8 *addr); 2455 const u8 *addr,
2456 const u8 *localaddr);
2454 2457
2455/** 2458/**
2456 * ieee80211_sta_block_awake - block station from waking up 2459 * ieee80211_sta_block_awake - block station from waking up
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 44e10a9de0a7..ca2cba9cea87 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -838,13 +838,20 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
838 mutex_unlock(&local->sta_mtx); 838 mutex_unlock(&local->sta_mtx);
839} 839}
840 840
841struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, 841struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
842 const u8 *addr) 842 const u8 *addr,
843 const u8 *localaddr)
843{ 844{
844 struct sta_info *sta, *nxt; 845 struct sta_info *sta, *nxt;
845 846
846 /* Just return a random station ... first in list ... */ 847 /*
848 * Just return a random station if localaddr is NULL
849 * ... first in list.
850 */
847 for_each_sta_info(hw_to_local(hw), addr, sta, nxt) { 851 for_each_sta_info(hw_to_local(hw), addr, sta, nxt) {
852 if (localaddr &&
853 compare_ether_addr(sta->sdata->vif.addr, localaddr) != 0)
854 continue;
848 if (!sta->uploaded) 855 if (!sta->uploaded)
849 return NULL; 856 return NULL;
850 return &sta->sta; 857 return &sta->sta;
@@ -852,7 +859,7 @@ struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
852 859
853 return NULL; 860 return NULL;
854} 861}
855EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); 862EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_ifaddr);
856 863
857struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, 864struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
858 const u8 *addr) 865 const u8 *addr)