Commit 8f77f3849cc3ae2d6df9301785a3d316ea7d7ee1

Authored by Johannes Berg
Committed by John W. Linville
1 parent fc240e3fc5

mac80211: do not pass PS frames out of mac80211 again

In order to handle powersave frames properly we had needed
to pass these out to the device queues again, and introduce
the skb->requeue bit. This, however, also has unnecessary
overhead by needing to 'clean up' already tried frames, and
this clean-up code is also buggy when software encryption
is used.

Instead of sending the frames via the master netdev queue
again, simply put them into the pending queue. This also
fixes a problem where frames for that particular station
could be reordered when some were still on the software
queues and older ones are re-injected into the software
queue after them.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

Showing 9 changed files with 72 additions and 78 deletions Side-by-side Diff

include/linux/skbuff.h
... ... @@ -304,9 +304,6 @@
304 304 * @tc_verd: traffic control verdict
305 305 * @ndisc_nodetype: router type (from link layer)
306 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 307 * @dma_cookie: a cookie to one of several possible DMA operations
311 308 * done by skb DMA functions
312 309 * @secmark: security marking
... ... @@ -380,7 +377,6 @@
380 377 #endif
381 378 #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
382 379 __u8 do_not_encrypt:1;
383   - __u8 requeue:1;
384 380 #endif
385 381 /* 0/13/14 bit hole */
386 382  
include/net/mac80211.h
... ... @@ -239,6 +239,8 @@
239 239 * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211,
240 240 * used to indicate that a pending frame requires TX processing before
241 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 245 enum mac80211_tx_control_flags {
244 246 IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
... ... @@ -256,6 +258,7 @@
256 258 IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12),
257 259 IEEE80211_TX_INTFL_RCALGO = BIT(13),
258 260 IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14),
  261 + IEEE80211_TX_INTFL_RETRIED = BIT(15),
259 262 };
260 263  
261 264 /**
... ... @@ -552,7 +552,6 @@
552 552 new->vlan_tci = old->vlan_tci;
553 553 #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
554 554 new->do_not_encrypt = old->do_not_encrypt;
555   - new->requeue = old->requeue;
556 555 #endif
557 556  
558 557 skb_copy_secmark(new, old);
net/mac80211/ieee80211_i.h
... ... @@ -589,6 +589,7 @@
589 589 IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
590 590 IEEE80211_QUEUE_STOP_REASON_SUSPEND,
591 591 IEEE80211_QUEUE_STOP_REASON_PENDING,
  592 + IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
592 593 };
593 594  
594 595 struct ieee80211_master_priv {
... ... @@ -1121,6 +1122,10 @@
1121 1122 enum queue_stop_reason reason);
1122 1123 void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
1123 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 1130 void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
1126 1131 u16 transaction, u16 auth_alg,
... ... @@ -369,60 +369,12 @@
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 372 static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
423 373 struct sta_info *sta,
424 374 struct sk_buff *skb)
425 375 {
  376 + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  377 +
426 378 sta->tx_filtered_count++;
427 379  
428 380 /*
429 381  
430 382  
... ... @@ -464,16 +416,15 @@
464 416 */
465 417 if (test_sta_flags(sta, WLAN_STA_PS) &&
466 418 skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {
467   - ieee80211_remove_tx_extra(local, sta->key, skb);
468 419 skb_queue_tail(&sta->tx_filtered, skb);
469 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 425 /* Software retry the packet once */
474   - skb->requeue = 1;
475   - ieee80211_remove_tx_extra(local, sta->key, skb);
476   - dev_queue_xmit(skb);
  426 + info->flags |= IEEE80211_TX_INTFL_RETRIED;
  427 + ieee80211_add_pending_skb(local, skb);
477 428 return;
478 429 }
479 430  
... ... @@ -797,8 +797,7 @@
797 797 {
798 798 struct ieee80211_sub_if_data *sdata = sta->sdata;
799 799 struct ieee80211_local *local = sdata->local;
800   - struct sk_buff *skb;
801   - int sent = 0;
  800 + int sent, buffered;
802 801  
803 802 atomic_dec(&sdata->bss->num_sta_ps);
804 803  
805 804  
806 805  
... ... @@ -814,22 +813,16 @@
814 813 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
815 814  
816 815 /* Send all buffered frames to the station */
817   - while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
818   - sent++;
819   - skb->requeue = 1;
820   - dev_queue_xmit(skb);
821   - }
822   - while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
823   - local->total_ps_buffered--;
824   - sent++;
  816 + sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered);
  817 + buffered = ieee80211_add_pending_skbs(local, &sta->ps_tx_buf);
  818 + sent += buffered;
  819 + local->total_ps_buffered -= buffered;
  820 +
825 821 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
826   - printk(KERN_DEBUG "%s: STA %pM aid %d send PS frame "
827   - "since STA not sleeping anymore\n", sdata->dev->name,
828   - sta->sta.addr, sta->sta.aid);
  822 + printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames "
  823 + "since STA not sleeping anymore\n", sdata->dev->name,
  824 + sta->sta.addr, sta->sta.aid, sent - buffered, buffered);
829 825 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
830   - skb->requeue = 1;
831   - dev_queue_xmit(skb);
832   - }
833 826  
834 827 return sent;
835 828 }
... ... @@ -400,6 +400,7 @@
400 400 sta_info_set_tim_bit(sta);
401 401  
402 402 info->control.jiffies = jiffies;
  403 + info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
403 404 skb_queue_tail(&sta->ps_tx_buf, tx->skb);
404 405 return TX_QUEUED;
405 406 }
... ... @@ -420,7 +421,7 @@
420 421 * frame filtering and keeps a station blacklist on its own
421 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 425 * As, it is really unlikely that we still have any pending
425 426 * frame for this station in the hw's buffers/fifos left,
426 427 * that is not rejected with a unsuccessful tx_status yet.
... ... @@ -341,6 +341,52 @@
341 341 }
342 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 390 void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
345 391 enum queue_stop_reason reason)
346 392 {
... ... @@ -101,7 +101,7 @@
101 101 * Now we know the 1d priority, fill in the QoS header if
102 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 105 u8 *p = ieee80211_get_qos_ctl(hdr);
106 106 u8 ack_policy = 0;
107 107 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;