MFC: Fix up locking and mark MPSAFE.
Approved by: re (scottl)
This commit is contained in:
parent
2bcd5cdce1
commit
e878090f8a
213
sys/pci/if_dc.c
213
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);
|
||||
}
|
||||
|
||||
@ -864,8 +857,8 @@ dc_miibus_readreg(device_t dev, int phy, int reg)
|
||||
phy_reg = DC_AL_ANER;
|
||||
break;
|
||||
default:
|
||||
printf("dc%d: phy_read: bad phy register %x\n",
|
||||
sc->dc_unit, reg);
|
||||
device_printf(dev, "phy_read: bad phy register %x\n",
|
||||
reg);
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
@ -940,8 +933,8 @@ dc_miibus_writereg(device_t dev, int phy, int reg, int data)
|
||||
phy_reg = DC_AL_ANER;
|
||||
break;
|
||||
default:
|
||||
printf("dc%d: phy_write: bad phy register %x\n",
|
||||
sc->dc_unit, reg);
|
||||
device_printf(dev, "phy_write: bad phy register %x\n",
|
||||
reg);
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
@ -1388,8 +1381,8 @@ dc_setcfg(struct dc_softc *sc, int media)
|
||||
}
|
||||
|
||||
if (i == DC_TIMEOUT)
|
||||
printf("dc%d: failed to force tx and "
|
||||
"rx to idle state\n", sc->dc_unit);
|
||||
if_printf(sc->dc_ifp,
|
||||
"failed to force tx and rx to idle state\n");
|
||||
}
|
||||
|
||||
if (IFM_SUBTYPE(media) == IFM_100_TX) {
|
||||
@ -1529,7 +1522,7 @@ dc_reset(struct dc_softc *sc)
|
||||
}
|
||||
|
||||
if (i == DC_TIMEOUT)
|
||||
printf("dc%d: reset never completed!\n", sc->dc_unit);
|
||||
if_printf(sc->dc_ifp, "reset never completed!\n");
|
||||
|
||||
/* Wait a little while for the chip to get its brains in order. */
|
||||
DELAY(1000);
|
||||
@ -1837,15 +1830,14 @@ dc_attach(device_t dev)
|
||||
struct dc_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
u_int32_t revision;
|
||||
int unit, error = 0, rid, mac_offset;
|
||||
int error = 0, rid, mac_offset;
|
||||
int i;
|
||||
u_int8_t *mac;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
unit = device_get_unit(dev);
|
||||
|
||||
mtx_init(&sc->dc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
|
||||
MTX_DEF | MTX_RECURSE);
|
||||
MTX_DEF);
|
||||
|
||||
/*
|
||||
* Map control/status registers.
|
||||
@ -1856,7 +1848,7 @@ dc_attach(device_t dev)
|
||||
sc->dc_res = bus_alloc_resource_any(dev, DC_RES, &rid, RF_ACTIVE);
|
||||
|
||||
if (sc->dc_res == NULL) {
|
||||
printf("dc%d: couldn't map ports/memory\n", unit);
|
||||
device_printf(dev, "couldn't map ports/memory\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
@ -1870,7 +1862,7 @@ dc_attach(device_t dev)
|
||||
RF_SHAREABLE | RF_ACTIVE);
|
||||
|
||||
if (sc->dc_irq == NULL) {
|
||||
printf("dc%d: couldn't map interrupt\n", unit);
|
||||
device_printf(dev, "couldn't map interrupt\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
@ -2001,8 +1993,7 @@ dc_attach(device_t dev)
|
||||
dc_read_srom(sc, sc->dc_romwidth);
|
||||
break;
|
||||
default:
|
||||
printf("dc%d: unknown device: %x\n", sc->dc_unit,
|
||||
sc->dc_info->dc_did);
|
||||
device_printf(dev, "unknown device: %x\n", sc->dc_info->dc_did);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2097,21 +2088,19 @@ dc_attach(device_t dev)
|
||||
break;
|
||||
}
|
||||
|
||||
sc->dc_unit = unit;
|
||||
|
||||
/* Allocate a busdma tag and DMA safe memory for TX/RX descriptors. */
|
||||
error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, BUS_SPACE_MAXADDR_32BIT,
|
||||
BUS_SPACE_MAXADDR, NULL, NULL, sizeof(struct dc_list_data), 1,
|
||||
sizeof(struct dc_list_data), 0, NULL, NULL, &sc->dc_ltag);
|
||||
if (error) {
|
||||
printf("dc%d: failed to allocate busdma tag\n", unit);
|
||||
device_printf(dev, "failed to allocate busdma tag\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
error = bus_dmamem_alloc(sc->dc_ltag, (void **)&sc->dc_ldata,
|
||||
BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sc->dc_lmap);
|
||||
if (error) {
|
||||
printf("dc%d: failed to allocate DMA safe memory\n", unit);
|
||||
device_printf(dev, "failed to allocate DMA safe memory\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
@ -2119,7 +2108,7 @@ dc_attach(device_t dev)
|
||||
sizeof(struct dc_list_data), dc_dma_map_addr, &sc->dc_laddr,
|
||||
BUS_DMA_NOWAIT);
|
||||
if (error) {
|
||||
printf("dc%d: cannot get address of the descriptors\n", unit);
|
||||
device_printf(dev, "cannot get address of the descriptors\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
@ -2132,21 +2121,21 @@ dc_attach(device_t dev)
|
||||
BUS_SPACE_MAXADDR, NULL, NULL, DC_SFRAME_LEN + DC_MIN_FRAMELEN, 1,
|
||||
DC_SFRAME_LEN + DC_MIN_FRAMELEN, 0, NULL, NULL, &sc->dc_stag);
|
||||
if (error) {
|
||||
printf("dc%d: failed to allocate busdma tag\n", unit);
|
||||
device_printf(dev, "failed to allocate busdma tag\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
error = bus_dmamem_alloc(sc->dc_stag, (void **)&sc->dc_cdata.dc_sbuf,
|
||||
BUS_DMA_NOWAIT, &sc->dc_smap);
|
||||
if (error) {
|
||||
printf("dc%d: failed to allocate DMA safe memory\n", unit);
|
||||
device_printf(dev, "failed to allocate DMA safe memory\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
error = bus_dmamap_load(sc->dc_stag, sc->dc_smap, sc->dc_cdata.dc_sbuf,
|
||||
DC_SFRAME_LEN, dc_dma_map_addr, &sc->dc_saddr, BUS_DMA_NOWAIT);
|
||||
if (error) {
|
||||
printf("dc%d: cannot get address of the descriptors\n", unit);
|
||||
device_printf(dev, "cannot get address of the descriptors\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
@ -2156,7 +2145,7 @@ dc_attach(device_t dev)
|
||||
BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, DC_TX_LIST_CNT, MCLBYTES,
|
||||
0, NULL, NULL, &sc->dc_mtag);
|
||||
if (error) {
|
||||
printf("dc%d: failed to allocate busdma tag\n", unit);
|
||||
device_printf(dev, "failed to allocate busdma tag\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
@ -2166,7 +2155,7 @@ dc_attach(device_t dev)
|
||||
error = bus_dmamap_create(sc->dc_mtag, 0,
|
||||
&sc->dc_cdata.dc_tx_map[i]);
|
||||
if (error) {
|
||||
printf("dc%d: failed to init TX ring\n", unit);
|
||||
device_printf(dev, "failed to init TX ring\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
@ -2175,21 +2164,21 @@ dc_attach(device_t dev)
|
||||
error = bus_dmamap_create(sc->dc_mtag, 0,
|
||||
&sc->dc_cdata.dc_rx_map[i]);
|
||||
if (error) {
|
||||
printf("dc%d: failed to init RX ring\n", unit);
|
||||
device_printf(dev, "failed to init RX ring\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
error = bus_dmamap_create(sc->dc_mtag, 0, &sc->dc_sparemap);
|
||||
if (error) {
|
||||
printf("dc%d: failed to init RX ring\n", unit);
|
||||
device_printf(dev, "failed to init RX ring\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ifp = sc->dc_ifp = if_alloc(IFT_ETHER);
|
||||
if (ifp == NULL) {
|
||||
printf("dc%d: can not if_alloc()\n", unit);
|
||||
device_printf(dev, "can not if_alloc()\n");
|
||||
error = ENOSPC;
|
||||
goto fail;
|
||||
}
|
||||
@ -2198,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;
|
||||
@ -2259,7 +2246,7 @@ dc_attach(device_t dev)
|
||||
}
|
||||
|
||||
if (error) {
|
||||
printf("dc%d: MII without any PHY!\n", sc->dc_unit);
|
||||
device_printf(dev, "MII without any PHY!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -2280,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;
|
||||
@ -2314,12 +2301,11 @@ 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) {
|
||||
printf("dc%d: couldn't set up irq\n", unit);
|
||||
device_printf(dev, "couldn't set up irq\n");
|
||||
ether_ifdetach(ifp);
|
||||
if_free(ifp);
|
||||
goto fail;
|
||||
@ -2348,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);
|
||||
}
|
||||
@ -2394,7 +2382,6 @@ dc_detach(device_t dev)
|
||||
}
|
||||
free(sc->dc_srom, M_DEVBUF);
|
||||
|
||||
DC_UNLOCK(sc);
|
||||
mtx_destroy(&sc->dc_mtx);
|
||||
|
||||
return (0);
|
||||
@ -2755,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;
|
||||
}
|
||||
}
|
||||
@ -2883,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;
|
||||
}
|
||||
}
|
||||
@ -2922,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);
|
||||
|
||||
@ -2976,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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2998,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)) {
|
||||
/*
|
||||
@ -3015,13 +3000,13 @@ dc_tx_underrun(struct dc_softc *sc)
|
||||
DELAY(10);
|
||||
}
|
||||
if (i == DC_TIMEOUT) {
|
||||
printf("dc%d: failed to force tx to idle state\n",
|
||||
sc->dc_unit);
|
||||
dc_init(sc);
|
||||
if_printf(sc->dc_ifp,
|
||||
"failed to force tx to idle state\n");
|
||||
dc_init_locked(sc);
|
||||
}
|
||||
}
|
||||
|
||||
printf("dc%d: TX underrun -- ", sc->dc_unit);
|
||||
if_printf(sc->dc_ifp, "TX underrun -- ");
|
||||
sc->dc_txthresh += DC_TXTHRESH_INC;
|
||||
if (sc->dc_txthresh > DC_TXTHRESH_MAX) {
|
||||
printf("using store and forward mode\n");
|
||||
@ -3059,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;
|
||||
@ -3090,9 +3075,9 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
|
||||
dc_tx_underrun(sc);
|
||||
|
||||
if (status & DC_ISR_BUS_ERR) {
|
||||
printf("dc_poll: dc%d bus error\n", sc->dc_unit);
|
||||
if_printf(ifp, "dc_poll: bus error\n");
|
||||
dc_reset(sc);
|
||||
dc_init(sc);
|
||||
dc_init_locked(sc);
|
||||
}
|
||||
}
|
||||
DC_UNLOCK(sc);
|
||||
@ -3179,7 +3164,7 @@ dc_intr(void *arg)
|
||||
|
||||
if (status & DC_ISR_BUS_ERR) {
|
||||
dc_reset(sc);
|
||||
dc_init(sc);
|
||||
dc_init_locked(sc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3187,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:
|
||||
@ -3314,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;
|
||||
@ -3322,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;
|
||||
|
||||
@ -3384,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);
|
||||
|
||||
@ -3488,10 +3499,9 @@ dc_init(void *xsc)
|
||||
|
||||
/* Init circular RX list. */
|
||||
if (dc_list_rx_init(sc) == ENOBUFS) {
|
||||
printf("dc%d: initialization failed: no "
|
||||
"memory for rx buffers\n", sc->dc_unit);
|
||||
if_printf(ifp,
|
||||
"initialization failed: no memory for rx buffers\n");
|
||||
dc_stop(sc);
|
||||
DC_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3563,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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3588,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;
|
||||
|
||||
@ -3596,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);
|
||||
}
|
||||
@ -3612,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)) {
|
||||
@ -3623,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
|
||||
@ -3633,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);
|
||||
@ -3646,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:
|
||||
@ -3665,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,14 +3700,14 @@ dc_watchdog(struct ifnet *ifp)
|
||||
DC_LOCK(sc);
|
||||
|
||||
ifp->if_oerrors++;
|
||||
printf("dc%d: watchdog timeout\n", sc->dc_unit);
|
||||
if_printf(ifp, "watchdog timeout\n");
|
||||
|
||||
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);
|
||||
}
|
||||
@ -3718,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;
|
||||
@ -3766,8 +3773,6 @@ dc_stop(struct dc_softc *sc)
|
||||
}
|
||||
}
|
||||
bzero(&ld->dc_tx_list, sizeof(ld->dc_tx_list));
|
||||
|
||||
DC_UNLOCK(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3779,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);
|
||||
}
|
||||
|
||||
@ -3801,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);
|
||||
}
|
||||
|
||||
@ -3829,5 +3830,7 @@ dc_shutdown(device_t dev)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
DC_LOCK(sc);
|
||||
dc_stop(sc);
|
||||
DC_UNLOCK(sc);
|
||||
}
|
||||
|
@ -732,7 +732,6 @@ struct dc_softc {
|
||||
struct resource *dc_res;
|
||||
struct dc_type *dc_info; /* adapter info */
|
||||
device_t dc_miibus;
|
||||
u_int8_t dc_unit; /* interface number */
|
||||
u_int8_t dc_type;
|
||||
u_int8_t dc_pmode;
|
||||
u_int8_t dc_link;
|
||||
|
170
sys/pci/if_sf.c
170
sys/pci/if_sf.c
@ -137,12 +137,15 @@ static void sf_txeof(struct sf_softc *);
|
||||
static int sf_encap(struct sf_softc *, struct sf_tx_bufdesc_type0 *,
|
||||
struct mbuf *);
|
||||
static void sf_start(struct ifnet *);
|
||||
static void sf_start_locked(struct ifnet *);
|
||||
static int sf_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void sf_init(void *);
|
||||
static void sf_init_locked(struct sf_softc *);
|
||||
static void sf_stop(struct sf_softc *);
|
||||
static void sf_watchdog(struct ifnet *);
|
||||
static void sf_shutdown(device_t);
|
||||
static int sf_ifmedia_upd(struct ifnet *);
|
||||
static void sf_ifmedia_upd_locked(struct ifnet *);
|
||||
static void sf_ifmedia_sts(struct ifnet *, struct ifmediareq *);
|
||||
static void sf_reset(struct sf_softc *);
|
||||
static int sf_init_rx_ring(struct sf_softc *);
|
||||
@ -462,10 +465,25 @@ sf_ifmedia_upd(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
SF_LOCK(sc);
|
||||
sf_ifmedia_upd_locked(ifp);
|
||||
SF_UNLOCK(sc);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void
|
||||
sf_ifmedia_upd_locked(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
struct mii_data *mii;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
SF_LOCK_ASSERT(sc);
|
||||
sc->sf_link = 0;
|
||||
if (mii->mii_instance) {
|
||||
struct mii_softc *miisc;
|
||||
@ -473,8 +491,6 @@ sf_ifmedia_upd(ifp)
|
||||
mii_phy_reset(miisc);
|
||||
}
|
||||
mii_mediachg(mii);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -489,11 +505,13 @@ sf_ifmedia_sts(ifp, ifmr)
|
||||
struct mii_data *mii;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
SF_LOCK(sc);
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
|
||||
mii_pollstat(mii);
|
||||
ifmr->ifm_active = mii->mii_media_active;
|
||||
ifmr->ifm_status = mii->mii_media_status;
|
||||
SF_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -507,10 +525,9 @@ sf_ioctl(ifp, command, data)
|
||||
struct mii_data *mii;
|
||||
int error = 0;
|
||||
|
||||
SF_LOCK(sc);
|
||||
|
||||
switch(command) {
|
||||
case SIOCSIFFLAGS:
|
||||
SF_LOCK(sc);
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
|
||||
ifp->if_flags & IFF_PROMISC &&
|
||||
@ -521,17 +538,20 @@ sf_ioctl(ifp, command, data)
|
||||
sc->sf_if_flags & IFF_PROMISC) {
|
||||
SF_CLRBIT(sc, SF_RXFILT, SF_RXFILT_PROMISC);
|
||||
} else if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
|
||||
sf_init(sc);
|
||||
sf_init_locked(sc);
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
sf_stop(sc);
|
||||
}
|
||||
sc->sf_if_flags = ifp->if_flags;
|
||||
SF_UNLOCK(sc);
|
||||
error = 0;
|
||||
break;
|
||||
case SIOCADDMULTI:
|
||||
case SIOCDELMULTI:
|
||||
SF_LOCK(sc);
|
||||
sf_setmulti(sc);
|
||||
SF_UNLOCK(sc);
|
||||
error = 0;
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
@ -540,16 +560,16 @@ sf_ioctl(ifp, command, data)
|
||||
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
|
||||
break;
|
||||
case SIOCSIFCAP:
|
||||
SF_LOCK(sc);
|
||||
ifp->if_capenable &= ~IFCAP_POLLING;
|
||||
ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING;
|
||||
SF_UNLOCK(sc);
|
||||
break;
|
||||
default:
|
||||
error = ether_ioctl(ifp, command, data);
|
||||
break;
|
||||
}
|
||||
|
||||
SF_UNLOCK(sc);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
@ -573,7 +593,7 @@ sf_reset(sc)
|
||||
}
|
||||
|
||||
if (i == SF_TIMEOUT)
|
||||
printf("sf%d: reset never completed!\n", sc->sf_unit);
|
||||
if_printf(sc->sf_ifp, "reset never completed!\n");
|
||||
|
||||
/* Wait a little while for the chip to get its brains in order. */
|
||||
DELAY(1000);
|
||||
@ -643,14 +663,13 @@ sf_attach(dev)
|
||||
int i;
|
||||
struct sf_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
int unit, rid, error = 0;
|
||||
int rid, error = 0;
|
||||
u_char eaddr[6];
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
unit = device_get_unit(dev);
|
||||
|
||||
mtx_init(&sc->sf_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
|
||||
MTX_DEF | MTX_RECURSE);
|
||||
MTX_DEF);
|
||||
/*
|
||||
* Map control/status registers.
|
||||
*/
|
||||
@ -660,7 +679,7 @@ sf_attach(dev)
|
||||
sc->sf_res = bus_alloc_resource_any(dev, SF_RES, &rid, RF_ACTIVE);
|
||||
|
||||
if (sc->sf_res == NULL) {
|
||||
printf ("sf%d: couldn't map ports\n", unit);
|
||||
device_printf(dev, "couldn't map ports\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
@ -674,12 +693,13 @@ sf_attach(dev)
|
||||
RF_SHAREABLE | RF_ACTIVE);
|
||||
|
||||
if (sc->sf_irq == NULL) {
|
||||
printf("sf%d: couldn't map interrupt\n", unit);
|
||||
device_printf(dev, "couldn't map interrupt\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
callout_handle_init(&sc->sf_stat_ch);
|
||||
callout_init_mtx(&sc->sf_stat_callout, &sc->sf_mtx, 0);
|
||||
|
||||
/* Reset the adapter. */
|
||||
sf_reset(sc);
|
||||
|
||||
@ -690,14 +710,12 @@ sf_attach(dev)
|
||||
eaddr[i] =
|
||||
sf_read_eeprom(sc, SF_EE_NODEADDR + ETHER_ADDR_LEN - i);
|
||||
|
||||
sc->sf_unit = unit;
|
||||
|
||||
/* Allocate the descriptor queues. */
|
||||
sc->sf_ldata = contigmalloc(sizeof(struct sf_list_data), M_DEVBUF,
|
||||
M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0);
|
||||
|
||||
if (sc->sf_ldata == NULL) {
|
||||
printf("sf%d: no memory for list buffers!\n", unit);
|
||||
device_printf(dev, "no memory for list buffers!\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
@ -706,7 +724,7 @@ sf_attach(dev)
|
||||
|
||||
ifp = sc->sf_ifp = if_alloc(IFT_ETHER);
|
||||
if (ifp == NULL) {
|
||||
printf("sf%d: can not if_alloc()\n", sc->sf_unit);
|
||||
device_printf(dev, "can not if_alloc()\n");
|
||||
error = ENOSPC;
|
||||
goto fail;
|
||||
}
|
||||
@ -714,7 +732,7 @@ sf_attach(dev)
|
||||
/* Do MII setup. */
|
||||
if (mii_phy_probe(dev, &sc->sf_miibus,
|
||||
sf_ifmedia_upd, sf_ifmedia_sts)) {
|
||||
printf("sf%d: MII without any phy!\n", sc->sf_unit);
|
||||
device_printf(dev, "MII without any phy!\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
@ -722,8 +740,7 @@ sf_attach(dev)
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
|
||||
ifp->if_mtu = ETHERMTU;
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
|
||||
IFF_NEEDSGIANT;
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
ifp->if_ioctl = sf_ioctl;
|
||||
ifp->if_start = sf_start;
|
||||
ifp->if_watchdog = sf_watchdog;
|
||||
@ -743,11 +760,11 @@ sf_attach(dev)
|
||||
ether_ifattach(ifp, eaddr);
|
||||
|
||||
/* Hook interrupt last to avoid having to lock softc */
|
||||
error = bus_setup_intr(dev, sc->sf_irq, INTR_TYPE_NET,
|
||||
error = bus_setup_intr(dev, sc->sf_irq, INTR_TYPE_NET | INTR_MPSAFE,
|
||||
sf_intr, sc, &sc->sf_intrhand);
|
||||
|
||||
if (error) {
|
||||
printf("sf%d: couldn't set up irq\n", unit);
|
||||
device_printf(dev, "couldn't set up irq\n");
|
||||
ether_ifdetach(ifp);
|
||||
if_free(ifp);
|
||||
goto fail;
|
||||
@ -776,12 +793,14 @@ sf_detach(dev)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
KASSERT(mtx_initialized(&sc->sf_mtx), ("sf mutex not initialized"));
|
||||
SF_LOCK(sc);
|
||||
ifp = sc->sf_ifp;
|
||||
|
||||
/* These should only be active if attach succeeded */
|
||||
if (device_is_attached(dev)) {
|
||||
SF_LOCK(sc);
|
||||
sf_stop(sc);
|
||||
SF_UNLOCK(sc);
|
||||
callout_drain(&sc->sf_stat_callout);
|
||||
ether_ifdetach(ifp);
|
||||
if_free(ifp);
|
||||
}
|
||||
@ -799,7 +818,6 @@ sf_detach(dev)
|
||||
if (sc->sf_ldata)
|
||||
contigfree(sc->sf_ldata, sizeof(struct sf_list_data), M_DEVBUF);
|
||||
|
||||
SF_UNLOCK(sc);
|
||||
mtx_destroy(&sc->sf_mtx);
|
||||
|
||||
return(0);
|
||||
@ -987,6 +1005,7 @@ sf_txeof(sc)
|
||||
|
||||
ifp = sc->sf_ifp;
|
||||
|
||||
SF_LOCK_ASSERT(sc);
|
||||
txcons = csr_read_4(sc, SF_CQ_CONSIDX);
|
||||
cmpprodidx = SF_IDX_HI(csr_read_4(sc, SF_CQ_PRODIDX));
|
||||
cmpconsidx = SF_IDX_HI(txcons);
|
||||
@ -1034,9 +1053,9 @@ sf_txthresh_adjust(sc)
|
||||
txfctl &= ~SF_TXFRMCTL_TXTHRESH;
|
||||
txfctl |= txthresh;
|
||||
#ifdef DIAGNOSTIC
|
||||
printf("sf%d: tx underrun, increasing "
|
||||
if_printf(sc->sf_ifp, "tx underrun, increasing "
|
||||
"tx threshold to %d bytes\n",
|
||||
sc->sf_unit, txthresh * 4);
|
||||
txthresh * 4);
|
||||
#endif
|
||||
csr_write_4(sc, SF_TX_FRAMCTL, txfctl);
|
||||
}
|
||||
@ -1075,7 +1094,7 @@ sf_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
|
||||
sf_rxeof(sc);
|
||||
sf_txeof(sc);
|
||||
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
|
||||
sf_start(ifp);
|
||||
sf_start_locked(ifp);
|
||||
|
||||
if (cmd == POLL_AND_CHECK_STATUS) {
|
||||
u_int32_t status;
|
||||
@ -1089,11 +1108,10 @@ sf_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
|
||||
|
||||
if (status & SF_ISR_ABNORMALINTR) {
|
||||
if (status & SF_ISR_STATSOFLOW) {
|
||||
untimeout(sf_stats_update, sc,
|
||||
sc->sf_stat_ch);
|
||||
callout_stop(&sc->sf_stat_callout);
|
||||
sf_stats_update(sc);
|
||||
} else
|
||||
sf_init(sc);
|
||||
sf_init_locked(sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1154,11 +1172,10 @@ sf_intr(arg)
|
||||
|
||||
if (status & SF_ISR_ABNORMALINTR) {
|
||||
if (status & SF_ISR_STATSOFLOW) {
|
||||
untimeout(sf_stats_update, sc,
|
||||
sc->sf_stat_ch);
|
||||
callout_stop(&sc->sf_stat_callout);
|
||||
sf_stats_update(sc);
|
||||
} else
|
||||
sf_init(sc);
|
||||
sf_init_locked(sc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1166,7 +1183,7 @@ sf_intr(arg)
|
||||
csr_write_4(sc, SF_IMR, SF_INTRS);
|
||||
|
||||
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
|
||||
sf_start(ifp);
|
||||
sf_start_locked(ifp);
|
||||
|
||||
#ifdef DEVICE_POLLING
|
||||
done_locked:
|
||||
@ -1179,12 +1196,22 @@ sf_init(xsc)
|
||||
void *xsc;
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
|
||||
sc = xsc;
|
||||
SF_LOCK(sc);
|
||||
sf_init_locked(sc);
|
||||
SF_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
sf_init_locked(sc)
|
||||
struct sf_softc *sc;
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
struct mii_data *mii;
|
||||
int i;
|
||||
|
||||
sc = xsc;
|
||||
SF_LOCK(sc);
|
||||
SF_LOCK_ASSERT(sc);
|
||||
ifp = sc->sf_ifp;
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
|
||||
@ -1207,9 +1234,8 @@ sf_init(xsc)
|
||||
sf_setperf(sc, 0, (caddr_t)&IFP2ENADDR(sc->sf_ifp));
|
||||
|
||||
if (sf_init_rx_ring(sc) == ENOBUFS) {
|
||||
printf("sf%d: initialization failed: no "
|
||||
"memory for rx buffers\n", sc->sf_unit);
|
||||
SF_UNLOCK(sc);
|
||||
if_printf(sc->sf_ifp,
|
||||
"initialization failed: no memory for rx buffers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1284,14 +1310,12 @@ sf_init(xsc)
|
||||
SF_SETBIT(sc, SF_GEN_ETH_CTL, SF_ETHCTL_TX_ENB|SF_ETHCTL_TXDMA_ENB);
|
||||
|
||||
/*mii_mediachg(mii);*/
|
||||
sf_ifmedia_upd(ifp);
|
||||
sf_ifmedia_upd_locked(ifp);
|
||||
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
|
||||
sc->sf_stat_ch = timeout(sf_stats_update, sc, hz);
|
||||
|
||||
SF_UNLOCK(sc);
|
||||
callout_reset(&sc->sf_stat_callout, hz, sf_stats_update, sc);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1324,7 +1348,7 @@ sf_encap(sc, c, m_head)
|
||||
|
||||
MGETHDR(m_new, M_DONTWAIT, MT_DATA);
|
||||
if (m_new == NULL) {
|
||||
printf("sf%d: no memory for tx list\n", sc->sf_unit);
|
||||
if_printf(sc->sf_ifp, "no memory for tx list\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -1332,8 +1356,7 @@ sf_encap(sc, c, m_head)
|
||||
MCLGET(m_new, M_DONTWAIT);
|
||||
if (!(m_new->m_flags & M_EXT)) {
|
||||
m_freem(m_new);
|
||||
printf("sf%d: no memory for tx list\n",
|
||||
sc->sf_unit);
|
||||
if_printf(sc->sf_ifp, "no memory for tx list\n");
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
@ -1363,29 +1386,37 @@ sf_start(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
SF_LOCK(sc);
|
||||
sf_start_locked(ifp);
|
||||
SF_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
sf_start_locked(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
struct sf_tx_bufdesc_type0 *cur_tx = NULL;
|
||||
struct mbuf *m_head = NULL;
|
||||
int i, txprod;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
SF_LOCK(sc);
|
||||
SF_LOCK_ASSERT(sc);
|
||||
|
||||
if (!sc->sf_link && ifp->if_snd.ifq_len < 10) {
|
||||
SF_UNLOCK(sc);
|
||||
if (!sc->sf_link && ifp->if_snd.ifq_len < 10)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
|
||||
SF_UNLOCK(sc);
|
||||
if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
|
||||
return;
|
||||
}
|
||||
|
||||
txprod = csr_read_4(sc, SF_TXDQ_PRODIDX);
|
||||
i = SF_IDX_HI(txprod) >> 4;
|
||||
|
||||
if (sc->sf_ldata->sf_tx_dlist[i].sf_mbuf != NULL) {
|
||||
printf("sf%d: TX ring full, resetting\n", sc->sf_unit);
|
||||
sf_init(sc);
|
||||
if_printf(ifp, "TX ring full, resetting\n");
|
||||
sf_init_locked(sc);
|
||||
txprod = csr_read_4(sc, SF_TXDQ_PRODIDX);
|
||||
i = SF_IDX_HI(txprod) >> 4;
|
||||
}
|
||||
@ -1423,10 +1454,8 @@ sf_start(ifp)
|
||||
break;
|
||||
}
|
||||
|
||||
if (cur_tx == NULL) {
|
||||
SF_UNLOCK(sc);
|
||||
if (cur_tx == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Transmit */
|
||||
csr_write_4(sc, SF_TXDQ_PRODIDX,
|
||||
@ -1434,8 +1463,6 @@ sf_start(ifp)
|
||||
((i << 20) & 0xFFFF0000));
|
||||
|
||||
ifp->if_timer = 5;
|
||||
|
||||
SF_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1445,11 +1472,11 @@ sf_stop(sc)
|
||||
int i;
|
||||
struct ifnet *ifp;
|
||||
|
||||
SF_LOCK(sc);
|
||||
SF_LOCK_ASSERT(sc);
|
||||
|
||||
ifp = sc->sf_ifp;
|
||||
|
||||
untimeout(sf_stats_update, sc, sc->sf_stat_ch);
|
||||
callout_stop(&sc->sf_stat_callout);
|
||||
|
||||
#ifdef DEVICE_POLLING
|
||||
ether_poll_deregister(ifp);
|
||||
@ -1483,7 +1510,6 @@ sf_stop(sc)
|
||||
}
|
||||
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING|IFF_DRV_OACTIVE);
|
||||
SF_UNLOCK(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1505,7 +1531,7 @@ sf_stats_update(xsc)
|
||||
int i;
|
||||
|
||||
sc = xsc;
|
||||
SF_LOCK(sc);
|
||||
SF_LOCK_ASSERT(sc);
|
||||
ifp = sc->sf_ifp;
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
|
||||
@ -1527,12 +1553,10 @@ sf_stats_update(xsc)
|
||||
IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
|
||||
sc->sf_link++;
|
||||
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
|
||||
sf_start(ifp);
|
||||
sf_start_locked(ifp);
|
||||
}
|
||||
|
||||
sc->sf_stat_ch = timeout(sf_stats_update, sc, hz);
|
||||
|
||||
SF_UNLOCK(sc);
|
||||
callout_reset(&sc->sf_stat_callout, hz, sf_stats_update, sc);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1546,14 +1570,14 @@ sf_watchdog(ifp)
|
||||
SF_LOCK(sc);
|
||||
|
||||
ifp->if_oerrors++;
|
||||
printf("sf%d: watchdog timeout\n", sc->sf_unit);
|
||||
if_printf(ifp, "watchdog timeout\n");
|
||||
|
||||
sf_stop(sc);
|
||||
sf_reset(sc);
|
||||
sf_init(sc);
|
||||
sf_init_locked(sc);
|
||||
|
||||
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
|
||||
sf_start(ifp);
|
||||
sf_start_locked(ifp);
|
||||
|
||||
SF_UNLOCK(sc);
|
||||
}
|
||||
@ -1566,5 +1590,7 @@ sf_shutdown(dev)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
SF_LOCK(sc);
|
||||
sf_stop(sc);
|
||||
SF_UNLOCK(sc);
|
||||
}
|
||||
|
@ -1039,12 +1039,11 @@ struct sf_softc {
|
||||
struct resource *sf_res; /* mem/ioport resource */
|
||||
struct sf_type *sf_info; /* Starfire adapter info */
|
||||
device_t sf_miibus;
|
||||
u_int8_t sf_unit; /* interface number */
|
||||
struct sf_list_data *sf_ldata;
|
||||
int sf_tx_cnt;
|
||||
u_int8_t sf_link;
|
||||
int sf_if_flags;
|
||||
struct callout_handle sf_stat_ch;
|
||||
struct callout sf_stat_callout;
|
||||
struct mtx sf_mtx;
|
||||
#ifdef DEVICE_POLLING
|
||||
int rxcycles;
|
||||
|
Loading…
Reference in New Issue
Block a user