diff options
-rw-r--r-- | include/linux/skbuff.h | 4 | ||||
-rw-r--r-- | include/net/mac80211.h | 3 | ||||
-rw-r--r-- | net/core/skbuff.c | 1 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 5 | ||||
-rw-r--r-- | net/mac80211/main.c | 61 | ||||
-rw-r--r-- | net/mac80211/rx.c | 25 | ||||
-rw-r--r-- | net/mac80211/tx.c | 3 | ||||
-rw-r--r-- | net/mac80211/util.c | 46 | ||||
-rw-r--r-- | net/mac80211/wme.c | 2 |
9 files changed, 72 insertions, 78 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index f1c93b878b3b..fa51293f2708 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -304,9 +304,6 @@ typedef unsigned char *sk_buff_data_t; | |||
304 | * @tc_verd: traffic control verdict | 304 | * @tc_verd: traffic control verdict |
305 | * @ndisc_nodetype: router type (from link layer) | 305 | * @ndisc_nodetype: router type (from link layer) |
306 | * @do_not_encrypt: set to prevent encryption of this frame | 306 | * @do_not_encrypt: set to prevent encryption of this frame |
307 | * @requeue: set to indicate that the wireless core should attempt | ||
308 | * a software retry on this frame if we failed to | ||
309 | * receive an ACK for it | ||
310 | * @dma_cookie: a cookie to one of several possible DMA operations | 307 | * @dma_cookie: a cookie to one of several possible DMA operations |
311 | * done by skb DMA functions | 308 | * done by skb DMA functions |
312 | * @secmark: security marking | 309 | * @secmark: security marking |
@@ -380,7 +377,6 @@ struct sk_buff { | |||
380 | #endif | 377 | #endif |
381 | #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) | 378 | #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) |
382 | __u8 do_not_encrypt:1; | 379 | __u8 do_not_encrypt:1; |
383 | __u8 requeue:1; | ||
384 | #endif | 380 | #endif |
385 | /* 0/13/14 bit hole */ | 381 | /* 0/13/14 bit hole */ |
386 | 382 | ||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 17d61d19d912..c06104476973 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -239,6 +239,8 @@ struct ieee80211_bss_conf { | |||
239 | * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211, | 239 | * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211, |
240 | * used to indicate that a pending frame requires TX processing before | 240 | * used to indicate that a pending frame requires TX processing before |
241 | * it can be sent out. | 241 | * it can be sent out. |
242 | * @IEEE80211_TX_INTFL_RETRIED: completely internal to mac80211, | ||
243 | * used to indicate that a frame was already retried due to PS | ||
242 | */ | 244 | */ |
243 | enum mac80211_tx_control_flags { | 245 | enum mac80211_tx_control_flags { |
244 | IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), | 246 | IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), |
@@ -256,6 +258,7 @@ enum mac80211_tx_control_flags { | |||
256 | IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), | 258 | IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), |
257 | IEEE80211_TX_INTFL_RCALGO = BIT(13), | 259 | IEEE80211_TX_INTFL_RCALGO = BIT(13), |
258 | IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14), | 260 | IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14), |
261 | IEEE80211_TX_INTFL_RETRIED = BIT(15), | ||
259 | }; | 262 | }; |
260 | 263 | ||
261 | /** | 264 | /** |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 49961ba3c0f6..b94d777e3eb4 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -552,7 +552,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
552 | new->vlan_tci = old->vlan_tci; | 552 | new->vlan_tci = old->vlan_tci; |
553 | #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) | 553 | #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) |
554 | new->do_not_encrypt = old->do_not_encrypt; | 554 | new->do_not_encrypt = old->do_not_encrypt; |
555 | new->requeue = old->requeue; | ||
556 | #endif | 555 | #endif |
557 | 556 | ||
558 | skb_copy_secmark(new, old); | 557 | skb_copy_secmark(new, old); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c088c46704a3..4dbc28964196 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -589,6 +589,7 @@ enum queue_stop_reason { | |||
589 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, | 589 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, |
590 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, | 590 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, |
591 | IEEE80211_QUEUE_STOP_REASON_PENDING, | 591 | IEEE80211_QUEUE_STOP_REASON_PENDING, |
592 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, | ||
592 | }; | 593 | }; |
593 | 594 | ||
594 | struct ieee80211_master_priv { | 595 | struct ieee80211_master_priv { |
@@ -1121,6 +1122,10 @@ void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | |||
1121 | enum queue_stop_reason reason); | 1122 | enum queue_stop_reason reason); |
1122 | void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, | 1123 | void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, |
1123 | enum queue_stop_reason reason); | 1124 | enum queue_stop_reason reason); |
1125 | void ieee80211_add_pending_skb(struct ieee80211_local *local, | ||
1126 | struct sk_buff *skb); | ||
1127 | int ieee80211_add_pending_skbs(struct ieee80211_local *local, | ||
1128 | struct sk_buff_head *skbs); | ||
1124 | 1129 | ||
1125 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 1130 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
1126 | u16 transaction, u16 auth_alg, | 1131 | u16 transaction, u16 auth_alg, |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 2683df918073..092a017b237e 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -369,60 +369,12 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
369 | } | 369 | } |
370 | } | 370 | } |
371 | 371 | ||
372 | /* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to | ||
373 | * make a prepared TX frame (one that has been given to hw) to look like brand | ||
374 | * new IEEE 802.11 frame that is ready to go through TX processing again. | ||
375 | */ | ||
376 | static void ieee80211_remove_tx_extra(struct ieee80211_local *local, | ||
377 | struct ieee80211_key *key, | ||
378 | struct sk_buff *skb) | ||
379 | { | ||
380 | unsigned int hdrlen, iv_len, mic_len; | ||
381 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
382 | |||
383 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
384 | |||
385 | if (!key) | ||
386 | goto no_key; | ||
387 | |||
388 | switch (key->conf.alg) { | ||
389 | case ALG_WEP: | ||
390 | iv_len = WEP_IV_LEN; | ||
391 | mic_len = WEP_ICV_LEN; | ||
392 | break; | ||
393 | case ALG_TKIP: | ||
394 | iv_len = TKIP_IV_LEN; | ||
395 | mic_len = TKIP_ICV_LEN; | ||
396 | break; | ||
397 | case ALG_CCMP: | ||
398 | iv_len = CCMP_HDR_LEN; | ||
399 | mic_len = CCMP_MIC_LEN; | ||
400 | break; | ||
401 | default: | ||
402 | goto no_key; | ||
403 | } | ||
404 | |||
405 | if (skb->len >= hdrlen + mic_len && | ||
406 | !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | ||
407 | skb_trim(skb, skb->len - mic_len); | ||
408 | if (skb->len >= hdrlen + iv_len) { | ||
409 | memmove(skb->data + iv_len, skb->data, hdrlen); | ||
410 | hdr = (struct ieee80211_hdr *)skb_pull(skb, iv_len); | ||
411 | } | ||
412 | |||
413 | no_key: | ||
414 | if (ieee80211_is_data_qos(hdr->frame_control)) { | ||
415 | hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); | ||
416 | memmove(skb->data + IEEE80211_QOS_CTL_LEN, skb->data, | ||
417 | hdrlen - IEEE80211_QOS_CTL_LEN); | ||
418 | skb_pull(skb, IEEE80211_QOS_CTL_LEN); | ||
419 | } | ||
420 | } | ||
421 | |||
422 | static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | 372 | static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, |
423 | struct sta_info *sta, | 373 | struct sta_info *sta, |
424 | struct sk_buff *skb) | 374 | struct sk_buff *skb) |
425 | { | 375 | { |
376 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
377 | |||
426 | sta->tx_filtered_count++; | 378 | sta->tx_filtered_count++; |
427 | 379 | ||
428 | /* | 380 | /* |
@@ -464,16 +416,15 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
464 | */ | 416 | */ |
465 | if (test_sta_flags(sta, WLAN_STA_PS) && | 417 | if (test_sta_flags(sta, WLAN_STA_PS) && |
466 | skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { | 418 | skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { |
467 | ieee80211_remove_tx_extra(local, sta->key, skb); | ||
468 | skb_queue_tail(&sta->tx_filtered, skb); | 419 | skb_queue_tail(&sta->tx_filtered, skb); |
469 | return; | 420 | return; |
470 | } | 421 | } |
471 | 422 | ||
472 | if (!test_sta_flags(sta, WLAN_STA_PS) && !skb->requeue) { | 423 | if (!test_sta_flags(sta, WLAN_STA_PS) && |
424 | !(info->flags & IEEE80211_TX_INTFL_RETRIED)) { | ||
473 | /* Software retry the packet once */ | 425 | /* Software retry the packet once */ |
474 | skb->requeue = 1; | 426 | info->flags |= IEEE80211_TX_INTFL_RETRIED; |
475 | ieee80211_remove_tx_extra(local, sta->key, skb); | 427 | ieee80211_add_pending_skb(local, skb); |
476 | dev_queue_xmit(skb); | ||
477 | return; | 428 | return; |
478 | } | 429 | } |
479 | 430 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 754125185109..de5bba7f910a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -797,8 +797,7 @@ static int ap_sta_ps_end(struct sta_info *sta) | |||
797 | { | 797 | { |
798 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 798 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
799 | struct ieee80211_local *local = sdata->local; | 799 | struct ieee80211_local *local = sdata->local; |
800 | struct sk_buff *skb; | 800 | int sent, buffered; |
801 | int sent = 0; | ||
802 | 801 | ||
803 | atomic_dec(&sdata->bss->num_sta_ps); | 802 | atomic_dec(&sdata->bss->num_sta_ps); |
804 | 803 | ||
@@ -814,22 +813,16 @@ static int ap_sta_ps_end(struct sta_info *sta) | |||
814 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 813 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
815 | 814 | ||
816 | /* Send all buffered frames to the station */ | 815 | /* Send all buffered frames to the station */ |
817 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { | 816 | sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered); |
818 | sent++; | 817 | buffered = ieee80211_add_pending_skbs(local, &sta->ps_tx_buf); |
819 | skb->requeue = 1; | 818 | sent += buffered; |
820 | dev_queue_xmit(skb); | 819 | local->total_ps_buffered -= buffered; |
821 | } | 820 | |
822 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { | ||
823 | local->total_ps_buffered--; | ||
824 | sent++; | ||
825 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 821 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
826 | printk(KERN_DEBUG "%s: STA %pM aid %d send PS frame " | 822 | printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " |
827 | "since STA not sleeping anymore\n", sdata->dev->name, | 823 | "since STA not sleeping anymore\n", sdata->dev->name, |
828 | sta->sta.addr, sta->sta.aid); | 824 | sta->sta.addr, sta->sta.aid, sent - buffered, buffered); |
829 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 825 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
830 | skb->requeue = 1; | ||
831 | dev_queue_xmit(skb); | ||
832 | } | ||
833 | 826 | ||
834 | return sent; | 827 | return sent; |
835 | } | 828 | } |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 1436f747531a..bfaa9ce33146 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -400,6 +400,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
400 | sta_info_set_tim_bit(sta); | 400 | sta_info_set_tim_bit(sta); |
401 | 401 | ||
402 | info->control.jiffies = jiffies; | 402 | info->control.jiffies = jiffies; |
403 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | ||
403 | skb_queue_tail(&sta->ps_tx_buf, tx->skb); | 404 | skb_queue_tail(&sta->ps_tx_buf, tx->skb); |
404 | return TX_QUEUED; | 405 | return TX_QUEUED; |
405 | } | 406 | } |
@@ -420,7 +421,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
420 | * frame filtering and keeps a station blacklist on its own | 421 | * frame filtering and keeps a station blacklist on its own |
421 | * (e.g: p54), so that frames can be delivered unimpeded. | 422 | * (e.g: p54), so that frames can be delivered unimpeded. |
422 | * | 423 | * |
423 | * Note: It should be save to disable the filter now. | 424 | * Note: It should be safe to disable the filter now. |
424 | * As, it is really unlikely that we still have any pending | 425 | * As, it is really unlikely that we still have any pending |
425 | * frame for this station in the hw's buffers/fifos left, | 426 | * frame for this station in the hw's buffers/fifos left, |
426 | * that is not rejected with a unsuccessful tx_status yet. | 427 | * that is not rejected with a unsuccessful tx_status yet. |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 22f63815fb36..66ce96a69f31 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -341,6 +341,52 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) | |||
341 | } | 341 | } |
342 | EXPORT_SYMBOL(ieee80211_stop_queue); | 342 | EXPORT_SYMBOL(ieee80211_stop_queue); |
343 | 343 | ||
344 | void ieee80211_add_pending_skb(struct ieee80211_local *local, | ||
345 | struct sk_buff *skb) | ||
346 | { | ||
347 | struct ieee80211_hw *hw = &local->hw; | ||
348 | unsigned long flags; | ||
349 | int queue = skb_get_queue_mapping(skb); | ||
350 | |||
351 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
352 | __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | ||
353 | __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_PENDING); | ||
354 | skb_queue_tail(&local->pending[queue], skb); | ||
355 | __ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | ||
356 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
357 | } | ||
358 | |||
359 | int ieee80211_add_pending_skbs(struct ieee80211_local *local, | ||
360 | struct sk_buff_head *skbs) | ||
361 | { | ||
362 | struct ieee80211_hw *hw = &local->hw; | ||
363 | struct sk_buff *skb; | ||
364 | unsigned long flags; | ||
365 | int queue, ret = 0, i; | ||
366 | |||
367 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
368 | for (i = 0; i < hw->queues; i++) | ||
369 | __ieee80211_stop_queue(hw, i, | ||
370 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | ||
371 | |||
372 | while ((skb = skb_dequeue(skbs))) { | ||
373 | ret++; | ||
374 | queue = skb_get_queue_mapping(skb); | ||
375 | skb_queue_tail(&local->pending[queue], skb); | ||
376 | } | ||
377 | |||
378 | for (i = 0; i < hw->queues; i++) { | ||
379 | if (ret) | ||
380 | __ieee80211_stop_queue(hw, i, | ||
381 | IEEE80211_QUEUE_STOP_REASON_PENDING); | ||
382 | __ieee80211_wake_queue(hw, i, | ||
383 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | ||
384 | } | ||
385 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
386 | |||
387 | return ret; | ||
388 | } | ||
389 | |||
344 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | 390 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, |
345 | enum queue_stop_reason reason) | 391 | enum queue_stop_reason reason) |
346 | { | 392 | { |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 694343b9102b..116a923b14d6 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -101,7 +101,7 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) | |||
101 | * Now we know the 1d priority, fill in the QoS header if | 101 | * Now we know the 1d priority, fill in the QoS header if |
102 | * there is one (and we haven't done this before). | 102 | * there is one (and we haven't done this before). |
103 | */ | 103 | */ |
104 | if (!skb->requeue && ieee80211_is_data_qos(hdr->frame_control)) { | 104 | if (ieee80211_is_data_qos(hdr->frame_control)) { |
105 | u8 *p = ieee80211_get_qos_ctl(hdr); | 105 | u8 *p = ieee80211_get_qos_ctl(hdr); |
106 | u8 ack_policy = 0; | 106 | u8 ack_policy = 0; |
107 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; | 107 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; |