summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2007-01-20 10:47:16 +0000
committermarius <marius@FreeBSD.org>2007-01-20 10:47:16 +0000
commita31f50a3fbb019e8bef333536641691ebce78066 (patch)
tree8606f79689e4024c144fa70d49e3b09decc1d48d /sys
parent613c7e2883fd4fbbdd40df85bdb9b599815510bf (diff)
downloadFreeBSD-src-a31f50a3fbb019e8bef333536641691ebce78066.zip
FreeBSD-src-a31f50a3fbb019e8bef333536641691ebce78066.tar.gz
For setting the port PCnet chips must be powered down or stopped and
unlike documented may not take effect without an initialization. So don't invoke (*sc_mediachange) directly in lance_mediachange() but go through lance_init_locked(). It's suboptimal to impose this for all chips but given that besides the affected PCI bus front-end the only other front-end which supports media selection is and likely ever will be the 'ledma' front-end I see not enough reason to break the in-driver API for this (though one could argue both ways here).
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/le/lance.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/sys/dev/le/lance.c b/sys/dev/le/lance.c
index 3257637..68673a9 100644
--- a/sys/dev/le/lance.c
+++ b/sys/dev/le/lance.c
@@ -299,6 +299,10 @@ lance_init_locked(struct lance_softc *sc)
/* Set the correct byte swapping mode, etc. */
(*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3);
+ /* Set the current media. This may require the chip to be stopped. */
+ if (sc->sc_mediachange)
+ (void)(*sc->sc_mediachange)(sc);
+
/*
* Update our private copy of the Ethernet address.
* We NEED the copy so we can ensure its alignment!
@@ -322,10 +326,6 @@ lance_init_locked(struct lance_softc *sc)
if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON)
break;
- /* Set the current media. */
- if (sc->sc_mediachange)
- (void)(*sc->sc_mediachange)(sc);
-
if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) {
/* Start the LANCE. */
(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT);
@@ -460,13 +460,21 @@ static int
lance_mediachange(struct ifnet *ifp)
{
struct lance_softc *sc = ifp->if_softc;
- int error;
if (sc->sc_mediachange) {
+ /*
+ * For setting the port in LE_CSR15 the PCnet chips must
+ * be powered down or stopped and unlike documented may
+ * not take effect without an initialization. So don't
+ * invoke (*sc_mediachange) directly here but go through
+ * lance_init_locked().
+ */
LE_LOCK(sc);
- error = (*sc->sc_mediachange)(sc);
+ lance_stop(sc);
+ lance_init_locked(sc);
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ (*sc->sc_start_locked)(sc);
LE_UNLOCK(sc);
- return (error);
}
return (0);
}
OpenPOWER on IntegriCloud