diff options
Diffstat (limited to 'net/mac80211')
39 files changed, 2518 insertions, 1350 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 7d3b438755f0..96ddb72760b9 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -247,15 +247,3 @@ config MAC80211_DEBUG_COUNTERS | |||
247 | and show them in debugfs. | 247 | and show them in debugfs. |
248 | 248 | ||
249 | If unsure, say N. | 249 | If unsure, say N. |
250 | |||
251 | config MAC80211_DRIVER_API_TRACER | ||
252 | bool "Driver API tracer" | ||
253 | depends on MAC80211_DEBUG_MENU | ||
254 | depends on EVENT_TRACING | ||
255 | help | ||
256 | Say Y here to make mac80211 register with the ftrace | ||
257 | framework for the driver API -- you can then see which | ||
258 | driver methods it is calling and which API functions | ||
259 | drivers are calling by looking at the trace. | ||
260 | |||
261 | If unsure, say Y. | ||
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index fdb54e61d637..d540c3b160f3 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -24,7 +24,8 @@ mac80211-y := \ | |||
24 | util.o \ | 24 | util.o \ |
25 | wme.o \ | 25 | wme.o \ |
26 | event.o \ | 26 | event.o \ |
27 | chan.o | 27 | chan.o \ |
28 | driver-trace.o | ||
28 | 29 | ||
29 | mac80211-$(CONFIG_MAC80211_LEDS) += led.o | 30 | mac80211-$(CONFIG_MAC80211_LEDS) += led.o |
30 | mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ | 31 | mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ |
@@ -41,7 +42,6 @@ mac80211-$(CONFIG_MAC80211_MESH) += \ | |||
41 | 42 | ||
42 | mac80211-$(CONFIG_PM) += pm.o | 43 | mac80211-$(CONFIG_PM) += pm.o |
43 | 44 | ||
44 | mac80211-$(CONFIG_MAC80211_DRIVER_API_TRACER) += driver-trace.o | ||
45 | CFLAGS_driver-trace.o := -I$(src) | 45 | CFLAGS_driver-trace.o := -I$(src) |
46 | 46 | ||
47 | # objects for PID algorithm | 47 | # objects for PID algorithm |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 93b243422659..96debba2c407 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -73,8 +73,11 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
73 | RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL); | 73 | RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL); |
74 | 74 | ||
75 | #ifdef CONFIG_MAC80211_HT_DEBUG | 75 | #ifdef CONFIG_MAC80211_HT_DEBUG |
76 | printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", | 76 | printk(KERN_DEBUG |
77 | sta->sta.addr, tid); | 77 | "Rx BA session stop requested for %pM tid %u %s reason: %d\n", |
78 | sta->sta.addr, tid, | ||
79 | initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator", | ||
80 | (int)reason); | ||
78 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 81 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
79 | 82 | ||
80 | if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, | 83 | if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, |
@@ -85,7 +88,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
85 | /* check if this is a self generated aggregation halt */ | 88 | /* check if this is a self generated aggregation halt */ |
86 | if (initiator == WLAN_BACK_RECIPIENT && tx) | 89 | if (initiator == WLAN_BACK_RECIPIENT && tx) |
87 | ieee80211_send_delba(sta->sdata, sta->sta.addr, | 90 | ieee80211_send_delba(sta->sdata, sta->sta.addr, |
88 | tid, 0, reason); | 91 | tid, WLAN_BACK_RECIPIENT, reason); |
89 | 92 | ||
90 | del_timer_sync(&tid_rx->session_timer); | 93 | del_timer_sync(&tid_rx->session_timer); |
91 | del_timer_sync(&tid_rx->reorder_timer); | 94 | del_timer_sync(&tid_rx->reorder_timer); |
@@ -109,7 +112,7 @@ void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap, | |||
109 | int i; | 112 | int i; |
110 | 113 | ||
111 | rcu_read_lock(); | 114 | rcu_read_lock(); |
112 | sta = sta_info_get(sdata, addr); | 115 | sta = sta_info_get_bss(sdata, addr); |
113 | if (!sta) { | 116 | if (!sta) { |
114 | rcu_read_unlock(); | 117 | rcu_read_unlock(); |
115 | return; | 118 | return; |
@@ -177,10 +180,13 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d | |||
177 | memcpy(mgmt->da, da, ETH_ALEN); | 180 | memcpy(mgmt->da, da, ETH_ALEN); |
178 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 181 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
179 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 182 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
180 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 183 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
184 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | ||
181 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); | 185 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
182 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | 186 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
183 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); | 187 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
188 | else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
189 | memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN); | ||
184 | 190 | ||
185 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 191 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
186 | IEEE80211_STYPE_ACTION); | 192 | IEEE80211_STYPE_ACTION); |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 2e4b961648d4..76be61744198 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -55,6 +55,8 @@ | |||
55 | * @ampdu_action function will be called with the action | 55 | * @ampdu_action function will be called with the action |
56 | * %IEEE80211_AMPDU_TX_STOP. In this case, the call must not fail, | 56 | * %IEEE80211_AMPDU_TX_STOP. In this case, the call must not fail, |
57 | * and the driver must later call ieee80211_stop_tx_ba_cb_irqsafe(). | 57 | * and the driver must later call ieee80211_stop_tx_ba_cb_irqsafe(). |
58 | * Note that the sta can get destroyed before the BA tear down is | ||
59 | * complete. | ||
58 | */ | 60 | */ |
59 | 61 | ||
60 | static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | 62 | static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, |
@@ -78,10 +80,13 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | |||
78 | memcpy(mgmt->da, da, ETH_ALEN); | 80 | memcpy(mgmt->da, da, ETH_ALEN); |
79 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 81 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
80 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 82 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
81 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 83 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
84 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | ||
82 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); | 85 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
83 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | 86 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
84 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); | 87 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
88 | else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
89 | memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN); | ||
85 | 90 | ||
86 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 91 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
87 | IEEE80211_STYPE_ACTION); | 92 | IEEE80211_STYPE_ACTION); |
@@ -102,7 +107,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | |||
102 | mgmt->u.action.u.addba_req.start_seq_num = | 107 | mgmt->u.action.u.addba_req.start_seq_num = |
103 | cpu_to_le16(start_seq_num << 4); | 108 | cpu_to_le16(start_seq_num << 4); |
104 | 109 | ||
105 | ieee80211_tx_skb(sdata, skb); | 110 | ieee80211_tx_skb_tid(sdata, skb, tid); |
106 | } | 111 | } |
107 | 112 | ||
108 | void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) | 113 | void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) |
@@ -131,7 +136,7 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) | |||
131 | bar->start_seq_num = cpu_to_le16(ssn); | 136 | bar->start_seq_num = cpu_to_le16(ssn); |
132 | 137 | ||
133 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 138 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
134 | ieee80211_tx_skb(sdata, skb); | 139 | ieee80211_tx_skb_tid(sdata, skb, tid); |
135 | } | 140 | } |
136 | EXPORT_SYMBOL(ieee80211_send_bar); | 141 | EXPORT_SYMBOL(ieee80211_send_bar); |
137 | 142 | ||
@@ -185,6 +190,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
185 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 190 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
186 | 191 | ||
187 | del_timer_sync(&tid_tx->addba_resp_timer); | 192 | del_timer_sync(&tid_tx->addba_resp_timer); |
193 | del_timer_sync(&tid_tx->session_timer); | ||
188 | 194 | ||
189 | /* | 195 | /* |
190 | * After this packets are no longer handed right through | 196 | * After this packets are no longer handed right through |
@@ -386,6 +392,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
386 | #endif | 392 | #endif |
387 | 393 | ||
388 | spin_lock_bh(&sta->lock); | 394 | spin_lock_bh(&sta->lock); |
395 | sta->ampdu_mlme.last_addba_req_time[tid] = jiffies; | ||
389 | sta->ampdu_mlme.addba_req_num[tid]++; | 396 | sta->ampdu_mlme.addba_req_num[tid]++; |
390 | spin_unlock_bh(&sta->lock); | 397 | spin_unlock_bh(&sta->lock); |
391 | 398 | ||
@@ -396,6 +403,28 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
396 | tid_tx->timeout); | 403 | tid_tx->timeout); |
397 | } | 404 | } |
398 | 405 | ||
406 | /* | ||
407 | * After accepting the AddBA Response we activated a timer, | ||
408 | * resetting it after each frame that we send. | ||
409 | */ | ||
410 | static void sta_tx_agg_session_timer_expired(unsigned long data) | ||
411 | { | ||
412 | /* not an elegant detour, but there is no choice as the timer passes | ||
413 | * only one argument, and various sta_info are needed here, so init | ||
414 | * flow in sta_info_create gives the TID as data, while the timer_to_id | ||
415 | * array gives the sta through container_of */ | ||
416 | u8 *ptid = (u8 *)data; | ||
417 | u8 *timer_to_id = ptid - *ptid; | ||
418 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, | ||
419 | timer_to_tid[0]); | ||
420 | |||
421 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
422 | printk(KERN_DEBUG "tx session timer expired on tid %d\n", (u16)*ptid); | ||
423 | #endif | ||
424 | |||
425 | ieee80211_stop_tx_ba_session(&sta->sta, *ptid); | ||
426 | } | ||
427 | |||
399 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | 428 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, |
400 | u16 timeout) | 429 | u16 timeout) |
401 | { | 430 | { |
@@ -420,15 +449,11 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
420 | pubsta->addr, tid); | 449 | pubsta->addr, tid); |
421 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 450 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
422 | 451 | ||
423 | /* | ||
424 | * The aggregation code is not prepared to handle | ||
425 | * anything but STA/AP due to the BSSID handling. | ||
426 | * IBSS could work in the code but isn't supported | ||
427 | * by drivers or the standard. | ||
428 | */ | ||
429 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 452 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
453 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && | ||
430 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 454 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
431 | sdata->vif.type != NL80211_IFTYPE_AP) | 455 | sdata->vif.type != NL80211_IFTYPE_AP && |
456 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | ||
432 | return -EINVAL; | 457 | return -EINVAL; |
433 | 458 | ||
434 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { | 459 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { |
@@ -439,6 +464,27 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
439 | return -EINVAL; | 464 | return -EINVAL; |
440 | } | 465 | } |
441 | 466 | ||
467 | /* | ||
468 | * 802.11n-2009 11.5.1.1: If the initiating STA is an HT STA, is a | ||
469 | * member of an IBSS, and has no other existing Block Ack agreement | ||
470 | * with the recipient STA, then the initiating STA shall transmit a | ||
471 | * Probe Request frame to the recipient STA and shall not transmit an | ||
472 | * ADDBA Request frame unless it receives a Probe Response frame | ||
473 | * from the recipient within dot11ADDBAFailureTimeout. | ||
474 | * | ||
475 | * The probe request mechanism for ADDBA is currently not implemented, | ||
476 | * but we only build up Block Ack session with HT STAs. This information | ||
477 | * is set when we receive a bss info from a probe response or a beacon. | ||
478 | */ | ||
479 | if (sta->sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
480 | !sta->sta.ht_cap.ht_supported) { | ||
481 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
482 | printk(KERN_DEBUG "BA request denied - IBSS STA %pM" | ||
483 | "does not advertise HT support\n", pubsta->addr); | ||
484 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
485 | return -EINVAL; | ||
486 | } | ||
487 | |||
442 | spin_lock_bh(&sta->lock); | 488 | spin_lock_bh(&sta->lock); |
443 | 489 | ||
444 | /* we have tried too many times, receiver does not want A-MPDU */ | 490 | /* we have tried too many times, receiver does not want A-MPDU */ |
@@ -447,6 +493,24 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
447 | goto err_unlock_sta; | 493 | goto err_unlock_sta; |
448 | } | 494 | } |
449 | 495 | ||
496 | /* | ||
497 | * if we have tried more than HT_AGG_BURST_RETRIES times we | ||
498 | * will spread our requests in time to avoid stalling connection | ||
499 | * for too long | ||
500 | */ | ||
501 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_BURST_RETRIES && | ||
502 | time_before(jiffies, sta->ampdu_mlme.last_addba_req_time[tid] + | ||
503 | HT_AGG_RETRIES_PERIOD)) { | ||
504 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
505 | printk(KERN_DEBUG "BA request denied - " | ||
506 | "waiting a grace period after %d failed requests " | ||
507 | "on tid %u\n", | ||
508 | sta->ampdu_mlme.addba_req_num[tid], tid); | ||
509 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
510 | ret = -EBUSY; | ||
511 | goto err_unlock_sta; | ||
512 | } | ||
513 | |||
450 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 514 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
451 | /* check if the TID is not in aggregation flow already */ | 515 | /* check if the TID is not in aggregation flow already */ |
452 | if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) { | 516 | if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) { |
@@ -470,11 +534,16 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
470 | 534 | ||
471 | tid_tx->timeout = timeout; | 535 | tid_tx->timeout = timeout; |
472 | 536 | ||
473 | /* Tx timer */ | 537 | /* response timer */ |
474 | tid_tx->addba_resp_timer.function = sta_addba_resp_timer_expired; | 538 | tid_tx->addba_resp_timer.function = sta_addba_resp_timer_expired; |
475 | tid_tx->addba_resp_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | 539 | tid_tx->addba_resp_timer.data = (unsigned long)&sta->timer_to_tid[tid]; |
476 | init_timer(&tid_tx->addba_resp_timer); | 540 | init_timer(&tid_tx->addba_resp_timer); |
477 | 541 | ||
542 | /* tx timer */ | ||
543 | tid_tx->session_timer.function = sta_tx_agg_session_timer_expired; | ||
544 | tid_tx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | ||
545 | init_timer(&tid_tx->session_timer); | ||
546 | |||
478 | /* assign a dialog token */ | 547 | /* assign a dialog token */ |
479 | sta->ampdu_mlme.dialog_token_allocator++; | 548 | sta->ampdu_mlme.dialog_token_allocator++; |
480 | tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator; | 549 | tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator; |
@@ -547,7 +616,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | |||
547 | } | 616 | } |
548 | 617 | ||
549 | mutex_lock(&local->sta_mtx); | 618 | mutex_lock(&local->sta_mtx); |
550 | sta = sta_info_get(sdata, ra); | 619 | sta = sta_info_get_bss(sdata, ra); |
551 | if (!sta) { | 620 | if (!sta) { |
552 | mutex_unlock(&local->sta_mtx); | 621 | mutex_unlock(&local->sta_mtx); |
553 | #ifdef CONFIG_MAC80211_HT_DEBUG | 622 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -676,7 +745,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
676 | 745 | ||
677 | mutex_lock(&local->sta_mtx); | 746 | mutex_lock(&local->sta_mtx); |
678 | 747 | ||
679 | sta = sta_info_get(sdata, ra); | 748 | sta = sta_info_get_bss(sdata, ra); |
680 | if (!sta) { | 749 | if (!sta) { |
681 | #ifdef CONFIG_MAC80211_HT_DEBUG | 750 | #ifdef CONFIG_MAC80211_HT_DEBUG |
682 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); | 751 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); |
@@ -814,6 +883,11 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
814 | ieee80211_agg_tx_operational(local, sta, tid); | 883 | ieee80211_agg_tx_operational(local, sta, tid); |
815 | 884 | ||
816 | sta->ampdu_mlme.addba_req_num[tid] = 0; | 885 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
886 | |||
887 | if (tid_tx->timeout) | ||
888 | mod_timer(&tid_tx->session_timer, | ||
889 | TU_TO_EXP_TIME(tid_tx->timeout)); | ||
890 | |||
817 | } else { | 891 | } else { |
818 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, | 892 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, |
819 | true); | 893 | true); |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d06c65fa5526..850bb96bd680 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -102,6 +102,16 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
102 | return 0; | 102 | return 0; |
103 | } | 103 | } |
104 | 104 | ||
105 | static int ieee80211_set_noack_map(struct wiphy *wiphy, | ||
106 | struct net_device *dev, | ||
107 | u16 noack_map) | ||
108 | { | ||
109 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
110 | |||
111 | sdata->noack_map = noack_map; | ||
112 | return 0; | ||
113 | } | ||
114 | |||
105 | static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | 115 | static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, |
106 | u8 key_idx, bool pairwise, const u8 *mac_addr, | 116 | u8 key_idx, bool pairwise, const u8 *mac_addr, |
107 | struct key_params *params) | 117 | struct key_params *params) |
@@ -345,7 +355,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
345 | STATION_INFO_RX_DROP_MISC | | 355 | STATION_INFO_RX_DROP_MISC | |
346 | STATION_INFO_BSS_PARAM | | 356 | STATION_INFO_BSS_PARAM | |
347 | STATION_INFO_CONNECTED_TIME | | 357 | STATION_INFO_CONNECTED_TIME | |
348 | STATION_INFO_STA_FLAGS; | 358 | STATION_INFO_STA_FLAGS | |
359 | STATION_INFO_BEACON_LOSS_COUNT; | ||
349 | 360 | ||
350 | do_posix_clock_monotonic_gettime(&uptime); | 361 | do_posix_clock_monotonic_gettime(&uptime); |
351 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; | 362 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; |
@@ -358,6 +369,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
358 | sinfo->tx_retries = sta->tx_retry_count; | 369 | sinfo->tx_retries = sta->tx_retry_count; |
359 | sinfo->tx_failed = sta->tx_retry_failed; | 370 | sinfo->tx_failed = sta->tx_retry_failed; |
360 | sinfo->rx_dropped_misc = sta->rx_dropped; | 371 | sinfo->rx_dropped_misc = sta->rx_dropped; |
372 | sinfo->beacon_loss_count = sta->beacon_loss_count; | ||
361 | 373 | ||
362 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || | 374 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || |
363 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { | 375 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { |
@@ -411,7 +423,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
411 | BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | | 423 | BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | |
412 | BIT(NL80211_STA_FLAG_WME) | | 424 | BIT(NL80211_STA_FLAG_WME) | |
413 | BIT(NL80211_STA_FLAG_MFP) | | 425 | BIT(NL80211_STA_FLAG_MFP) | |
414 | BIT(NL80211_STA_FLAG_AUTHENTICATED); | 426 | BIT(NL80211_STA_FLAG_AUTHENTICATED) | |
427 | BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
415 | if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | 428 | if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) |
416 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED); | 429 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED); |
417 | if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE)) | 430 | if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE)) |
@@ -422,6 +435,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
422 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP); | 435 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP); |
423 | if (test_sta_flag(sta, WLAN_STA_AUTH)) | 436 | if (test_sta_flag(sta, WLAN_STA_AUTH)) |
424 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED); | 437 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED); |
438 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | ||
439 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
425 | } | 440 | } |
426 | 441 | ||
427 | 442 | ||
@@ -488,6 +503,31 @@ static void ieee80211_config_ap_ssid(struct ieee80211_sub_if_data *sdata, | |||
488 | (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE); | 503 | (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE); |
489 | } | 504 | } |
490 | 505 | ||
506 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, | ||
507 | u8 *resp, size_t resp_len) | ||
508 | { | ||
509 | struct sk_buff *new, *old; | ||
510 | |||
511 | if (!resp || !resp_len) | ||
512 | return -EINVAL; | ||
513 | |||
514 | old = rtnl_dereference(sdata->u.ap.probe_resp); | ||
515 | |||
516 | new = dev_alloc_skb(resp_len); | ||
517 | if (!new) | ||
518 | return -ENOMEM; | ||
519 | |||
520 | memcpy(skb_put(new, resp_len), resp, resp_len); | ||
521 | |||
522 | rcu_assign_pointer(sdata->u.ap.probe_resp, new); | ||
523 | synchronize_rcu(); | ||
524 | |||
525 | if (old) | ||
526 | dev_kfree_skb(old); | ||
527 | |||
528 | return 0; | ||
529 | } | ||
530 | |||
491 | /* | 531 | /* |
492 | * This handles both adding a beacon and setting new beacon info | 532 | * This handles both adding a beacon and setting new beacon info |
493 | */ | 533 | */ |
@@ -498,6 +538,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
498 | int new_head_len, new_tail_len; | 538 | int new_head_len, new_tail_len; |
499 | int size; | 539 | int size; |
500 | int err = -EINVAL; | 540 | int err = -EINVAL; |
541 | u32 changed = 0; | ||
501 | 542 | ||
502 | old = rtnl_dereference(sdata->u.ap.beacon); | 543 | old = rtnl_dereference(sdata->u.ap.beacon); |
503 | 544 | ||
@@ -581,11 +622,17 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
581 | 622 | ||
582 | kfree(old); | 623 | kfree(old); |
583 | 624 | ||
625 | err = ieee80211_set_probe_resp(sdata, params->probe_resp, | ||
626 | params->probe_resp_len); | ||
627 | if (!err) | ||
628 | changed |= BSS_CHANGED_AP_PROBE_RESP; | ||
629 | |||
584 | ieee80211_config_ap_ssid(sdata, params); | 630 | ieee80211_config_ap_ssid(sdata, params); |
631 | changed |= BSS_CHANGED_BEACON_ENABLED | | ||
632 | BSS_CHANGED_BEACON | | ||
633 | BSS_CHANGED_SSID; | ||
585 | 634 | ||
586 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | | 635 | ieee80211_bss_info_change_notify(sdata, changed); |
587 | BSS_CHANGED_BEACON | | ||
588 | BSS_CHANGED_SSID); | ||
589 | return 0; | 636 | return 0; |
590 | } | 637 | } |
591 | 638 | ||
@@ -594,6 +641,8 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
594 | { | 641 | { |
595 | struct ieee80211_sub_if_data *sdata; | 642 | struct ieee80211_sub_if_data *sdata; |
596 | struct beacon_data *old; | 643 | struct beacon_data *old; |
644 | struct ieee80211_sub_if_data *vlan; | ||
645 | int ret; | ||
597 | 646 | ||
598 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 647 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
599 | 648 | ||
@@ -601,7 +650,24 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
601 | if (old) | 650 | if (old) |
602 | return -EALREADY; | 651 | return -EALREADY; |
603 | 652 | ||
604 | return ieee80211_config_beacon(sdata, params); | 653 | ret = ieee80211_config_beacon(sdata, params); |
654 | if (ret) | ||
655 | return ret; | ||
656 | |||
657 | /* | ||
658 | * Apply control port protocol, this allows us to | ||
659 | * not encrypt dynamic WEP control frames. | ||
660 | */ | ||
661 | sdata->control_port_protocol = params->crypto.control_port_ethertype; | ||
662 | sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt; | ||
663 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { | ||
664 | vlan->control_port_protocol = | ||
665 | params->crypto.control_port_ethertype; | ||
666 | vlan->control_port_no_encrypt = | ||
667 | params->crypto.control_port_no_encrypt; | ||
668 | } | ||
669 | |||
670 | return 0; | ||
605 | } | 671 | } |
606 | 672 | ||
607 | static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | 673 | static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, |
@@ -682,10 +748,11 @@ static void ieee80211_send_layer2_update(struct sta_info *sta) | |||
682 | netif_rx_ni(skb); | 748 | netif_rx_ni(skb); |
683 | } | 749 | } |
684 | 750 | ||
685 | static void sta_apply_parameters(struct ieee80211_local *local, | 751 | static int sta_apply_parameters(struct ieee80211_local *local, |
686 | struct sta_info *sta, | 752 | struct sta_info *sta, |
687 | struct station_parameters *params) | 753 | struct station_parameters *params) |
688 | { | 754 | { |
755 | int ret = 0; | ||
689 | u32 rates; | 756 | u32 rates; |
690 | int i, j; | 757 | int i, j; |
691 | struct ieee80211_supported_band *sband; | 758 | struct ieee80211_supported_band *sband; |
@@ -697,13 +764,59 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
697 | mask = params->sta_flags_mask; | 764 | mask = params->sta_flags_mask; |
698 | set = params->sta_flags_set; | 765 | set = params->sta_flags_set; |
699 | 766 | ||
767 | /* | ||
768 | * In mesh mode, we can clear AUTHENTICATED flag but must | ||
769 | * also make ASSOCIATED follow appropriately for the driver | ||
770 | * API. See also below, after AUTHORIZED changes. | ||
771 | */ | ||
772 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { | ||
773 | /* cfg80211 should not allow this in non-mesh modes */ | ||
774 | if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif))) | ||
775 | return -EINVAL; | ||
776 | |||
777 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED) && | ||
778 | !test_sta_flag(sta, WLAN_STA_AUTH)) { | ||
779 | ret = sta_info_move_state_checked(sta, | ||
780 | IEEE80211_STA_AUTH); | ||
781 | if (ret) | ||
782 | return ret; | ||
783 | ret = sta_info_move_state_checked(sta, | ||
784 | IEEE80211_STA_ASSOC); | ||
785 | if (ret) | ||
786 | return ret; | ||
787 | } | ||
788 | } | ||
789 | |||
700 | if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { | 790 | if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { |
701 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) | 791 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) |
702 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); | 792 | ret = sta_info_move_state_checked(sta, |
793 | IEEE80211_STA_AUTHORIZED); | ||
703 | else | 794 | else |
704 | clear_sta_flag(sta, WLAN_STA_AUTHORIZED); | 795 | ret = sta_info_move_state_checked(sta, |
796 | IEEE80211_STA_ASSOC); | ||
797 | if (ret) | ||
798 | return ret; | ||
799 | } | ||
800 | |||
801 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { | ||
802 | /* cfg80211 should not allow this in non-mesh modes */ | ||
803 | if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif))) | ||
804 | return -EINVAL; | ||
805 | |||
806 | if (!(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) && | ||
807 | test_sta_flag(sta, WLAN_STA_AUTH)) { | ||
808 | ret = sta_info_move_state_checked(sta, | ||
809 | IEEE80211_STA_AUTH); | ||
810 | if (ret) | ||
811 | return ret; | ||
812 | ret = sta_info_move_state_checked(sta, | ||
813 | IEEE80211_STA_NONE); | ||
814 | if (ret) | ||
815 | return ret; | ||
816 | } | ||
705 | } | 817 | } |
706 | 818 | ||
819 | |||
707 | if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { | 820 | if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { |
708 | if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) | 821 | if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) |
709 | set_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE); | 822 | set_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE); |
@@ -728,13 +841,6 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
728 | clear_sta_flag(sta, WLAN_STA_MFP); | 841 | clear_sta_flag(sta, WLAN_STA_MFP); |
729 | } | 842 | } |
730 | 843 | ||
731 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { | ||
732 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) | ||
733 | set_sta_flag(sta, WLAN_STA_AUTH); | ||
734 | else | ||
735 | clear_sta_flag(sta, WLAN_STA_AUTH); | ||
736 | } | ||
737 | |||
738 | if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) { | 844 | if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) { |
739 | if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | 845 | if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) |
740 | set_sta_flag(sta, WLAN_STA_TDLS_PEER); | 846 | set_sta_flag(sta, WLAN_STA_TDLS_PEER); |
@@ -778,7 +884,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
778 | } | 884 | } |
779 | 885 | ||
780 | if (params->ht_capa) | 886 | if (params->ht_capa) |
781 | ieee80211_ht_cap_ie_to_sta_ht_cap(sband, | 887 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
782 | params->ht_capa, | 888 | params->ht_capa, |
783 | &sta->sta.ht_cap); | 889 | &sta->sta.ht_cap); |
784 | 890 | ||
@@ -806,6 +912,8 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
806 | } | 912 | } |
807 | #endif | 913 | #endif |
808 | } | 914 | } |
915 | |||
916 | return 0; | ||
809 | } | 917 | } |
810 | 918 | ||
811 | static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | 919 | static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, |
@@ -832,22 +940,25 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
832 | if (is_multicast_ether_addr(mac)) | 940 | if (is_multicast_ether_addr(mac)) |
833 | return -EINVAL; | 941 | return -EINVAL; |
834 | 942 | ||
835 | /* Only TDLS-supporting stations can add TDLS peers */ | ||
836 | if ((params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) && | ||
837 | !((wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) && | ||
838 | sdata->vif.type == NL80211_IFTYPE_STATION)) | ||
839 | return -ENOTSUPP; | ||
840 | |||
841 | sta = sta_info_alloc(sdata, mac, GFP_KERNEL); | 943 | sta = sta_info_alloc(sdata, mac, GFP_KERNEL); |
842 | if (!sta) | 944 | if (!sta) |
843 | return -ENOMEM; | 945 | return -ENOMEM; |
844 | 946 | ||
845 | set_sta_flag(sta, WLAN_STA_AUTH); | 947 | sta_info_move_state(sta, IEEE80211_STA_AUTH); |
846 | set_sta_flag(sta, WLAN_STA_ASSOC); | 948 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
847 | 949 | ||
848 | sta_apply_parameters(local, sta, params); | 950 | err = sta_apply_parameters(local, sta, params); |
951 | if (err) { | ||
952 | sta_info_free(local, sta); | ||
953 | return err; | ||
954 | } | ||
849 | 955 | ||
850 | rate_control_rate_init(sta); | 956 | /* |
957 | * for TDLS, rate control should be initialized only when supported | ||
958 | * rates are known. | ||
959 | */ | ||
960 | if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | ||
961 | rate_control_rate_init(sta); | ||
851 | 962 | ||
852 | layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | 963 | layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
853 | sdata->vif.type == NL80211_IFTYPE_AP; | 964 | sdata->vif.type == NL80211_IFTYPE_AP; |
@@ -891,19 +1002,19 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
891 | struct sta_info *sta; | 1002 | struct sta_info *sta; |
892 | struct ieee80211_sub_if_data *vlansdata; | 1003 | struct ieee80211_sub_if_data *vlansdata; |
893 | 1004 | ||
894 | rcu_read_lock(); | 1005 | mutex_lock(&local->sta_mtx); |
895 | 1006 | ||
896 | sta = sta_info_get_bss(sdata, mac); | 1007 | sta = sta_info_get_bss(sdata, mac); |
897 | if (!sta) { | 1008 | if (!sta) { |
898 | rcu_read_unlock(); | 1009 | mutex_unlock(&local->sta_mtx); |
899 | return -ENOENT; | 1010 | return -ENOENT; |
900 | } | 1011 | } |
901 | 1012 | ||
902 | /* The TDLS bit cannot be toggled after the STA was added */ | 1013 | /* in station mode, supported rates are only valid with TDLS */ |
903 | if ((params->sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) && | 1014 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
904 | !!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) != | 1015 | params->supported_rates && |
905 | !!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { | 1016 | !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { |
906 | rcu_read_unlock(); | 1017 | mutex_unlock(&local->sta_mtx); |
907 | return -EINVAL; | 1018 | return -EINVAL; |
908 | } | 1019 | } |
909 | 1020 | ||
@@ -912,13 +1023,13 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
912 | 1023 | ||
913 | if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 1024 | if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
914 | vlansdata->vif.type != NL80211_IFTYPE_AP) { | 1025 | vlansdata->vif.type != NL80211_IFTYPE_AP) { |
915 | rcu_read_unlock(); | 1026 | mutex_unlock(&local->sta_mtx); |
916 | return -EINVAL; | 1027 | return -EINVAL; |
917 | } | 1028 | } |
918 | 1029 | ||
919 | if (params->vlan->ieee80211_ptr->use_4addr) { | 1030 | if (params->vlan->ieee80211_ptr->use_4addr) { |
920 | if (vlansdata->u.vlan.sta) { | 1031 | if (vlansdata->u.vlan.sta) { |
921 | rcu_read_unlock(); | 1032 | mutex_unlock(&local->sta_mtx); |
922 | return -EBUSY; | 1033 | return -EBUSY; |
923 | } | 1034 | } |
924 | 1035 | ||
@@ -931,7 +1042,10 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
931 | 1042 | ||
932 | sta_apply_parameters(local, sta, params); | 1043 | sta_apply_parameters(local, sta, params); |
933 | 1044 | ||
934 | rcu_read_unlock(); | 1045 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && params->supported_rates) |
1046 | rate_control_rate_init(sta); | ||
1047 | |||
1048 | mutex_unlock(&local->sta_mtx); | ||
935 | 1049 | ||
936 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 1050 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
937 | params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) | 1051 | params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) |
@@ -1123,6 +1237,8 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, | |||
1123 | { | 1237 | { |
1124 | u8 *new_ie; | 1238 | u8 *new_ie; |
1125 | const u8 *old_ie; | 1239 | const u8 *old_ie; |
1240 | struct ieee80211_sub_if_data *sdata = container_of(ifmsh, | ||
1241 | struct ieee80211_sub_if_data, u.mesh); | ||
1126 | 1242 | ||
1127 | /* allocate information elements */ | 1243 | /* allocate information elements */ |
1128 | new_ie = NULL; | 1244 | new_ie = NULL; |
@@ -1149,6 +1265,10 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, | |||
1149 | if (setup->is_secure) | 1265 | if (setup->is_secure) |
1150 | ifmsh->security |= IEEE80211_MESH_SEC_SECURED; | 1266 | ifmsh->security |= IEEE80211_MESH_SEC_SECURED; |
1151 | 1267 | ||
1268 | /* mcast rate setting in Mesh Node */ | ||
1269 | memcpy(sdata->vif.bss_conf.mcast_rate, setup->mcast_rate, | ||
1270 | sizeof(setup->mcast_rate)); | ||
1271 | |||
1152 | return 0; | 1272 | return 0; |
1153 | } | 1273 | } |
1154 | 1274 | ||
@@ -1194,6 +1314,9 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, | |||
1194 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, mask)) | 1314 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, mask)) |
1195 | conf->dot11MeshHWMPpreqMinInterval = | 1315 | conf->dot11MeshHWMPpreqMinInterval = |
1196 | nconf->dot11MeshHWMPpreqMinInterval; | 1316 | nconf->dot11MeshHWMPpreqMinInterval; |
1317 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, mask)) | ||
1318 | conf->dot11MeshHWMPperrMinInterval = | ||
1319 | nconf->dot11MeshHWMPperrMinInterval; | ||
1197 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, | 1320 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, |
1198 | mask)) | 1321 | mask)) |
1199 | conf->dot11MeshHWMPnetDiameterTraversalTime = | 1322 | conf->dot11MeshHWMPnetDiameterTraversalTime = |
@@ -1394,7 +1517,7 @@ static int ieee80211_set_channel(struct wiphy *wiphy, | |||
1394 | (old_oper_type != local->_oper_channel_type)) | 1517 | (old_oper_type != local->_oper_channel_type)) |
1395 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 1518 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
1396 | 1519 | ||
1397 | if ((sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR) && | 1520 | if (sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR && |
1398 | old_vif_oper_type != sdata->vif.bss_conf.channel_type) | 1521 | old_vif_oper_type != sdata->vif.bss_conf.channel_type) |
1399 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT); | 1522 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT); |
1400 | 1523 | ||
@@ -1917,7 +2040,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1917 | enum nl80211_channel_type channel_type, | 2040 | enum nl80211_channel_type channel_type, |
1918 | bool channel_type_valid, unsigned int wait, | 2041 | bool channel_type_valid, unsigned int wait, |
1919 | const u8 *buf, size_t len, bool no_cck, | 2042 | const u8 *buf, size_t len, bool no_cck, |
1920 | u64 *cookie) | 2043 | bool dont_wait_for_ack, u64 *cookie) |
1921 | { | 2044 | { |
1922 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2045 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1923 | struct ieee80211_local *local = sdata->local; | 2046 | struct ieee80211_local *local = sdata->local; |
@@ -1925,10 +2048,15 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1925 | struct sta_info *sta; | 2048 | struct sta_info *sta; |
1926 | struct ieee80211_work *wk; | 2049 | struct ieee80211_work *wk; |
1927 | const struct ieee80211_mgmt *mgmt = (void *)buf; | 2050 | const struct ieee80211_mgmt *mgmt = (void *)buf; |
1928 | u32 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | | 2051 | u32 flags; |
1929 | IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
1930 | bool is_offchan = false; | 2052 | bool is_offchan = false; |
1931 | 2053 | ||
2054 | if (dont_wait_for_ack) | ||
2055 | flags = IEEE80211_TX_CTL_NO_ACK; | ||
2056 | else | ||
2057 | flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | | ||
2058 | IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
2059 | |||
1932 | /* Check that we are on the requested channel for transmission */ | 2060 | /* Check that we are on the requested channel for transmission */ |
1933 | if (chan != local->tmp_channel && | 2061 | if (chan != local->tmp_channel && |
1934 | chan != local->oper_channel) | 2062 | chan != local->oper_channel) |
@@ -2488,6 +2616,82 @@ static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | |||
2488 | return 0; | 2616 | return 0; |
2489 | } | 2617 | } |
2490 | 2618 | ||
2619 | static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | ||
2620 | const u8 *peer, u64 *cookie) | ||
2621 | { | ||
2622 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2623 | struct ieee80211_local *local = sdata->local; | ||
2624 | struct ieee80211_qos_hdr *nullfunc; | ||
2625 | struct sk_buff *skb; | ||
2626 | int size = sizeof(*nullfunc); | ||
2627 | __le16 fc; | ||
2628 | bool qos; | ||
2629 | struct ieee80211_tx_info *info; | ||
2630 | struct sta_info *sta; | ||
2631 | |||
2632 | rcu_read_lock(); | ||
2633 | sta = sta_info_get(sdata, peer); | ||
2634 | if (sta) { | ||
2635 | qos = test_sta_flag(sta, WLAN_STA_WME); | ||
2636 | rcu_read_unlock(); | ||
2637 | } else { | ||
2638 | rcu_read_unlock(); | ||
2639 | return -ENOLINK; | ||
2640 | } | ||
2641 | |||
2642 | if (qos) { | ||
2643 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
2644 | IEEE80211_STYPE_QOS_NULLFUNC | | ||
2645 | IEEE80211_FCTL_FROMDS); | ||
2646 | } else { | ||
2647 | size -= 2; | ||
2648 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
2649 | IEEE80211_STYPE_NULLFUNC | | ||
2650 | IEEE80211_FCTL_FROMDS); | ||
2651 | } | ||
2652 | |||
2653 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + size); | ||
2654 | if (!skb) | ||
2655 | return -ENOMEM; | ||
2656 | |||
2657 | skb->dev = dev; | ||
2658 | |||
2659 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
2660 | |||
2661 | nullfunc = (void *) skb_put(skb, size); | ||
2662 | nullfunc->frame_control = fc; | ||
2663 | nullfunc->duration_id = 0; | ||
2664 | memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); | ||
2665 | memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); | ||
2666 | memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN); | ||
2667 | nullfunc->seq_ctrl = 0; | ||
2668 | |||
2669 | info = IEEE80211_SKB_CB(skb); | ||
2670 | |||
2671 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS | | ||
2672 | IEEE80211_TX_INTFL_NL80211_FRAME_TX; | ||
2673 | |||
2674 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); | ||
2675 | skb->priority = 7; | ||
2676 | if (qos) | ||
2677 | nullfunc->qos_ctrl = cpu_to_le16(7); | ||
2678 | |||
2679 | local_bh_disable(); | ||
2680 | ieee80211_xmit(sdata, skb); | ||
2681 | local_bh_enable(); | ||
2682 | |||
2683 | *cookie = (unsigned long) skb; | ||
2684 | return 0; | ||
2685 | } | ||
2686 | |||
2687 | static struct ieee80211_channel * | ||
2688 | ieee80211_wiphy_get_channel(struct wiphy *wiphy) | ||
2689 | { | ||
2690 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
2691 | |||
2692 | return local->oper_channel; | ||
2693 | } | ||
2694 | |||
2491 | struct cfg80211_ops mac80211_config_ops = { | 2695 | struct cfg80211_ops mac80211_config_ops = { |
2492 | .add_virtual_intf = ieee80211_add_iface, | 2696 | .add_virtual_intf = ieee80211_add_iface, |
2493 | .del_virtual_intf = ieee80211_del_iface, | 2697 | .del_virtual_intf = ieee80211_del_iface, |
@@ -2553,4 +2757,7 @@ struct cfg80211_ops mac80211_config_ops = { | |||
2553 | .set_rekey_data = ieee80211_set_rekey_data, | 2757 | .set_rekey_data = ieee80211_set_rekey_data, |
2554 | .tdls_oper = ieee80211_tdls_oper, | 2758 | .tdls_oper = ieee80211_tdls_oper, |
2555 | .tdls_mgmt = ieee80211_tdls_mgmt, | 2759 | .tdls_mgmt = ieee80211_tdls_mgmt, |
2760 | .probe_client = ieee80211_probe_client, | ||
2761 | .get_channel = ieee80211_wiphy_get_channel, | ||
2762 | .set_noack_map = ieee80211_set_noack_map, | ||
2556 | }; | 2763 | }; |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 883996b2f99f..90baea53e7c5 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -97,40 +97,6 @@ static const struct file_operations reset_ops = { | |||
97 | .llseek = noop_llseek, | 97 | .llseek = noop_llseek, |
98 | }; | 98 | }; |
99 | 99 | ||
100 | static ssize_t noack_read(struct file *file, char __user *user_buf, | ||
101 | size_t count, loff_t *ppos) | ||
102 | { | ||
103 | struct ieee80211_local *local = file->private_data; | ||
104 | |||
105 | return mac80211_format_buffer(user_buf, count, ppos, "%d\n", | ||
106 | local->wifi_wme_noack_test); | ||
107 | } | ||
108 | |||
109 | static ssize_t noack_write(struct file *file, | ||
110 | const char __user *user_buf, | ||
111 | size_t count, loff_t *ppos) | ||
112 | { | ||
113 | struct ieee80211_local *local = file->private_data; | ||
114 | char buf[10]; | ||
115 | size_t len; | ||
116 | |||
117 | len = min(count, sizeof(buf) - 1); | ||
118 | if (copy_from_user(buf, user_buf, len)) | ||
119 | return -EFAULT; | ||
120 | buf[len] = '\0'; | ||
121 | |||
122 | local->wifi_wme_noack_test = !!simple_strtoul(buf, NULL, 0); | ||
123 | |||
124 | return count; | ||
125 | } | ||
126 | |||
127 | static const struct file_operations noack_ops = { | ||
128 | .read = noack_read, | ||
129 | .write = noack_write, | ||
130 | .open = mac80211_open_file_generic, | ||
131 | .llseek = default_llseek, | ||
132 | }; | ||
133 | |||
134 | static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf, | 100 | static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf, |
135 | size_t count, loff_t *ppos) | 101 | size_t count, loff_t *ppos) |
136 | { | 102 | { |
@@ -190,7 +156,7 @@ static ssize_t uapsd_max_sp_len_write(struct file *file, | |||
190 | return -EFAULT; | 156 | return -EFAULT; |
191 | buf[len] = '\0'; | 157 | buf[len] = '\0'; |
192 | 158 | ||
193 | ret = strict_strtoul(buf, 0, &val); | 159 | ret = kstrtoul(buf, 0, &val); |
194 | 160 | ||
195 | if (ret) | 161 | if (ret) |
196 | return -EINVAL; | 162 | return -EINVAL; |
@@ -398,7 +364,6 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
398 | DEBUGFS_ADD(wep_iv); | 364 | DEBUGFS_ADD(wep_iv); |
399 | DEBUGFS_ADD(queues); | 365 | DEBUGFS_ADD(queues); |
400 | DEBUGFS_ADD_MODE(reset, 0200); | 366 | DEBUGFS_ADD_MODE(reset, 0200); |
401 | DEBUGFS_ADD(noack); | ||
402 | DEBUGFS_ADD(uapsd_queues); | 367 | DEBUGFS_ADD(uapsd_queues); |
403 | DEBUGFS_ADD(uapsd_max_sp_len); | 368 | DEBUGFS_ADD(uapsd_max_sp_len); |
404 | DEBUGFS_ADD(channel_type); | 369 | DEBUGFS_ADD(channel_type); |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 9352819a986b..176c08ffb13c 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -321,6 +321,7 @@ static ssize_t ieee80211_if_parse_tkip_mic_test( | |||
321 | __IEEE80211_IF_FILE_W(tkip_mic_test); | 321 | __IEEE80211_IF_FILE_W(tkip_mic_test); |
322 | 322 | ||
323 | /* AP attributes */ | 323 | /* AP attributes */ |
324 | IEEE80211_IF_FILE(num_sta_authorized, u.ap.num_sta_authorized, ATOMIC); | ||
324 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); | 325 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); |
325 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); | 326 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); |
326 | 327 | ||
@@ -405,6 +406,8 @@ IEEE80211_IF_FILE(dot11MeshHWMPactivePathTimeout, | |||
405 | u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC); | 406 | u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC); |
406 | IEEE80211_IF_FILE(dot11MeshHWMPpreqMinInterval, | 407 | IEEE80211_IF_FILE(dot11MeshHWMPpreqMinInterval, |
407 | u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC); | 408 | u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC); |
409 | IEEE80211_IF_FILE(dot11MeshHWMPperrMinInterval, | ||
410 | u.mesh.mshcfg.dot11MeshHWMPperrMinInterval, DEC); | ||
408 | IEEE80211_IF_FILE(dot11MeshHWMPnetDiameterTraversalTime, | 411 | IEEE80211_IF_FILE(dot11MeshHWMPnetDiameterTraversalTime, |
409 | u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC); | 412 | u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC); |
410 | IEEE80211_IF_FILE(dot11MeshHWMPmaxPREQretries, | 413 | IEEE80211_IF_FILE(dot11MeshHWMPmaxPREQretries, |
@@ -456,6 +459,7 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) | |||
456 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 459 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
457 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 460 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
458 | 461 | ||
462 | DEBUGFS_ADD(num_sta_authorized); | ||
459 | DEBUGFS_ADD(num_sta_ps); | 463 | DEBUGFS_ADD(num_sta_ps); |
460 | DEBUGFS_ADD(dtim_count); | 464 | DEBUGFS_ADD(dtim_count); |
461 | DEBUGFS_ADD(num_buffered_multicast); | 465 | DEBUGFS_ADD(num_buffered_multicast); |
@@ -534,6 +538,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) | |||
534 | MESHPARAMS_ADD(dot11MeshMaxPeerLinks); | 538 | MESHPARAMS_ADD(dot11MeshMaxPeerLinks); |
535 | MESHPARAMS_ADD(dot11MeshHWMPactivePathTimeout); | 539 | MESHPARAMS_ADD(dot11MeshHWMPactivePathTimeout); |
536 | MESHPARAMS_ADD(dot11MeshHWMPpreqMinInterval); | 540 | MESHPARAMS_ADD(dot11MeshHWMPpreqMinInterval); |
541 | MESHPARAMS_ADD(dot11MeshHWMPperrMinInterval); | ||
537 | MESHPARAMS_ADD(dot11MeshHWMPnetDiameterTraversalTime); | 542 | MESHPARAMS_ADD(dot11MeshHWMPnetDiameterTraversalTime); |
538 | MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries); | 543 | MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries); |
539 | MESHPARAMS_ADD(path_refresh_time); | 544 | MESHPARAMS_ADD(path_refresh_time); |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 3110cbdc501b..2406b3e7393f 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -63,10 +63,10 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | |||
63 | test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" | 63 | test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" |
64 | 64 | ||
65 | int res = scnprintf(buf, sizeof(buf), | 65 | int res = scnprintf(buf, sizeof(buf), |
66 | "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", | 66 | "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", |
67 | TEST(AUTH), TEST(ASSOC), TEST(PS_STA), | 67 | TEST(AUTH), TEST(ASSOC), TEST(PS_STA), |
68 | TEST(PS_DRIVER), TEST(AUTHORIZED), | 68 | TEST(PS_DRIVER), TEST(AUTHORIZED), |
69 | TEST(SHORT_PREAMBLE), TEST(ASSOC_AP), | 69 | TEST(SHORT_PREAMBLE), |
70 | TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT), | 70 | TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT), |
71 | TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), | 71 | TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), |
72 | TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), | 72 | TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 5f165d7eb2db..e8960ae39861 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -5,11 +5,34 @@ | |||
5 | #include "ieee80211_i.h" | 5 | #include "ieee80211_i.h" |
6 | #include "driver-trace.h" | 6 | #include "driver-trace.h" |
7 | 7 | ||
8 | static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) | ||
9 | { | ||
10 | WARN_ON(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER)); | ||
11 | } | ||
12 | |||
13 | static inline struct ieee80211_sub_if_data * | ||
14 | get_bss_sdata(struct ieee80211_sub_if_data *sdata) | ||
15 | { | ||
16 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
17 | sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, | ||
18 | u.ap); | ||
19 | |||
20 | return sdata; | ||
21 | } | ||
22 | |||
8 | static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb) | 23 | static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb) |
9 | { | 24 | { |
10 | local->ops->tx(&local->hw, skb); | 25 | local->ops->tx(&local->hw, skb); |
11 | } | 26 | } |
12 | 27 | ||
28 | static inline void drv_tx_frags(struct ieee80211_local *local, | ||
29 | struct ieee80211_vif *vif, | ||
30 | struct ieee80211_sta *sta, | ||
31 | struct sk_buff_head *skbs) | ||
32 | { | ||
33 | local->ops->tx_frags(&local->hw, vif, sta, skbs); | ||
34 | } | ||
35 | |||
13 | static inline int drv_start(struct ieee80211_local *local) | 36 | static inline int drv_start(struct ieee80211_local *local) |
14 | { | 37 | { |
15 | int ret; | 38 | int ret; |
@@ -69,15 +92,23 @@ static inline int drv_resume(struct ieee80211_local *local) | |||
69 | #endif | 92 | #endif |
70 | 93 | ||
71 | static inline int drv_add_interface(struct ieee80211_local *local, | 94 | static inline int drv_add_interface(struct ieee80211_local *local, |
72 | struct ieee80211_vif *vif) | 95 | struct ieee80211_sub_if_data *sdata) |
73 | { | 96 | { |
74 | int ret; | 97 | int ret; |
75 | 98 | ||
76 | might_sleep(); | 99 | might_sleep(); |
77 | 100 | ||
78 | trace_drv_add_interface(local, vif_to_sdata(vif)); | 101 | if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
79 | ret = local->ops->add_interface(&local->hw, vif); | 102 | sdata->vif.type == NL80211_IFTYPE_MONITOR)) |
103 | return -EINVAL; | ||
104 | |||
105 | trace_drv_add_interface(local, sdata); | ||
106 | ret = local->ops->add_interface(&local->hw, &sdata->vif); | ||
80 | trace_drv_return_int(local, ret); | 107 | trace_drv_return_int(local, ret); |
108 | |||
109 | if (ret == 0) | ||
110 | sdata->flags |= IEEE80211_SDATA_IN_DRIVER; | ||
111 | |||
81 | return ret; | 112 | return ret; |
82 | } | 113 | } |
83 | 114 | ||
@@ -89,6 +120,8 @@ static inline int drv_change_interface(struct ieee80211_local *local, | |||
89 | 120 | ||
90 | might_sleep(); | 121 | might_sleep(); |
91 | 122 | ||
123 | check_sdata_in_driver(sdata); | ||
124 | |||
92 | trace_drv_change_interface(local, sdata, type, p2p); | 125 | trace_drv_change_interface(local, sdata, type, p2p); |
93 | ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p); | 126 | ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p); |
94 | trace_drv_return_int(local, ret); | 127 | trace_drv_return_int(local, ret); |
@@ -96,12 +129,15 @@ static inline int drv_change_interface(struct ieee80211_local *local, | |||
96 | } | 129 | } |
97 | 130 | ||
98 | static inline void drv_remove_interface(struct ieee80211_local *local, | 131 | static inline void drv_remove_interface(struct ieee80211_local *local, |
99 | struct ieee80211_vif *vif) | 132 | struct ieee80211_sub_if_data *sdata) |
100 | { | 133 | { |
101 | might_sleep(); | 134 | might_sleep(); |
102 | 135 | ||
103 | trace_drv_remove_interface(local, vif_to_sdata(vif)); | 136 | check_sdata_in_driver(sdata); |
104 | local->ops->remove_interface(&local->hw, vif); | 137 | |
138 | trace_drv_remove_interface(local, sdata); | ||
139 | local->ops->remove_interface(&local->hw, &sdata->vif); | ||
140 | sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER; | ||
105 | trace_drv_return_void(local); | 141 | trace_drv_return_void(local); |
106 | } | 142 | } |
107 | 143 | ||
@@ -124,6 +160,8 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local, | |||
124 | { | 160 | { |
125 | might_sleep(); | 161 | might_sleep(); |
126 | 162 | ||
163 | check_sdata_in_driver(sdata); | ||
164 | |||
127 | trace_drv_bss_info_changed(local, sdata, info, changed); | 165 | trace_drv_bss_info_changed(local, sdata, info, changed); |
128 | if (local->ops->bss_info_changed) | 166 | if (local->ops->bss_info_changed) |
129 | local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed); | 167 | local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed); |
@@ -139,6 +177,8 @@ static inline int drv_tx_sync(struct ieee80211_local *local, | |||
139 | 177 | ||
140 | might_sleep(); | 178 | might_sleep(); |
141 | 179 | ||
180 | check_sdata_in_driver(sdata); | ||
181 | |||
142 | trace_drv_tx_sync(local, sdata, bssid, type); | 182 | trace_drv_tx_sync(local, sdata, bssid, type); |
143 | if (local->ops->tx_sync) | 183 | if (local->ops->tx_sync) |
144 | ret = local->ops->tx_sync(&local->hw, &sdata->vif, | 184 | ret = local->ops->tx_sync(&local->hw, &sdata->vif, |
@@ -154,6 +194,8 @@ static inline void drv_finish_tx_sync(struct ieee80211_local *local, | |||
154 | { | 194 | { |
155 | might_sleep(); | 195 | might_sleep(); |
156 | 196 | ||
197 | check_sdata_in_driver(sdata); | ||
198 | |||
157 | trace_drv_finish_tx_sync(local, sdata, bssid, type); | 199 | trace_drv_finish_tx_sync(local, sdata, bssid, type); |
158 | if (local->ops->finish_tx_sync) | 200 | if (local->ops->finish_tx_sync) |
159 | local->ops->finish_tx_sync(&local->hw, &sdata->vif, | 201 | local->ops->finish_tx_sync(&local->hw, &sdata->vif, |
@@ -211,6 +253,8 @@ static inline int drv_set_key(struct ieee80211_local *local, | |||
211 | 253 | ||
212 | might_sleep(); | 254 | might_sleep(); |
213 | 255 | ||
256 | check_sdata_in_driver(sdata); | ||
257 | |||
214 | trace_drv_set_key(local, cmd, sdata, sta, key); | 258 | trace_drv_set_key(local, cmd, sdata, sta, key); |
215 | ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); | 259 | ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); |
216 | trace_drv_return_int(local, ret); | 260 | trace_drv_return_int(local, ret); |
@@ -228,6 +272,8 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, | |||
228 | if (sta) | 272 | if (sta) |
229 | ista = &sta->sta; | 273 | ista = &sta->sta; |
230 | 274 | ||
275 | check_sdata_in_driver(sdata); | ||
276 | |||
231 | trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); | 277 | trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); |
232 | if (local->ops->update_tkip_key) | 278 | if (local->ops->update_tkip_key) |
233 | local->ops->update_tkip_key(&local->hw, &sdata->vif, conf, | 279 | local->ops->update_tkip_key(&local->hw, &sdata->vif, conf, |
@@ -243,6 +289,8 @@ static inline int drv_hw_scan(struct ieee80211_local *local, | |||
243 | 289 | ||
244 | might_sleep(); | 290 | might_sleep(); |
245 | 291 | ||
292 | check_sdata_in_driver(sdata); | ||
293 | |||
246 | trace_drv_hw_scan(local, sdata); | 294 | trace_drv_hw_scan(local, sdata); |
247 | ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); | 295 | ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); |
248 | trace_drv_return_int(local, ret); | 296 | trace_drv_return_int(local, ret); |
@@ -254,6 +302,8 @@ static inline void drv_cancel_hw_scan(struct ieee80211_local *local, | |||
254 | { | 302 | { |
255 | might_sleep(); | 303 | might_sleep(); |
256 | 304 | ||
305 | check_sdata_in_driver(sdata); | ||
306 | |||
257 | trace_drv_cancel_hw_scan(local, sdata); | 307 | trace_drv_cancel_hw_scan(local, sdata); |
258 | local->ops->cancel_hw_scan(&local->hw, &sdata->vif); | 308 | local->ops->cancel_hw_scan(&local->hw, &sdata->vif); |
259 | trace_drv_return_void(local); | 309 | trace_drv_return_void(local); |
@@ -269,6 +319,8 @@ drv_sched_scan_start(struct ieee80211_local *local, | |||
269 | 319 | ||
270 | might_sleep(); | 320 | might_sleep(); |
271 | 321 | ||
322 | check_sdata_in_driver(sdata); | ||
323 | |||
272 | trace_drv_sched_scan_start(local, sdata); | 324 | trace_drv_sched_scan_start(local, sdata); |
273 | ret = local->ops->sched_scan_start(&local->hw, &sdata->vif, | 325 | ret = local->ops->sched_scan_start(&local->hw, &sdata->vif, |
274 | req, ies); | 326 | req, ies); |
@@ -281,6 +333,8 @@ static inline void drv_sched_scan_stop(struct ieee80211_local *local, | |||
281 | { | 333 | { |
282 | might_sleep(); | 334 | might_sleep(); |
283 | 335 | ||
336 | check_sdata_in_driver(sdata); | ||
337 | |||
284 | trace_drv_sched_scan_stop(local, sdata); | 338 | trace_drv_sched_scan_stop(local, sdata); |
285 | local->ops->sched_scan_stop(&local->hw, &sdata->vif); | 339 | local->ops->sched_scan_stop(&local->hw, &sdata->vif); |
286 | trace_drv_return_void(local); | 340 | trace_drv_return_void(local); |
@@ -377,6 +431,9 @@ static inline void drv_sta_notify(struct ieee80211_local *local, | |||
377 | enum sta_notify_cmd cmd, | 431 | enum sta_notify_cmd cmd, |
378 | struct ieee80211_sta *sta) | 432 | struct ieee80211_sta *sta) |
379 | { | 433 | { |
434 | sdata = get_bss_sdata(sdata); | ||
435 | check_sdata_in_driver(sdata); | ||
436 | |||
380 | trace_drv_sta_notify(local, sdata, cmd, sta); | 437 | trace_drv_sta_notify(local, sdata, cmd, sta); |
381 | if (local->ops->sta_notify) | 438 | if (local->ops->sta_notify) |
382 | local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta); | 439 | local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta); |
@@ -391,6 +448,9 @@ static inline int drv_sta_add(struct ieee80211_local *local, | |||
391 | 448 | ||
392 | might_sleep(); | 449 | might_sleep(); |
393 | 450 | ||
451 | sdata = get_bss_sdata(sdata); | ||
452 | check_sdata_in_driver(sdata); | ||
453 | |||
394 | trace_drv_sta_add(local, sdata, sta); | 454 | trace_drv_sta_add(local, sdata, sta); |
395 | if (local->ops->sta_add) | 455 | if (local->ops->sta_add) |
396 | ret = local->ops->sta_add(&local->hw, &sdata->vif, sta); | 456 | ret = local->ops->sta_add(&local->hw, &sdata->vif, sta); |
@@ -406,6 +466,9 @@ static inline void drv_sta_remove(struct ieee80211_local *local, | |||
406 | { | 466 | { |
407 | might_sleep(); | 467 | might_sleep(); |
408 | 468 | ||
469 | sdata = get_bss_sdata(sdata); | ||
470 | check_sdata_in_driver(sdata); | ||
471 | |||
409 | trace_drv_sta_remove(local, sdata, sta); | 472 | trace_drv_sta_remove(local, sdata, sta); |
410 | if (local->ops->sta_remove) | 473 | if (local->ops->sta_remove) |
411 | local->ops->sta_remove(&local->hw, &sdata->vif, sta); | 474 | local->ops->sta_remove(&local->hw, &sdata->vif, sta); |
@@ -421,6 +484,8 @@ static inline int drv_conf_tx(struct ieee80211_local *local, | |||
421 | 484 | ||
422 | might_sleep(); | 485 | might_sleep(); |
423 | 486 | ||
487 | check_sdata_in_driver(sdata); | ||
488 | |||
424 | trace_drv_conf_tx(local, sdata, queue, params); | 489 | trace_drv_conf_tx(local, sdata, queue, params); |
425 | if (local->ops->conf_tx) | 490 | if (local->ops->conf_tx) |
426 | ret = local->ops->conf_tx(&local->hw, &sdata->vif, | 491 | ret = local->ops->conf_tx(&local->hw, &sdata->vif, |
@@ -436,6 +501,8 @@ static inline u64 drv_get_tsf(struct ieee80211_local *local, | |||
436 | 501 | ||
437 | might_sleep(); | 502 | might_sleep(); |
438 | 503 | ||
504 | check_sdata_in_driver(sdata); | ||
505 | |||
439 | trace_drv_get_tsf(local, sdata); | 506 | trace_drv_get_tsf(local, sdata); |
440 | if (local->ops->get_tsf) | 507 | if (local->ops->get_tsf) |
441 | ret = local->ops->get_tsf(&local->hw, &sdata->vif); | 508 | ret = local->ops->get_tsf(&local->hw, &sdata->vif); |
@@ -449,6 +516,8 @@ static inline void drv_set_tsf(struct ieee80211_local *local, | |||
449 | { | 516 | { |
450 | might_sleep(); | 517 | might_sleep(); |
451 | 518 | ||
519 | check_sdata_in_driver(sdata); | ||
520 | |||
452 | trace_drv_set_tsf(local, sdata, tsf); | 521 | trace_drv_set_tsf(local, sdata, tsf); |
453 | if (local->ops->set_tsf) | 522 | if (local->ops->set_tsf) |
454 | local->ops->set_tsf(&local->hw, &sdata->vif, tsf); | 523 | local->ops->set_tsf(&local->hw, &sdata->vif, tsf); |
@@ -460,6 +529,8 @@ static inline void drv_reset_tsf(struct ieee80211_local *local, | |||
460 | { | 529 | { |
461 | might_sleep(); | 530 | might_sleep(); |
462 | 531 | ||
532 | check_sdata_in_driver(sdata); | ||
533 | |||
463 | trace_drv_reset_tsf(local, sdata); | 534 | trace_drv_reset_tsf(local, sdata); |
464 | if (local->ops->reset_tsf) | 535 | if (local->ops->reset_tsf) |
465 | local->ops->reset_tsf(&local->hw, &sdata->vif); | 536 | local->ops->reset_tsf(&local->hw, &sdata->vif); |
@@ -489,6 +560,9 @@ static inline int drv_ampdu_action(struct ieee80211_local *local, | |||
489 | 560 | ||
490 | might_sleep(); | 561 | might_sleep(); |
491 | 562 | ||
563 | sdata = get_bss_sdata(sdata); | ||
564 | check_sdata_in_driver(sdata); | ||
565 | |||
492 | trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size); | 566 | trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size); |
493 | 567 | ||
494 | if (local->ops->ampdu_action) | 568 | if (local->ops->ampdu_action) |
@@ -644,6 +718,8 @@ static inline int drv_set_bitrate_mask(struct ieee80211_local *local, | |||
644 | 718 | ||
645 | might_sleep(); | 719 | might_sleep(); |
646 | 720 | ||
721 | check_sdata_in_driver(sdata); | ||
722 | |||
647 | trace_drv_set_bitrate_mask(local, sdata, mask); | 723 | trace_drv_set_bitrate_mask(local, sdata, mask); |
648 | if (local->ops->set_bitrate_mask) | 724 | if (local->ops->set_bitrate_mask) |
649 | ret = local->ops->set_bitrate_mask(&local->hw, | 725 | ret = local->ops->set_bitrate_mask(&local->hw, |
@@ -657,6 +733,8 @@ static inline void drv_set_rekey_data(struct ieee80211_local *local, | |||
657 | struct ieee80211_sub_if_data *sdata, | 733 | struct ieee80211_sub_if_data *sdata, |
658 | struct cfg80211_gtk_rekey_data *data) | 734 | struct cfg80211_gtk_rekey_data *data) |
659 | { | 735 | { |
736 | check_sdata_in_driver(sdata); | ||
737 | |||
660 | trace_drv_set_rekey_data(local, sdata, data); | 738 | trace_drv_set_rekey_data(local, sdata, data); |
661 | if (local->ops->set_rekey_data) | 739 | if (local->ops->set_rekey_data) |
662 | local->ops->set_rekey_data(&local->hw, &sdata->vif, data); | 740 | local->ops->set_rekey_data(&local->hw, &sdata->vif, data); |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 2af4fca55337..6e9df8fd8fb8 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -5,17 +5,6 @@ | |||
5 | #include <net/mac80211.h> | 5 | #include <net/mac80211.h> |
6 | #include "ieee80211_i.h" | 6 | #include "ieee80211_i.h" |
7 | 7 | ||
8 | #if !defined(CONFIG_MAC80211_DRIVER_API_TRACER) || defined(__CHECKER__) | ||
9 | #undef TRACE_EVENT | ||
10 | #define TRACE_EVENT(name, proto, ...) \ | ||
11 | static inline void trace_ ## name(proto) {} | ||
12 | #undef DECLARE_EVENT_CLASS | ||
13 | #define DECLARE_EVENT_CLASS(...) | ||
14 | #undef DEFINE_EVENT | ||
15 | #define DEFINE_EVENT(evt_class, name, proto, ...) \ | ||
16 | static inline void trace_ ## name(proto) {} | ||
17 | #endif | ||
18 | |||
19 | #undef TRACE_SYSTEM | 8 | #undef TRACE_SYSTEM |
20 | #define TRACE_SYSTEM mac80211 | 9 | #define TRACE_SYSTEM mac80211 |
21 | 10 | ||
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index f0fb737efa86..f25fff7607d8 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -19,7 +19,84 @@ | |||
19 | #include "ieee80211_i.h" | 19 | #include "ieee80211_i.h" |
20 | #include "rate.h" | 20 | #include "rate.h" |
21 | 21 | ||
22 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, | 22 | bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata) |
23 | { | ||
24 | const __le16 flg = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40); | ||
25 | if ((sdata->u.mgd.ht_capa_mask.cap_info & flg) && | ||
26 | !(sdata->u.mgd.ht_capa.cap_info & flg)) | ||
27 | return true; | ||
28 | return false; | ||
29 | } | ||
30 | |||
31 | static void __check_htcap_disable(struct ieee80211_sub_if_data *sdata, | ||
32 | struct ieee80211_sta_ht_cap *ht_cap, | ||
33 | u16 flag) | ||
34 | { | ||
35 | __le16 le_flag = cpu_to_le16(flag); | ||
36 | if (sdata->u.mgd.ht_capa_mask.cap_info & le_flag) { | ||
37 | if (!(sdata->u.mgd.ht_capa.cap_info & le_flag)) | ||
38 | ht_cap->cap &= ~flag; | ||
39 | } | ||
40 | } | ||
41 | |||
42 | void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, | ||
43 | struct ieee80211_sta_ht_cap *ht_cap) | ||
44 | { | ||
45 | u8 *scaps = (u8 *)(&sdata->u.mgd.ht_capa.mcs.rx_mask); | ||
46 | u8 *smask = (u8 *)(&sdata->u.mgd.ht_capa_mask.mcs.rx_mask); | ||
47 | int i; | ||
48 | |||
49 | if (sdata->vif.type != NL80211_IFTYPE_STATION) { | ||
50 | /* AP interfaces call this code when adding new stations, | ||
51 | * so just silently ignore non station interfaces. | ||
52 | */ | ||
53 | return; | ||
54 | } | ||
55 | |||
56 | /* NOTE: If you add more over-rides here, update register_hw | ||
57 | * ht_capa_mod_msk logic in main.c as well. | ||
58 | * And, if this method can ever change ht_cap.ht_supported, fix | ||
59 | * the check in ieee80211_add_ht_ie. | ||
60 | */ | ||
61 | |||
62 | /* check for HT over-rides, MCS rates first. */ | ||
63 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { | ||
64 | u8 m = smask[i]; | ||
65 | ht_cap->mcs.rx_mask[i] &= ~m; /* turn off all masked bits */ | ||
66 | /* Add back rates that are supported */ | ||
67 | ht_cap->mcs.rx_mask[i] |= (m & scaps[i]); | ||
68 | } | ||
69 | |||
70 | /* Force removal of HT-40 capabilities? */ | ||
71 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SUP_WIDTH_20_40); | ||
72 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SGI_40); | ||
73 | |||
74 | /* Allow user to disable the max-AMSDU bit. */ | ||
75 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_MAX_AMSDU); | ||
76 | |||
77 | /* Allow user to decrease AMPDU factor */ | ||
78 | if (sdata->u.mgd.ht_capa_mask.ampdu_params_info & | ||
79 | IEEE80211_HT_AMPDU_PARM_FACTOR) { | ||
80 | u8 n = sdata->u.mgd.ht_capa.ampdu_params_info | ||
81 | & IEEE80211_HT_AMPDU_PARM_FACTOR; | ||
82 | if (n < ht_cap->ampdu_factor) | ||
83 | ht_cap->ampdu_factor = n; | ||
84 | } | ||
85 | |||
86 | /* Allow the user to increase AMPDU density. */ | ||
87 | if (sdata->u.mgd.ht_capa_mask.ampdu_params_info & | ||
88 | IEEE80211_HT_AMPDU_PARM_DENSITY) { | ||
89 | u8 n = (sdata->u.mgd.ht_capa.ampdu_params_info & | ||
90 | IEEE80211_HT_AMPDU_PARM_DENSITY) | ||
91 | >> IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT; | ||
92 | if (n > ht_cap->ampdu_density) | ||
93 | ht_cap->ampdu_density = n; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | |||
98 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | ||
99 | struct ieee80211_supported_band *sband, | ||
23 | struct ieee80211_ht_cap *ht_cap_ie, | 100 | struct ieee80211_ht_cap *ht_cap_ie, |
24 | struct ieee80211_sta_ht_cap *ht_cap) | 101 | struct ieee80211_sta_ht_cap *ht_cap) |
25 | { | 102 | { |
@@ -103,6 +180,12 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, | |||
103 | /* handle MCS rate 32 too */ | 180 | /* handle MCS rate 32 too */ |
104 | if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1) | 181 | if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1) |
105 | ht_cap->mcs.rx_mask[32/8] |= 1; | 182 | ht_cap->mcs.rx_mask[32/8] |= 1; |
183 | |||
184 | /* | ||
185 | * If user has specified capability over-rides, take care | ||
186 | * of that here. | ||
187 | */ | ||
188 | ieee80211_apply_htcap_overrides(sdata, ht_cap); | ||
106 | } | 189 | } |
107 | 190 | ||
108 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx) | 191 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx) |
@@ -196,10 +279,13 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
196 | memcpy(mgmt->da, da, ETH_ALEN); | 279 | memcpy(mgmt->da, da, ETH_ALEN); |
197 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 280 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
198 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 281 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
199 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 282 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
283 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | ||
200 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); | 284 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
201 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | 285 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
202 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); | 286 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
287 | else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
288 | memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN); | ||
203 | 289 | ||
204 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 290 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
205 | IEEE80211_STYPE_ACTION); | 291 | IEEE80211_STYPE_ACTION); |
@@ -214,7 +300,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
214 | mgmt->u.action.u.delba.params = cpu_to_le16(params); | 300 | mgmt->u.action.u.delba.params = cpu_to_le16(params); |
215 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); | 301 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); |
216 | 302 | ||
217 | ieee80211_tx_skb(sdata, skb); | 303 | ieee80211_tx_skb_tid(sdata, skb, tid); |
218 | } | 304 | } |
219 | 305 | ||
220 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | 306 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index ede9a8b341ac..f8a32bf98216 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -77,6 +77,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
77 | struct cfg80211_bss *bss; | 77 | struct cfg80211_bss *bss; |
78 | u32 bss_change; | 78 | u32 bss_change; |
79 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | 79 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; |
80 | enum nl80211_channel_type channel_type; | ||
80 | 81 | ||
81 | lockdep_assert_held(&ifibss->mtx); | 82 | lockdep_assert_held(&ifibss->mtx); |
82 | 83 | ||
@@ -97,6 +98,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
97 | /* if merging, indicate to driver that we leave the old IBSS */ | 98 | /* if merging, indicate to driver that we leave the old IBSS */ |
98 | if (sdata->vif.bss_conf.ibss_joined) { | 99 | if (sdata->vif.bss_conf.ibss_joined) { |
99 | sdata->vif.bss_conf.ibss_joined = false; | 100 | sdata->vif.bss_conf.ibss_joined = false; |
101 | netif_carrier_off(sdata->dev); | ||
100 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS); | 102 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS); |
101 | } | 103 | } |
102 | 104 | ||
@@ -104,8 +106,16 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
104 | 106 | ||
105 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; | 107 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; |
106 | 108 | ||
107 | local->oper_channel = chan; | 109 | channel_type = ifibss->channel_type; |
108 | WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT)); | 110 | if (channel_type > NL80211_CHAN_HT20 && |
111 | !cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) | ||
112 | channel_type = NL80211_CHAN_HT20; | ||
113 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { | ||
114 | /* can only fail due to HT40+/- mismatch */ | ||
115 | channel_type = NL80211_CHAN_HT20; | ||
116 | WARN_ON(!ieee80211_set_channel_type(local, sdata, | ||
117 | NL80211_CHAN_HT20)); | ||
118 | } | ||
109 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 119 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
110 | 120 | ||
111 | sband = local->hw.wiphy->bands[chan->band]; | 121 | sband = local->hw.wiphy->bands[chan->band]; |
@@ -171,6 +181,19 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
171 | memcpy(skb_put(skb, ifibss->ie_len), | 181 | memcpy(skb_put(skb, ifibss->ie_len), |
172 | ifibss->ie, ifibss->ie_len); | 182 | ifibss->ie, ifibss->ie_len); |
173 | 183 | ||
184 | /* add HT capability and information IEs */ | ||
185 | if (channel_type && sband->ht_cap.ht_supported) { | ||
186 | pos = skb_put(skb, 4 + | ||
187 | sizeof(struct ieee80211_ht_cap) + | ||
188 | sizeof(struct ieee80211_ht_info)); | ||
189 | pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, | ||
190 | sband->ht_cap.cap); | ||
191 | pos = ieee80211_ie_build_ht_info(pos, | ||
192 | &sband->ht_cap, | ||
193 | chan, | ||
194 | channel_type); | ||
195 | } | ||
196 | |||
174 | if (local->hw.queues >= 4) { | 197 | if (local->hw.queues >= 4) { |
175 | pos = skb_put(skb, 9); | 198 | pos = skb_put(skb, 9); |
176 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; | 199 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; |
@@ -194,6 +217,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
194 | bss_change |= BSS_CHANGED_BEACON; | 217 | bss_change |= BSS_CHANGED_BEACON; |
195 | bss_change |= BSS_CHANGED_BEACON_ENABLED; | 218 | bss_change |= BSS_CHANGED_BEACON_ENABLED; |
196 | bss_change |= BSS_CHANGED_BASIC_RATES; | 219 | bss_change |= BSS_CHANGED_BASIC_RATES; |
220 | bss_change |= BSS_CHANGED_HT; | ||
197 | bss_change |= BSS_CHANGED_IBSS; | 221 | bss_change |= BSS_CHANGED_IBSS; |
198 | sdata->vif.bss_conf.ibss_joined = true; | 222 | sdata->vif.bss_conf.ibss_joined = true; |
199 | ieee80211_bss_info_change_notify(sdata, bss_change); | 223 | ieee80211_bss_info_change_notify(sdata, bss_change); |
@@ -207,6 +231,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
207 | bss = cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel, | 231 | bss = cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel, |
208 | mgmt, skb->len, 0, GFP_KERNEL); | 232 | mgmt, skb->len, 0, GFP_KERNEL); |
209 | cfg80211_put_bss(bss); | 233 | cfg80211_put_bss(bss); |
234 | netif_carrier_on(sdata->dev); | ||
210 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); | 235 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); |
211 | } | 236 | } |
212 | 237 | ||
@@ -250,6 +275,80 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
250 | cbss->tsf); | 275 | cbss->tsf); |
251 | } | 276 | } |
252 | 277 | ||
278 | static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta) | ||
279 | __acquires(RCU) | ||
280 | { | ||
281 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
282 | u8 addr[ETH_ALEN]; | ||
283 | |||
284 | memcpy(addr, sta->sta.addr, ETH_ALEN); | ||
285 | |||
286 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
287 | wiphy_debug(sdata->local->hw.wiphy, | ||
288 | "Adding new IBSS station %pM (dev=%s)\n", | ||
289 | addr, sdata->name); | ||
290 | #endif | ||
291 | |||
292 | sta_info_move_state(sta, IEEE80211_STA_AUTH); | ||
293 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); | ||
294 | sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
295 | |||
296 | rate_control_rate_init(sta); | ||
297 | |||
298 | /* If it fails, maybe we raced another insertion? */ | ||
299 | if (sta_info_insert_rcu(sta)) | ||
300 | return sta_info_get(sdata, addr); | ||
301 | return sta; | ||
302 | } | ||
303 | |||
304 | static struct sta_info * | ||
305 | ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | ||
306 | const u8 *bssid, const u8 *addr, | ||
307 | u32 supp_rates) | ||
308 | __acquires(RCU) | ||
309 | { | ||
310 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
311 | struct ieee80211_local *local = sdata->local; | ||
312 | struct sta_info *sta; | ||
313 | int band = local->hw.conf.channel->band; | ||
314 | |||
315 | /* | ||
316 | * XXX: Consider removing the least recently used entry and | ||
317 | * allow new one to be added. | ||
318 | */ | ||
319 | if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { | ||
320 | if (net_ratelimit()) | ||
321 | printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n", | ||
322 | sdata->name, addr); | ||
323 | rcu_read_lock(); | ||
324 | return NULL; | ||
325 | } | ||
326 | |||
327 | if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH) { | ||
328 | rcu_read_lock(); | ||
329 | return NULL; | ||
330 | } | ||
331 | |||
332 | if (compare_ether_addr(bssid, sdata->u.ibss.bssid)) { | ||
333 | rcu_read_lock(); | ||
334 | return NULL; | ||
335 | } | ||
336 | |||
337 | sta = sta_info_alloc(sdata, addr, GFP_KERNEL); | ||
338 | if (!sta) { | ||
339 | rcu_read_lock(); | ||
340 | return NULL; | ||
341 | } | ||
342 | |||
343 | sta->last_rx = jiffies; | ||
344 | |||
345 | /* make sure mandatory rates are always added */ | ||
346 | sta->sta.supp_rates[band] = supp_rates | | ||
347 | ieee80211_mandatory_rates(local, band); | ||
348 | |||
349 | return ieee80211_ibss_finish_sta(sta); | ||
350 | } | ||
351 | |||
253 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | 352 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, |
254 | struct ieee80211_mgmt *mgmt, | 353 | struct ieee80211_mgmt *mgmt, |
255 | size_t len, | 354 | size_t len, |
@@ -266,6 +365,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
266 | u64 beacon_timestamp, rx_timestamp; | 365 | u64 beacon_timestamp, rx_timestamp; |
267 | u32 supp_rates = 0; | 366 | u32 supp_rates = 0; |
268 | enum ieee80211_band band = rx_status->band; | 367 | enum ieee80211_band band = rx_status->band; |
368 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; | ||
369 | bool rates_updated = false; | ||
269 | 370 | ||
270 | if (elems->ds_params && elems->ds_params_len == 1) | 371 | if (elems->ds_params && elems->ds_params_len == 1) |
271 | freq = ieee80211_channel_to_frequency(elems->ds_params[0], | 372 | freq = ieee80211_channel_to_frequency(elems->ds_params[0], |
@@ -305,17 +406,51 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
305 | prev_rates, | 406 | prev_rates, |
306 | sta->sta.supp_rates[band]); | 407 | sta->sta.supp_rates[band]); |
307 | #endif | 408 | #endif |
308 | rate_control_rate_init(sta); | 409 | rates_updated = true; |
309 | } | 410 | } |
310 | } else | 411 | } else { |
412 | rcu_read_unlock(); | ||
311 | sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, | 413 | sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, |
312 | mgmt->sa, supp_rates, | 414 | mgmt->sa, supp_rates); |
313 | GFP_ATOMIC); | 415 | } |
314 | } | 416 | } |
315 | 417 | ||
316 | if (sta && elems->wmm_info) | 418 | if (sta && elems->wmm_info) |
317 | set_sta_flag(sta, WLAN_STA_WME); | 419 | set_sta_flag(sta, WLAN_STA_WME); |
318 | 420 | ||
421 | if (sta && elems->ht_info_elem && elems->ht_cap_elem && | ||
422 | sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) { | ||
423 | /* we both use HT */ | ||
424 | struct ieee80211_sta_ht_cap sta_ht_cap_new; | ||
425 | enum nl80211_channel_type channel_type = | ||
426 | ieee80211_ht_info_to_channel_type( | ||
427 | elems->ht_info_elem); | ||
428 | |||
429 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | ||
430 | elems->ht_cap_elem, | ||
431 | &sta_ht_cap_new); | ||
432 | |||
433 | /* | ||
434 | * fall back to HT20 if we don't use or use | ||
435 | * the other extension channel | ||
436 | */ | ||
437 | if ((channel_type == NL80211_CHAN_HT40MINUS || | ||
438 | channel_type == NL80211_CHAN_HT40PLUS) && | ||
439 | channel_type != sdata->u.ibss.channel_type) | ||
440 | sta_ht_cap_new.cap &= | ||
441 | ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
442 | |||
443 | if (memcmp(&sta->sta.ht_cap, &sta_ht_cap_new, | ||
444 | sizeof(sta_ht_cap_new))) { | ||
445 | memcpy(&sta->sta.ht_cap, &sta_ht_cap_new, | ||
446 | sizeof(sta_ht_cap_new)); | ||
447 | rates_updated = true; | ||
448 | } | ||
449 | } | ||
450 | |||
451 | if (sta && rates_updated) | ||
452 | rate_control_rate_init(sta); | ||
453 | |||
319 | rcu_read_unlock(); | 454 | rcu_read_unlock(); |
320 | } | 455 | } |
321 | 456 | ||
@@ -404,21 +539,17 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
404 | ieee80211_sta_join_ibss(sdata, bss); | 539 | ieee80211_sta_join_ibss(sdata, bss); |
405 | supp_rates = ieee80211_sta_get_rates(local, elems, band); | 540 | supp_rates = ieee80211_sta_get_rates(local, elems, band); |
406 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, | 541 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
407 | supp_rates, GFP_KERNEL); | 542 | supp_rates); |
543 | rcu_read_unlock(); | ||
408 | } | 544 | } |
409 | 545 | ||
410 | put_bss: | 546 | put_bss: |
411 | ieee80211_rx_bss_put(local, bss); | 547 | ieee80211_rx_bss_put(local, bss); |
412 | } | 548 | } |
413 | 549 | ||
414 | /* | 550 | void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, |
415 | * Add a new IBSS station, will also be called by the RX code when, | 551 | const u8 *bssid, const u8 *addr, |
416 | * in IBSS mode, receiving a frame from a yet-unknown station, hence | 552 | u32 supp_rates) |
417 | * must be callable in atomic context. | ||
418 | */ | ||
419 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | ||
420 | u8 *bssid, u8 *addr, u32 supp_rates, | ||
421 | gfp_t gfp) | ||
422 | { | 553 | { |
423 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 554 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
424 | struct ieee80211_local *local = sdata->local; | 555 | struct ieee80211_local *local = sdata->local; |
@@ -433,37 +564,29 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
433 | if (net_ratelimit()) | 564 | if (net_ratelimit()) |
434 | printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n", | 565 | printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n", |
435 | sdata->name, addr); | 566 | sdata->name, addr); |
436 | return NULL; | 567 | return; |
437 | } | 568 | } |
438 | 569 | ||
439 | if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH) | 570 | if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH) |
440 | return NULL; | 571 | return; |
441 | 572 | ||
442 | if (compare_ether_addr(bssid, sdata->u.ibss.bssid)) | 573 | if (compare_ether_addr(bssid, sdata->u.ibss.bssid)) |
443 | return NULL; | 574 | return; |
444 | |||
445 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
446 | wiphy_debug(local->hw.wiphy, "Adding new IBSS station %pM (dev=%s)\n", | ||
447 | addr, sdata->name); | ||
448 | #endif | ||
449 | 575 | ||
450 | sta = sta_info_alloc(sdata, addr, gfp); | 576 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); |
451 | if (!sta) | 577 | if (!sta) |
452 | return NULL; | 578 | return; |
453 | 579 | ||
454 | sta->last_rx = jiffies; | 580 | sta->last_rx = jiffies; |
455 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); | ||
456 | 581 | ||
457 | /* make sure mandatory rates are always added */ | 582 | /* make sure mandatory rates are always added */ |
458 | sta->sta.supp_rates[band] = supp_rates | | 583 | sta->sta.supp_rates[band] = supp_rates | |
459 | ieee80211_mandatory_rates(local, band); | 584 | ieee80211_mandatory_rates(local, band); |
460 | 585 | ||
461 | rate_control_rate_init(sta); | 586 | spin_lock(&ifibss->incomplete_lock); |
462 | 587 | list_add(&sta->list, &ifibss->incomplete_stations); | |
463 | /* If it fails, maybe we raced another insertion? */ | 588 | spin_unlock(&ifibss->incomplete_lock); |
464 | if (sta_info_insert(sta)) | 589 | ieee80211_queue_work(&local->hw, &sdata->work); |
465 | return sta_info_get(sdata, addr); | ||
466 | return sta; | ||
467 | } | 590 | } |
468 | 591 | ||
469 | static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) | 592 | static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) |
@@ -802,6 +925,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
802 | void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) | 925 | void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) |
803 | { | 926 | { |
804 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 927 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
928 | struct sta_info *sta; | ||
805 | 929 | ||
806 | mutex_lock(&ifibss->mtx); | 930 | mutex_lock(&ifibss->mtx); |
807 | 931 | ||
@@ -813,6 +937,19 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) | |||
813 | if (!ifibss->ssid_len) | 937 | if (!ifibss->ssid_len) |
814 | goto out; | 938 | goto out; |
815 | 939 | ||
940 | spin_lock_bh(&ifibss->incomplete_lock); | ||
941 | while (!list_empty(&ifibss->incomplete_stations)) { | ||
942 | sta = list_first_entry(&ifibss->incomplete_stations, | ||
943 | struct sta_info, list); | ||
944 | list_del(&sta->list); | ||
945 | spin_unlock_bh(&ifibss->incomplete_lock); | ||
946 | |||
947 | ieee80211_ibss_finish_sta(sta); | ||
948 | rcu_read_unlock(); | ||
949 | spin_lock_bh(&ifibss->incomplete_lock); | ||
950 | } | ||
951 | spin_unlock_bh(&ifibss->incomplete_lock); | ||
952 | |||
816 | switch (ifibss->state) { | 953 | switch (ifibss->state) { |
817 | case IEEE80211_IBSS_MLME_SEARCH: | 954 | case IEEE80211_IBSS_MLME_SEARCH: |
818 | ieee80211_sta_find_ibss(sdata); | 955 | ieee80211_sta_find_ibss(sdata); |
@@ -871,6 +1008,8 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
871 | setup_timer(&ifibss->timer, ieee80211_ibss_timer, | 1008 | setup_timer(&ifibss->timer, ieee80211_ibss_timer, |
872 | (unsigned long) sdata); | 1009 | (unsigned long) sdata); |
873 | mutex_init(&ifibss->mtx); | 1010 | mutex_init(&ifibss->mtx); |
1011 | INIT_LIST_HEAD(&ifibss->incomplete_stations); | ||
1012 | spin_lock_init(&ifibss->incomplete_lock); | ||
874 | } | 1013 | } |
875 | 1014 | ||
876 | /* scan finished notification */ | 1015 | /* scan finished notification */ |
@@ -894,12 +1033,18 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
894 | struct cfg80211_ibss_params *params) | 1033 | struct cfg80211_ibss_params *params) |
895 | { | 1034 | { |
896 | struct sk_buff *skb; | 1035 | struct sk_buff *skb; |
1036 | u32 changed = 0; | ||
897 | 1037 | ||
898 | skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + | 1038 | skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + |
899 | 36 /* bitrates */ + | 1039 | sizeof(struct ieee80211_hdr_3addr) + |
900 | 34 /* SSID */ + | 1040 | 12 /* struct ieee80211_mgmt.u.beacon */ + |
901 | 3 /* DS params */ + | 1041 | 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ + |
902 | 4 /* IBSS params */ + | 1042 | 2 + 8 /* max Supported Rates */ + |
1043 | 3 /* max DS params */ + | ||
1044 | 4 /* IBSS params */ + | ||
1045 | 2 + (IEEE80211_MAX_SUPP_RATES - 8) + | ||
1046 | 2 + sizeof(struct ieee80211_ht_cap) + | ||
1047 | 2 + sizeof(struct ieee80211_ht_info) + | ||
903 | params->ie_len); | 1048 | params->ie_len); |
904 | if (!skb) | 1049 | if (!skb) |
905 | return -ENOMEM; | 1050 | return -ENOMEM; |
@@ -920,13 +1065,18 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
920 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; | 1065 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; |
921 | 1066 | ||
922 | sdata->u.ibss.channel = params->channel; | 1067 | sdata->u.ibss.channel = params->channel; |
1068 | sdata->u.ibss.channel_type = params->channel_type; | ||
923 | sdata->u.ibss.fixed_channel = params->channel_fixed; | 1069 | sdata->u.ibss.fixed_channel = params->channel_fixed; |
924 | 1070 | ||
925 | /* fix ourselves to that channel now already */ | 1071 | /* fix ourselves to that channel now already */ |
926 | if (params->channel_fixed) { | 1072 | if (params->channel_fixed) { |
927 | sdata->local->oper_channel = params->channel; | 1073 | sdata->local->oper_channel = params->channel; |
928 | WARN_ON(!ieee80211_set_channel_type(sdata->local, sdata, | 1074 | if (!ieee80211_set_channel_type(sdata->local, sdata, |
929 | NL80211_CHAN_NO_HT)); | 1075 | params->channel_type)) { |
1076 | mutex_unlock(&sdata->u.ibss.mtx); | ||
1077 | kfree_skb(skb); | ||
1078 | return -EINVAL; | ||
1079 | } | ||
930 | } | 1080 | } |
931 | 1081 | ||
932 | if (params->ie) { | 1082 | if (params->ie) { |
@@ -949,6 +1099,23 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
949 | ieee80211_recalc_idle(sdata->local); | 1099 | ieee80211_recalc_idle(sdata->local); |
950 | mutex_unlock(&sdata->local->mtx); | 1100 | mutex_unlock(&sdata->local->mtx); |
951 | 1101 | ||
1102 | /* | ||
1103 | * 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is | ||
1104 | * reserved, but an HT STA shall protect HT transmissions as though | ||
1105 | * the HT Protection field were set to non-HT mixed mode. | ||
1106 | * | ||
1107 | * In an IBSS, the RIFS Mode field of the HT Operation element is | ||
1108 | * also reserved, but an HT STA shall operate as though this field | ||
1109 | * were set to 1. | ||
1110 | */ | ||
1111 | |||
1112 | sdata->vif.bss_conf.ht_operation_mode |= | ||
1113 | IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED | ||
1114 | | IEEE80211_HT_PARAM_RIFS_MODE; | ||
1115 | |||
1116 | changed |= BSS_CHANGED_HT; | ||
1117 | ieee80211_bss_info_change_notify(sdata, changed); | ||
1118 | |||
952 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); | 1119 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
953 | 1120 | ||
954 | return 0; | 1121 | return 0; |
@@ -962,6 +1129,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
962 | struct cfg80211_bss *cbss; | 1129 | struct cfg80211_bss *cbss; |
963 | u16 capability; | 1130 | u16 capability; |
964 | int active_ibss; | 1131 | int active_ibss; |
1132 | struct sta_info *sta; | ||
965 | 1133 | ||
966 | mutex_lock(&sdata->u.ibss.mtx); | 1134 | mutex_lock(&sdata->u.ibss.mtx); |
967 | 1135 | ||
@@ -991,6 +1159,20 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
991 | 1159 | ||
992 | sta_info_flush(sdata->local, sdata); | 1160 | sta_info_flush(sdata->local, sdata); |
993 | 1161 | ||
1162 | spin_lock_bh(&ifibss->incomplete_lock); | ||
1163 | while (!list_empty(&ifibss->incomplete_stations)) { | ||
1164 | sta = list_first_entry(&ifibss->incomplete_stations, | ||
1165 | struct sta_info, list); | ||
1166 | list_del(&sta->list); | ||
1167 | spin_unlock_bh(&ifibss->incomplete_lock); | ||
1168 | |||
1169 | sta_info_free(local, sta); | ||
1170 | spin_lock_bh(&ifibss->incomplete_lock); | ||
1171 | } | ||
1172 | spin_unlock_bh(&ifibss->incomplete_lock); | ||
1173 | |||
1174 | netif_carrier_off(sdata->dev); | ||
1175 | |||
994 | /* remove beacon */ | 1176 | /* remove beacon */ |
995 | kfree(sdata->u.ibss.ie); | 1177 | kfree(sdata->u.ibss.ie); |
996 | skb = rcu_dereference_protected(sdata->u.ibss.presp, | 1178 | skb = rcu_dereference_protected(sdata->u.ibss.presp, |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ea10a51babda..2f0642d9e154 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/etherdevice.h> | 25 | #include <linux/etherdevice.h> |
26 | #include <linux/leds.h> | 26 | #include <linux/leds.h> |
27 | #include <linux/idr.h> | ||
27 | #include <net/ieee80211_radiotap.h> | 28 | #include <net/ieee80211_radiotap.h> |
28 | #include <net/cfg80211.h> | 29 | #include <net/cfg80211.h> |
29 | #include <net/mac80211.h> | 30 | #include <net/mac80211.h> |
@@ -141,6 +142,7 @@ typedef unsigned __bitwise__ ieee80211_tx_result; | |||
141 | 142 | ||
142 | struct ieee80211_tx_data { | 143 | struct ieee80211_tx_data { |
143 | struct sk_buff *skb; | 144 | struct sk_buff *skb; |
145 | struct sk_buff_head skbs; | ||
144 | struct ieee80211_local *local; | 146 | struct ieee80211_local *local; |
145 | struct ieee80211_sub_if_data *sdata; | 147 | struct ieee80211_sub_if_data *sdata; |
146 | struct sta_info *sta; | 148 | struct sta_info *sta; |
@@ -184,12 +186,15 @@ enum ieee80211_packet_rx_flags { | |||
184 | * enum ieee80211_rx_flags - RX data flags | 186 | * enum ieee80211_rx_flags - RX data flags |
185 | * | 187 | * |
186 | * @IEEE80211_RX_CMNTR: received on cooked monitor already | 188 | * @IEEE80211_RX_CMNTR: received on cooked monitor already |
189 | * @IEEE80211_RX_BEACON_REPORTED: This frame was already reported | ||
190 | * to cfg80211_report_obss_beacon(). | ||
187 | * | 191 | * |
188 | * These flags are used across handling multiple interfaces | 192 | * These flags are used across handling multiple interfaces |
189 | * for a single frame. | 193 | * for a single frame. |
190 | */ | 194 | */ |
191 | enum ieee80211_rx_flags { | 195 | enum ieee80211_rx_flags { |
192 | IEEE80211_RX_CMNTR = BIT(0), | 196 | IEEE80211_RX_CMNTR = BIT(0), |
197 | IEEE80211_RX_BEACON_REPORTED = BIT(1), | ||
193 | }; | 198 | }; |
194 | 199 | ||
195 | struct ieee80211_rx_data { | 200 | struct ieee80211_rx_data { |
@@ -228,6 +233,7 @@ struct beacon_data { | |||
228 | 233 | ||
229 | struct ieee80211_if_ap { | 234 | struct ieee80211_if_ap { |
230 | struct beacon_data __rcu *beacon; | 235 | struct beacon_data __rcu *beacon; |
236 | struct sk_buff __rcu *probe_resp; | ||
231 | 237 | ||
232 | struct list_head vlans; | 238 | struct list_head vlans; |
233 | 239 | ||
@@ -237,6 +243,7 @@ struct ieee80211_if_ap { | |||
237 | u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; | 243 | u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; |
238 | struct sk_buff_head ps_bc_buf; | 244 | struct sk_buff_head ps_bc_buf; |
239 | atomic_t num_sta_ps; /* number of stations in PS mode */ | 245 | atomic_t num_sta_ps; /* number of stations in PS mode */ |
246 | atomic_t num_sta_authorized; /* number of authorized stations */ | ||
240 | int dtim_count; | 247 | int dtim_count; |
241 | bool dtim_bc_mc; | 248 | bool dtim_bc_mc; |
242 | }; | 249 | }; |
@@ -443,6 +450,9 @@ struct ieee80211_if_managed { | |||
443 | */ | 450 | */ |
444 | int rssi_min_thold, rssi_max_thold; | 451 | int rssi_min_thold, rssi_max_thold; |
445 | int last_ave_beacon_signal; | 452 | int last_ave_beacon_signal; |
453 | |||
454 | struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */ | ||
455 | struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */ | ||
446 | }; | 456 | }; |
447 | 457 | ||
448 | struct ieee80211_if_ibss { | 458 | struct ieee80211_if_ibss { |
@@ -465,12 +475,16 @@ struct ieee80211_if_ibss { | |||
465 | u8 ssid_len, ie_len; | 475 | u8 ssid_len, ie_len; |
466 | u8 *ie; | 476 | u8 *ie; |
467 | struct ieee80211_channel *channel; | 477 | struct ieee80211_channel *channel; |
478 | enum nl80211_channel_type channel_type; | ||
468 | 479 | ||
469 | unsigned long ibss_join_req; | 480 | unsigned long ibss_join_req; |
470 | /* probe response/beacon for IBSS */ | 481 | /* probe response/beacon for IBSS */ |
471 | struct sk_buff __rcu *presp; | 482 | struct sk_buff __rcu *presp; |
472 | struct sk_buff *skb; | 483 | struct sk_buff *skb; |
473 | 484 | ||
485 | spinlock_t incomplete_lock; | ||
486 | struct list_head incomplete_stations; | ||
487 | |||
474 | enum { | 488 | enum { |
475 | IEEE80211_IBSS_MLME_SEARCH, | 489 | IEEE80211_IBSS_MLME_SEARCH, |
476 | IEEE80211_IBSS_MLME_JOINED, | 490 | IEEE80211_IBSS_MLME_JOINED, |
@@ -505,7 +519,9 @@ struct ieee80211_if_mesh { | |||
505 | atomic_t mpaths; | 519 | atomic_t mpaths; |
506 | /* Timestamp of last SN update */ | 520 | /* Timestamp of last SN update */ |
507 | unsigned long last_sn_update; | 521 | unsigned long last_sn_update; |
508 | /* Timestamp of last SN sent */ | 522 | /* Time when it's ok to send next PERR */ |
523 | unsigned long next_perr; | ||
524 | /* Timestamp of last PREQ sent */ | ||
509 | unsigned long last_preq; | 525 | unsigned long last_preq; |
510 | struct mesh_rmc *rmc; | 526 | struct mesh_rmc *rmc; |
511 | spinlock_t mesh_preq_queue_lock; | 527 | spinlock_t mesh_preq_queue_lock; |
@@ -543,6 +559,7 @@ struct ieee80211_if_mesh { | |||
543 | * associated stations and deliver multicast frames both | 559 | * associated stations and deliver multicast frames both |
544 | * back to wireless media and to the local net stack. | 560 | * back to wireless media and to the local net stack. |
545 | * @IEEE80211_SDATA_DISCONNECT_RESUME: Disconnect after resume. | 561 | * @IEEE80211_SDATA_DISCONNECT_RESUME: Disconnect after resume. |
562 | * @IEEE80211_SDATA_IN_DRIVER: indicates interface was added to driver | ||
546 | */ | 563 | */ |
547 | enum ieee80211_sub_if_data_flags { | 564 | enum ieee80211_sub_if_data_flags { |
548 | IEEE80211_SDATA_ALLMULTI = BIT(0), | 565 | IEEE80211_SDATA_ALLMULTI = BIT(0), |
@@ -550,6 +567,7 @@ enum ieee80211_sub_if_data_flags { | |||
550 | IEEE80211_SDATA_OPERATING_GMODE = BIT(2), | 567 | IEEE80211_SDATA_OPERATING_GMODE = BIT(2), |
551 | IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3), | 568 | IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3), |
552 | IEEE80211_SDATA_DISCONNECT_RESUME = BIT(4), | 569 | IEEE80211_SDATA_DISCONNECT_RESUME = BIT(4), |
570 | IEEE80211_SDATA_IN_DRIVER = BIT(5), | ||
553 | }; | 571 | }; |
554 | 572 | ||
555 | /** | 573 | /** |
@@ -600,6 +618,9 @@ struct ieee80211_sub_if_data { | |||
600 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; | 618 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; |
601 | unsigned int fragment_next; | 619 | unsigned int fragment_next; |
602 | 620 | ||
621 | /* TID bitmap for NoAck policy */ | ||
622 | u16 noack_map; | ||
623 | |||
603 | struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; | 624 | struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; |
604 | struct ieee80211_key __rcu *default_unicast_key; | 625 | struct ieee80211_key __rcu *default_unicast_key; |
605 | struct ieee80211_key __rcu *default_multicast_key; | 626 | struct ieee80211_key __rcu *default_multicast_key; |
@@ -722,17 +743,16 @@ enum { | |||
722 | * operating channel | 743 | * operating channel |
723 | * @SCAN_SET_CHANNEL: Set the next channel to be scanned | 744 | * @SCAN_SET_CHANNEL: Set the next channel to be scanned |
724 | * @SCAN_SEND_PROBE: Send probe requests and wait for probe responses | 745 | * @SCAN_SEND_PROBE: Send probe requests and wait for probe responses |
725 | * @SCAN_LEAVE_OPER_CHANNEL: Leave the operating channel, notify the AP | 746 | * @SCAN_SUSPEND: Suspend the scan and go back to operating channel to |
726 | * about us leaving the channel and stop all associated STA interfaces | 747 | * send out data |
727 | * @SCAN_ENTER_OPER_CHANNEL: Enter the operating channel again, notify the | 748 | * @SCAN_RESUME: Resume the scan and scan the next channel |
728 | * AP about us being back and restart all associated STA interfaces | ||
729 | */ | 749 | */ |
730 | enum mac80211_scan_state { | 750 | enum mac80211_scan_state { |
731 | SCAN_DECISION, | 751 | SCAN_DECISION, |
732 | SCAN_SET_CHANNEL, | 752 | SCAN_SET_CHANNEL, |
733 | SCAN_SEND_PROBE, | 753 | SCAN_SEND_PROBE, |
734 | SCAN_LEAVE_OPER_CHANNEL, | 754 | SCAN_SUSPEND, |
735 | SCAN_ENTER_OPER_CHANNEL, | 755 | SCAN_RESUME, |
736 | }; | 756 | }; |
737 | 757 | ||
738 | struct ieee80211_local { | 758 | struct ieee80211_local { |
@@ -835,18 +855,15 @@ struct ieee80211_local { | |||
835 | 855 | ||
836 | /* Station data */ | 856 | /* Station data */ |
837 | /* | 857 | /* |
838 | * The mutex only protects the list and counter, | 858 | * The mutex only protects the list, hash table and |
839 | * reads are done in RCU. | 859 | * counter, reads are done with RCU. |
840 | * Additionally, the lock protects the hash table, | ||
841 | * the pending list and each BSS's TIM bitmap. | ||
842 | */ | 860 | */ |
843 | struct mutex sta_mtx; | 861 | struct mutex sta_mtx; |
844 | spinlock_t sta_lock; | 862 | spinlock_t tim_lock; |
845 | unsigned long num_sta; | 863 | unsigned long num_sta; |
846 | struct list_head sta_list, sta_pending_list; | 864 | struct list_head sta_list; |
847 | struct sta_info __rcu *sta_hash[STA_HASH_SIZE]; | 865 | struct sta_info __rcu *sta_hash[STA_HASH_SIZE]; |
848 | struct timer_list sta_cleanup; | 866 | struct timer_list sta_cleanup; |
849 | struct work_struct sta_finish_work; | ||
850 | int sta_generation; | 867 | int sta_generation; |
851 | 868 | ||
852 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; | 869 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; |
@@ -951,7 +968,6 @@ struct ieee80211_local { | |||
951 | int total_ps_buffered; /* total number of all buffered unicast and | 968 | int total_ps_buffered; /* total number of all buffered unicast and |
952 | * multicast packets for power saving stations | 969 | * multicast packets for power saving stations |
953 | */ | 970 | */ |
954 | int wifi_wme_noack_test; | ||
955 | unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ | 971 | unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ |
956 | 972 | ||
957 | /* | 973 | /* |
@@ -1012,6 +1028,9 @@ struct ieee80211_local { | |||
1012 | u32 hw_roc_cookie; | 1028 | u32 hw_roc_cookie; |
1013 | bool hw_roc_for_tx; | 1029 | bool hw_roc_for_tx; |
1014 | 1030 | ||
1031 | struct idr ack_status_frames; | ||
1032 | spinlock_t ack_status_lock; | ||
1033 | |||
1015 | /* dummy netdev for use w/ NAPI */ | 1034 | /* dummy netdev for use w/ NAPI */ |
1016 | struct net_device napi_dev; | 1035 | struct net_device napi_dev; |
1017 | 1036 | ||
@@ -1030,6 +1049,69 @@ struct ieee80211_ra_tid { | |||
1030 | u16 tid; | 1049 | u16 tid; |
1031 | }; | 1050 | }; |
1032 | 1051 | ||
1052 | /* Parsed Information Elements */ | ||
1053 | struct ieee802_11_elems { | ||
1054 | u8 *ie_start; | ||
1055 | size_t total_len; | ||
1056 | |||
1057 | /* pointers to IEs */ | ||
1058 | u8 *ssid; | ||
1059 | u8 *supp_rates; | ||
1060 | u8 *fh_params; | ||
1061 | u8 *ds_params; | ||
1062 | u8 *cf_params; | ||
1063 | struct ieee80211_tim_ie *tim; | ||
1064 | u8 *ibss_params; | ||
1065 | u8 *challenge; | ||
1066 | u8 *wpa; | ||
1067 | u8 *rsn; | ||
1068 | u8 *erp_info; | ||
1069 | u8 *ext_supp_rates; | ||
1070 | u8 *wmm_info; | ||
1071 | u8 *wmm_param; | ||
1072 | struct ieee80211_ht_cap *ht_cap_elem; | ||
1073 | struct ieee80211_ht_info *ht_info_elem; | ||
1074 | struct ieee80211_meshconf_ie *mesh_config; | ||
1075 | u8 *mesh_id; | ||
1076 | u8 *peering; | ||
1077 | u8 *preq; | ||
1078 | u8 *prep; | ||
1079 | u8 *perr; | ||
1080 | struct ieee80211_rann_ie *rann; | ||
1081 | u8 *ch_switch_elem; | ||
1082 | u8 *country_elem; | ||
1083 | u8 *pwr_constr_elem; | ||
1084 | u8 *quiet_elem; /* first quite element */ | ||
1085 | u8 *timeout_int; | ||
1086 | |||
1087 | /* length of them, respectively */ | ||
1088 | u8 ssid_len; | ||
1089 | u8 supp_rates_len; | ||
1090 | u8 fh_params_len; | ||
1091 | u8 ds_params_len; | ||
1092 | u8 cf_params_len; | ||
1093 | u8 tim_len; | ||
1094 | u8 ibss_params_len; | ||
1095 | u8 challenge_len; | ||
1096 | u8 wpa_len; | ||
1097 | u8 rsn_len; | ||
1098 | u8 erp_info_len; | ||
1099 | u8 ext_supp_rates_len; | ||
1100 | u8 wmm_info_len; | ||
1101 | u8 wmm_param_len; | ||
1102 | u8 mesh_id_len; | ||
1103 | u8 peering_len; | ||
1104 | u8 preq_len; | ||
1105 | u8 prep_len; | ||
1106 | u8 perr_len; | ||
1107 | u8 ch_switch_elem_len; | ||
1108 | u8 country_elem_len; | ||
1109 | u8 pwr_constr_elem_len; | ||
1110 | u8 quiet_elem_len; | ||
1111 | u8 num_of_quiet_elem; /* can be more the one */ | ||
1112 | u8 timeout_int_len; | ||
1113 | }; | ||
1114 | |||
1033 | static inline struct ieee80211_local *hw_to_local( | 1115 | static inline struct ieee80211_local *hw_to_local( |
1034 | struct ieee80211_hw *hw) | 1116 | struct ieee80211_hw *hw) |
1035 | { | 1117 | { |
@@ -1090,9 +1172,8 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); | |||
1090 | /* IBSS code */ | 1172 | /* IBSS code */ |
1091 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); | 1173 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); |
1092 | void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); | 1174 | void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); |
1093 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 1175 | void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, |
1094 | u8 *bssid, u8 *addr, u32 supp_rates, | 1176 | const u8 *bssid, const u8 *addr, u32 supp_rates); |
1095 | gfp_t gfp); | ||
1096 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | 1177 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, |
1097 | struct cfg80211_ibss_params *params); | 1178 | struct cfg80211_ibss_params *params); |
1098 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); | 1179 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); |
@@ -1140,13 +1221,9 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); | |||
1140 | void ieee80211_sched_scan_stopped_work(struct work_struct *work); | 1221 | void ieee80211_sched_scan_stopped_work(struct work_struct *work); |
1141 | 1222 | ||
1142 | /* off-channel helpers */ | 1223 | /* off-channel helpers */ |
1143 | bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local); | ||
1144 | void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, | ||
1145 | bool tell_ap); | ||
1146 | void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, | 1224 | void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, |
1147 | bool offchannel_ps_enable); | 1225 | bool offchannel_ps_enable); |
1148 | void ieee80211_offchannel_return(struct ieee80211_local *local, | 1226 | void ieee80211_offchannel_return(struct ieee80211_local *local, |
1149 | bool enable_beaconing, | ||
1150 | bool offchannel_ps_disable); | 1227 | bool offchannel_ps_disable); |
1151 | void ieee80211_hw_roc_setup(struct ieee80211_local *local); | 1228 | void ieee80211_hw_roc_setup(struct ieee80211_local *local); |
1152 | 1229 | ||
@@ -1179,7 +1256,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1179 | struct net_device *dev); | 1256 | struct net_device *dev); |
1180 | 1257 | ||
1181 | /* HT */ | 1258 | /* HT */ |
1182 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, | 1259 | bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata); |
1260 | void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, | ||
1261 | struct ieee80211_sta_ht_cap *ht_cap); | ||
1262 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | ||
1263 | struct ieee80211_supported_band *sband, | ||
1183 | struct ieee80211_ht_cap *ht_cap_ie, | 1264 | struct ieee80211_ht_cap *ht_cap_ie, |
1184 | struct ieee80211_sta_ht_cap *ht_cap); | 1265 | struct ieee80211_sta_ht_cap *ht_cap); |
1185 | void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | 1266 | void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, |
@@ -1266,7 +1347,16 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke | |||
1266 | gfp_t gfp); | 1347 | gfp_t gfp); |
1267 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); | 1348 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); |
1268 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); | 1349 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); |
1269 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); | 1350 | |
1351 | void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, | ||
1352 | struct sk_buff *skb, int tid); | ||
1353 | static void inline ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, | ||
1354 | struct sk_buff *skb) | ||
1355 | { | ||
1356 | /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */ | ||
1357 | ieee80211_tx_skb_tid(sdata, skb, 7); | ||
1358 | } | ||
1359 | |||
1270 | void ieee802_11_parse_elems(u8 *start, size_t len, | 1360 | void ieee802_11_parse_elems(u8 *start, size_t len, |
1271 | struct ieee802_11_elems *elems); | 1361 | struct ieee802_11_elems *elems); |
1272 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | 1362 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, |
@@ -1334,6 +1424,12 @@ void ieee80211_recalc_smps(struct ieee80211_local *local); | |||
1334 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, | 1424 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, |
1335 | const u8 *ids, int n_ids, size_t offset); | 1425 | const u8 *ids, int n_ids, size_t offset); |
1336 | size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); | 1426 | size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); |
1427 | u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | ||
1428 | u16 cap); | ||
1429 | u8 *ieee80211_ie_build_ht_info(u8 *pos, | ||
1430 | struct ieee80211_sta_ht_cap *ht_cap, | ||
1431 | struct ieee80211_channel *channel, | ||
1432 | enum nl80211_channel_type channel_type); | ||
1337 | 1433 | ||
1338 | /* internal work items */ | 1434 | /* internal work items */ |
1339 | void ieee80211_work_init(struct ieee80211_local *local); | 1435 | void ieee80211_work_init(struct ieee80211_local *local); |
@@ -1362,6 +1458,8 @@ ieee80211_get_channel_mode(struct ieee80211_local *local, | |||
1362 | bool ieee80211_set_channel_type(struct ieee80211_local *local, | 1458 | bool ieee80211_set_channel_type(struct ieee80211_local *local, |
1363 | struct ieee80211_sub_if_data *sdata, | 1459 | struct ieee80211_sub_if_data *sdata, |
1364 | enum nl80211_channel_type chantype); | 1460 | enum nl80211_channel_type chantype); |
1461 | enum nl80211_channel_type | ||
1462 | ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info); | ||
1365 | 1463 | ||
1366 | #ifdef CONFIG_MAC80211_NOINLINE | 1464 | #ifdef CONFIG_MAC80211_NOINLINE |
1367 | #define debug_noinline noinline | 1465 | #define debug_noinline noinline |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 30d73552e9ab..e47768cb8cb3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -188,11 +188,22 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
188 | if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) | 188 | if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) |
189 | return -ENOLINK; | 189 | return -ENOLINK; |
190 | break; | 190 | break; |
191 | case NL80211_IFTYPE_AP_VLAN: | 191 | case NL80211_IFTYPE_AP_VLAN: { |
192 | struct ieee80211_sub_if_data *master; | ||
193 | |||
192 | if (!sdata->bss) | 194 | if (!sdata->bss) |
193 | return -ENOLINK; | 195 | return -ENOLINK; |
196 | |||
194 | list_add(&sdata->u.vlan.list, &sdata->bss->vlans); | 197 | list_add(&sdata->u.vlan.list, &sdata->bss->vlans); |
198 | |||
199 | master = container_of(sdata->bss, | ||
200 | struct ieee80211_sub_if_data, u.ap); | ||
201 | sdata->control_port_protocol = | ||
202 | master->control_port_protocol; | ||
203 | sdata->control_port_no_encrypt = | ||
204 | master->control_port_no_encrypt; | ||
195 | break; | 205 | break; |
206 | } | ||
196 | case NL80211_IFTYPE_AP: | 207 | case NL80211_IFTYPE_AP: |
197 | sdata->bss = &sdata->u.ap; | 208 | sdata->bss = &sdata->u.ap; |
198 | break; | 209 | break; |
@@ -265,7 +276,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
265 | break; | 276 | break; |
266 | default: | 277 | default: |
267 | if (coming_up) { | 278 | if (coming_up) { |
268 | res = drv_add_interface(local, &sdata->vif); | 279 | res = drv_add_interface(local, sdata); |
269 | if (res) | 280 | if (res) |
270 | goto err_stop; | 281 | goto err_stop; |
271 | } | 282 | } |
@@ -282,10 +293,18 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
282 | changed |= ieee80211_reset_erp_info(sdata); | 293 | changed |= ieee80211_reset_erp_info(sdata); |
283 | ieee80211_bss_info_change_notify(sdata, changed); | 294 | ieee80211_bss_info_change_notify(sdata, changed); |
284 | 295 | ||
285 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 296 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
297 | sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
286 | netif_carrier_off(dev); | 298 | netif_carrier_off(dev); |
287 | else | 299 | else |
288 | netif_carrier_on(dev); | 300 | netif_carrier_on(dev); |
301 | |||
302 | /* | ||
303 | * set default queue parameters so drivers don't | ||
304 | * need to initialise the hardware if the hardware | ||
305 | * doesn't start up with sane defaults | ||
306 | */ | ||
307 | ieee80211_set_wmm_default(sdata); | ||
289 | } | 308 | } |
290 | 309 | ||
291 | set_bit(SDATA_STATE_RUNNING, &sdata->state); | 310 | set_bit(SDATA_STATE_RUNNING, &sdata->state); |
@@ -299,8 +318,9 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
299 | goto err_del_interface; | 318 | goto err_del_interface; |
300 | } | 319 | } |
301 | 320 | ||
302 | /* no atomic bitop required since STA is not live yet */ | 321 | sta_info_move_state(sta, IEEE80211_STA_AUTH); |
303 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); | 322 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
323 | sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
304 | 324 | ||
305 | res = sta_info_insert(sta); | 325 | res = sta_info_insert(sta); |
306 | if (res) { | 326 | if (res) { |
@@ -329,15 +349,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
329 | if (coming_up) | 349 | if (coming_up) |
330 | local->open_count++; | 350 | local->open_count++; |
331 | 351 | ||
332 | if (hw_reconf_flags) { | 352 | if (hw_reconf_flags) |
333 | ieee80211_hw_config(local, hw_reconf_flags); | 353 | ieee80211_hw_config(local, hw_reconf_flags); |
334 | /* | ||
335 | * set default queue parameters so drivers don't | ||
336 | * need to initialise the hardware if the hardware | ||
337 | * doesn't start up with sane defaults | ||
338 | */ | ||
339 | ieee80211_set_wmm_default(sdata); | ||
340 | } | ||
341 | 354 | ||
342 | ieee80211_recalc_ps(local, -1); | 355 | ieee80211_recalc_ps(local, -1); |
343 | 356 | ||
@@ -345,7 +358,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
345 | 358 | ||
346 | return 0; | 359 | return 0; |
347 | err_del_interface: | 360 | err_del_interface: |
348 | drv_remove_interface(local, &sdata->vif); | 361 | drv_remove_interface(local, sdata); |
349 | err_stop: | 362 | err_stop: |
350 | if (!local->open_count) | 363 | if (!local->open_count) |
351 | drv_stop(local); | 364 | drv_stop(local); |
@@ -450,15 +463,19 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
450 | struct ieee80211_sub_if_data *vlan, *tmpsdata; | 463 | struct ieee80211_sub_if_data *vlan, *tmpsdata; |
451 | struct beacon_data *old_beacon = | 464 | struct beacon_data *old_beacon = |
452 | rtnl_dereference(sdata->u.ap.beacon); | 465 | rtnl_dereference(sdata->u.ap.beacon); |
466 | struct sk_buff *old_probe_resp = | ||
467 | rtnl_dereference(sdata->u.ap.probe_resp); | ||
453 | 468 | ||
454 | /* sdata_running will return false, so this will disable */ | 469 | /* sdata_running will return false, so this will disable */ |
455 | ieee80211_bss_info_change_notify(sdata, | 470 | ieee80211_bss_info_change_notify(sdata, |
456 | BSS_CHANGED_BEACON_ENABLED); | 471 | BSS_CHANGED_BEACON_ENABLED); |
457 | 472 | ||
458 | /* remove beacon */ | 473 | /* remove beacon and probe response */ |
459 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); | 474 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); |
475 | RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL); | ||
460 | synchronize_rcu(); | 476 | synchronize_rcu(); |
461 | kfree(old_beacon); | 477 | kfree(old_beacon); |
478 | kfree_skb(old_probe_resp); | ||
462 | 479 | ||
463 | /* down all dependent devices, that is VLANs */ | 480 | /* down all dependent devices, that is VLANs */ |
464 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, | 481 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, |
@@ -520,7 +537,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
520 | ieee80211_free_keys(sdata); | 537 | ieee80211_free_keys(sdata); |
521 | 538 | ||
522 | if (going_down) | 539 | if (going_down) |
523 | drv_remove_interface(local, &sdata->vif); | 540 | drv_remove_interface(local, sdata); |
524 | } | 541 | } |
525 | 542 | ||
526 | sdata->bss = NULL; | 543 | sdata->bss = NULL; |
@@ -656,7 +673,6 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, | |||
656 | struct ieee80211_local *local = sdata->local; | 673 | struct ieee80211_local *local = sdata->local; |
657 | struct ieee80211_hdr *hdr; | 674 | struct ieee80211_hdr *hdr; |
658 | struct ieee80211_radiotap_header *rtap = (void *)skb->data; | 675 | struct ieee80211_radiotap_header *rtap = (void *)skb->data; |
659 | u8 *p; | ||
660 | 676 | ||
661 | if (local->hw.queues < 4) | 677 | if (local->hw.queues < 4) |
662 | return 0; | 678 | return 0; |
@@ -667,19 +683,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, | |||
667 | 683 | ||
668 | hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); | 684 | hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); |
669 | 685 | ||
670 | if (!ieee80211_is_data(hdr->frame_control)) { | 686 | return ieee80211_select_queue_80211(local, skb, hdr); |
671 | skb->priority = 7; | ||
672 | return ieee802_1d_to_ac[skb->priority]; | ||
673 | } | ||
674 | if (!ieee80211_is_data_qos(hdr->frame_control)) { | ||
675 | skb->priority = 0; | ||
676 | return ieee802_1d_to_ac[skb->priority]; | ||
677 | } | ||
678 | |||
679 | p = ieee80211_get_qos_ctl(hdr); | ||
680 | skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK; | ||
681 | |||
682 | return ieee80211_downgrade_queue(local, skb); | ||
683 | } | 687 | } |
684 | 688 | ||
685 | static const struct net_device_ops ieee80211_monitorif_ops = { | 689 | static const struct net_device_ops ieee80211_monitorif_ops = { |
@@ -850,6 +854,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
850 | sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); | 854 | sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); |
851 | sdata->control_port_no_encrypt = false; | 855 | sdata->control_port_no_encrypt = false; |
852 | 856 | ||
857 | sdata->noack_map = 0; | ||
858 | |||
853 | /* only monitor differs */ | 859 | /* only monitor differs */ |
854 | sdata->dev->type = ARPHRD_ETHER; | 860 | sdata->dev->type = ARPHRD_ETHER; |
855 | 861 | ||
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index fb02ea52d2c2..87a89741432d 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -134,9 +134,13 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
134 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; | 134 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; |
135 | 135 | ||
136 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || | 136 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || |
137 | (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))) | 137 | (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) || |
138 | (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))) | ||
138 | sdata->crypto_tx_tailroom_needed_cnt--; | 139 | sdata->crypto_tx_tailroom_needed_cnt--; |
139 | 140 | ||
141 | WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) && | ||
142 | (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)); | ||
143 | |||
140 | return 0; | 144 | return 0; |
141 | } | 145 | } |
142 | 146 | ||
@@ -179,7 +183,8 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | |||
179 | sdata = key->sdata; | 183 | sdata = key->sdata; |
180 | 184 | ||
181 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || | 185 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || |
182 | (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))) | 186 | (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) || |
187 | (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))) | ||
183 | increment_tailroom_need_count(sdata); | 188 | increment_tailroom_need_count(sdata); |
184 | 189 | ||
185 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 190 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index cae443563ec9..0a0d94ad9b08 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -47,7 +47,7 @@ void ieee80211_configure_filter(struct ieee80211_local *local) | |||
47 | if (atomic_read(&local->iff_allmultis)) | 47 | if (atomic_read(&local->iff_allmultis)) |
48 | new_flags |= FIF_ALLMULTI; | 48 | new_flags |= FIF_ALLMULTI; |
49 | 49 | ||
50 | if (local->monitors || local->scanning) | 50 | if (local->monitors || test_bit(SCAN_SW_SCANNING, &local->scanning)) |
51 | new_flags |= FIF_BCN_PRBRESP_PROMISC; | 51 | new_flags |= FIF_BCN_PRBRESP_PROMISC; |
52 | 52 | ||
53 | if (local->fif_probe_req || local->probe_req_reg) | 53 | if (local->fif_probe_req || local->probe_req_reg) |
@@ -92,50 +92,9 @@ static void ieee80211_reconfig_filter(struct work_struct *work) | |||
92 | ieee80211_configure_filter(local); | 92 | ieee80211_configure_filter(local); |
93 | } | 93 | } |
94 | 94 | ||
95 | /* | ||
96 | * Returns true if we are logically configured to be on | ||
97 | * the operating channel AND the hardware-conf is currently | ||
98 | * configured on the operating channel. Compares channel-type | ||
99 | * as well. | ||
100 | */ | ||
101 | bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local) | ||
102 | { | ||
103 | struct ieee80211_channel *chan, *scan_chan; | ||
104 | enum nl80211_channel_type channel_type; | ||
105 | |||
106 | /* This logic needs to match logic in ieee80211_hw_config */ | ||
107 | if (local->scan_channel) { | ||
108 | chan = local->scan_channel; | ||
109 | /* If scanning on oper channel, use whatever channel-type | ||
110 | * is currently in use. | ||
111 | */ | ||
112 | if (chan == local->oper_channel) | ||
113 | channel_type = local->_oper_channel_type; | ||
114 | else | ||
115 | channel_type = NL80211_CHAN_NO_HT; | ||
116 | } else if (local->tmp_channel) { | ||
117 | chan = scan_chan = local->tmp_channel; | ||
118 | channel_type = local->tmp_channel_type; | ||
119 | } else { | ||
120 | chan = local->oper_channel; | ||
121 | channel_type = local->_oper_channel_type; | ||
122 | } | ||
123 | |||
124 | if (chan != local->oper_channel || | ||
125 | channel_type != local->_oper_channel_type) | ||
126 | return false; | ||
127 | |||
128 | /* Check current hardware-config against oper_channel. */ | ||
129 | if ((local->oper_channel != local->hw.conf.channel) || | ||
130 | (local->_oper_channel_type != local->hw.conf.channel_type)) | ||
131 | return false; | ||
132 | |||
133 | return true; | ||
134 | } | ||
135 | |||
136 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | 95 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) |
137 | { | 96 | { |
138 | struct ieee80211_channel *chan, *scan_chan; | 97 | struct ieee80211_channel *chan; |
139 | int ret = 0; | 98 | int ret = 0; |
140 | int power; | 99 | int power; |
141 | enum nl80211_channel_type channel_type; | 100 | enum nl80211_channel_type channel_type; |
@@ -143,14 +102,12 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
143 | 102 | ||
144 | might_sleep(); | 103 | might_sleep(); |
145 | 104 | ||
146 | scan_chan = local->scan_channel; | ||
147 | |||
148 | /* If this off-channel logic ever changes, ieee80211_on_oper_channel | 105 | /* If this off-channel logic ever changes, ieee80211_on_oper_channel |
149 | * may need to change as well. | 106 | * may need to change as well. |
150 | */ | 107 | */ |
151 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | 108 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
152 | if (scan_chan) { | 109 | if (local->scan_channel) { |
153 | chan = scan_chan; | 110 | chan = local->scan_channel; |
154 | /* If scanning on oper channel, use whatever channel-type | 111 | /* If scanning on oper channel, use whatever channel-type |
155 | * is currently in use. | 112 | * is currently in use. |
156 | */ | 113 | */ |
@@ -159,7 +116,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
159 | else | 116 | else |
160 | channel_type = NL80211_CHAN_NO_HT; | 117 | channel_type = NL80211_CHAN_NO_HT; |
161 | } else if (local->tmp_channel) { | 118 | } else if (local->tmp_channel) { |
162 | chan = scan_chan = local->tmp_channel; | 119 | chan = local->tmp_channel; |
163 | channel_type = local->tmp_channel_type; | 120 | channel_type = local->tmp_channel_type; |
164 | } else { | 121 | } else { |
165 | chan = local->oper_channel; | 122 | chan = local->oper_channel; |
@@ -193,8 +150,8 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
193 | changed |= IEEE80211_CONF_CHANGE_SMPS; | 150 | changed |= IEEE80211_CONF_CHANGE_SMPS; |
194 | } | 151 | } |
195 | 152 | ||
196 | if ((local->scanning & SCAN_SW_SCANNING) || | 153 | if (test_bit(SCAN_SW_SCANNING, &local->scanning) || |
197 | (local->scanning & SCAN_HW_SCANNING)) | 154 | test_bit(SCAN_HW_SCANNING, &local->scanning)) |
198 | power = chan->max_power; | 155 | power = chan->max_power; |
199 | else | 156 | else |
200 | power = local->power_constr_level ? | 157 | power = local->power_constr_level ? |
@@ -436,9 +393,6 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
436 | sdata = IEEE80211_DEV_TO_SUB_IF(ndev); | 393 | sdata = IEEE80211_DEV_TO_SUB_IF(ndev); |
437 | bss_conf = &sdata->vif.bss_conf; | 394 | bss_conf = &sdata->vif.bss_conf; |
438 | 395 | ||
439 | if (!ieee80211_sdata_running(sdata)) | ||
440 | return NOTIFY_DONE; | ||
441 | |||
442 | /* ARP filtering is only supported in managed mode */ | 396 | /* ARP filtering is only supported in managed mode */ |
443 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 397 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
444 | return NOTIFY_DONE; | 398 | return NOTIFY_DONE; |
@@ -467,7 +421,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
467 | } | 421 | } |
468 | bss_conf->arp_addr_cnt = c; | 422 | bss_conf->arp_addr_cnt = c; |
469 | 423 | ||
470 | /* Configure driver only if associated */ | 424 | /* Configure driver only if associated (which also implies it is up) */ |
471 | if (ifmgd->associated) { | 425 | if (ifmgd->associated) { |
472 | bss_conf->arp_filter_enabled = sdata->arp_filter_state; | 426 | bss_conf->arp_filter_enabled = sdata->arp_filter_state; |
473 | ieee80211_bss_info_change_notify(sdata, | 427 | ieee80211_bss_info_change_notify(sdata, |
@@ -560,6 +514,19 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | |||
560 | }, | 514 | }, |
561 | }; | 515 | }; |
562 | 516 | ||
517 | static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = { | ||
518 | .ampdu_params_info = IEEE80211_HT_AMPDU_PARM_FACTOR | | ||
519 | IEEE80211_HT_AMPDU_PARM_DENSITY, | ||
520 | |||
521 | .cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | ||
522 | IEEE80211_HT_CAP_MAX_AMSDU | | ||
523 | IEEE80211_HT_CAP_SGI_40), | ||
524 | .mcs = { | ||
525 | .rx_mask = { 0xff, 0xff, 0xff, 0xff, 0xff, | ||
526 | 0xff, 0xff, 0xff, 0xff, 0xff, }, | ||
527 | }, | ||
528 | }; | ||
529 | |||
563 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 530 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
564 | const struct ieee80211_ops *ops) | 531 | const struct ieee80211_ops *ops) |
565 | { | 532 | { |
@@ -595,7 +562,13 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
595 | 562 | ||
596 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | | 563 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | |
597 | WIPHY_FLAG_4ADDR_AP | | 564 | WIPHY_FLAG_4ADDR_AP | |
598 | WIPHY_FLAG_4ADDR_STATION; | 565 | WIPHY_FLAG_4ADDR_STATION | |
566 | WIPHY_FLAG_REPORTS_OBSS | | ||
567 | WIPHY_FLAG_OFFCHAN_TX | | ||
568 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | ||
569 | |||
570 | wiphy->features = NL80211_FEATURE_SK_TX_STATUS | | ||
571 | NL80211_FEATURE_HT_IBSS; | ||
599 | 572 | ||
600 | if (!ops->set_key) | 573 | if (!ops->set_key) |
601 | wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | 574 | wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
@@ -608,7 +581,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
608 | 581 | ||
609 | local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); | 582 | local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); |
610 | 583 | ||
611 | BUG_ON(!ops->tx); | 584 | BUG_ON(!ops->tx && !ops->tx_frags); |
612 | BUG_ON(!ops->start); | 585 | BUG_ON(!ops->start); |
613 | BUG_ON(!ops->stop); | 586 | BUG_ON(!ops->stop); |
614 | BUG_ON(!ops->config); | 587 | BUG_ON(!ops->config); |
@@ -628,6 +601,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
628 | local->user_power_level = -1; | 601 | local->user_power_level = -1; |
629 | local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES; | 602 | local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES; |
630 | local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN; | 603 | local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN; |
604 | wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; | ||
631 | 605 | ||
632 | INIT_LIST_HEAD(&local->interfaces); | 606 | INIT_LIST_HEAD(&local->interfaces); |
633 | 607 | ||
@@ -670,6 +644,11 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
670 | INIT_WORK(&local->sched_scan_stopped_work, | 644 | INIT_WORK(&local->sched_scan_stopped_work, |
671 | ieee80211_sched_scan_stopped_work); | 645 | ieee80211_sched_scan_stopped_work); |
672 | 646 | ||
647 | spin_lock_init(&local->ack_status_lock); | ||
648 | idr_init(&local->ack_status_frames); | ||
649 | /* preallocate at least one entry */ | ||
650 | idr_pre_get(&local->ack_status_frames, GFP_KERNEL); | ||
651 | |||
673 | sta_info_init(local); | 652 | sta_info_init(local); |
674 | 653 | ||
675 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { | 654 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { |
@@ -1051,6 +1030,13 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1051 | } | 1030 | } |
1052 | EXPORT_SYMBOL(ieee80211_unregister_hw); | 1031 | EXPORT_SYMBOL(ieee80211_unregister_hw); |
1053 | 1032 | ||
1033 | static int ieee80211_free_ack_frame(int id, void *p, void *data) | ||
1034 | { | ||
1035 | WARN_ONCE(1, "Have pending ack frames!\n"); | ||
1036 | kfree_skb(p); | ||
1037 | return 0; | ||
1038 | } | ||
1039 | |||
1054 | void ieee80211_free_hw(struct ieee80211_hw *hw) | 1040 | void ieee80211_free_hw(struct ieee80211_hw *hw) |
1055 | { | 1041 | { |
1056 | struct ieee80211_local *local = hw_to_local(hw); | 1042 | struct ieee80211_local *local = hw_to_local(hw); |
@@ -1061,6 +1047,10 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) | |||
1061 | if (local->wiphy_ciphers_allocated) | 1047 | if (local->wiphy_ciphers_allocated) |
1062 | kfree(local->hw.wiphy->cipher_suites); | 1048 | kfree(local->hw.wiphy->cipher_suites); |
1063 | 1049 | ||
1050 | idr_for_each(&local->ack_status_frames, | ||
1051 | ieee80211_free_ack_frame, NULL); | ||
1052 | idr_destroy(&local->ack_status_frames); | ||
1053 | |||
1064 | wiphy_free(local->hw.wiphy); | 1054 | wiphy_free(local->hw.wiphy); |
1065 | } | 1055 | } |
1066 | EXPORT_SYMBOL(ieee80211_free_hw); | 1056 | EXPORT_SYMBOL(ieee80211_free_hw); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index a7078fdba8ca..c707c8bf6d2c 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -76,6 +76,7 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data) | |||
76 | bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) | 76 | bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) |
77 | { | 77 | { |
78 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 78 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
79 | struct ieee80211_local *local = sdata->local; | ||
79 | 80 | ||
80 | /* | 81 | /* |
81 | * As support for each feature is added, check for matching | 82 | * As support for each feature is added, check for matching |
@@ -87,15 +88,23 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat | |||
87 | * - MDA enabled | 88 | * - MDA enabled |
88 | * - Power management control on fc | 89 | * - Power management control on fc |
89 | */ | 90 | */ |
90 | if (ifmsh->mesh_id_len == ie->mesh_id_len && | 91 | if (!(ifmsh->mesh_id_len == ie->mesh_id_len && |
91 | memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && | 92 | memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && |
92 | (ifmsh->mesh_pp_id == ie->mesh_config->meshconf_psel) && | 93 | (ifmsh->mesh_pp_id == ie->mesh_config->meshconf_psel) && |
93 | (ifmsh->mesh_pm_id == ie->mesh_config->meshconf_pmetric) && | 94 | (ifmsh->mesh_pm_id == ie->mesh_config->meshconf_pmetric) && |
94 | (ifmsh->mesh_cc_id == ie->mesh_config->meshconf_congest) && | 95 | (ifmsh->mesh_cc_id == ie->mesh_config->meshconf_congest) && |
95 | (ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) && | 96 | (ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) && |
96 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)) | 97 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) |
97 | return true; | 98 | goto mismatch; |
98 | 99 | ||
100 | /* disallow peering with mismatched channel types for now */ | ||
101 | if (ie->ht_info_elem && | ||
102 | (local->_oper_channel_type != | ||
103 | ieee80211_ht_info_to_channel_type(ie->ht_info_elem))) | ||
104 | goto mismatch; | ||
105 | |||
106 | return true; | ||
107 | mismatch: | ||
99 | return false; | 108 | return false; |
100 | } | 109 | } |
101 | 110 | ||
@@ -341,6 +350,49 @@ int mesh_add_ds_params_ie(struct sk_buff *skb, | |||
341 | return 0; | 350 | return 0; |
342 | } | 351 | } |
343 | 352 | ||
353 | int mesh_add_ht_cap_ie(struct sk_buff *skb, | ||
354 | struct ieee80211_sub_if_data *sdata) | ||
355 | { | ||
356 | struct ieee80211_local *local = sdata->local; | ||
357 | struct ieee80211_supported_band *sband; | ||
358 | u8 *pos; | ||
359 | |||
360 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | ||
361 | if (!sband->ht_cap.ht_supported || | ||
362 | local->_oper_channel_type == NL80211_CHAN_NO_HT) | ||
363 | return 0; | ||
364 | |||
365 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) | ||
366 | return -ENOMEM; | ||
367 | |||
368 | pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_cap)); | ||
369 | ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, sband->ht_cap.cap); | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | int mesh_add_ht_info_ie(struct sk_buff *skb, | ||
375 | struct ieee80211_sub_if_data *sdata) | ||
376 | { | ||
377 | struct ieee80211_local *local = sdata->local; | ||
378 | struct ieee80211_channel *channel = local->oper_channel; | ||
379 | enum nl80211_channel_type channel_type = local->_oper_channel_type; | ||
380 | struct ieee80211_supported_band *sband = | ||
381 | local->hw.wiphy->bands[channel->band]; | ||
382 | struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap; | ||
383 | u8 *pos; | ||
384 | |||
385 | if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT) | ||
386 | return 0; | ||
387 | |||
388 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_info)) | ||
389 | return -ENOMEM; | ||
390 | |||
391 | pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_info)); | ||
392 | ieee80211_ie_build_ht_info(pos, ht_cap, channel, channel_type); | ||
393 | |||
394 | return 0; | ||
395 | } | ||
344 | static void ieee80211_mesh_path_timer(unsigned long data) | 396 | static void ieee80211_mesh_path_timer(unsigned long data) |
345 | { | 397 | { |
346 | struct ieee80211_sub_if_data *sdata = | 398 | struct ieee80211_sub_if_data *sdata = |
@@ -697,6 +749,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
697 | atomic_set(&ifmsh->mpaths, 0); | 749 | atomic_set(&ifmsh->mpaths, 0); |
698 | mesh_rmc_init(sdata); | 750 | mesh_rmc_init(sdata); |
699 | ifmsh->last_preq = jiffies; | 751 | ifmsh->last_preq = jiffies; |
752 | ifmsh->next_perr = jiffies; | ||
700 | /* Allocate all mesh structures when creating the first mesh interface. */ | 753 | /* Allocate all mesh structures when creating the first mesh interface. */ |
701 | if (!mesh_allocated) | 754 | if (!mesh_allocated) |
702 | ieee80211s_init(); | 755 | ieee80211s_init(); |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 8c00e2d1d636..bd14bd26a2b6 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -31,6 +31,8 @@ | |||
31 | * @MESH_PATH_FIXED: the mesh path has been manually set and should not be | 31 | * @MESH_PATH_FIXED: the mesh path has been manually set and should not be |
32 | * modified | 32 | * modified |
33 | * @MESH_PATH_RESOLVED: the mesh path can has been resolved | 33 | * @MESH_PATH_RESOLVED: the mesh path can has been resolved |
34 | * @MESH_PATH_REQ_QUEUED: there is an unsent path request for this destination | ||
35 | * already queued up, waiting for the discovery process to start. | ||
34 | * | 36 | * |
35 | * MESH_PATH_RESOLVED is used by the mesh path timer to | 37 | * MESH_PATH_RESOLVED is used by the mesh path timer to |
36 | * decide when to stop or cancel the mesh path discovery. | 38 | * decide when to stop or cancel the mesh path discovery. |
@@ -41,6 +43,7 @@ enum mesh_path_flags { | |||
41 | MESH_PATH_SN_VALID = BIT(2), | 43 | MESH_PATH_SN_VALID = BIT(2), |
42 | MESH_PATH_FIXED = BIT(3), | 44 | MESH_PATH_FIXED = BIT(3), |
43 | MESH_PATH_RESOLVED = BIT(4), | 45 | MESH_PATH_RESOLVED = BIT(4), |
46 | MESH_PATH_REQ_QUEUED = BIT(5), | ||
44 | }; | 47 | }; |
45 | 48 | ||
46 | /** | 49 | /** |
@@ -212,6 +215,10 @@ int mesh_add_vendor_ies(struct sk_buff *skb, | |||
212 | struct ieee80211_sub_if_data *sdata); | 215 | struct ieee80211_sub_if_data *sdata); |
213 | int mesh_add_ds_params_ie(struct sk_buff *skb, | 216 | int mesh_add_ds_params_ie(struct sk_buff *skb, |
214 | struct ieee80211_sub_if_data *sdata); | 217 | struct ieee80211_sub_if_data *sdata); |
218 | int mesh_add_ht_cap_ie(struct sk_buff *skb, | ||
219 | struct ieee80211_sub_if_data *sdata); | ||
220 | int mesh_add_ht_info_ie(struct sk_buff *skb, | ||
221 | struct ieee80211_sub_if_data *sdata); | ||
215 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); | 222 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); |
216 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); | 223 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); |
217 | void ieee80211s_init(void); | 224 | void ieee80211s_init(void); |
@@ -226,6 +233,8 @@ void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh); | |||
226 | /* Mesh paths */ | 233 | /* Mesh paths */ |
227 | int mesh_nexthop_lookup(struct sk_buff *skb, | 234 | int mesh_nexthop_lookup(struct sk_buff *skb, |
228 | struct ieee80211_sub_if_data *sdata); | 235 | struct ieee80211_sub_if_data *sdata); |
236 | int mesh_nexthop_resolve(struct sk_buff *skb, | ||
237 | struct ieee80211_sub_if_data *sdata); | ||
229 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); | 238 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); |
230 | struct mesh_path *mesh_path_lookup(u8 *dst, | 239 | struct mesh_path *mesh_path_lookup(u8 *dst, |
231 | struct ieee80211_sub_if_data *sdata); | 240 | struct ieee80211_sub_if_data *sdata); |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 174040a42887..73abb7524b2c 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -113,20 +113,20 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
113 | struct ieee80211_sub_if_data *sdata) | 113 | struct ieee80211_sub_if_data *sdata) |
114 | { | 114 | { |
115 | struct ieee80211_local *local = sdata->local; | 115 | struct ieee80211_local *local = sdata->local; |
116 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 116 | struct sk_buff *skb; |
117 | struct ieee80211_mgmt *mgmt; | 117 | struct ieee80211_mgmt *mgmt; |
118 | u8 *pos; | 118 | u8 *pos, ie_len; |
119 | int ie_len; | 119 | int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) + |
120 | sizeof(mgmt->u.action.u.mesh_action); | ||
120 | 121 | ||
122 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | ||
123 | hdr_len + | ||
124 | 2 + 37); /* max HWMP IE */ | ||
121 | if (!skb) | 125 | if (!skb) |
122 | return -1; | 126 | return -1; |
123 | skb_reserve(skb, local->hw.extra_tx_headroom); | 127 | skb_reserve(skb, local->hw.extra_tx_headroom); |
124 | /* 25 is the size of the common mgmt part (24) plus the size of the | 128 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); |
125 | * common action part (1) | 129 | memset(mgmt, 0, hdr_len); |
126 | */ | ||
127 | mgmt = (struct ieee80211_mgmt *) | ||
128 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action)); | ||
129 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action)); | ||
130 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 130 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
131 | IEEE80211_STYPE_ACTION); | 131 | IEEE80211_STYPE_ACTION); |
132 | 132 | ||
@@ -240,20 +240,24 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, | |||
240 | struct ieee80211_sub_if_data *sdata) | 240 | struct ieee80211_sub_if_data *sdata) |
241 | { | 241 | { |
242 | struct ieee80211_local *local = sdata->local; | 242 | struct ieee80211_local *local = sdata->local; |
243 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 243 | struct sk_buff *skb; |
244 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
244 | struct ieee80211_mgmt *mgmt; | 245 | struct ieee80211_mgmt *mgmt; |
245 | u8 *pos; | 246 | u8 *pos, ie_len; |
246 | int ie_len; | 247 | int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) + |
248 | sizeof(mgmt->u.action.u.mesh_action); | ||
247 | 249 | ||
250 | if (time_before(jiffies, ifmsh->next_perr)) | ||
251 | return -EAGAIN; | ||
252 | |||
253 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | ||
254 | hdr_len + | ||
255 | 2 + 15 /* PERR IE */); | ||
248 | if (!skb) | 256 | if (!skb) |
249 | return -1; | 257 | return -1; |
250 | skb_reserve(skb, local->tx_headroom + local->hw.extra_tx_headroom); | 258 | skb_reserve(skb, local->tx_headroom + local->hw.extra_tx_headroom); |
251 | /* 25 is the size of the common mgmt part (24) plus the size of the | 259 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); |
252 | * common action part (1) | 260 | memset(mgmt, 0, hdr_len); |
253 | */ | ||
254 | mgmt = (struct ieee80211_mgmt *) | ||
255 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action)); | ||
256 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action)); | ||
257 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 261 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
258 | IEEE80211_STYPE_ACTION); | 262 | IEEE80211_STYPE_ACTION); |
259 | 263 | ||
@@ -290,6 +294,8 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, | |||
290 | 294 | ||
291 | /* see note in function header */ | 295 | /* see note in function header */ |
292 | prepare_frame_for_deferred_tx(sdata, skb); | 296 | prepare_frame_for_deferred_tx(sdata, skb); |
297 | ifmsh->next_perr = TU_TO_EXP_TIME( | ||
298 | ifmsh->mshcfg.dot11MeshHWMPperrMinInterval); | ||
293 | ieee80211_add_pending_skb(local, skb); | 299 | ieee80211_add_pending_skb(local, skb); |
294 | return 0; | 300 | return 0; |
295 | } | 301 | } |
@@ -393,15 +399,13 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
393 | orig_metric = PREQ_IE_METRIC(hwmp_ie); | 399 | orig_metric = PREQ_IE_METRIC(hwmp_ie); |
394 | break; | 400 | break; |
395 | case MPATH_PREP: | 401 | case MPATH_PREP: |
396 | /* Originator here refers to the MP that was the destination in | 402 | /* Originator here refers to the MP that was the target in the |
397 | * the Path Request. The draft refers to that MP as the | 403 | * Path Request. We divert from the nomenclature in the draft |
398 | * destination address, even though usually it is the origin of | ||
399 | * the PREP frame. We divert from the nomenclature in the draft | ||
400 | * so that we can easily use a single function to gather path | 404 | * so that we can easily use a single function to gather path |
401 | * information from both PREQ and PREP frames. | 405 | * information from both PREQ and PREP frames. |
402 | */ | 406 | */ |
403 | orig_addr = PREP_IE_ORIG_ADDR(hwmp_ie); | 407 | orig_addr = PREP_IE_TARGET_ADDR(hwmp_ie); |
404 | orig_sn = PREP_IE_ORIG_SN(hwmp_ie); | 408 | orig_sn = PREP_IE_TARGET_SN(hwmp_ie); |
405 | orig_lifetime = PREP_IE_LIFETIME(hwmp_ie); | 409 | orig_lifetime = PREP_IE_LIFETIME(hwmp_ie); |
406 | orig_metric = PREP_IE_METRIC(hwmp_ie); | 410 | orig_metric = PREP_IE_METRIC(hwmp_ie); |
407 | break; | 411 | break; |
@@ -562,9 +566,9 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
562 | ttl = ifmsh->mshcfg.element_ttl; | 566 | ttl = ifmsh->mshcfg.element_ttl; |
563 | if (ttl != 0) { | 567 | if (ttl != 0) { |
564 | mhwmp_dbg("replying to the PREQ"); | 568 | mhwmp_dbg("replying to the PREQ"); |
565 | mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr, | 569 | mesh_path_sel_frame_tx(MPATH_PREP, 0, orig_addr, |
566 | cpu_to_le32(target_sn), 0, orig_addr, | 570 | cpu_to_le32(orig_sn), 0, target_addr, |
567 | cpu_to_le32(orig_sn), mgmt->sa, 0, ttl, | 571 | cpu_to_le32(target_sn), mgmt->sa, 0, ttl, |
568 | cpu_to_le32(lifetime), cpu_to_le32(metric), | 572 | cpu_to_le32(lifetime), cpu_to_le32(metric), |
569 | 0, sdata); | 573 | 0, sdata); |
570 | } else | 574 | } else |
@@ -618,14 +622,8 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
618 | 622 | ||
619 | mhwmp_dbg("received PREP from %pM", PREP_IE_ORIG_ADDR(prep_elem)); | 623 | mhwmp_dbg("received PREP from %pM", PREP_IE_ORIG_ADDR(prep_elem)); |
620 | 624 | ||
621 | /* Note that we divert from the draft nomenclature and denominate | 625 | orig_addr = PREP_IE_ORIG_ADDR(prep_elem); |
622 | * destination to what the draft refers to as origininator. So in this | 626 | if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) |
623 | * function destnation refers to the final destination of the PREP, | ||
624 | * which corresponds with the originator of the PREQ which this PREP | ||
625 | * replies | ||
626 | */ | ||
627 | target_addr = PREP_IE_TARGET_ADDR(prep_elem); | ||
628 | if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) | ||
629 | /* destination, no forwarding required */ | 627 | /* destination, no forwarding required */ |
630 | return; | 628 | return; |
631 | 629 | ||
@@ -636,7 +634,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
636 | } | 634 | } |
637 | 635 | ||
638 | rcu_read_lock(); | 636 | rcu_read_lock(); |
639 | mpath = mesh_path_lookup(target_addr, sdata); | 637 | mpath = mesh_path_lookup(orig_addr, sdata); |
640 | if (mpath) | 638 | if (mpath) |
641 | spin_lock_bh(&mpath->state_lock); | 639 | spin_lock_bh(&mpath->state_lock); |
642 | else | 640 | else |
@@ -651,7 +649,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
651 | flags = PREP_IE_FLAGS(prep_elem); | 649 | flags = PREP_IE_FLAGS(prep_elem); |
652 | lifetime = PREP_IE_LIFETIME(prep_elem); | 650 | lifetime = PREP_IE_LIFETIME(prep_elem); |
653 | hopcount = PREP_IE_HOPCOUNT(prep_elem) + 1; | 651 | hopcount = PREP_IE_HOPCOUNT(prep_elem) + 1; |
654 | orig_addr = PREP_IE_ORIG_ADDR(prep_elem); | 652 | target_addr = PREP_IE_TARGET_ADDR(prep_elem); |
655 | target_sn = PREP_IE_TARGET_SN(prep_elem); | 653 | target_sn = PREP_IE_TARGET_SN(prep_elem); |
656 | orig_sn = PREP_IE_ORIG_SN(prep_elem); | 654 | orig_sn = PREP_IE_ORIG_SN(prep_elem); |
657 | 655 | ||
@@ -867,9 +865,20 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | |||
867 | return; | 865 | return; |
868 | } | 866 | } |
869 | 867 | ||
868 | spin_lock(&mpath->state_lock); | ||
869 | if (mpath->flags & MESH_PATH_REQ_QUEUED) { | ||
870 | spin_unlock(&mpath->state_lock); | ||
871 | spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); | ||
872 | kfree(preq_node); | ||
873 | return; | ||
874 | } | ||
875 | |||
870 | memcpy(preq_node->dst, mpath->dst, ETH_ALEN); | 876 | memcpy(preq_node->dst, mpath->dst, ETH_ALEN); |
871 | preq_node->flags = flags; | 877 | preq_node->flags = flags; |
872 | 878 | ||
879 | mpath->flags |= MESH_PATH_REQ_QUEUED; | ||
880 | spin_unlock(&mpath->state_lock); | ||
881 | |||
873 | list_add_tail(&preq_node->list, &ifmsh->preq_queue.list); | 882 | list_add_tail(&preq_node->list, &ifmsh->preq_queue.list); |
874 | ++ifmsh->preq_queue_len; | 883 | ++ifmsh->preq_queue_len; |
875 | spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); | 884 | spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); |
@@ -921,6 +930,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
921 | goto enddiscovery; | 930 | goto enddiscovery; |
922 | 931 | ||
923 | spin_lock_bh(&mpath->state_lock); | 932 | spin_lock_bh(&mpath->state_lock); |
933 | mpath->flags &= ~MESH_PATH_REQ_QUEUED; | ||
924 | if (preq_node->flags & PREQ_Q_F_START) { | 934 | if (preq_node->flags & PREQ_Q_F_START) { |
925 | if (mpath->flags & MESH_PATH_RESOLVING) { | 935 | if (mpath->flags & MESH_PATH_RESOLVING) { |
926 | spin_unlock_bh(&mpath->state_lock); | 936 | spin_unlock_bh(&mpath->state_lock); |
@@ -972,71 +982,97 @@ enddiscovery: | |||
972 | kfree(preq_node); | 982 | kfree(preq_node); |
973 | } | 983 | } |
974 | 984 | ||
975 | /** | 985 | /* mesh_nexthop_resolve - lookup next hop for given skb and start path |
976 | * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame | 986 | * discovery if no forwarding information is found. |
977 | * | 987 | * |
978 | * @skb: 802.11 frame to be sent | 988 | * @skb: 802.11 frame to be sent |
979 | * @sdata: network subif the frame will be sent through | 989 | * @sdata: network subif the frame will be sent through |
980 | * | 990 | * |
981 | * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is | 991 | * Returns: 0 if the next hop was found and -ENOENT if the frame was queued. |
982 | * found, the function will start a path discovery and queue the frame so it is | 992 | * skb is freeed here if no mpath could be allocated. |
983 | * sent when the path is resolved. This means the caller must not free the skb | ||
984 | * in this case. | ||
985 | */ | 993 | */ |
986 | int mesh_nexthop_lookup(struct sk_buff *skb, | 994 | int mesh_nexthop_resolve(struct sk_buff *skb, |
987 | struct ieee80211_sub_if_data *sdata) | 995 | struct ieee80211_sub_if_data *sdata) |
988 | { | 996 | { |
989 | struct sk_buff *skb_to_free = NULL; | ||
990 | struct mesh_path *mpath; | ||
991 | struct sta_info *next_hop; | ||
992 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 997 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
998 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
999 | struct mesh_path *mpath; | ||
1000 | struct sk_buff *skb_to_free = NULL; | ||
993 | u8 *target_addr = hdr->addr3; | 1001 | u8 *target_addr = hdr->addr3; |
994 | int err = 0; | 1002 | int err = 0; |
995 | 1003 | ||
996 | rcu_read_lock(); | 1004 | rcu_read_lock(); |
997 | mpath = mesh_path_lookup(target_addr, sdata); | 1005 | err = mesh_nexthop_lookup(skb, sdata); |
1006 | if (!err) | ||
1007 | goto endlookup; | ||
998 | 1008 | ||
1009 | /* no nexthop found, start resolving */ | ||
1010 | mpath = mesh_path_lookup(target_addr, sdata); | ||
999 | if (!mpath) { | 1011 | if (!mpath) { |
1000 | mesh_path_add(target_addr, sdata); | 1012 | mesh_path_add(target_addr, sdata); |
1001 | mpath = mesh_path_lookup(target_addr, sdata); | 1013 | mpath = mesh_path_lookup(target_addr, sdata); |
1002 | if (!mpath) { | 1014 | if (!mpath) { |
1003 | sdata->u.mesh.mshstats.dropped_frames_no_route++; | 1015 | mesh_path_discard_frame(skb, sdata); |
1004 | err = -ENOSPC; | 1016 | err = -ENOSPC; |
1005 | goto endlookup; | 1017 | goto endlookup; |
1006 | } | 1018 | } |
1007 | } | 1019 | } |
1008 | 1020 | ||
1009 | if (mpath->flags & MESH_PATH_ACTIVE) { | 1021 | if (!(mpath->flags & MESH_PATH_RESOLVING)) |
1010 | if (time_after(jiffies, | 1022 | mesh_queue_preq(mpath, PREQ_Q_F_START); |
1011 | mpath->exp_time - | 1023 | |
1012 | msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && | 1024 | if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN) |
1013 | !memcmp(sdata->vif.addr, hdr->addr4, ETH_ALEN) && | 1025 | skb_to_free = skb_dequeue(&mpath->frame_queue); |
1014 | !(mpath->flags & MESH_PATH_RESOLVING) && | ||
1015 | !(mpath->flags & MESH_PATH_FIXED)) { | ||
1016 | mesh_queue_preq(mpath, | ||
1017 | PREQ_Q_F_START | PREQ_Q_F_REFRESH); | ||
1018 | } | ||
1019 | next_hop = rcu_dereference(mpath->next_hop); | ||
1020 | if (next_hop) | ||
1021 | memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); | ||
1022 | else | ||
1023 | err = -ENOENT; | ||
1024 | } else { | ||
1025 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1026 | if (!(mpath->flags & MESH_PATH_RESOLVING)) { | ||
1027 | /* Start discovery only if it is not running yet */ | ||
1028 | mesh_queue_preq(mpath, PREQ_Q_F_START); | ||
1029 | } | ||
1030 | 1026 | ||
1031 | if (skb_queue_len(&mpath->frame_queue) >= | 1027 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
1032 | MESH_FRAME_QUEUE_LEN) | 1028 | ieee80211_set_qos_hdr(sdata, skb); |
1033 | skb_to_free = skb_dequeue(&mpath->frame_queue); | 1029 | skb_queue_tail(&mpath->frame_queue, skb); |
1030 | err = -ENOENT; | ||
1031 | if (skb_to_free) | ||
1032 | mesh_path_discard_frame(skb_to_free, sdata); | ||
1033 | |||
1034 | endlookup: | ||
1035 | rcu_read_unlock(); | ||
1036 | return err; | ||
1037 | } | ||
1038 | /** | ||
1039 | * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling | ||
1040 | * this function is considered "using" the associated mpath, so preempt a path | ||
1041 | * refresh if this mpath expires soon. | ||
1042 | * | ||
1043 | * @skb: 802.11 frame to be sent | ||
1044 | * @sdata: network subif the frame will be sent through | ||
1045 | * | ||
1046 | * Returns: 0 if the next hop was found. Nonzero otherwise. | ||
1047 | */ | ||
1048 | int mesh_nexthop_lookup(struct sk_buff *skb, | ||
1049 | struct ieee80211_sub_if_data *sdata) | ||
1050 | { | ||
1051 | struct mesh_path *mpath; | ||
1052 | struct sta_info *next_hop; | ||
1053 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
1054 | u8 *target_addr = hdr->addr3; | ||
1055 | int err = -ENOENT; | ||
1056 | |||
1057 | rcu_read_lock(); | ||
1058 | mpath = mesh_path_lookup(target_addr, sdata); | ||
1059 | |||
1060 | if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE)) | ||
1061 | goto endlookup; | ||
1062 | |||
1063 | if (time_after(jiffies, | ||
1064 | mpath->exp_time - | ||
1065 | msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && | ||
1066 | !memcmp(sdata->vif.addr, hdr->addr4, ETH_ALEN) && | ||
1067 | !(mpath->flags & MESH_PATH_RESOLVING) && | ||
1068 | !(mpath->flags & MESH_PATH_FIXED)) | ||
1069 | mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); | ||
1034 | 1070 | ||
1035 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 1071 | next_hop = rcu_dereference(mpath->next_hop); |
1036 | skb_queue_tail(&mpath->frame_queue, skb); | 1072 | if (next_hop) { |
1037 | if (skb_to_free) | 1073 | memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); |
1038 | mesh_path_discard_frame(skb_to_free, sdata); | 1074 | memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); |
1039 | err = -ENOENT; | 1075 | err = 0; |
1040 | } | 1076 | } |
1041 | 1077 | ||
1042 | endlookup: | 1078 | endlookup: |
@@ -1061,6 +1097,7 @@ void mesh_path_timer(unsigned long data) | |||
1061 | } else if (mpath->discovery_retries < max_preq_retries(sdata)) { | 1097 | } else if (mpath->discovery_retries < max_preq_retries(sdata)) { |
1062 | ++mpath->discovery_retries; | 1098 | ++mpath->discovery_retries; |
1063 | mpath->discovery_timeout *= 2; | 1099 | mpath->discovery_timeout *= 2; |
1100 | mpath->flags &= ~MESH_PATH_REQ_QUEUED; | ||
1064 | spin_unlock_bh(&mpath->state_lock); | 1101 | spin_unlock_bh(&mpath->state_lock); |
1065 | mesh_queue_preq(mpath, 0); | 1102 | mesh_queue_preq(mpath, 0); |
1066 | } else { | 1103 | } else { |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 7f54c5042235..edf167e3b8f3 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -69,8 +69,6 @@ static inline struct mesh_table *resize_dereference_mpp_paths(void) | |||
69 | lockdep_is_held(&pathtbl_resize_lock)); | 69 | lockdep_is_held(&pathtbl_resize_lock)); |
70 | } | 70 | } |
71 | 71 | ||
72 | static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath); | ||
73 | |||
74 | /* | 72 | /* |
75 | * CAREFUL -- "tbl" must not be an expression, | 73 | * CAREFUL -- "tbl" must not be an expression, |
76 | * in particular not an rcu_dereference(), since | 74 | * in particular not an rcu_dereference(), since |
@@ -213,7 +211,6 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) | |||
213 | struct ieee80211_hdr *hdr; | 211 | struct ieee80211_hdr *hdr; |
214 | struct sk_buff_head tmpq; | 212 | struct sk_buff_head tmpq; |
215 | unsigned long flags; | 213 | unsigned long flags; |
216 | struct ieee80211_sub_if_data *sdata = mpath->sdata; | ||
217 | 214 | ||
218 | rcu_assign_pointer(mpath->next_hop, sta); | 215 | rcu_assign_pointer(mpath->next_hop, sta); |
219 | 216 | ||
@@ -224,8 +221,7 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) | |||
224 | while ((skb = __skb_dequeue(&mpath->frame_queue)) != NULL) { | 221 | while ((skb = __skb_dequeue(&mpath->frame_queue)) != NULL) { |
225 | hdr = (struct ieee80211_hdr *) skb->data; | 222 | hdr = (struct ieee80211_hdr *) skb->data; |
226 | memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); | 223 | memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); |
227 | skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb)); | 224 | memcpy(hdr->addr2, mpath->sdata->vif.addr, ETH_ALEN); |
228 | ieee80211_set_qos_hdr(sdata, skb); | ||
229 | __skb_queue_tail(&tmpq, skb); | 225 | __skb_queue_tail(&tmpq, skb); |
230 | } | 226 | } |
231 | 227 | ||
@@ -269,6 +265,7 @@ static void prepare_for_gate(struct sk_buff *skb, char *dst_addr, | |||
269 | next_hop = rcu_dereference(gate_mpath->next_hop)->sta.addr; | 265 | next_hop = rcu_dereference(gate_mpath->next_hop)->sta.addr; |
270 | memcpy(hdr->addr1, next_hop, ETH_ALEN); | 266 | memcpy(hdr->addr1, next_hop, ETH_ALEN); |
271 | rcu_read_unlock(); | 267 | rcu_read_unlock(); |
268 | memcpy(hdr->addr2, gate_mpath->sdata->vif.addr, ETH_ALEN); | ||
272 | memcpy(hdr->addr3, dst_addr, ETH_ALEN); | 269 | memcpy(hdr->addr3, dst_addr, ETH_ALEN); |
273 | } | 270 | } |
274 | 271 | ||
@@ -423,21 +420,18 @@ static void mesh_gate_node_reclaim(struct rcu_head *rp) | |||
423 | } | 420 | } |
424 | 421 | ||
425 | /** | 422 | /** |
426 | * mesh_gate_add - mark mpath as path to a mesh gate and add to known_gates | 423 | * mesh_path_add_gate - add the given mpath to a mesh gate to our path table |
427 | * @mesh_tbl: table which contains known_gates list | 424 | * @mpath: gate path to add to table |
428 | * @mpath: mpath to known mesh gate | ||
429 | * | ||
430 | * Returns: 0 on success | ||
431 | * | ||
432 | */ | 425 | */ |
433 | static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath) | 426 | int mesh_path_add_gate(struct mesh_path *mpath) |
434 | { | 427 | { |
428 | struct mesh_table *tbl; | ||
435 | struct mpath_node *gate, *new_gate; | 429 | struct mpath_node *gate, *new_gate; |
436 | struct hlist_node *n; | 430 | struct hlist_node *n; |
437 | int err; | 431 | int err; |
438 | 432 | ||
439 | rcu_read_lock(); | 433 | rcu_read_lock(); |
440 | tbl = rcu_dereference(tbl); | 434 | tbl = rcu_dereference(mesh_paths); |
441 | 435 | ||
442 | hlist_for_each_entry_rcu(gate, n, tbl->known_gates, list) | 436 | hlist_for_each_entry_rcu(gate, n, tbl->known_gates, list) |
443 | if (gate->mpath == mpath) { | 437 | if (gate->mpath == mpath) { |
@@ -481,8 +475,6 @@ static int mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath) | |||
481 | struct mpath_node *gate; | 475 | struct mpath_node *gate; |
482 | struct hlist_node *p, *q; | 476 | struct hlist_node *p, *q; |
483 | 477 | ||
484 | tbl = rcu_dereference(tbl); | ||
485 | |||
486 | hlist_for_each_entry_safe(gate, p, q, tbl->known_gates, list) | 478 | hlist_for_each_entry_safe(gate, p, q, tbl->known_gates, list) |
487 | if (gate->mpath == mpath) { | 479 | if (gate->mpath == mpath) { |
488 | spin_lock_bh(&tbl->gates_lock); | 480 | spin_lock_bh(&tbl->gates_lock); |
@@ -501,16 +493,6 @@ static int mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath) | |||
501 | } | 493 | } |
502 | 494 | ||
503 | /** | 495 | /** |
504 | * | ||
505 | * mesh_path_add_gate - add the given mpath to a mesh gate to our path table | ||
506 | * @mpath: gate path to add to table | ||
507 | */ | ||
508 | int mesh_path_add_gate(struct mesh_path *mpath) | ||
509 | { | ||
510 | return mesh_gate_add(mesh_paths, mpath); | ||
511 | } | ||
512 | |||
513 | /** | ||
514 | * mesh_gate_num - number of gates known to this interface | 496 | * mesh_gate_num - number of gates known to this interface |
515 | * @sdata: subif data | 497 | * @sdata: subif data |
516 | */ | 498 | */ |
@@ -991,38 +973,11 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) | |||
991 | * @skb: frame to discard | 973 | * @skb: frame to discard |
992 | * @sdata: network subif the frame was to be sent through | 974 | * @sdata: network subif the frame was to be sent through |
993 | * | 975 | * |
994 | * If the frame was being forwarded from another MP, a PERR frame will be sent | ||
995 | * to the precursor. The precursor's address (i.e. the previous hop) was saved | ||
996 | * in addr1 of the frame-to-be-forwarded, and would only be overwritten once | ||
997 | * the destination is successfully resolved. | ||
998 | * | ||
999 | * Locking: the function must me called within a rcu_read_lock region | 976 | * Locking: the function must me called within a rcu_read_lock region |
1000 | */ | 977 | */ |
1001 | void mesh_path_discard_frame(struct sk_buff *skb, | 978 | void mesh_path_discard_frame(struct sk_buff *skb, |
1002 | struct ieee80211_sub_if_data *sdata) | 979 | struct ieee80211_sub_if_data *sdata) |
1003 | { | 980 | { |
1004 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
1005 | struct mesh_path *mpath; | ||
1006 | u32 sn = 0; | ||
1007 | __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD); | ||
1008 | |||
1009 | if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) { | ||
1010 | u8 *ra, *da; | ||
1011 | |||
1012 | da = hdr->addr3; | ||
1013 | ra = hdr->addr1; | ||
1014 | rcu_read_lock(); | ||
1015 | mpath = mesh_path_lookup(da, sdata); | ||
1016 | if (mpath) { | ||
1017 | spin_lock_bh(&mpath->state_lock); | ||
1018 | sn = ++mpath->sn; | ||
1019 | spin_unlock_bh(&mpath->state_lock); | ||
1020 | } | ||
1021 | rcu_read_unlock(); | ||
1022 | mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, skb->data, | ||
1023 | cpu_to_le32(sn), reason, ra, sdata); | ||
1024 | } | ||
1025 | |||
1026 | kfree_skb(skb); | 981 | kfree_skb(skb); |
1027 | sdata->u.mesh.mshstats.dropped_frames_no_route++; | 982 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
1028 | } | 983 | } |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 7e57f5d07f66..41ef1b476442 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -80,11 +80,15 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta) | |||
80 | * on it in the lifecycle management section! | 80 | * on it in the lifecycle management section! |
81 | */ | 81 | */ |
82 | static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | 82 | static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, |
83 | u8 *hw_addr, u32 rates) | 83 | u8 *hw_addr, u32 rates, |
84 | struct ieee802_11_elems *elems) | ||
84 | { | 85 | { |
85 | struct ieee80211_local *local = sdata->local; | 86 | struct ieee80211_local *local = sdata->local; |
87 | struct ieee80211_supported_band *sband; | ||
86 | struct sta_info *sta; | 88 | struct sta_info *sta; |
87 | 89 | ||
90 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | ||
91 | |||
88 | if (local->num_sta >= MESH_MAX_PLINKS) | 92 | if (local->num_sta >= MESH_MAX_PLINKS) |
89 | return NULL; | 93 | return NULL; |
90 | 94 | ||
@@ -92,10 +96,17 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
92 | if (!sta) | 96 | if (!sta) |
93 | return NULL; | 97 | return NULL; |
94 | 98 | ||
95 | set_sta_flag(sta, WLAN_STA_AUTH); | 99 | sta_info_move_state(sta, IEEE80211_STA_AUTH); |
96 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); | 100 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
101 | sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
102 | |||
97 | set_sta_flag(sta, WLAN_STA_WME); | 103 | set_sta_flag(sta, WLAN_STA_WME); |
104 | |||
98 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; | 105 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
106 | if (elems->ht_cap_elem) | ||
107 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | ||
108 | elems->ht_cap_elem, | ||
109 | &sta->sta.ht_cap); | ||
99 | rate_control_rate_init(sta); | 110 | rate_control_rate_init(sta); |
100 | 111 | ||
101 | return sta; | 112 | return sta; |
@@ -153,23 +164,31 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
153 | enum ieee80211_self_protected_actioncode action, | 164 | enum ieee80211_self_protected_actioncode action, |
154 | u8 *da, __le16 llid, __le16 plid, __le16 reason) { | 165 | u8 *da, __le16 llid, __le16 plid, __le16 reason) { |
155 | struct ieee80211_local *local = sdata->local; | 166 | struct ieee80211_local *local = sdata->local; |
156 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + | 167 | struct sk_buff *skb; |
157 | sdata->u.mesh.ie_len); | ||
158 | struct ieee80211_mgmt *mgmt; | 168 | struct ieee80211_mgmt *mgmt; |
159 | bool include_plid = false; | 169 | bool include_plid = false; |
160 | int ie_len = 4; | ||
161 | u16 peering_proto = 0; | 170 | u16 peering_proto = 0; |
162 | u8 *pos; | 171 | u8 *pos, ie_len = 4; |
163 | 172 | int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) + | |
173 | sizeof(mgmt->u.action.u.self_prot); | ||
174 | |||
175 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | ||
176 | hdr_len + | ||
177 | 2 + /* capability info */ | ||
178 | 2 + /* AID */ | ||
179 | 2 + 8 + /* supported rates */ | ||
180 | 2 + (IEEE80211_MAX_SUPP_RATES - 8) + | ||
181 | 2 + sdata->u.mesh.mesh_id_len + | ||
182 | 2 + sizeof(struct ieee80211_meshconf_ie) + | ||
183 | 2 + sizeof(struct ieee80211_ht_cap) + | ||
184 | 2 + sizeof(struct ieee80211_ht_info) + | ||
185 | 2 + 8 + /* peering IE */ | ||
186 | sdata->u.mesh.ie_len); | ||
164 | if (!skb) | 187 | if (!skb) |
165 | return -1; | 188 | return -1; |
166 | skb_reserve(skb, local->hw.extra_tx_headroom); | 189 | skb_reserve(skb, local->hw.extra_tx_headroom); |
167 | /* 25 is the size of the common mgmt part (24) plus the size of the | 190 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); |
168 | * common action part (1) | 191 | memset(mgmt, 0, hdr_len); |
169 | */ | ||
170 | mgmt = (struct ieee80211_mgmt *) | ||
171 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.self_prot)); | ||
172 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.self_prot)); | ||
173 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 192 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
174 | IEEE80211_STYPE_ACTION); | 193 | IEEE80211_STYPE_ACTION); |
175 | memcpy(mgmt->da, da, ETH_ALEN); | 194 | memcpy(mgmt->da, da, ETH_ALEN); |
@@ -235,6 +254,13 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
235 | memcpy(pos, &reason, 2); | 254 | memcpy(pos, &reason, 2); |
236 | pos += 2; | 255 | pos += 2; |
237 | } | 256 | } |
257 | |||
258 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { | ||
259 | if (mesh_add_ht_cap_ie(skb, sdata) || | ||
260 | mesh_add_ht_info_ie(skb, sdata)) | ||
261 | return -1; | ||
262 | } | ||
263 | |||
238 | if (mesh_add_vendor_ies(skb, sdata)) | 264 | if (mesh_add_vendor_ies(skb, sdata)) |
239 | return -1; | 265 | return -1; |
240 | 266 | ||
@@ -261,7 +287,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, | |||
261 | elems->ie_start, elems->total_len, | 287 | elems->ie_start, elems->total_len, |
262 | GFP_KERNEL); | 288 | GFP_KERNEL); |
263 | else | 289 | else |
264 | sta = mesh_plink_alloc(sdata, hw_addr, rates); | 290 | sta = mesh_plink_alloc(sdata, hw_addr, rates, elems); |
265 | if (!sta) | 291 | if (!sta) |
266 | return; | 292 | return; |
267 | if (sta_info_insert_rcu(sta)) { | 293 | if (sta_info_insert_rcu(sta)) { |
@@ -552,7 +578,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
552 | } | 578 | } |
553 | 579 | ||
554 | rates = ieee80211_sta_get_rates(local, &elems, rx_status->band); | 580 | rates = ieee80211_sta_get_rates(local, &elems, rx_status->band); |
555 | sta = mesh_plink_alloc(sdata, mgmt->sa, rates); | 581 | sta = mesh_plink_alloc(sdata, mgmt->sa, rates, &elems); |
556 | if (!sta) { | 582 | if (!sta) { |
557 | mpl_dbg("Mesh plink error: plink table full\n"); | 583 | mpl_dbg("Mesh plink error: plink table full\n"); |
558 | return; | 584 | return; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b1b1bb368f70..ecb4c84c1bb3 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -209,6 +209,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
209 | channel_type = NL80211_CHAN_HT20; | 209 | channel_type = NL80211_CHAN_HT20; |
210 | 210 | ||
211 | if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && | 211 | if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && |
212 | !ieee80111_cfg_override_disables_ht40(sdata) && | ||
212 | (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && | 213 | (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && |
213 | (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { | 214 | (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { |
214 | switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 215 | switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
@@ -818,7 +819,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
818 | } | 819 | } |
819 | 820 | ||
820 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && | 821 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && |
821 | (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { | 822 | !(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) { |
822 | netif_tx_stop_all_queues(sdata->dev); | 823 | netif_tx_stop_all_queues(sdata->dev); |
823 | 824 | ||
824 | if (drv_tx_frames_pending(local)) | 825 | if (drv_tx_frames_pending(local)) |
@@ -1120,6 +1121,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1120 | 1121 | ||
1121 | /* on the next assoc, re-program HT parameters */ | 1122 | /* on the next assoc, re-program HT parameters */ |
1122 | sdata->ht_opmode_valid = false; | 1123 | sdata->ht_opmode_valid = false; |
1124 | memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); | ||
1125 | memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); | ||
1123 | 1126 | ||
1124 | local->power_constr_level = 0; | 1127 | local->power_constr_level = 0; |
1125 | 1128 | ||
@@ -1359,9 +1362,6 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
1359 | ieee80211_set_disassoc(sdata, true, true); | 1362 | ieee80211_set_disassoc(sdata, true, true); |
1360 | mutex_unlock(&ifmgd->mtx); | 1363 | mutex_unlock(&ifmgd->mtx); |
1361 | 1364 | ||
1362 | mutex_lock(&local->mtx); | ||
1363 | ieee80211_recalc_idle(local); | ||
1364 | mutex_unlock(&local->mtx); | ||
1365 | /* | 1365 | /* |
1366 | * must be outside lock due to cfg80211, | 1366 | * must be outside lock due to cfg80211, |
1367 | * but that's not a problem. | 1367 | * but that's not a problem. |
@@ -1370,6 +1370,10 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
1370 | IEEE80211_STYPE_DEAUTH, | 1370 | IEEE80211_STYPE_DEAUTH, |
1371 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | 1371 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, |
1372 | NULL, true); | 1372 | NULL, true); |
1373 | |||
1374 | mutex_lock(&local->mtx); | ||
1375 | ieee80211_recalc_idle(local); | ||
1376 | mutex_unlock(&local->mtx); | ||
1373 | } | 1377 | } |
1374 | 1378 | ||
1375 | void ieee80211_beacon_connection_loss_work(struct work_struct *work) | 1379 | void ieee80211_beacon_connection_loss_work(struct work_struct *work) |
@@ -1377,6 +1381,16 @@ void ieee80211_beacon_connection_loss_work(struct work_struct *work) | |||
1377 | struct ieee80211_sub_if_data *sdata = | 1381 | struct ieee80211_sub_if_data *sdata = |
1378 | container_of(work, struct ieee80211_sub_if_data, | 1382 | container_of(work, struct ieee80211_sub_if_data, |
1379 | u.mgd.beacon_connection_loss_work); | 1383 | u.mgd.beacon_connection_loss_work); |
1384 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1385 | struct sta_info *sta; | ||
1386 | |||
1387 | if (ifmgd->associated) { | ||
1388 | rcu_read_lock(); | ||
1389 | sta = sta_info_get(sdata, ifmgd->bssid); | ||
1390 | if (sta) | ||
1391 | sta->beacon_loss_count++; | ||
1392 | rcu_read_unlock(); | ||
1393 | } | ||
1380 | 1394 | ||
1381 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | 1395 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) |
1382 | __ieee80211_connection_loss(sdata); | 1396 | __ieee80211_connection_loss(sdata); |
@@ -1468,6 +1482,47 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1468 | return RX_MGMT_CFG80211_DISASSOC; | 1482 | return RX_MGMT_CFG80211_DISASSOC; |
1469 | } | 1483 | } |
1470 | 1484 | ||
1485 | static void ieee80211_get_rates(struct ieee80211_supported_band *sband, | ||
1486 | u8 *supp_rates, unsigned int supp_rates_len, | ||
1487 | u32 *rates, u32 *basic_rates, | ||
1488 | bool *have_higher_than_11mbit, | ||
1489 | int *min_rate, int *min_rate_index) | ||
1490 | { | ||
1491 | int i, j; | ||
1492 | |||
1493 | for (i = 0; i < supp_rates_len; i++) { | ||
1494 | int rate = (supp_rates[i] & 0x7f) * 5; | ||
1495 | bool is_basic = !!(supp_rates[i] & 0x80); | ||
1496 | |||
1497 | if (rate > 110) | ||
1498 | *have_higher_than_11mbit = true; | ||
1499 | |||
1500 | /* | ||
1501 | * BSS_MEMBERSHIP_SELECTOR_HT_PHY is defined in 802.11n-2009 | ||
1502 | * 7.3.2.2 as a magic value instead of a rate. Hence, skip it. | ||
1503 | * | ||
1504 | * Note: Even through the membership selector and the basic | ||
1505 | * rate flag share the same bit, they are not exactly | ||
1506 | * the same. | ||
1507 | */ | ||
1508 | if (!!(supp_rates[i] & 0x80) && | ||
1509 | (supp_rates[i] & 0x7f) == BSS_MEMBERSHIP_SELECTOR_HT_PHY) | ||
1510 | continue; | ||
1511 | |||
1512 | for (j = 0; j < sband->n_bitrates; j++) { | ||
1513 | if (sband->bitrates[j].bitrate == rate) { | ||
1514 | *rates |= BIT(j); | ||
1515 | if (is_basic) | ||
1516 | *basic_rates |= BIT(j); | ||
1517 | if (rate < *min_rate) { | ||
1518 | *min_rate = rate; | ||
1519 | *min_rate_index = j; | ||
1520 | } | ||
1521 | break; | ||
1522 | } | ||
1523 | } | ||
1524 | } | ||
1525 | } | ||
1471 | 1526 | ||
1472 | static bool ieee80211_assoc_success(struct ieee80211_work *wk, | 1527 | static bool ieee80211_assoc_success(struct ieee80211_work *wk, |
1473 | struct ieee80211_mgmt *mgmt, size_t len) | 1528 | struct ieee80211_mgmt *mgmt, size_t len) |
@@ -1484,7 +1539,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1484 | struct ieee802_11_elems elems; | 1539 | struct ieee802_11_elems elems; |
1485 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | 1540 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; |
1486 | u32 changed = 0; | 1541 | u32 changed = 0; |
1487 | int i, j, err; | 1542 | int err; |
1488 | bool have_higher_than_11mbit = false; | 1543 | bool have_higher_than_11mbit = false; |
1489 | u16 ap_ht_cap_flags; | 1544 | u16 ap_ht_cap_flags; |
1490 | int min_rate = INT_MAX, min_rate_index = -1; | 1545 | int min_rate = INT_MAX, min_rate_index = -1; |
@@ -1532,57 +1587,23 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1532 | return false; | 1587 | return false; |
1533 | } | 1588 | } |
1534 | 1589 | ||
1535 | set_sta_flag(sta, WLAN_STA_AUTH); | 1590 | sta_info_move_state(sta, IEEE80211_STA_AUTH); |
1536 | set_sta_flag(sta, WLAN_STA_ASSOC); | 1591 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
1537 | set_sta_flag(sta, WLAN_STA_ASSOC_AP); | ||
1538 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | 1592 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) |
1539 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); | 1593 | sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); |
1540 | 1594 | ||
1541 | rates = 0; | 1595 | rates = 0; |
1542 | basic_rates = 0; | 1596 | basic_rates = 0; |
1543 | sband = local->hw.wiphy->bands[wk->chan->band]; | 1597 | sband = local->hw.wiphy->bands[wk->chan->band]; |
1544 | 1598 | ||
1545 | for (i = 0; i < elems.supp_rates_len; i++) { | 1599 | ieee80211_get_rates(sband, elems.supp_rates, elems.supp_rates_len, |
1546 | int rate = (elems.supp_rates[i] & 0x7f) * 5; | 1600 | &rates, &basic_rates, &have_higher_than_11mbit, |
1547 | bool is_basic = !!(elems.supp_rates[i] & 0x80); | 1601 | &min_rate, &min_rate_index); |
1548 | 1602 | ||
1549 | if (rate > 110) | 1603 | ieee80211_get_rates(sband, elems.ext_supp_rates, |
1550 | have_higher_than_11mbit = true; | 1604 | elems.ext_supp_rates_len, &rates, &basic_rates, |
1551 | 1605 | &have_higher_than_11mbit, | |
1552 | for (j = 0; j < sband->n_bitrates; j++) { | 1606 | &min_rate, &min_rate_index); |
1553 | if (sband->bitrates[j].bitrate == rate) { | ||
1554 | rates |= BIT(j); | ||
1555 | if (is_basic) | ||
1556 | basic_rates |= BIT(j); | ||
1557 | if (rate < min_rate) { | ||
1558 | min_rate = rate; | ||
1559 | min_rate_index = j; | ||
1560 | } | ||
1561 | break; | ||
1562 | } | ||
1563 | } | ||
1564 | } | ||
1565 | |||
1566 | for (i = 0; i < elems.ext_supp_rates_len; i++) { | ||
1567 | int rate = (elems.ext_supp_rates[i] & 0x7f) * 5; | ||
1568 | bool is_basic = !!(elems.ext_supp_rates[i] & 0x80); | ||
1569 | |||
1570 | if (rate > 110) | ||
1571 | have_higher_than_11mbit = true; | ||
1572 | |||
1573 | for (j = 0; j < sband->n_bitrates; j++) { | ||
1574 | if (sband->bitrates[j].bitrate == rate) { | ||
1575 | rates |= BIT(j); | ||
1576 | if (is_basic) | ||
1577 | basic_rates |= BIT(j); | ||
1578 | if (rate < min_rate) { | ||
1579 | min_rate = rate; | ||
1580 | min_rate_index = j; | ||
1581 | } | ||
1582 | break; | ||
1583 | } | ||
1584 | } | ||
1585 | } | ||
1586 | 1607 | ||
1587 | /* | 1608 | /* |
1588 | * some buggy APs don't advertise basic_rates. use the lowest | 1609 | * some buggy APs don't advertise basic_rates. use the lowest |
@@ -1605,7 +1626,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1605 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | 1626 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; |
1606 | 1627 | ||
1607 | if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 1628 | if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
1608 | ieee80211_ht_cap_ie_to_sta_ht_cap(sband, | 1629 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
1609 | elems.ht_cap_elem, &sta->sta.ht_cap); | 1630 | elems.ht_cap_elem, &sta->sta.ht_cap); |
1610 | 1631 | ||
1611 | ap_ht_cap_flags = sta->sta.ht_cap.cap; | 1632 | ap_ht_cap_flags = sta->sta.ht_cap.cap; |
@@ -1974,7 +1995,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1974 | 1995 | ||
1975 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1996 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
1976 | 1997 | ||
1977 | ieee80211_ht_cap_ie_to_sta_ht_cap(sband, | 1998 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
1978 | elems.ht_cap_elem, &sta->sta.ht_cap); | 1999 | elems.ht_cap_elem, &sta->sta.ht_cap); |
1979 | 2000 | ||
1980 | ap_ht_cap_flags = sta->sta.ht_cap.cap; | 2001 | ap_ht_cap_flags = sta->sta.ht_cap.cap; |
@@ -2128,9 +2149,6 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | |||
2128 | 2149 | ||
2129 | ieee80211_set_disassoc(sdata, true, true); | 2150 | ieee80211_set_disassoc(sdata, true, true); |
2130 | mutex_unlock(&ifmgd->mtx); | 2151 | mutex_unlock(&ifmgd->mtx); |
2131 | mutex_lock(&local->mtx); | ||
2132 | ieee80211_recalc_idle(local); | ||
2133 | mutex_unlock(&local->mtx); | ||
2134 | /* | 2152 | /* |
2135 | * must be outside lock due to cfg80211, | 2153 | * must be outside lock due to cfg80211, |
2136 | * but that's not a problem. | 2154 | * but that's not a problem. |
@@ -2138,6 +2156,11 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | |||
2138 | ieee80211_send_deauth_disassoc(sdata, bssid, | 2156 | ieee80211_send_deauth_disassoc(sdata, bssid, |
2139 | IEEE80211_STYPE_DEAUTH, reason, | 2157 | IEEE80211_STYPE_DEAUTH, reason, |
2140 | NULL, true); | 2158 | NULL, true); |
2159 | |||
2160 | mutex_lock(&local->mtx); | ||
2161 | ieee80211_recalc_idle(local); | ||
2162 | mutex_unlock(&local->mtx); | ||
2163 | |||
2141 | mutex_lock(&ifmgd->mtx); | 2164 | mutex_lock(&ifmgd->mtx); |
2142 | } | 2165 | } |
2143 | 2166 | ||
@@ -2358,6 +2381,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2358 | (unsigned long) sdata); | 2381 | (unsigned long) sdata); |
2359 | 2382 | ||
2360 | ifmgd->flags = 0; | 2383 | ifmgd->flags = 0; |
2384 | ifmgd->powersave = sdata->wdev.ps; | ||
2361 | 2385 | ||
2362 | mutex_init(&ifmgd->mtx); | 2386 | mutex_init(&ifmgd->mtx); |
2363 | 2387 | ||
@@ -2632,6 +2656,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2632 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 2656 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
2633 | 2657 | ||
2634 | 2658 | ||
2659 | if (req->flags & ASSOC_REQ_DISABLE_HT) | ||
2660 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | ||
2661 | |||
2662 | memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); | ||
2663 | memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, | ||
2664 | sizeof(ifmgd->ht_capa_mask)); | ||
2665 | |||
2635 | if (req->ie && req->ie_len) { | 2666 | if (req->ie && req->ie_len) { |
2636 | memcpy(wk->ie, req->ie, req->ie_len); | 2667 | memcpy(wk->ie, req->ie, req->ie_len); |
2637 | wk->ie_len = req->ie_len; | 2668 | wk->ie_len = req->ie_len; |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 3d414411a96e..f054e94901a2 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -138,31 +138,16 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, | |||
138 | mutex_unlock(&local->iflist_mtx); | 138 | mutex_unlock(&local->iflist_mtx); |
139 | } | 139 | } |
140 | 140 | ||
141 | void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, | ||
142 | bool tell_ap) | ||
143 | { | ||
144 | struct ieee80211_sub_if_data *sdata; | ||
145 | |||
146 | mutex_lock(&local->iflist_mtx); | ||
147 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
148 | if (!ieee80211_sdata_running(sdata)) | ||
149 | continue; | ||
150 | |||
151 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
152 | sdata->u.mgd.associated) | ||
153 | ieee80211_offchannel_ps_enable(sdata, tell_ap); | ||
154 | } | ||
155 | mutex_unlock(&local->iflist_mtx); | ||
156 | } | ||
157 | |||
158 | void ieee80211_offchannel_return(struct ieee80211_local *local, | 141 | void ieee80211_offchannel_return(struct ieee80211_local *local, |
159 | bool enable_beaconing, | ||
160 | bool offchannel_ps_disable) | 142 | bool offchannel_ps_disable) |
161 | { | 143 | { |
162 | struct ieee80211_sub_if_data *sdata; | 144 | struct ieee80211_sub_if_data *sdata; |
163 | 145 | ||
164 | mutex_lock(&local->iflist_mtx); | 146 | mutex_lock(&local->iflist_mtx); |
165 | list_for_each_entry(sdata, &local->interfaces, list) { | 147 | list_for_each_entry(sdata, &local->interfaces, list) { |
148 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) | ||
149 | clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | ||
150 | |||
166 | if (!ieee80211_sdata_running(sdata)) | 151 | if (!ieee80211_sdata_running(sdata)) |
167 | continue; | 152 | continue; |
168 | 153 | ||
@@ -174,7 +159,6 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | |||
174 | } | 159 | } |
175 | 160 | ||
176 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { | 161 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { |
177 | clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | ||
178 | /* | 162 | /* |
179 | * This may wake up queues even though the driver | 163 | * This may wake up queues even though the driver |
180 | * currently has them stopped. This is not very | 164 | * currently has them stopped. This is not very |
@@ -188,11 +172,9 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | |||
188 | netif_tx_wake_all_queues(sdata->dev); | 172 | netif_tx_wake_all_queues(sdata->dev); |
189 | } | 173 | } |
190 | 174 | ||
191 | /* Check to see if we should re-enable beaconing */ | 175 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
192 | if (enable_beaconing && | 176 | sdata->vif.type == NL80211_IFTYPE_ADHOC || |
193 | (sdata->vif.type == NL80211_IFTYPE_AP || | 177 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) |
194 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | ||
195 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT)) | ||
196 | ieee80211_bss_info_change_notify( | 178 | ieee80211_bss_info_change_notify( |
197 | sdata, BSS_CHANGED_BEACON_ENABLED); | 179 | sdata, BSS_CHANGED_BEACON_ENABLED); |
198 | } | 180 | } |
@@ -212,8 +194,6 @@ static void ieee80211_hw_roc_start(struct work_struct *work) | |||
212 | return; | 194 | return; |
213 | } | 195 | } |
214 | 196 | ||
215 | ieee80211_recalc_idle(local); | ||
216 | |||
217 | if (local->hw_roc_skb) { | 197 | if (local->hw_roc_skb) { |
218 | sdata = IEEE80211_DEV_TO_SUB_IF(local->hw_roc_dev); | 198 | sdata = IEEE80211_DEV_TO_SUB_IF(local->hw_roc_dev); |
219 | ieee80211_tx_skb(sdata, local->hw_roc_skb); | 199 | ieee80211_tx_skb(sdata, local->hw_roc_skb); |
@@ -227,6 +207,8 @@ static void ieee80211_hw_roc_start(struct work_struct *work) | |||
227 | GFP_KERNEL); | 207 | GFP_KERNEL); |
228 | } | 208 | } |
229 | 209 | ||
210 | ieee80211_recalc_idle(local); | ||
211 | |||
230 | mutex_unlock(&local->mtx); | 212 | mutex_unlock(&local->mtx); |
231 | } | 213 | } |
232 | 214 | ||
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 9ee7164b207c..596efaf50e09 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -125,7 +125,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
125 | ieee80211_bss_info_change_notify(sdata, | 125 | ieee80211_bss_info_change_notify(sdata, |
126 | BSS_CHANGED_BEACON_ENABLED); | 126 | BSS_CHANGED_BEACON_ENABLED); |
127 | 127 | ||
128 | drv_remove_interface(local, &sdata->vif); | 128 | drv_remove_interface(local, sdata); |
129 | } | 129 | } |
130 | 130 | ||
131 | /* stop hardware - this must stop RX */ | 131 | /* stop hardware - this must stop RX */ |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 58a89554b788..b39dda523f39 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -334,8 +334,8 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
334 | 334 | ||
335 | 335 | ||
336 | static void | 336 | static void |
337 | calc_rate_durations(struct minstrel_sta_info *mi, struct ieee80211_local *local, | 337 | calc_rate_durations(struct ieee80211_local *local, struct minstrel_rate *d, |
338 | struct minstrel_rate *d, struct ieee80211_rate *rate) | 338 | struct ieee80211_rate *rate) |
339 | { | 339 | { |
340 | int erp = !!(rate->flags & IEEE80211_RATE_ERP_G); | 340 | int erp = !!(rate->flags & IEEE80211_RATE_ERP_G); |
341 | 341 | ||
@@ -402,8 +402,7 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
402 | 402 | ||
403 | mr->rix = i; | 403 | mr->rix = i; |
404 | mr->bitrate = sband->bitrates[i].bitrate / 5; | 404 | mr->bitrate = sband->bitrates[i].bitrate / 5; |
405 | calc_rate_durations(mi, local, mr, | 405 | calc_rate_durations(local, mr, &sband->bitrates[i]); |
406 | &sband->bitrates[i]); | ||
407 | 406 | ||
408 | /* calculate maximum number of retransmissions before | 407 | /* calculate maximum number of retransmissions before |
409 | * fallback (based on maximum segment size) */ | 408 | * fallback (based on maximum segment size) */ |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index cdb28535716b..ff5f7b84e825 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -36,8 +36,17 @@ | |||
36 | /* Transmit duration for the raw data part of an average sized packet */ | 36 | /* Transmit duration for the raw data part of an average sized packet */ |
37 | #define MCS_DURATION(streams, sgi, bps) MCS_SYMBOL_TIME(sgi, MCS_NSYMS((streams) * (bps))) | 37 | #define MCS_DURATION(streams, sgi, bps) MCS_SYMBOL_TIME(sgi, MCS_NSYMS((streams) * (bps))) |
38 | 38 | ||
39 | /* | ||
40 | * Define group sort order: HT40 -> SGI -> #streams | ||
41 | */ | ||
42 | #define GROUP_IDX(_streams, _sgi, _ht40) \ | ||
43 | MINSTREL_MAX_STREAMS * 2 * _ht40 + \ | ||
44 | MINSTREL_MAX_STREAMS * _sgi + \ | ||
45 | _streams - 1 | ||
46 | |||
39 | /* MCS rate information for an MCS group */ | 47 | /* MCS rate information for an MCS group */ |
40 | #define MCS_GROUP(_streams, _sgi, _ht40) { \ | 48 | #define MCS_GROUP(_streams, _sgi, _ht40) \ |
49 | [GROUP_IDX(_streams, _sgi, _ht40)] = { \ | ||
41 | .streams = _streams, \ | 50 | .streams = _streams, \ |
42 | .flags = \ | 51 | .flags = \ |
43 | (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \ | 52 | (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \ |
@@ -58,6 +67,9 @@ | |||
58 | * To enable sufficiently targeted rate sampling, MCS rates are divided into | 67 | * To enable sufficiently targeted rate sampling, MCS rates are divided into |
59 | * groups, based on the number of streams and flags (HT40, SGI) that they | 68 | * groups, based on the number of streams and flags (HT40, SGI) that they |
60 | * use. | 69 | * use. |
70 | * | ||
71 | * Sortorder has to be fixed for GROUP_IDX macro to be applicable: | ||
72 | * HT40 -> SGI -> #streams | ||
61 | */ | 73 | */ |
62 | const struct mcs_group minstrel_mcs_groups[] = { | 74 | const struct mcs_group minstrel_mcs_groups[] = { |
63 | MCS_GROUP(1, 0, 0), | 75 | MCS_GROUP(1, 0, 0), |
@@ -102,21 +114,9 @@ minstrel_ewma(int old, int new, int weight) | |||
102 | static int | 114 | static int |
103 | minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate) | 115 | minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate) |
104 | { | 116 | { |
105 | int streams = (rate->idx / MCS_GROUP_RATES) + 1; | 117 | return GROUP_IDX((rate->idx / MCS_GROUP_RATES) + 1, |
106 | u32 flags = IEEE80211_TX_RC_SHORT_GI | IEEE80211_TX_RC_40_MHZ_WIDTH; | 118 | !!(rate->flags & IEEE80211_TX_RC_SHORT_GI), |
107 | int i; | 119 | !!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)); |
108 | |||
109 | for (i = 0; i < ARRAY_SIZE(minstrel_mcs_groups); i++) { | ||
110 | if (minstrel_mcs_groups[i].streams != streams) | ||
111 | continue; | ||
112 | if (minstrel_mcs_groups[i].flags != (rate->flags & flags)) | ||
113 | continue; | ||
114 | |||
115 | return i; | ||
116 | } | ||
117 | |||
118 | WARN_ON(1); | ||
119 | return 0; | ||
120 | } | 120 | } |
121 | 121 | ||
122 | static inline struct minstrel_rate_stats * | 122 | static inline struct minstrel_rate_stats * |
@@ -130,7 +130,7 @@ minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index) | |||
130 | * Recalculate success probabilities and counters for a rate using EWMA | 130 | * Recalculate success probabilities and counters for a rate using EWMA |
131 | */ | 131 | */ |
132 | static void | 132 | static void |
133 | minstrel_calc_rate_ewma(struct minstrel_priv *mp, struct minstrel_rate_stats *mr) | 133 | minstrel_calc_rate_ewma(struct minstrel_rate_stats *mr) |
134 | { | 134 | { |
135 | if (unlikely(mr->attempts > 0)) { | 135 | if (unlikely(mr->attempts > 0)) { |
136 | mr->sample_skipped = 0; | 136 | mr->sample_skipped = 0; |
@@ -156,8 +156,7 @@ minstrel_calc_rate_ewma(struct minstrel_priv *mp, struct minstrel_rate_stats *mr | |||
156 | * the expected number of retransmissions and their expected length | 156 | * the expected number of retransmissions and their expected length |
157 | */ | 157 | */ |
158 | static void | 158 | static void |
159 | minstrel_ht_calc_tp(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | 159 | minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate) |
160 | int group, int rate) | ||
161 | { | 160 | { |
162 | struct minstrel_rate_stats *mr; | 161 | struct minstrel_rate_stats *mr; |
163 | unsigned int usecs; | 162 | unsigned int usecs; |
@@ -226,8 +225,8 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
226 | mr = &mg->rates[i]; | 225 | mr = &mg->rates[i]; |
227 | mr->retry_updated = false; | 226 | mr->retry_updated = false; |
228 | index = MCS_GROUP_RATES * group + i; | 227 | index = MCS_GROUP_RATES * group + i; |
229 | minstrel_calc_rate_ewma(mp, mr); | 228 | minstrel_calc_rate_ewma(mr); |
230 | minstrel_ht_calc_tp(mp, mi, group, i); | 229 | minstrel_ht_calc_tp(mi, group, i); |
231 | 230 | ||
232 | if (!mr->cur_tp) | 231 | if (!mr->cur_tp) |
233 | continue; | 232 | continue; |
@@ -300,10 +299,10 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
300 | static bool | 299 | static bool |
301 | minstrel_ht_txstat_valid(struct ieee80211_tx_rate *rate) | 300 | minstrel_ht_txstat_valid(struct ieee80211_tx_rate *rate) |
302 | { | 301 | { |
303 | if (!rate->count) | 302 | if (rate->idx < 0) |
304 | return false; | 303 | return false; |
305 | 304 | ||
306 | if (rate->idx < 0) | 305 | if (!rate->count) |
307 | return false; | 306 | return false; |
308 | 307 | ||
309 | return !!(rate->flags & IEEE80211_TX_RC_MCS); | 308 | return !!(rate->flags & IEEE80211_TX_RC_MCS); |
@@ -357,7 +356,7 @@ minstrel_downgrade_rate(struct minstrel_ht_sta *mi, unsigned int *idx, | |||
357 | } | 356 | } |
358 | 357 | ||
359 | static void | 358 | static void |
360 | minstrel_aggr_check(struct minstrel_priv *mp, struct ieee80211_sta *pubsta, struct sk_buff *skb) | 359 | minstrel_aggr_check(struct ieee80211_sta *pubsta, struct sk_buff *skb) |
361 | { | 360 | { |
362 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 361 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
363 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | 362 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
@@ -455,7 +454,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
455 | if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) { | 454 | if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) { |
456 | minstrel_ht_update_stats(mp, mi); | 455 | minstrel_ht_update_stats(mp, mi); |
457 | if (!(info->flags & IEEE80211_TX_CTL_AMPDU)) | 456 | if (!(info->flags & IEEE80211_TX_CTL_AMPDU)) |
458 | minstrel_aggr_check(mp, sta, skb); | 457 | minstrel_aggr_check(sta, skb); |
459 | } | 458 | } |
460 | } | 459 | } |
461 | 460 | ||
@@ -515,7 +514,6 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | |||
515 | static void | 514 | static void |
516 | minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | 515 | minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, |
517 | struct ieee80211_tx_rate *rate, int index, | 516 | struct ieee80211_tx_rate *rate, int index, |
518 | struct ieee80211_tx_rate_control *txrc, | ||
519 | bool sample, bool rtscts) | 517 | bool sample, bool rtscts) |
520 | { | 518 | { |
521 | const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; | 519 | const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; |
@@ -628,11 +626,11 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
628 | if (sample_idx >= 0) { | 626 | if (sample_idx >= 0) { |
629 | sample = true; | 627 | sample = true; |
630 | minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx, | 628 | minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx, |
631 | txrc, true, false); | 629 | true, false); |
632 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | 630 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
633 | } else { | 631 | } else { |
634 | minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate, | 632 | minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate, |
635 | txrc, false, false); | 633 | false, false); |
636 | } | 634 | } |
637 | 635 | ||
638 | if (mp->hw->max_rates >= 3) { | 636 | if (mp->hw->max_rates >= 3) { |
@@ -643,13 +641,13 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
643 | */ | 641 | */ |
644 | if (sample_idx >= 0) | 642 | if (sample_idx >= 0) |
645 | minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate, | 643 | minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate, |
646 | txrc, false, false); | 644 | false, false); |
647 | else | 645 | else |
648 | minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2, | 646 | minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2, |
649 | txrc, false, true); | 647 | false, true); |
650 | 648 | ||
651 | minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate, | 649 | minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate, |
652 | txrc, false, !sample); | 650 | false, !sample); |
653 | 651 | ||
654 | ar[3].count = 0; | 652 | ar[3].count = 0; |
655 | ar[3].idx = -1; | 653 | ar[3].idx = -1; |
@@ -660,7 +658,7 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
660 | * max_tp_rate -> max_prob_rate by default. | 658 | * max_tp_rate -> max_prob_rate by default. |
661 | */ | 659 | */ |
662 | minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate, | 660 | minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate, |
663 | txrc, false, !sample); | 661 | false, !sample); |
664 | 662 | ||
665 | ar[2].count = 0; | 663 | ar[2].count = 0; |
666 | ar[2].idx = -1; | 664 | ar[2].idx = -1; |
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index aeda65466f3e..502d3ecc4a79 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -318,7 +318,7 @@ rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
318 | rinfo[i].diff = i * pinfo->norm_offset; | 318 | rinfo[i].diff = i * pinfo->norm_offset; |
319 | } | 319 | } |
320 | for (i = 1; i < sband->n_bitrates; i++) { | 320 | for (i = 1; i < sband->n_bitrates; i++) { |
321 | s = 0; | 321 | s = false; |
322 | for (j = 0; j < sband->n_bitrates - i; j++) | 322 | for (j = 0; j < sband->n_bitrates - i; j++) |
323 | if (unlikely(sband->bitrates[rinfo[j].index].bitrate > | 323 | if (unlikely(sband->bitrates[rinfo[j].index].bitrate > |
324 | sband->bitrates[rinfo[j + 1].index].bitrate)) { | 324 | sband->bitrates[rinfo[j + 1].index].bitrate)) { |
@@ -327,7 +327,7 @@ rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
327 | rinfo[j + 1].index = tmp; | 327 | rinfo[j + 1].index = tmp; |
328 | rinfo[rinfo[j].index].rev_index = j; | 328 | rinfo[rinfo[j].index].rev_index = j; |
329 | rinfo[rinfo[j + 1].index].rev_index = j + 1; | 329 | rinfo[rinfo[j + 1].index].rev_index = j + 1; |
330 | s = 1; | 330 | s = true; |
331 | } | 331 | } |
332 | if (!s) | 332 | if (!s) |
333 | break; | 333 | break; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fb123e2e081a..f407427c642f 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "wpa.h" | 28 | #include "wpa.h" |
29 | #include "tkip.h" | 29 | #include "tkip.h" |
30 | #include "wme.h" | 30 | #include "wme.h" |
31 | #include "rate.h" | ||
31 | 32 | ||
32 | /* | 33 | /* |
33 | * monitor mode reception | 34 | * monitor mode reception |
@@ -748,10 +749,11 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx) | |||
748 | struct ieee80211_local *local = rx->local; | 749 | struct ieee80211_local *local = rx->local; |
749 | struct ieee80211_hw *hw = &local->hw; | 750 | struct ieee80211_hw *hw = &local->hw; |
750 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 751 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
752 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
751 | struct sta_info *sta = rx->sta; | 753 | struct sta_info *sta = rx->sta; |
752 | struct tid_ampdu_rx *tid_agg_rx; | 754 | struct tid_ampdu_rx *tid_agg_rx; |
753 | u16 sc; | 755 | u16 sc; |
754 | int tid; | 756 | u8 tid, ack_policy; |
755 | 757 | ||
756 | if (!ieee80211_is_data_qos(hdr->frame_control)) | 758 | if (!ieee80211_is_data_qos(hdr->frame_control)) |
757 | goto dont_reorder; | 759 | goto dont_reorder; |
@@ -764,6 +766,8 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx) | |||
764 | if (!sta) | 766 | if (!sta) |
765 | goto dont_reorder; | 767 | goto dont_reorder; |
766 | 768 | ||
769 | ack_policy = *ieee80211_get_qos_ctl(hdr) & | ||
770 | IEEE80211_QOS_CTL_ACK_POLICY_MASK; | ||
767 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | 771 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; |
768 | 772 | ||
769 | tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]); | 773 | tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]); |
@@ -774,6 +778,15 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx) | |||
774 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) | 778 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) |
775 | goto dont_reorder; | 779 | goto dont_reorder; |
776 | 780 | ||
781 | /* not part of a BA session */ | ||
782 | if (ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK && | ||
783 | ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL) | ||
784 | goto dont_reorder; | ||
785 | |||
786 | /* not actually part of this BA session */ | ||
787 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
788 | goto dont_reorder; | ||
789 | |||
777 | /* new, potentially un-ordered, ampdu frame - process it */ | 790 | /* new, potentially un-ordered, ampdu frame - process it */ |
778 | 791 | ||
779 | /* reset session timer */ | 792 | /* reset session timer */ |
@@ -858,6 +871,13 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
858 | rx->sdata->control_port_protocol) | 871 | rx->sdata->control_port_protocol) |
859 | return RX_CONTINUE; | 872 | return RX_CONTINUE; |
860 | } | 873 | } |
874 | |||
875 | if (rx->sdata->vif.type == NL80211_IFTYPE_AP && | ||
876 | cfg80211_rx_spurious_frame(rx->sdata->dev, | ||
877 | hdr->addr2, | ||
878 | GFP_ATOMIC)) | ||
879 | return RX_DROP_UNUSABLE; | ||
880 | |||
861 | return RX_DROP_MONITOR; | 881 | return RX_DROP_MONITOR; |
862 | } | 882 | } |
863 | 883 | ||
@@ -1327,15 +1347,20 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1327 | 1347 | ||
1328 | /* | 1348 | /* |
1329 | * If we receive a 4-addr nullfunc frame from a STA | 1349 | * If we receive a 4-addr nullfunc frame from a STA |
1330 | * that was not moved to a 4-addr STA vlan yet, drop | 1350 | * that was not moved to a 4-addr STA vlan yet send |
1331 | * the frame to the monitor interface, to make sure | 1351 | * the event to userspace and for older hostapd drop |
1332 | * that hostapd sees it | 1352 | * the frame to the monitor interface. |
1333 | */ | 1353 | */ |
1334 | if (ieee80211_has_a4(hdr->frame_control) && | 1354 | if (ieee80211_has_a4(hdr->frame_control) && |
1335 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || | 1355 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || |
1336 | (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && | 1356 | (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && |
1337 | !rx->sdata->u.vlan.sta))) | 1357 | !rx->sdata->u.vlan.sta))) { |
1358 | if (!test_and_set_sta_flag(sta, WLAN_STA_4ADDR_EVENT)) | ||
1359 | cfg80211_rx_unexpected_4addr_frame( | ||
1360 | rx->sdata->dev, sta->sta.addr, | ||
1361 | GFP_ATOMIC); | ||
1338 | return RX_DROP_MONITOR; | 1362 | return RX_DROP_MONITOR; |
1363 | } | ||
1339 | /* | 1364 | /* |
1340 | * Update counter and free packet here to avoid | 1365 | * Update counter and free packet here to avoid |
1341 | * counting this as a dropped packed. | 1366 | * counting this as a dropped packed. |
@@ -1551,25 +1576,6 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1551 | return RX_CONTINUE; | 1576 | return RX_CONTINUE; |
1552 | } | 1577 | } |
1553 | 1578 | ||
1554 | static ieee80211_rx_result debug_noinline | ||
1555 | ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) | ||
1556 | { | ||
1557 | u8 *data = rx->skb->data; | ||
1558 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)data; | ||
1559 | |||
1560 | if (!ieee80211_is_data_qos(hdr->frame_control)) | ||
1561 | return RX_CONTINUE; | ||
1562 | |||
1563 | /* remove the qos control field, update frame type and meta-data */ | ||
1564 | memmove(data + IEEE80211_QOS_CTL_LEN, data, | ||
1565 | ieee80211_hdrlen(hdr->frame_control) - IEEE80211_QOS_CTL_LEN); | ||
1566 | hdr = (struct ieee80211_hdr *)skb_pull(rx->skb, IEEE80211_QOS_CTL_LEN); | ||
1567 | /* change frame type to non QOS */ | ||
1568 | hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); | ||
1569 | |||
1570 | return RX_CONTINUE; | ||
1571 | } | ||
1572 | |||
1573 | static int | 1579 | static int |
1574 | ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) | 1580 | ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) |
1575 | { | 1581 | { |
@@ -1802,7 +1808,12 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1802 | } | 1808 | } |
1803 | 1809 | ||
1804 | if (xmit_skb) { | 1810 | if (xmit_skb) { |
1805 | /* send to wireless media */ | 1811 | /* |
1812 | * Send to wireless media and increase priority by 256 to | ||
1813 | * keep the received priority instead of reclassifying | ||
1814 | * the frame (see cfg80211_classify8021d). | ||
1815 | */ | ||
1816 | xmit_skb->priority += 256; | ||
1806 | xmit_skb->protocol = htons(ETH_P_802_3); | 1817 | xmit_skb->protocol = htons(ETH_P_802_3); |
1807 | skb_reset_network_header(xmit_skb); | 1818 | skb_reset_network_header(xmit_skb); |
1808 | skb_reset_mac_header(xmit_skb); | 1819 | skb_reset_mac_header(xmit_skb); |
@@ -1871,13 +1882,16 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1871 | static ieee80211_rx_result | 1882 | static ieee80211_rx_result |
1872 | ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | 1883 | ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) |
1873 | { | 1884 | { |
1874 | struct ieee80211_hdr *hdr; | 1885 | struct ieee80211_hdr *fwd_hdr, *hdr; |
1886 | struct ieee80211_tx_info *info; | ||
1875 | struct ieee80211s_hdr *mesh_hdr; | 1887 | struct ieee80211s_hdr *mesh_hdr; |
1876 | unsigned int hdrlen; | ||
1877 | struct sk_buff *skb = rx->skb, *fwd_skb; | 1888 | struct sk_buff *skb = rx->skb, *fwd_skb; |
1878 | struct ieee80211_local *local = rx->local; | 1889 | struct ieee80211_local *local = rx->local; |
1879 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1890 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1880 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 1891 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
1892 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
1893 | __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD); | ||
1894 | u16 q, hdrlen; | ||
1881 | 1895 | ||
1882 | hdr = (struct ieee80211_hdr *) skb->data; | 1896 | hdr = (struct ieee80211_hdr *) skb->data; |
1883 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1897 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
@@ -1893,14 +1907,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1893 | return RX_CONTINUE; | 1907 | return RX_CONTINUE; |
1894 | 1908 | ||
1895 | if (!mesh_hdr->ttl) | 1909 | if (!mesh_hdr->ttl) |
1896 | /* illegal frame */ | ||
1897 | return RX_DROP_MONITOR; | ||
1898 | |||
1899 | if (ieee80211_queue_stopped(&local->hw, skb_get_queue_mapping(skb))) { | ||
1900 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, | ||
1901 | dropped_frames_congestion); | ||
1902 | return RX_DROP_MONITOR; | 1910 | return RX_DROP_MONITOR; |
1903 | } | ||
1904 | 1911 | ||
1905 | if (mesh_hdr->flags & MESH_FLAGS_AE) { | 1912 | if (mesh_hdr->flags & MESH_FLAGS_AE) { |
1906 | struct mesh_path *mppath; | 1913 | struct mesh_path *mppath; |
@@ -1933,60 +1940,50 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1933 | compare_ether_addr(sdata->vif.addr, hdr->addr3) == 0) | 1940 | compare_ether_addr(sdata->vif.addr, hdr->addr3) == 0) |
1934 | return RX_CONTINUE; | 1941 | return RX_CONTINUE; |
1935 | 1942 | ||
1936 | mesh_hdr->ttl--; | 1943 | q = ieee80211_select_queue_80211(local, skb, hdr); |
1944 | if (ieee80211_queue_stopped(&local->hw, q)) { | ||
1945 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion); | ||
1946 | return RX_DROP_MONITOR; | ||
1947 | } | ||
1948 | skb_set_queue_mapping(skb, q); | ||
1937 | 1949 | ||
1938 | if (status->rx_flags & IEEE80211_RX_RA_MATCH) { | 1950 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) |
1939 | if (!mesh_hdr->ttl) | 1951 | goto out; |
1940 | IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh, | 1952 | |
1941 | dropped_frames_ttl); | 1953 | if (!--mesh_hdr->ttl) { |
1942 | else { | 1954 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); |
1943 | struct ieee80211_hdr *fwd_hdr; | 1955 | return RX_DROP_MONITOR; |
1944 | struct ieee80211_tx_info *info; | 1956 | } |
1945 | 1957 | ||
1946 | fwd_skb = skb_copy(skb, GFP_ATOMIC); | 1958 | fwd_skb = skb_copy(skb, GFP_ATOMIC); |
1947 | 1959 | if (!fwd_skb) { | |
1948 | if (!fwd_skb && net_ratelimit()) | 1960 | if (net_ratelimit()) |
1949 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", | 1961 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", |
1950 | sdata->name); | 1962 | sdata->name); |
1951 | if (!fwd_skb) | 1963 | goto out; |
1952 | goto out; | ||
1953 | |||
1954 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; | ||
1955 | memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); | ||
1956 | info = IEEE80211_SKB_CB(fwd_skb); | ||
1957 | memset(info, 0, sizeof(*info)); | ||
1958 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | ||
1959 | info->control.vif = &rx->sdata->vif; | ||
1960 | if (is_multicast_ether_addr(fwd_hdr->addr1)) { | ||
1961 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, | ||
1962 | fwded_mcast); | ||
1963 | skb_set_queue_mapping(fwd_skb, | ||
1964 | ieee80211_select_queue(sdata, fwd_skb)); | ||
1965 | ieee80211_set_qos_hdr(sdata, fwd_skb); | ||
1966 | } else { | ||
1967 | int err; | ||
1968 | /* | ||
1969 | * Save TA to addr1 to send TA a path error if a | ||
1970 | * suitable next hop is not found | ||
1971 | */ | ||
1972 | memcpy(fwd_hdr->addr1, fwd_hdr->addr2, | ||
1973 | ETH_ALEN); | ||
1974 | err = mesh_nexthop_lookup(fwd_skb, sdata); | ||
1975 | /* Failed to immediately resolve next hop: | ||
1976 | * fwded frame was dropped or will be added | ||
1977 | * later to the pending skb queue. */ | ||
1978 | if (err) | ||
1979 | return RX_DROP_MONITOR; | ||
1980 | |||
1981 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, | ||
1982 | fwded_unicast); | ||
1983 | } | ||
1984 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, | ||
1985 | fwded_frames); | ||
1986 | ieee80211_add_pending_skb(local, fwd_skb); | ||
1987 | } | ||
1988 | } | 1964 | } |
1989 | 1965 | ||
1966 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; | ||
1967 | info = IEEE80211_SKB_CB(fwd_skb); | ||
1968 | memset(info, 0, sizeof(*info)); | ||
1969 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | ||
1970 | info->control.vif = &rx->sdata->vif; | ||
1971 | info->control.jiffies = jiffies; | ||
1972 | if (is_multicast_ether_addr(fwd_hdr->addr1)) { | ||
1973 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast); | ||
1974 | memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); | ||
1975 | } else if (!mesh_nexthop_lookup(fwd_skb, sdata)) { | ||
1976 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast); | ||
1977 | } else { | ||
1978 | /* unable to resolve next hop */ | ||
1979 | mesh_path_error_tx(ifmsh->mshcfg.element_ttl, fwd_hdr->addr3, | ||
1980 | 0, reason, fwd_hdr->addr2, sdata); | ||
1981 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route); | ||
1982 | return RX_DROP_MONITOR; | ||
1983 | } | ||
1984 | |||
1985 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames); | ||
1986 | ieee80211_add_pending_skb(local, fwd_skb); | ||
1990 | out: | 1987 | out: |
1991 | if (is_multicast_ether_addr(hdr->addr1) || | 1988 | if (is_multicast_ether_addr(hdr->addr1) || |
1992 | sdata->dev->flags & IFF_PROMISC) | 1989 | sdata->dev->flags & IFF_PROMISC) |
@@ -2014,12 +2011,17 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
2014 | return RX_DROP_MONITOR; | 2011 | return RX_DROP_MONITOR; |
2015 | 2012 | ||
2016 | /* | 2013 | /* |
2017 | * Allow the cooked monitor interface of an AP to see 4-addr frames so | 2014 | * Send unexpected-4addr-frame event to hostapd. For older versions, |
2018 | * that a 4-addr station can be detected and moved into a separate VLAN | 2015 | * also drop the frame to cooked monitor interfaces. |
2019 | */ | 2016 | */ |
2020 | if (ieee80211_has_a4(hdr->frame_control) && | 2017 | if (ieee80211_has_a4(hdr->frame_control) && |
2021 | sdata->vif.type == NL80211_IFTYPE_AP) | 2018 | sdata->vif.type == NL80211_IFTYPE_AP) { |
2019 | if (rx->sta && | ||
2020 | !test_and_set_sta_flag(rx->sta, WLAN_STA_4ADDR_EVENT)) | ||
2021 | cfg80211_rx_unexpected_4addr_frame( | ||
2022 | rx->sdata->dev, rx->sta->sta.addr, GFP_ATOMIC); | ||
2022 | return RX_DROP_MONITOR; | 2023 | return RX_DROP_MONITOR; |
2024 | } | ||
2023 | 2025 | ||
2024 | err = __ieee80211_data_to_8023(rx, &port_control); | 2026 | err = __ieee80211_data_to_8023(rx, &port_control); |
2025 | if (unlikely(err)) | 2027 | if (unlikely(err)) |
@@ -2174,6 +2176,18 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) | |||
2174 | if (!ieee80211_is_mgmt(mgmt->frame_control)) | 2176 | if (!ieee80211_is_mgmt(mgmt->frame_control)) |
2175 | return RX_DROP_MONITOR; | 2177 | return RX_DROP_MONITOR; |
2176 | 2178 | ||
2179 | if (rx->sdata->vif.type == NL80211_IFTYPE_AP && | ||
2180 | ieee80211_is_beacon(mgmt->frame_control) && | ||
2181 | !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) { | ||
2182 | struct ieee80211_rx_status *status; | ||
2183 | |||
2184 | status = IEEE80211_SKB_RXCB(rx->skb); | ||
2185 | cfg80211_report_obss_beacon(rx->local->hw.wiphy, | ||
2186 | rx->skb->data, rx->skb->len, | ||
2187 | status->freq, GFP_ATOMIC); | ||
2188 | rx->flags |= IEEE80211_RX_BEACON_REPORTED; | ||
2189 | } | ||
2190 | |||
2177 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | 2191 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) |
2178 | return RX_DROP_MONITOR; | 2192 | return RX_DROP_MONITOR; |
2179 | 2193 | ||
@@ -2206,16 +2220,69 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2206 | return RX_DROP_UNUSABLE; | 2220 | return RX_DROP_UNUSABLE; |
2207 | 2221 | ||
2208 | switch (mgmt->u.action.category) { | 2222 | switch (mgmt->u.action.category) { |
2223 | case WLAN_CATEGORY_HT: | ||
2224 | /* reject HT action frames from stations not supporting HT */ | ||
2225 | if (!rx->sta->sta.ht_cap.ht_supported) | ||
2226 | goto invalid; | ||
2227 | |||
2228 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | ||
2229 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && | ||
2230 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
2231 | sdata->vif.type != NL80211_IFTYPE_AP && | ||
2232 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | ||
2233 | break; | ||
2234 | |||
2235 | /* verify action & smps_control are present */ | ||
2236 | if (len < IEEE80211_MIN_ACTION_SIZE + 2) | ||
2237 | goto invalid; | ||
2238 | |||
2239 | switch (mgmt->u.action.u.ht_smps.action) { | ||
2240 | case WLAN_HT_ACTION_SMPS: { | ||
2241 | struct ieee80211_supported_band *sband; | ||
2242 | u8 smps; | ||
2243 | |||
2244 | /* convert to HT capability */ | ||
2245 | switch (mgmt->u.action.u.ht_smps.smps_control) { | ||
2246 | case WLAN_HT_SMPS_CONTROL_DISABLED: | ||
2247 | smps = WLAN_HT_CAP_SM_PS_DISABLED; | ||
2248 | break; | ||
2249 | case WLAN_HT_SMPS_CONTROL_STATIC: | ||
2250 | smps = WLAN_HT_CAP_SM_PS_STATIC; | ||
2251 | break; | ||
2252 | case WLAN_HT_SMPS_CONTROL_DYNAMIC: | ||
2253 | smps = WLAN_HT_CAP_SM_PS_DYNAMIC; | ||
2254 | break; | ||
2255 | default: | ||
2256 | goto invalid; | ||
2257 | } | ||
2258 | smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
2259 | |||
2260 | /* if no change do nothing */ | ||
2261 | if ((rx->sta->sta.ht_cap.cap & | ||
2262 | IEEE80211_HT_CAP_SM_PS) == smps) | ||
2263 | goto handled; | ||
2264 | |||
2265 | rx->sta->sta.ht_cap.cap &= ~IEEE80211_HT_CAP_SM_PS; | ||
2266 | rx->sta->sta.ht_cap.cap |= smps; | ||
2267 | |||
2268 | sband = rx->local->hw.wiphy->bands[status->band]; | ||
2269 | |||
2270 | rate_control_rate_update(local, sband, rx->sta, | ||
2271 | IEEE80211_RC_SMPS_CHANGED, | ||
2272 | local->_oper_channel_type); | ||
2273 | goto handled; | ||
2274 | } | ||
2275 | default: | ||
2276 | goto invalid; | ||
2277 | } | ||
2278 | |||
2279 | break; | ||
2209 | case WLAN_CATEGORY_BACK: | 2280 | case WLAN_CATEGORY_BACK: |
2210 | /* | ||
2211 | * The aggregation code is not prepared to handle | ||
2212 | * anything but STA/AP due to the BSSID handling; | ||
2213 | * IBSS could work in the code but isn't supported | ||
2214 | * by drivers or the standard. | ||
2215 | */ | ||
2216 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 2281 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
2282 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && | ||
2217 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 2283 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
2218 | sdata->vif.type != NL80211_IFTYPE_AP) | 2284 | sdata->vif.type != NL80211_IFTYPE_AP && |
2285 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | ||
2219 | break; | 2286 | break; |
2220 | 2287 | ||
2221 | /* verify action_code is present */ | 2288 | /* verify action_code is present */ |
@@ -2493,6 +2560,10 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, | |||
2493 | goto out_free_skb; | 2560 | goto out_free_skb; |
2494 | rx->flags |= IEEE80211_RX_CMNTR; | 2561 | rx->flags |= IEEE80211_RX_CMNTR; |
2495 | 2562 | ||
2563 | /* If there are no cooked monitor interfaces, just free the SKB */ | ||
2564 | if (!local->cooked_mntrs) | ||
2565 | goto out_free_skb; | ||
2566 | |||
2496 | if (skb_headroom(skb) < sizeof(*rthdr) && | 2567 | if (skb_headroom(skb) < sizeof(*rthdr) && |
2497 | pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) | 2568 | pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) |
2498 | goto out_free_skb; | 2569 | goto out_free_skb; |
@@ -2628,7 +2699,6 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) | |||
2628 | if (ieee80211_vif_is_mesh(&rx->sdata->vif)) | 2699 | if (ieee80211_vif_is_mesh(&rx->sdata->vif)) |
2629 | CALL_RXH(ieee80211_rx_h_mesh_fwding); | 2700 | CALL_RXH(ieee80211_rx_h_mesh_fwding); |
2630 | #endif | 2701 | #endif |
2631 | CALL_RXH(ieee80211_rx_h_remove_qos_control) | ||
2632 | CALL_RXH(ieee80211_rx_h_amsdu) | 2702 | CALL_RXH(ieee80211_rx_h_amsdu) |
2633 | CALL_RXH(ieee80211_rx_h_data) | 2703 | CALL_RXH(ieee80211_rx_h_data) |
2634 | CALL_RXH(ieee80211_rx_h_ctrl); | 2704 | CALL_RXH(ieee80211_rx_h_ctrl); |
@@ -2748,8 +2818,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2748 | rate_idx = 0; /* TODO: HT rates */ | 2818 | rate_idx = 0; /* TODO: HT rates */ |
2749 | else | 2819 | else |
2750 | rate_idx = status->rate_idx; | 2820 | rate_idx = status->rate_idx; |
2751 | rx->sta = ieee80211_ibss_add_sta(sdata, bssid, | 2821 | ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2, |
2752 | hdr->addr2, BIT(rate_idx), GFP_ATOMIC); | 2822 | BIT(rate_idx)); |
2753 | } | 2823 | } |
2754 | break; | 2824 | break; |
2755 | case NL80211_IFTYPE_MESH_POINT: | 2825 | case NL80211_IFTYPE_MESH_POINT: |
@@ -2770,10 +2840,17 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2770 | return 0; | 2840 | return 0; |
2771 | } else if (!ieee80211_bssid_match(bssid, | 2841 | } else if (!ieee80211_bssid_match(bssid, |
2772 | sdata->vif.addr)) { | 2842 | sdata->vif.addr)) { |
2843 | /* | ||
2844 | * Accept public action frames even when the | ||
2845 | * BSSID doesn't match, this is used for P2P | ||
2846 | * and location updates. Note that mac80211 | ||
2847 | * itself never looks at these frames. | ||
2848 | */ | ||
2849 | if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && | ||
2850 | ieee80211_is_public_action(hdr, skb->len)) | ||
2851 | return 1; | ||
2773 | if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && | 2852 | if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && |
2774 | !ieee80211_is_beacon(hdr->frame_control) && | 2853 | !ieee80211_is_beacon(hdr->frame_control)) |
2775 | !(ieee80211_is_action(hdr->frame_control) && | ||
2776 | sdata->vif.p2p)) | ||
2777 | return 0; | 2854 | return 0; |
2778 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | 2855 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; |
2779 | } | 2856 | } |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 105436dbb90d..9270771702fe 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -106,7 +106,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
106 | /* save the ERP value so that it is available at association time */ | 106 | /* save the ERP value so that it is available at association time */ |
107 | if (elems->erp_info && elems->erp_info_len >= 1) { | 107 | if (elems->erp_info && elems->erp_info_len >= 1) { |
108 | bss->erp_value = elems->erp_info[0]; | 108 | bss->erp_value = elems->erp_info[0]; |
109 | bss->has_erp_value = 1; | 109 | bss->has_erp_value = true; |
110 | } | 110 | } |
111 | 111 | ||
112 | if (elems->tim) { | 112 | if (elems->tim) { |
@@ -213,12 +213,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
213 | if (bss) | 213 | if (bss) |
214 | ieee80211_rx_bss_put(sdata->local, bss); | 214 | ieee80211_rx_bss_put(sdata->local, bss); |
215 | 215 | ||
216 | /* If we are on-operating-channel, and this packet is for the | 216 | if (channel == sdata->local->oper_channel) |
217 | * current channel, pass the pkt on up the stack so that | ||
218 | * the rest of the stack can make use of it. | ||
219 | */ | ||
220 | if (ieee80211_cfg_on_oper_channel(sdata->local) | ||
221 | && (channel == sdata->local->oper_channel)) | ||
222 | return RX_CONTINUE; | 217 | return RX_CONTINUE; |
223 | 218 | ||
224 | dev_kfree_skb(skb); | 219 | dev_kfree_skb(skb); |
@@ -264,8 +259,6 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, | |||
264 | bool was_hw_scan) | 259 | bool was_hw_scan) |
265 | { | 260 | { |
266 | struct ieee80211_local *local = hw_to_local(hw); | 261 | struct ieee80211_local *local = hw_to_local(hw); |
267 | bool on_oper_chan; | ||
268 | bool enable_beacons = false; | ||
269 | 262 | ||
270 | lockdep_assert_held(&local->mtx); | 263 | lockdep_assert_held(&local->mtx); |
271 | 264 | ||
@@ -298,25 +291,13 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, | |||
298 | local->scanning = 0; | 291 | local->scanning = 0; |
299 | local->scan_channel = NULL; | 292 | local->scan_channel = NULL; |
300 | 293 | ||
301 | on_oper_chan = ieee80211_cfg_on_oper_channel(local); | 294 | /* Set power back to normal operating levels. */ |
302 | 295 | ieee80211_hw_config(local, 0); | |
303 | if (was_hw_scan || !on_oper_chan) | ||
304 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
305 | else | ||
306 | /* Set power back to normal operating levels. */ | ||
307 | ieee80211_hw_config(local, 0); | ||
308 | 296 | ||
309 | if (!was_hw_scan) { | 297 | if (!was_hw_scan) { |
310 | bool on_oper_chan2; | ||
311 | ieee80211_configure_filter(local); | 298 | ieee80211_configure_filter(local); |
312 | drv_sw_scan_complete(local); | 299 | drv_sw_scan_complete(local); |
313 | on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); | 300 | ieee80211_offchannel_return(local, true); |
314 | /* We should always be on-channel at this point. */ | ||
315 | WARN_ON(!on_oper_chan2); | ||
316 | if (on_oper_chan2 && (on_oper_chan != on_oper_chan2)) | ||
317 | enable_beacons = true; | ||
318 | |||
319 | ieee80211_offchannel_return(local, enable_beacons, true); | ||
320 | } | 301 | } |
321 | 302 | ||
322 | ieee80211_recalc_idle(local); | 303 | ieee80211_recalc_idle(local); |
@@ -361,11 +342,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
361 | local->next_scan_state = SCAN_DECISION; | 342 | local->next_scan_state = SCAN_DECISION; |
362 | local->scan_channel_idx = 0; | 343 | local->scan_channel_idx = 0; |
363 | 344 | ||
364 | /* We always want to use off-channel PS, even if we | 345 | ieee80211_offchannel_stop_vifs(local, true); |
365 | * are not really leaving oper-channel. Don't | ||
366 | * tell the AP though, as long as we are on-channel. | ||
367 | */ | ||
368 | ieee80211_offchannel_enable_all_ps(local, false); | ||
369 | 346 | ||
370 | ieee80211_configure_filter(local); | 347 | ieee80211_configure_filter(local); |
371 | 348 | ||
@@ -373,8 +350,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
373 | ieee80211_hw_config(local, 0); | 350 | ieee80211_hw_config(local, 0); |
374 | 351 | ||
375 | ieee80211_queue_delayed_work(&local->hw, | 352 | ieee80211_queue_delayed_work(&local->hw, |
376 | &local->scan_work, | 353 | &local->scan_work, 0); |
377 | IEEE80211_CHANNEL_TIME); | ||
378 | 354 | ||
379 | return 0; | 355 | return 0; |
380 | } | 356 | } |
@@ -510,96 +486,39 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
510 | 486 | ||
511 | next_chan = local->scan_req->channels[local->scan_channel_idx]; | 487 | next_chan = local->scan_req->channels[local->scan_channel_idx]; |
512 | 488 | ||
513 | if (ieee80211_cfg_on_oper_channel(local)) { | ||
514 | /* We're currently on operating channel. */ | ||
515 | if (next_chan == local->oper_channel) | ||
516 | /* We don't need to move off of operating channel. */ | ||
517 | local->next_scan_state = SCAN_SET_CHANNEL; | ||
518 | else | ||
519 | /* | ||
520 | * We do need to leave operating channel, as next | ||
521 | * scan is somewhere else. | ||
522 | */ | ||
523 | local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; | ||
524 | } else { | ||
525 | /* | ||
526 | * we're currently scanning a different channel, let's | ||
527 | * see if we can scan another channel without interfering | ||
528 | * with the current traffic situation. | ||
529 | * | ||
530 | * Since we don't know if the AP has pending frames for us | ||
531 | * we can only check for our tx queues and use the current | ||
532 | * pm_qos requirements for rx. Hence, if no tx traffic occurs | ||
533 | * at all we will scan as many channels in a row as the pm_qos | ||
534 | * latency allows us to. Additionally we also check for the | ||
535 | * currently negotiated listen interval to prevent losing | ||
536 | * frames unnecessarily. | ||
537 | * | ||
538 | * Otherwise switch back to the operating channel. | ||
539 | */ | ||
540 | |||
541 | bad_latency = time_after(jiffies + | ||
542 | ieee80211_scan_get_channel_time(next_chan), | ||
543 | local->leave_oper_channel_time + | ||
544 | usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY))); | ||
545 | |||
546 | listen_int_exceeded = time_after(jiffies + | ||
547 | ieee80211_scan_get_channel_time(next_chan), | ||
548 | local->leave_oper_channel_time + | ||
549 | usecs_to_jiffies(min_beacon_int * 1024) * | ||
550 | local->hw.conf.listen_interval); | ||
551 | |||
552 | if (associated && ( !tx_empty || bad_latency || | ||
553 | listen_int_exceeded)) | ||
554 | local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; | ||
555 | else | ||
556 | local->next_scan_state = SCAN_SET_CHANNEL; | ||
557 | } | ||
558 | |||
559 | *next_delay = 0; | ||
560 | } | ||
561 | |||
562 | static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, | ||
563 | unsigned long *next_delay) | ||
564 | { | ||
565 | /* PS will already be in off-channel mode, | ||
566 | * we do that once at the beginning of scanning. | ||
567 | */ | ||
568 | ieee80211_offchannel_stop_vifs(local, false); | ||
569 | |||
570 | /* | 489 | /* |
571 | * What if the nullfunc frames didn't arrive? | 490 | * we're currently scanning a different channel, let's |
491 | * see if we can scan another channel without interfering | ||
492 | * with the current traffic situation. | ||
493 | * | ||
494 | * Since we don't know if the AP has pending frames for us | ||
495 | * we can only check for our tx queues and use the current | ||
496 | * pm_qos requirements for rx. Hence, if no tx traffic occurs | ||
497 | * at all we will scan as many channels in a row as the pm_qos | ||
498 | * latency allows us to. Additionally we also check for the | ||
499 | * currently negotiated listen interval to prevent losing | ||
500 | * frames unnecessarily. | ||
501 | * | ||
502 | * Otherwise switch back to the operating channel. | ||
572 | */ | 503 | */ |
573 | drv_flush(local, false); | ||
574 | if (local->ops->flush) | ||
575 | *next_delay = 0; | ||
576 | else | ||
577 | *next_delay = HZ / 10; | ||
578 | 504 | ||
579 | /* remember when we left the operating channel */ | 505 | bad_latency = time_after(jiffies + |
580 | local->leave_oper_channel_time = jiffies; | 506 | ieee80211_scan_get_channel_time(next_chan), |
507 | local->leave_oper_channel_time + | ||
508 | usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY))); | ||
581 | 509 | ||
582 | /* advance to the next channel to be scanned */ | 510 | listen_int_exceeded = time_after(jiffies + |
583 | local->next_scan_state = SCAN_SET_CHANNEL; | 511 | ieee80211_scan_get_channel_time(next_chan), |
584 | } | 512 | local->leave_oper_channel_time + |
585 | 513 | usecs_to_jiffies(min_beacon_int * 1024) * | |
586 | static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local, | 514 | local->hw.conf.listen_interval); |
587 | unsigned long *next_delay) | ||
588 | { | ||
589 | /* switch back to the operating channel */ | ||
590 | local->scan_channel = NULL; | ||
591 | if (!ieee80211_cfg_on_oper_channel(local)) | ||
592 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
593 | 515 | ||
594 | /* | 516 | if (associated && (!tx_empty || bad_latency || listen_int_exceeded)) |
595 | * Re-enable vifs and beaconing. Leave PS | 517 | local->next_scan_state = SCAN_SUSPEND; |
596 | * in off-channel state..will put that back | 518 | else |
597 | * on-channel at the end of scanning. | 519 | local->next_scan_state = SCAN_SET_CHANNEL; |
598 | */ | ||
599 | ieee80211_offchannel_return(local, true, false); | ||
600 | 520 | ||
601 | *next_delay = HZ / 5; | 521 | *next_delay = 0; |
602 | local->next_scan_state = SCAN_DECISION; | ||
603 | } | 522 | } |
604 | 523 | ||
605 | static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | 524 | static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, |
@@ -613,10 +532,8 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | |||
613 | 532 | ||
614 | local->scan_channel = chan; | 533 | local->scan_channel = chan; |
615 | 534 | ||
616 | /* Only call hw-config if we really need to change channels. */ | 535 | if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL)) |
617 | if (chan != local->hw.conf.channel) | 536 | skip = 1; |
618 | if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL)) | ||
619 | skip = 1; | ||
620 | 537 | ||
621 | /* advance state machine to next channel/band */ | 538 | /* advance state machine to next channel/band */ |
622 | local->scan_channel_idx++; | 539 | local->scan_channel_idx++; |
@@ -673,6 +590,44 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
673 | local->next_scan_state = SCAN_DECISION; | 590 | local->next_scan_state = SCAN_DECISION; |
674 | } | 591 | } |
675 | 592 | ||
593 | static void ieee80211_scan_state_suspend(struct ieee80211_local *local, | ||
594 | unsigned long *next_delay) | ||
595 | { | ||
596 | /* switch back to the operating channel */ | ||
597 | local->scan_channel = NULL; | ||
598 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
599 | |||
600 | /* | ||
601 | * Re-enable vifs and beaconing. Leave PS | ||
602 | * in off-channel state..will put that back | ||
603 | * on-channel at the end of scanning. | ||
604 | */ | ||
605 | ieee80211_offchannel_return(local, false); | ||
606 | |||
607 | *next_delay = HZ / 5; | ||
608 | /* afterwards, resume scan & go to next channel */ | ||
609 | local->next_scan_state = SCAN_RESUME; | ||
610 | } | ||
611 | |||
612 | static void ieee80211_scan_state_resume(struct ieee80211_local *local, | ||
613 | unsigned long *next_delay) | ||
614 | { | ||
615 | /* PS already is in off-channel mode */ | ||
616 | ieee80211_offchannel_stop_vifs(local, false); | ||
617 | |||
618 | if (local->ops->flush) { | ||
619 | drv_flush(local, false); | ||
620 | *next_delay = 0; | ||
621 | } else | ||
622 | *next_delay = HZ / 10; | ||
623 | |||
624 | /* remember when we left the operating channel */ | ||
625 | local->leave_oper_channel_time = jiffies; | ||
626 | |||
627 | /* advance to the next channel to be scanned */ | ||
628 | local->next_scan_state = SCAN_SET_CHANNEL; | ||
629 | } | ||
630 | |||
676 | void ieee80211_scan_work(struct work_struct *work) | 631 | void ieee80211_scan_work(struct work_struct *work) |
677 | { | 632 | { |
678 | struct ieee80211_local *local = | 633 | struct ieee80211_local *local = |
@@ -743,11 +698,11 @@ void ieee80211_scan_work(struct work_struct *work) | |||
743 | case SCAN_SEND_PROBE: | 698 | case SCAN_SEND_PROBE: |
744 | ieee80211_scan_state_send_probe(local, &next_delay); | 699 | ieee80211_scan_state_send_probe(local, &next_delay); |
745 | break; | 700 | break; |
746 | case SCAN_LEAVE_OPER_CHANNEL: | 701 | case SCAN_SUSPEND: |
747 | ieee80211_scan_state_leave_oper_channel(local, &next_delay); | 702 | ieee80211_scan_state_suspend(local, &next_delay); |
748 | break; | 703 | break; |
749 | case SCAN_ENTER_OPER_CHANNEL: | 704 | case SCAN_RESUME: |
750 | ieee80211_scan_state_enter_oper_channel(local, &next_delay); | 705 | ieee80211_scan_state_resume(local, &next_delay); |
751 | break; | 706 | break; |
752 | } | 707 | } |
753 | } while (next_delay == 0); | 708 | } while (next_delay == 0); |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 8eaa746ec7a2..b197136aea2c 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -62,14 +62,14 @@ | |||
62 | * freed before they are done using it. | 62 | * freed before they are done using it. |
63 | */ | 63 | */ |
64 | 64 | ||
65 | /* Caller must hold local->sta_lock */ | 65 | /* Caller must hold local->sta_mtx */ |
66 | static int sta_info_hash_del(struct ieee80211_local *local, | 66 | static int sta_info_hash_del(struct ieee80211_local *local, |
67 | struct sta_info *sta) | 67 | struct sta_info *sta) |
68 | { | 68 | { |
69 | struct sta_info *s; | 69 | struct sta_info *s; |
70 | 70 | ||
71 | s = rcu_dereference_protected(local->sta_hash[STA_HASH(sta->sta.addr)], | 71 | s = rcu_dereference_protected(local->sta_hash[STA_HASH(sta->sta.addr)], |
72 | lockdep_is_held(&local->sta_lock)); | 72 | lockdep_is_held(&local->sta_mtx)); |
73 | if (!s) | 73 | if (!s) |
74 | return -ENOENT; | 74 | return -ENOENT; |
75 | if (s == sta) { | 75 | if (s == sta) { |
@@ -81,7 +81,7 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
81 | while (rcu_access_pointer(s->hnext) && | 81 | while (rcu_access_pointer(s->hnext) && |
82 | rcu_access_pointer(s->hnext) != sta) | 82 | rcu_access_pointer(s->hnext) != sta) |
83 | s = rcu_dereference_protected(s->hnext, | 83 | s = rcu_dereference_protected(s->hnext, |
84 | lockdep_is_held(&local->sta_lock)); | 84 | lockdep_is_held(&local->sta_mtx)); |
85 | if (rcu_access_pointer(s->hnext)) { | 85 | if (rcu_access_pointer(s->hnext)) { |
86 | RCU_INIT_POINTER(s->hnext, sta->hnext); | 86 | RCU_INIT_POINTER(s->hnext, sta->hnext); |
87 | return 0; | 87 | return 0; |
@@ -98,14 +98,12 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | |||
98 | struct sta_info *sta; | 98 | struct sta_info *sta; |
99 | 99 | ||
100 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | 100 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
101 | lockdep_is_held(&local->sta_lock) || | ||
102 | lockdep_is_held(&local->sta_mtx)); | 101 | lockdep_is_held(&local->sta_mtx)); |
103 | while (sta) { | 102 | while (sta) { |
104 | if (sta->sdata == sdata && !sta->dummy && | 103 | if (sta->sdata == sdata && !sta->dummy && |
105 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 104 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
106 | break; | 105 | break; |
107 | sta = rcu_dereference_check(sta->hnext, | 106 | sta = rcu_dereference_check(sta->hnext, |
108 | lockdep_is_held(&local->sta_lock) || | ||
109 | lockdep_is_held(&local->sta_mtx)); | 107 | lockdep_is_held(&local->sta_mtx)); |
110 | } | 108 | } |
111 | return sta; | 109 | return sta; |
@@ -119,14 +117,12 @@ struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, | |||
119 | struct sta_info *sta; | 117 | struct sta_info *sta; |
120 | 118 | ||
121 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | 119 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
122 | lockdep_is_held(&local->sta_lock) || | ||
123 | lockdep_is_held(&local->sta_mtx)); | 120 | lockdep_is_held(&local->sta_mtx)); |
124 | while (sta) { | 121 | while (sta) { |
125 | if (sta->sdata == sdata && | 122 | if (sta->sdata == sdata && |
126 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 123 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
127 | break; | 124 | break; |
128 | sta = rcu_dereference_check(sta->hnext, | 125 | sta = rcu_dereference_check(sta->hnext, |
129 | lockdep_is_held(&local->sta_lock) || | ||
130 | lockdep_is_held(&local->sta_mtx)); | 126 | lockdep_is_held(&local->sta_mtx)); |
131 | } | 127 | } |
132 | return sta; | 128 | return sta; |
@@ -143,7 +139,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
143 | struct sta_info *sta; | 139 | struct sta_info *sta; |
144 | 140 | ||
145 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | 141 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
146 | lockdep_is_held(&local->sta_lock) || | ||
147 | lockdep_is_held(&local->sta_mtx)); | 142 | lockdep_is_held(&local->sta_mtx)); |
148 | while (sta) { | 143 | while (sta) { |
149 | if ((sta->sdata == sdata || | 144 | if ((sta->sdata == sdata || |
@@ -152,7 +147,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
152 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 147 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
153 | break; | 148 | break; |
154 | sta = rcu_dereference_check(sta->hnext, | 149 | sta = rcu_dereference_check(sta->hnext, |
155 | lockdep_is_held(&local->sta_lock) || | ||
156 | lockdep_is_held(&local->sta_mtx)); | 150 | lockdep_is_held(&local->sta_mtx)); |
157 | } | 151 | } |
158 | return sta; | 152 | return sta; |
@@ -169,7 +163,6 @@ struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, | |||
169 | struct sta_info *sta; | 163 | struct sta_info *sta; |
170 | 164 | ||
171 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | 165 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
172 | lockdep_is_held(&local->sta_lock) || | ||
173 | lockdep_is_held(&local->sta_mtx)); | 166 | lockdep_is_held(&local->sta_mtx)); |
174 | while (sta) { | 167 | while (sta) { |
175 | if ((sta->sdata == sdata || | 168 | if ((sta->sdata == sdata || |
@@ -177,7 +170,6 @@ struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, | |||
177 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 170 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
178 | break; | 171 | break; |
179 | sta = rcu_dereference_check(sta->hnext, | 172 | sta = rcu_dereference_check(sta->hnext, |
180 | lockdep_is_held(&local->sta_lock) || | ||
181 | lockdep_is_held(&local->sta_mtx)); | 173 | lockdep_is_held(&local->sta_mtx)); |
182 | } | 174 | } |
183 | return sta; | 175 | return sta; |
@@ -204,16 +196,17 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, | |||
204 | } | 196 | } |
205 | 197 | ||
206 | /** | 198 | /** |
207 | * __sta_info_free - internal STA free helper | 199 | * sta_info_free - free STA |
208 | * | 200 | * |
209 | * @local: pointer to the global information | 201 | * @local: pointer to the global information |
210 | * @sta: STA info to free | 202 | * @sta: STA info to free |
211 | * | 203 | * |
212 | * This function must undo everything done by sta_info_alloc() | 204 | * This function must undo everything done by sta_info_alloc() |
213 | * that may happen before sta_info_insert(). | 205 | * that may happen before sta_info_insert(). It may only be |
206 | * called when sta_info_insert() has not been attempted (and | ||
207 | * if that fails, the station is freed anyway.) | ||
214 | */ | 208 | */ |
215 | static void __sta_info_free(struct ieee80211_local *local, | 209 | void sta_info_free(struct ieee80211_local *local, struct sta_info *sta) |
216 | struct sta_info *sta) | ||
217 | { | 210 | { |
218 | if (sta->rate_ctrl) { | 211 | if (sta->rate_ctrl) { |
219 | rate_control_free_sta(sta); | 212 | rate_control_free_sta(sta); |
@@ -227,10 +220,11 @@ static void __sta_info_free(struct ieee80211_local *local, | |||
227 | kfree(sta); | 220 | kfree(sta); |
228 | } | 221 | } |
229 | 222 | ||
230 | /* Caller must hold local->sta_lock */ | 223 | /* Caller must hold local->sta_mtx */ |
231 | static void sta_info_hash_add(struct ieee80211_local *local, | 224 | static void sta_info_hash_add(struct ieee80211_local *local, |
232 | struct sta_info *sta) | 225 | struct sta_info *sta) |
233 | { | 226 | { |
227 | lockdep_assert_held(&local->sta_mtx); | ||
234 | sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)]; | 228 | sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)]; |
235 | RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)], sta); | 229 | RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)], sta); |
236 | } | 230 | } |
@@ -280,7 +274,7 @@ static int sta_prepare_rate_control(struct ieee80211_local *local, | |||
280 | } | 274 | } |
281 | 275 | ||
282 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | 276 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, |
283 | u8 *addr, gfp_t gfp) | 277 | const u8 *addr, gfp_t gfp) |
284 | { | 278 | { |
285 | struct ieee80211_local *local = sdata->local; | 279 | struct ieee80211_local *local = sdata->local; |
286 | struct sta_info *sta; | 280 | struct sta_info *sta; |
@@ -338,102 +332,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
338 | return sta; | 332 | return sta; |
339 | } | 333 | } |
340 | 334 | ||
341 | static int sta_info_finish_insert(struct sta_info *sta, | ||
342 | bool async, bool dummy_reinsert) | ||
343 | { | ||
344 | struct ieee80211_local *local = sta->local; | ||
345 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
346 | struct station_info sinfo; | ||
347 | unsigned long flags; | ||
348 | int err = 0; | ||
349 | |||
350 | lockdep_assert_held(&local->sta_mtx); | ||
351 | |||
352 | if (!sta->dummy || dummy_reinsert) { | ||
353 | /* notify driver */ | ||
354 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
355 | sdata = container_of(sdata->bss, | ||
356 | struct ieee80211_sub_if_data, | ||
357 | u.ap); | ||
358 | err = drv_sta_add(local, sdata, &sta->sta); | ||
359 | if (err) { | ||
360 | if (!async) | ||
361 | return err; | ||
362 | printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to " | ||
363 | "driver (%d) - keeping it anyway.\n", | ||
364 | sdata->name, sta->sta.addr, err); | ||
365 | } else { | ||
366 | sta->uploaded = true; | ||
367 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
368 | if (async) | ||
369 | wiphy_debug(local->hw.wiphy, | ||
370 | "Finished adding IBSS STA %pM\n", | ||
371 | sta->sta.addr); | ||
372 | #endif | ||
373 | } | ||
374 | |||
375 | sdata = sta->sdata; | ||
376 | } | ||
377 | |||
378 | if (!dummy_reinsert) { | ||
379 | if (!async) { | ||
380 | local->num_sta++; | ||
381 | local->sta_generation++; | ||
382 | smp_mb(); | ||
383 | |||
384 | /* make the station visible */ | ||
385 | spin_lock_irqsave(&local->sta_lock, flags); | ||
386 | sta_info_hash_add(local, sta); | ||
387 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
388 | } | ||
389 | |||
390 | list_add(&sta->list, &local->sta_list); | ||
391 | } else { | ||
392 | sta->dummy = false; | ||
393 | } | ||
394 | |||
395 | if (!sta->dummy) { | ||
396 | ieee80211_sta_debugfs_add(sta); | ||
397 | rate_control_add_sta_debugfs(sta); | ||
398 | |||
399 | memset(&sinfo, 0, sizeof(sinfo)); | ||
400 | sinfo.filled = 0; | ||
401 | sinfo.generation = local->sta_generation; | ||
402 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); | ||
403 | } | ||
404 | |||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | static void sta_info_finish_pending(struct ieee80211_local *local) | ||
409 | { | ||
410 | struct sta_info *sta; | ||
411 | unsigned long flags; | ||
412 | |||
413 | spin_lock_irqsave(&local->sta_lock, flags); | ||
414 | while (!list_empty(&local->sta_pending_list)) { | ||
415 | sta = list_first_entry(&local->sta_pending_list, | ||
416 | struct sta_info, list); | ||
417 | list_del(&sta->list); | ||
418 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
419 | |||
420 | sta_info_finish_insert(sta, true, false); | ||
421 | |||
422 | spin_lock_irqsave(&local->sta_lock, flags); | ||
423 | } | ||
424 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
425 | } | ||
426 | |||
427 | static void sta_info_finish_work(struct work_struct *work) | ||
428 | { | ||
429 | struct ieee80211_local *local = | ||
430 | container_of(work, struct ieee80211_local, sta_finish_work); | ||
431 | |||
432 | mutex_lock(&local->sta_mtx); | ||
433 | sta_info_finish_pending(local); | ||
434 | mutex_unlock(&local->sta_mtx); | ||
435 | } | ||
436 | |||
437 | static int sta_info_insert_check(struct sta_info *sta) | 335 | static int sta_info_insert_check(struct sta_info *sta) |
438 | { | 336 | { |
439 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 337 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -453,50 +351,15 @@ static int sta_info_insert_check(struct sta_info *sta) | |||
453 | return 0; | 351 | return 0; |
454 | } | 352 | } |
455 | 353 | ||
456 | static int sta_info_insert_ibss(struct sta_info *sta) __acquires(RCU) | ||
457 | { | ||
458 | struct ieee80211_local *local = sta->local; | ||
459 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
460 | unsigned long flags; | ||
461 | |||
462 | spin_lock_irqsave(&local->sta_lock, flags); | ||
463 | /* check if STA exists already */ | ||
464 | if (sta_info_get_bss_rx(sdata, sta->sta.addr)) { | ||
465 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
466 | rcu_read_lock(); | ||
467 | return -EEXIST; | ||
468 | } | ||
469 | |||
470 | local->num_sta++; | ||
471 | local->sta_generation++; | ||
472 | smp_mb(); | ||
473 | sta_info_hash_add(local, sta); | ||
474 | |||
475 | list_add_tail(&sta->list, &local->sta_pending_list); | ||
476 | |||
477 | rcu_read_lock(); | ||
478 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
479 | |||
480 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
481 | wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n", | ||
482 | sta->sta.addr); | ||
483 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
484 | |||
485 | ieee80211_queue_work(&local->hw, &local->sta_finish_work); | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | /* | 354 | /* |
491 | * should be called with sta_mtx locked | 355 | * should be called with sta_mtx locked |
492 | * this function replaces the mutex lock | 356 | * this function replaces the mutex lock |
493 | * with a RCU lock | 357 | * with a RCU lock |
494 | */ | 358 | */ |
495 | static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU) | 359 | static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) |
496 | { | 360 | { |
497 | struct ieee80211_local *local = sta->local; | 361 | struct ieee80211_local *local = sta->local; |
498 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 362 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
499 | unsigned long flags; | ||
500 | struct sta_info *exist_sta; | 363 | struct sta_info *exist_sta; |
501 | bool dummy_reinsert = false; | 364 | bool dummy_reinsert = false; |
502 | int err = 0; | 365 | int err = 0; |
@@ -504,19 +367,8 @@ static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU) | |||
504 | lockdep_assert_held(&local->sta_mtx); | 367 | lockdep_assert_held(&local->sta_mtx); |
505 | 368 | ||
506 | /* | 369 | /* |
507 | * On first glance, this will look racy, because the code | ||
508 | * in this function, which inserts a station with sleeping, | ||
509 | * unlocks the sta_lock between checking existence in the | ||
510 | * hash table and inserting into it. | ||
511 | * | ||
512 | * However, it is not racy against itself because it keeps | ||
513 | * the mutex locked. | ||
514 | */ | ||
515 | |||
516 | spin_lock_irqsave(&local->sta_lock, flags); | ||
517 | /* | ||
518 | * check if STA exists already. | 370 | * check if STA exists already. |
519 | * only accept a scenario of a second call to sta_info_insert_non_ibss | 371 | * only accept a scenario of a second call to sta_info_insert_finish |
520 | * with a dummy station entry that was inserted earlier | 372 | * with a dummy station entry that was inserted earlier |
521 | * in that case - assume that the dummy station flag should | 373 | * in that case - assume that the dummy station flag should |
522 | * be removed. | 374 | * be removed. |
@@ -526,20 +378,47 @@ static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU) | |||
526 | if (exist_sta == sta && sta->dummy) { | 378 | if (exist_sta == sta && sta->dummy) { |
527 | dummy_reinsert = true; | 379 | dummy_reinsert = true; |
528 | } else { | 380 | } else { |
529 | spin_unlock_irqrestore(&local->sta_lock, flags); | 381 | err = -EEXIST; |
530 | mutex_unlock(&local->sta_mtx); | 382 | goto out_err; |
531 | rcu_read_lock(); | ||
532 | return -EEXIST; | ||
533 | } | 383 | } |
534 | } | 384 | } |
535 | 385 | ||
536 | spin_unlock_irqrestore(&local->sta_lock, flags); | 386 | if (!sta->dummy || dummy_reinsert) { |
387 | /* notify driver */ | ||
388 | err = drv_sta_add(local, sdata, &sta->sta); | ||
389 | if (err) { | ||
390 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | ||
391 | goto out_err; | ||
392 | printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to " | ||
393 | "driver (%d) - keeping it anyway.\n", | ||
394 | sdata->name, sta->sta.addr, err); | ||
395 | } else | ||
396 | sta->uploaded = true; | ||
397 | } | ||
537 | 398 | ||
538 | err = sta_info_finish_insert(sta, false, dummy_reinsert); | 399 | if (!dummy_reinsert) { |
539 | if (err) { | 400 | local->num_sta++; |
540 | mutex_unlock(&local->sta_mtx); | 401 | local->sta_generation++; |
541 | rcu_read_lock(); | 402 | smp_mb(); |
542 | return err; | 403 | |
404 | /* make the station visible */ | ||
405 | sta_info_hash_add(local, sta); | ||
406 | |||
407 | list_add(&sta->list, &local->sta_list); | ||
408 | } else { | ||
409 | sta->dummy = false; | ||
410 | } | ||
411 | |||
412 | if (!sta->dummy) { | ||
413 | struct station_info sinfo; | ||
414 | |||
415 | ieee80211_sta_debugfs_add(sta); | ||
416 | rate_control_add_sta_debugfs(sta); | ||
417 | |||
418 | memset(&sinfo, 0, sizeof(sinfo)); | ||
419 | sinfo.filled = 0; | ||
420 | sinfo.generation = local->sta_generation; | ||
421 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); | ||
543 | } | 422 | } |
544 | 423 | ||
545 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 424 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -555,54 +434,35 @@ static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU) | |||
555 | mesh_accept_plinks_update(sdata); | 434 | mesh_accept_plinks_update(sdata); |
556 | 435 | ||
557 | return 0; | 436 | return 0; |
437 | out_err: | ||
438 | mutex_unlock(&local->sta_mtx); | ||
439 | rcu_read_lock(); | ||
440 | return err; | ||
558 | } | 441 | } |
559 | 442 | ||
560 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) | 443 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) |
561 | { | 444 | { |
562 | struct ieee80211_local *local = sta->local; | 445 | struct ieee80211_local *local = sta->local; |
563 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
564 | int err = 0; | 446 | int err = 0; |
565 | 447 | ||
448 | might_sleep(); | ||
449 | |||
566 | err = sta_info_insert_check(sta); | 450 | err = sta_info_insert_check(sta); |
567 | if (err) { | 451 | if (err) { |
568 | rcu_read_lock(); | 452 | rcu_read_lock(); |
569 | goto out_free; | 453 | goto out_free; |
570 | } | 454 | } |
571 | 455 | ||
572 | /* | ||
573 | * In ad-hoc mode, we sometimes need to insert stations | ||
574 | * from tasklet context from the RX path. To avoid races, | ||
575 | * always do so in that case -- see the comment below. | ||
576 | */ | ||
577 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
578 | err = sta_info_insert_ibss(sta); | ||
579 | if (err) | ||
580 | goto out_free; | ||
581 | |||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | /* | ||
586 | * It might seem that the function called below is in race against | ||
587 | * the function call above that atomically inserts the station... That, | ||
588 | * however, is not true because the above code can only | ||
589 | * be invoked for IBSS interfaces, and the below code will | ||
590 | * not be -- and the two do not race against each other as | ||
591 | * the hash table also keys off the interface. | ||
592 | */ | ||
593 | |||
594 | might_sleep(); | ||
595 | |||
596 | mutex_lock(&local->sta_mtx); | 456 | mutex_lock(&local->sta_mtx); |
597 | 457 | ||
598 | err = sta_info_insert_non_ibss(sta); | 458 | err = sta_info_insert_finish(sta); |
599 | if (err) | 459 | if (err) |
600 | goto out_free; | 460 | goto out_free; |
601 | 461 | ||
602 | return 0; | 462 | return 0; |
603 | out_free: | 463 | out_free: |
604 | BUG_ON(!err); | 464 | BUG_ON(!err); |
605 | __sta_info_free(local, sta); | 465 | sta_info_free(local, sta); |
606 | return err; | 466 | return err; |
607 | } | 467 | } |
608 | 468 | ||
@@ -629,7 +489,7 @@ int sta_info_reinsert(struct sta_info *sta) | |||
629 | 489 | ||
630 | might_sleep(); | 490 | might_sleep(); |
631 | 491 | ||
632 | err = sta_info_insert_non_ibss(sta); | 492 | err = sta_info_insert_finish(sta); |
633 | rcu_read_unlock(); | 493 | rcu_read_unlock(); |
634 | return err; | 494 | return err; |
635 | } | 495 | } |
@@ -716,7 +576,7 @@ void sta_info_recalc_tim(struct sta_info *sta) | |||
716 | } | 576 | } |
717 | 577 | ||
718 | done: | 578 | done: |
719 | spin_lock_irqsave(&local->sta_lock, flags); | 579 | spin_lock_irqsave(&local->tim_lock, flags); |
720 | 580 | ||
721 | if (indicate_tim) | 581 | if (indicate_tim) |
722 | __bss_tim_set(bss, sta->sta.aid); | 582 | __bss_tim_set(bss, sta->sta.aid); |
@@ -729,7 +589,7 @@ void sta_info_recalc_tim(struct sta_info *sta) | |||
729 | local->tim_in_locked_section = false; | 589 | local->tim_in_locked_section = false; |
730 | } | 590 | } |
731 | 591 | ||
732 | spin_unlock_irqrestore(&local->sta_lock, flags); | 592 | spin_unlock_irqrestore(&local->tim_lock, flags); |
733 | } | 593 | } |
734 | 594 | ||
735 | static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb) | 595 | static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb) |
@@ -853,8 +713,8 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
853 | { | 713 | { |
854 | struct ieee80211_local *local; | 714 | struct ieee80211_local *local; |
855 | struct ieee80211_sub_if_data *sdata; | 715 | struct ieee80211_sub_if_data *sdata; |
856 | unsigned long flags; | ||
857 | int ret, i, ac; | 716 | int ret, i, ac; |
717 | struct tid_ampdu_tx *tid_tx; | ||
858 | 718 | ||
859 | might_sleep(); | 719 | might_sleep(); |
860 | 720 | ||
@@ -873,15 +733,12 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
873 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); | 733 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); |
874 | ieee80211_sta_tear_down_BA_sessions(sta, true); | 734 | ieee80211_sta_tear_down_BA_sessions(sta, true); |
875 | 735 | ||
876 | spin_lock_irqsave(&local->sta_lock, flags); | ||
877 | ret = sta_info_hash_del(local, sta); | 736 | ret = sta_info_hash_del(local, sta); |
878 | /* this might still be the pending list ... which is fine */ | ||
879 | if (!ret) | ||
880 | list_del(&sta->list); | ||
881 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
882 | if (ret) | 737 | if (ret) |
883 | return ret; | 738 | return ret; |
884 | 739 | ||
740 | list_del(&sta->list); | ||
741 | |||
885 | mutex_lock(&local->key_mtx); | 742 | mutex_lock(&local->key_mtx); |
886 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) | 743 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) |
887 | __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i])); | 744 | __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i])); |
@@ -908,6 +765,9 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
908 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 765 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
909 | RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); | 766 | RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); |
910 | 767 | ||
768 | while (sta->sta_state > IEEE80211_STA_NONE) | ||
769 | sta_info_move_state(sta, sta->sta_state - 1); | ||
770 | |||
911 | if (sta->uploaded) { | 771 | if (sta->uploaded) { |
912 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 772 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
913 | sdata = container_of(sdata->bss, | 773 | sdata = container_of(sdata->bss, |
@@ -953,7 +813,36 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
953 | } | 813 | } |
954 | #endif | 814 | #endif |
955 | 815 | ||
956 | __sta_info_free(local, sta); | 816 | /* There could be some memory leaks because of ampdu tx pending queue |
817 | * not being freed before destroying the station info. | ||
818 | * | ||
819 | * Make sure that such queues are purged before freeing the station | ||
820 | * info. | ||
821 | * TODO: We have to somehow postpone the full destruction | ||
822 | * until the aggregation stop completes. Refer | ||
823 | * http://thread.gmane.org/gmane.linux.kernel.wireless.general/81936 | ||
824 | */ | ||
825 | |||
826 | mutex_lock(&sta->ampdu_mlme.mtx); | ||
827 | |||
828 | for (i = 0; i < STA_TID_NUM; i++) { | ||
829 | tid_tx = rcu_dereference_protected_tid_tx(sta, i); | ||
830 | if (!tid_tx) | ||
831 | continue; | ||
832 | if (skb_queue_len(&tid_tx->pending)) { | ||
833 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
834 | wiphy_debug(local->hw.wiphy, "TX A-MPDU purging %d " | ||
835 | "packets for tid=%d\n", | ||
836 | skb_queue_len(&tid_tx->pending), i); | ||
837 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
838 | __skb_queue_purge(&tid_tx->pending); | ||
839 | } | ||
840 | kfree_rcu(tid_tx, rcu_head); | ||
841 | } | ||
842 | |||
843 | mutex_unlock(&sta->ampdu_mlme.mtx); | ||
844 | |||
845 | sta_info_free(local, sta); | ||
957 | 846 | ||
958 | return 0; | 847 | return 0; |
959 | } | 848 | } |
@@ -1009,11 +898,9 @@ static void sta_info_cleanup(unsigned long data) | |||
1009 | 898 | ||
1010 | void sta_info_init(struct ieee80211_local *local) | 899 | void sta_info_init(struct ieee80211_local *local) |
1011 | { | 900 | { |
1012 | spin_lock_init(&local->sta_lock); | 901 | spin_lock_init(&local->tim_lock); |
1013 | mutex_init(&local->sta_mtx); | 902 | mutex_init(&local->sta_mtx); |
1014 | INIT_LIST_HEAD(&local->sta_list); | 903 | INIT_LIST_HEAD(&local->sta_list); |
1015 | INIT_LIST_HEAD(&local->sta_pending_list); | ||
1016 | INIT_WORK(&local->sta_finish_work, sta_info_finish_work); | ||
1017 | 904 | ||
1018 | setup_timer(&local->sta_cleanup, sta_info_cleanup, | 905 | setup_timer(&local->sta_cleanup, sta_info_cleanup, |
1019 | (unsigned long)local); | 906 | (unsigned long)local); |
@@ -1042,9 +929,6 @@ int sta_info_flush(struct ieee80211_local *local, | |||
1042 | might_sleep(); | 929 | might_sleep(); |
1043 | 930 | ||
1044 | mutex_lock(&local->sta_mtx); | 931 | mutex_lock(&local->sta_mtx); |
1045 | |||
1046 | sta_info_finish_pending(local); | ||
1047 | |||
1048 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { | 932 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { |
1049 | if (!sdata || sdata == sta->sdata) | 933 | if (!sdata || sdata == sta->sdata) |
1050 | WARN_ON(__sta_info_destroy(sta)); | 934 | WARN_ON(__sta_info_destroy(sta)); |
@@ -1061,7 +945,11 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | |||
1061 | struct sta_info *sta, *tmp; | 945 | struct sta_info *sta, *tmp; |
1062 | 946 | ||
1063 | mutex_lock(&local->sta_mtx); | 947 | mutex_lock(&local->sta_mtx); |
1064 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) | 948 | |
949 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { | ||
950 | if (sdata != sta->sdata) | ||
951 | continue; | ||
952 | |||
1065 | if (time_after(jiffies, sta->last_rx + exp_time)) { | 953 | if (time_after(jiffies, sta->last_rx + exp_time)) { |
1066 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 954 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
1067 | printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", | 955 | printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", |
@@ -1069,6 +957,8 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | |||
1069 | #endif | 957 | #endif |
1070 | WARN_ON(__sta_info_destroy(sta)); | 958 | WARN_ON(__sta_info_destroy(sta)); |
1071 | } | 959 | } |
960 | } | ||
961 | |||
1072 | mutex_unlock(&local->sta_mtx); | 962 | mutex_unlock(&local->sta_mtx); |
1073 | } | 963 | } |
1074 | 964 | ||
@@ -1517,3 +1407,56 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, | |||
1517 | sta_info_recalc_tim(sta); | 1407 | sta_info_recalc_tim(sta); |
1518 | } | 1408 | } |
1519 | EXPORT_SYMBOL(ieee80211_sta_set_buffered); | 1409 | EXPORT_SYMBOL(ieee80211_sta_set_buffered); |
1410 | |||
1411 | int sta_info_move_state_checked(struct sta_info *sta, | ||
1412 | enum ieee80211_sta_state new_state) | ||
1413 | { | ||
1414 | might_sleep(); | ||
1415 | |||
1416 | if (sta->sta_state == new_state) | ||
1417 | return 0; | ||
1418 | |||
1419 | switch (new_state) { | ||
1420 | case IEEE80211_STA_NONE: | ||
1421 | if (sta->sta_state == IEEE80211_STA_AUTH) | ||
1422 | clear_bit(WLAN_STA_AUTH, &sta->_flags); | ||
1423 | else | ||
1424 | return -EINVAL; | ||
1425 | break; | ||
1426 | case IEEE80211_STA_AUTH: | ||
1427 | if (sta->sta_state == IEEE80211_STA_NONE) | ||
1428 | set_bit(WLAN_STA_AUTH, &sta->_flags); | ||
1429 | else if (sta->sta_state == IEEE80211_STA_ASSOC) | ||
1430 | clear_bit(WLAN_STA_ASSOC, &sta->_flags); | ||
1431 | else | ||
1432 | return -EINVAL; | ||
1433 | break; | ||
1434 | case IEEE80211_STA_ASSOC: | ||
1435 | if (sta->sta_state == IEEE80211_STA_AUTH) { | ||
1436 | set_bit(WLAN_STA_ASSOC, &sta->_flags); | ||
1437 | } else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) { | ||
1438 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP) | ||
1439 | atomic_dec(&sta->sdata->u.ap.num_sta_authorized); | ||
1440 | clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags); | ||
1441 | } else | ||
1442 | return -EINVAL; | ||
1443 | break; | ||
1444 | case IEEE80211_STA_AUTHORIZED: | ||
1445 | if (sta->sta_state == IEEE80211_STA_ASSOC) { | ||
1446 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP) | ||
1447 | atomic_inc(&sta->sdata->u.ap.num_sta_authorized); | ||
1448 | set_bit(WLAN_STA_AUTHORIZED, &sta->_flags); | ||
1449 | } else | ||
1450 | return -EINVAL; | ||
1451 | break; | ||
1452 | default: | ||
1453 | WARN(1, "invalid state %d", new_state); | ||
1454 | return -EINVAL; | ||
1455 | } | ||
1456 | |||
1457 | printk(KERN_DEBUG "%s: moving STA %pM to state %d\n", | ||
1458 | sta->sdata->name, sta->sta.addr, new_state); | ||
1459 | sta->sta_state = new_state; | ||
1460 | |||
1461 | return 0; | ||
1462 | } | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 8c8ce05ad26f..6f77f12dc3fc 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -30,7 +30,6 @@ | |||
30 | * when virtual port control is not in use. | 30 | * when virtual port control is not in use. |
31 | * @WLAN_STA_SHORT_PREAMBLE: Station is capable of receiving short-preamble | 31 | * @WLAN_STA_SHORT_PREAMBLE: Station is capable of receiving short-preamble |
32 | * frames. | 32 | * frames. |
33 | * @WLAN_STA_ASSOC_AP: We're associated to that station, it is an AP. | ||
34 | * @WLAN_STA_WME: Station is a QoS-STA. | 33 | * @WLAN_STA_WME: Station is a QoS-STA. |
35 | * @WLAN_STA_WDS: Station is one of our WDS peers. | 34 | * @WLAN_STA_WDS: Station is one of our WDS peers. |
36 | * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the | 35 | * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the |
@@ -52,6 +51,7 @@ | |||
52 | * unblocks the station. | 51 | * unblocks the station. |
53 | * @WLAN_STA_SP: Station is in a service period, so don't try to | 52 | * @WLAN_STA_SP: Station is in a service period, so don't try to |
54 | * reply to other uAPSD trigger frames or PS-Poll. | 53 | * reply to other uAPSD trigger frames or PS-Poll. |
54 | * @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame. | ||
55 | */ | 55 | */ |
56 | enum ieee80211_sta_info_flags { | 56 | enum ieee80211_sta_info_flags { |
57 | WLAN_STA_AUTH, | 57 | WLAN_STA_AUTH, |
@@ -59,7 +59,6 @@ enum ieee80211_sta_info_flags { | |||
59 | WLAN_STA_PS_STA, | 59 | WLAN_STA_PS_STA, |
60 | WLAN_STA_AUTHORIZED, | 60 | WLAN_STA_AUTHORIZED, |
61 | WLAN_STA_SHORT_PREAMBLE, | 61 | WLAN_STA_SHORT_PREAMBLE, |
62 | WLAN_STA_ASSOC_AP, | ||
63 | WLAN_STA_WME, | 62 | WLAN_STA_WME, |
64 | WLAN_STA_WDS, | 63 | WLAN_STA_WDS, |
65 | WLAN_STA_CLEAR_PS_FILT, | 64 | WLAN_STA_CLEAR_PS_FILT, |
@@ -71,11 +70,22 @@ enum ieee80211_sta_info_flags { | |||
71 | WLAN_STA_TDLS_PEER_AUTH, | 70 | WLAN_STA_TDLS_PEER_AUTH, |
72 | WLAN_STA_UAPSD, | 71 | WLAN_STA_UAPSD, |
73 | WLAN_STA_SP, | 72 | WLAN_STA_SP, |
73 | WLAN_STA_4ADDR_EVENT, | ||
74 | }; | ||
75 | |||
76 | enum ieee80211_sta_state { | ||
77 | /* NOTE: These need to be ordered correctly! */ | ||
78 | IEEE80211_STA_NONE, | ||
79 | IEEE80211_STA_AUTH, | ||
80 | IEEE80211_STA_ASSOC, | ||
81 | IEEE80211_STA_AUTHORIZED, | ||
74 | }; | 82 | }; |
75 | 83 | ||
76 | #define STA_TID_NUM 16 | 84 | #define STA_TID_NUM 16 |
77 | #define ADDBA_RESP_INTERVAL HZ | 85 | #define ADDBA_RESP_INTERVAL HZ |
78 | #define HT_AGG_MAX_RETRIES 0x3 | 86 | #define HT_AGG_MAX_RETRIES 15 |
87 | #define HT_AGG_BURST_RETRIES 3 | ||
88 | #define HT_AGG_RETRIES_PERIOD (15 * HZ) | ||
79 | 89 | ||
80 | #define HT_AGG_STATE_DRV_READY 0 | 90 | #define HT_AGG_STATE_DRV_READY 0 |
81 | #define HT_AGG_STATE_RESPONSE_RECEIVED 1 | 91 | #define HT_AGG_STATE_RESPONSE_RECEIVED 1 |
@@ -88,6 +98,7 @@ enum ieee80211_sta_info_flags { | |||
88 | * struct tid_ampdu_tx - TID aggregation information (Tx). | 98 | * struct tid_ampdu_tx - TID aggregation information (Tx). |
89 | * | 99 | * |
90 | * @rcu_head: rcu head for freeing structure | 100 | * @rcu_head: rcu head for freeing structure |
101 | * @session_timer: check if we keep Tx-ing on the TID (by timeout value) | ||
91 | * @addba_resp_timer: timer for peer's response to addba request | 102 | * @addba_resp_timer: timer for peer's response to addba request |
92 | * @pending: pending frames queue -- use sta's spinlock to protect | 103 | * @pending: pending frames queue -- use sta's spinlock to protect |
93 | * @dialog_token: dialog token for aggregation session | 104 | * @dialog_token: dialog token for aggregation session |
@@ -110,6 +121,7 @@ enum ieee80211_sta_info_flags { | |||
110 | */ | 121 | */ |
111 | struct tid_ampdu_tx { | 122 | struct tid_ampdu_tx { |
112 | struct rcu_head rcu_head; | 123 | struct rcu_head rcu_head; |
124 | struct timer_list session_timer; | ||
113 | struct timer_list addba_resp_timer; | 125 | struct timer_list addba_resp_timer; |
114 | struct sk_buff_head pending; | 126 | struct sk_buff_head pending; |
115 | unsigned long state; | 127 | unsigned long state; |
@@ -169,6 +181,7 @@ struct tid_ampdu_rx { | |||
169 | * @tid_tx: aggregation info for Tx per TID | 181 | * @tid_tx: aggregation info for Tx per TID |
170 | * @tid_start_tx: sessions where start was requested | 182 | * @tid_start_tx: sessions where start was requested |
171 | * @addba_req_num: number of times addBA request has been sent. | 183 | * @addba_req_num: number of times addBA request has been sent. |
184 | * @last_addba_req_time: timestamp of the last addBA request. | ||
172 | * @dialog_token_allocator: dialog token enumerator for each new session; | 185 | * @dialog_token_allocator: dialog token enumerator for each new session; |
173 | * @work: work struct for starting/stopping aggregation | 186 | * @work: work struct for starting/stopping aggregation |
174 | * @tid_rx_timer_expired: bitmap indicating on which TIDs the | 187 | * @tid_rx_timer_expired: bitmap indicating on which TIDs the |
@@ -188,6 +201,7 @@ struct sta_ampdu_mlme { | |||
188 | struct work_struct work; | 201 | struct work_struct work; |
189 | struct tid_ampdu_tx __rcu *tid_tx[STA_TID_NUM]; | 202 | struct tid_ampdu_tx __rcu *tid_tx[STA_TID_NUM]; |
190 | struct tid_ampdu_tx *tid_start_tx[STA_TID_NUM]; | 203 | struct tid_ampdu_tx *tid_start_tx[STA_TID_NUM]; |
204 | unsigned long last_addba_req_time[STA_TID_NUM]; | ||
191 | u8 addba_req_num[STA_TID_NUM]; | 205 | u8 addba_req_num[STA_TID_NUM]; |
192 | u8 dialog_token_allocator; | 206 | u8 dialog_token_allocator; |
193 | }; | 207 | }; |
@@ -260,6 +274,8 @@ struct sta_ampdu_mlme { | |||
260 | * @dummy: indicate a dummy station created for receiving | 274 | * @dummy: indicate a dummy station created for receiving |
261 | * EAP frames before association | 275 | * EAP frames before association |
262 | * @sta: station information we share with the driver | 276 | * @sta: station information we share with the driver |
277 | * @sta_state: duplicates information about station state (for debug) | ||
278 | * @beacon_loss_count: number of times beacon loss has triggered | ||
263 | */ | 279 | */ |
264 | struct sta_info { | 280 | struct sta_info { |
265 | /* General information, mostly static */ | 281 | /* General information, mostly static */ |
@@ -281,6 +297,8 @@ struct sta_info { | |||
281 | 297 | ||
282 | bool uploaded; | 298 | bool uploaded; |
283 | 299 | ||
300 | enum ieee80211_sta_state sta_state; | ||
301 | |||
284 | /* use the accessors defined below */ | 302 | /* use the accessors defined below */ |
285 | unsigned long _flags; | 303 | unsigned long _flags; |
286 | 304 | ||
@@ -350,6 +368,7 @@ struct sta_info { | |||
350 | #endif | 368 | #endif |
351 | 369 | ||
352 | unsigned int lost_packets; | 370 | unsigned int lost_packets; |
371 | unsigned int beacon_loss_count; | ||
353 | 372 | ||
354 | /* should be right in front of sta to be in the same cache line */ | 373 | /* should be right in front of sta to be in the same cache line */ |
355 | bool dummy; | 374 | bool dummy; |
@@ -369,12 +388,18 @@ static inline enum nl80211_plink_state sta_plink_state(struct sta_info *sta) | |||
369 | static inline void set_sta_flag(struct sta_info *sta, | 388 | static inline void set_sta_flag(struct sta_info *sta, |
370 | enum ieee80211_sta_info_flags flag) | 389 | enum ieee80211_sta_info_flags flag) |
371 | { | 390 | { |
391 | WARN_ON(flag == WLAN_STA_AUTH || | ||
392 | flag == WLAN_STA_ASSOC || | ||
393 | flag == WLAN_STA_AUTHORIZED); | ||
372 | set_bit(flag, &sta->_flags); | 394 | set_bit(flag, &sta->_flags); |
373 | } | 395 | } |
374 | 396 | ||
375 | static inline void clear_sta_flag(struct sta_info *sta, | 397 | static inline void clear_sta_flag(struct sta_info *sta, |
376 | enum ieee80211_sta_info_flags flag) | 398 | enum ieee80211_sta_info_flags flag) |
377 | { | 399 | { |
400 | WARN_ON(flag == WLAN_STA_AUTH || | ||
401 | flag == WLAN_STA_ASSOC || | ||
402 | flag == WLAN_STA_AUTHORIZED); | ||
378 | clear_bit(flag, &sta->_flags); | 403 | clear_bit(flag, &sta->_flags); |
379 | } | 404 | } |
380 | 405 | ||
@@ -387,9 +412,32 @@ static inline int test_sta_flag(struct sta_info *sta, | |||
387 | static inline int test_and_clear_sta_flag(struct sta_info *sta, | 412 | static inline int test_and_clear_sta_flag(struct sta_info *sta, |
388 | enum ieee80211_sta_info_flags flag) | 413 | enum ieee80211_sta_info_flags flag) |
389 | { | 414 | { |
415 | WARN_ON(flag == WLAN_STA_AUTH || | ||
416 | flag == WLAN_STA_ASSOC || | ||
417 | flag == WLAN_STA_AUTHORIZED); | ||
390 | return test_and_clear_bit(flag, &sta->_flags); | 418 | return test_and_clear_bit(flag, &sta->_flags); |
391 | } | 419 | } |
392 | 420 | ||
421 | static inline int test_and_set_sta_flag(struct sta_info *sta, | ||
422 | enum ieee80211_sta_info_flags flag) | ||
423 | { | ||
424 | WARN_ON(flag == WLAN_STA_AUTH || | ||
425 | flag == WLAN_STA_ASSOC || | ||
426 | flag == WLAN_STA_AUTHORIZED); | ||
427 | return test_and_set_bit(flag, &sta->_flags); | ||
428 | } | ||
429 | |||
430 | int sta_info_move_state_checked(struct sta_info *sta, | ||
431 | enum ieee80211_sta_state new_state); | ||
432 | |||
433 | static inline void sta_info_move_state(struct sta_info *sta, | ||
434 | enum ieee80211_sta_state new_state) | ||
435 | { | ||
436 | int ret = sta_info_move_state_checked(sta, new_state); | ||
437 | WARN_ON_ONCE(ret); | ||
438 | } | ||
439 | |||
440 | |||
393 | void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, | 441 | void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, |
394 | struct tid_ampdu_tx *tid_tx); | 442 | struct tid_ampdu_tx *tid_tx); |
395 | 443 | ||
@@ -480,7 +528,10 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, | |||
480 | * until sta_info_insert(). | 528 | * until sta_info_insert(). |
481 | */ | 529 | */ |
482 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | 530 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, |
483 | u8 *addr, gfp_t gfp); | 531 | const u8 *addr, gfp_t gfp); |
532 | |||
533 | void sta_info_free(struct ieee80211_local *local, struct sta_info *sta); | ||
534 | |||
484 | /* | 535 | /* |
485 | * Insert STA info into hash table/list, returns zero or a | 536 | * Insert STA info into hash table/list, returns zero or a |
486 | * -EEXIST if (if the same MAC address is already present). | 537 | * -EEXIST if (if the same MAC address is already present). |
@@ -491,7 +542,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
491 | */ | 542 | */ |
492 | int sta_info_insert(struct sta_info *sta); | 543 | int sta_info_insert(struct sta_info *sta); |
493 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); | 544 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); |
494 | int sta_info_insert_atomic(struct sta_info *sta); | ||
495 | int sta_info_reinsert(struct sta_info *sta); | 545 | int sta_info_reinsert(struct sta_info *sta); |
496 | 546 | ||
497 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, | 547 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 16518f386117..30c265c98f73 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -340,7 +340,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
340 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 340 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
341 | struct ieee80211_local *local = hw_to_local(hw); | 341 | struct ieee80211_local *local = hw_to_local(hw); |
342 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 342 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
343 | u16 frag, type; | ||
344 | __le16 fc; | 343 | __le16 fc; |
345 | struct ieee80211_supported_band *sband; | 344 | struct ieee80211_supported_band *sband; |
346 | struct ieee80211_sub_if_data *sdata; | 345 | struct ieee80211_sub_if_data *sdata; |
@@ -476,12 +475,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
476 | * Fragments are passed to low-level drivers as separate skbs, so these | 475 | * Fragments are passed to low-level drivers as separate skbs, so these |
477 | * are actually fragments, not frames. Update frame counters only for | 476 | * are actually fragments, not frames. Update frame counters only for |
478 | * the first fragment of the frame. */ | 477 | * the first fragment of the frame. */ |
479 | |||
480 | frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; | ||
481 | type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE; | ||
482 | |||
483 | if (info->flags & IEEE80211_TX_STAT_ACK) { | 478 | if (info->flags & IEEE80211_TX_STAT_ACK) { |
484 | if (frag == 0) { | 479 | if (ieee80211_is_first_frag(hdr->seq_ctrl)) { |
485 | local->dot11TransmittedFrameCount++; | 480 | local->dot11TransmittedFrameCount++; |
486 | if (is_multicast_ether_addr(hdr->addr1)) | 481 | if (is_multicast_ether_addr(hdr->addr1)) |
487 | local->dot11MulticastTransmittedFrameCount++; | 482 | local->dot11MulticastTransmittedFrameCount++; |
@@ -496,11 +491,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
496 | * with a multicast address in the address 1 field of type Data | 491 | * with a multicast address in the address 1 field of type Data |
497 | * or Management. */ | 492 | * or Management. */ |
498 | if (!is_multicast_ether_addr(hdr->addr1) || | 493 | if (!is_multicast_ether_addr(hdr->addr1) || |
499 | type == IEEE80211_FTYPE_DATA || | 494 | ieee80211_is_data(fc) || |
500 | type == IEEE80211_FTYPE_MGMT) | 495 | ieee80211_is_mgmt(fc)) |
501 | local->dot11TransmittedFragmentCount++; | 496 | local->dot11TransmittedFragmentCount++; |
502 | } else { | 497 | } else { |
503 | if (frag == 0) | 498 | if (ieee80211_is_first_frag(hdr->seq_ctrl)) |
504 | local->dot11FailedCount++; | 499 | local->dot11FailedCount++; |
505 | } | 500 | } |
506 | 501 | ||
@@ -517,27 +512,54 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
517 | } | 512 | } |
518 | 513 | ||
519 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { | 514 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { |
520 | struct ieee80211_work *wk; | ||
521 | u64 cookie = (unsigned long)skb; | 515 | u64 cookie = (unsigned long)skb; |
522 | 516 | ||
523 | rcu_read_lock(); | 517 | if (ieee80211_is_nullfunc(hdr->frame_control) || |
524 | list_for_each_entry_rcu(wk, &local->work_list, list) { | 518 | ieee80211_is_qos_nullfunc(hdr->frame_control)) { |
525 | if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX) | 519 | bool acked = info->flags & IEEE80211_TX_STAT_ACK; |
526 | continue; | 520 | cfg80211_probe_status(skb->dev, hdr->addr1, |
527 | if (wk->offchan_tx.frame != skb) | 521 | cookie, acked, GFP_ATOMIC); |
528 | continue; | 522 | } else { |
529 | wk->offchan_tx.status = true; | 523 | struct ieee80211_work *wk; |
530 | break; | 524 | |
531 | } | 525 | rcu_read_lock(); |
532 | rcu_read_unlock(); | 526 | list_for_each_entry_rcu(wk, &local->work_list, list) { |
533 | if (local->hw_roc_skb_for_status == skb) { | 527 | if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX) |
534 | cookie = local->hw_roc_cookie ^ 2; | 528 | continue; |
535 | local->hw_roc_skb_for_status = NULL; | 529 | if (wk->offchan_tx.frame != skb) |
530 | continue; | ||
531 | wk->offchan_tx.status = true; | ||
532 | break; | ||
533 | } | ||
534 | rcu_read_unlock(); | ||
535 | if (local->hw_roc_skb_for_status == skb) { | ||
536 | cookie = local->hw_roc_cookie ^ 2; | ||
537 | local->hw_roc_skb_for_status = NULL; | ||
538 | } | ||
539 | |||
540 | cfg80211_mgmt_tx_status( | ||
541 | skb->dev, cookie, skb->data, skb->len, | ||
542 | !!(info->flags & IEEE80211_TX_STAT_ACK), | ||
543 | GFP_ATOMIC); | ||
536 | } | 544 | } |
545 | } | ||
537 | 546 | ||
538 | cfg80211_mgmt_tx_status( | 547 | if (unlikely(info->ack_frame_id)) { |
539 | skb->dev, cookie, skb->data, skb->len, | 548 | struct sk_buff *ack_skb; |
540 | !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); | 549 | unsigned long flags; |
550 | |||
551 | spin_lock_irqsave(&local->ack_status_lock, flags); | ||
552 | ack_skb = idr_find(&local->ack_status_frames, | ||
553 | info->ack_frame_id); | ||
554 | if (ack_skb) | ||
555 | idr_remove(&local->ack_status_frames, | ||
556 | info->ack_frame_id); | ||
557 | spin_unlock_irqrestore(&local->ack_status_lock, flags); | ||
558 | |||
559 | /* consumes ack_skb */ | ||
560 | if (ack_skb) | ||
561 | skb_complete_wifi_ack(ack_skb, | ||
562 | info->flags & IEEE80211_TX_STAT_ACK); | ||
541 | } | 563 | } |
542 | 564 | ||
543 | /* this was a transmitted frame, but now we want to reuse it */ | 565 | /* this was a transmitted frame, but now we want to reuse it */ |
@@ -545,7 +567,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
545 | 567 | ||
546 | /* Need to make a copy before skb->cb gets cleared */ | 568 | /* Need to make a copy before skb->cb gets cleared */ |
547 | send_to_cooked = !!(info->flags & IEEE80211_TX_CTL_INJECTED) || | 569 | send_to_cooked = !!(info->flags & IEEE80211_TX_CTL_INJECTED) || |
548 | (type != IEEE80211_FTYPE_DATA); | 570 | !(ieee80211_is_data(fc)); |
549 | 571 | ||
550 | /* | 572 | /* |
551 | * This is a bit racy but we can avoid a lot of work | 573 | * This is a bit racy but we can avoid a lot of work |
@@ -610,3 +632,29 @@ void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets) | |||
610 | num_packets, GFP_ATOMIC); | 632 | num_packets, GFP_ATOMIC); |
611 | } | 633 | } |
612 | EXPORT_SYMBOL(ieee80211_report_low_ack); | 634 | EXPORT_SYMBOL(ieee80211_report_low_ack); |
635 | |||
636 | void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
637 | { | ||
638 | struct ieee80211_local *local = hw_to_local(hw); | ||
639 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
640 | |||
641 | if (unlikely(info->ack_frame_id)) { | ||
642 | struct sk_buff *ack_skb; | ||
643 | unsigned long flags; | ||
644 | |||
645 | spin_lock_irqsave(&local->ack_status_lock, flags); | ||
646 | ack_skb = idr_find(&local->ack_status_frames, | ||
647 | info->ack_frame_id); | ||
648 | if (ack_skb) | ||
649 | idr_remove(&local->ack_status_frames, | ||
650 | info->ack_frame_id); | ||
651 | spin_unlock_irqrestore(&local->ack_status_lock, flags); | ||
652 | |||
653 | /* consumes ack_skb */ | ||
654 | if (ack_skb) | ||
655 | dev_kfree_skb_any(ack_skb); | ||
656 | } | ||
657 | |||
658 | dev_kfree_skb_any(skb); | ||
659 | } | ||
660 | EXPORT_SYMBOL(ieee80211_free_txskb); | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 1f8b120146d1..edcd1c7ab83f 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -36,7 +36,8 @@ | |||
36 | 36 | ||
37 | /* misc utils */ | 37 | /* misc utils */ |
38 | 38 | ||
39 | static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | 39 | static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, |
40 | struct sk_buff *skb, int group_addr, | ||
40 | int next_frag_len) | 41 | int next_frag_len) |
41 | { | 42 | { |
42 | int rate, mrate, erp, dur, i; | 43 | int rate, mrate, erp, dur, i; |
@@ -44,7 +45,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
44 | struct ieee80211_local *local = tx->local; | 45 | struct ieee80211_local *local = tx->local; |
45 | struct ieee80211_supported_band *sband; | 46 | struct ieee80211_supported_band *sband; |
46 | struct ieee80211_hdr *hdr; | 47 | struct ieee80211_hdr *hdr; |
47 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 48 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
48 | 49 | ||
49 | /* assume HW handles this */ | 50 | /* assume HW handles this */ |
50 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS) | 51 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS) |
@@ -76,7 +77,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
76 | * at the highest possible rate belonging to the PHY rates in the | 77 | * at the highest possible rate belonging to the PHY rates in the |
77 | * BSSBasicRateSet | 78 | * BSSBasicRateSet |
78 | */ | 79 | */ |
79 | hdr = (struct ieee80211_hdr *)tx->skb->data; | 80 | hdr = (struct ieee80211_hdr *)skb->data; |
80 | if (ieee80211_is_ctl(hdr->frame_control)) { | 81 | if (ieee80211_is_ctl(hdr->frame_control)) { |
81 | /* TODO: These control frames are not currently sent by | 82 | /* TODO: These control frames are not currently sent by |
82 | * mac80211, but should they be implemented, this function | 83 | * mac80211, but should they be implemented, this function |
@@ -150,11 +151,15 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
150 | rate = mrate; | 151 | rate = mrate; |
151 | } | 152 | } |
152 | 153 | ||
153 | /* Time needed to transmit ACK | 154 | /* Don't calculate ACKs for QoS Frames with NoAck Policy set */ |
154 | * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up | 155 | if (ieee80211_is_data_qos(hdr->frame_control) && |
155 | * to closest integer */ | 156 | *(ieee80211_get_qos_ctl(hdr)) | IEEE80211_QOS_CTL_ACK_POLICY_NOACK) |
156 | 157 | dur = 0; | |
157 | dur = ieee80211_frame_duration(local, 10, rate, erp, | 158 | else |
159 | /* Time needed to transmit ACK | ||
160 | * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up | ||
161 | * to closest integer */ | ||
162 | dur = ieee80211_frame_duration(local, 10, rate, erp, | ||
158 | tx->sdata->vif.bss_conf.use_short_preamble); | 163 | tx->sdata->vif.bss_conf.use_short_preamble); |
159 | 164 | ||
160 | if (next_frag_len) { | 165 | if (next_frag_len) { |
@@ -290,7 +295,6 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
290 | 295 | ||
291 | if (likely(tx->flags & IEEE80211_TX_UNICAST)) { | 296 | if (likely(tx->flags & IEEE80211_TX_UNICAST)) { |
292 | if (unlikely(!assoc && | 297 | if (unlikely(!assoc && |
293 | tx->sdata->vif.type != NL80211_IFTYPE_ADHOC && | ||
294 | ieee80211_is_data(hdr->frame_control))) { | 298 | ieee80211_is_data(hdr->frame_control))) { |
295 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 299 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
296 | printk(KERN_DEBUG "%s: dropped data frame to not " | 300 | printk(KERN_DEBUG "%s: dropped data frame to not " |
@@ -300,17 +304,14 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
300 | I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); | 304 | I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); |
301 | return TX_DROP; | 305 | return TX_DROP; |
302 | } | 306 | } |
303 | } else { | 307 | } else if (unlikely(tx->sdata->vif.type == NL80211_IFTYPE_AP && |
304 | if (unlikely(ieee80211_is_data(hdr->frame_control) && | 308 | ieee80211_is_data(hdr->frame_control) && |
305 | tx->local->num_sta == 0 && | 309 | !atomic_read(&tx->sdata->u.ap.num_sta_authorized))) { |
306 | tx->sdata->vif.type != NL80211_IFTYPE_ADHOC)) { | 310 | /* |
307 | /* | 311 | * No associated STAs - no need to send multicast |
308 | * No associated STAs - no need to send multicast | 312 | * frames. |
309 | * frames. | 313 | */ |
310 | */ | 314 | return TX_DROP; |
311 | return TX_DROP; | ||
312 | } | ||
313 | return TX_CONTINUE; | ||
314 | } | 315 | } |
315 | 316 | ||
316 | return TX_CONTINUE; | 317 | return TX_CONTINUE; |
@@ -572,8 +573,6 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
572 | switch (tx->key->conf.cipher) { | 573 | switch (tx->key->conf.cipher) { |
573 | case WLAN_CIPHER_SUITE_WEP40: | 574 | case WLAN_CIPHER_SUITE_WEP40: |
574 | case WLAN_CIPHER_SUITE_WEP104: | 575 | case WLAN_CIPHER_SUITE_WEP104: |
575 | if (ieee80211_is_auth(hdr->frame_control)) | ||
576 | break; | ||
577 | case WLAN_CIPHER_SUITE_TKIP: | 576 | case WLAN_CIPHER_SUITE_TKIP: |
578 | if (!ieee80211_is_data_present(hdr->frame_control)) | 577 | if (!ieee80211_is_data_present(hdr->frame_control)) |
579 | tx->key = NULL; | 578 | tx->key = NULL; |
@@ -637,6 +636,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
637 | else | 636 | else |
638 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | 637 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; |
639 | txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP || | 638 | txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP || |
639 | tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT || | ||
640 | tx->sdata->vif.type == NL80211_IFTYPE_ADHOC); | 640 | tx->sdata->vif.type == NL80211_IFTYPE_ADHOC); |
641 | 641 | ||
642 | /* set up RTS protection if desired */ | 642 | /* set up RTS protection if desired */ |
@@ -844,11 +844,13 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
844 | return TX_CONTINUE; | 844 | return TX_CONTINUE; |
845 | } | 845 | } |
846 | 846 | ||
847 | static int ieee80211_fragment(struct ieee80211_local *local, | 847 | static int ieee80211_fragment(struct ieee80211_tx_data *tx, |
848 | struct sk_buff *skb, int hdrlen, | 848 | struct sk_buff *skb, int hdrlen, |
849 | int frag_threshold) | 849 | int frag_threshold) |
850 | { | 850 | { |
851 | struct sk_buff *tail = skb, *tmp; | 851 | struct ieee80211_local *local = tx->local; |
852 | struct ieee80211_tx_info *info; | ||
853 | struct sk_buff *tmp; | ||
852 | int per_fragm = frag_threshold - hdrlen - FCS_LEN; | 854 | int per_fragm = frag_threshold - hdrlen - FCS_LEN; |
853 | int pos = hdrlen + per_fragm; | 855 | int pos = hdrlen + per_fragm; |
854 | int rem = skb->len - hdrlen - per_fragm; | 856 | int rem = skb->len - hdrlen - per_fragm; |
@@ -856,6 +858,8 @@ static int ieee80211_fragment(struct ieee80211_local *local, | |||
856 | if (WARN_ON(rem < 0)) | 858 | if (WARN_ON(rem < 0)) |
857 | return -EINVAL; | 859 | return -EINVAL; |
858 | 860 | ||
861 | /* first fragment was already added to queue by caller */ | ||
862 | |||
859 | while (rem) { | 863 | while (rem) { |
860 | int fraglen = per_fragm; | 864 | int fraglen = per_fragm; |
861 | 865 | ||
@@ -868,12 +872,21 @@ static int ieee80211_fragment(struct ieee80211_local *local, | |||
868 | IEEE80211_ENCRYPT_TAILROOM); | 872 | IEEE80211_ENCRYPT_TAILROOM); |
869 | if (!tmp) | 873 | if (!tmp) |
870 | return -ENOMEM; | 874 | return -ENOMEM; |
871 | tail->next = tmp; | 875 | |
872 | tail = tmp; | 876 | __skb_queue_tail(&tx->skbs, tmp); |
877 | |||
873 | skb_reserve(tmp, local->tx_headroom + | 878 | skb_reserve(tmp, local->tx_headroom + |
874 | IEEE80211_ENCRYPT_HEADROOM); | 879 | IEEE80211_ENCRYPT_HEADROOM); |
875 | /* copy control information */ | 880 | /* copy control information */ |
876 | memcpy(tmp->cb, skb->cb, sizeof(tmp->cb)); | 881 | memcpy(tmp->cb, skb->cb, sizeof(tmp->cb)); |
882 | |||
883 | info = IEEE80211_SKB_CB(tmp); | ||
884 | info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | | ||
885 | IEEE80211_TX_CTL_FIRST_FRAGMENT); | ||
886 | |||
887 | if (rem) | ||
888 | info->flags |= IEEE80211_TX_CTL_MORE_FRAMES; | ||
889 | |||
877 | skb_copy_queue_mapping(tmp, skb); | 890 | skb_copy_queue_mapping(tmp, skb); |
878 | tmp->priority = skb->priority; | 891 | tmp->priority = skb->priority; |
879 | tmp->dev = skb->dev; | 892 | tmp->dev = skb->dev; |
@@ -885,6 +898,7 @@ static int ieee80211_fragment(struct ieee80211_local *local, | |||
885 | pos += fraglen; | 898 | pos += fraglen; |
886 | } | 899 | } |
887 | 900 | ||
901 | /* adjust first fragment's length */ | ||
888 | skb->len = hdrlen + per_fragm; | 902 | skb->len = hdrlen + per_fragm; |
889 | return 0; | 903 | return 0; |
890 | } | 904 | } |
@@ -899,6 +913,10 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
899 | int hdrlen; | 913 | int hdrlen; |
900 | int fragnum; | 914 | int fragnum; |
901 | 915 | ||
916 | /* no matter what happens, tx->skb moves to tx->skbs */ | ||
917 | __skb_queue_tail(&tx->skbs, skb); | ||
918 | tx->skb = NULL; | ||
919 | |||
902 | if (info->flags & IEEE80211_TX_CTL_DONTFRAG) | 920 | if (info->flags & IEEE80211_TX_CTL_DONTFRAG) |
903 | return TX_CONTINUE; | 921 | return TX_CONTINUE; |
904 | 922 | ||
@@ -927,21 +945,21 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
927 | * of the fragments then we will simply pretend to accept the skb | 945 | * of the fragments then we will simply pretend to accept the skb |
928 | * but store it away as pending. | 946 | * but store it away as pending. |
929 | */ | 947 | */ |
930 | if (ieee80211_fragment(tx->local, skb, hdrlen, frag_threshold)) | 948 | if (ieee80211_fragment(tx, skb, hdrlen, frag_threshold)) |
931 | return TX_DROP; | 949 | return TX_DROP; |
932 | 950 | ||
933 | /* update duration/seq/flags of fragments */ | 951 | /* update duration/seq/flags of fragments */ |
934 | fragnum = 0; | 952 | fragnum = 0; |
935 | do { | 953 | |
954 | skb_queue_walk(&tx->skbs, skb) { | ||
936 | int next_len; | 955 | int next_len; |
937 | const __le16 morefrags = cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); | 956 | const __le16 morefrags = cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); |
938 | 957 | ||
939 | hdr = (void *)skb->data; | 958 | hdr = (void *)skb->data; |
940 | info = IEEE80211_SKB_CB(skb); | 959 | info = IEEE80211_SKB_CB(skb); |
941 | 960 | ||
942 | if (skb->next) { | 961 | if (!skb_queue_is_last(&tx->skbs, skb)) { |
943 | hdr->frame_control |= morefrags; | 962 | hdr->frame_control |= morefrags; |
944 | next_len = skb->next->len; | ||
945 | /* | 963 | /* |
946 | * No multi-rate retries for fragmented frames, that | 964 | * No multi-rate retries for fragmented frames, that |
947 | * would completely throw off the NAV at other STAs. | 965 | * would completely throw off the NAV at other STAs. |
@@ -956,10 +974,9 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
956 | hdr->frame_control &= ~morefrags; | 974 | hdr->frame_control &= ~morefrags; |
957 | next_len = 0; | 975 | next_len = 0; |
958 | } | 976 | } |
959 | hdr->duration_id = ieee80211_duration(tx, 0, next_len); | ||
960 | hdr->seq_ctrl |= cpu_to_le16(fragnum & IEEE80211_SCTL_FRAG); | 977 | hdr->seq_ctrl |= cpu_to_le16(fragnum & IEEE80211_SCTL_FRAG); |
961 | fragnum++; | 978 | fragnum++; |
962 | } while ((skb = skb->next)); | 979 | } |
963 | 980 | ||
964 | return TX_CONTINUE; | 981 | return TX_CONTINUE; |
965 | } | 982 | } |
@@ -967,16 +984,16 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
967 | static ieee80211_tx_result debug_noinline | 984 | static ieee80211_tx_result debug_noinline |
968 | ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) | 985 | ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) |
969 | { | 986 | { |
970 | struct sk_buff *skb = tx->skb; | 987 | struct sk_buff *skb; |
971 | 988 | ||
972 | if (!tx->sta) | 989 | if (!tx->sta) |
973 | return TX_CONTINUE; | 990 | return TX_CONTINUE; |
974 | 991 | ||
975 | tx->sta->tx_packets++; | 992 | tx->sta->tx_packets++; |
976 | do { | 993 | skb_queue_walk(&tx->skbs, skb) { |
977 | tx->sta->tx_fragments++; | 994 | tx->sta->tx_fragments++; |
978 | tx->sta->tx_bytes += skb->len; | 995 | tx->sta->tx_bytes += skb->len; |
979 | } while ((skb = skb->next)); | 996 | } |
980 | 997 | ||
981 | return TX_CONTINUE; | 998 | return TX_CONTINUE; |
982 | } | 999 | } |
@@ -1015,21 +1032,25 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) | |||
1015 | static ieee80211_tx_result debug_noinline | 1032 | static ieee80211_tx_result debug_noinline |
1016 | ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) | 1033 | ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) |
1017 | { | 1034 | { |
1018 | struct sk_buff *skb = tx->skb; | 1035 | struct sk_buff *skb; |
1019 | struct ieee80211_hdr *hdr; | 1036 | struct ieee80211_hdr *hdr; |
1020 | int next_len; | 1037 | int next_len; |
1021 | bool group_addr; | 1038 | bool group_addr; |
1022 | 1039 | ||
1023 | do { | 1040 | skb_queue_walk(&tx->skbs, skb) { |
1024 | hdr = (void *) skb->data; | 1041 | hdr = (void *) skb->data; |
1025 | if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) | 1042 | if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) |
1026 | break; /* must not overwrite AID */ | 1043 | break; /* must not overwrite AID */ |
1027 | next_len = skb->next ? skb->next->len : 0; | 1044 | if (!skb_queue_is_last(&tx->skbs, skb)) { |
1045 | struct sk_buff *next = skb_queue_next(&tx->skbs, skb); | ||
1046 | next_len = next->len; | ||
1047 | } else | ||
1048 | next_len = 0; | ||
1028 | group_addr = is_multicast_ether_addr(hdr->addr1); | 1049 | group_addr = is_multicast_ether_addr(hdr->addr1); |
1029 | 1050 | ||
1030 | hdr->duration_id = | 1051 | hdr->duration_id = |
1031 | ieee80211_duration(tx, group_addr, next_len); | 1052 | ieee80211_duration(tx, skb, group_addr, next_len); |
1032 | } while ((skb = skb->next)); | 1053 | } |
1033 | 1054 | ||
1034 | return TX_CONTINUE; | 1055 | return TX_CONTINUE; |
1035 | } | 1056 | } |
@@ -1043,9 +1064,11 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, | |||
1043 | int tid) | 1064 | int tid) |
1044 | { | 1065 | { |
1045 | bool queued = false; | 1066 | bool queued = false; |
1067 | bool reset_agg_timer = false; | ||
1046 | 1068 | ||
1047 | if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { | 1069 | if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { |
1048 | info->flags |= IEEE80211_TX_CTL_AMPDU; | 1070 | info->flags |= IEEE80211_TX_CTL_AMPDU; |
1071 | reset_agg_timer = true; | ||
1049 | } else if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { | 1072 | } else if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { |
1050 | /* | 1073 | /* |
1051 | * nothing -- this aggregation session is being started | 1074 | * nothing -- this aggregation session is being started |
@@ -1077,6 +1100,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, | |||
1077 | /* do nothing, let packet pass through */ | 1100 | /* do nothing, let packet pass through */ |
1078 | } else if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { | 1101 | } else if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { |
1079 | info->flags |= IEEE80211_TX_CTL_AMPDU; | 1102 | info->flags |= IEEE80211_TX_CTL_AMPDU; |
1103 | reset_agg_timer = true; | ||
1080 | } else { | 1104 | } else { |
1081 | queued = true; | 1105 | queued = true; |
1082 | info->control.vif = &tx->sdata->vif; | 1106 | info->control.vif = &tx->sdata->vif; |
@@ -1086,6 +1110,11 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, | |||
1086 | spin_unlock(&tx->sta->lock); | 1110 | spin_unlock(&tx->sta->lock); |
1087 | } | 1111 | } |
1088 | 1112 | ||
1113 | /* reset session timer */ | ||
1114 | if (reset_agg_timer && tid_tx->timeout) | ||
1115 | mod_timer(&tid_tx->session_timer, | ||
1116 | TU_TO_EXP_TIME(tid_tx->timeout)); | ||
1117 | |||
1089 | return queued; | 1118 | return queued; |
1090 | } | 1119 | } |
1091 | 1120 | ||
@@ -1108,6 +1137,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1108 | tx->local = local; | 1137 | tx->local = local; |
1109 | tx->sdata = sdata; | 1138 | tx->sdata = sdata; |
1110 | tx->channel = local->hw.conf.channel; | 1139 | tx->channel = local->hw.conf.channel; |
1140 | __skb_queue_head_init(&tx->skbs); | ||
1111 | 1141 | ||
1112 | /* | 1142 | /* |
1113 | * If this flag is set to true anywhere, and we get here, | 1143 | * If this flag is set to true anywhere, and we get here, |
@@ -1152,16 +1182,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1152 | if (is_multicast_ether_addr(hdr->addr1)) { | 1182 | if (is_multicast_ether_addr(hdr->addr1)) { |
1153 | tx->flags &= ~IEEE80211_TX_UNICAST; | 1183 | tx->flags &= ~IEEE80211_TX_UNICAST; |
1154 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | 1184 | info->flags |= IEEE80211_TX_CTL_NO_ACK; |
1155 | } else { | 1185 | } else |
1156 | tx->flags |= IEEE80211_TX_UNICAST; | 1186 | tx->flags |= IEEE80211_TX_UNICAST; |
1157 | if (unlikely(local->wifi_wme_noack_test)) | ||
1158 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
1159 | /* | ||
1160 | * Flags are initialized to 0. Hence, no need to | ||
1161 | * explicitly unset IEEE80211_TX_CTL_NO_ACK since | ||
1162 | * it might already be set for injected frames. | ||
1163 | */ | ||
1164 | } | ||
1165 | 1187 | ||
1166 | if (!(info->flags & IEEE80211_TX_CTL_DONTFRAG)) { | 1188 | if (!(info->flags & IEEE80211_TX_CTL_DONTFRAG)) { |
1167 | if (!(tx->flags & IEEE80211_TX_UNICAST) || | 1189 | if (!(tx->flags & IEEE80211_TX_UNICAST) || |
@@ -1180,22 +1202,18 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1180 | return TX_CONTINUE; | 1202 | return TX_CONTINUE; |
1181 | } | 1203 | } |
1182 | 1204 | ||
1183 | /* | 1205 | static bool ieee80211_tx_frags(struct ieee80211_local *local, |
1184 | * Returns false if the frame couldn't be transmitted but was queued instead. | 1206 | struct ieee80211_vif *vif, |
1185 | */ | 1207 | struct ieee80211_sta *sta, |
1186 | static bool __ieee80211_tx(struct ieee80211_local *local, struct sk_buff **skbp, | 1208 | struct sk_buff_head *skbs, |
1187 | struct sta_info *sta, bool txpending) | 1209 | bool txpending) |
1188 | { | 1210 | { |
1189 | struct sk_buff *skb = *skbp, *next; | 1211 | struct sk_buff *skb, *tmp; |
1190 | struct ieee80211_tx_info *info; | 1212 | struct ieee80211_tx_info *info; |
1191 | struct ieee80211_sub_if_data *sdata; | ||
1192 | unsigned long flags; | 1213 | unsigned long flags; |
1193 | int len; | ||
1194 | bool fragm = false; | ||
1195 | 1214 | ||
1196 | while (skb) { | 1215 | skb_queue_walk_safe(skbs, skb, tmp) { |
1197 | int q = skb_get_queue_mapping(skb); | 1216 | int q = skb_get_queue_mapping(skb); |
1198 | __le16 fc; | ||
1199 | 1217 | ||
1200 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 1218 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
1201 | if (local->queue_stop_reasons[q] || | 1219 | if (local->queue_stop_reasons[q] || |
@@ -1205,24 +1223,11 @@ static bool __ieee80211_tx(struct ieee80211_local *local, struct sk_buff **skbp, | |||
1205 | * transmission from the tx-pending tasklet when the | 1223 | * transmission from the tx-pending tasklet when the |
1206 | * queue is woken again. | 1224 | * queue is woken again. |
1207 | */ | 1225 | */ |
1208 | 1226 | if (txpending) | |
1209 | do { | 1227 | skb_queue_splice_init(skbs, &local->pending[q]); |
1210 | next = skb->next; | 1228 | else |
1211 | skb->next = NULL; | 1229 | skb_queue_splice_tail_init(skbs, |
1212 | /* | 1230 | &local->pending[q]); |
1213 | * NB: If txpending is true, next must already | ||
1214 | * be NULL since we must've gone through this | ||
1215 | * loop before already; therefore we can just | ||
1216 | * queue the frame to the head without worrying | ||
1217 | * about reordering of fragments. | ||
1218 | */ | ||
1219 | if (unlikely(txpending)) | ||
1220 | __skb_queue_head(&local->pending[q], | ||
1221 | skb); | ||
1222 | else | ||
1223 | __skb_queue_tail(&local->pending[q], | ||
1224 | skb); | ||
1225 | } while ((skb = next)); | ||
1226 | 1231 | ||
1227 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | 1232 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, |
1228 | flags); | 1233 | flags); |
@@ -1231,47 +1236,72 @@ static bool __ieee80211_tx(struct ieee80211_local *local, struct sk_buff **skbp, | |||
1231 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 1236 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
1232 | 1237 | ||
1233 | info = IEEE80211_SKB_CB(skb); | 1238 | info = IEEE80211_SKB_CB(skb); |
1239 | info->control.vif = vif; | ||
1240 | info->control.sta = sta; | ||
1234 | 1241 | ||
1235 | if (fragm) | 1242 | __skb_unlink(skb, skbs); |
1236 | info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | | 1243 | drv_tx(local, skb); |
1237 | IEEE80211_TX_CTL_FIRST_FRAGMENT); | 1244 | } |
1238 | |||
1239 | next = skb->next; | ||
1240 | len = skb->len; | ||
1241 | 1245 | ||
1242 | if (next) | 1246 | return true; |
1243 | info->flags |= IEEE80211_TX_CTL_MORE_FRAMES; | 1247 | } |
1244 | 1248 | ||
1245 | sdata = vif_to_sdata(info->control.vif); | 1249 | /* |
1250 | * Returns false if the frame couldn't be transmitted but was queued instead. | ||
1251 | */ | ||
1252 | static bool __ieee80211_tx(struct ieee80211_local *local, | ||
1253 | struct sk_buff_head *skbs, int led_len, | ||
1254 | struct sta_info *sta, bool txpending) | ||
1255 | { | ||
1256 | struct ieee80211_tx_info *info; | ||
1257 | struct ieee80211_sub_if_data *sdata; | ||
1258 | struct ieee80211_vif *vif; | ||
1259 | struct ieee80211_sta *pubsta; | ||
1260 | struct sk_buff *skb; | ||
1261 | bool result = true; | ||
1262 | __le16 fc; | ||
1246 | 1263 | ||
1247 | switch (sdata->vif.type) { | 1264 | if (WARN_ON(skb_queue_empty(skbs))) |
1248 | case NL80211_IFTYPE_MONITOR: | 1265 | return true; |
1249 | info->control.vif = NULL; | ||
1250 | break; | ||
1251 | case NL80211_IFTYPE_AP_VLAN: | ||
1252 | info->control.vif = &container_of(sdata->bss, | ||
1253 | struct ieee80211_sub_if_data, u.ap)->vif; | ||
1254 | break; | ||
1255 | default: | ||
1256 | /* keep */ | ||
1257 | break; | ||
1258 | } | ||
1259 | 1266 | ||
1260 | if (sta && sta->uploaded) | 1267 | skb = skb_peek(skbs); |
1261 | info->control.sta = &sta->sta; | 1268 | fc = ((struct ieee80211_hdr *)skb->data)->frame_control; |
1262 | else | 1269 | info = IEEE80211_SKB_CB(skb); |
1263 | info->control.sta = NULL; | 1270 | sdata = vif_to_sdata(info->control.vif); |
1271 | if (sta && !sta->uploaded) | ||
1272 | sta = NULL; | ||
1264 | 1273 | ||
1265 | fc = ((struct ieee80211_hdr *)skb->data)->frame_control; | 1274 | if (sta) |
1266 | drv_tx(local, skb); | 1275 | pubsta = &sta->sta; |
1276 | else | ||
1277 | pubsta = NULL; | ||
1267 | 1278 | ||
1268 | ieee80211_tpt_led_trig_tx(local, fc, len); | 1279 | switch (sdata->vif.type) { |
1269 | *skbp = skb = next; | 1280 | case NL80211_IFTYPE_MONITOR: |
1270 | ieee80211_led_tx(local, 1); | 1281 | sdata = NULL; |
1271 | fragm = true; | 1282 | vif = NULL; |
1283 | break; | ||
1284 | case NL80211_IFTYPE_AP_VLAN: | ||
1285 | sdata = container_of(sdata->bss, | ||
1286 | struct ieee80211_sub_if_data, u.ap); | ||
1287 | /* fall through */ | ||
1288 | default: | ||
1289 | vif = &sdata->vif; | ||
1290 | break; | ||
1272 | } | 1291 | } |
1273 | 1292 | ||
1274 | return true; | 1293 | if (local->ops->tx_frags) |
1294 | drv_tx_frags(local, vif, pubsta, skbs); | ||
1295 | else | ||
1296 | result = ieee80211_tx_frags(local, vif, pubsta, skbs, | ||
1297 | txpending); | ||
1298 | |||
1299 | ieee80211_tpt_led_trig_tx(local, fc, led_len); | ||
1300 | ieee80211_led_tx(local, 1); | ||
1301 | |||
1302 | WARN_ON_ONCE(!skb_queue_empty(skbs)); | ||
1303 | |||
1304 | return result; | ||
1275 | } | 1305 | } |
1276 | 1306 | ||
1277 | /* | 1307 | /* |
@@ -1280,8 +1310,7 @@ static bool __ieee80211_tx(struct ieee80211_local *local, struct sk_buff **skbp, | |||
1280 | */ | 1310 | */ |
1281 | static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | 1311 | static int invoke_tx_handlers(struct ieee80211_tx_data *tx) |
1282 | { | 1312 | { |
1283 | struct sk_buff *skb = tx->skb; | 1313 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
1284 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1285 | ieee80211_tx_result res = TX_DROP; | 1314 | ieee80211_tx_result res = TX_DROP; |
1286 | 1315 | ||
1287 | #define CALL_TXH(txh) \ | 1316 | #define CALL_TXH(txh) \ |
@@ -1299,8 +1328,11 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | |||
1299 | if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) | 1328 | if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) |
1300 | CALL_TXH(ieee80211_tx_h_rate_ctrl); | 1329 | CALL_TXH(ieee80211_tx_h_rate_ctrl); |
1301 | 1330 | ||
1302 | if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) | 1331 | if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) { |
1332 | __skb_queue_tail(&tx->skbs, tx->skb); | ||
1333 | tx->skb = NULL; | ||
1303 | goto txh_done; | 1334 | goto txh_done; |
1335 | } | ||
1304 | 1336 | ||
1305 | CALL_TXH(ieee80211_tx_h_michael_mic_add); | 1337 | CALL_TXH(ieee80211_tx_h_michael_mic_add); |
1306 | CALL_TXH(ieee80211_tx_h_sequence); | 1338 | CALL_TXH(ieee80211_tx_h_sequence); |
@@ -1315,13 +1347,10 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | |||
1315 | txh_done: | 1347 | txh_done: |
1316 | if (unlikely(res == TX_DROP)) { | 1348 | if (unlikely(res == TX_DROP)) { |
1317 | I802_DEBUG_INC(tx->local->tx_handlers_drop); | 1349 | I802_DEBUG_INC(tx->local->tx_handlers_drop); |
1318 | while (skb) { | 1350 | if (tx->skb) |
1319 | struct sk_buff *next; | 1351 | dev_kfree_skb(tx->skb); |
1320 | 1352 | else | |
1321 | next = skb->next; | 1353 | __skb_queue_purge(&tx->skbs); |
1322 | dev_kfree_skb(skb); | ||
1323 | skb = next; | ||
1324 | } | ||
1325 | return -1; | 1354 | return -1; |
1326 | } else if (unlikely(res == TX_QUEUED)) { | 1355 | } else if (unlikely(res == TX_QUEUED)) { |
1327 | I802_DEBUG_INC(tx->local->tx_handlers_queued); | 1356 | I802_DEBUG_INC(tx->local->tx_handlers_queued); |
@@ -1342,6 +1371,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, | |||
1342 | ieee80211_tx_result res_prepare; | 1371 | ieee80211_tx_result res_prepare; |
1343 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1372 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1344 | bool result = true; | 1373 | bool result = true; |
1374 | int led_len; | ||
1345 | 1375 | ||
1346 | if (unlikely(skb->len < 10)) { | 1376 | if (unlikely(skb->len < 10)) { |
1347 | dev_kfree_skb(skb); | 1377 | dev_kfree_skb(skb); |
@@ -1351,6 +1381,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, | |||
1351 | rcu_read_lock(); | 1381 | rcu_read_lock(); |
1352 | 1382 | ||
1353 | /* initialises tx */ | 1383 | /* initialises tx */ |
1384 | led_len = skb->len; | ||
1354 | res_prepare = ieee80211_tx_prepare(sdata, &tx, skb); | 1385 | res_prepare = ieee80211_tx_prepare(sdata, &tx, skb); |
1355 | 1386 | ||
1356 | if (unlikely(res_prepare == TX_DROP)) { | 1387 | if (unlikely(res_prepare == TX_DROP)) { |
@@ -1364,7 +1395,8 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, | |||
1364 | info->band = tx.channel->band; | 1395 | info->band = tx.channel->band; |
1365 | 1396 | ||
1366 | if (!invoke_tx_handlers(&tx)) | 1397 | if (!invoke_tx_handlers(&tx)) |
1367 | result = __ieee80211_tx(local, &tx.skb, tx.sta, txpending); | 1398 | result = __ieee80211_tx(local, &tx.skbs, led_len, |
1399 | tx.sta, txpending); | ||
1368 | out: | 1400 | out: |
1369 | rcu_read_unlock(); | 1401 | rcu_read_unlock(); |
1370 | return result; | 1402 | return result; |
@@ -1431,7 +1463,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
1431 | if (ieee80211_vif_is_mesh(&sdata->vif) && | 1463 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
1432 | ieee80211_is_data(hdr->frame_control) && | 1464 | ieee80211_is_data(hdr->frame_control) && |
1433 | !is_multicast_ether_addr(hdr->addr1)) | 1465 | !is_multicast_ether_addr(hdr->addr1)) |
1434 | if (mesh_nexthop_lookup(skb, sdata)) { | 1466 | if (mesh_nexthop_resolve(skb, sdata)) { |
1435 | /* skb queued: don't free */ | 1467 | /* skb queued: don't free */ |
1436 | rcu_read_unlock(); | 1468 | rcu_read_unlock(); |
1437 | return; | 1469 | return; |
@@ -1685,8 +1717,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1685 | int nh_pos, h_pos; | 1717 | int nh_pos, h_pos; |
1686 | struct sta_info *sta = NULL; | 1718 | struct sta_info *sta = NULL; |
1687 | bool wme_sta = false, authorized = false, tdls_auth = false; | 1719 | bool wme_sta = false, authorized = false, tdls_auth = false; |
1688 | struct sk_buff *tmp_skb; | ||
1689 | bool tdls_direct = false; | 1720 | bool tdls_direct = false; |
1721 | bool multicast; | ||
1722 | u32 info_flags = 0; | ||
1723 | u16 info_id = 0; | ||
1690 | 1724 | ||
1691 | if (unlikely(skb->len < ETH_HLEN)) { | 1725 | if (unlikely(skb->len < ETH_HLEN)) { |
1692 | ret = NETDEV_TX_OK; | 1726 | ret = NETDEV_TX_OK; |
@@ -1873,7 +1907,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1873 | * if it is a multicast address (which can only happen | 1907 | * if it is a multicast address (which can only happen |
1874 | * in AP mode) | 1908 | * in AP mode) |
1875 | */ | 1909 | */ |
1876 | if (!is_multicast_ether_addr(hdr.addr1)) { | 1910 | multicast = is_multicast_ether_addr(hdr.addr1); |
1911 | if (!multicast) { | ||
1877 | rcu_read_lock(); | 1912 | rcu_read_lock(); |
1878 | sta = sta_info_get(sdata, hdr.addr1); | 1913 | sta = sta_info_get(sdata, hdr.addr1); |
1879 | if (sta) { | 1914 | if (sta) { |
@@ -1914,11 +1949,54 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1914 | goto fail; | 1949 | goto fail; |
1915 | } | 1950 | } |
1916 | 1951 | ||
1952 | if (unlikely(!multicast && skb->sk && | ||
1953 | skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)) { | ||
1954 | struct sk_buff *orig_skb = skb; | ||
1955 | |||
1956 | skb = skb_clone(skb, GFP_ATOMIC); | ||
1957 | if (skb) { | ||
1958 | unsigned long flags; | ||
1959 | int id, r; | ||
1960 | |||
1961 | spin_lock_irqsave(&local->ack_status_lock, flags); | ||
1962 | r = idr_get_new_above(&local->ack_status_frames, | ||
1963 | orig_skb, 1, &id); | ||
1964 | if (r == -EAGAIN) { | ||
1965 | idr_pre_get(&local->ack_status_frames, | ||
1966 | GFP_ATOMIC); | ||
1967 | r = idr_get_new_above(&local->ack_status_frames, | ||
1968 | orig_skb, 1, &id); | ||
1969 | } | ||
1970 | if (WARN_ON(!id) || id > 0xffff) { | ||
1971 | idr_remove(&local->ack_status_frames, id); | ||
1972 | r = -ERANGE; | ||
1973 | } | ||
1974 | spin_unlock_irqrestore(&local->ack_status_lock, flags); | ||
1975 | |||
1976 | if (!r) { | ||
1977 | info_id = id; | ||
1978 | info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
1979 | } else if (skb_shared(skb)) { | ||
1980 | kfree_skb(orig_skb); | ||
1981 | } else { | ||
1982 | kfree_skb(skb); | ||
1983 | skb = orig_skb; | ||
1984 | } | ||
1985 | } else { | ||
1986 | /* couldn't clone -- lose tx status ... */ | ||
1987 | skb = orig_skb; | ||
1988 | } | ||
1989 | } | ||
1990 | |||
1917 | /* | 1991 | /* |
1918 | * If the skb is shared we need to obtain our own copy. | 1992 | * If the skb is shared we need to obtain our own copy. |
1919 | */ | 1993 | */ |
1920 | if (skb_shared(skb)) { | 1994 | if (skb_shared(skb)) { |
1921 | tmp_skb = skb; | 1995 | struct sk_buff *tmp_skb = skb; |
1996 | |||
1997 | /* can't happen -- skb is a clone if info_id != 0 */ | ||
1998 | WARN_ON(info_id); | ||
1999 | |||
1922 | skb = skb_clone(skb, GFP_ATOMIC); | 2000 | skb = skb_clone(skb, GFP_ATOMIC); |
1923 | kfree_skb(tmp_skb); | 2001 | kfree_skb(tmp_skb); |
1924 | 2002 | ||
@@ -2019,6 +2097,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2019 | memset(info, 0, sizeof(*info)); | 2097 | memset(info, 0, sizeof(*info)); |
2020 | 2098 | ||
2021 | dev->trans_start = jiffies; | 2099 | dev->trans_start = jiffies; |
2100 | |||
2101 | info->flags = info_flags; | ||
2102 | info->ack_frame_id = info_id; | ||
2103 | |||
2022 | ieee80211_xmit(sdata, skb); | 2104 | ieee80211_xmit(sdata, skb); |
2023 | 2105 | ||
2024 | return NETDEV_TX_OK; | 2106 | return NETDEV_TX_OK; |
@@ -2062,10 +2144,15 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
2062 | if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) { | 2144 | if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) { |
2063 | result = ieee80211_tx(sdata, skb, true); | 2145 | result = ieee80211_tx(sdata, skb, true); |
2064 | } else { | 2146 | } else { |
2147 | struct sk_buff_head skbs; | ||
2148 | |||
2149 | __skb_queue_head_init(&skbs); | ||
2150 | __skb_queue_tail(&skbs, skb); | ||
2151 | |||
2065 | hdr = (struct ieee80211_hdr *)skb->data; | 2152 | hdr = (struct ieee80211_hdr *)skb->data; |
2066 | sta = sta_info_get(sdata, hdr->addr1); | 2153 | sta = sta_info_get(sdata, hdr->addr1); |
2067 | 2154 | ||
2068 | result = __ieee80211_tx(local, &skb, sta, true); | 2155 | result = __ieee80211_tx(local, &skbs, skb->len, sta, true); |
2069 | } | 2156 | } |
2070 | 2157 | ||
2071 | return result; | 2158 | return result; |
@@ -2178,10 +2265,10 @@ static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss, | |||
2178 | /* Bitmap control */ | 2265 | /* Bitmap control */ |
2179 | *pos++ = n1 | aid0; | 2266 | *pos++ = n1 | aid0; |
2180 | /* Part Virt Bitmap */ | 2267 | /* Part Virt Bitmap */ |
2268 | skb_put(skb, n2 - n1); | ||
2181 | memcpy(pos, bss->tim + n1, n2 - n1 + 1); | 2269 | memcpy(pos, bss->tim + n1, n2 - n1 + 1); |
2182 | 2270 | ||
2183 | tim[1] = n2 - n1 + 4; | 2271 | tim[1] = n2 - n1 + 4; |
2184 | skb_put(skb, n2 - n1); | ||
2185 | } else { | 2272 | } else { |
2186 | *pos++ = aid0; /* Bitmap control */ | 2273 | *pos++ = aid0; /* Bitmap control */ |
2187 | *pos++ = 0; /* Part Virt Bitmap */ | 2274 | *pos++ = 0; /* Part Virt Bitmap */ |
@@ -2246,9 +2333,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2246 | } else { | 2333 | } else { |
2247 | unsigned long flags; | 2334 | unsigned long flags; |
2248 | 2335 | ||
2249 | spin_lock_irqsave(&local->sta_lock, flags); | 2336 | spin_lock_irqsave(&local->tim_lock, flags); |
2250 | ieee80211_beacon_add_tim(ap, skb, beacon); | 2337 | ieee80211_beacon_add_tim(ap, skb, beacon); |
2251 | spin_unlock_irqrestore(&local->sta_lock, flags); | 2338 | spin_unlock_irqrestore(&local->tim_lock, flags); |
2252 | } | 2339 | } |
2253 | 2340 | ||
2254 | if (tim_offset) | 2341 | if (tim_offset) |
@@ -2279,22 +2366,31 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2279 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 2366 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
2280 | struct ieee80211_mgmt *mgmt; | 2367 | struct ieee80211_mgmt *mgmt; |
2281 | u8 *pos; | 2368 | u8 *pos; |
2369 | int hdr_len = offsetof(struct ieee80211_mgmt, u.beacon) + | ||
2370 | sizeof(mgmt->u.beacon); | ||
2282 | 2371 | ||
2283 | #ifdef CONFIG_MAC80211_MESH | 2372 | #ifdef CONFIG_MAC80211_MESH |
2284 | if (!sdata->u.mesh.mesh_id_len) | 2373 | if (!sdata->u.mesh.mesh_id_len) |
2285 | goto out; | 2374 | goto out; |
2286 | #endif | 2375 | #endif |
2287 | 2376 | ||
2288 | /* headroom, head length, tail length and maximum TIM length */ | 2377 | skb = dev_alloc_skb(local->tx_headroom + |
2289 | skb = dev_alloc_skb(local->tx_headroom + 400 + | 2378 | hdr_len + |
2290 | sdata->u.mesh.ie_len); | 2379 | 2 + /* NULL SSID */ |
2380 | 2 + 8 + /* supported rates */ | ||
2381 | 2 + 3 + /* DS params */ | ||
2382 | 2 + (IEEE80211_MAX_SUPP_RATES - 8) + | ||
2383 | 2 + sizeof(struct ieee80211_ht_cap) + | ||
2384 | 2 + sizeof(struct ieee80211_ht_info) + | ||
2385 | 2 + sdata->u.mesh.mesh_id_len + | ||
2386 | 2 + sizeof(struct ieee80211_meshconf_ie) + | ||
2387 | sdata->u.mesh.ie_len); | ||
2291 | if (!skb) | 2388 | if (!skb) |
2292 | goto out; | 2389 | goto out; |
2293 | 2390 | ||
2294 | skb_reserve(skb, local->hw.extra_tx_headroom); | 2391 | skb_reserve(skb, local->hw.extra_tx_headroom); |
2295 | mgmt = (struct ieee80211_mgmt *) | 2392 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); |
2296 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); | 2393 | memset(mgmt, 0, hdr_len); |
2297 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | ||
2298 | mgmt->frame_control = | 2394 | mgmt->frame_control = |
2299 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); | 2395 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); |
2300 | memset(mgmt->da, 0xff, ETH_ALEN); | 2396 | memset(mgmt->da, 0xff, ETH_ALEN); |
@@ -2313,6 +2409,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2313 | mesh_add_ds_params_ie(skb, sdata) || | 2409 | mesh_add_ds_params_ie(skb, sdata) || |
2314 | ieee80211_add_ext_srates_ie(&sdata->vif, skb) || | 2410 | ieee80211_add_ext_srates_ie(&sdata->vif, skb) || |
2315 | mesh_add_rsn_ie(skb, sdata) || | 2411 | mesh_add_rsn_ie(skb, sdata) || |
2412 | mesh_add_ht_cap_ie(skb, sdata) || | ||
2413 | mesh_add_ht_info_ie(skb, sdata) || | ||
2316 | mesh_add_meshid_ie(skb, sdata) || | 2414 | mesh_add_meshid_ie(skb, sdata) || |
2317 | mesh_add_meshconf_ie(skb, sdata) || | 2415 | mesh_add_meshconf_ie(skb, sdata) || |
2318 | mesh_add_vendor_ies(skb, sdata)) { | 2416 | mesh_add_vendor_ies(skb, sdata)) { |
@@ -2355,6 +2453,37 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2355 | } | 2453 | } |
2356 | EXPORT_SYMBOL(ieee80211_beacon_get_tim); | 2454 | EXPORT_SYMBOL(ieee80211_beacon_get_tim); |
2357 | 2455 | ||
2456 | struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw, | ||
2457 | struct ieee80211_vif *vif) | ||
2458 | { | ||
2459 | struct ieee80211_if_ap *ap = NULL; | ||
2460 | struct sk_buff *presp = NULL, *skb = NULL; | ||
2461 | struct ieee80211_hdr *hdr; | ||
2462 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
2463 | |||
2464 | if (sdata->vif.type != NL80211_IFTYPE_AP) | ||
2465 | return NULL; | ||
2466 | |||
2467 | rcu_read_lock(); | ||
2468 | |||
2469 | ap = &sdata->u.ap; | ||
2470 | presp = rcu_dereference(ap->probe_resp); | ||
2471 | if (!presp) | ||
2472 | goto out; | ||
2473 | |||
2474 | skb = skb_copy(presp, GFP_ATOMIC); | ||
2475 | if (!skb) | ||
2476 | goto out; | ||
2477 | |||
2478 | hdr = (struct ieee80211_hdr *) skb->data; | ||
2479 | memset(hdr->addr1, 0, sizeof(hdr->addr1)); | ||
2480 | |||
2481 | out: | ||
2482 | rcu_read_unlock(); | ||
2483 | return skb; | ||
2484 | } | ||
2485 | EXPORT_SYMBOL(ieee80211_proberesp_get); | ||
2486 | |||
2358 | struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, | 2487 | struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, |
2359 | struct ieee80211_vif *vif) | 2488 | struct ieee80211_vif *vif) |
2360 | { | 2489 | { |
@@ -2567,15 +2696,15 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2567 | } | 2696 | } |
2568 | EXPORT_SYMBOL(ieee80211_get_buffered_bc); | 2697 | EXPORT_SYMBOL(ieee80211_get_buffered_bc); |
2569 | 2698 | ||
2570 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | 2699 | void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, |
2700 | struct sk_buff *skb, int tid) | ||
2571 | { | 2701 | { |
2572 | skb_set_mac_header(skb, 0); | 2702 | skb_set_mac_header(skb, 0); |
2573 | skb_set_network_header(skb, 0); | 2703 | skb_set_network_header(skb, 0); |
2574 | skb_set_transport_header(skb, 0); | 2704 | skb_set_transport_header(skb, 0); |
2575 | 2705 | ||
2576 | /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */ | 2706 | skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]); |
2577 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); | 2707 | skb->priority = tid; |
2578 | skb->priority = 7; | ||
2579 | 2708 | ||
2580 | /* | 2709 | /* |
2581 | * The other path calling ieee80211_xmit is from the tasklet, | 2710 | * The other path calling ieee80211_xmit is from the tasklet, |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d5230ecc784d..9919892575f4 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/etherdevice.h> | 20 | #include <linux/etherdevice.h> |
21 | #include <linux/if_arp.h> | 21 | #include <linux/if_arp.h> |
22 | #include <linux/bitmap.h> | 22 | #include <linux/bitmap.h> |
23 | #include <linux/crc32.h> | ||
23 | #include <net/net_namespace.h> | 24 | #include <net/net_namespace.h> |
24 | #include <net/cfg80211.h> | 25 | #include <net/cfg80211.h> |
25 | #include <net/rtnetlink.h> | 26 | #include <net/rtnetlink.h> |
@@ -96,13 +97,13 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | |||
96 | 97 | ||
97 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) | 98 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) |
98 | { | 99 | { |
99 | struct sk_buff *skb = tx->skb; | 100 | struct sk_buff *skb; |
100 | struct ieee80211_hdr *hdr; | 101 | struct ieee80211_hdr *hdr; |
101 | 102 | ||
102 | do { | 103 | skb_queue_walk(&tx->skbs, skb) { |
103 | hdr = (struct ieee80211_hdr *) skb->data; | 104 | hdr = (struct ieee80211_hdr *) skb->data; |
104 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | 105 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
105 | } while ((skb = skb->next)); | 106 | } |
106 | } | 107 | } |
107 | 108 | ||
108 | int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, | 109 | int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, |
@@ -564,6 +565,172 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, | |||
564 | } | 565 | } |
565 | EXPORT_SYMBOL(ieee80211_queue_delayed_work); | 566 | EXPORT_SYMBOL(ieee80211_queue_delayed_work); |
566 | 567 | ||
568 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | ||
569 | struct ieee802_11_elems *elems, | ||
570 | u64 filter, u32 crc) | ||
571 | { | ||
572 | size_t left = len; | ||
573 | u8 *pos = start; | ||
574 | bool calc_crc = filter != 0; | ||
575 | |||
576 | memset(elems, 0, sizeof(*elems)); | ||
577 | elems->ie_start = start; | ||
578 | elems->total_len = len; | ||
579 | |||
580 | while (left >= 2) { | ||
581 | u8 id, elen; | ||
582 | |||
583 | id = *pos++; | ||
584 | elen = *pos++; | ||
585 | left -= 2; | ||
586 | |||
587 | if (elen > left) | ||
588 | break; | ||
589 | |||
590 | if (calc_crc && id < 64 && (filter & (1ULL << id))) | ||
591 | crc = crc32_be(crc, pos - 2, elen + 2); | ||
592 | |||
593 | switch (id) { | ||
594 | case WLAN_EID_SSID: | ||
595 | elems->ssid = pos; | ||
596 | elems->ssid_len = elen; | ||
597 | break; | ||
598 | case WLAN_EID_SUPP_RATES: | ||
599 | elems->supp_rates = pos; | ||
600 | elems->supp_rates_len = elen; | ||
601 | break; | ||
602 | case WLAN_EID_FH_PARAMS: | ||
603 | elems->fh_params = pos; | ||
604 | elems->fh_params_len = elen; | ||
605 | break; | ||
606 | case WLAN_EID_DS_PARAMS: | ||
607 | elems->ds_params = pos; | ||
608 | elems->ds_params_len = elen; | ||
609 | break; | ||
610 | case WLAN_EID_CF_PARAMS: | ||
611 | elems->cf_params = pos; | ||
612 | elems->cf_params_len = elen; | ||
613 | break; | ||
614 | case WLAN_EID_TIM: | ||
615 | if (elen >= sizeof(struct ieee80211_tim_ie)) { | ||
616 | elems->tim = (void *)pos; | ||
617 | elems->tim_len = elen; | ||
618 | } | ||
619 | break; | ||
620 | case WLAN_EID_IBSS_PARAMS: | ||
621 | elems->ibss_params = pos; | ||
622 | elems->ibss_params_len = elen; | ||
623 | break; | ||
624 | case WLAN_EID_CHALLENGE: | ||
625 | elems->challenge = pos; | ||
626 | elems->challenge_len = elen; | ||
627 | break; | ||
628 | case WLAN_EID_VENDOR_SPECIFIC: | ||
629 | if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && | ||
630 | pos[2] == 0xf2) { | ||
631 | /* Microsoft OUI (00:50:F2) */ | ||
632 | |||
633 | if (calc_crc) | ||
634 | crc = crc32_be(crc, pos - 2, elen + 2); | ||
635 | |||
636 | if (pos[3] == 1) { | ||
637 | /* OUI Type 1 - WPA IE */ | ||
638 | elems->wpa = pos; | ||
639 | elems->wpa_len = elen; | ||
640 | } else if (elen >= 5 && pos[3] == 2) { | ||
641 | /* OUI Type 2 - WMM IE */ | ||
642 | if (pos[4] == 0) { | ||
643 | elems->wmm_info = pos; | ||
644 | elems->wmm_info_len = elen; | ||
645 | } else if (pos[4] == 1) { | ||
646 | elems->wmm_param = pos; | ||
647 | elems->wmm_param_len = elen; | ||
648 | } | ||
649 | } | ||
650 | } | ||
651 | break; | ||
652 | case WLAN_EID_RSN: | ||
653 | elems->rsn = pos; | ||
654 | elems->rsn_len = elen; | ||
655 | break; | ||
656 | case WLAN_EID_ERP_INFO: | ||
657 | elems->erp_info = pos; | ||
658 | elems->erp_info_len = elen; | ||
659 | break; | ||
660 | case WLAN_EID_EXT_SUPP_RATES: | ||
661 | elems->ext_supp_rates = pos; | ||
662 | elems->ext_supp_rates_len = elen; | ||
663 | break; | ||
664 | case WLAN_EID_HT_CAPABILITY: | ||
665 | if (elen >= sizeof(struct ieee80211_ht_cap)) | ||
666 | elems->ht_cap_elem = (void *)pos; | ||
667 | break; | ||
668 | case WLAN_EID_HT_INFORMATION: | ||
669 | if (elen >= sizeof(struct ieee80211_ht_info)) | ||
670 | elems->ht_info_elem = (void *)pos; | ||
671 | break; | ||
672 | case WLAN_EID_MESH_ID: | ||
673 | elems->mesh_id = pos; | ||
674 | elems->mesh_id_len = elen; | ||
675 | break; | ||
676 | case WLAN_EID_MESH_CONFIG: | ||
677 | if (elen >= sizeof(struct ieee80211_meshconf_ie)) | ||
678 | elems->mesh_config = (void *)pos; | ||
679 | break; | ||
680 | case WLAN_EID_PEER_MGMT: | ||
681 | elems->peering = pos; | ||
682 | elems->peering_len = elen; | ||
683 | break; | ||
684 | case WLAN_EID_PREQ: | ||
685 | elems->preq = pos; | ||
686 | elems->preq_len = elen; | ||
687 | break; | ||
688 | case WLAN_EID_PREP: | ||
689 | elems->prep = pos; | ||
690 | elems->prep_len = elen; | ||
691 | break; | ||
692 | case WLAN_EID_PERR: | ||
693 | elems->perr = pos; | ||
694 | elems->perr_len = elen; | ||
695 | break; | ||
696 | case WLAN_EID_RANN: | ||
697 | if (elen >= sizeof(struct ieee80211_rann_ie)) | ||
698 | elems->rann = (void *)pos; | ||
699 | break; | ||
700 | case WLAN_EID_CHANNEL_SWITCH: | ||
701 | elems->ch_switch_elem = pos; | ||
702 | elems->ch_switch_elem_len = elen; | ||
703 | break; | ||
704 | case WLAN_EID_QUIET: | ||
705 | if (!elems->quiet_elem) { | ||
706 | elems->quiet_elem = pos; | ||
707 | elems->quiet_elem_len = elen; | ||
708 | } | ||
709 | elems->num_of_quiet_elem++; | ||
710 | break; | ||
711 | case WLAN_EID_COUNTRY: | ||
712 | elems->country_elem = pos; | ||
713 | elems->country_elem_len = elen; | ||
714 | break; | ||
715 | case WLAN_EID_PWR_CONSTRAINT: | ||
716 | elems->pwr_constr_elem = pos; | ||
717 | elems->pwr_constr_elem_len = elen; | ||
718 | break; | ||
719 | case WLAN_EID_TIMEOUT_INTERVAL: | ||
720 | elems->timeout_int = pos; | ||
721 | elems->timeout_int_len = elen; | ||
722 | break; | ||
723 | default: | ||
724 | break; | ||
725 | } | ||
726 | |||
727 | left -= elen; | ||
728 | pos += elen; | ||
729 | } | ||
730 | |||
731 | return crc; | ||
732 | } | ||
733 | |||
567 | void ieee802_11_parse_elems(u8 *start, size_t len, | 734 | void ieee802_11_parse_elems(u8 *start, size_t len, |
568 | struct ieee802_11_elems *elems) | 735 | struct ieee802_11_elems *elems) |
569 | { | 736 | { |
@@ -812,23 +979,9 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
812 | offset = noffset; | 979 | offset = noffset; |
813 | } | 980 | } |
814 | 981 | ||
815 | if (sband->ht_cap.ht_supported) { | 982 | if (sband->ht_cap.ht_supported) |
816 | u16 cap = sband->ht_cap.cap; | 983 | pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, |
817 | __le16 tmp; | 984 | sband->ht_cap.cap); |
818 | |||
819 | *pos++ = WLAN_EID_HT_CAPABILITY; | ||
820 | *pos++ = sizeof(struct ieee80211_ht_cap); | ||
821 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); | ||
822 | tmp = cpu_to_le16(cap); | ||
823 | memcpy(pos, &tmp, sizeof(u16)); | ||
824 | pos += sizeof(u16); | ||
825 | *pos++ = sband->ht_cap.ampdu_factor | | ||
826 | (sband->ht_cap.ampdu_density << | ||
827 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); | ||
828 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); | ||
829 | pos += sizeof(sband->ht_cap.mcs); | ||
830 | pos += 2 + 4 + 1; /* ext info, BF cap, antsel */ | ||
831 | } | ||
832 | 985 | ||
833 | /* | 986 | /* |
834 | * If adding more here, adjust code in main.c | 987 | * If adding more here, adjust code in main.c |
@@ -989,16 +1142,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
989 | */ | 1142 | */ |
990 | } | 1143 | } |
991 | #endif | 1144 | #endif |
992 | |||
993 | /* setup fragmentation threshold */ | ||
994 | drv_set_frag_threshold(local, hw->wiphy->frag_threshold); | ||
995 | |||
996 | /* setup RTS threshold */ | ||
997 | drv_set_rts_threshold(local, hw->wiphy->rts_threshold); | ||
998 | |||
999 | /* reset coverage class */ | ||
1000 | drv_set_coverage_class(local, hw->wiphy->coverage_class); | ||
1001 | |||
1002 | /* everything else happens only if HW was up & running */ | 1145 | /* everything else happens only if HW was up & running */ |
1003 | if (!local->open_count) | 1146 | if (!local->open_count) |
1004 | goto wake_up; | 1147 | goto wake_up; |
@@ -1017,6 +1160,15 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1017 | return res; | 1160 | return res; |
1018 | } | 1161 | } |
1019 | 1162 | ||
1163 | /* setup fragmentation threshold */ | ||
1164 | drv_set_frag_threshold(local, hw->wiphy->frag_threshold); | ||
1165 | |||
1166 | /* setup RTS threshold */ | ||
1167 | drv_set_rts_threshold(local, hw->wiphy->rts_threshold); | ||
1168 | |||
1169 | /* reset coverage class */ | ||
1170 | drv_set_coverage_class(local, hw->wiphy->coverage_class); | ||
1171 | |||
1020 | ieee80211_led_radio(local, true); | 1172 | ieee80211_led_radio(local, true); |
1021 | ieee80211_mod_tpt_led_trig(local, | 1173 | ieee80211_mod_tpt_led_trig(local, |
1022 | IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); | 1174 | IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); |
@@ -1026,7 +1178,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1026 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 1178 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
1027 | sdata->vif.type != NL80211_IFTYPE_MONITOR && | 1179 | sdata->vif.type != NL80211_IFTYPE_MONITOR && |
1028 | ieee80211_sdata_running(sdata)) | 1180 | ieee80211_sdata_running(sdata)) |
1029 | res = drv_add_interface(local, &sdata->vif); | 1181 | res = drv_add_interface(local, sdata); |
1030 | } | 1182 | } |
1031 | 1183 | ||
1032 | /* add STAs back */ | 1184 | /* add STAs back */ |
@@ -1076,11 +1228,13 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1076 | BSS_CHANGED_BEACON_INT | | 1228 | BSS_CHANGED_BEACON_INT | |
1077 | BSS_CHANGED_BSSID | | 1229 | BSS_CHANGED_BSSID | |
1078 | BSS_CHANGED_CQM | | 1230 | BSS_CHANGED_CQM | |
1079 | BSS_CHANGED_QOS; | 1231 | BSS_CHANGED_QOS | |
1232 | BSS_CHANGED_IDLE; | ||
1080 | 1233 | ||
1081 | switch (sdata->vif.type) { | 1234 | switch (sdata->vif.type) { |
1082 | case NL80211_IFTYPE_STATION: | 1235 | case NL80211_IFTYPE_STATION: |
1083 | changed |= BSS_CHANGED_ASSOC; | 1236 | changed |= BSS_CHANGED_ASSOC | |
1237 | BSS_CHANGED_ARP_FILTER; | ||
1084 | mutex_lock(&sdata->u.mgd.mtx); | 1238 | mutex_lock(&sdata->u.mgd.mtx); |
1085 | ieee80211_bss_info_change_notify(sdata, changed); | 1239 | ieee80211_bss_info_change_notify(sdata, changed); |
1086 | mutex_unlock(&sdata->u.mgd.mtx); | 1240 | mutex_unlock(&sdata->u.mgd.mtx); |
@@ -1090,6 +1244,10 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1090 | /* fall through */ | 1244 | /* fall through */ |
1091 | case NL80211_IFTYPE_AP: | 1245 | case NL80211_IFTYPE_AP: |
1092 | changed |= BSS_CHANGED_SSID; | 1246 | changed |= BSS_CHANGED_SSID; |
1247 | |||
1248 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
1249 | changed |= BSS_CHANGED_AP_PROBE_RESP; | ||
1250 | |||
1093 | /* fall through */ | 1251 | /* fall through */ |
1094 | case NL80211_IFTYPE_MESH_POINT: | 1252 | case NL80211_IFTYPE_MESH_POINT: |
1095 | changed |= BSS_CHANGED_BEACON | | 1253 | changed |= BSS_CHANGED_BEACON | |
@@ -1111,6 +1269,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1111 | } | 1269 | } |
1112 | } | 1270 | } |
1113 | 1271 | ||
1272 | ieee80211_recalc_ps(local, -1); | ||
1273 | |||
1114 | /* | 1274 | /* |
1115 | * Clear the WLAN_STA_BLOCK_BA flag so new aggregation | 1275 | * Clear the WLAN_STA_BLOCK_BA flag so new aggregation |
1116 | * sessions can be established after a resume. | 1276 | * sessions can be established after a resume. |
@@ -1366,6 +1526,108 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif) | |||
1366 | } | 1526 | } |
1367 | EXPORT_SYMBOL(ieee80211_disable_rssi_reports); | 1527 | EXPORT_SYMBOL(ieee80211_disable_rssi_reports); |
1368 | 1528 | ||
1529 | u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | ||
1530 | u16 cap) | ||
1531 | { | ||
1532 | __le16 tmp; | ||
1533 | |||
1534 | *pos++ = WLAN_EID_HT_CAPABILITY; | ||
1535 | *pos++ = sizeof(struct ieee80211_ht_cap); | ||
1536 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); | ||
1537 | |||
1538 | /* capability flags */ | ||
1539 | tmp = cpu_to_le16(cap); | ||
1540 | memcpy(pos, &tmp, sizeof(u16)); | ||
1541 | pos += sizeof(u16); | ||
1542 | |||
1543 | /* AMPDU parameters */ | ||
1544 | *pos++ = ht_cap->ampdu_factor | | ||
1545 | (ht_cap->ampdu_density << | ||
1546 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); | ||
1547 | |||
1548 | /* MCS set */ | ||
1549 | memcpy(pos, &ht_cap->mcs, sizeof(ht_cap->mcs)); | ||
1550 | pos += sizeof(ht_cap->mcs); | ||
1551 | |||
1552 | /* extended capabilities */ | ||
1553 | pos += sizeof(__le16); | ||
1554 | |||
1555 | /* BF capabilities */ | ||
1556 | pos += sizeof(__le32); | ||
1557 | |||
1558 | /* antenna selection */ | ||
1559 | pos += sizeof(u8); | ||
1560 | |||
1561 | return pos; | ||
1562 | } | ||
1563 | |||
1564 | u8 *ieee80211_ie_build_ht_info(u8 *pos, | ||
1565 | struct ieee80211_sta_ht_cap *ht_cap, | ||
1566 | struct ieee80211_channel *channel, | ||
1567 | enum nl80211_channel_type channel_type) | ||
1568 | { | ||
1569 | struct ieee80211_ht_info *ht_info; | ||
1570 | /* Build HT Information */ | ||
1571 | *pos++ = WLAN_EID_HT_INFORMATION; | ||
1572 | *pos++ = sizeof(struct ieee80211_ht_info); | ||
1573 | ht_info = (struct ieee80211_ht_info *)pos; | ||
1574 | ht_info->control_chan = | ||
1575 | ieee80211_frequency_to_channel(channel->center_freq); | ||
1576 | switch (channel_type) { | ||
1577 | case NL80211_CHAN_HT40MINUS: | ||
1578 | ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
1579 | break; | ||
1580 | case NL80211_CHAN_HT40PLUS: | ||
1581 | ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
1582 | break; | ||
1583 | case NL80211_CHAN_HT20: | ||
1584 | default: | ||
1585 | ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
1586 | break; | ||
1587 | } | ||
1588 | if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) | ||
1589 | ht_info->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; | ||
1590 | |||
1591 | /* | ||
1592 | * Note: According to 802.11n-2009 9.13.3.1, HT Protection field and | ||
1593 | * RIFS Mode are reserved in IBSS mode, therefore keep them at 0 | ||
1594 | */ | ||
1595 | ht_info->operation_mode = 0x0000; | ||
1596 | ht_info->stbc_param = 0x0000; | ||
1597 | |||
1598 | /* It seems that Basic MCS set and Supported MCS set | ||
1599 | are identical for the first 10 bytes */ | ||
1600 | memset(&ht_info->basic_set, 0, 16); | ||
1601 | memcpy(&ht_info->basic_set, &ht_cap->mcs, 10); | ||
1602 | |||
1603 | return pos + sizeof(struct ieee80211_ht_info); | ||
1604 | } | ||
1605 | |||
1606 | enum nl80211_channel_type | ||
1607 | ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info) | ||
1608 | { | ||
1609 | enum nl80211_channel_type channel_type; | ||
1610 | |||
1611 | if (!ht_info) | ||
1612 | return NL80211_CHAN_NO_HT; | ||
1613 | |||
1614 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | ||
1615 | case IEEE80211_HT_PARAM_CHA_SEC_NONE: | ||
1616 | channel_type = NL80211_CHAN_HT20; | ||
1617 | break; | ||
1618 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
1619 | channel_type = NL80211_CHAN_HT40PLUS; | ||
1620 | break; | ||
1621 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
1622 | channel_type = NL80211_CHAN_HT40MINUS; | ||
1623 | break; | ||
1624 | default: | ||
1625 | channel_type = NL80211_CHAN_NO_HT; | ||
1626 | } | ||
1627 | |||
1628 | return channel_type; | ||
1629 | } | ||
1630 | |||
1369 | int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb) | 1631 | int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb) |
1370 | { | 1632 | { |
1371 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 1633 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index a1c6bfd55f0f..68ad351479df 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -330,13 +330,12 @@ ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx) | |||
330 | 330 | ||
331 | ieee80211_tx_set_protected(tx); | 331 | ieee80211_tx_set_protected(tx); |
332 | 332 | ||
333 | skb = tx->skb; | 333 | skb_queue_walk(&tx->skbs, skb) { |
334 | do { | ||
335 | if (wep_encrypt_skb(tx, skb) < 0) { | 334 | if (wep_encrypt_skb(tx, skb) < 0) { |
336 | I802_DEBUG_INC(tx->local->tx_handlers_drop_wep); | 335 | I802_DEBUG_INC(tx->local->tx_handlers_drop_wep); |
337 | return TX_DROP; | 336 | return TX_DROP; |
338 | } | 337 | } |
339 | } while ((skb = skb->next)); | 338 | } |
340 | 339 | ||
341 | return TX_CONTINUE; | 340 | return TX_CONTINUE; |
342 | } | 341 | } |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index fd52e695c071..89511be3111e 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -52,6 +52,30 @@ static int wme_downgrade_ac(struct sk_buff *skb) | |||
52 | } | 52 | } |
53 | } | 53 | } |
54 | 54 | ||
55 | /* Indicate which queue to use for this fully formed 802.11 frame */ | ||
56 | u16 ieee80211_select_queue_80211(struct ieee80211_local *local, | ||
57 | struct sk_buff *skb, | ||
58 | struct ieee80211_hdr *hdr) | ||
59 | { | ||
60 | u8 *p; | ||
61 | |||
62 | if (local->hw.queues < 4) | ||
63 | return 0; | ||
64 | |||
65 | if (!ieee80211_is_data(hdr->frame_control)) { | ||
66 | skb->priority = 7; | ||
67 | return ieee802_1d_to_ac[skb->priority]; | ||
68 | } | ||
69 | if (!ieee80211_is_data_qos(hdr->frame_control)) { | ||
70 | skb->priority = 0; | ||
71 | return ieee802_1d_to_ac[skb->priority]; | ||
72 | } | ||
73 | |||
74 | p = ieee80211_get_qos_ctl(hdr); | ||
75 | skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK; | ||
76 | |||
77 | return ieee80211_downgrade_queue(local, skb); | ||
78 | } | ||
55 | 79 | ||
56 | /* Indicate which queue to use. */ | 80 | /* Indicate which queue to use. */ |
57 | u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | 81 | u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, |
@@ -83,7 +107,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
83 | break; | 107 | break; |
84 | #ifdef CONFIG_MAC80211_MESH | 108 | #ifdef CONFIG_MAC80211_MESH |
85 | case NL80211_IFTYPE_MESH_POINT: | 109 | case NL80211_IFTYPE_MESH_POINT: |
86 | ra = skb->data; | 110 | qos = true; |
87 | break; | 111 | break; |
88 | #endif | 112 | #endif |
89 | case NL80211_IFTYPE_STATION: | 113 | case NL80211_IFTYPE_STATION: |
@@ -139,16 +163,24 @@ void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, | |||
139 | struct sk_buff *skb) | 163 | struct sk_buff *skb) |
140 | { | 164 | { |
141 | struct ieee80211_hdr *hdr = (void *)skb->data; | 165 | struct ieee80211_hdr *hdr = (void *)skb->data; |
166 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
142 | 167 | ||
143 | /* Fill in the QoS header if there is one. */ | 168 | /* Fill in the QoS header if there is one. */ |
144 | if (ieee80211_is_data_qos(hdr->frame_control)) { | 169 | if (ieee80211_is_data_qos(hdr->frame_control)) { |
145 | u8 *p = ieee80211_get_qos_ctl(hdr); | 170 | u8 *p = ieee80211_get_qos_ctl(hdr); |
146 | u8 ack_policy = 0, tid; | 171 | u8 ack_policy, tid; |
147 | 172 | ||
148 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; | 173 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; |
149 | 174 | ||
150 | if (unlikely(sdata->local->wifi_wme_noack_test)) | 175 | /* preserve EOSP bit */ |
176 | ack_policy = *p & IEEE80211_QOS_CTL_EOSP; | ||
177 | |||
178 | if (is_multicast_ether_addr(hdr->addr1) || | ||
179 | sdata->noack_map & BIT(tid)) { | ||
151 | ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; | 180 | ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; |
181 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
182 | } | ||
183 | |||
152 | /* qos header is 2 bytes */ | 184 | /* qos header is 2 bytes */ |
153 | *p++ = ack_policy | tid; | 185 | *p++ = ack_policy | tid; |
154 | *p = ieee80211_vif_is_mesh(&sdata->vif) ? | 186 | *p = ieee80211_vif_is_mesh(&sdata->vif) ? |
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index 34e166fbf4d4..94edceb617ff 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h | |||
@@ -15,6 +15,9 @@ | |||
15 | 15 | ||
16 | extern const int ieee802_1d_to_ac[8]; | 16 | extern const int ieee802_1d_to_ac[8]; |
17 | 17 | ||
18 | u16 ieee80211_select_queue_80211(struct ieee80211_local *local, | ||
19 | struct sk_buff *skb, | ||
20 | struct ieee80211_hdr *hdr); | ||
18 | u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | 21 | u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, |
19 | struct sk_buff *skb); | 22 | struct sk_buff *skb); |
20 | void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, | 23 | void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 6c53b6d1002b..c6dd01a05291 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -94,7 +94,8 @@ static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, | |||
94 | 94 | ||
95 | /* frame sending functions */ | 95 | /* frame sending functions */ |
96 | 96 | ||
97 | static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie, | 97 | static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, |
98 | struct sk_buff *skb, const u8 *ht_info_ie, | ||
98 | struct ieee80211_supported_band *sband, | 99 | struct ieee80211_supported_band *sband, |
99 | struct ieee80211_channel *channel, | 100 | struct ieee80211_channel *channel, |
100 | enum ieee80211_smps_mode smps) | 101 | enum ieee80211_smps_mode smps) |
@@ -102,8 +103,10 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie, | |||
102 | struct ieee80211_ht_info *ht_info; | 103 | struct ieee80211_ht_info *ht_info; |
103 | u8 *pos; | 104 | u8 *pos; |
104 | u32 flags = channel->flags; | 105 | u32 flags = channel->flags; |
105 | u16 cap = sband->ht_cap.cap; | 106 | u16 cap; |
106 | __le16 tmp; | 107 | struct ieee80211_sta_ht_cap ht_cap; |
108 | |||
109 | BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); | ||
107 | 110 | ||
108 | if (!sband->ht_cap.ht_supported) | 111 | if (!sband->ht_cap.ht_supported) |
109 | return; | 112 | return; |
@@ -114,9 +117,13 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie, | |||
114 | if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info)) | 117 | if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info)) |
115 | return; | 118 | return; |
116 | 119 | ||
120 | memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); | ||
121 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); | ||
122 | |||
117 | ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2); | 123 | ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2); |
118 | 124 | ||
119 | /* determine capability flags */ | 125 | /* determine capability flags */ |
126 | cap = ht_cap.cap; | ||
120 | 127 | ||
121 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 128 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
122 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 129 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
@@ -154,34 +161,8 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie, | |||
154 | } | 161 | } |
155 | 162 | ||
156 | /* reserve and fill IE */ | 163 | /* reserve and fill IE */ |
157 | |||
158 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); | 164 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); |
159 | *pos++ = WLAN_EID_HT_CAPABILITY; | 165 | ieee80211_ie_build_ht_cap(pos, &ht_cap, cap); |
160 | *pos++ = sizeof(struct ieee80211_ht_cap); | ||
161 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); | ||
162 | |||
163 | /* capability flags */ | ||
164 | tmp = cpu_to_le16(cap); | ||
165 | memcpy(pos, &tmp, sizeof(u16)); | ||
166 | pos += sizeof(u16); | ||
167 | |||
168 | /* AMPDU parameters */ | ||
169 | *pos++ = sband->ht_cap.ampdu_factor | | ||
170 | (sband->ht_cap.ampdu_density << | ||
171 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); | ||
172 | |||
173 | /* MCS set */ | ||
174 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); | ||
175 | pos += sizeof(sband->ht_cap.mcs); | ||
176 | |||
177 | /* extended capabilities */ | ||
178 | pos += sizeof(__le16); | ||
179 | |||
180 | /* BF capabilities */ | ||
181 | pos += sizeof(__le32); | ||
182 | |||
183 | /* antenna selection */ | ||
184 | pos += sizeof(u8); | ||
185 | } | 166 | } |
186 | 167 | ||
187 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | 168 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, |
@@ -356,7 +337,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
356 | 337 | ||
357 | if (wk->assoc.use_11n && wk->assoc.wmm_used && | 338 | if (wk->assoc.use_11n && wk->assoc.wmm_used && |
358 | local->hw.queues >= 4) | 339 | local->hw.queues >= 4) |
359 | ieee80211_add_ht_ie(skb, wk->assoc.ht_information_ie, | 340 | ieee80211_add_ht_ie(sdata, skb, wk->assoc.ht_information_ie, |
360 | sband, wk->chan, wk->assoc.smps); | 341 | sband, wk->chan, wk->assoc.smps); |
361 | 342 | ||
362 | /* if present, add any custom non-vendor IEs that go after HT */ | 343 | /* if present, add any custom non-vendor IEs that go after HT */ |
@@ -881,44 +862,6 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
881 | kfree_skb(skb); | 862 | kfree_skb(skb); |
882 | } | 863 | } |
883 | 864 | ||
884 | static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct, | ||
885 | enum nl80211_channel_type oper_ct) | ||
886 | { | ||
887 | switch (wk_ct) { | ||
888 | case NL80211_CHAN_NO_HT: | ||
889 | return true; | ||
890 | case NL80211_CHAN_HT20: | ||
891 | if (oper_ct != NL80211_CHAN_NO_HT) | ||
892 | return true; | ||
893 | return false; | ||
894 | case NL80211_CHAN_HT40MINUS: | ||
895 | case NL80211_CHAN_HT40PLUS: | ||
896 | return (wk_ct == oper_ct); | ||
897 | } | ||
898 | WARN_ON(1); /* shouldn't get here */ | ||
899 | return false; | ||
900 | } | ||
901 | |||
902 | static enum nl80211_channel_type | ||
903 | ieee80211_calc_ct(enum nl80211_channel_type wk_ct, | ||
904 | enum nl80211_channel_type oper_ct) | ||
905 | { | ||
906 | switch (wk_ct) { | ||
907 | case NL80211_CHAN_NO_HT: | ||
908 | return oper_ct; | ||
909 | case NL80211_CHAN_HT20: | ||
910 | if (oper_ct != NL80211_CHAN_NO_HT) | ||
911 | return oper_ct; | ||
912 | return wk_ct; | ||
913 | case NL80211_CHAN_HT40MINUS: | ||
914 | case NL80211_CHAN_HT40PLUS: | ||
915 | return wk_ct; | ||
916 | } | ||
917 | WARN_ON(1); /* shouldn't get here */ | ||
918 | return wk_ct; | ||
919 | } | ||
920 | |||
921 | |||
922 | static void ieee80211_work_timer(unsigned long data) | 865 | static void ieee80211_work_timer(unsigned long data) |
923 | { | 866 | { |
924 | struct ieee80211_local *local = (void *) data; | 867 | struct ieee80211_local *local = (void *) data; |
@@ -969,51 +912,12 @@ static void ieee80211_work_work(struct work_struct *work) | |||
969 | } | 912 | } |
970 | 913 | ||
971 | if (!started && !local->tmp_channel) { | 914 | if (!started && !local->tmp_channel) { |
972 | bool on_oper_chan; | 915 | ieee80211_offchannel_stop_vifs(local, true); |
973 | bool tmp_chan_changed = false; | ||
974 | bool on_oper_chan2; | ||
975 | enum nl80211_channel_type wk_ct; | ||
976 | on_oper_chan = ieee80211_cfg_on_oper_channel(local); | ||
977 | |||
978 | /* Work with existing channel type if possible. */ | ||
979 | wk_ct = wk->chan_type; | ||
980 | if (wk->chan == local->hw.conf.channel) | ||
981 | wk_ct = ieee80211_calc_ct(wk->chan_type, | ||
982 | local->hw.conf.channel_type); | ||
983 | |||
984 | if (local->tmp_channel) | ||
985 | if ((local->tmp_channel != wk->chan) || | ||
986 | (local->tmp_channel_type != wk_ct)) | ||
987 | tmp_chan_changed = true; | ||
988 | 916 | ||
989 | local->tmp_channel = wk->chan; | 917 | local->tmp_channel = wk->chan; |
990 | local->tmp_channel_type = wk_ct; | 918 | local->tmp_channel_type = wk->chan_type; |
991 | /* | 919 | |
992 | * Leave the station vifs in awake mode if they | 920 | ieee80211_hw_config(local, 0); |
993 | * happen to be on the same channel as | ||
994 | * the requested channel. | ||
995 | */ | ||
996 | on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); | ||
997 | if (on_oper_chan != on_oper_chan2) { | ||
998 | if (on_oper_chan2) { | ||
999 | /* going off oper channel, PS too */ | ||
1000 | ieee80211_offchannel_stop_vifs(local, | ||
1001 | true); | ||
1002 | ieee80211_hw_config(local, 0); | ||
1003 | } else { | ||
1004 | /* going on channel, but leave PS | ||
1005 | * off-channel. */ | ||
1006 | ieee80211_hw_config(local, 0); | ||
1007 | ieee80211_offchannel_return(local, | ||
1008 | true, | ||
1009 | false); | ||
1010 | } | ||
1011 | } else if (tmp_chan_changed) | ||
1012 | /* Still off-channel, but on some other | ||
1013 | * channel, so update hardware. | ||
1014 | * PS should already be off-channel. | ||
1015 | */ | ||
1016 | ieee80211_hw_config(local, 0); | ||
1017 | 921 | ||
1018 | started = true; | 922 | started = true; |
1019 | wk->timeout = jiffies; | 923 | wk->timeout = jiffies; |
@@ -1082,34 +986,17 @@ static void ieee80211_work_work(struct work_struct *work) | |||
1082 | list_for_each_entry(wk, &local->work_list, list) { | 986 | list_for_each_entry(wk, &local->work_list, list) { |
1083 | if (!wk->started) | 987 | if (!wk->started) |
1084 | continue; | 988 | continue; |
1085 | if (wk->chan != local->tmp_channel) | 989 | if (wk->chan != local->tmp_channel || |
1086 | continue; | 990 | wk->chan_type != local->tmp_channel_type) |
1087 | if (!ieee80211_work_ct_coexists(wk->chan_type, | ||
1088 | local->tmp_channel_type)) | ||
1089 | continue; | 991 | continue; |
1090 | remain_off_channel = true; | 992 | remain_off_channel = true; |
1091 | } | 993 | } |
1092 | 994 | ||
1093 | if (!remain_off_channel && local->tmp_channel) { | 995 | if (!remain_off_channel && local->tmp_channel) { |
1094 | local->tmp_channel = NULL; | 996 | local->tmp_channel = NULL; |
1095 | /* If tmp_channel wasn't operating channel, then | 997 | ieee80211_hw_config(local, 0); |
1096 | * we need to go back on-channel. | ||
1097 | * NOTE: If we can ever be here while scannning, | ||
1098 | * or if the hw_config() channel config logic changes, | ||
1099 | * then we may need to do a more thorough check to see if | ||
1100 | * we still need to do a hardware config. Currently, | ||
1101 | * we cannot be here while scanning, however. | ||
1102 | */ | ||
1103 | if (!ieee80211_cfg_on_oper_channel(local)) | ||
1104 | ieee80211_hw_config(local, 0); | ||
1105 | 998 | ||
1106 | /* At the least, we need to disable offchannel_ps, | 999 | ieee80211_offchannel_return(local, true); |
1107 | * so just go ahead and run the entire offchannel | ||
1108 | * return logic here. We *could* skip enabling | ||
1109 | * beaconing if we were already on-oper-channel | ||
1110 | * as a future optimization. | ||
1111 | */ | ||
1112 | ieee80211_offchannel_return(local, true, true); | ||
1113 | 1000 | ||
1114 | /* give connection some time to breathe */ | 1001 | /* give connection some time to breathe */ |
1115 | run_again(local, jiffies + HZ/2); | 1002 | run_again(local, jiffies + HZ/2); |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index f614ce7bb6e3..93aab0715e8a 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -223,14 +223,14 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
223 | ieee80211_tx_result | 223 | ieee80211_tx_result |
224 | ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx) | 224 | ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx) |
225 | { | 225 | { |
226 | struct sk_buff *skb = tx->skb; | 226 | struct sk_buff *skb; |
227 | 227 | ||
228 | ieee80211_tx_set_protected(tx); | 228 | ieee80211_tx_set_protected(tx); |
229 | 229 | ||
230 | do { | 230 | skb_queue_walk(&tx->skbs, skb) { |
231 | if (tkip_encrypt_skb(tx, skb) < 0) | 231 | if (tkip_encrypt_skb(tx, skb) < 0) |
232 | return TX_DROP; | 232 | return TX_DROP; |
233 | } while ((skb = skb->next)); | 233 | } |
234 | 234 | ||
235 | return TX_CONTINUE; | 235 | return TX_CONTINUE; |
236 | } | 236 | } |
@@ -390,7 +390,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
390 | u8 scratch[6 * AES_BLOCK_SIZE]; | 390 | u8 scratch[6 * AES_BLOCK_SIZE]; |
391 | 391 | ||
392 | if (info->control.hw_key && | 392 | if (info->control.hw_key && |
393 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | 393 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) && |
394 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) { | ||
394 | /* | 395 | /* |
395 | * hwaccel has no need for preallocated room for CCMP | 396 | * hwaccel has no need for preallocated room for CCMP |
396 | * header or MIC fields | 397 | * header or MIC fields |
@@ -412,6 +413,12 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
412 | 413 | ||
413 | pos = skb_push(skb, CCMP_HDR_LEN); | 414 | pos = skb_push(skb, CCMP_HDR_LEN); |
414 | memmove(pos, pos + CCMP_HDR_LEN, hdrlen); | 415 | memmove(pos, pos + CCMP_HDR_LEN, hdrlen); |
416 | |||
417 | /* the HW only needs room for the IV, but not the actual IV */ | ||
418 | if (info->control.hw_key && | ||
419 | (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) | ||
420 | return 0; | ||
421 | |||
415 | hdr = (struct ieee80211_hdr *) pos; | 422 | hdr = (struct ieee80211_hdr *) pos; |
416 | pos += hdrlen; | 423 | pos += hdrlen; |
417 | 424 | ||
@@ -442,14 +449,14 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
442 | ieee80211_tx_result | 449 | ieee80211_tx_result |
443 | ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) | 450 | ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) |
444 | { | 451 | { |
445 | struct sk_buff *skb = tx->skb; | 452 | struct sk_buff *skb; |
446 | 453 | ||
447 | ieee80211_tx_set_protected(tx); | 454 | ieee80211_tx_set_protected(tx); |
448 | 455 | ||
449 | do { | 456 | skb_queue_walk(&tx->skbs, skb) { |
450 | if (ccmp_encrypt_skb(tx, skb) < 0) | 457 | if (ccmp_encrypt_skb(tx, skb) < 0) |
451 | return TX_DROP; | 458 | return TX_DROP; |
452 | } while ((skb = skb->next)); | 459 | } |
453 | 460 | ||
454 | return TX_CONTINUE; | 461 | return TX_CONTINUE; |
455 | } | 462 | } |
@@ -547,15 +554,22 @@ static inline void bip_ipn_swap(u8 *d, const u8 *s) | |||
547 | ieee80211_tx_result | 554 | ieee80211_tx_result |
548 | ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx) | 555 | ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx) |
549 | { | 556 | { |
550 | struct sk_buff *skb = tx->skb; | 557 | struct sk_buff *skb; |
551 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 558 | struct ieee80211_tx_info *info; |
552 | struct ieee80211_key *key = tx->key; | 559 | struct ieee80211_key *key = tx->key; |
553 | struct ieee80211_mmie *mmie; | 560 | struct ieee80211_mmie *mmie; |
554 | u8 aad[20]; | 561 | u8 aad[20]; |
555 | u64 pn64; | 562 | u64 pn64; |
556 | 563 | ||
564 | if (WARN_ON(skb_queue_len(&tx->skbs) != 1)) | ||
565 | return TX_DROP; | ||
566 | |||
567 | skb = skb_peek(&tx->skbs); | ||
568 | |||
569 | info = IEEE80211_SKB_CB(skb); | ||
570 | |||
557 | if (info->control.hw_key) | 571 | if (info->control.hw_key) |
558 | return 0; | 572 | return TX_CONTINUE; |
559 | 573 | ||
560 | if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) | 574 | if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) |
561 | return TX_DROP; | 575 | return TX_DROP; |