diff options
Diffstat (limited to 'net/mac80211/work.c')
-rw-r--r-- | net/mac80211/work.c | 62 |
1 files changed, 50 insertions, 12 deletions
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 15e1ba931b8..be3d4a69869 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #define IEEE80211_MAX_PROBE_TRIES 5 | 33 | #define IEEE80211_MAX_PROBE_TRIES 5 |
34 | 34 | ||
35 | enum work_action { | 35 | enum work_action { |
36 | WORK_ACT_MISMATCH, | ||
36 | WORK_ACT_NONE, | 37 | WORK_ACT_NONE, |
37 | WORK_ACT_TIMEOUT, | 38 | WORK_ACT_TIMEOUT, |
38 | WORK_ACT_DONE, | 39 | WORK_ACT_DONE, |
@@ -213,15 +214,25 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
213 | 214 | ||
214 | sband = local->hw.wiphy->bands[wk->chan->band]; | 215 | sband = local->hw.wiphy->bands[wk->chan->band]; |
215 | 216 | ||
216 | /* | 217 | if (wk->assoc.supp_rates_len) { |
217 | * Get all rates supported by the device and the AP as | 218 | /* |
218 | * some APs don't like getting a superset of their rates | 219 | * Get all rates supported by the device and the AP as |
219 | * in the association request (e.g. D-Link DAP 1353 in | 220 | * some APs don't like getting a superset of their rates |
220 | * b-only mode)... | 221 | * in the association request (e.g. D-Link DAP 1353 in |
221 | */ | 222 | * b-only mode)... |
222 | rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, | 223 | */ |
223 | wk->assoc.supp_rates_len, | 224 | rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, |
224 | sband, &rates); | 225 | wk->assoc.supp_rates_len, |
226 | sband, &rates); | ||
227 | } else { | ||
228 | /* | ||
229 | * In case AP not provide any supported rates information | ||
230 | * before association, we send information element(s) with | ||
231 | * all rates that we support. | ||
232 | */ | ||
233 | rates = ~0; | ||
234 | rates_len = sband->n_bitrates; | ||
235 | } | ||
225 | 236 | ||
226 | skb = alloc_skb(local->hw.extra_tx_headroom + | 237 | skb = alloc_skb(local->hw.extra_tx_headroom + |
227 | sizeof(*mgmt) + /* bit too much but doesn't matter */ | 238 | sizeof(*mgmt) + /* bit too much but doesn't matter */ |
@@ -575,7 +586,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_work *wk, | |||
575 | u16 auth_alg, auth_transaction, status_code; | 586 | u16 auth_alg, auth_transaction, status_code; |
576 | 587 | ||
577 | if (wk->type != IEEE80211_WORK_AUTH) | 588 | if (wk->type != IEEE80211_WORK_AUTH) |
578 | return WORK_ACT_NONE; | 589 | return WORK_ACT_MISMATCH; |
579 | 590 | ||
580 | if (len < 24 + 6) | 591 | if (len < 24 + 6) |
581 | return WORK_ACT_NONE; | 592 | return WORK_ACT_NONE; |
@@ -626,6 +637,9 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk, | |||
626 | struct ieee802_11_elems elems; | 637 | struct ieee802_11_elems elems; |
627 | u8 *pos; | 638 | u8 *pos; |
628 | 639 | ||
640 | if (wk->type != IEEE80211_WORK_ASSOC) | ||
641 | return WORK_ACT_MISMATCH; | ||
642 | |||
629 | /* | 643 | /* |
630 | * AssocResp and ReassocResp have identical structure, so process both | 644 | * AssocResp and ReassocResp have identical structure, so process both |
631 | * of them in this function. | 645 | * of them in this function. |
@@ -681,6 +695,12 @@ ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk, | |||
681 | 695 | ||
682 | ASSERT_WORK_MTX(local); | 696 | ASSERT_WORK_MTX(local); |
683 | 697 | ||
698 | if (wk->type != IEEE80211_WORK_DIRECT_PROBE) | ||
699 | return WORK_ACT_MISMATCH; | ||
700 | |||
701 | if (len < 24 + 12) | ||
702 | return WORK_ACT_NONE; | ||
703 | |||
684 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 704 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
685 | if (baselen > len) | 705 | if (baselen > len) |
686 | return WORK_ACT_NONE; | 706 | return WORK_ACT_NONE; |
@@ -695,7 +715,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
695 | struct ieee80211_rx_status *rx_status; | 715 | struct ieee80211_rx_status *rx_status; |
696 | struct ieee80211_mgmt *mgmt; | 716 | struct ieee80211_mgmt *mgmt; |
697 | struct ieee80211_work *wk; | 717 | struct ieee80211_work *wk; |
698 | enum work_action rma = WORK_ACT_NONE; | 718 | enum work_action rma; |
699 | u16 fc; | 719 | u16 fc; |
700 | 720 | ||
701 | rx_status = (struct ieee80211_rx_status *) skb->cb; | 721 | rx_status = (struct ieee80211_rx_status *) skb->cb; |
@@ -742,7 +762,17 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
742 | break; | 762 | break; |
743 | default: | 763 | default: |
744 | WARN_ON(1); | 764 | WARN_ON(1); |
765 | rma = WORK_ACT_NONE; | ||
745 | } | 766 | } |
767 | |||
768 | /* | ||
769 | * We've either received an unexpected frame, or we have | ||
770 | * multiple work items and need to match the frame to the | ||
771 | * right one. | ||
772 | */ | ||
773 | if (rma == WORK_ACT_MISMATCH) | ||
774 | continue; | ||
775 | |||
746 | /* | 776 | /* |
747 | * We've processed this frame for that work, so it can't | 777 | * We've processed this frame for that work, so it can't |
748 | * belong to another work struct. | 778 | * belong to another work struct. |
@@ -752,6 +782,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
752 | } | 782 | } |
753 | 783 | ||
754 | switch (rma) { | 784 | switch (rma) { |
785 | case WORK_ACT_MISMATCH: | ||
786 | /* ignore this unmatched frame */ | ||
787 | break; | ||
755 | case WORK_ACT_NONE: | 788 | case WORK_ACT_NONE: |
756 | break; | 789 | break; |
757 | case WORK_ACT_DONE: | 790 | case WORK_ACT_DONE: |
@@ -920,11 +953,16 @@ static void ieee80211_work_work(struct work_struct *work) | |||
920 | run_again(local, jiffies + HZ/2); | 953 | run_again(local, jiffies + HZ/2); |
921 | } | 954 | } |
922 | 955 | ||
923 | if (list_empty(&local->work_list) && local->scan_req) | 956 | mutex_lock(&local->scan_mtx); |
957 | |||
958 | if (list_empty(&local->work_list) && local->scan_req && | ||
959 | !local->scanning) | ||
924 | ieee80211_queue_delayed_work(&local->hw, | 960 | ieee80211_queue_delayed_work(&local->hw, |
925 | &local->scan_work, | 961 | &local->scan_work, |
926 | round_jiffies_relative(0)); | 962 | round_jiffies_relative(0)); |
927 | 963 | ||
964 | mutex_unlock(&local->scan_mtx); | ||
965 | |||
928 | mutex_unlock(&local->work_mtx); | 966 | mutex_unlock(&local->work_mtx); |
929 | 967 | ||
930 | ieee80211_recalc_idle(local); | 968 | ieee80211_recalc_idle(local); |