Module Name:    src
Committed By:   msaitoh
Date:           Thu Mar  7 08:46:55 UTC 2013

Modified Files:
        src/sys/dev/pci: if_bge.c if_bgevar.h

Log Message:
Insert the completion barrier between register write and the
consecutive delay(). It will fix some device timeout problems
we have seen before.


To generate a diff of this commit:
cvs rdiff -u -r1.210 -r1.211 src/sys/dev/pci/if_bge.c
cvs rdiff -u -r1.10 -r1.11 src/sys/dev/pci/if_bgevar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/if_bge.c
diff -u src/sys/dev/pci/if_bge.c:1.210 src/sys/dev/pci/if_bge.c:1.211
--- src/sys/dev/pci/if_bge.c:1.210	Thu Mar  7 04:42:09 2013
+++ src/sys/dev/pci/if_bge.c	Thu Mar  7 08:46:54 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_bge.c,v 1.210 2013/03/07 04:42:09 msaitoh Exp $	*/
+/*	$NetBSD: if_bge.c,v 1.211 2013/03/07 08:46:54 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 2001 Wind River Systems
@@ -79,7 +79,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.210 2013/03/07 04:42:09 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.211 2013/03/07 08:46:54 msaitoh Exp $");
 
 #include "vlan.h"
 
@@ -243,6 +243,7 @@ static int bge_setpowerstate(struct bge_
 static uint32_t bge_readmem_ind(struct bge_softc *, int);
 static void bge_writemem_ind(struct bge_softc *, int, int);
 static void bge_writembx(struct bge_softc *, int, int);
+static void bge_writembx_flush(struct bge_softc *, int, int);
 static void bge_writemem_direct(struct bge_softc *, int, int);
 static void bge_writereg_ind(struct bge_softc *, int, int);
 static void bge_set_max_readrq(struct bge_softc *);
@@ -825,6 +826,15 @@ bge_writembx(struct bge_softc *sc, int o
 	CSR_WRITE_4(sc, off, val);
 }
 
+static void
+bge_writembx_flush(struct bge_softc *sc, int off, int val)
+{
+	if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906)
+		off += BGE_LPMBX_IRQ0_HI - BGE_MBX_IRQ0_HI;
+
+	CSR_WRITE_4_FLUSH(sc, off, val);
+}
+
 static uint8_t
 bge_nvram_getbyte(struct bge_softc *sc, int addr, uint8_t *dest)
 {
@@ -869,8 +879,7 @@ bge_nvram_getbyte(struct bge_softc *sc, 
 	CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access);
 
 	/* Unlock. */
-	CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_CLR1);
-	CSR_READ_4(sc, BGE_NVRAM_SWARB);
+	CSR_WRITE_4_FLUSH(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_CLR1);
 
 	return 0;
 }
@@ -987,11 +996,11 @@ bge_miibus_readreg(device_t dev, int phy
 	autopoll = CSR_READ_4(sc, BGE_MI_MODE);
 	if (autopoll & BGE_MIMODE_AUTOPOLL) {
 		BGE_STS_CLRBIT(sc, BGE_STS_AUTOPOLL);
-		BGE_CLRBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL);
+		BGE_CLRBIT_FLUSH(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL);
 		DELAY(40);
 	}
 
-	CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_READ | BGE_MICOMM_BUSY |
+	CSR_WRITE_4_FLUSH(sc, BGE_MI_COMM, BGE_MICMD_READ | BGE_MICOMM_BUSY |
 	    BGE_MIPHY(phy) | BGE_MIREG(reg));
 
 	for (i = 0; i < BGE_TIMEOUT; i++) {
@@ -1012,7 +1021,7 @@ bge_miibus_readreg(device_t dev, int phy
 done:
 	if (autopoll & BGE_MIMODE_AUTOPOLL) {
 		BGE_STS_SETBIT(sc, BGE_STS_AUTOPOLL);
-		BGE_SETBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL);
+		BGE_SETBIT_FLUSH(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL);
 		DELAY(40);
 	}
 
@@ -1042,11 +1051,11 @@ bge_miibus_writereg(device_t dev, int ph
 	if (autopoll & BGE_MIMODE_AUTOPOLL) {
 		delay(40);
 		BGE_STS_CLRBIT(sc, BGE_STS_AUTOPOLL);
-		BGE_CLRBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL);
+		BGE_CLRBIT_FLUSH(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL);
 		delay(10); /* 40 usec is supposed to be adequate */
 	}
 
-	CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_WRITE | BGE_MICOMM_BUSY |
+	CSR_WRITE_4_FLUSH(sc, BGE_MI_COMM, BGE_MICMD_WRITE | BGE_MICOMM_BUSY |
 	    BGE_MIPHY(phy) | BGE_MIREG(reg) | val);
 
 	for (i = 0; i < BGE_TIMEOUT; i++) {
@@ -1060,7 +1069,7 @@ bge_miibus_writereg(device_t dev, int ph
 
 	if (autopoll & BGE_MIMODE_AUTOPOLL) {
 		BGE_STS_SETBIT(sc, BGE_STS_AUTOPOLL);
-		BGE_SETBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL);
+		BGE_SETBIT_FLUSH(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL);
 		delay(40);
 	}
 
@@ -1091,9 +1100,10 @@ bge_miibus_statchg(struct ifnet *ifp)
 		BGE_SETBIT(sc, BGE_MAC_MODE, BGE_PORTMODE_MII);
 
 	if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX)
-		BGE_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX);
+		BGE_CLRBIT_FLUSH(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX);
 	else
