aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c155
1 files changed, 129 insertions, 26 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index d595265d6c2..0f48368c2e2 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -613,6 +613,9 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata)
613 if (!mgd->powersave) 613 if (!mgd->powersave)
614 return false; 614 return false;
615 615
616 if (mgd->broken_ap)
617 return false;
618
616 if (!mgd->associated) 619 if (!mgd->associated)
617 return false; 620 return false;
618 621
@@ -749,7 +752,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
749 container_of(work, struct ieee80211_local, 752 container_of(work, struct ieee80211_local,
750 dynamic_ps_enable_work); 753 dynamic_ps_enable_work);
751 struct ieee80211_sub_if_data *sdata = local->ps_sdata; 754 struct ieee80211_sub_if_data *sdata = local->ps_sdata;
752 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 755 struct ieee80211_if_managed *ifmgd;
753 unsigned long flags; 756 unsigned long flags;
754 int q; 757 int q;
755 758
@@ -757,26 +760,39 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
757 if (!sdata) 760 if (!sdata)
758 return; 761 return;
759 762
763 ifmgd = &sdata->u.mgd;
764
760 if (local->hw.conf.flags & IEEE80211_CONF_PS) 765 if (local->hw.conf.flags & IEEE80211_CONF_PS)
761 return; 766 return;
762 767
763 /* 768 if (!local->disable_dynamic_ps &&
764 * transmission can be stopped by others which leads to 769 local->hw.conf.dynamic_ps_timeout > 0) {
765 * dynamic_ps_timer expiry. Postpond the ps timer if it 770 /* don't enter PS if TX frames are pending */
766 * is not the actual idle state. 771 if (drv_tx_frames_pending(local)) {
767 */
768 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
769 for (q = 0; q < local->hw.queues; q++) {
770 if (local->queue_stop_reasons[q]) {
771 spin_unlock_irqrestore(&local->queue_stop_reason_lock,
772 flags);
773 mod_timer(&local->dynamic_ps_timer, jiffies + 772 mod_timer(&local->dynamic_ps_timer, jiffies +
774 msecs_to_jiffies( 773 msecs_to_jiffies(
775 local->hw.conf.dynamic_ps_timeout)); 774 local->hw.conf.dynamic_ps_timeout));
776 return; 775 return;
777 } 776 }
777
778 /*
779 * transmission can be stopped by others which leads to
780 * dynamic_ps_timer expiry. Postpone the ps timer if it
781 * is not the actual idle state.
782 */
783 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
784 for (q = 0; q < local->hw.queues; q++) {
785 if (local->queue_stop_reasons[q]) {
786 spin_unlock_irqrestore(&local->queue_stop_reason_lock,
787 flags);
788 mod_timer(&local->dynamic_ps_timer, jiffies +
789 msecs_to_jiffies(
790 local->hw.conf.dynamic_ps_timeout));
791 return;
792 }
793 }
794 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
778 } 795 }
779 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
780 796
781 if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && 797 if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
782 (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { 798 (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) {
@@ -801,7 +817,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
801 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); 817 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
802 } 818 }
803 819
804 netif_tx_wake_all_queues(sdata->dev); 820 if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
821 netif_tx_wake_all_queues(sdata->dev);
805} 822}
806 823
807void ieee80211_dynamic_ps_timer(unsigned long data) 824void ieee80211_dynamic_ps_timer(unsigned long data)
@@ -903,6 +920,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
903 params.aifs, params.cw_min, params.cw_max, 920 params.aifs, params.cw_min, params.cw_max,
904 params.txop, params.uapsd); 921 params.txop, params.uapsd);
905#endif 922#endif
923 local->tx_conf[queue] = params;
906 if (drv_conf_tx(local, queue, &params)) 924 if (drv_conf_tx(local, queue, &params))
907 wiphy_debug(local->hw.wiphy, 925 wiphy_debug(local->hw.wiphy,
908 "failed to set TX queue parameters for queue %d\n", 926 "failed to set TX queue parameters for queue %d\n",
@@ -1204,7 +1222,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
1204 ieee80211_send_nullfunc(sdata->local, sdata, 0); 1222 ieee80211_send_nullfunc(sdata->local, sdata, 0);
1205 } else { 1223 } else {
1206 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); 1224 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
1207 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); 1225 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0,
1226 (u32) -1, true);
1208 } 1227 }
1209 1228
1210 ifmgd->probe_send_count++; 1229 ifmgd->probe_send_count++;
@@ -1289,7 +1308,8 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
1289 1308
1290 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); 1309 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
1291 skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid, 1310 skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid,
1292 ssid + 2, ssid[1], NULL, 0); 1311 (u32) -1, ssid + 2, ssid[1],
1312 NULL, 0, true);
1293 1313
1294 return skb; 1314 return skb;
1295} 1315}
@@ -1450,10 +1470,21 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1450 capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); 1470 capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
1451 1471
1452 if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) 1472 if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
1453 printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " 1473 printk(KERN_DEBUG
1454 "set\n", sdata->name, aid); 1474 "%s: invalid AID value 0x%x; bits 15:14 not set\n",
1475 sdata->name, aid);
1455 aid &= ~(BIT(15) | BIT(14)); 1476 aid &= ~(BIT(15) | BIT(14));
1456 1477
1478 ifmgd->broken_ap = false;
1479
1480 if (aid == 0 || aid > IEEE80211_MAX_AID) {
1481 printk(KERN_DEBUG
1482 "%s: invalid AID value %d (out of range), turn off PS\n",
1483 sdata->name, aid);
1484 aid = 0;
1485 ifmgd->broken_ap = true;
1486 }
1487
1457 pos = mgmt->u.assoc_resp.variable; 1488 pos = mgmt->u.assoc_resp.variable;
1458 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); 1489 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
1459 1490
@@ -1748,6 +1779,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1748 ifmgd->ave_beacon_signal = rx_status->signal * 16; 1779 ifmgd->ave_beacon_signal = rx_status->signal * 16;
1749 ifmgd->last_cqm_event_signal = 0; 1780 ifmgd->last_cqm_event_signal = 0;
1750 ifmgd->count_beacon_signal = 1; 1781 ifmgd->count_beacon_signal = 1;
1782 ifmgd->last_ave_beacon_signal = 0;
1751 } else { 1783 } else {
1752 ifmgd->ave_beacon_signal = 1784 ifmgd->ave_beacon_signal =
1753 (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + 1785 (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 +
@@ -1755,6 +1787,28 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1755 ifmgd->ave_beacon_signal) / 16; 1787 ifmgd->ave_beacon_signal) / 16;
1756 ifmgd->count_beacon_signal++; 1788 ifmgd->count_beacon_signal++;
1757 } 1789 }
1790
1791 if (ifmgd->rssi_min_thold != ifmgd->rssi_max_thold &&
1792 ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
1793 int sig = ifmgd->ave_beacon_signal;
1794 int last_sig = ifmgd->last_ave_beacon_signal;
1795
1796 /*
1797 * if signal crosses either of the boundaries, invoke callback
1798 * with appropriate parameters
1799 */
1800 if (sig > ifmgd->rssi_max_thold &&
1801 (last_sig <= ifmgd->rssi_min_thold || last_sig == 0)) {
1802 ifmgd->last_ave_beacon_signal = sig;
1803 drv_rssi_callback(local, RSSI_EVENT_HIGH);
1804 } else if (sig < ifmgd->rssi_min_thold &&
1805 (last_sig >= ifmgd->rssi_max_thold ||
1806 last_sig == 0)) {
1807 ifmgd->last_ave_beacon_signal = sig;
1808 drv_rssi_callback(local, RSSI_EVENT_LOW);
1809 }
1810 }
1811
1758 if (bss_conf->cqm_rssi_thold && 1812 if (bss_conf->cqm_rssi_thold &&
1759 ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT && 1813 ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT &&
1760 !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { 1814 !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) {
@@ -2014,7 +2068,7 @@ static void ieee80211_sta_timer(unsigned long data)
2014} 2068}
2015 2069
2016static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, 2070static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
2017 u8 *bssid) 2071 u8 *bssid, u8 reason)
2018{ 2072{
2019 struct ieee80211_local *local = sdata->local; 2073 struct ieee80211_local *local = sdata->local;
2020 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2074 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -2032,8 +2086,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
2032 * but that's not a problem. 2086 * but that's not a problem.
2033 */ 2087 */
2034 ieee80211_send_deauth_disassoc(sdata, bssid, 2088 ieee80211_send_deauth_disassoc(sdata, bssid,
2035 IEEE80211_STYPE_DEAUTH, 2089 IEEE80211_STYPE_DEAUTH, reason,
2036 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
2037 NULL, true); 2090 NULL, true);
2038 mutex_lock(&ifmgd->mtx); 2091 mutex_lock(&ifmgd->mtx);
2039} 2092}
@@ -2079,7 +2132,8 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
2079 " AP %pM, disconnecting.\n", 2132 " AP %pM, disconnecting.\n",
2080 sdata->name, bssid); 2133 sdata->name, bssid);
2081#endif 2134#endif
2082 ieee80211_sta_connection_lost(sdata, bssid); 2135 ieee80211_sta_connection_lost(sdata, bssid,
2136 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
2083 } 2137 }
2084 } else if (time_is_after_jiffies(ifmgd->probe_timeout)) 2138 } else if (time_is_after_jiffies(ifmgd->probe_timeout))
2085 run_again(ifmgd, ifmgd->probe_timeout); 2139 run_again(ifmgd, ifmgd->probe_timeout);
@@ -2091,7 +2145,8 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
2091 sdata->name, 2145 sdata->name,
2092 bssid, probe_wait_ms); 2146 bssid, probe_wait_ms);
2093#endif 2147#endif
2094 ieee80211_sta_connection_lost(sdata, bssid); 2148 ieee80211_sta_connection_lost(sdata, bssid,
2149 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
2095 } else if (ifmgd->probe_send_count < max_tries) { 2150 } else if (ifmgd->probe_send_count < max_tries) {
2096#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 2151#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
2097 wiphy_debug(local->hw.wiphy, 2152 wiphy_debug(local->hw.wiphy,
@@ -2113,7 +2168,8 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
2113 sdata->name, 2168 sdata->name,
2114 bssid, probe_wait_ms); 2169 bssid, probe_wait_ms);
2115 2170
2116 ieee80211_sta_connection_lost(sdata, bssid); 2171 ieee80211_sta_connection_lost(sdata, bssid,
2172 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
2117 } 2173 }
2118 } 2174 }
2119 2175
@@ -2200,12 +2256,34 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
2200{ 2256{
2201 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2257 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2202 2258
2259 if (!ifmgd->associated)
2260 return;
2261
2262 if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) {
2263 sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME;
2264 mutex_lock(&ifmgd->mtx);
2265 if (ifmgd->associated) {
2266#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
2267 wiphy_debug(sdata->local->hw.wiphy,
2268 "%s: driver requested disconnect after resume.\n",
2269 sdata->name);
2270#endif
2271 ieee80211_sta_connection_lost(sdata,
2272 ifmgd->associated->bssid,
2273 WLAN_REASON_UNSPECIFIED);
2274 mutex_unlock(&ifmgd->mtx);
2275 return;
2276 }
2277 mutex_unlock(&ifmgd->mtx);
2278 }
2279
2203 if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running)) 2280 if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running))
2204 add_timer(&ifmgd->timer); 2281 add_timer(&ifmgd->timer);
2205 if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) 2282 if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running))
2206 add_timer(&ifmgd->chswitch_timer); 2283 add_timer(&ifmgd->chswitch_timer);
2207 ieee80211_sta_reset_beacon_monitor(sdata); 2284 ieee80211_sta_reset_beacon_monitor(sdata);
2208 ieee80211_restart_sta_timer(sdata); 2285 ieee80211_restart_sta_timer(sdata);
2286 ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.monitor_work);
2209} 2287}
2210#endif 2288#endif
2211 2289
@@ -2271,14 +2349,16 @@ static enum work_done_result
2271ieee80211_probe_auth_done(struct ieee80211_work *wk, 2349ieee80211_probe_auth_done(struct ieee80211_work *wk,
2272 struct sk_buff *skb) 2350 struct sk_buff *skb)
2273{ 2351{
2352 struct ieee80211_local *local = wk->sdata->local;
2353
2274 if (!skb) { 2354 if (!skb) {
2275 cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta); 2355 cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta);
2276 return WORK_DONE_DESTROY; 2356 goto destroy;
2277 } 2357 }
2278 2358
2279 if (wk->type == IEEE80211_WORK_AUTH) { 2359 if (wk->type == IEEE80211_WORK_AUTH) {
2280 cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len); 2360 cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len);
2281 return WORK_DONE_DESTROY; 2361 goto destroy;
2282 } 2362 }
2283 2363
2284 mutex_lock(&wk->sdata->u.mgd.mtx); 2364 mutex_lock(&wk->sdata->u.mgd.mtx);
@@ -2288,6 +2368,12 @@ ieee80211_probe_auth_done(struct ieee80211_work *wk,
2288 wk->type = IEEE80211_WORK_AUTH; 2368 wk->type = IEEE80211_WORK_AUTH;
2289 wk->probe_auth.tries = 0; 2369 wk->probe_auth.tries = 0;
2290 return WORK_DONE_REQUEUE; 2370 return WORK_DONE_REQUEUE;
2371 destroy:
2372 if (wk->probe_auth.synced)
2373 drv_finish_tx_sync(local, wk->sdata, wk->filter_ta,
2374 IEEE80211_TX_SYNC_AUTH);
2375
2376 return WORK_DONE_DESTROY;
2291} 2377}
2292 2378
2293int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, 2379int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
@@ -2360,6 +2446,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
2360static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, 2446static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
2361 struct sk_buff *skb) 2447 struct sk_buff *skb)
2362{ 2448{
2449 struct ieee80211_local *local = wk->sdata->local;
2363 struct ieee80211_mgmt *mgmt; 2450 struct ieee80211_mgmt *mgmt;
2364 struct ieee80211_rx_status *rx_status; 2451 struct ieee80211_rx_status *rx_status;
2365 struct ieee802_11_elems elems; 2452 struct ieee802_11_elems elems;
@@ -2367,7 +2454,7 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
2367 2454
2368 if (!skb) { 2455 if (!skb) {
2369 cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); 2456 cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta);
2370 return WORK_DONE_DESTROY; 2457 goto destroy;
2371 } 2458 }
2372 2459
2373 if (wk->type == IEEE80211_WORK_ASSOC_BEACON_WAIT) { 2460 if (wk->type == IEEE80211_WORK_ASSOC_BEACON_WAIT) {
@@ -2387,6 +2474,10 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
2387 status = le16_to_cpu(mgmt->u.assoc_resp.status_code); 2474 status = le16_to_cpu(mgmt->u.assoc_resp.status_code);
2388 2475
2389 if (status == WLAN_STATUS_SUCCESS) { 2476 if (status == WLAN_STATUS_SUCCESS) {
2477 if (wk->assoc.synced)
2478 drv_finish_tx_sync(local, wk->sdata, wk->filter_ta,
2479 IEEE80211_TX_SYNC_ASSOC);
2480
2390 mutex_lock(&wk->sdata->u.mgd.mtx); 2481 mutex_lock(&wk->sdata->u.mgd.mtx);
2391 if (!ieee80211_assoc_success(wk, mgmt, skb->len)) { 2482 if (!ieee80211_assoc_success(wk, mgmt, skb->len)) {
2392 mutex_unlock(&wk->sdata->u.mgd.mtx); 2483 mutex_unlock(&wk->sdata->u.mgd.mtx);
@@ -2400,6 +2491,11 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
2400 } 2491 }
2401 2492
2402 cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); 2493 cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len);
2494 destroy:
2495 if (wk->assoc.synced)
2496 drv_finish_tx_sync(local, wk->sdata, wk->filter_ta,
2497 IEEE80211_TX_SYNC_ASSOC);
2498
2403 return WORK_DONE_DESTROY; 2499 return WORK_DONE_DESTROY;
2404} 2500}
2405 2501
@@ -2652,3 +2748,10 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
2652 cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); 2748 cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp);
2653} 2749}
2654EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); 2750EXPORT_SYMBOL(ieee80211_cqm_rssi_notify);
2751
2752unsigned char ieee80211_get_operstate(struct ieee80211_vif *vif)
2753{
2754 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
2755 return sdata->dev->operstate;
2756}
2757EXPORT_SYMBOL(ieee80211_get_operstate);