diff options
author | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2013-03-17 05:59:29 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-03-25 16:42:22 -0400 |
commit | 657e27656dfb3a99e81c99df6e78e770d7fe0d48 (patch) | |
tree | b1ed261b1d47ba78bf96fab5ccc3bfc51c331a4b /drivers | |
parent | 29bb7013a53d8fc43f79f39d22a15ba8d3e77d9b (diff) |
rtlwifi: usb: add NET_IP_ALIGN padding to RX skb when needed
Add proper alignment at first packet copy, to avoid extra copies made later
in networking stack.
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/rtlwifi/usb.c | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index a7b54f631293..72c2614213c4 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
@@ -569,6 +569,37 @@ static void _rtl_rx_work(unsigned long param) | |||
569 | } | 569 | } |
570 | } | 570 | } |
571 | 571 | ||
572 | static unsigned int _rtl_rx_get_padding(struct ieee80211_hdr *hdr, | ||
573 | unsigned int len) | ||
574 | { | ||
575 | unsigned int padding = 0; | ||
576 | |||
577 | /* make function no-op when possible */ | ||
578 | if (NET_IP_ALIGN == 0 || len < sizeof(*hdr)) | ||
579 | return 0; | ||
580 | |||
581 | /* alignment calculation as in lbtf_rx() / carl9170_rx_copy_data() */ | ||
582 | /* TODO: deduplicate common code, define helper function instead? */ | ||
583 | |||
584 | if (ieee80211_is_data_qos(hdr->frame_control)) { | ||
585 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
586 | |||
587 | padding ^= NET_IP_ALIGN; | ||
588 | |||
589 | /* Input might be invalid, avoid accessing memory outside | ||
590 | * the buffer. | ||
591 | */ | ||
592 | if ((unsigned long)qc - (unsigned long)hdr < len && | ||
593 | *qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT) | ||
594 | padding ^= NET_IP_ALIGN; | ||
595 | } | ||
596 | |||
597 | if (ieee80211_has_a4(hdr->frame_control)) | ||
598 | padding ^= NET_IP_ALIGN; | ||
599 | |||
600 | return padding; | ||
601 | } | ||
602 | |||
572 | #define __RADIO_TAP_SIZE_RSV 32 | 603 | #define __RADIO_TAP_SIZE_RSV 32 |
573 | 604 | ||
574 | static void _rtl_rx_completed(struct urb *_urb) | 605 | static void _rtl_rx_completed(struct urb *_urb) |
@@ -582,9 +613,11 @@ static void _rtl_rx_completed(struct urb *_urb) | |||
582 | goto free; | 613 | goto free; |
583 | 614 | ||
584 | if (likely(0 == _urb->status)) { | 615 | if (likely(0 == _urb->status)) { |
616 | unsigned int padding; | ||
585 | struct sk_buff *skb; | 617 | struct sk_buff *skb; |
586 | unsigned int qlen; | 618 | unsigned int qlen; |
587 | unsigned int size = _urb->actual_length; | 619 | unsigned int size = _urb->actual_length; |
620 | struct ieee80211_hdr *hdr; | ||
588 | 621 | ||
589 | if (size < RTL_RX_DESC_SIZE + sizeof(struct ieee80211_hdr)) { | 622 | if (size < RTL_RX_DESC_SIZE + sizeof(struct ieee80211_hdr)) { |
590 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, | 623 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, |
@@ -601,7 +634,10 @@ static void _rtl_rx_completed(struct urb *_urb) | |||
601 | goto resubmit; | 634 | goto resubmit; |
602 | } | 635 | } |
603 | 636 | ||
604 | skb = dev_alloc_skb(size + __RADIO_TAP_SIZE_RSV); | 637 | hdr = (void *)(_urb->transfer_buffer + RTL_RX_DESC_SIZE); |
638 | padding = _rtl_rx_get_padding(hdr, size - RTL_RX_DESC_SIZE); | ||
639 | |||
640 | skb = dev_alloc_skb(size + __RADIO_TAP_SIZE_RSV + padding); | ||
605 | if (!skb) { | 641 | if (!skb) { |
606 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, | 642 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, |
607 | "Can't allocate skb for bulk IN!\n"); | 643 | "Can't allocate skb for bulk IN!\n"); |
@@ -610,6 +646,9 @@ static void _rtl_rx_completed(struct urb *_urb) | |||
610 | 646 | ||
611 | _rtl_install_trx_info(rtlusb, skb, rtlusb->in_ep); | 647 | _rtl_install_trx_info(rtlusb, skb, rtlusb->in_ep); |
612 | 648 | ||
649 | /* Make sure the payload data is 4 byte aligned. */ | ||
650 | skb_reserve(skb, padding); | ||
651 | |||
613 | /* reserve some space for mac80211's radiotap */ | 652 | /* reserve some space for mac80211's radiotap */ |
614 | skb_reserve(skb, __RADIO_TAP_SIZE_RSV); | 653 | skb_reserve(skb, __RADIO_TAP_SIZE_RSV); |
615 | 654 | ||