--- /dev/null
+From stable-bounces@linux.kernel.org Fri Jan 11 01:38:55 2008
+Date: Fri, 11 Jan 2008 01:38:38 -0800 (PST)
+From: Al Viro <viro@zeniv.linux.org.uk>
+Subject: CASSINI: Fix endianness bug.
+Message-ID: <20080111.013838.267004233.davem@davemloft.net>
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+[ Upstream commit: e5e025401f6e926c1d9dc3f3f2813cf98a2d8708 ]
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/cassini.c | 8 +++++---
+ drivers/net/cassini.h | 18 +++++++++---------
+ 2 files changed, 14 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/cassini.c
++++ b/drivers/net/cassini.c
+@@ -1979,6 +1979,7 @@ static int cas_rx_process_pkt(struct cas
+ 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 @@ end_copy_pkt:
+ 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;
+--- a/drivers/net/cassini.h
++++ b/drivers/net/cassini.h
+@@ -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
--- /dev/null
+From stable-bounces@linux.kernel.org Fri Jan 11 01:38:55 2008
+Date: Fri, 11 Jan 2008 01:38:38 -0800 (PST)
+From: David Miller <davem@davemloft.net>
+Subject: CASSINI: Revert 'dont touch page_count'.
+Message-ID: <20080111.013838.267004233.davem@davemloft.net>
+
+From: David Miller <davem@davemloft.net>
+
+[ Upstream commit: 9de4dfb4c7176e5bb232a21cdd8df78da2b15cac ]
+
+This reverts changeset fa4f0774d7c6cccb4d1fda76b91dd8eddcb2dd6a
+([CASSINI]: dont touch page_count) because it breaks the driver.
+
+The local page counting added by this changeset did not account
+for the asynchronous page count changes done by kfree_skb()
+and friends.
+
+The change adds extra atomics and on top of it all appears to be
+totally unnecessary as well.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Acked-by: Nick Piggin <npiggin@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/cassini.c | 36 ++++--------------------------------
+ 1 file changed, 4 insertions(+), 32 deletions(-)
+
+--- a/drivers/net/cassini.c
++++ b/drivers/net/cassini.c
+@@ -336,30 +336,6 @@ static inline void cas_mask_intr(struct
+ cas_disable_irq(cp, i);
+ }
+
+-static inline void cas_buffer_init(cas_page_t *cp)
+-{
+- struct page *page = cp->buffer;
+- atomic_set((atomic_t *)&page->lru.next, 1);
+-}
+-
+-static inline int cas_buffer_count(cas_page_t *cp)
+-{
+- struct page *page = cp->buffer;
+- return atomic_read((atomic_t *)&page->lru.next);
+-}
+-
+-static inline void cas_buffer_inc(cas_page_t *cp)
+-{
+- struct page *page = cp->buffer;
+- atomic_inc((atomic_t *)&page->lru.next);
+-}
+-
+-static inline void cas_buffer_dec(cas_page_t *cp)
+-{
+- struct page *page = cp->buffer;
+- atomic_dec((atomic_t *)&page->lru.next);
+-}
+-
+ static void cas_enable_irq(struct cas *cp, const int ring)
+ {
+ if (ring == 0) { /* all but TX_DONE */
+@@ -497,7 +473,6 @@ static int cas_page_free(struct cas *cp,
+ {
+ pci_unmap_page(cp->pdev, page->dma_addr, cp->page_size,
+ PCI_DMA_FROMDEVICE);
+- cas_buffer_dec(page);
+ __free_pages(page->buffer, cp->page_order);
+ kfree(page);
+ return 0;
+@@ -527,7 +502,6 @@ static cas_page_t *cas_page_alloc(struct
+ page->buffer = alloc_pages(flags, cp->page_order);
+ if (!page->buffer)
+ goto page_err;
+- cas_buffer_init(page);
+ page->dma_addr = pci_map_page(cp->pdev, page->buffer, 0,
+ cp->page_size, PCI_DMA_FROMDEVICE);
+ return page;
+@@ -606,7 +580,7 @@ static void cas_spare_recover(struct cas
+ list_for_each_safe(elem, tmp, &list) {
+ cas_page_t *page = list_entry(elem, cas_page_t, list);
+
+- if (cas_buffer_count(page) > 1)
++ if (page_count(page->buffer) > 1)
+ continue;
+
+ list_del(elem);
+@@ -1374,7 +1348,7 @@ static inline cas_page_t *cas_page_spare
+ cas_page_t *page = cp->rx_pages[1][index];
+ cas_page_t *new;
+
+- if (cas_buffer_count(page) == 1)
++ if (page_count(page->buffer) == 1)
+ return page;
+
+ new = cas_page_dequeue(cp);
+@@ -1394,7 +1368,7 @@ static cas_page_t *cas_page_swap(struct
+ cas_page_t **page1 = cp->rx_pages[1];
+
+ /* swap if buffer is in use */
+- if (cas_buffer_count(page0[index]) > 1) {
++ if (page_count(page0[index]->buffer) > 1) {
+ cas_page_t *new = cas_page_spare(cp, index);
+ if (new) {
+ page1[index] = page0[index];
+@@ -2066,7 +2040,6 @@ static int cas_rx_process_pkt(struct cas
+ skb->len += hlen - swivel;
+
+ get_page(page->buffer);
+- cas_buffer_inc(page);
+ frag->page = page->buffer;
+ frag->page_offset = off;
+ frag->size = hlen - swivel;
+@@ -2091,7 +2064,6 @@ static int cas_rx_process_pkt(struct cas
+ frag++;
+
+ get_page(page->buffer);
+- cas_buffer_inc(page);
+ frag->page = page->buffer;
+ frag->page_offset = 0;
+ frag->size = hlen;
+@@ -2255,7 +2227,7 @@ static int cas_post_rxds_ringN(struct ca
+ released = 0;
+ while (entry != last) {
+ /* make a new buffer if it's still in use */
+- if (cas_buffer_count(page[entry]) > 1) {
++ if (page_count(page[entry]->buffer) > 1) {
+ cas_page_t *new = cas_page_dequeue(cp);
+ if (!new) {
+ /* let the timer know that we need to
--- /dev/null
+From stable-bounces@linux.kernel.org Fri Jan 11 01:38:55 2008
+Date: Fri, 11 Jan 2008 01:38:38 -0800 (PST)
+From: David Miller <davem@davemloft.net>
+Subject: CASSINI: Set skb->truesize properly on receive packets.
+Message-ID: <20080111.013838.267004233.davem@davemloft.net>
+
+From: David Miller <davem@davemloft.net>
+
+[ Upstream commit: d011a231675b240157a3c335dd53e9b849d7d30d ]
+
+skb->truesize was not being incremented at all to
+reflect the page based data added to RX SKBs.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/cassini.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/cassini.c
++++ b/drivers/net/cassini.c
+@@ -2037,6 +2037,7 @@ static int cas_rx_process_pkt(struct cas
+
+ skb_shinfo(skb)->nr_frags++;
+ skb->data_len += hlen - swivel;
++ skb->truesize += hlen - swivel;
+ skb->len += hlen - swivel;
+
+ get_page(page->buffer);