diff options
author | Michael Buesch <mb@bu3sch.de> | 2007-12-29 11:24:23 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:09:30 -0500 |
commit | 9081728b5f08f8137973c70e172c47ccb0dd33c9 (patch) | |
tree | 0469a1659a20b13ac48ff02b423800e181271c0b /drivers/net | |
parent | 01c20986cb2c2aa9c66603e9be14be5ebae99aca (diff) |
zd1211rw: fix alignment for QOS and WDS frames
This patch fixes RX packet alignment issues in the zd1211rw driver.
This is based on a patch by Johannes Berg.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_mac.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 14fb727583d5..7b8693050480 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -623,6 +623,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
623 | const struct rx_status *status; | 623 | const struct rx_status *status; |
624 | struct sk_buff *skb; | 624 | struct sk_buff *skb; |
625 | int bad_frame = 0; | 625 | int bad_frame = 0; |
626 | u16 fc; | ||
627 | bool is_qos, is_4addr, need_padding; | ||
626 | 628 | ||
627 | if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ + | 629 | if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ + |
628 | FCS_LEN + sizeof(struct rx_status)) | 630 | FCS_LEN + sizeof(struct rx_status)) |
@@ -674,9 +676,22 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
674 | && !mac->pass_ctrl) | 676 | && !mac->pass_ctrl) |
675 | return 0; | 677 | return 0; |
676 | 678 | ||
677 | skb = dev_alloc_skb(length); | 679 | fc = le16_to_cpu(*((__le16 *) buffer)); |
680 | |||
681 | is_qos = ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && | ||
682 | ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_QOS_DATA); | ||
683 | is_4addr = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == | ||
684 | (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS); | ||
685 | need_padding = is_qos ^ is_4addr; | ||
686 | |||
687 | skb = dev_alloc_skb(length + (need_padding ? 2 : 0)); | ||
678 | if (skb == NULL) | 688 | if (skb == NULL) |
679 | return -ENOMEM; | 689 | return -ENOMEM; |
690 | if (need_padding) { | ||
691 | /* Make sure the the payload data is 4 byte aligned. */ | ||
692 | skb_reserve(skb, 2); | ||
693 | } | ||
694 | |||
680 | memcpy(skb_put(skb, length), buffer, length); | 695 | memcpy(skb_put(skb, length), buffer, length); |
681 | 696 | ||
682 | ieee80211_rx_irqsafe(hw, skb, &stats); | 697 | ieee80211_rx_irqsafe(hw, skb, &stats); |