aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cassini.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2008-01-03 21:49:00 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-04 03:47:04 -0500
commite5e025401f6e926c1d9dc3f3f2813cf98a2d8708 (patch)
tree0d682965be7d1582c49570f4199b5d4a9b8a1891 /drivers/net/cassini.c
parent2d60abc2a937bf77575c3b8c83faeeb84a84e654 (diff)
[CASSINI]: Fix endianness bug.
Here's proposed fix for RX checksum handling in cassini; it affects little-endian working with half-duplex gigabit, but obviously needs testing on big-endian too. The problem is, we need to convert checksum to fixed-endian *before* correcting for (unstripped) FCS. On big-endian it won't matter (conversion is no-op), on little-endian it will, but only if FCS is not stripped by hardware; i.e. in half-duplex gigabit mode when ->crc_size is set. cassini.c part is that fix, cassini.h one consists of trivial endianness annotations. With that applied the sucker is endian-clean, according to sparse. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/cassini.c')
-rw-r--r--drivers/net/cassini.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 7df31b5561cc..9030ca54a5bd 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -1979,6 +1979,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
1979 struct cas_page *page; 1979 struct cas_page *page;
1980 struct sk_buff *skb; 1980 struct sk_buff *skb;
1981 void *addr, *crcaddr; 1981 void *addr, *crcaddr;
1982 __sum16 csum;
1982 char *p; 1983 char *p;
1983 1984
1984 hlen = CAS_VAL(RX_COMP2_HDR_SIZE, words[1]); 1985 hlen = CAS_VAL(RX_COMP2_HDR_SIZE, words[1]);
@@ -2158,14 +2159,15 @@ end_copy_pkt:
2158 skb_put(skb, alloclen); 2159 skb_put(skb, alloclen);
2159 } 2160 }
2160 2161
2161 i = CAS_VAL(RX_COMP4_TCP_CSUM, words[3]); 2162 csum = (__force __sum16)htons(CAS_VAL(RX_COMP4_TCP_CSUM, words[3]));
2162 if (cp->crc_size) { 2163 if (cp->crc_size) {
2163 /* checksum includes FCS. strip it out. */ 2164 /* checksum includes FCS. strip it out. */
2164 i = csum_fold(csum_partial(crcaddr, cp->crc_size, i)); 2165 csum = csum_fold(csum_partial(crcaddr, cp->crc_size,
2166 csum_unfold(csum)));
2165 if (addr) 2167 if (addr)
2166 cas_page_unmap(addr); 2168 cas_page_unmap(addr);
2167 } 2169 }
2168 skb->csum = ntohs(i ^ 0xffff); 2170 skb->csum = csum_unfold(~csum);
2169 skb->ip_summed = CHECKSUM_COMPLETE; 2171 skb->ip_summed = CHECKSUM_COMPLETE;
2170 skb->protocol = eth_type_trans(skb, cp->dev); 2172 skb->protocol = eth_type_trans(skb, cp->dev);
2171 return len; 2173 return len;