aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-05-22 15:18:06 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-05-22 15:18:06 -0400
commita0d0d1685f9763ab26a394df3ab84026b39a06a7 (patch)
tree4165dc6fd3266977ab4b3fa3b379c47597f97d88 /net/mac80211
parent31a67102f4762df5544bc2dfb34a931233d2a5b2 (diff)
parent05f8f25276ea8c7d41b3649890d6eaf179e67a81 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/agg-tx.c10
-rw-r--r--net/mac80211/debugfs_netdev.c2
-rw-r--r--net/mac80211/ibss.c5
-rw-r--r--net/mac80211/iface.c4
-rw-r--r--net/mac80211/main.c3
-rw-r--r--net/mac80211/mesh.c6
-rw-r--r--net/mac80211/mesh_hwmp.c5
-rw-r--r--net/mac80211/mesh_plink.c65
-rw-r--r--net/mac80211/rx.c6
-rw-r--r--net/mac80211/wep.c15
-rw-r--r--net/mac80211/wpa.c10
11 files changed, 86 insertions, 45 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 5b7053c58732..7cf07158805c 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -421,16 +421,22 @@ static void sta_tx_agg_session_timer_expired(unsigned long data)
421 struct tid_ampdu_tx *tid_tx; 421 struct tid_ampdu_tx *tid_tx;
422 unsigned long timeout; 422 unsigned long timeout;
423 423
424 tid_tx = rcu_dereference_protected_tid_tx(sta, *ptid); 424 rcu_read_lock();
425 if (!tid_tx) 425 tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[*ptid]);
426 if (!tid_tx || test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
427 rcu_read_unlock();
426 return; 428 return;
429 }
427 430
428 timeout = tid_tx->last_tx + TU_TO_JIFFIES(tid_tx->timeout); 431 timeout = tid_tx->last_tx + TU_TO_JIFFIES(tid_tx->timeout);
429 if (time_is_after_jiffies(timeout)) { 432 if (time_is_after_jiffies(timeout)) {
430 mod_timer(&tid_tx->session_timer, timeout); 433 mod_timer(&tid_tx->session_timer, timeout);
434 rcu_read_unlock();
431 return; 435 return;
432 } 436 }
433 437
438 rcu_read_unlock();
439
434#ifdef CONFIG_MAC80211_HT_DEBUG 440#ifdef CONFIG_MAC80211_HT_DEBUG
435 printk(KERN_DEBUG "tx session timer expired on tid %d\n", (u16)*ptid); 441 printk(KERN_DEBUG "tx session timer expired on tid %d\n", (u16)*ptid);
436#endif 442#endif
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index ea0122dbd2b3..7ed433c66d68 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -509,6 +509,7 @@ IEEE80211_IF_FILE(dot11MeshHWMPRannInterval,
509 u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC); 509 u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
510IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC); 510IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC);
511IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC); 511IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC);
512IEEE80211_IF_FILE(ht_opmode, u.mesh.mshcfg.ht_opmode, DEC);
512#endif 513#endif
513 514
514#define DEBUGFS_ADD_MODE(name, mode) \ 515#define DEBUGFS_ADD_MODE(name, mode) \
@@ -608,6 +609,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
608 MESHPARAMS_ADD(dot11MeshHWMPRannInterval); 609 MESHPARAMS_ADD(dot11MeshHWMPRannInterval);
609 MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol); 610 MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol);
610 MESHPARAMS_ADD(rssi_threshold); 611 MESHPARAMS_ADD(rssi_threshold);
612 MESHPARAMS_ADD(ht_opmode);
611#undef MESHPARAMS_ADD 613#undef MESHPARAMS_ADD
612} 614}
613#endif 615#endif
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 3ad33a824624..33d9d0c3e3d0 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -163,6 +163,11 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
163 sizeof(struct ieee80211_ht_operation)); 163 sizeof(struct ieee80211_ht_operation));
164 pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, 164 pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap,
165 sband->ht_cap.cap); 165 sband->ht_cap.cap);
166 /*
167 * Note: According to 802.11n-2009 9.13.3.1, HT Protection
168 * field and RIFS Mode are reserved in IBSS mode, therefore
169 * keep them at 0
170 */
166 pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, 171 pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap,
167 chan, channel_type, 0); 172 chan, channel_type, 0);
168 } 173 }
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 856237c5c1f8..d4c19a7773db 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -206,8 +206,10 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
206 for (i = 0; i < IEEE80211_NUM_ACS; i++) { 206 for (i = 0; i < IEEE80211_NUM_ACS; i++) {
207 if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) 207 if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
208 sdata->vif.hw_queue[i] = IEEE80211_INVAL_HW_QUEUE; 208 sdata->vif.hw_queue[i] = IEEE80211_INVAL_HW_QUEUE;
209 else 209 else if (local->hw.queues >= IEEE80211_NUM_ACS)
210 sdata->vif.hw_queue[i] = i; 210 sdata->vif.hw_queue[i] = i;
211 else
212 sdata->vif.hw_queue[i] = 0;
211 } 213 }
212 sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; 214 sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
213} 215}
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index b70f7f09da61..f5548e953259 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -596,6 +596,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
596 local->hw.offchannel_tx_hw_queue = IEEE80211_INVAL_HW_QUEUE; 596 local->hw.offchannel_tx_hw_queue = IEEE80211_INVAL_HW_QUEUE;
597 local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; 597 local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
598 local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; 598 local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
599 local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
600 IEEE80211_RADIOTAP_MCS_HAVE_GI |
601 IEEE80211_RADIOTAP_MCS_HAVE_BW;
599 local->user_power_level = -1; 602 local->user_power_level = -1;
600 wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; 603 wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
601 604
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 0675a2fec6a6..2913113c5833 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -109,8 +109,10 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
109 109
110 /* Disallow HT40+/- mismatch */ 110 /* Disallow HT40+/- mismatch */
111 if (ie->ht_operation && 111 if (ie->ht_operation &&
112 local->_oper_channel_type > NL80211_CHAN_HT20 && 112 (local->_oper_channel_type == NL80211_CHAN_HT40MINUS ||
113 sta_channel_type > NL80211_CHAN_HT20 && 113 local->_oper_channel_type == NL80211_CHAN_HT40PLUS) &&
114 (sta_channel_type == NL80211_CHAN_HT40MINUS ||
115 sta_channel_type == NL80211_CHAN_HT40PLUS) &&
114 local->_oper_channel_type != sta_channel_type) 116 local->_oper_channel_type != sta_channel_type)
115 goto mismatch; 117 goto mismatch;
116 118
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 27e0c2f06795..9b59658e8650 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -603,7 +603,10 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
603 hopcount, ttl, cpu_to_le32(lifetime), 603 hopcount, ttl, cpu_to_le32(lifetime),
604 cpu_to_le32(metric), cpu_to_le32(preq_id), 604 cpu_to_le32(metric), cpu_to_le32(preq_id),
605 sdata); 605 sdata);
606 ifmsh->mshstats.fwded_mcast++; 606 if (!is_multicast_ether_addr(da))
607 ifmsh->mshstats.fwded_unicast++;
608 else
609 ifmsh->mshstats.fwded_mcast++;
607 ifmsh->mshstats.fwded_frames++; 610 ifmsh->mshstats.fwded_frames++;
608 } 611 }
609} 612}
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 8cc8461b48a0..60ef235c9d9b 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -105,15 +105,15 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
105 return sta; 105 return sta;
106} 106}
107 107
108/** mesh_set_ht_prot_mode - set correct HT protection mode 108/*
109 * mesh_set_ht_prot_mode - set correct HT protection mode
109 * 110 *
110 * Section 9.23.3.5 of IEEE 80211s standard describes the protection rules for 111 * Section 9.23.3.5 of IEEE 80211-2012 describes the protection rules for HT
111 * HT mesh STA in a MBSS. Three HT protection modes are supported for now, 112 * mesh STA in a MBSS. Three HT protection modes are supported for now, non-HT
112 * non-HT mixed mode, 20MHz-protection and no-protection mode. non-HT mixed 113 * mixed mode, 20MHz-protection and no-protection mode. non-HT mixed mode is
113 * mode is selected if any non-HT peers are present in our MBSS. 114 * selected if any non-HT peers are present in our MBSS. 20MHz-protection mode
114 * 20MHz-protection mode is selected if all peers in our 20/40MHz MBSS support 115 * is selected if all peers in our 20/40MHz MBSS support HT and atleast one
115 * HT and atleast one HT20 peer is present. Otherwise no-protection mode is 116 * HT20 peer is present. Otherwise no-protection mode is selected.
116 * selected.
117 */ 117 */
118static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) 118static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
119{ 119{
@@ -128,21 +128,22 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
128 128
129 rcu_read_lock(); 129 rcu_read_lock();
130 list_for_each_entry_rcu(sta, &local->sta_list, list) { 130 list_for_each_entry_rcu(sta, &local->sta_list, list) {
131 if (sdata == sta->sdata && 131 if (sdata != sta->sdata ||
132 sta->plink_state == NL80211_PLINK_ESTAB) { 132 sta->plink_state != NL80211_PLINK_ESTAB)
133 switch (sta->ch_type) { 133 continue;
134 case NL80211_CHAN_NO_HT: 134
135 mpl_dbg("mesh_plink %pM: nonHT sta (%pM) is present", 135 switch (sta->ch_type) {
136 sdata->vif.addr, sta->sta.addr); 136 case NL80211_CHAN_NO_HT:
137 non_ht_sta = true; 137 mpl_dbg("mesh_plink %pM: nonHT sta (%pM) is present",
138 goto out; 138 sdata->vif.addr, sta->sta.addr);
139 case NL80211_CHAN_HT20: 139 non_ht_sta = true;
140 mpl_dbg("mesh_plink %pM: HT20 sta (%pM) is present", 140 goto out;
141 sdata->vif.addr, sta->sta.addr); 141 case NL80211_CHAN_HT20:
142 ht20_sta = true; 142 mpl_dbg("mesh_plink %pM: HT20 sta (%pM) is present",
143 default: 143 sdata->vif.addr, sta->sta.addr);
144 break; 144 ht20_sta = true;
145 } 145 default:
146 break;
146 } 147 }
147 } 148 }
148out: 149out:
@@ -346,6 +347,15 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
346 347
347 sta = sta_info_get(sdata, addr); 348 sta = sta_info_get(sdata, addr);
348 if (!sta) { 349 if (!sta) {
350 /* Userspace handles peer allocation when security is enabled */
351 if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) {
352 cfg80211_notify_new_peer_candidate(sdata->dev, addr,
353 elems->ie_start,
354 elems->total_len,
355 GFP_ATOMIC);
356 return NULL;
357 }
358
349 sta = mesh_plink_alloc(sdata, addr); 359 sta = mesh_plink_alloc(sdata, addr);
350 if (!sta) 360 if (!sta)
351 return NULL; 361 return NULL;
@@ -387,15 +397,6 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
387{ 397{
388 struct sta_info *sta; 398 struct sta_info *sta;
389 399
390 /* Userspace handles peer allocation when security is enabled */
391 if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) {
392 cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr,
393 elems->ie_start,
394 elems->total_len,
395 GFP_KERNEL);
396 return;
397 }
398
399 rcu_read_lock(); 400 rcu_read_lock();
400 sta = mesh_peer_init(sdata, hw_addr, elems); 401 sta = mesh_peer_init(sdata, hw_addr, elems);
401 if (!sta) 402 if (!sta)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 8257a09eeed4..7bcecf73aafb 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -204,14 +204,14 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
204 204
205 if (status->flag & RX_FLAG_HT) { 205 if (status->flag & RX_FLAG_HT) {
206 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS); 206 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
207 *pos++ = IEEE80211_RADIOTAP_MCS_HAVE_MCS | 207 *pos++ = local->hw.radiotap_mcs_details;
208 IEEE80211_RADIOTAP_MCS_HAVE_GI |
209 IEEE80211_RADIOTAP_MCS_HAVE_BW;
210 *pos = 0; 208 *pos = 0;
211 if (status->flag & RX_FLAG_SHORT_GI) 209 if (status->flag & RX_FLAG_SHORT_GI)
212 *pos |= IEEE80211_RADIOTAP_MCS_SGI; 210 *pos |= IEEE80211_RADIOTAP_MCS_SGI;
213 if (status->flag & RX_FLAG_40MHZ) 211 if (status->flag & RX_FLAG_40MHZ)
214 *pos |= IEEE80211_RADIOTAP_MCS_BW_40; 212 *pos |= IEEE80211_RADIOTAP_MCS_BW_40;
213 if (status->flag & RX_FLAG_HT_GF)
214 *pos |= IEEE80211_RADIOTAP_MCS_FMT_GF;
215 pos++; 215 pos++;
216 *pos++ = status->rate_idx; 216 *pos++ = status->rate_idx;
217 } 217 }
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index 7aa31bbfaa3b..c04d401dae92 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -92,6 +92,7 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local,
92 int keylen, int keyidx) 92 int keylen, int keyidx)
93{ 93{
94 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 94 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
95 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
95 unsigned int hdrlen; 96 unsigned int hdrlen;
96 u8 *newhdr; 97 u8 *newhdr;
97 98
@@ -104,6 +105,13 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local,
104 hdrlen = ieee80211_hdrlen(hdr->frame_control); 105 hdrlen = ieee80211_hdrlen(hdr->frame_control);
105 newhdr = skb_push(skb, WEP_IV_LEN); 106 newhdr = skb_push(skb, WEP_IV_LEN);
106 memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen); 107 memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen);
108
109 /* the HW only needs room for the IV, but not the actual IV */
110 if (info->control.hw_key &&
111 (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
112 return newhdr + hdrlen;
113
114 skb_set_network_header(skb, skb_network_offset(skb) + WEP_IV_LEN);
107 ieee80211_wep_get_iv(local, keylen, keyidx, newhdr + hdrlen); 115 ieee80211_wep_get_iv(local, keylen, keyidx, newhdr + hdrlen);
108 return newhdr + hdrlen; 116 return newhdr + hdrlen;
109} 117}
@@ -313,14 +321,15 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx)
313static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) 321static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
314{ 322{
315 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 323 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
324 struct ieee80211_key_conf *hw_key = info->control.hw_key;
316 325
317 if (!info->control.hw_key) { 326 if (!hw_key) {
318 if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key, 327 if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key,
319 tx->key->conf.keylen, 328 tx->key->conf.keylen,
320 tx->key->conf.keyidx)) 329 tx->key->conf.keyidx))
321 return -1; 330 return -1;
322 } else if (info->control.hw_key->flags & 331 } else if ((hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
323 IEEE80211_KEY_FLAG_GENERATE_IV) { 332 (hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) {
324 if (!ieee80211_wep_add_iv(tx->local, skb, 333 if (!ieee80211_wep_add_iv(tx->local, skb,
325 tx->key->conf.keylen, 334 tx->key->conf.keylen,
326 tx->key->conf.keyidx)) 335 tx->key->conf.keyidx))
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 0ae23c60968c..bdb53aba888e 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -183,7 +183,8 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
183 u8 *pos; 183 u8 *pos;
184 184
185 if (info->control.hw_key && 185 if (info->control.hw_key &&
186 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { 186 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
187 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) {
187 /* hwaccel - with no need for software-generated IV */ 188 /* hwaccel - with no need for software-generated IV */
188 return 0; 189 return 0;
189 } 190 }
@@ -202,8 +203,14 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
202 203
203 pos = skb_push(skb, TKIP_IV_LEN); 204 pos = skb_push(skb, TKIP_IV_LEN);
204 memmove(pos, pos + TKIP_IV_LEN, hdrlen); 205 memmove(pos, pos + TKIP_IV_LEN, hdrlen);
206 skb_set_network_header(skb, skb_network_offset(skb) + TKIP_IV_LEN);
205 pos += hdrlen; 207 pos += hdrlen;
206 208
209 /* the HW only needs room for the IV, but not the actual IV */
210 if (info->control.hw_key &&
211 (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
212 return 0;
213
207 /* Increase IV for the frame */ 214 /* Increase IV for the frame */
208 spin_lock_irqsave(&key->u.tkip.txlock, flags); 215 spin_lock_irqsave(&key->u.tkip.txlock, flags);
209 key->u.tkip.tx.iv16++; 216 key->u.tkip.tx.iv16++;
@@ -422,6 +429,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
422 429
423 pos = skb_push(skb, CCMP_HDR_LEN); 430 pos = skb_push(skb, CCMP_HDR_LEN);
424 memmove(pos, pos + CCMP_HDR_LEN, hdrlen); 431 memmove(pos, pos + CCMP_HDR_LEN, hdrlen);
432 skb_set_network_header(skb, skb_network_offset(skb) + CCMP_HDR_LEN);
425 433
426 /* the HW only needs room for the IV, but not the actual IV */ 434 /* the HW only needs room for the IV, but not the actual IV */
427 if (info->control.hw_key && 435 if (info->control.hw_key &&