diff options
| author | aiju <aiju@phicode.de> | 2011-11-05 10:22:21 +0100 |
|---|---|---|
| committer | aiju <aiju@phicode.de> | 2011-11-05 10:22:21 +0100 |
| commit | 6f8f383ab17375d21064df4c1a7dd49971c13a95 (patch) | |
| tree | 9091912cef2415be9783bde20a87eb79978e220b | |
| parent | c8524f52ada4416622e10d4015a369fb35dac1bd (diff) | |
| download | plan9front-6f8f383ab17375d21064df4c1a7dd49971c13a95.tar.xz | |
added timeouts to bcminit()
| -rw-r--r-- | sys/src/9/pc/etherbcm.c | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/sys/src/9/pc/etherbcm.c b/sys/src/9/pc/etherbcm.c index a82e748d8..d45cdbfaf 100644 --- a/sys/src/9/pc/etherbcm.c +++ b/sys/src/9/pc/etherbcm.c @@ -425,7 +425,7 @@ bcminterrupt(Ureg*, void *arg) iunlock(&ctlr->imlock); } -static void +static int bcminit(Ether *edev) { ulong i, j; @@ -436,7 +436,12 @@ bcminit(Ether *edev) /* initialization procedure according to the datasheet */ csr32(ctlr, MiscHostCtl) |= MaskPCIInt | ClearIntA; csr32(ctlr, SwArbitration) |= SwArbitSet1; - while((csr32(ctlr, SwArbitration) & SwArbitWon1) == 0); + for(i = 0; i < 10000 && (csr32(ctlr, SwArbitration) & SwArbitWon1) == 0; i++) + microdelay(100); + if(i == 10000){ + iprint("bcm: arbiter failed to respond\n"); + return -1; + } csr32(ctlr, MemArbiterMode) |= Enable; csr32(ctlr, MiscHostCtl) |= IndirectAccessEnable | EnablePCIStateRegister | EnableClockControlRegister; csr32(ctlr, MemoryWindow) = 0; @@ -452,7 +457,12 @@ bcminit(Ether *edev) csr32(ctlr, ModeControl) |= ByteWordSwap; csr32(ctlr, MACMode) = (csr32(ctlr, MACMode) & MACPortMask) | MACPortGMII; microdelay(40000); - while(mem32(ctlr, 0xB50) != 0xB49A89AB); + for(i = 0; i < 100000 && mem32(ctlr, 0xB50) != 0xB49A89AB; i++) + microdelay(100); + if(i == 100000){ + iprint("bcm: chip failed to reset\n"); + return -1; + } csr32(ctlr, TLPControl) |= (1<<25) | (1<<29); memset(ctlr->status, 0, 20); csr32(ctlr, DMARWControl) = (csr32(ctlr, DMARWControl) & DMAWatermarkMask) | DMAWatermarkValue; @@ -462,10 +472,20 @@ bcminit(Ether *edev) csr32(ctlr, MBUFHighWatermark) = 0x60; csr32(ctlr, LowWatermarkMaximum) = (csr32(ctlr, LowWatermarkMaximum) & LowWatermarkMaxMask) | LowWatermarkMaxValue; csr32(ctlr, BufferManMode) |= Enable | Attn; - while((csr32(ctlr, BufferManMode) & Enable) == 0); + for(i = 0; i < 100 && (csr32(ctlr, BufferManMode) & Enable) == 0; i++) + microdelay(100); + if(i == 100){ + iprint("bcm: buffer manager failed to start\n"); + return -1; + } csr32(ctlr, FTQReset) = -1; csr32(ctlr, FTQReset) = 0; - while(csr32(ctlr, FTQReset)); + for(i = 0; i < 1000 && csr32(ctlr, FTQReset) != 0; i++) + microdelay(100); + if(i == 1000){ + iprint("bcm: ftq failed to reset\n"); + return -1; + } csr32(ctlr, ReceiveBDHostAddr) = 0; csr32(ctlr, ReceiveBDHostAddr + 4) = PADDR(ctlr->recvprod); csr32(ctlr, ReceiveBDFlags) = RecvProdRingLen << 16; @@ -503,7 +523,12 @@ bcminit(Ether *edev) csr32(ctlr, SendInitiatorMask) = 0xFFFFFF; csr32(ctlr, SendInitiatorConfiguration) |= SendStats; csr32(ctlr, HostCoalescingMode) = 0; - while(csr32(ctlr, HostCoalescingMode) != 0); + for(i = 0; i < 200 && csr32(ctlr, HostCoalescingMode) != 0; i++) + microdelay(100); + if(i == 200){ + iprint("bcm: host coalescing engine failed to stop\n"); + return -1; + } csr32(ctlr, HostCoalescingRecvTicks) = 150; csr32(ctlr, HostCoalescingSendTicks) = 150; csr32(ctlr, RecvMaxCoalescedFrames) = 10; @@ -539,7 +564,12 @@ bcminit(Ether *edev) csr32(ctlr, MIMode) = 0xC0000; microdelay(40); miiw(ctlr, PhyControl, 1<<15); - while(miir(ctlr, PhyControl) & (1<<15)); + for(i = 0; i < 1000 && miir(ctlr, PhyControl) & (1<<15); i++) + microdelay(100); + if(i == 1000){ + iprint("bcm: PHY failed to reset\n"); + return -1; + } miiw(ctlr, PhyAuxControl, 2); miir(ctlr, PhyIntStatus); miir(ctlr, PhyIntStatus); @@ -554,6 +584,7 @@ bcminit(Ether *edev) csr32(ctlr, ReceiveRulesConfiguration) = 1 << 3; csr32(ctlr, MSIMode) |= Enable; csr32(ctlr, MiscHostCtl) &= ~(MaskPCIInt | ClearIntA); + return 0; } static void @@ -637,6 +668,7 @@ bcmpnp(Ether* edev) { Ctlr *ctlr; +again: if(bcmhead == nil) bcmpci(); @@ -664,7 +696,10 @@ bcmpnp(Ether* edev) edev->arg = edev; edev->mbps = 1000; - bcminit(edev); + if(bcminit(edev) < 0){ + edev->ctlr = nil; + goto again; + } return 0; } |
