From 49bfc8e1cb3e721d54045729e1367d58ae30ca7b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 12 May 2012 10:03:30 +0000 Subject: [PATCH] sky2: fix receive length error in mixed non-VLAN/VLAN traffic (Closes: #492853) svn path=/dists/sid/linux-2.6/; revision=18992 --- debian/changelog | 2 + ...-length-error-in-mixed-non-vlan-vlan.patch | 137 ++++++++++++++++++ debian/patches/series/base | 1 + 3 files changed, 140 insertions(+) create mode 100644 debian/patches/bugfix/all/sky2-fix-receive-length-error-in-mixed-non-vlan-vlan.patch diff --git a/debian/changelog b/debian/changelog index c9ffe6155..b9f5588cd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,6 +8,8 @@ linux-2.6 (3.2.17-1) UNRELEASED; urgency=low * ext4: Report max_batch_time option correctly (Closes: #654206) * [i386/rt-686-pae] Enable HIGHMEM64G as intended for this configuration * NFSv4: Revalidate uid/gid after open (Closes: #659111) + * sky2: fix receive length error in mixed non-VLAN/VLAN traffic + (Closes: #492853) [ Bastian Blank ] * [s390] Enable IUCV special message support. (closes: #671238) diff --git a/debian/patches/bugfix/all/sky2-fix-receive-length-error-in-mixed-non-vlan-vlan.patch b/debian/patches/bugfix/all/sky2-fix-receive-length-error-in-mixed-non-vlan-vlan.patch new file mode 100644 index 000000000..64b8396ff --- /dev/null +++ b/debian/patches/bugfix/all/sky2-fix-receive-length-error-in-mixed-non-vlan-vlan.patch @@ -0,0 +1,137 @@ +From dc7296f6dc82ac546b5006dcfff1b16967b6c234 Mon Sep 17 00:00:00 2001 +From: stephen hemminger +Date: Mon, 30 Apr 2012 06:47:37 +0000 +Subject: [PATCH 06/10] sky2: fix receive length error in mixed non-VLAN/VLAN + traffic + +[ Upstream commit e072b3fad5f3915102c94628b4971f52ff99dd05 ] + +Bug: The VLAN bit of the MAC RX Status Word is unreliable in several older +supported chips. Sometimes the VLAN bit is not set for valid VLAN packets +and also sometimes the VLAN bit is set for non-VLAN packets that came after +a VLAN packet. This results in a receive length error when VLAN hardware +tagging is enabled. + +Fix: Variation on original fix proposed by Mirko. +The VLAN information is decoded in the status loop, and can be +applied to the received SKB there. This eliminates the need for the +separate tag field in the interface data structure. The tag has to +be copied and cleared if packet is copied. This version checked out +with vlan and normal traffic. + +Note: vlan_tx_tag_present should be renamed vlan_tag_present, but that +is outside scope of this. + +Reported-by: Mirko Lindner +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Signed-off-by: Ben Hutchings +--- + drivers/net/ethernet/marvell/sky2.c | 28 +++++++++++++++++----------- + drivers/net/ethernet/marvell/sky2.h | 1 - + 2 files changed, 17 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c +index e1f4b65..65c51ff 100644 +--- a/drivers/net/ethernet/marvell/sky2.c ++++ b/drivers/net/ethernet/marvell/sky2.c +@@ -2476,9 +2476,11 @@ static struct sk_buff *receive_copy(struct sky2_port *sky2, + skb->ip_summed = re->skb->ip_summed; + skb->csum = re->skb->csum; + skb->rxhash = re->skb->rxhash; ++ skb->vlan_tci = re->skb->vlan_tci; + + pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr, + length, PCI_DMA_FROMDEVICE); ++ re->skb->vlan_tci = 0; + re->skb->rxhash = 0; + re->skb->ip_summed = CHECKSUM_NONE; + skb_put(skb, length); +@@ -2564,9 +2566,6 @@ static struct sk_buff *sky2_receive(struct net_device *dev, + struct sk_buff *skb = NULL; + u16 count = (status & GMR_FS_LEN) >> 16; + +- if (status & GMR_FS_VLAN) +- count -= VLAN_HLEN; /* Account for vlan tag */ +- + netif_printk(sky2, rx_status, KERN_DEBUG, dev, + "rx slot %u status 0x%x len %d\n", + sky2->rx_next, status, length); +@@ -2574,6 +2573,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev, + sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; + prefetch(sky2->rx_ring + sky2->rx_next); + ++ if (vlan_tx_tag_present(re->skb)) ++ count -= VLAN_HLEN; /* Account for vlan tag */ ++ + /* This chip has hardware problems that generates bogus status. + * So do only marginal checking and expect higher level protocols + * to handle crap frames. +@@ -2631,11 +2633,8 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) + } + + static inline void sky2_skb_rx(const struct sky2_port *sky2, +- u32 status, struct sk_buff *skb) ++ struct sk_buff *skb) + { +- if (status & GMR_FS_VLAN) +- __vlan_hwaccel_put_tag(skb, be16_to_cpu(sky2->rx_tag)); +- + if (skb->ip_summed == CHECKSUM_NONE) + netif_receive_skb(skb); + else +@@ -2689,6 +2688,14 @@ static void sky2_rx_checksum(struct sky2_port *sky2, u32 status) + } + } + ++static void sky2_rx_tag(struct sky2_port *sky2, u16 length) ++{ ++ struct sk_buff *skb; ++ ++ skb = sky2->rx_ring[sky2->rx_next].skb; ++ __vlan_hwaccel_put_tag(skb, be16_to_cpu(length)); ++} ++ + static void sky2_rx_hash(struct sky2_port *sky2, u32 status) + { + struct sk_buff *skb; +@@ -2747,8 +2754,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) + } + + skb->protocol = eth_type_trans(skb, dev); +- +- sky2_skb_rx(sky2, status, skb); ++ sky2_skb_rx(sky2, skb); + + /* Stop after net poll weight */ + if (++work_done >= to_do) +@@ -2756,11 +2762,11 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) + break; + + case OP_RXVLAN: +- sky2->rx_tag = length; ++ sky2_rx_tag(sky2, length); + break; + + case OP_RXCHKSVLAN: +- sky2->rx_tag = length; ++ sky2_rx_tag(sky2, length); + /* fall through */ + case OP_RXCHKS: + if (likely(dev->features & NETIF_F_RXCSUM)) +diff --git a/drivers/net/ethernet/marvell/sky2.h b/drivers/net/ethernet/marvell/sky2.h +index ff6f58b..3c896ce 100644 +--- a/drivers/net/ethernet/marvell/sky2.h ++++ b/drivers/net/ethernet/marvell/sky2.h +@@ -2241,7 +2241,6 @@ struct sky2_port { + u16 rx_pending; + u16 rx_data_size; + u16 rx_nfrags; +- u16 rx_tag; + + struct { + unsigned long last; +-- +1.7.10.1 + + diff --git a/debian/patches/series/base b/debian/patches/series/base index 8c4b94920..293c48358 100644 --- a/debian/patches/series/base +++ b/debian/patches/series/base @@ -193,3 +193,4 @@ + bugfix/all/ext4-Report-max_batch_time-option-correctly.patch + bugfix/all/brcm80211-smac-pass-missing-argument-to-brcms_b_mute.patch + bugfix/all/nfsv4-revalidate-uid-gid-after-open.patch ++ bugfix/all/sky2-fix-receive-length-error-in-mixed-non-vlan-vlan.patch