lkml.org 
[lkml]   [2008]   [Feb]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 28/73] CASSINI: Fix endianness bug.
    2.6.23-stable review patch.  If anyone has any objections, please let us know.
    ------------------
    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
    --


    \
     
     \ /
      Last update: 2008-02-07 01:11    [W:0.048 / U:30.436 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site