diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2008-01-03 21:49:00 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-04 03:47:04 -0500 |
commit | e5e025401f6e926c1d9dc3f3f2813cf98a2d8708 (patch) | |
tree | 0d682965be7d1582c49570f4199b5d4a9b8a1891 /drivers/net | |
parent | 2d60abc2a937bf77575c3b8c83faeeb84a84e654 (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')
-rw-r--r-- | drivers/net/cassini.c | 8 | ||||
-rw-r--r-- | drivers/net/cassini.h | 18 |
2 files changed, 14 insertions, 12 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; |
diff --git a/drivers/net/cassini.h b/drivers/net/cassini.h index 2f93f83342d2..552af89ca1cf 100644 --- a/drivers/net/cassini.h +++ b/drivers/net/cassini.h | |||
@@ -4122,8 +4122,8 @@ cas_saturn_patch_t cas_saturn_patch[] = { | |||
4122 | inserted into | 4122 | inserted into |
4123 | outgoing frame. */ | 4123 | outgoing frame. */ |
4124 | struct cas_tx_desc { | 4124 | struct cas_tx_desc { |
4125 | u64 control; | 4125 | __le64 control; |
4126 | u64 buffer; | 4126 | __le64 buffer; |
4127 | }; | 4127 | }; |
4128 | 4128 | ||
4129 | /* descriptor ring for free buffers contains page-sized buffers. the index | 4129 | /* descriptor ring for free buffers contains page-sized buffers. the index |
@@ -4131,8 +4131,8 @@ struct cas_tx_desc { | |||
4131 | * the completion ring. | 4131 | * the completion ring. |
4132 | */ | 4132 | */ |
4133 | struct cas_rx_desc { | 4133 | struct cas_rx_desc { |
4134 | u64 index; | 4134 | __le64 index; |
4135 | u64 buffer; | 4135 | __le64 buffer; |
4136 | }; | 4136 | }; |
4137 | 4137 | ||
4138 | /* received packets are put on the completion ring. */ | 4138 | /* received packets are put on the completion ring. */ |
@@ -4210,10 +4210,10 @@ struct cas_rx_desc { | |||
4210 | #define RX_INDEX_RELEASE 0x0000000000002000ULL | 4210 | #define RX_INDEX_RELEASE 0x0000000000002000ULL |
4211 | 4211 | ||
4212 | struct cas_rx_comp { | 4212 | struct cas_rx_comp { |
4213 | u64 word1; | 4213 | __le64 word1; |
4214 | u64 word2; | 4214 | __le64 word2; |
4215 | u64 word3; | 4215 | __le64 word3; |
4216 | u64 word4; | 4216 | __le64 word4; |
4217 | }; | 4217 | }; |
4218 | 4218 | ||
4219 | enum link_state { | 4219 | enum link_state { |
@@ -4252,7 +4252,7 @@ struct cas_init_block { | |||
4252 | struct cas_rx_comp rxcs[N_RX_COMP_RINGS][INIT_BLOCK_RX_COMP]; | 4252 | struct cas_rx_comp rxcs[N_RX_COMP_RINGS][INIT_BLOCK_RX_COMP]; |
4253 | struct cas_rx_desc rxds[N_RX_DESC_RINGS][INIT_BLOCK_RX_DESC]; | 4253 | struct cas_rx_desc rxds[N_RX_DESC_RINGS][INIT_BLOCK_RX_DESC]; |
4254 | struct cas_tx_desc txds[N_TX_RINGS][INIT_BLOCK_TX]; | 4254 | struct cas_tx_desc txds[N_TX_RINGS][INIT_BLOCK_TX]; |
4255 | u64 tx_compwb; | 4255 | __le64 tx_compwb; |
4256 | }; | 4256 | }; |
4257 | 4257 | ||
4258 | /* tiny buffers to deal with target abort issue. we allocate a bit | 4258 | /* tiny buffers to deal with target abort issue. we allocate a bit |