aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ieee80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/ieee80211.c')
-rw-r--r--net/mac80211/ieee80211.c78
1 files changed, 52 insertions, 26 deletions
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 727af295c969..85b1391375c0 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -375,15 +375,19 @@ static int ieee80211_stop(struct net_device *dev)
375 375
376 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 376 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
377 377
378 list_for_each_entry(sta, &local->sta_list, list) { 378 rcu_read_lock();
379 if (sta->dev == dev) 379
380 list_for_each_entry_rcu(sta, &local->sta_list, list) {
381 if (sta->sdata == sdata)
380 for (i = 0; i < STA_TID_NUM; i++) 382 for (i = 0; i < STA_TID_NUM; i++)
381 ieee80211_sta_stop_rx_ba_session(sta->dev, 383 ieee80211_sta_stop_rx_ba_session(sdata->dev,
382 sta->addr, i, 384 sta->addr, i,
383 WLAN_BACK_RECIPIENT, 385 WLAN_BACK_RECIPIENT,
384 WLAN_REASON_QSTA_LEAVE_QBSS); 386 WLAN_REASON_QSTA_LEAVE_QBSS);
385 } 387 }
386 388
389 rcu_read_unlock();
390
387 netif_stop_queue(dev); 391 netif_stop_queue(dev);
388 392
389 /* 393 /*
@@ -449,7 +453,7 @@ static int ieee80211_stop(struct net_device *dev)
449 netif_tx_unlock_bh(local->mdev); 453 netif_tx_unlock_bh(local->mdev);
450 break; 454 break;
451 case IEEE80211_IF_TYPE_MESH_POINT: 455 case IEEE80211_IF_TYPE_MESH_POINT:
452 sta_info_flush(local, dev); 456 sta_info_flush(local, sdata);
453 /* fall through */ 457 /* fall through */
454 case IEEE80211_IF_TYPE_STA: 458 case IEEE80211_IF_TYPE_STA:
455 case IEEE80211_IF_TYPE_IBSS: 459 case IEEE80211_IF_TYPE_IBSS:
@@ -522,9 +526,12 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
522 print_mac(mac, ra), tid); 526 print_mac(mac, ra), tid);
523#endif /* CONFIG_MAC80211_HT_DEBUG */ 527#endif /* CONFIG_MAC80211_HT_DEBUG */
524 528
529 rcu_read_lock();
530
525 sta = sta_info_get(local, ra); 531 sta = sta_info_get(local, ra);
526 if (!sta) { 532 if (!sta) {
527 printk(KERN_DEBUG "Could not find the station\n"); 533 printk(KERN_DEBUG "Could not find the station\n");
534 rcu_read_unlock();
528 return -ENOENT; 535 return -ENOENT;
529 } 536 }
530 537
@@ -564,7 +571,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
564 spin_unlock_bh(&local->mdev->queue_lock); 571 spin_unlock_bh(&local->mdev->queue_lock);
565 goto start_ba_exit; 572 goto start_ba_exit;
566 } 573 }
567 sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); 574 sdata = sta->sdata;
568 575
569 /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the 576 /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the
570 * call back right away, it must see that the flow has begun */ 577 * call back right away, it must see that the flow has begun */
@@ -601,7 +608,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
601 sta->ampdu_mlme.dialog_token_allocator; 608 sta->ampdu_mlme.dialog_token_allocator;
602 sta->ampdu_mlme.tid_tx[tid].ssn = start_seq_num; 609 sta->ampdu_mlme.tid_tx[tid].ssn = start_seq_num;
603 610
604 ieee80211_send_addba_request(sta->dev, ra, tid, 611 ieee80211_send_addba_request(sta->sdata->dev, ra, tid,
605 sta->ampdu_mlme.tid_tx[tid].dialog_token, 612 sta->ampdu_mlme.tid_tx[tid].dialog_token,
606 sta->ampdu_mlme.tid_tx[tid].ssn, 613 sta->ampdu_mlme.tid_tx[tid].ssn,
607 0x40, 5000); 614 0x40, 5000);
@@ -614,7 +621,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
614 621
615start_ba_exit: 622start_ba_exit:
616 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 623 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
617 sta_info_put(sta); 624 rcu_read_unlock();
618 return ret; 625 return ret;
619} 626}
620EXPORT_SYMBOL(ieee80211_start_tx_ba_session); 627EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
@@ -637,9 +644,12 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
637 print_mac(mac, ra), tid); 644 print_mac(mac, ra), tid);
638#endif /* CONFIG_MAC80211_HT_DEBUG */ 645#endif /* CONFIG_MAC80211_HT_DEBUG */
639 646
647 rcu_read_lock();
640 sta = sta_info_get(local, ra); 648 sta = sta_info_get(local, ra);
641 if (!sta) 649 if (!sta) {
650 rcu_read_unlock();
642 return -ENOENT; 651 return -ENOENT;
652 }
643 653
644 /* check if the TID is in aggregation */ 654 /* check if the TID is in aggregation */
645 state = &sta->ampdu_mlme.tid_tx[tid].state; 655 state = &sta->ampdu_mlme.tid_tx[tid].state;
@@ -673,7 +683,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
673 683
674stop_BA_exit: 684stop_BA_exit:
675 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 685 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
676 sta_info_put(sta); 686 rcu_read_unlock();
677 return ret; 687 return ret;
678} 688}
679EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); 689EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
@@ -691,8 +701,10 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
691 return; 701 return;
692 } 702 }
693 703
704 rcu_read_lock();
694 sta = sta_info_get(local, ra); 705 sta = sta_info_get(local, ra);
695 if (!sta) { 706 if (!sta) {
707 rcu_read_unlock();
696 printk(KERN_DEBUG "Could not find station: %s\n", 708 printk(KERN_DEBUG "Could not find station: %s\n",
697 print_mac(mac, ra)); 709 print_mac(mac, ra));
698 return; 710 return;
@@ -705,7 +717,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
705 printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", 717 printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
706 *state); 718 *state);
707 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 719 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
708 sta_info_put(sta); 720 rcu_read_unlock();
709 return; 721 return;
710 } 722 }
711 723
@@ -718,7 +730,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
718 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); 730 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
719 } 731 }
720 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 732 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
721 sta_info_put(sta); 733 rcu_read_unlock();
722} 734}
723EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); 735EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
724 736
@@ -739,10 +751,12 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
739 printk(KERN_DEBUG "Stop a BA session requested on DA %s tid %d\n", 751 printk(KERN_DEBUG "Stop a BA session requested on DA %s tid %d\n",
740 print_mac(mac, ra), tid); 752 print_mac(mac, ra), tid);
741 753
754 rcu_read_lock();
742 sta = sta_info_get(local, ra); 755 sta = sta_info_get(local, ra);
743 if (!sta) { 756 if (!sta) {
744 printk(KERN_DEBUG "Could not find station: %s\n", 757 printk(KERN_DEBUG "Could not find station: %s\n",
745 print_mac(mac, ra)); 758 print_mac(mac, ra));
759 rcu_read_unlock();
746 return; 760 return;
747 } 761 }
748 state = &sta->ampdu_mlme.tid_tx[tid].state; 762 state = &sta->ampdu_mlme.tid_tx[tid].state;
@@ -750,13 +764,13 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
750 spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); 764 spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
751 if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { 765 if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
752 printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); 766 printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
753 sta_info_put(sta);
754 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 767 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
768 rcu_read_unlock();
755 return; 769 return;
756 } 770 }
757 771
758 if (*state & HT_AGG_STATE_INITIATOR_MSK) 772 if (*state & HT_AGG_STATE_INITIATOR_MSK)
759 ieee80211_send_delba(sta->dev, ra, tid, 773 ieee80211_send_delba(sta->sdata->dev, ra, tid,
760 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); 774 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
761 775
762 agg_queue = sta->tid_to_tx_q[tid]; 776 agg_queue = sta->tid_to_tx_q[tid];
@@ -777,7 +791,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
777 sta->ampdu_mlme.tid_tx[tid].addba_req_num = 0; 791 sta->ampdu_mlme.tid_tx[tid].addba_req_num = 0;
778 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 792 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
779 793
780 sta_info_put(sta); 794 rcu_read_unlock();
781} 795}
782EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb); 796EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb);
783 797
@@ -887,32 +901,41 @@ int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr)
887 struct sta_info *sta; 901 struct sta_info *sta;
888 DECLARE_MAC_BUF(mac); 902 DECLARE_MAC_BUF(mac);
889 903
904 might_sleep();
905
890 if (compare_ether_addr(remote_addr, sdata->u.wds.remote_addr) == 0) 906 if (compare_ether_addr(remote_addr, sdata->u.wds.remote_addr) == 0)
891 return 0; 907 return 0;
892 908
909 rcu_read_lock();
910
893 /* Create STA entry for the new peer */ 911 /* Create STA entry for the new peer */
894 sta = sta_info_add(local, dev, remote_addr, GFP_KERNEL); 912 sta = sta_info_add(sdata, remote_addr);
895 if (IS_ERR(sta)) 913 if (IS_ERR(sta)) {
914 rcu_read_unlock();
896 return PTR_ERR(sta); 915 return PTR_ERR(sta);
916 }
897 917
898 sta->flags |= WLAN_STA_AUTHORIZED; 918 sta->flags |= WLAN_STA_AUTHORIZED;
899 919
900 sta_info_put(sta);
901
902 /* Remove STA entry for the old peer */ 920 /* Remove STA entry for the old peer */
903 sta = sta_info_get(local, sdata->u.wds.remote_addr); 921 sta = sta_info_get(local, sdata->u.wds.remote_addr);
904 if (sta) { 922 if (sta)
905 sta_info_free(sta); 923 sta_info_unlink(&sta);
906 sta_info_put(sta); 924 else
907 } else {
908 printk(KERN_DEBUG "%s: could not find STA entry for WDS link " 925 printk(KERN_DEBUG "%s: could not find STA entry for WDS link "
909 "peer %s\n", 926 "peer %s\n",
910 dev->name, print_mac(mac, sdata->u.wds.remote_addr)); 927 dev->name, print_mac(mac, sdata->u.wds.remote_addr));
911 }
912 928
913 /* Update WDS link data */ 929 /* Update WDS link data */
914 memcpy(&sdata->u.wds.remote_addr, remote_addr, ETH_ALEN); 930 memcpy(&sdata->u.wds.remote_addr, remote_addr, ETH_ALEN);
915 931
932 rcu_read_unlock();
933
934 if (sta) {
935 synchronize_rcu();
936 sta_info_destroy(sta);
937 }
938
916 return 0; 939 return 0;
917} 940}
918 941
@@ -1330,6 +1353,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
1330 return; 1353 return;
1331 } 1354 }
1332 1355
1356 rcu_read_lock();
1357
1333 if (status->excessive_retries) { 1358 if (status->excessive_retries) {
1334 struct sta_info *sta; 1359 struct sta_info *sta;
1335 sta = sta_info_get(local, hdr->addr1); 1360 sta = sta_info_get(local, hdr->addr1);
@@ -1343,10 +1368,9 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
1343 status->flags |= IEEE80211_TX_STATUS_TX_FILTERED; 1368 status->flags |= IEEE80211_TX_STATUS_TX_FILTERED;
1344 ieee80211_handle_filtered_frame(local, sta, 1369 ieee80211_handle_filtered_frame(local, sta,
1345 skb, status); 1370 skb, status);
1346 sta_info_put(sta); 1371 rcu_read_unlock();
1347 return; 1372 return;
1348 } 1373 }
1349 sta_info_put(sta);
1350 } 1374 }
1351 } 1375 }
1352 1376
@@ -1356,12 +1380,14 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
1356 if (sta) { 1380 if (sta) {
1357 ieee80211_handle_filtered_frame(local, sta, skb, 1381 ieee80211_handle_filtered_frame(local, sta, skb,
1358 status); 1382 status);
1359 sta_info_put(sta); 1383 rcu_read_unlock();
1360 return; 1384 return;
1361 } 1385 }
1362 } else 1386 } else
1363 rate_control_tx_status(local->mdev, skb, status); 1387 rate_control_tx_status(local->mdev, skb, status);
1364 1388
1389 rcu_read_unlock();
1390
1365 ieee80211_led_tx(local, 0); 1391 ieee80211_led_tx(local, 0);
1366 1392
1367 /* SNMP counters 1393 /* SNMP counters