diff options
-rw-r--r-- | net/mac80211/agg-rx.c | 3 | ||||
-rw-r--r-- | net/mac80211/agg-tx.c | 4 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 25 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 2 | ||||
-rw-r--r-- | net/mac80211/key.c | 2 | ||||
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 2 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 4 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 10 | ||||
-rw-r--r-- | net/mac80211/rx.c | 119 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 18 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 29 | ||||
-rw-r--r-- | net/mac80211/status.c | 8 | ||||
-rw-r--r-- | net/mac80211/tx.c | 9 |
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, | |||
83 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, | 83 | void 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, | |||
414 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | 414 | static 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, | |||
846 | static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | 843 | static 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 */ |
106 | struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr) | 106 | struct 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, | |||
843 | struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, | 846 | struct 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 | } |
852 | EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); | 856 | EXPORT_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 | */ |
408 | struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr); | 408 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, |
409 | const u8 *addr); | ||
410 | |||
411 | static inline | ||
412 | void 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) |