diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-05-22 15:18:06 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-05-22 15:18:06 -0400 |
commit | a0d0d1685f9763ab26a394df3ab84026b39a06a7 (patch) | |
tree | 4165dc6fd3266977ab4b3fa3b379c47597f97d88 /net/mac80211 | |
parent | 31a67102f4762df5544bc2dfb34a931233d2a5b2 (diff) | |
parent | 05f8f25276ea8c7d41b3649890d6eaf179e67a81 (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.c | 10 | ||||
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 2 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 5 | ||||
-rw-r--r-- | net/mac80211/iface.c | 4 | ||||
-rw-r--r-- | net/mac80211/main.c | 3 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 6 | ||||
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 5 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 65 | ||||
-rw-r--r-- | net/mac80211/rx.c | 6 | ||||
-rw-r--r-- | net/mac80211/wep.c | 15 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 10 |
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); |
510 | IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC); | 510 | IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC); |
511 | IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC); | 511 | IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC); |
512 | IEEE80211_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 | */ |
118 | static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) | 118 | static 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 | } |
148 | out: | 149 | out: |
@@ -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) | |||
313 | static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | 321 | static 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 && |