-		BGE_SETBIT(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX);
+		BGE_SETBIT_FLUSH(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX);
+	DELAY(40);
 
 	/*
 	 * 802.3x flow control
@@ -1731,7 +1741,7 @@ bge_stop_fw(struct bge_softc *sc)
 
 	if (sc->bge_asf_mode) {
 		bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM_FW, BGE_FW_PAUSE);
-		CSR_WRITE_4(sc, BGE_CPU_EVENT,
+		CSR_WRITE_4_FLUSH(sc, BGE_CPU_EVENT,
 		    CSR_READ_4(sc, BGE_CPU_EVENT) | (1 << 14));
 
 		for (i = 0; i < 100; i++) {
@@ -1932,8 +1942,7 @@ bge_chipinit(struct bge_softc *sc)
 		DELAY(40);	/* XXX */
 
 		/* Put PHY into ready state */
-		BGE_CLRBIT(sc, BGE_MISC_CFG, BGE_MISCCFG_EPHY_IDDQ);
-		CSR_READ_4(sc, BGE_MISC_CFG); /* Flush */
+		BGE_CLRBIT_FLUSH(sc, BGE_MISC_CFG, BGE_MISCCFG_EPHY_IDDQ);
 		DELAY(40);
 	}
 
@@ -2297,7 +2306,8 @@ bge_blockinit(struct bge_softc *sc)
 		val |= BGE_PORTMODE_MII;
 
 	/* Turn on DMA, clear stats */
-	CSR_WRITE_4(sc, BGE_MAC_MODE, val);
+	CSR_WRITE_4_FLUSH(sc, BGE_MAC_MODE, val);
+	DELAY(40);
 
 	/* Set misc. local control, enable interrupts on attentions */
 	sc->bge_local_ctrl_reg = BGE_MLC_INTR_ONATTN | BGE_MLC_AUTO_EEPROM;
@@ -2349,7 +2359,7 @@ bge_blockinit(struct bge_softc *sc)
 		val |= BGE_RDMAMODE_TSO4_ENABLE;
 
 	/* Turn on read DMA state machine */
-	CSR_WRITE_4(sc, BGE_RDMA_MODE, val);
+	CSR_WRITE_4_FLUSH(sc, BGE_RDMA_MODE, val);
 	delay(40);
 
 	/* Turn on RX data completion state machine */
@@ -3280,7 +3290,8 @@ bge_reset(struct bge_softc *sc)
 	 * Step 18: wirte mac mode
 	 * XXX Write 0x0c for 5703S and 5704S
 	 */
-	CSR_WRITE_4(sc, BGE_MAC_MODE, 0);
+	CSR_WRITE_4_FLUSH(sc, BGE_MAC_MODE, 0);
+	DELAY(40);
 
 
 	/* Step 21: 5822 B0 errata */
@@ -3626,7 +3637,7 @@ bge_intr(void *xsc)
 	    (!(pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_PCISTATE) &
 		BGE_PCISTATE_INTR_NOT_ACTIVE))) {
 		/* Ack interrupt and stop others from occuring. */
-		bge_writembx(sc, BGE_MBX_IRQ0_LO, 1);
+		bge_writembx_flush(sc, BGE_MBX_IRQ0_LO, 1);
 
 		BGE_EVCNT_INCR(sc->bge_ev_intr);
 
@@ -3664,7 +3675,7 @@ bge_intr(void *xsc)
 		bge_handle_events(sc);
 
 		/* Re-enable interrupts. */
-		bge_writembx(sc, BGE_MBX_IRQ0_LO, 0);
+		bge_writembx_flush(sc, BGE_MBX_IRQ0_LO, 0);
 
 		if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd))
 			bge_start(ifp);
@@ -3687,7 +3698,7 @@ bge_asf_driver_up(struct bge_softc *sc)
 			    BGE_FW_DRV_ALIVE);
 			bge_writemem_ind(sc, BGE_SOFTWARE_GENNCOMM_FW_LEN, 4);
 			bge_writemem_ind(sc, BGE_SOFTWARE_GENNCOMM_FW_DATA, 3);
-			CSR_WRITE_4(sc, BGE_CPU_EVENT,
+			CSR_WRITE_4_FLUSH(sc, BGE_CPU_EVENT,
 			    CSR_READ_4(sc, BGE_CPU_EVENT) | (1 << 14));
 		}
 	}
@@ -4417,11 +4428,11 @@ bge_init(struct ifnet *ifp)
 		mode |= BGE_TXMODE_MBUF_LOCKUP_FIX;
 
 	/* Turn on transmitter */
