Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2965

kernel-2.6.18-238.el5.src.rpm

From: Andy Gospodarek <gospo@redhat.com>
Date: Mon, 24 Nov 2008 18:55:18 -0500
Subject: [net] niu: fix obscure 64-bit read issue
Message-id: 20081124235517.GC9306@gospo.rdu.redhat.com
O-Subject: [RHEL5.3 PATCH] niu: fix obscure 64-bit read issue
Bugzilla: 472849
RH-Acked-by: David Miller <davem@redhat.com>
RH-Acked-by: Neil Horman <nhorman@redhat.com>
RH-Acked-by: Thomas Graf <tgraf@redhat.com>

While testing the 5.2 kmod, it was discovered that the 32-bit driver
for 5.3 is hitting a rather obscure hardware related issue that has
already been fixed upstream.  This patch is a backport of the following
commit:

commit e23a59e1ca6d177a57a7791b3629db93ff1d9813
Author: David S. Miller <davem@davemloft.net>
Date:   Wed Nov 12 14:32:54 2008 -0800

    niu: Fix readq implementation when architecture does not provide one.

    This fixes a TX hang reported by Jesper Dangaard Brouer.

    When an architecutre cannot provide a fully functional
    64-bit atomic readq/writeq, the driver must implement
    it's own.  This is because only the driver can say whether
    doing something like using two 32-bit reads to implement
    the full 64-bit read will actually work properly.

    In particular one of the issues is whether the top 32-bits
    or the bottom 32-bits of the 64-bit register should be read
    first.  There could be side effects, and in fact that is
    exactly the problem here.

    The TX_CS register has counters in the upper 32-bits and
    state bits in the lower 32-bits.  A read clears the state
    bits.

    We would read the counter half before the state bit half.
    That first read would clear the state bits, and then the
    driver thinks that no interrupts are pending because the
    interrupt indication state bits are seen clear every time.

    Fix this by reading the bottom half before the upper half.

    Tested-by: Jesper Dangaard Brouer <jdb@comx.dk>
    Signed-off-by: David S. Miller <davem@davemloft.net>

This should fix RHBZ 462432.

diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index 257b1e9..ada1e94 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -52,8 +52,7 @@ MODULE_VERSION(DRV_MODULE_VERSION);
 #ifndef readq
 static u64 readq(void __iomem *reg)
 {
-	return (((u64)readl(reg + 0x4UL) << 32) |
-		(u64)readl(reg));
+	return ((u64) readl(reg)) | (((u64) readl(reg + 4UL)) << 32);
 }
 
 static void writeq(u64 val, void __iomem *reg)