Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e5e02540 authored by Al Viro's avatar Al Viro Committed by David S. Miller
Browse files

[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: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2d60abc2
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -1979,6 +1979,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
	struct cas_page *page;
	struct sk_buff *skb;
	void *addr, *crcaddr;
	__sum16 csum;
	char *p;

	hlen = CAS_VAL(RX_COMP2_HDR_SIZE, words[1]);
@@ -2158,14 +2159,15 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
		skb_put(skb, alloclen);
	}

	i = CAS_VAL(RX_COMP4_TCP_CSUM, words[3]);
	csum = (__force __sum16)htons(CAS_VAL(RX_COMP4_TCP_CSUM, words[3]));
	if (cp->crc_size) {
		/* checksum includes FCS. strip it out. */
		i = csum_fold(csum_partial(crcaddr, cp->crc_size, i));
		csum = csum_fold(csum_partial(crcaddr, cp->crc_size,
					      csum_unfold(csum)));
		if (addr)
			cas_page_unmap(addr);
	}
	skb->csum = ntohs(i ^ 0xffff);
	skb->csum = csum_unfold(~csum);
	skb->ip_summed = CHECKSUM_COMPLETE;
	skb->protocol = eth_type_trans(skb, cp->dev);
	return len;
+9 −9
Original line number Diff line number Diff line
@@ -4122,8 +4122,8 @@ cas_saturn_patch_t cas_saturn_patch[] = {
							     inserted into
							     outgoing frame. */
struct cas_tx_desc {
	u64     control;
	u64     buffer;
	__le64     control;
	__le64     buffer;
};

/* descriptor ring for free buffers contains page-sized buffers. the index
@@ -4131,8 +4131,8 @@ struct cas_tx_desc {
 * the completion ring.
 */
struct cas_rx_desc {
	u64     index;
	u64     buffer;
	__le64     index;
	__le64     buffer;
};

/* received packets are put on the completion ring. */
@@ -4210,10 +4210,10 @@ struct cas_rx_desc {
#define RX_INDEX_RELEASE                  0x0000000000002000ULL

struct cas_rx_comp {
	u64     word1;
	u64     word2;
	u64     word3;
	u64     word4;
	__le64     word1;
	__le64     word2;
	__le64     word3;
	__le64     word4;
};

enum link_state {
@@ -4252,7 +4252,7 @@ struct cas_init_block {
	struct cas_rx_comp rxcs[N_RX_COMP_RINGS][INIT_BLOCK_RX_COMP];
	struct cas_rx_desc rxds[N_RX_DESC_RINGS][INIT_BLOCK_RX_DESC];
	struct cas_tx_desc txds[N_TX_RINGS][INIT_BLOCK_TX];
	u64 tx_compwb;
	__le64 tx_compwb;
};

/* tiny buffers to deal with target abort issue. we allocate a bit