Locking for etherswitch framework:

* add lock/unlock methods;
* add lock/unlock default implementation;
* surround switch IOCTLs with locking;
* add lock/unlock implementation for arswitch;

Submitted by:	Luiz Otavio O Souza
Approved by:	adrian (mentor)
This commit is contained in:
ray 2012-10-15 12:20:40 +00:00
parent 5b7ad0edc8
commit 304e13439b
4 changed files with 82 additions and 7 deletions

View File

@ -263,7 +263,10 @@ arswitch_attach(device_t dev)
return (err);
callout_init_mtx(&sc->callout_tick, &sc->sc_mtx, 0);
ARSWITCH_LOCK(sc);
arswitch_tick(sc);
ARSWITCH_UNLOCK(sc);
return (err);
}
@ -371,6 +374,8 @@ arswitch_miipollstat(struct arswitch_softc *sc)
struct mii_softc *miisc;
int portstatus;
ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
for (i = 0; i < sc->numphys; i++) {
if (sc->miibus[i] == NULL)
continue;
@ -404,6 +409,24 @@ arswitch_tick(void *arg)
callout_reset(&sc->callout_tick, hz, arswitch_tick, sc);
}
static void
arswitch_lock(device_t dev)
{
struct arswitch_softc *sc = device_get_softc(dev);
ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
ARSWITCH_LOCK(sc);
}
static void
arswitch_unlock(device_t dev)
{
struct arswitch_softc *sc = device_get_softc(dev);
ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
ARSWITCH_UNLOCK(sc);
}
static etherswitch_info_t *
arswitch_getinfo(device_t dev)
{
@ -552,6 +575,8 @@ static device_method_t arswitch_methods[] = {
DEVMETHOD(mdio_writereg, arswitch_writephy),
/* etherswitch interface */
DEVMETHOD(etherswitch_lock, arswitch_lock),
DEVMETHOD(etherswitch_unlock, arswitch_unlock),
DEVMETHOD(etherswitch_getinfo, arswitch_getinfo),
DEVMETHOD(etherswitch_readreg, arswitch_readreg),
DEVMETHOD(etherswitch_writereg, arswitch_writereg),

View File

@ -75,13 +75,19 @@ static SYSCTL_NODE(_debug, OID_AUTO, arswitch, CTLFLAG_RD, 0, "arswitch");
int
arswitch_readphy(device_t dev, int phy, int reg)
{
struct arswitch_softc *sc;
uint32_t data = 0, ctrl;
int err, timeout;
sc = device_get_softc(dev);
ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
if (phy < 0 || phy >= 32)
return (ENXIO);
if (reg < 0 || reg >= 32)
return (ENXIO);
ARSWITCH_LOCK(sc);
err = arswitch_writereg_msb(dev, AR8X16_REG_MDIO_CTRL,
AR8X16_MDIO_CTRL_BUSY | AR8X16_MDIO_CTRL_MASTER_EN |
AR8X16_MDIO_CTRL_CMD_READ |
@ -89,41 +95,50 @@ arswitch_readphy(device_t dev, int phy, int reg)
(reg << AR8X16_MDIO_CTRL_REG_ADDR_SHIFT));
DEVERR(dev, err, "arswitch_readphy()=%d: phy=%d.%02x\n", phy, reg);
if (err != 0)
return (-1);
goto fail;
for (timeout = 100; timeout--; ) {
ctrl = arswitch_readreg_msb(dev, AR8X16_REG_MDIO_CTRL);
if ((ctrl & AR8X16_MDIO_CTRL_BUSY) == 0)
break;
}
if (timeout < 0)
err = EIO;
goto fail;
data = arswitch_readreg_lsb(dev, AR8X16_REG_MDIO_CTRL) &
AR8X16_MDIO_CTRL_DATA_MASK;
ARSWITCH_UNLOCK(sc);
return (data);
fail:
ARSWITCH_UNLOCK(sc);
return (-1);
}
int
arswitch_writephy(device_t dev, int phy, int reg, int data)
{
struct arswitch_softc *sc;
uint32_t ctrl;
int err, timeout;
sc = device_get_softc(dev);
ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
if (reg < 0 || reg >= 32)
return (ENXIO);
ARSWITCH_LOCK(sc);
err = arswitch_writereg_lsb(dev, AR8X16_REG_MDIO_CTRL,
(data & AR8X16_MDIO_CTRL_DATA_MASK));
DEVERR(dev, err, "arswitch_writephy()=%d: phy=%d.%02x\n", phy, reg);
if (err != 0)
return (err);
goto out;
err = arswitch_writereg_msb(dev, AR8X16_REG_MDIO_CTRL,
AR8X16_MDIO_CTRL_BUSY |
AR8X16_MDIO_CTRL_MASTER_EN |
AR8X16_MDIO_CTRL_CMD_WRITE |
(phy << AR8X16_MDIO_CTRL_PHY_ADDR_SHIFT) |
(reg << AR8X16_MDIO_CTRL_REG_ADDR_SHIFT));
DEVERR(dev, err, "arswitch_writephy()=%d: phy=%d.%02x\n", phy, reg);
if (err != 0)
return (err);
goto out;
for (timeout = 100; timeout--; ) {
ctrl = arswitch_readreg(dev, AR8X16_REG_MDIO_CTRL);
if ((ctrl & AR8X16_MDIO_CTRL_BUSY) == 0)
@ -131,6 +146,8 @@ arswitch_writephy(device_t dev, int phy, int reg, int data)
}
if (timeout < 0)
err = EIO;
out:
DEVERR(dev, err, "arswitch_writephy()=%d: phy=%d.%02x\n", phy, reg);
ARSWITCH_UNLOCK(sc);
return (err);
}

View File

@ -213,12 +213,16 @@ etherswitchioctl(struct cdev *cdev, u_long cmd, caddr_t data, int flags, struct
case IOETHERSWITCHGETREG:
reg = (etherswitch_reg_t *)data;
ETHERSWITCH_LOCK(etherswitch);
reg->val = ETHERSWITCH_READREG(etherswitch, reg->reg);
ETHERSWITCH_UNLOCK(etherswitch);
break;
case IOETHERSWITCHSETREG:
reg = (etherswitch_reg_t *)data;
ETHERSWITCH_LOCK(etherswitch);
error = ETHERSWITCH_WRITEREG(etherswitch, reg->reg, reg->val);
ETHERSWITCH_UNLOCK(etherswitch);
break;
case IOETHERSWITCHGETPORT:

View File

@ -10,6 +10,21 @@
INTERFACE etherswitch;
#
# Default implementation
#
CODE {
static void
null_etherswitch_lock(device_t dev)
{
}
static void
null_etherswitch_unlock(device_t dev)
{
}
};
#
# Return device info
#
@ -17,6 +32,20 @@ METHOD etherswitch_info_t* getinfo {
device_t dev;
}
#
# Lock access to switch registers
#
METHOD void lock {
device_t dev;
} DEFAULT null_etherswitch_lock;
#
# Unlock access to switch registers
#
METHOD void unlock {
device_t dev;
} DEFAULT null_etherswitch_unlock;
#
# Read switch register
#