-	CSR_WRITE_4(sc, BGE_TX_MODE, mode | BGE_TXMODE_ENABLE);
+	CSR_WRITE_4_FLUSH(sc, BGE_TX_MODE, mode | BGE_TXMODE_ENABLE);
 	DELAY(100);
 
 	/* Turn on receiver */
-	BGE_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE);
+	BGE_SETBIT_FLUSH(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE);
 	DELAY(10);
 
 	CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 2);
@@ -4434,7 +4445,7 @@ bge_init(struct ifnet *ifp)
 	    BGE_PCIMISCCTL_CLEAR_INTA);
 	PCI_CLRBIT(sc->sc_pc, sc->sc_pcitag, BGE_PCI_MISC_CTL,
 	    BGE_PCIMISCCTL_MASK_PCI_INTR);
-	bge_writembx(sc, BGE_MBX_IRQ0_LO, 0);
+	bge_writembx_flush(sc, BGE_MBX_IRQ0_LO, 0);
 
 	if ((error = bge_ifmedia_upd(ifp)) != 0)
 		goto out;
@@ -4482,10 +4493,11 @@ bge_ifmedia_upd(struct ifnet *ifp)
 					sgdig |= BGE_SGDIGCFG_AUTO |
 					    BGE_SGDIGCFG_PAUSE_CAP |
 					    BGE_SGDIGCFG_ASYM_PAUSE;
-					CSR_WRITE_4(sc, BGE_SGDIG_CFG,
+					CSR_WRITE_4_FLUSH(sc, BGE_SGDIG_CFG,
 					    sgdig | BGE_SGDIGCFG_SEND);
 					DELAY(5);
-					CSR_WRITE_4(sc, BGE_SGDIG_CFG, sgdig);
+					CSR_WRITE_4_FLUSH(sc, BGE_SGDIG_CFG,
+					    sgdig);
 				}
 			}
 			break;
@@ -4658,7 +4670,7 @@ bge_stop_block(struct bge_softc *sc, bus
 {
 	int i;
 
-	BGE_CLRBIT(sc, reg, bit);
+	BGE_CLRBIT_FLUSH(sc, reg, bit);
 
 	for (i = 0; i < 1000; i++) {
 		if ((CSR_READ_4(sc, reg) & bit) == 0)
@@ -4696,7 +4708,7 @@ bge_stop(struct ifnet *ifp, int disable)
 	/* Disable host interrupts. */
 	PCI_SETBIT(sc->sc_pc, sc->sc_pcitag, BGE_PCI_MISC_CTL,
 	    BGE_PCIMISCCTL_MASK_PCI_INTR);
-	bge_writembx(sc, BGE_MBX_IRQ0_LO, 1);
+	bge_writembx_flush(sc, BGE_MBX_IRQ0_LO, 1);
 
 	/*
 	 * Disable all of the receiver blocks.

Index: src/sys/dev/pci/if_bgevar.h
diff -u src/sys/dev/pci/if_bgevar.h:1.10 src/sys/dev/pci/if_bgevar.h:1.11
--- src/sys/dev/pci/if_bgevar.h:1.10	Wed Feb 27 13:53:51 2013
+++ src/sys/dev/pci/if_bgevar.h	Thu Mar  7 08:46:54 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_bgevar.h,v 1.10 2013/02/27 13:53:51 msaitoh Exp $	*/
+/*	$NetBSD: if_bgevar.h,v 1.11 2013/03/07 08:46:54 msaitoh Exp $	*/
 /*
  * Copyright (c) 2001 Wind River Systems
  * Copyright (c) 1997, 1998, 1999, 2001
@@ -99,10 +99,26 @@
 #define CSR_READ_4(sc, reg)		\
 	bus_space_read_4(sc->bge_btag, sc->bge_bhandle, reg)
 
+#define CSR_WRITE_4_FLUSH(sc, reg, val)		\
+	do {					\
+		CSR_WRITE_4(sc, reg, val);	\
+		CSR_READ_4(sc, reg);		\
+	} while(0)
+
 #define BGE_SETBIT(sc, reg, x)	\
 	CSR_WRITE_4(sc, reg, (CSR_READ_4(sc, reg) | (x)))
+#define BGE_SETBIT_FLUSH(sc, reg, x)	\
+	do {				\
+		BGE_SETBIT(sc, reg, x);	\
+		CSR_READ_4(sc, reg);	\
+	} while(0)
 #define BGE_CLRBIT(sc, reg, x)	\
 	CSR_WRITE_4(sc, reg, (CSR_READ_4(sc, reg) & ~(x)))
+#define BGE_CLRBIT_FLUSH(sc, reg, x)	\
+	do {				\
+		BGE_CLRBIT(sc, reg, x);	\
+		CSR_READ_4(sc, reg);	\
+	} while(0)
 
 #define PCI_SETBIT(pc, tag, reg, x)	\
 	pci_conf_write(pc, tag, reg, (pci_conf_read(pc, tag, reg) | (x)))

Reply via email to