Make be(4) is properly initialized at the first ifconfig(8) command:

- make beinit() and bestop() match struct ifnet
- if ether_ioctl() returns ENETRESET always call init function
This commit is contained in:
tsutsui 2009-09-18 13:45:20 +00:00
parent 1d5ec6dab9
commit 0ab05b4a42
1 changed files with 42 additions and 32 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: be.c,v 1.67 2009/09/18 12:23:16 tsutsui Exp $ */ /* $NetBSD: be.c,v 1.68 2009/09/18 13:45:20 tsutsui Exp $ */
/*- /*-
* Copyright (c) 1999 The NetBSD Foundation, Inc. * Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -57,7 +57,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: be.c,v 1.67 2009/09/18 12:23:16 tsutsui Exp $"); __KERNEL_RCSID(0, "$NetBSD: be.c,v 1.68 2009/09/18 13:45:20 tsutsui Exp $");
#include "opt_ddb.h" #include "opt_ddb.h"
#include "opt_inet.h" #include "opt_inet.h"
@ -161,12 +161,13 @@ struct be_softc {
int bematch(device_t, cfdata_t, void *); int bematch(device_t, cfdata_t, void *);
void beattach(device_t, device_t, void *); void beattach(device_t, device_t, void *);
void beinit(struct be_softc *); int beinit(struct ifnet *);
void bestart(struct ifnet *); void bestart(struct ifnet *);
void bestop(struct be_softc *); void bestop(struct ifnet *, int);
void bewatchdog(struct ifnet *); void bewatchdog(struct ifnet *);
int beioctl(struct ifnet *, u_long, void *); int beioctl(struct ifnet *, u_long, void *);
void bereset(struct be_softc *); void bereset(struct be_softc *);
void behwreset(struct be_softc *);
int beintr(void *); int beintr(void *);
int berint(struct be_softc *); int berint(struct be_softc *);
@ -277,8 +278,6 @@ beattach(device_t parent, device_t self, void *aux)
callout_init(&sc->sc_tick_ch, 0); callout_init(&sc->sc_tick_ch, 0);
bestop(sc);
sc->sc_channel = prom_getpropint(node, "channel#", -1); sc->sc_channel = prom_getpropint(node, "channel#", -1);
if (sc->sc_channel == -1) if (sc->sc_channel == -1)
sc->sc_channel = 0; sc->sc_channel = 0;
@ -457,6 +456,8 @@ beattach(device_t parent, device_t self, void *aux)
ifp->if_start = bestart; ifp->if_start = bestart;
ifp->if_ioctl = beioctl; ifp->if_ioctl = beioctl;
ifp->if_watchdog = bewatchdog; ifp->if_watchdog = bewatchdog;
ifp->if_init = beinit;
ifp->if_stop = bestop;
ifp->if_flags = ifp->if_flags =
IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
IFQ_SET_READY(&ifp->if_snd); IFQ_SET_READY(&ifp->if_snd);
@ -656,11 +657,9 @@ bestart(struct ifnet *ifp)
} }
void void
bestop(struct be_softc *sc) bestop(struct ifnet *ifp, int disable)
{ {
int n; struct be_softc *sc = ifp->if_softc;
bus_space_tag_t t = sc->sc_bustag;
bus_space_handle_t br = sc->sc_br;
callout_stop(&sc->sc_tick_ch); callout_stop(&sc->sc_tick_ch);
@ -668,6 +667,16 @@ bestop(struct be_softc *sc)
mii_down(&sc->sc_mii); mii_down(&sc->sc_mii);
(void)be_intphy_service(sc, &sc->sc_mii, MII_DOWN); (void)be_intphy_service(sc, &sc->sc_mii, MII_DOWN);
behwreset(sc);
}
void
behwreset(struct be_softc *sc)
{
int n;
bus_space_tag_t t = sc->sc_bustag;
bus_space_handle_t br = sc->sc_br;
/* Stop the transmitter */ /* Stop the transmitter */
bus_space_write_4(t, br, BE_BRI_TXCFG, 0); bus_space_write_4(t, br, BE_BRI_TXCFG, 0);
for (n = 32; n > 0; n--) { for (n = 32; n > 0; n--) {
@ -691,12 +700,13 @@ bestop(struct be_softc *sc)
void void
bereset(struct be_softc *sc) bereset(struct be_softc *sc)
{ {
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
int s; int s;
s = splnet(); s = splnet();
bestop(sc); behwreset(sc);
if ((sc->sc_ethercom.ec_if.if_flags & IFF_UP) != 0) if ((sc->sc_ethercom.ec_if.if_flags & IFF_UP) != 0)
beinit(sc); beinit(ifp);
splx(s); splx(s);
} }
@ -963,7 +973,7 @@ beioctl(struct ifnet *ifp, u_long cmd, void *data)
switch (cmd) { switch (cmd) {
case SIOCINITIFADDR: case SIOCINITIFADDR:
ifp->if_flags |= IFF_UP; ifp->if_flags |= IFF_UP;
beinit(sc); beinit(ifp);
switch (ifa->ifa_addr->sa_family) { switch (ifa->ifa_addr->sa_family) {
#ifdef INET #ifdef INET
case AF_INET: case AF_INET:
@ -985,7 +995,7 @@ beioctl(struct ifnet *ifp, u_long cmd, void *data)
* If interface is marked down and it is running, then * If interface is marked down and it is running, then
* stop it. * stop it.
*/ */
bestop(sc); bestop(ifp, 0);
ifp->if_flags &= ~IFF_RUNNING; ifp->if_flags &= ~IFF_RUNNING;
break; break;
case IFF_UP: case IFF_UP:
@ -993,15 +1003,15 @@ beioctl(struct ifnet *ifp, u_long cmd, void *data)
* If interface is marked up and it is stopped, then * If interface is marked up and it is stopped, then
* start it. * start it.
*/ */
beinit(sc); beinit(ifp);
break; break;
default: default:
/* /*
* Reset the interface to pick up changes in any other * Reset the interface to pick up changes in any other
* flags that affect hardware registers. * flags that affect hardware registers.
*/ */
bestop(sc); bestop(ifp, 0);
beinit(sc); beinit(ifp);
break; break;
} }
#ifdef BEDEBUG #ifdef BEDEBUG
@ -1012,35 +1022,32 @@ beioctl(struct ifnet *ifp, u_long cmd, void *data)
#endif #endif
break; break;
case SIOCADDMULTI: case SIOCGIFMEDIA:
case SIOCDELMULTI: case SIOCSIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
break;
default:
if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) { if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
/* /*
* Multicast list has changed; set the hardware filter * Multicast list has changed; set the hardware filter
* accordingly. * accordingly.
*/ */
if (ifp->if_flags & IFF_RUNNING) if (ifp->if_flags & IFF_RUNNING)
be_mcreset(sc); error = beinit(ifp);
error = 0; else
error = 0;
} }
break; break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
break;
default:
error = ether_ioctl(ifp, cmd, data);
break;
} }
splx(s); splx(s);
return (error); return (error);
} }
void int
beinit(struct be_softc *sc) beinit(struct ifnet *ifp)
{ {
struct ifnet *ifp = &sc->sc_ethercom.ec_if; struct be_softc *sc = ifp->if_softc;
bus_space_tag_t t = sc->sc_bustag; bus_space_tag_t t = sc->sc_bustag;
bus_space_handle_t br = sc->sc_br; bus_space_handle_t br = sc->sc_br;
bus_space_handle_t cr = sc->sc_cr; bus_space_handle_t cr = sc->sc_cr;
@ -1054,7 +1061,7 @@ beinit(struct be_softc *sc)
qec_meminit(&sc->sc_rb, BE_PKT_BUF_SZ); qec_meminit(&sc->sc_rb, BE_PKT_BUF_SZ);
bestop(sc); bestop(ifp, 1);
ea = sc->sc_enaddr; ea = sc->sc_enaddr;
bus_space_write_4(t, br, BE_BRI_MACADDR0, (ea[0] << 8) | ea[1]); bus_space_write_4(t, br, BE_BRI_MACADDR0, (ea[0] << 8) | ea[1]);
@ -1137,8 +1144,11 @@ beinit(struct be_softc *sc)
ifp->if_flags &= ~IFF_OACTIVE; ifp->if_flags &= ~IFF_OACTIVE;
callout_reset(&sc->sc_tick_ch, hz, be_tick, sc); callout_reset(&sc->sc_tick_ch, hz, be_tick, sc);
return 0;
out: out:
splx(s); splx(s);
return rc;
} }
void void