aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-11-25 11:46:18 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-12-21 18:38:51 -0500
commitabe60632f311d515b082b450504ee24006023951 (patch)
treea51fc3b135fa8a31cc0d7953be43502ecc6433c6 /net
parent15920d8afc87861672e16fa95ae2764b065d6dd3 (diff)
mac80211: make station management completely depend on vif
The station management currently uses the virtual interface, but you cannot add the same station to multiple virtual interfaces if you're communicating with it in multiple ways. This restriction should be lifted so that in the future we can, for instance, support bluetooth 3 with an access point that mac80211 is already associated to. We can do that by requiring all sta_info_get users to provide the virtual interface and making the RX code aware that an address may match more than one station struct. Thanks to the previous patches this one isn't all that large and except for the RX and TX status paths changes has low complexity. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/agg-rx.c3
-rw-r--r--net/mac80211/agg-tx.c4
-rw-r--r--net/mac80211/cfg.c25
-rw-r--r--net/mac80211/ibss.c2
-rw-r--r--net/mac80211/key.c2
-rw-r--r--net/mac80211/mesh_hwmp.c2
-rw-r--r--net/mac80211/mesh_plink.c4
-rw-r--r--net/mac80211/mlme.c10
-rw-r--r--net/mac80211/rx.c119
-rw-r--r--net/mac80211/sta_info.c18
-rw-r--r--net/mac80211/sta_info.h29
-rw-r--r--net/mac80211/status.c8
-rw-r--r--net/mac80211/tx.c9
13 files changed, 134 insertions, 101 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 51c7dc3c4c3b..f16d49d474b4 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -83,12 +83,11 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
83void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, 83void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid,
84 u16 initiator, u16 reason) 84 u16 initiator, u16 reason)
85{ 85{
86 struct ieee80211_local *local = sdata->local;
87 struct sta_info *sta; 86 struct sta_info *sta;
88 87
89 rcu_read_lock(); 88 rcu_read_lock();
90 89
91 sta = sta_info_get(local, ra); 90 sta = sta_info_get(sdata, ra);
92 if (!sta) { 91 if (!sta) {
93 rcu_read_unlock(); 92 rcu_read_unlock();
94 return; 93 return;
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 5e3a7eccef5a..b05de532c379 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -441,7 +441,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
441 } 441 }
442 442
443 rcu_read_lock(); 443 rcu_read_lock();
444 sta = sta_info_get(local, ra); 444 sta = sta_info_get(sdata, ra);
445 if (!sta) { 445 if (!sta) {
446 rcu_read_unlock(); 446 rcu_read_unlock();
447#ifdef CONFIG_MAC80211_HT_DEBUG 447#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -564,7 +564,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
564#endif /* CONFIG_MAC80211_HT_DEBUG */ 564#endif /* CONFIG_MAC80211_HT_DEBUG */
565 565
566 rcu_read_lock(); 566 rcu_read_lock();
567 sta = sta_info_get(local, ra); 567 sta = sta_info_get(sdata, ra);
568 if (!sta) { 568 if (!sta) {
569#ifdef CONFIG_MAC80211_HT_DEBUG 569#ifdef CONFIG_MAC80211_HT_DEBUG
570 printk(KERN_DEBUG "Could not find station: %pM\n", ra); 570 printk(KERN_DEBUG "Could not find station: %pM\n", ra);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 93ee1fd5c08d..14e1f4015a72 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -150,7 +150,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
150 rcu_read_lock(); 150 rcu_read_lock();
151 151
152 if (mac_addr) { 152 if (mac_addr) {
153 sta = sta_info_get(sdata->local, mac_addr); 153 sta = sta_info_get(sdata, mac_addr);
154 if (!sta) { 154 if (!sta) {
155 ieee80211_key_free(key); 155 ieee80211_key_free(key);
156 err = -ENOENT; 156 err = -ENOENT;
@@ -181,7 +181,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
181 if (mac_addr) { 181 if (mac_addr) {
182 ret = -ENOENT; 182 ret = -ENOENT;
183 183
184 sta = sta_info_get(sdata->local, mac_addr); 184 sta = sta_info_get(sdata, mac_addr);
185 if (!sta) 185 if (!sta)
186 goto out_unlock; 186 goto out_unlock;
187 187
@@ -228,7 +228,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
228 rcu_read_lock(); 228 rcu_read_lock();
229 229
230 if (mac_addr) { 230 if (mac_addr) {
231 sta = sta_info_get(sdata->local, mac_addr); 231 sta = sta_info_get(sdata, mac_addr);
232 if (!sta) 232 if (!sta)
233 goto out; 233 goto out;
234 234
@@ -414,15 +414,13 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
414static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, 414static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
415 u8 *mac, struct station_info *sinfo) 415 u8 *mac, struct station_info *sinfo)
416{ 416{
417 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 417 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
418 struct sta_info *sta; 418 struct sta_info *sta;
419 int ret = -ENOENT; 419 int ret = -ENOENT;
420 420
421 rcu_read_lock(); 421 rcu_read_lock();
422 422
423 /* XXX: verify sta->dev == dev */ 423 sta = sta_info_get(sdata, mac);
424
425 sta = sta_info_get(local, mac);
426 if (sta) { 424 if (sta) {
427 ret = 0; 425 ret = 0;
428 sta_set_sinfo(sta, sinfo); 426 sta_set_sinfo(sta, sinfo);
@@ -778,8 +776,7 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
778 if (mac) { 776 if (mac) {
779 rcu_read_lock(); 777 rcu_read_lock();
780 778
781 /* XXX: get sta belonging to dev */ 779 sta = sta_info_get(sdata, mac);
782 sta = sta_info_get(local, mac);
783 if (!sta) { 780 if (!sta) {
784 rcu_read_unlock(); 781 rcu_read_unlock();
785 return -ENOENT; 782 return -ENOENT;
@@ -800,14 +797,14 @@ static int ieee80211_change_station(struct wiphy *wiphy,
800 u8 *mac, 797 u8 *mac,
801 struct station_parameters *params) 798 struct station_parameters *params)
802{ 799{
800 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
803 struct ieee80211_local *local = wiphy_priv(wiphy); 801 struct ieee80211_local *local = wiphy_priv(wiphy);
804 struct sta_info *sta; 802 struct sta_info *sta;
805 struct ieee80211_sub_if_data *vlansdata; 803 struct ieee80211_sub_if_data *vlansdata;
806 804
807 rcu_read_lock(); 805 rcu_read_lock();
808 806
809 /* XXX: get sta belonging to dev */ 807 sta = sta_info_get(sdata, mac);
810 sta = sta_info_get(local, mac);
811 if (!sta) { 808 if (!sta) {
812 rcu_read_unlock(); 809 rcu_read_unlock();
813 return -ENOENT; 810 return -ENOENT;
@@ -846,7 +843,6 @@ static int ieee80211_change_station(struct wiphy *wiphy,
846static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, 843static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
847 u8 *dst, u8 *next_hop) 844 u8 *dst, u8 *next_hop)
848{ 845{
849 struct ieee80211_local *local = wiphy_priv(wiphy);
850 struct ieee80211_sub_if_data *sdata; 846 struct ieee80211_sub_if_data *sdata;
851 struct mesh_path *mpath; 847 struct mesh_path *mpath;
852 struct sta_info *sta; 848 struct sta_info *sta;
@@ -855,7 +851,7 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
855 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 851 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
856 852
857 rcu_read_lock(); 853 rcu_read_lock();
858 sta = sta_info_get(local, next_hop); 854 sta = sta_info_get(sdata, next_hop);
859 if (!sta) { 855 if (!sta) {
860 rcu_read_unlock(); 856 rcu_read_unlock();
861 return -ENOENT; 857 return -ENOENT;
@@ -894,7 +890,6 @@ static int ieee80211_change_mpath(struct wiphy *wiphy,
894 struct net_device *dev, 890 struct net_device *dev,
895 u8 *dst, u8 *next_hop) 891 u8 *dst, u8 *next_hop)
896{ 892{
897 struct ieee80211_local *local = wiphy_priv(wiphy);
898 struct ieee80211_sub_if_data *sdata; 893 struct ieee80211_sub_if_data *sdata;
899 struct mesh_path *mpath; 894 struct mesh_path *mpath;
900 struct sta_info *sta; 895 struct sta_info *sta;
@@ -903,7 +898,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy,
903 898
904 rcu_read_lock(); 899 rcu_read_lock();
905 900
906 sta = sta_info_get(local, next_hop); 901 sta = sta_info_get(sdata, next_hop);
907 if (!sta) { 902 if (!sta) {
908 rcu_read_unlock(); 903 rcu_read_unlock();
909 return -ENOENT; 904 return -ENOENT;
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 10d13856f86c..1925be9b82fb 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -252,7 +252,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
252 252
253 rcu_read_lock(); 253 rcu_read_lock();
254 254
255 sta = sta_info_get(local, mgmt->sa); 255 sta = sta_info_get(sdata, mgmt->sa);
256 if (sta) { 256 if (sta) {
257 u32 prev_rates; 257 u32 prev_rates;
258 258
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 659a42d529e3..ac1a777674f6 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -421,7 +421,7 @@ void ieee80211_key_link(struct ieee80211_key *key,
421 */ 421 */
422 422
423 /* same here, the AP could be using QoS */ 423 /* same here, the AP could be using QoS */
424 ap = sta_info_get(key->local, key->sdata->u.mgd.bssid); 424 ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid);
425 if (ap) { 425 if (ap) {
426 if (test_sta_flags(ap, WLAN_STA_WME)) 426 if (test_sta_flags(ap, WLAN_STA_WME))
427 key->conf.flags |= 427 key->conf.flags |=
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 833b2f3670c5..b836892f0ba9 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -335,7 +335,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
335 bool process = true; 335 bool process = true;
336 336
337 rcu_read_lock(); 337 rcu_read_lock();
338 sta = sta_info_get(local, mgmt->sa); 338 sta = sta_info_get(sdata, mgmt->sa);
339 if (!sta) { 339 if (!sta) {
340 rcu_read_unlock(); 340 rcu_read_unlock();
341 return 0; 341 return 0;
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 0f7c6e6a4248..8fcf56ee7743 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -234,7 +234,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data
234 234
235 rcu_read_lock(); 235 rcu_read_lock();
236 236
237 sta = sta_info_get(local, hw_addr); 237 sta = sta_info_get(sdata, hw_addr);
238 if (!sta) { 238 if (!sta) {
239 sta = mesh_plink_alloc(sdata, hw_addr, rates); 239 sta = mesh_plink_alloc(sdata, hw_addr, rates);
240 if (!sta) { 240 if (!sta) {
@@ -455,7 +455,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
455 455
456 rcu_read_lock(); 456 rcu_read_lock();
457 457
458 sta = sta_info_get(local, mgmt->sa); 458 sta = sta_info_get(sdata, mgmt->sa);
459 if (!sta && ftype != PLINK_OPEN) { 459 if (!sta && ftype != PLINK_OPEN) {
460 mpl_dbg("Mesh plink: cls or cnf from unknown peer\n"); 460 mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");
461 rcu_read_unlock(); 461 rcu_read_unlock();
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 6dc7b5ad9a41..c16667a7c8df 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -202,7 +202,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
202 ieee80211_hw_config(local, 0); 202 ieee80211_hw_config(local, 0);
203 203
204 rcu_read_lock(); 204 rcu_read_lock();
205 sta = sta_info_get(local, bssid); 205 sta = sta_info_get(sdata, bssid);
206 if (sta) 206 if (sta)
207 rate_control_rate_update(local, sband, sta, 207 rate_control_rate_update(local, sband, sta,
208 IEEE80211_RC_HT_CHANGED); 208 IEEE80211_RC_HT_CHANGED);
@@ -1070,7 +1070,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1070 netif_carrier_off(sdata->dev); 1070 netif_carrier_off(sdata->dev);
1071 1071
1072 rcu_read_lock(); 1072 rcu_read_lock();
1073 sta = sta_info_get(local, bssid); 1073 sta = sta_info_get(sdata, bssid);
1074 if (sta) 1074 if (sta)
1075 ieee80211_sta_tear_down_BA_sessions(sta); 1075 ieee80211_sta_tear_down_BA_sessions(sta);
1076 rcu_read_unlock(); 1076 rcu_read_unlock();
@@ -1109,7 +1109,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1109 1109
1110 rcu_read_lock(); 1110 rcu_read_lock();
1111 1111
1112 sta = sta_info_get(local, bssid); 1112 sta = sta_info_get(sdata, bssid);
1113 if (!sta) { 1113 if (!sta) {
1114 rcu_read_unlock(); 1114 rcu_read_unlock();
1115 return; 1115 return;
@@ -1489,7 +1489,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1489 rcu_read_lock(); 1489 rcu_read_lock();
1490 1490
1491 /* Add STA entry for the AP */ 1491 /* Add STA entry for the AP */
1492 sta = sta_info_get(local, wk->bss->cbss.bssid); 1492 sta = sta_info_get(sdata, wk->bss->cbss.bssid);
1493 if (!sta) { 1493 if (!sta) {
1494 newsta = true; 1494 newsta = true;
1495 1495
@@ -1857,7 +1857,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1857 1857
1858 rcu_read_lock(); 1858 rcu_read_lock();
1859 1859
1860 sta = sta_info_get(local, bssid); 1860 sta = sta_info_get(sdata, bssid);
1861 if (WARN_ON(!sta)) { 1861 if (WARN_ON(!sta)) {
1862 rcu_read_unlock(); 1862 rcu_read_unlock();
1863 return; 1863 return;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index f237df408378..5bae28693da8 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1472,7 +1472,6 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
1472{ 1472{
1473 struct ieee80211_sub_if_data *sdata = rx->sdata; 1473 struct ieee80211_sub_if_data *sdata = rx->sdata;
1474 struct net_device *dev = sdata->dev; 1474 struct net_device *dev = sdata->dev;
1475 struct ieee80211_local *local = rx->local;
1476 struct sk_buff *skb, *xmit_skb; 1475 struct sk_buff *skb, *xmit_skb;
1477 struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; 1476 struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
1478 struct sta_info *dsta; 1477 struct sta_info *dsta;
@@ -1495,8 +1494,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
1495 printk(KERN_DEBUG "%s: failed to clone " 1494 printk(KERN_DEBUG "%s: failed to clone "
1496 "multicast frame\n", dev->name); 1495 "multicast frame\n", dev->name);
1497 } else { 1496 } else {
1498 dsta = sta_info_get(local, skb->data); 1497 dsta = sta_info_get(sdata, skb->data);
1499 if (dsta && dsta->sdata->dev == dev) { 1498 if (dsta) {
1500 /* 1499 /*
1501 * The destination station is associated to 1500 * The destination station is associated to
1502 * this AP (in this VLAN), so send the frame 1501 * this AP (in this VLAN), so send the frame
@@ -2363,6 +2362,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2363 int prepares; 2362 int prepares;
2364 struct ieee80211_sub_if_data *prev = NULL; 2363 struct ieee80211_sub_if_data *prev = NULL;
2365 struct sk_buff *skb_new; 2364 struct sk_buff *skb_new;
2365 struct sta_info *sta, *tmp;
2366 bool found_sta = false;
2366 2367
2367 hdr = (struct ieee80211_hdr *)skb->data; 2368 hdr = (struct ieee80211_hdr *)skb->data;
2368 memset(&rx, 0, sizeof(rx)); 2369 memset(&rx, 0, sizeof(rx));
@@ -2379,68 +2380,76 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2379 ieee80211_parse_qos(&rx); 2380 ieee80211_parse_qos(&rx);
2380 ieee80211_verify_alignment(&rx); 2381 ieee80211_verify_alignment(&rx);
2381 2382
2382 rx.sta = sta_info_get(local, hdr->addr2); 2383 if (ieee80211_is_data(hdr->frame_control)) {
2383 if (rx.sta) 2384 for_each_sta_info(local, hdr->addr2, sta, tmp) {
2384 rx.sdata = rx.sta->sdata; 2385 rx.sta = sta;
2385 2386 found_sta = true;
2386 if (rx.sdata && ieee80211_is_data(hdr->frame_control)) { 2387 rx.sdata = sta->sdata;
2387 rx.flags |= IEEE80211_RX_RA_MATCH; 2388
2388 prepares = prepare_for_handlers(rx.sdata, &rx, hdr); 2389 rx.flags |= IEEE80211_RX_RA_MATCH;
2389 if (prepares) { 2390 prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
2390 if (status->flag & RX_FLAG_MMIC_ERROR) { 2391 if (prepares) {
2391 if (rx.flags & IEEE80211_RX_RA_MATCH) 2392 if (status->flag & RX_FLAG_MMIC_ERROR) {
2392 ieee80211_rx_michael_mic_report(hdr, &rx); 2393 if (rx.flags & IEEE80211_RX_RA_MATCH)
2393 } else 2394 ieee80211_rx_michael_mic_report(hdr, &rx);
2394 prev = rx.sdata; 2395 } else
2396 prev = rx.sdata;
2397 }
2395 } 2398 }
2396 } else list_for_each_entry_rcu(sdata, &local->interfaces, list) { 2399 }
2397 if (!netif_running(sdata->dev)) 2400 if (!found_sta) {
2398 continue; 2401 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
2402 if (!netif_running(sdata->dev))
2403 continue;
2399 2404
2400 if (sdata->vif.type == NL80211_IFTYPE_MONITOR || 2405 if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
2401 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 2406 sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
2402 continue; 2407 continue;
2403 2408
2404 rx.flags |= IEEE80211_RX_RA_MATCH; 2409 rx.sta = sta_info_get(sdata, hdr->addr2);
2405 prepares = prepare_for_handlers(sdata, &rx, hdr);
2406 2410
2407 if (!prepares) 2411 rx.flags |= IEEE80211_RX_RA_MATCH;
2408 continue; 2412 prepares = prepare_for_handlers(sdata, &rx, hdr);
2409 2413
2410 if (status->flag & RX_FLAG_MMIC_ERROR) { 2414 if (!prepares)
2411 rx.sdata = sdata; 2415 continue;
2412 if (rx.flags & IEEE80211_RX_RA_MATCH)
2413 ieee80211_rx_michael_mic_report(hdr, &rx);
2414 continue;
2415 }
2416 2416
2417 /* 2417 if (status->flag & RX_FLAG_MMIC_ERROR) {
2418 * frame is destined for this interface, but if it's not 2418 rx.sdata = sdata;
2419 * also for the previous one we handle that after the 2419 if (rx.flags & IEEE80211_RX_RA_MATCH)
2420 * loop to avoid copying the SKB once too much 2420 ieee80211_rx_michael_mic_report(hdr,
2421 */ 2421 &rx);
2422 continue;
2423 }
2422 2424
2423 if (!prev) { 2425 /*
2424 prev = sdata; 2426 * frame is destined for this interface, but if it's
2425 continue; 2427 * not also for the previous one we handle that after
2426 } 2428 * the loop to avoid copying the SKB once too much
2429 */
2427 2430
2428 /* 2431 if (!prev) {
2429 * frame was destined for the previous interface 2432 prev = sdata;
2430 * so invoke RX handlers for it 2433 continue;
2431 */ 2434 }
2432 2435
2433 skb_new = skb_copy(skb, GFP_ATOMIC); 2436 /*
2434 if (!skb_new) { 2437 * frame was destined for the previous interface
2435 if (net_ratelimit()) 2438 * so invoke RX handlers for it
2436 printk(KERN_DEBUG "%s: failed to copy " 2439 */
2437 "multicast frame for %s\n", 2440
2438 wiphy_name(local->hw.wiphy), 2441 skb_new = skb_copy(skb, GFP_ATOMIC);
2439 prev->dev->name); 2442 if (!skb_new) {
2440 continue; 2443 if (net_ratelimit())
2444 printk(KERN_DEBUG "%s: failed to copy "
2445 "multicast frame for %s\n",
2446 wiphy_name(local->hw.wiphy),
2447 prev->dev->name);
2448 continue;
2449 }
2450 ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate);
2451 prev = sdata;
2441 } 2452 }
2442 ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate);
2443 prev = sdata;
2444 } 2453 }
2445 if (prev) 2454 if (prev)
2446 ieee80211_invoke_rx_handlers(prev, &rx, skb, rate); 2455 ieee80211_invoke_rx_handlers(prev, &rx, skb, rate);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 71f370dd24bc..c58a23eea58c 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -103,13 +103,16 @@ static int sta_info_hash_del(struct ieee80211_local *local,
103} 103}
104 104
105/* protected by RCU */ 105/* protected by RCU */
106struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr) 106struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
107 const u8 *addr)
107{ 108{
109 struct ieee80211_local *local = sdata->local;
108 struct sta_info *sta; 110 struct sta_info *sta;
109 111
110 sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); 112 sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]);
111 while (sta) { 113 while (sta) {
112 if (memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) 114 if (sta->sdata == sdata &&
115 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
113 break; 116 break;
114 sta = rcu_dereference(sta->hnext); 117 sta = rcu_dereference(sta->hnext);
115 } 118 }
@@ -377,7 +380,7 @@ int sta_info_insert(struct sta_info *sta)
377 380
378 spin_lock_irqsave(&local->sta_lock, flags); 381 spin_lock_irqsave(&local->sta_lock, flags);
379 /* check if STA exists already */ 382 /* check if STA exists already */
380 if (sta_info_get(local, sta->sta.addr)) { 383 if (sta_info_get(sdata, sta->sta.addr)) {
381 spin_unlock_irqrestore(&local->sta_lock, flags); 384 spin_unlock_irqrestore(&local->sta_lock, flags);
382 err = -EEXIST; 385 err = -EEXIST;
383 goto out_free; 386 goto out_free;
@@ -843,11 +846,12 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
843struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, 846struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
844 const u8 *addr) 847 const u8 *addr)
845{ 848{
846 struct sta_info *sta = sta_info_get(hw_to_local(hw), addr); 849 struct sta_info *sta, *nxt;
847 850
848 if (!sta) 851 /* Just return a random station ... first in list ... */
849 return NULL; 852 for_each_sta_info(hw_to_local(hw), addr, sta, nxt)
850 return &sta->sta; 853 return &sta->sta;
854 return NULL;
851} 855}
852EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); 856EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw);
853 857
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index b4810f6aa94f..c8208236e896 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -403,9 +403,34 @@ static inline u32 get_sta_flags(struct sta_info *sta)
403#define STA_INFO_CLEANUP_INTERVAL (10 * HZ) 403#define STA_INFO_CLEANUP_INTERVAL (10 * HZ)
404 404
405/* 405/*
406 * Get a STA info, must have be under RCU read lock. 406 * Get a STA info, must be under RCU read lock.
407 */ 407 */
408struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr); 408struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
409 const u8 *addr);
410
411static inline
412void for_each_sta_info_type_check(struct ieee80211_local *local,
413 const u8 *addr,
414 struct sta_info *sta,
415 struct sta_info *nxt)
416{
417}
418
419#define for_each_sta_info(local, _addr, sta, nxt) \
420 for ( /* initialise loop */ \
421 sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\
422 nxt = sta ? rcu_dereference(sta->hnext) : NULL; \
423 /* typecheck */ \
424 for_each_sta_info_type_check(local, (_addr), sta, nxt), \
425 /* continue condition */ \
426 sta; \
427 /* advance loop */ \
428 sta = nxt, \
429 nxt = sta ? rcu_dereference(sta->hnext) : NULL \
430 ) \
431 /* compare address and run code only if it matches */ \
432 if (memcmp(sta->sta.addr, (_addr), ETH_ALEN) == 0)
433
409/* 434/*
410 * Get STA info by index, BROKEN! 435 * Get STA info by index, BROKEN!
411 */ 436 */
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index d78f36c64c7b..32fe327acf4e 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -146,7 +146,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
146 struct ieee80211_tx_status_rtap_hdr *rthdr; 146 struct ieee80211_tx_status_rtap_hdr *rthdr;
147 struct ieee80211_sub_if_data *sdata; 147 struct ieee80211_sub_if_data *sdata;
148 struct net_device *prev_dev = NULL; 148 struct net_device *prev_dev = NULL;
149 struct sta_info *sta; 149 struct sta_info *sta, *tmp;
150 int retry_count = -1, i; 150 int retry_count = -1, i;
151 bool injected; 151 bool injected;
152 152
@@ -166,9 +166,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
166 166
167 sband = local->hw.wiphy->bands[info->band]; 167 sband = local->hw.wiphy->bands[info->band];
168 168
169 sta = sta_info_get(local, hdr->addr1); 169 for_each_sta_info(local, hdr->addr1, sta, tmp) {
170 /* skip wrong virtual interface */
171 if (memcmp(hdr->addr2, sta->sdata->dev->dev_addr, ETH_ALEN))
172 continue;
170 173
171 if (sta) {
172 if (!(info->flags & IEEE80211_TX_STAT_ACK) && 174 if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
173 test_sta_flags(sta, WLAN_STA_PS_STA)) { 175 test_sta_flags(sta, WLAN_STA_PS_STA)) {
174 /* 176 /*
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 8834cc93c716..b913bfc34a9f 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1055,7 +1055,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1055 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 1055 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1056 tx->sta = rcu_dereference(sdata->u.vlan.sta); 1056 tx->sta = rcu_dereference(sdata->u.vlan.sta);
1057 if (!tx->sta) 1057 if (!tx->sta)
1058 tx->sta = sta_info_get(local, hdr->addr1); 1058 tx->sta = sta_info_get(sdata, hdr->addr1);
1059 1059
1060 if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && 1060 if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
1061 (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { 1061 (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) {
@@ -1761,9 +1761,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1761 */ 1761 */
1762 if (!is_multicast_ether_addr(hdr.addr1)) { 1762 if (!is_multicast_ether_addr(hdr.addr1)) {
1763 rcu_read_lock(); 1763 rcu_read_lock();
1764 sta = sta_info_get(local, hdr.addr1); 1764 sta = sta_info_get(sdata, hdr.addr1);
1765 /* XXX: in the future, use sdata to look up the sta */ 1765 if (sta)
1766 if (sta && sta->sdata == sdata)
1767 sta_flags = get_sta_flags(sta); 1766 sta_flags = get_sta_flags(sta);
1768 rcu_read_unlock(); 1767 rcu_read_unlock();
1769 } 1768 }
@@ -1922,7 +1921,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
1922 ieee80211_tx(sdata, skb, true); 1921 ieee80211_tx(sdata, skb, true);
1923 } else { 1922 } else {
1924 hdr = (struct ieee80211_hdr *)skb->data; 1923 hdr = (struct ieee80211_hdr *)skb->data;
1925 sta = sta_info_get(local, hdr->addr1); 1924 sta = sta_info_get(sdata, hdr->addr1);
1926 1925
1927 ret = __ieee80211_tx(local, &skb, sta, true); 1926 ret = __ieee80211_tx(local, &skb, sta, true);
1928 if (ret != IEEE80211_TX_OK) 1927 if (ret != IEEE80211_TX_OK)