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).
This commit is contained in:
thorpej 2002-06-28 18:44:45 +00:00
parent 50ade28e9b
commit 9066ce1621

View File

@ -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 * Copyright (c) 2001 Wind River Systems
@ -2785,6 +2785,23 @@ bge_watchdog(ifp)
ifp->if_oerrors++; 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 * Stop the adapter and free any mbufs allocated to the
* RX and TX lists. * RX and TX lists.
@ -2800,36 +2817,38 @@ bge_stop(sc)
/* /*
* Disable all of the receiver blocks * Disable all of the receiver blocks
*/ */
BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE); bge_stop_block(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE);
BGE_CLRBIT(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE); bge_stop_block(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE);
BGE_CLRBIT(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); bge_stop_block(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE);
BGE_CLRBIT(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE); bge_stop_block(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE);
BGE_CLRBIT(sc, BGE_RDBDI_MODE, BGE_RBDIMODE_ENABLE); bge_stop_block(sc, BGE_RDBDI_MODE, BGE_RBDIMODE_ENABLE);
BGE_CLRBIT(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE); bge_stop_block(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE);
BGE_CLRBIT(sc, BGE_RBDC_MODE, BGE_RBDCMODE_ENABLE); bge_stop_block(sc, BGE_RBDC_MODE, BGE_RBDCMODE_ENABLE);
/* /*
* Disable all of the transmit blocks * Disable all of the transmit blocks
*/ */
BGE_CLRBIT(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE); bge_stop_block(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE);
BGE_CLRBIT(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE); bge_stop_block(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE);
BGE_CLRBIT(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); bge_stop_block(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE);
BGE_CLRBIT(sc, BGE_RDMA_MODE, BGE_RDMAMODE_ENABLE); bge_stop_block(sc, BGE_RDMA_MODE, BGE_RDMAMODE_ENABLE);
BGE_CLRBIT(sc, BGE_SDC_MODE, BGE_SDCMODE_ENABLE); bge_stop_block(sc, BGE_SDC_MODE, BGE_SDCMODE_ENABLE);
BGE_CLRBIT(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE); bge_stop_block(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE);
BGE_CLRBIT(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); bge_stop_block(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE);
/* /*
* Shut down all of the memory managers and related * Shut down all of the memory managers and related
* state machines. * state machines.
*/ */
BGE_CLRBIT(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE); bge_stop_block(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE);
BGE_CLRBIT(sc, BGE_WDMA_MODE, BGE_WDMAMODE_ENABLE); bge_stop_block(sc, BGE_WDMA_MODE, BGE_WDMAMODE_ENABLE);
BGE_CLRBIT(sc, BGE_MBCF_MODE, BGE_MBCFMODE_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, 0xFFFFFFFF);
CSR_WRITE_4(sc, BGE_FTQ_RESET, 0); 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. */ /* Disable host interrupts. */
BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR); BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR);