diff options
author | bz <bz@FreeBSD.org> | 2005-08-13 11:13:12 +0000 |
---|---|---|
committer | bz <bz@FreeBSD.org> | 2005-08-13 11:13:12 +0000 |
commit | f6434969628744c99a49f83d6ff55743d40a5ff2 (patch) | |
tree | 7e5ba4e9f5fd40f7c0b2c44e256185c0cc5c7f3e /sys/pci | |
parent | 5434a588080f496f3f78c9b62fcc9bc2993449cb (diff) | |
download | FreeBSD-src-f6434969628744c99a49f83d6ff55743d40a5ff2.zip FreeBSD-src-f6434969628744c99a49f83d6ff55743d40a5ff2.tar.gz |
* Solve "No PHY found" problem for more Yukon Lite variants.
* Catch a bus attach error.
* Improve locking.
MFC after: 6 days
Diffstat (limited to 'sys/pci')
-rw-r--r-- | sys/pci/if_sk.c | 86 |
1 files changed, 61 insertions, 25 deletions
diff --git a/sys/pci/if_sk.c b/sys/pci/if_sk.c index 65b3a5f..b0d937a 100644 --- a/sys/pci/if_sk.c +++ b/sys/pci/if_sk.c @@ -195,8 +195,10 @@ static void sk_txeof(struct sk_if_softc *); static int sk_encap(struct sk_if_softc *, struct mbuf *, u_int32_t *); static void sk_start(struct ifnet *); +static void sk_start_locked(struct ifnet *); static int sk_ioctl(struct ifnet *, u_long, caddr_t); static void sk_init(void *); +static void sk_init_locked(struct sk_if_softc *); static void sk_init_xmac(struct sk_if_softc *); static void sk_init_yukon(struct sk_if_softc *); static void sk_stop(struct sk_if_softc *); @@ -797,6 +799,7 @@ sk_setmulti(sc_if) struct ifmultiaddr *ifma; u_int8_t dummy[] = { 0, 0, 0, 0, 0 ,0 }; + SK_IF_LOCK_ASSERT(sc_if); /* First, zot all the existing filters. */ switch(sc->sk_type) { @@ -886,6 +889,8 @@ sk_setpromisc(sc_if) struct sk_softc *sc = sc_if->sk_softc; struct ifnet *ifp = sc_if->sk_ifp; + SK_IF_LOCK_ASSERT(sc_if); + switch(sc->sk_type) { case SK_GENESIS: if (ifp->if_flags & IFF_PROMISC) { @@ -1240,13 +1245,15 @@ sk_ioctl(ifp, command, data) switch(command) { case SIOCSIFMTU: + SK_IF_LOCK(sc_if); if (ifr->ifr_mtu > SK_JUMBO_MTU) error = EINVAL; else { ifp->if_mtu = ifr->ifr_mtu; ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - sk_init(sc_if); + sk_init_locked(sc_if); } + SK_IF_UNLOCK(sc_if); break; case SIOCSIFFLAGS: SK_IF_LOCK(sc_if); @@ -1258,7 +1265,7 @@ sk_ioctl(ifp, command, data) sk_setmulti(sc_if); } } else - sk_init(sc_if); + sk_init_locked(sc_if); } else { if (ifp->if_drv_flags & IFF_DRV_RUNNING) sk_stop(sc_if); @@ -1269,12 +1276,12 @@ sk_ioctl(ifp, command, data) break; case SIOCADDMULTI: case SIOCDELMULTI: + SK_IF_LOCK(sc_if); if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - SK_IF_LOCK(sc_if); sk_setmulti(sc_if); - SK_IF_UNLOCK(sc_if); error = 0; } + SK_IF_UNLOCK(sc_if); break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: @@ -1353,8 +1360,9 @@ sk_reset(sc) * register represents 18.825ns, so to specify a timeout in * microseconds, we have to multiply by 54. */ - printf("skc%d: interrupt moderation is %d us\n", - sc->sk_unit, sc->sk_int_mod); + if (bootverbose) + printf("skc%d: interrupt moderation is %d us\n", + sc->sk_unit, sc->sk_int_mod); sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(sc->sk_int_mod)); sk_win_write_4(sc, SK_IMMR, SK_ISR_TX1_S_EOF|SK_ISR_TX2_S_EOF| SK_ISR_RX1_EOF|SK_ISR_RX2_EOF); @@ -1678,7 +1686,7 @@ skc_attach(dev) break; default: printf("skc%d: unknown ram size: %d\n", - sc->sk_unit, sk_win_read_1(sc, SK_EPROM0)); + sc->sk_unit, skrs); error = ENXIO; goto fail; } @@ -1866,7 +1874,11 @@ skc_attach(dev) /* Turn on the 'driver is loaded' LED. */ CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_ON); - bus_generic_attach(dev); + error = bus_generic_attach(dev); + if (error) { + device_printf(dev, "failed to attach port(s)\n"); + goto fail; + } /* Hook interrupt last to avoid having to lock softc */ error = bus_setup_intr(dev, sc->sk_irq, INTR_TYPE_NET|INTR_MPSAFE, @@ -2028,6 +2040,21 @@ static void sk_start(ifp) struct ifnet *ifp; { + struct sk_if_softc *sc_if; + + sc_if = ifp->if_softc; + + SK_IF_LOCK(sc_if); + sk_start_locked(ifp); + SK_IF_UNLOCK(sc_if); + + return; +} + +static void +sk_start_locked(ifp) + struct ifnet *ifp; +{ struct sk_softc *sc; struct sk_if_softc *sc_if; struct mbuf *m_head = NULL; @@ -2036,7 +2063,7 @@ sk_start(ifp) sc_if = ifp->if_softc; sc = sc_if->sk_softc; - SK_IF_LOCK(sc_if); + SK_IF_LOCK_ASSERT(sc_if); idx = sc_if->sk_cdata.sk_tx_prod; @@ -2071,7 +2098,6 @@ sk_start(ifp) /* Set a timeout in case the chip goes out to lunch. */ ifp->if_timer = 5; } - SK_IF_UNLOCK(sc_if); return; } @@ -2086,8 +2112,10 @@ sk_watchdog(ifp) sc_if = ifp->if_softc; printf("sk%d: watchdog timeout\n", sc_if->sk_unit); + SK_IF_LOCK(sc_if); ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - sk_init(sc_if); + sk_init_locked(sc_if); + SK_IF_UNLOCK(sc_if); return; } @@ -2458,9 +2486,9 @@ sk_intr(xsc) CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask); if (ifp0 != NULL && !IFQ_DRV_IS_EMPTY(&ifp0->if_snd)) - sk_start(ifp0); + sk_start_locked(ifp0); if (ifp1 != NULL && !IFQ_DRV_IS_EMPTY(&ifp1->if_snd)) - sk_start(ifp1); + sk_start_locked(ifp1); SK_UNLOCK(sc); @@ -2646,7 +2674,7 @@ sk_init_yukon(sc_if) ifp = sc_if->sk_ifp; if (sc->sk_type == SK_YUKON_LITE && - sc->sk_rev == SK_YUKON_LITE_REV_A3) { + sc->sk_rev >= SK_YUKON_LITE_REV_A3) { /* Take PHY out of reset. */ sk_win_write_4(sc, SK_GPIO, (sk_win_read_4(sc, SK_GPIO) | SK_GPIO_DIR9) & ~SK_GPIO_DAT9); @@ -2750,22 +2778,32 @@ sk_init(xsc) void *xsc; { struct sk_if_softc *sc_if = xsc; + + SK_IF_LOCK(sc_if); + sk_init_locked(sc_if); + SK_IF_UNLOCK(sc_if); + + return; +} + +static void +sk_init_locked(sc_if) + struct sk_if_softc *sc_if; +{ struct sk_softc *sc; struct ifnet *ifp; struct mii_data *mii; u_int16_t reg; u_int32_t imr; - SK_IF_LOCK(sc_if); + SK_IF_LOCK_ASSERT(sc_if); ifp = sc_if->sk_ifp; sc = sc_if->sk_softc; mii = device_get_softc(sc_if->sk_miibus); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - SK_IF_UNLOCK(sc_if); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) return; - } /* Cancel pending I/O and free all RX/TX buffers. */ sk_stop(sc_if); @@ -2847,7 +2885,6 @@ sk_init(xsc) printf("sk%d: initialization failed: no " "memory for rx buffers\n", sc_if->sk_unit); sk_stop(sc_if); - SK_IF_UNLOCK(sc_if); return; } sk_init_tx_ring(sc_if); @@ -2857,8 +2894,9 @@ sk_init(xsc) imr = sk_win_read_4(sc, SK_IMTIMERINIT); if (imr != SK_IM_USECS(sc->sk_int_mod)) { sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(sc->sk_int_mod)); - printf("skc%d: interrupt moderation is %d us\n", - sc->sk_unit, sc->sk_int_mod); + if (bootverbose) + printf("skc%d: interrupt moderation is %d us\n", + sc->sk_unit, sc->sk_int_mod); } /* SK_UNLOCK(sc); */ @@ -2894,8 +2932,6 @@ sk_init(xsc) ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - SK_IF_UNLOCK(sc_if); - return; } @@ -2907,7 +2943,7 @@ sk_stop(sc_if) struct sk_softc *sc; struct ifnet *ifp; - SK_IF_LOCK(sc_if); + SK_IF_LOCK_ASSERT(sc_if); sc = sc_if->sk_softc; ifp = sc_if->sk_ifp; @@ -2978,7 +3014,7 @@ sk_stop(sc_if) } ifp->if_drv_flags &= ~(IFF_DRV_RUNNING|IFF_DRV_OACTIVE); - SK_IF_UNLOCK(sc_if); + return; } |