diff options
Diffstat (limited to 'net/mac80211/work.c')
-rw-r--r-- | net/mac80211/work.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index b025dc7bb0fd..81d4ad64184a 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -560,6 +560,22 @@ ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk) | |||
560 | return WORK_ACT_TIMEOUT; | 560 | return WORK_ACT_TIMEOUT; |
561 | } | 561 | } |
562 | 562 | ||
563 | static enum work_action __must_check | ||
564 | ieee80211_assoc_beacon_wait(struct ieee80211_work *wk) | ||
565 | { | ||
566 | if (wk->started) | ||
567 | return WORK_ACT_TIMEOUT; | ||
568 | |||
569 | /* | ||
570 | * Wait up to one beacon interval ... | ||
571 | * should this be more if we miss one? | ||
572 | */ | ||
573 | printk(KERN_DEBUG "%s: waiting for beacon from %pM\n", | ||
574 | wk->sdata->name, wk->filter_ta); | ||
575 | wk->timeout = TU_TO_EXP_TIME(wk->assoc.bss->beacon_interval); | ||
576 | return WORK_ACT_NONE; | ||
577 | } | ||
578 | |||
563 | static void ieee80211_auth_challenge(struct ieee80211_work *wk, | 579 | static void ieee80211_auth_challenge(struct ieee80211_work *wk, |
564 | struct ieee80211_mgmt *mgmt, | 580 | struct ieee80211_mgmt *mgmt, |
565 | size_t len) | 581 | size_t len) |
@@ -709,6 +725,25 @@ ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk, | |||
709 | return WORK_ACT_DONE; | 725 | return WORK_ACT_DONE; |
710 | } | 726 | } |
711 | 727 | ||
728 | static enum work_action __must_check | ||
729 | ieee80211_rx_mgmt_beacon(struct ieee80211_work *wk, | ||
730 | struct ieee80211_mgmt *mgmt, size_t len) | ||
731 | { | ||
732 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
733 | struct ieee80211_local *local = sdata->local; | ||
734 | |||
735 | ASSERT_WORK_MTX(local); | ||
736 | |||
737 | if (wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) | ||
738 | return WORK_ACT_MISMATCH; | ||
739 | |||
740 | if (len < 24 + 12) | ||
741 | return WORK_ACT_NONE; | ||
742 | |||
743 | printk(KERN_DEBUG "%s: beacon received\n", sdata->name); | ||
744 | return WORK_ACT_DONE; | ||
745 | } | ||
746 | |||
712 | static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | 747 | static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, |
713 | struct sk_buff *skb) | 748 | struct sk_buff *skb) |
714 | { | 749 | { |
@@ -731,6 +766,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
731 | case IEEE80211_WORK_DIRECT_PROBE: | 766 | case IEEE80211_WORK_DIRECT_PROBE: |
732 | case IEEE80211_WORK_AUTH: | 767 | case IEEE80211_WORK_AUTH: |
733 | case IEEE80211_WORK_ASSOC: | 768 | case IEEE80211_WORK_ASSOC: |
769 | case IEEE80211_WORK_ASSOC_BEACON_WAIT: | ||
734 | bssid = wk->filter_ta; | 770 | bssid = wk->filter_ta; |
735 | break; | 771 | break; |
736 | default: | 772 | default: |
@@ -745,6 +781,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
745 | continue; | 781 | continue; |
746 | 782 | ||
747 | switch (fc & IEEE80211_FCTL_STYPE) { | 783 | switch (fc & IEEE80211_FCTL_STYPE) { |
784 | case IEEE80211_STYPE_BEACON: | ||
785 | rma = ieee80211_rx_mgmt_beacon(wk, mgmt, skb->len); | ||
786 | break; | ||
748 | case IEEE80211_STYPE_PROBE_RESP: | 787 | case IEEE80211_STYPE_PROBE_RESP: |
749 | rma = ieee80211_rx_mgmt_probe_resp(wk, mgmt, skb->len, | 788 | rma = ieee80211_rx_mgmt_probe_resp(wk, mgmt, skb->len, |
750 | rx_status); | 789 | rx_status); |
@@ -840,7 +879,7 @@ static void ieee80211_work_work(struct work_struct *work) | |||
840 | 879 | ||
841 | /* | 880 | /* |
842 | * ieee80211_queue_work() should have picked up most cases, | 881 | * ieee80211_queue_work() should have picked up most cases, |
843 | * here we'll pick the the rest. | 882 | * here we'll pick the rest. |
844 | */ | 883 | */ |
845 | if (WARN(local->suspended, "work scheduled while going to suspend\n")) | 884 | if (WARN(local->suspended, "work scheduled while going to suspend\n")) |
846 | return; | 885 | return; |
@@ -916,6 +955,9 @@ static void ieee80211_work_work(struct work_struct *work) | |||
916 | case IEEE80211_WORK_REMAIN_ON_CHANNEL: | 955 | case IEEE80211_WORK_REMAIN_ON_CHANNEL: |
917 | rma = ieee80211_remain_on_channel_timeout(wk); | 956 | rma = ieee80211_remain_on_channel_timeout(wk); |
918 | break; | 957 | break; |
958 | case IEEE80211_WORK_ASSOC_BEACON_WAIT: | ||
959 | rma = ieee80211_assoc_beacon_wait(wk); | ||
960 | break; | ||
919 | } | 961 | } |
920 | 962 | ||
921 | wk->started = started; | 963 | wk->started = started; |
@@ -1065,6 +1107,7 @@ ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1065 | case IEEE80211_STYPE_PROBE_RESP: | 1107 | case IEEE80211_STYPE_PROBE_RESP: |
1066 | case IEEE80211_STYPE_ASSOC_RESP: | 1108 | case IEEE80211_STYPE_ASSOC_RESP: |
1067 | case IEEE80211_STYPE_REASSOC_RESP: | 1109 | case IEEE80211_STYPE_REASSOC_RESP: |
1110 | case IEEE80211_STYPE_BEACON: | ||
1068 | skb_queue_tail(&local->work_skb_queue, skb); | 1111 | skb_queue_tail(&local->work_skb_queue, skb); |
1069 | ieee80211_queue_work(&local->hw, &local->work_work); | 1112 | ieee80211_queue_work(&local->hw, &local->work_work); |
1070 | return RX_QUEUED; | 1113 | return RX_QUEUED; |