Fixup locking and mark MPSAFE:

- Add locked versions of start and init.  The SRM_MEDIA code in dc_init()
  stayed in dc_init() instead of moving to dc_init_locked() to make the
  locking saner.
- Use callout_init_mtx().
- Fixup locking in detach and ioctl.
- Lock the driver in the ifmedia callouts.
- Don't recurse on the driver lock.
- De-spl.

MFC after:	3 days
This commit is contained in:
John Baldwin 2005-08-18 19:10:07 +00:00
parent 99030e6c12
commit c8b27aca43
2 changed files with 154 additions and 140 deletions

View File

@ -235,8 +235,10 @@ static void dc_tick(void *);
static void dc_tx_underrun(struct dc_softc *);
static void dc_intr(void *);
static void dc_start(struct ifnet *);
static void dc_start_locked(struct ifnet *);
static int dc_ioctl(struct ifnet *, u_long, caddr_t);
static void dc_init(void *);
static void dc_init_locked(struct dc_softc *);
static void dc_stop(struct dc_softc *);
static void dc_watchdog(struct ifnet *);
static void dc_shutdown(device_t);
@ -343,8 +345,6 @@ DRIVER_MODULE(miibus, dc, miibus_driver, miibus_devclass, 0, 0);
#define SIO_SET(x) DC_SETBIT(sc, DC_SIO, (x))
#define SIO_CLR(x) DC_CLRBIT(sc, DC_SIO, (x))
#define IS_MPSAFE 0
static void
dc_delay(struct dc_softc *sc)
{
@ -670,8 +670,6 @@ dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame)
{
int i, ack;
DC_LOCK(sc);
/*
* Set up frame for RX.
*/
@ -724,8 +722,6 @@ dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame)
dc_mii_writebit(sc, 0);
dc_mii_writebit(sc, 0);
DC_UNLOCK(sc);
if (ack)
return (1);
return (0);
@ -738,7 +734,6 @@ static int
dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame)
{
DC_LOCK(sc);
/*
* Set up frame for TX.
*/
@ -763,8 +758,6 @@ dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame)
dc_mii_writebit(sc, 0);
dc_mii_writebit(sc, 0);
DC_UNLOCK(sc);
return (0);
}
@ -1844,7 +1837,7 @@ dc_attach(device_t dev)
sc = device_get_softc(dev);
mtx_init(&sc->dc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF | MTX_RECURSE);
MTX_DEF);
/*
* Map control/status registers.
@ -2194,8 +2187,6 @@ dc_attach(device_t dev)
/* XXX: bleah, MTU gets overwritten in ether_ifattach() */
ifp->if_mtu = ETHERMTU;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
if (!IS_MPSAFE)
ifp->if_flags |= IFF_NEEDSGIANT;
ifp->if_ioctl = dc_ioctl;
ifp->if_start = dc_start;
ifp->if_watchdog = dc_watchdog;
@ -2276,7 +2267,7 @@ dc_attach(device_t dev)
#endif
ifp->if_capenable = ifp->if_capabilities;
callout_init(&sc->dc_stat_ch, IS_MPSAFE ? CALLOUT_MPSAFE : 0);
callout_init_mtx(&sc->dc_stat_ch, &sc->dc_mtx, 0);
#ifdef SRM_MEDIA
sc->dc_srm_media = 0;
@ -2310,8 +2301,7 @@ dc_attach(device_t dev)
ether_ifattach(ifp, eaddr);
/* Hook interrupt last to avoid having to lock softc */
error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET |
(IS_MPSAFE ? INTR_MPSAFE : 0),
error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET | INTR_MPSAFE,
dc_intr, sc, &sc->dc_intrhand);
if (error) {
@ -2344,13 +2334,15 @@ dc_detach(device_t dev)
sc = device_get_softc(dev);
KASSERT(mtx_initialized(&sc->dc_mtx), ("dc mutex not initialized"));
DC_LOCK(sc);
ifp = sc->dc_ifp;
/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
DC_LOCK(sc);
dc_stop(sc);
DC_UNLOCK(sc);
callout_drain(&sc->dc_stat_ch);
ether_ifdetach(ifp);
if_free(ifp);
}
@ -2390,7 +2382,6 @@ dc_detach(device_t dev)
}
free(sc->dc_srom, M_DEVBUF);
DC_UNLOCK(sc);
mtx_destroy(&sc->dc_mtx);
return (0);
@ -2751,7 +2742,7 @@ dc_rxeof(struct dc_softc *sc)
DC_INC(i, DC_RX_LIST_CNT);
continue;
} else {
dc_init(sc);
dc_init_locked(sc);
return;
}
}
@ -2879,7 +2870,7 @@ dc_txeof(struct dc_softc *sc)
if (txstat & DC_TXSTAT_LATECOLL)
ifp->if_collisions++;
if (!(txstat & DC_TXSTAT_UNDERRUN)) {
dc_init(sc);
dc_init_locked(sc);
return;
}
}
@ -2918,7 +2909,7 @@ dc_tick(void *xsc)
u_int32_t r;
sc = xsc;
DC_LOCK(sc);
DC_LOCK_ASSERT(sc);
ifp = sc->dc_ifp;
mii = device_get_softc(sc->dc_miibus);
@ -2972,15 +2963,13 @@ dc_tick(void *xsc)
IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
sc->dc_link++;
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
dc_start(ifp);
dc_start_locked(ifp);
}
if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link)
callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc);
else
callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc);
DC_UNLOCK(sc);
}
/*
@ -2994,7 +2983,7 @@ dc_tx_underrun(struct dc_softc *sc)
int i;
if (DC_IS_DAVICOM(sc))
dc_init(sc);
dc_init_locked(sc);
if (DC_IS_INTEL(sc)) {
/*
@ -3013,7 +3002,7 @@ dc_tx_underrun(struct dc_softc *sc)
if (i == DC_TIMEOUT) {
if_printf(sc->dc_ifp,
"failed to force tx to idle state\n");
dc_init(sc);
dc_init_locked(sc);
}
}
@ -3055,7 +3044,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
dc_txeof(sc);
if (!IFQ_IS_EMPTY(&ifp->if_snd) &&
!(ifp->if_drv_flags & IFF_DRV_OACTIVE))
dc_start(ifp);
dc_start_locked(ifp);
if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */
u_int32_t status;
@ -3088,7 +3077,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
if (status & DC_ISR_BUS_ERR) {
if_printf(ifp, "dc_poll: bus error\n");
dc_reset(sc);
dc_init(sc);
dc_init_locked(sc);
}
}
DC_UNLOCK(sc);
@ -3175,7 +3164,7 @@ dc_intr(void *arg)
if (status & DC_ISR_BUS_ERR) {
dc_reset(sc);
dc_init(sc);
dc_init_locked(sc);
}
}
@ -3183,7 +3172,7 @@ dc_intr(void *arg)
CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
dc_start(ifp);
dc_start_locked(ifp);
#ifdef DEVICE_POLLING
done:
@ -3310,6 +3299,17 @@ dc_encap(struct dc_softc *sc, struct mbuf **m_head)
static void
dc_start(struct ifnet *ifp)
{
struct dc_softc *sc;
sc = ifp->if_softc;
DC_LOCK(sc);
dc_start_locked(ifp);
DC_UNLOCK(sc);
}
static void
dc_start_locked(struct ifnet *ifp)
{
struct dc_softc *sc;
struct mbuf *m_head = NULL, *m;
@ -3318,17 +3318,13 @@ dc_start(struct ifnet *ifp)
sc = ifp->if_softc;
DC_LOCK(sc);
DC_LOCK_ASSERT(sc);
if (!sc->dc_link && ifp->if_snd.ifq_len < 10) {
DC_UNLOCK(sc);
if (!sc->dc_link && ifp->if_snd.ifq_len < 10)
return;
}
if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
DC_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
return;
}
idx = sc->dc_cdata.dc_tx_first = sc->dc_cdata.dc_tx_prod;
@ -3380,18 +3376,37 @@ dc_start(struct ifnet *ifp)
*/
ifp->if_timer = 5;
}
DC_UNLOCK(sc);
}
static void
dc_init(void *xsc)
{
struct dc_softc *sc = xsc;
DC_LOCK(sc);
dc_init_locked(sc);
#ifdef SRM_MEDIA
if(sc->dc_srm_media) {
struct ifreq ifr;
struct mii_data *mii;
ifr.ifr_media = sc->dc_srm_media;
sc->dc_srm_media = 0;
DC_UNLOCK(sc);
mii = device_get_softc(sc->dc_miibus);
ifmedia_ioctl(sc->dc_ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA);
} else
#endif
DC_UNLOCK(sc);
}
static void
dc_init_locked(struct dc_softc *sc)
{
struct ifnet *ifp = sc->dc_ifp;
struct mii_data *mii;
DC_LOCK(sc);
DC_LOCK_ASSERT(sc);
mii = device_get_softc(sc->dc_miibus);
@ -3487,7 +3502,6 @@ dc_init(void *xsc)
if_printf(ifp,
"initialization failed: no memory for rx buffers\n");
dc_stop(sc);
DC_UNLOCK(sc);
return;
}
@ -3559,17 +3573,6 @@ dc_init(void *xsc)
else
callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc);
}
#ifdef SRM_MEDIA
if(sc->dc_srm_media) {
struct ifreq ifr;
ifr.ifr_media = sc->dc_srm_media;
ifmedia_ioctl(ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA);
sc->dc_srm_media = 0;
}
#endif
DC_UNLOCK(sc);
}
/*
@ -3584,6 +3587,7 @@ dc_ifmedia_upd(struct ifnet *ifp)
sc = ifp->if_softc;
mii = device_get_softc(sc->dc_miibus);
DC_LOCK(sc);
mii_mediachg(mii);
ifm = &mii->mii_media;
@ -3592,6 +3596,7 @@ dc_ifmedia_upd(struct ifnet *ifp)
dc_setcfg(sc, ifm->ifm_media);
else
sc->dc_link = 0;
DC_UNLOCK(sc);
return (0);
}
@ -3608,6 +3613,7 @@ dc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
sc = ifp->if_softc;
mii = device_get_softc(sc->dc_miibus);
DC_LOCK(sc);
mii_pollstat(mii);
ifm = &mii->mii_media;
if (DC_IS_DAVICOM(sc)) {
@ -3619,6 +3625,7 @@ dc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
}
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
DC_UNLOCK(sc);
}
static int
@ -3629,10 +3636,9 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
struct mii_data *mii;
int error = 0;
DC_LOCK(sc);
switch (command) {
case SIOCSIFFLAGS:
DC_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
int need_setfilt = (ifp->if_flags ^ sc->dc_if_flags) &
(IFF_PROMISC | IFF_ALLMULTI);
@ -3642,18 +3648,21 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
dc_setfilt(sc);
} else {
sc->dc_txthresh = 0;
dc_init(sc);
dc_init_locked(sc);
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
dc_stop(sc);
}
sc->dc_if_flags = ifp->if_flags;
DC_UNLOCK(sc);
error = 0;
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
DC_LOCK(sc);
dc_setfilt(sc);
DC_UNLOCK(sc);
error = 0;
break;
case SIOCGIFMEDIA:
@ -3661,21 +3670,23 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
mii = device_get_softc(sc->dc_miibus);
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
#ifdef SRM_MEDIA
DC_LOCK(sc);
if (sc->dc_srm_media)
sc->dc_srm_media = 0;
DC_UNLOCK(sc);
#endif
break;
case SIOCSIFCAP:
DC_LOCK(sc);
ifp->if_capenable &= ~IFCAP_POLLING;
ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING;
DC_UNLOCK(sc);
break;
default:
error = ether_ioctl(ifp, command, data);
break;
}
DC_UNLOCK(sc);
return (error);
}
@ -3693,10 +3704,10 @@ dc_watchdog(struct ifnet *ifp)
dc_stop(sc);
dc_reset(sc);
dc_init(sc);
dc_init_locked(sc);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
dc_start(ifp);
dc_start_locked(ifp);
DC_UNLOCK(sc);
}
@ -3714,7 +3725,7 @@ dc_stop(struct dc_softc *sc)
int i;
u_int32_t ctl;
DC_LOCK(sc);
DC_LOCK_ASSERT(sc);
ifp = sc->dc_ifp;
ifp->if_timer = 0;
@ -3762,8 +3773,6 @@ dc_stop(struct dc_softc *sc)
}
}
bzero(&ld->dc_tx_list, sizeof(ld->dc_tx_list));
DC_UNLOCK(sc);
}
/*
@ -3775,15 +3784,13 @@ static int
dc_suspend(device_t dev)
{
struct dc_softc *sc;
int s;
s = splimp();
sc = device_get_softc(dev);
DC_LOCK(sc);
dc_stop(sc);
sc->suspended = 1;
DC_UNLOCK(sc);
splx(s);
return (0);
}
@ -3797,20 +3804,18 @@ dc_resume(device_t dev)
{
struct dc_softc *sc;
struct ifnet *ifp;
int s;
s = splimp();
sc = device_get_softc(dev);
ifp = sc->dc_ifp;
/* reinitialize interface if necessary */
DC_LOCK(sc);
if (ifp->if_flags & IFF_UP)
dc_init(sc);
dc_init_locked(sc);
sc->suspended = 0;
DC_UNLOCK(sc);
splx(s);
return (0);
}
@ -3825,5 +3830,7 @@ dc_shutdown(device_t dev)
sc = device_get_softc(dev);
DC_LOCK(sc);
dc_stop(sc);
DC_UNLOCK(sc);
}

