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:
parent
99030e6c12
commit
c8b27aca43
@ -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);
|
||||
}
|
||||
|
147
sys/pci/if_dc.c
147
sys/pci/if_dc.c
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user