Fixup locking in if_my(4) and mark it MPSAFE:
- Add locked variants of my_start() and my_init(). - Assert that the lock is held in several places rather than recursing. - Overhaul failure case handling in my_attach() so that it will actually clean up completely in each of the failure cases. - Setup the interrupt after ether_ifattach() in my_attach(). - Remove unused callout handle from softc. - Free the metadata for the descriptors my_in detach() (we leaked it before). - Fix locking in my_ioctl(). - Remove spls. Tested by: brueffer MFC after: 3 days
This commit is contained in:
parent
52d71e1a85
commit
ca5fc32d02
@ -127,8 +127,10 @@ static void my_txeof(struct my_softc *);
|
||||
static void my_txeoc(struct my_softc *);
|
||||
static void my_intr(void *);
|
||||
static void my_start(struct ifnet *);
|
||||
static void my_start_locked(struct ifnet *);
|
||||
static int my_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void my_init(void *);
|
||||
static void my_init_locked(struct my_softc *);
|
||||
static void my_stop(struct my_softc *);
|
||||
static void my_watchdog(struct ifnet *);
|
||||
static void my_shutdown(device_t);
|
||||
@ -179,7 +181,7 @@ my_send_cmd_to_phy(struct my_softc * sc, int opcode, int regad)
|
||||
int i;
|
||||
int mask, data;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
|
||||
/* enable MII output */
|
||||
miir = CSR_READ_4(sc, MY_MANAGEMENT);
|
||||
@ -221,7 +223,6 @@ my_send_cmd_to_phy(struct my_softc * sc, int opcode, int regad)
|
||||
miir &= ~MY_MASK_MIIR_MII_WRITE;
|
||||
}
|
||||
|
||||
MY_UNLOCK(sc);
|
||||
return miir;
|
||||
}
|
||||
|
||||
@ -232,7 +233,7 @@ my_phy_readreg(struct my_softc * sc, int reg)
|
||||
long miir;
|
||||
int mask, data;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
|
||||
if (sc->my_info->my_did == MTD803ID)
|
||||
data = CSR_READ_2(sc, MY_PHYBASE + reg * 2);
|
||||
@ -266,7 +267,6 @@ my_phy_readreg(struct my_softc * sc, int reg)
|
||||
CSR_WRITE_4(sc, MY_MANAGEMENT, miir);
|
||||
}
|
||||
|
||||
MY_UNLOCK(sc);
|
||||
return (u_int16_t) data;
|
||||
}
|
||||
|
||||
@ -277,7 +277,7 @@ my_phy_writereg(struct my_softc * sc, int reg, int data)
|
||||
long miir;
|
||||
int mask;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
|
||||
if (sc->my_info->my_did == MTD803ID)
|
||||
CSR_WRITE_2(sc, MY_PHYBASE + reg * 2, data);
|
||||
@ -307,7 +307,6 @@ my_phy_writereg(struct my_softc * sc, int reg, int data)
|
||||
miir &= ~MY_MASK_MIIR_MII_MDC;
|
||||
CSR_WRITE_4(sc, MY_MANAGEMENT, miir);
|
||||
}
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -325,7 +324,7 @@ my_setmulti(struct my_softc * sc)
|
||||
u_int32_t rxfilt;
|
||||
int mcnt = 0;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
|
||||
ifp = sc->my_ifp;
|
||||
|
||||
@ -337,8 +336,6 @@ my_setmulti(struct my_softc * sc)
|
||||
CSR_WRITE_4(sc, MY_MAR0, 0xFFFFFFFF);
|
||||
CSR_WRITE_4(sc, MY_MAR1, 0xFFFFFFFF);
|
||||
|
||||
MY_UNLOCK(sc);
|
||||
|
||||
return;
|
||||
}
|
||||
/* first, zot all the existing hash bits */
|
||||
@ -367,7 +364,6 @@ my_setmulti(struct my_softc * sc)
|
||||
CSR_WRITE_4(sc, MY_MAR0, hashes[0]);
|
||||
CSR_WRITE_4(sc, MY_MAR1, hashes[1]);
|
||||
CSR_WRITE_4(sc, MY_TCRRCR, rxfilt);
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -379,7 +375,7 @@ my_autoneg_xmit(struct my_softc * sc)
|
||||
{
|
||||
u_int16_t phy_sts = 0;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
|
||||
my_phy_writereg(sc, PHY_BMCR, PHY_BMCR_RESET);
|
||||
DELAY(500);
|
||||
@ -389,7 +385,6 @@ my_autoneg_xmit(struct my_softc * sc)
|
||||
phy_sts |= PHY_BMCR_AUTONEGENBL | PHY_BMCR_AUTONEGRSTR;
|
||||
my_phy_writereg(sc, PHY_BMCR, phy_sts);
|
||||
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -405,7 +400,7 @@ my_autoneg_mii(struct my_softc * sc, int flag, int verbose)
|
||||
struct ifnet *ifp;
|
||||
struct ifmedia *ifm;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
|
||||
ifm = &sc->ifmedia;
|
||||
ifp = sc->my_ifp;
|
||||
@ -422,7 +417,6 @@ my_autoneg_mii(struct my_softc * sc, int flag, int verbose)
|
||||
if (verbose)
|
||||
if_printf(ifp, "autonegotiation not supported\n");
|
||||
ifm->ifm_media = IFM_ETHER | IFM_10_T | IFM_HDX;
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@ -453,7 +447,6 @@ my_autoneg_mii(struct my_softc * sc, int flag, int verbose)
|
||||
ifp->if_timer = 5;
|
||||
sc->my_autoneg = 1;
|
||||
sc->my_want_auto = 0;
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
case MY_FLAG_DELAYTIMEO:
|
||||
ifp->if_timer = 0;
|
||||
@ -551,13 +544,12 @@ my_autoneg_mii(struct my_softc * sc, int flag, int verbose)
|
||||
if_printf(ifp, "no carrier\n");
|
||||
}
|
||||
|
||||
my_init(sc);
|
||||
my_init_locked(sc);
|
||||
if (sc->my_tx_pend) {
|
||||
sc->my_autoneg = 0;
|
||||
sc->my_tx_pend = 0;
|
||||
my_start(ifp);
|
||||
my_start_locked(ifp);
|
||||
}
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -570,7 +562,7 @@ my_getmode_mii(struct my_softc * sc)
|
||||
u_int16_t bmsr;
|
||||
struct ifnet *ifp;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
ifp = sc->my_ifp;
|
||||
bmsr = my_phy_readreg(sc, PHY_BMSR);
|
||||
if (bootverbose)
|
||||
@ -648,7 +640,6 @@ my_getmode_mii(struct my_softc * sc)
|
||||
ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_AUTO, 0, NULL);
|
||||
sc->ifmedia.ifm_media = IFM_ETHER | IFM_AUTO;
|
||||
}
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -661,7 +652,7 @@ my_setmode_mii(struct my_softc * sc, int media)
|
||||
u_int16_t bmcr;
|
||||
struct ifnet *ifp;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
ifp = sc->my_ifp;
|
||||
/*
|
||||
* If an autoneg session is in progress, stop it.
|
||||
@ -708,7 +699,6 @@ my_setmode_mii(struct my_softc * sc, int media)
|
||||
}
|
||||
my_phy_writereg(sc, PHY_BMCR, bmcr);
|
||||
my_setcfg(sc, bmcr);
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -722,7 +712,7 @@ my_setcfg(struct my_softc * sc, int bmcr)
|
||||
{
|
||||
int i, restart = 0;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
if (CSR_READ_4(sc, MY_TCRRCR) & (MY_TE | MY_RE)) {
|
||||
restart = 1;
|
||||
MY_CLRBIT(sc, MY_TCRRCR, (MY_TE | MY_RE));
|
||||
@ -748,7 +738,6 @@ my_setcfg(struct my_softc * sc, int bmcr)
|
||||
MY_CLRBIT(sc, MY_TCRRCR, MY_FD);
|
||||
if (restart)
|
||||
MY_SETBIT(sc, MY_TCRRCR, MY_TE | MY_RE);
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -757,7 +746,7 @@ my_reset(struct my_softc * sc)
|
||||
{
|
||||
register int i;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
MY_SETBIT(sc, MY_BCR, MY_SWR);
|
||||
for (i = 0; i < MY_TIMEOUT; i++) {
|
||||
DELAY(10);
|
||||
@ -769,7 +758,6 @@ my_reset(struct my_softc * sc)
|
||||
|
||||
/* Wait a little while for the chip to get its brains in order. */
|
||||
DELAY(1000);
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -802,7 +790,7 @@ my_probe(device_t dev)
|
||||
static int
|
||||
my_attach(device_t dev)
|
||||
{
|
||||
int s, i;
|
||||
int i;
|
||||
u_char eaddr[ETHER_ADDR_LEN];
|
||||
u_int32_t iobase;
|
||||
struct my_softc *sc;
|
||||
@ -814,11 +802,9 @@ my_attach(device_t dev)
|
||||
u_int16_t phy_vid, phy_did, phy_sts = 0;
|
||||
int rid, error = 0;
|
||||
|
||||
s = splimp();
|
||||
sc = device_get_softc(dev);
|
||||
mtx_init(&sc->my_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
|
||||
MTX_DEF | MTX_RECURSE);
|
||||
MY_LOCK(sc);
|
||||
MTX_DEF);
|
||||
|
||||
/*
|
||||
* Map control/status registers.
|
||||
@ -837,7 +823,7 @@ my_attach(device_t dev)
|
||||
if (sc->my_res == NULL) {
|
||||
device_printf(dev, "couldn't map ports/memory\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
goto destroy_mutex;
|
||||
}
|
||||
sc->my_btag = rman_get_bustag(sc->my_res);
|
||||
sc->my_bhandle = rman_get_bushandle(sc->my_res);
|
||||
@ -848,25 +834,16 @@ my_attach(device_t dev)
|
||||
|
||||
if (sc->my_irq == NULL) {
|
||||
device_printf(dev, "couldn't map interrupt\n");
|
||||
bus_release_resource(dev, MY_RES, MY_RID, sc->my_res);
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
goto release_io;
|
||||
}
|
||||
error = bus_setup_intr(dev, sc->my_irq, INTR_TYPE_NET,
|
||||
my_intr, sc, &sc->my_intrhand);
|
||||
|
||||
if (error) {
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->my_irq);
|
||||
bus_release_resource(dev, MY_RES, MY_RID, sc->my_res);
|
||||
device_printf(dev, "couldn't set up irq\n");
|
||||
goto fail;
|
||||
}
|
||||
callout_handle_init(&sc->my_stat_ch);
|
||||
|
||||
sc->my_info = my_info_tmp;
|
||||
|
||||
/* Reset the adapter. */
|
||||
MY_LOCK(sc);
|
||||
my_reset(sc);
|
||||
MY_UNLOCK(sc);
|
||||
|
||||
/*
|
||||
* Get station address
|
||||
@ -879,7 +856,7 @@ my_attach(device_t dev)
|
||||
if (sc->my_ldata_ptr == NULL) {
|
||||
device_printf(dev, "no memory for list buffers!\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
goto release_irq;
|
||||
}
|
||||
sc->my_ldata = (struct my_list_data *) sc->my_ldata_ptr;
|
||||
round = (uintptr_t)sc->my_ldata_ptr & 0xF;
|
||||
@ -898,7 +875,7 @@ my_attach(device_t dev)
|
||||
if (ifp == NULL) {
|
||||
device_printf(dev, "can not if_alloc()\n");
|
||||
error = ENOSPC;
|
||||
goto fail;
|
||||
goto free_ldata;
|
||||
}
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
|
||||
@ -916,6 +893,7 @@ my_attach(device_t dev)
|
||||
else {
|
||||
if (bootverbose)
|
||||
device_printf(dev, "probing for a PHY\n");
|
||||
MY_LOCK(sc);
|
||||
for (i = MY_PHYADDR_MIN; i < MY_PHYADDR_MAX + 1; i++) {
|
||||
if (bootverbose)
|
||||
device_printf(dev, "checking address: %d\n", i);
|
||||
@ -949,31 +927,48 @@ my_attach(device_t dev)
|
||||
device_printf(dev, "PHY type: %s\n",
|
||||
sc->my_pinfo->my_name);
|
||||
} else {
|
||||
MY_UNLOCK(sc);
|
||||
device_printf(dev, "MII without any phy!\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
goto free_if;
|
||||
}
|
||||
MY_UNLOCK(sc);
|
||||
}
|
||||
|
||||
/* Do ifmedia setup. */
|
||||
ifmedia_init(&sc->ifmedia, 0, my_ifmedia_upd, my_ifmedia_sts);
|
||||
MY_LOCK(sc);
|
||||
my_getmode_mii(sc);
|
||||
my_autoneg_mii(sc, MY_FLAG_FORCEDELAY, 1);
|
||||
media = sc->ifmedia.ifm_media;
|
||||
my_stop(sc);
|
||||
MY_UNLOCK(sc);
|
||||
ifmedia_set(&sc->ifmedia, media);
|
||||
|
||||
ether_ifattach(ifp, eaddr);
|
||||
|
||||
error = bus_setup_intr(dev, sc->my_irq, INTR_TYPE_NET | INTR_MPSAFE,
|
||||
my_intr, sc, &sc->my_intrhand);
|
||||
|
||||
if (error) {
|
||||
device_printf(dev, "couldn't set up irq\n");
|
||||
goto detach_if;
|
||||
}
|
||||
|
||||
MY_UNLOCK(sc);
|
||||
return (0);
|
||||
|
||||
fail:
|
||||
MY_UNLOCK(sc);
|
||||
detach_if:
|
||||
ether_ifdetach(ifp);
|
||||
free_if:
|
||||
if_free(ifp);
|
||||
free_ldata:
|
||||
free(sc->my_ldata_ptr, M_DEVBUF);
|
||||
release_irq:
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->my_irq);
|
||||
release_io:
|
||||
bus_release_resource(dev, MY_RES, MY_RID, sc->my_res);
|
||||
destroy_mutex:
|
||||
mtx_destroy(&sc->my_mtx);
|
||||
if (sc->my_ldata_ptr != NULL)
|
||||
free(sc->my_ldata_ptr, M_DEVBUF);
|
||||
splx(s);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -982,21 +977,20 @@ my_detach(device_t dev)
|
||||
{
|
||||
struct my_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
int s;
|
||||
|
||||
s = splimp();
|
||||
sc = device_get_softc(dev);
|
||||
MY_LOCK(sc);
|
||||
my_stop(sc);
|
||||
MY_UNLOCK(sc);
|
||||
bus_teardown_intr(dev, sc->my_irq, sc->my_intrhand);
|
||||
|
||||
ifp = sc->my_ifp;
|
||||
ether_ifdetach(ifp);
|
||||
if_free(ifp);
|
||||
my_stop(sc);
|
||||
free(sc->my_ldata_ptr, M_DEVBUF);
|
||||
|
||||
bus_teardown_intr(dev, sc->my_irq, sc->my_intrhand);
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->my_irq);
|
||||
bus_release_resource(dev, MY_RES, MY_RID, sc->my_res);
|
||||
MY_UNLOCK(sc);
|
||||
splx(s);
|
||||
mtx_destroy(&sc->my_mtx);
|
||||
return (0);
|
||||
}
|
||||
@ -1012,7 +1006,7 @@ my_list_tx_init(struct my_softc * sc)
|
||||
struct my_list_data *ld;
|
||||
int i;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
cd = &sc->my_cdata;
|
||||
ld = sc->my_ldata;
|
||||
for (i = 0; i < MY_TX_LIST_CNT; i++) {
|
||||
@ -1025,7 +1019,6 @@ my_list_tx_init(struct my_softc * sc)
|
||||
}
|
||||
cd->my_tx_free = &cd->my_tx_chain[0];
|
||||
cd->my_tx_tail = cd->my_tx_head = NULL;
|
||||
MY_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1041,7 +1034,7 @@ my_list_rx_init(struct my_softc * sc)
|
||||
struct my_list_data *ld;
|
||||
int i;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
cd = &sc->my_cdata;
|
||||
ld = sc->my_ldata;
|
||||
for (i = 0; i < MY_RX_LIST_CNT; i++) {
|
||||
@ -1062,7 +1055,6 @@ my_list_rx_init(struct my_softc * sc)
|
||||
}
|
||||
}
|
||||
cd->my_rx_head = &cd->my_rx_chain[0];
|
||||
MY_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1074,12 +1066,11 @@ my_newbuf(struct my_softc * sc, struct my_chain_onefrag * c)
|
||||
{
|
||||
struct mbuf *m_new = NULL;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
MGETHDR(m_new, M_DONTWAIT, MT_DATA);
|
||||
if (m_new == NULL) {
|
||||
if_printf(sc->my_ifp,
|
||||
"no memory for rx list -- packet dropped!\n");
|
||||
MY_UNLOCK(sc);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
MCLGET(m_new, M_DONTWAIT);
|
||||
@ -1087,14 +1078,12 @@ my_newbuf(struct my_softc * sc, struct my_chain_onefrag * c)
|
||||
if_printf(sc->my_ifp,
|
||||
"no memory for rx list -- packet dropped!\n");
|
||||
m_freem(m_new);
|
||||
MY_UNLOCK(sc);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
c->my_mbuf = m_new;
|
||||
c->my_ptr->my_data = vtophys(mtod(m_new, caddr_t));
|
||||
c->my_ptr->my_ctl = (MCLBYTES - 1) << MY_RBSShift;
|
||||
c->my_ptr->my_status = MY_OWNByNIC;
|
||||
MY_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1112,7 +1101,7 @@ my_rxeof(struct my_softc * sc)
|
||||
int total_len = 0;
|
||||
u_int32_t rxstat;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
ifp = sc->my_ifp;
|
||||
while (!((rxstat = sc->my_cdata.my_rx_head->my_ptr->my_status)
|
||||
& MY_OWNByNIC)) {
|
||||
@ -1177,7 +1166,6 @@ my_rxeof(struct my_softc * sc)
|
||||
(*ifp->if_input)(ifp, m);
|
||||
MY_LOCK(sc);
|
||||
}
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1192,12 +1180,11 @@ my_txeof(struct my_softc * sc)
|
||||
struct my_chain *cur_tx;
|
||||
struct ifnet *ifp;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
ifp = sc->my_ifp;
|
||||
/* Clear the timeout timer. */
|
||||
ifp->if_timer = 0;
|
||||
if (sc->my_cdata.my_tx_head == NULL) {
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
@ -1235,7 +1222,6 @@ my_txeof(struct my_softc * sc)
|
||||
if (CSR_READ_4(sc, MY_TCRRCR) & MY_Enhanced) {
|
||||
ifp->if_collisions += (CSR_READ_4(sc, MY_TSR) & MY_NCRMask);
|
||||
}
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1247,7 +1233,7 @@ my_txeoc(struct my_softc * sc)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
ifp = sc->my_ifp;
|
||||
ifp->if_timer = 0;
|
||||
if (sc->my_cdata.my_tx_head == NULL) {
|
||||
@ -1262,7 +1248,6 @@ my_txeoc(struct my_softc * sc)
|
||||
CSR_WRITE_4(sc, MY_TXPDR, 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1300,7 +1285,7 @@ my_intr(void *arg)
|
||||
#ifdef foo
|
||||
my_stop(sc);
|
||||
my_reset(sc);
|
||||
my_init(sc);
|
||||
my_init_locked(sc);
|
||||
#endif
|
||||
}
|
||||
if (status & MY_TI) /* tx interrupt */
|
||||
@ -1313,7 +1298,7 @@ my_intr(void *arg)
|
||||
#if 0 /* 90/1/18 delete */
|
||||
if (status & MY_FBE) {
|
||||
my_reset(sc);
|
||||
my_init(sc);
|
||||
my_init_locked(sc);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1322,7 +1307,7 @@ my_intr(void *arg)
|
||||
/* Re-enable interrupts. */
|
||||
CSR_WRITE_4(sc, MY_IMR, MY_INTRS);
|
||||
if (ifp->if_snd.ifq_head != NULL)
|
||||
my_start(ifp);
|
||||
my_start_locked(ifp);
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
@ -1338,7 +1323,7 @@ my_encap(struct my_softc * sc, struct my_chain * c, struct mbuf * m_head)
|
||||
int total_len;
|
||||
struct mbuf *m, *m_new = NULL;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
/* calculate the total tx pkt length */
|
||||
total_len = 0;
|
||||
for (m = m_head; m != NULL; m = m->m_next)
|
||||
@ -1352,7 +1337,6 @@ my_encap(struct my_softc * sc, struct my_chain * c, struct mbuf * m_head)
|
||||
MGETHDR(m_new, M_DONTWAIT, MT_DATA);
|
||||
if (m_new == NULL) {
|
||||
if_printf(sc->my_ifp, "no memory for tx list");
|
||||
MY_UNLOCK(sc);
|
||||
return (1);
|
||||
}
|
||||
if (m_head->m_pkthdr.len > MHLEN) {
|
||||
@ -1360,7 +1344,6 @@ my_encap(struct my_softc * sc, struct my_chain * c, struct mbuf * m_head)
|
||||
if (!(m_new->m_flags & M_EXT)) {
|
||||
m_freem(m_new);
|
||||
if_printf(sc->my_ifp, "no memory for tx list");
|
||||
MY_UNLOCK(sc);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
@ -1381,7 +1364,6 @@ my_encap(struct my_softc * sc, struct my_chain * c, struct mbuf * m_head)
|
||||
c->my_mbuf = m_head;
|
||||
c->my_lastdesc = 0;
|
||||
MY_TXNEXT(c) = vtophys(&c->my_nextdesc->my_ptr->my_frag[0]);
|
||||
MY_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1393,16 +1375,26 @@ my_encap(struct my_softc * sc, struct my_chain * c, struct mbuf * m_head)
|
||||
*/
|
||||
static void
|
||||
my_start(struct ifnet * ifp)
|
||||
{
|
||||
struct my_softc *sc;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
MY_LOCK(sc);
|
||||
my_start_locked(ifp);
|
||||
MY_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
my_start_locked(struct ifnet * ifp)
|
||||
{
|
||||
struct my_softc *sc;
|
||||
struct mbuf *m_head = NULL;
|
||||
struct my_chain *cur_tx = NULL, *start_tx;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
if (sc->my_autoneg) {
|
||||
sc->my_tx_pend = 1;
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
@ -1410,7 +1402,6 @@ my_start(struct ifnet * ifp)
|
||||
*/
|
||||
if (sc->my_cdata.my_tx_free->my_mbuf != NULL) {
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
start_tx = sc->my_cdata.my_tx_free;
|
||||
@ -1440,7 +1431,6 @@ my_start(struct ifnet * ifp)
|
||||
* If there are no packets queued, bail.
|
||||
*/
|
||||
if (cur_tx == NULL) {
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
@ -1461,7 +1451,6 @@ my_start(struct ifnet * ifp)
|
||||
* Set a timeout in case the chip goes out to lunch.
|
||||
*/
|
||||
ifp->if_timer = 5;
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1469,16 +1458,22 @@ static void
|
||||
my_init(void *xsc)
|
||||
{
|
||||
struct my_softc *sc = xsc;
|
||||
struct ifnet *ifp = sc->my_ifp;
|
||||
int s;
|
||||
u_int16_t phy_bmcr = 0;
|
||||
|
||||
MY_LOCK(sc);
|
||||
my_init_locked(sc);
|
||||
MY_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
my_init_locked(struct my_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->my_ifp;
|
||||
u_int16_t phy_bmcr = 0;
|
||||
|
||||
MY_LOCK_ASSERT(sc);
|
||||
if (sc->my_autoneg) {
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
s = splimp();
|
||||
if (sc->my_pinfo != NULL)
|
||||
phy_bmcr = my_phy_readreg(sc, PHY_BMCR);
|
||||
/*
|
||||
@ -1508,8 +1503,6 @@ my_init(void *xsc)
|
||||
if (my_list_rx_init(sc) == ENOBUFS) {
|
||||
if_printf(ifp, "init failed: no memory for rx buffers\n");
|
||||
my_stop(sc);
|
||||
(void)splx(s);
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
/* Init TX descriptors. */
|
||||
@ -1557,8 +1550,6 @@ my_init(void *xsc)
|
||||
my_phy_writereg(sc, PHY_BMCR, phy_bmcr);
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
(void)splx(s);
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1653,21 +1644,23 @@ my_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
|
||||
{
|
||||
struct my_softc *sc = ifp->if_softc;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int s, error = 0;
|
||||
int error;
|
||||
|
||||
s = splimp();
|
||||
MY_LOCK(sc);
|
||||
switch (command) {
|
||||
case SIOCSIFFLAGS:
|
||||
MY_LOCK(sc);
|
||||
if (ifp->if_flags & IFF_UP)
|
||||
my_init(sc);
|
||||
my_init_locked(sc);
|
||||
else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
my_stop(sc);
|
||||
MY_UNLOCK(sc);
|
||||
error = 0;
|
||||
break;
|
||||
case SIOCADDMULTI:
|
||||
case SIOCDELMULTI:
|
||||
MY_LOCK(sc);
|
||||
my_setmulti(sc);
|
||||
MY_UNLOCK(sc);
|
||||
error = 0;
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
@ -1678,8 +1671,6 @@ my_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
|
||||
error = ether_ioctl(ifp, command, data);
|
||||
break;
|
||||
}
|
||||
MY_UNLOCK(sc);
|
||||
(void)splx(s);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1701,9 +1692,9 @@ my_watchdog(struct ifnet * ifp)
|
||||
if_printf(ifp, "no carrier - transceiver cable problem?\n");
|
||||
my_stop(sc);
|
||||
my_reset(sc);
|
||||
my_init(sc);
|
||||
my_init_locked(sc);
|
||||
if (ifp->if_snd.ifq_head != NULL)
|
||||
my_start(ifp);
|
||||
my_start_locked(ifp);
|
||||
MY_LOCK(sc);
|
||||
return;
|
||||
}
|
||||
@ -1718,7 +1709,7 @@ my_stop(struct my_softc * sc)
|
||||
register int i;
|
||||
struct ifnet *ifp;
|
||||
|
||||
MY_LOCK(sc);
|
||||
MY_LOCK_ASSERT(sc);
|
||||
ifp = sc->my_ifp;
|
||||
ifp->if_timer = 0;
|
||||
|
||||
@ -1750,7 +1741,6 @@ my_stop(struct my_softc * sc)
|
||||
bzero((char *)&sc->my_ldata->my_tx_list,
|
||||
sizeof(sc->my_ldata->my_tx_list));
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1764,6 +1754,8 @@ my_shutdown(device_t dev)
|
||||
struct my_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
MY_LOCK(sc);
|
||||
my_stop(sc);
|
||||
MY_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
@ -369,7 +369,6 @@ struct my_softc {
|
||||
struct my_list_data *my_ldata;
|
||||
struct my_chain_data my_cdata;
|
||||
device_t my_miibus;
|
||||
struct callout_handle my_stat_ch;
|
||||
/* Add by Surfer 2001/12/2 */
|
||||
struct mtx my_mtx;
|
||||
|
||||
@ -378,6 +377,7 @@ struct my_softc {
|
||||
/* Add by Surfer 2001/12/2 */
|
||||
#define MY_LOCK(_sc) mtx_lock(&(_sc)->my_mtx)
|
||||
#define MY_UNLOCK(_sc) mtx_unlock(&(_sc)->my_mtx)
|
||||
#define MY_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->my_mtx, MA_OWNED)
|
||||
|
||||
/*
|
||||
* register space access macros
|
||||
|
Loading…
x
Reference in New Issue
Block a user