View File

@ -235,8 +235,10 @@ static void dc_tick(void *);
static void dc_tx_underrun(struct dc_softc *);
static void dc_intr(void *);
static void dc_start(struct ifnet *);
static void dc_start_locked(struct ifnet *);
static int dc_ioctl(struct ifnet *, u_long, caddr_t);
static void dc_init(void *);
static void dc_init_locked(struct dc_softc *);
static void dc_stop(struct dc_softc *);
static void dc_watchdog(struct ifnet *);
static void dc_shutdown(device_t);
@ -343,8 +345,6 @@ DRIVER_MODULE(miibus, dc, miibus_driver, miibus_devclass, 0, 0);
#define SIO_SET(x) DC_SETBIT(sc, DC_SIO, (x))
#define SIO_CLR(x) DC_CLRBIT(sc, DC_SIO, (x))
#define IS_MPSAFE 0
static void
dc_delay(struct dc_softc *sc)
{
@ -670,8 +670,6 @@ dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame)
{
int i, ack;
DC_LOCK(sc);
/*
* Set up frame for RX.
*/
@ -724,8 +722,6 @@ dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame)
dc_mii_writebit(sc, 0);
dc_mii_writebit(sc, 0);
DC_UNLOCK(sc);
if (ack)
return (1);
return (0);
@ -738,7 +734,6 @@ static int
dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame)
{
DC_LOCK(sc);
/*
* Set up frame for TX.
*/
@ -763,8 +758,6 @@ dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame)
dc_mii_writebit(sc, 0);
dc_mii_writebit(sc, 0);
DC_UNLOCK(sc);
return (0);
}
@ -1844,7 +1837,7 @@ dc_attach(device_t dev)
sc = device_get_softc(dev);
mtx_init(&sc->dc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF | MTX_RECURSE);
MTX_DEF);
/*
* Map control/status registers.
@ -2194,8 +2187,6 @@ dc_attach(device_t dev)
/* XXX: bleah, MTU gets overwritten in ether_ifattach() */
ifp->if_mtu = ETHERMTU;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
if (!IS_MPSAFE)
ifp->if_flags |= IFF_NEEDSGIANT;
ifp->if_ioctl = dc_ioctl;
ifp->if_start = dc_start;
ifp->if_watchdog = dc_watchdog;
@ -2276,7 +2267,7 @@ dc_attach(device_t dev)
#endif
ifp->if_capenable = ifp->if_capabilities;
callout_init(&sc->dc_stat_ch, IS_MPSAFE ? CALLOUT_MPSAFE : 0);
callout_init_mtx(&sc->dc_stat_ch, &sc->dc_mtx, 0);
#ifdef SRM_MEDIA
sc->dc_srm_media = 0;
@ -2310,8 +2301,7 @@ dc_attach(device_t dev)
ether_ifattach(ifp, eaddr);
/* Hook interrupt last to avoid having to lock softc */
error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET |
(IS_MPSAFE ? INTR_MPSAFE : 0),
error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET | INTR_MPSAFE,
dc_intr, sc, &sc->dc_intrhand);
if (error) {
@ -2344,13 +2334,15 @@ dc_detach(device_t dev)
sc = device_get_softc(dev);
KASSERT(mtx_initialized(&sc->dc_mtx), ("dc mutex not initialized"));
DC_LOCK(sc);
ifp = sc->dc_ifp;
/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
DC_LOCK(sc);
dc_stop(sc);
DC_UNLOCK(sc);
callout_drain(&sc->dc_stat_ch);
ether_ifdetach(ifp);
if_free(ifp);
}
@ -2390,7 +2382,6 @@ dc_detach(device_t dev)
}
free(sc->dc_srom, M_DEVBUF);
DC_UNLOCK(sc);
mtx_destroy(&sc->dc_mtx);
return (0);
@ -2751,7 +2742,7 @@ dc_rxeof(struct dc_softc *sc)
DC_INC(i, DC_RX_LIST_CNT);
continue;
} else {
dc_init(sc);
dc_init_locked(sc);
return;
}
}
@ -2879,7 +2870,7 @@ dc_txeof(struct dc_softc *sc)
if (txstat & DC_TXSTAT_LATECOLL)
ifp->if_collisions++;
if (!(txstat & DC_TXSTAT_UNDERRUN)) {
dc_init(sc);
dc_init_locked(sc);
return;
}
}
@ -2918,7 +2909,7 @@ dc_tick(void *xsc)
u_int32_t r;
sc = xsc;
DC_LOCK(sc);
DC_LOCK_ASSERT(sc);
ifp = sc->dc_ifp;
mii = device_get_softc(sc->dc_miibus);
@ -2972,15 +2963,13 @@ dc_tick(void *xsc)
IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
sc->dc_link++;
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
dc_start(ifp);
dc_start_locked(ifp);
}
if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link)
callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc);
else
callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc);
DC_UNLOCK(sc);
}
/*
@ -2994,7 +2983,7 @@ dc_tx_underrun(struct dc_softc *sc)
int i;
if (DC_IS_DAVICOM(sc))
dc_init(sc);
dc_init_locked(sc);
if (DC_IS_INTEL(sc)) {
/*
@ -3013,7 +3002,7 @@ dc_tx_underrun(struct dc_softc *sc)
if (i == DC_TIMEOUT) {
if_printf(sc->dc_ifp,
"failed to force tx to idle state\n");
dc_init(sc);
dc_init_locked(sc);
}
}
@ -3055,7 +3044,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
dc_txeof(sc);
if (!IFQ_IS_EMPTY(&ifp->if_snd) &&
!(ifp->if_drv_flags & IFF_DRV_OACTIVE))
dc_start(ifp);
dc_start_locked(ifp);
if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */
u_int32_t status;
@ -3088,7 +3077,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
if (status & DC_ISR_BUS_ERR) {
if_printf(ifp, "dc_poll: bus error\n");
dc_reset(sc);
dc_init(sc);
dc_init_locked(sc);
}
}
DC_UNLOCK(sc);
@ -3175,7 +3164,7 @@ dc_intr(void *arg)
if (status & DC_ISR_BUS_ERR) {
dc_reset(sc);
dc_init(sc);
dc_init_locked(sc);
}
}
@ -3183,7 +3172,7 @@ dc_intr(void *arg)
CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
dc_start(ifp);
dc_start_locked(ifp);
#ifdef DEVICE_POLLING
done:
@ -3310,6 +3299,17 @@ dc_encap(struct dc_softc *sc, struct mbuf **m_head)
static void
dc_start(struct ifnet *ifp)
{
struct dc_softc *sc;
sc = ifp->if_softc;
DC_LOCK(sc);
dc_start_locked(ifp);
DC_UNLOCK(sc);
}
static void
dc_start_locked(struct ifnet *ifp)
{
struct dc_softc *sc;
struct mbuf *m_head = NULL, *m;
@ -3318,17 +3318,13 @@ dc_start(struct ifnet *ifp)
sc = ifp->if_softc;
DC_LOCK(sc);
DC_LOCK_ASSERT(sc);
if (!sc->dc_link && ifp->if_snd.ifq_len < 10) {
DC_UNLOCK(sc);
if (!sc->dc_link && ifp->if_snd.ifq_len < 10)
return;
}
if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
DC_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
return;
}
idx = sc->dc_cdata.dc_tx_first = sc->dc_cdata.dc_tx_prod;
@ -3380,18 +3376,37 @@ dc_start(struct ifnet *ifp)
*/
ifp->if_timer = 5;
}
DC_UNLOCK(sc);
}
static void
dc_init(void *xsc)
{
struct dc_softc *sc = xsc;
DC_LOCK(sc);
dc_init_locked(sc);
#ifdef SRM_MEDIA
if(sc->dc_srm_media) {
struct ifreq ifr;
struct mii_data *mii;
ifr.ifr_media = sc->dc_srm_media;
sc->dc_srm_media = 0;
DC_UNLOCK(sc);
mii = device_get_softc(sc->dc_miibus);
ifmedia_ioctl(sc->dc_ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA);
} else
#endif
DC_UNLOCK(sc);
}
static void
dc_init_locked(struct dc_softc *sc)
{
struct ifnet *ifp = sc->dc_ifp;
struct mii_data *mii;
DC_LOCK(sc);
DC_LOCK_ASSERT(sc);
mii = device_get_softc(sc->dc_miibus);
@ -3487,7 +3502,6 @@ dc_init(void *xsc)
if_printf(ifp,
"initialization failed: no memory for rx buffers\n");
dc_stop(sc);
DC_UNLOCK(sc);
return;
}
@ -3559,17 +3573,6 @@ dc_init(void *xsc)
else
callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc);
}
#ifdef SRM_MEDIA
if(sc->dc_srm_media) {
struct ifreq ifr;
ifr.ifr_media = sc->dc_srm_media;
ifmedia_ioctl(ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA);
sc->dc_srm_media = 0;
}
#endif
DC_UNLOCK(sc);
}
/*
@ -3584,6 +3587,7 @@ dc_ifmedia_upd(struct ifnet *ifp)
sc = ifp->if_softc;
mii = device_get_softc(sc->dc_miibus);
DC_LOCK(sc);
mii_mediachg(mii);
ifm = &mii->mii_media;
@ -3592,6 +3596,7 @@ dc_ifmedia_upd(struct ifnet *ifp)
dc_setcfg(sc, ifm->ifm_media);
else
sc->dc_link = 0;
DC_UNLOCK(sc);
return (0);
}
@ -3608,6 +3613,7 @@ dc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
sc = ifp->if_softc;
mii = device_get_softc(sc->dc_miibus);
DC_LOCK(sc);
mii_pollstat(mii);
ifm = &mii->mii_media;
if (DC_IS_DAVICOM(sc)) {
@ -3619,6 +3625,7 @@ dc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
}
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
DC_UNLOCK(sc);
}
static int
@ -3629,10 +3636,9 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
struct mii_data *mii;
int error = 0;
DC_LOCK(sc);
switch (command) {
case SIOCSIFFLAGS:
DC_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
int need_setfilt = (ifp->if_flags ^ sc->dc_if_flags) &
(IFF_PROMISC | IFF_ALLMULTI);
@ -3642,18 +3648,21 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
dc_setfilt(sc);
} else {
sc->dc_txthresh = 0;
dc_init(sc);
dc_init_locked(sc);
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
dc_stop(sc);
}
sc->dc_if_flags = ifp->if_flags;
DC_UNLOCK(sc);
error = 0;
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
DC_LOCK(sc);
dc_setfilt(sc);
DC_UNLOCK(sc);
error = 0;
break;
case SIOCGIFMEDIA:
@ -3661,21 +3670,23 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
mii = device_get_softc(sc->dc_miibus);
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
#ifdef SRM_MEDIA
DC_LOCK(sc);
if (sc->dc_srm_media)
sc->dc_srm_media = 0;
DC_UNLOCK(sc);
#endif
break;
case SIOCSIFCAP:
DC_LOCK(sc);
ifp->if_capenable &= ~IFCAP_POLLING;
ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING;
DC_UNLOCK(sc);
break;
default:
error = ether_ioctl(ifp, command, data);
break;
}
DC_UNLOCK(sc);
return (error);
}
@ -3693,10 +3704,10 @@ dc_watchdog(struct ifnet *ifp)
dc_stop(sc);
dc_reset(sc);
dc_init(sc);
dc_init_locked(sc);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
dc_start(ifp);
dc_start_locked(ifp);
DC_UNLOCK(sc);
}
@ -3714,7 +3725,7 @@ dc_stop(struct dc_softc *sc)
int i;
u_int32_t ctl;
DC_LOCK(sc);
DC_LOCK_ASSERT(sc);
ifp = sc->dc_ifp;
ifp->if_timer = 0;
@ -3762,8 +3773,6 @@ dc_stop(struct dc_softc *sc)
}
}
bzero(&ld->dc_tx_list, sizeof(ld->dc_tx_list));
DC_UNLOCK(sc);
}
/*
@ -3775,15 +3784,13 @@ static int
dc_suspend(device_t dev)
{
struct dc_softc *sc;
int s;
s = splimp();
sc = device_get_softc(dev);
DC_LOCK(sc);
dc_stop(sc);
sc->suspended = 1;
DC_UNLOCK(sc);
splx(s);
return (0);
}
@ -3797,20 +3804,18 @@ dc_resume(device_t dev)
{
struct dc_softc *sc;
struct ifnet *ifp;
int s;
s = splimp();
sc = device_get_softc(dev);
ifp = sc->dc_ifp;
/* reinitialize interface if necessary */
DC_LOCK(sc);
if (ifp->if_flags & IFF_UP)
dc_init(sc);
dc_init_locked(sc);
sc->suspended = 0;
DC_UNLOCK(sc);
splx(s);
return (0);
}
@ -3825,5 +3830,7 @@ dc_shutdown(device_t dev)
sc = device_get_softc(dev);
DC_LOCK(sc);
dc_stop(sc);
DC_UNLOCK(sc);
}