mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
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).
This commit is contained in:
parent
d2255d0286
commit
17792f45fb
1 changed files with 15 additions and 7 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue