mac8390: Fix mmio access size probe [Linux 3.16.72]

This Linux kernel change "mac8390: Fix mmio access size probe" is included in the Linux 3.16.72 release. This change is authored by Finn Thain <fthain [at] telegraphics.com.au> on Sat Mar 16 14:21:19 2019 +1100. The commit for this change in Linux stable tree is 7e83430 (patch) which is from upstream commit bb9e5c5. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream bb9e5c5.

mac8390: Fix mmio access size probe

commit bb9e5c5bcd76f4474eac3baf643d7a39f7bac7bb upstream.

The bug that Stan reported is as follows. After a restart, a 16-bit NIC
may be incorrectly identified as a 32-bit NIC and stop working.

mac8390 slot.E: Memory length resource not found, probing
mac8390 slot.E: Farallon EtherMac II-C (type farallon)
mac8390 slot.E: MAC 00:00:c5:30:c2:99, IRQ 61, 32 KB shared memory at 0xfeed0000, 32-bit access.

The bug never arises after a cold start and only intermittently after a
warm start. (I didn't investigate why the bug is intermittent.)

It turns out that memcpy_toio() is deprecated and memcmp_withio() also
has issues. Replacing these calls with mmio accessors fixes the problem.

Reported-and-tested-by: Stan Johnson <[email protected]>
Fixes: 2964db0f5904 ("m68k: Mac DP8390 update")
Signed-off-by: Finn Thain <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>

There are 19 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/net/ethernet/8390/mac8390.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c
index da46650..02beb18 100644
--- a/drivers/net/ethernet/8390/mac8390.c
+++ b/drivers/net/ethernet/8390/mac8390.c
@@ -153,8 +153,6 @@ static void dayna_block_input(struct net_device *dev, int count,
 static void dayna_block_output(struct net_device *dev, int count,
                   const unsigned char *buf, int start_page);

-#define memcmp_withio(a, b, c) memcmp((a), (void *)(b), (c))
-
 /* Slow Sane (16-bit chunk memory read/write) Cabletron uses this */
 static void slow_sane_get_8390_hdr(struct net_device *dev,
                   struct e8390_pkt_hdr *hdr, int ring_page);
@@ -241,19 +239,26 @@ static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev)

 static enum mac8390_access __init mac8390_testio(volatile unsigned long membase)
 {
-   unsigned long outdata = 0xA5A0B5B0;
-   unsigned long indata =  0x00000000;
+   u32 outdata = 0xA5A0B5B0;
+   u32 indata = 0;
+
    /* Try writing 32 bits */
-   memcpy_toio((void __iomem *)membase, &outdata, 4);
-   /* Now compare them */
-   if (memcmp_withio(&outdata, membase, 4) == 0)
+   nubus_writel(outdata, membase);
+   /* Now read it back */
+   indata = nubus_readl(membase);
+   if (outdata == indata)
        return ACCESS_32;
+
+   outdata = 0xC5C0D5D0;
+   indata = 0;
+
    /* Write 16 bit output */
    word_memcpy_tocard(membase, &outdata, 4);
    /* Now read it back */
    word_memcpy_fromcard(&indata, membase, 4);
    if (outdata == indata)
        return ACCESS_16;
+
    return ACCESS_UNKNOWN;
 }

Leave a Reply

Your email address will not be published. Required fields are marked *