summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2005-08-16 20:39:30 +0000
committerjhb <jhb@FreeBSD.org>2005-08-16 20:39:30 +0000
commit907015177644e8c45939f686c9cafc14febbb80b (patch)
tree7c3a3643ef8deb9e0e9e2696f1893ea56d236747 /sys
parentc1c0b1f44eab8d811187701834cddb397b22027c (diff)
downloadFreeBSD-src-907015177644e8c45939f686c9cafc14febbb80b.zip
FreeBSD-src-907015177644e8c45939f686c9cafc14febbb80b.tar.gz
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
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/my/if_my.c198
-rw-r--r--sys/dev/my/if_myreg.h2
2 files changed, 96 insertions, 104 deletions
diff --git a/sys/dev/my/if_my.c b/sys/dev/my/if_my.c
index 39ec004..bc5568e 100644
--- a/sys/dev/my/if_my.c
+++ b/sys/dev/my/if_my.c
@@ -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;
- }
- 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;
+ goto release_io;
}
- 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);
}
@@ -1395,14 +1377,24 @@ 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;
+
+ 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;
- int s;
u_int16_t phy_bmcr = 0;
- MY_LOCK(sc);
+ 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;
}
diff --git a/sys/dev/my/if_myreg.h b/sys/dev/my/if_myreg.h
index 7e65fda..a552de5 100644
--- a/sys/dev/my/if_myreg.h
+++ b/sys/dev/my/if_myreg.h
@@ -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
OpenPOWER on IntegriCloud