From 9066ce1621d00da3ecc6d82abfa9798841f13ace Mon Sep 17 00:00:00 2001 From: thorpej Date: Fri, 28 Jun 2002 18:44:45 +0000 Subject: [PATCH] When stopping the various functional blocks of the chip, clear the bit and then read it back in a loop (with appropriate delays) waiting for it to read back clear. This fixes a problem where the bus would hang when bringing down the interface or changing interface flags on a system with a sufficiently fast CPU (e.g. 2GHz P4 Xeon). --- sys/dev/pci/if_bge.c | 59 +++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/sys/dev/pci/if_bge.c b/sys/dev/pci/if_bge.c index 56dc0b501408..8cd1acbf22eb 100644 --- a/sys/dev/pci/if_bge.c +++ b/sys/dev/pci/if_bge.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_bge.c,v 1.10 2002/06/28 18:39:45 fvdl Exp $ */ +/* $NetBSD: if_bge.c,v 1.11 2002/06/28 18:44:45 thorpej Exp $ */ /* * Copyright (c) 2001 Wind River Systems @@ -2785,6 +2785,23 @@ bge_watchdog(ifp) ifp->if_oerrors++; } +static void +bge_stop_block(struct bge_softc *sc, bus_addr_t reg, uint32_t bit) +{ + int i; + + BGE_CLRBIT(sc, reg, bit); + + for (i = 0; i < BGE_TIMEOUT; i++) { + if ((CSR_READ_4(sc, reg) & bit) == 0) + return; + delay(100); + } + + printf("%s: block failed to stop: reg 0x%lx, bit 0x%08x\n", + sc->bge_dev.dv_xname, (u_long) reg, bit); +} + /* * Stop the adapter and free any mbufs allocated to the * RX and TX lists. @@ -2800,36 +2817,38 @@ bge_stop(sc) /* * Disable all of the receiver blocks */ - BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE); - BGE_CLRBIT(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE); - BGE_CLRBIT(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); - BGE_CLRBIT(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE); - BGE_CLRBIT(sc, BGE_RDBDI_MODE, BGE_RBDIMODE_ENABLE); - BGE_CLRBIT(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE); - BGE_CLRBIT(sc, BGE_RBDC_MODE, BGE_RBDCMODE_ENABLE); + bge_stop_block(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE); + bge_stop_block(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE); + bge_stop_block(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); + bge_stop_block(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE); + bge_stop_block(sc, BGE_RDBDI_MODE, BGE_RBDIMODE_ENABLE); + bge_stop_block(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE); + bge_stop_block(sc, BGE_RBDC_MODE, BGE_RBDCMODE_ENABLE); /* * Disable all of the transmit blocks */ - BGE_CLRBIT(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE); - BGE_CLRBIT(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE); - BGE_CLRBIT(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); - BGE_CLRBIT(sc, BGE_RDMA_MODE, BGE_RDMAMODE_ENABLE); - BGE_CLRBIT(sc, BGE_SDC_MODE, BGE_SDCMODE_ENABLE); - BGE_CLRBIT(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE); - BGE_CLRBIT(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); + bge_stop_block(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE); + bge_stop_block(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE); + bge_stop_block(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); + bge_stop_block(sc, BGE_RDMA_MODE, BGE_RDMAMODE_ENABLE); + bge_stop_block(sc, BGE_SDC_MODE, BGE_SDCMODE_ENABLE); + bge_stop_block(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE); + bge_stop_block(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); /* * Shut down all of the memory managers and related * state machines. */ - BGE_CLRBIT(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE); - BGE_CLRBIT(sc, BGE_WDMA_MODE, BGE_WDMAMODE_ENABLE); - BGE_CLRBIT(sc, BGE_MBCF_MODE, BGE_MBCFMODE_ENABLE); + bge_stop_block(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE); + bge_stop_block(sc, BGE_WDMA_MODE, BGE_WDMAMODE_ENABLE); + bge_stop_block(sc, BGE_MBCF_MODE, BGE_MBCFMODE_ENABLE); + CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF); CSR_WRITE_4(sc, BGE_FTQ_RESET, 0); - BGE_CLRBIT(sc, BGE_BMAN_MODE, BGE_BMANMODE_ENABLE); - BGE_CLRBIT(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); + + bge_stop_block(sc, BGE_BMAN_MODE, BGE_BMANMODE_ENABLE); + bge_stop_block(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); /* Disable host interrupts. */ BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR);