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:
parent
5b7ad0edc8
commit
304e13439b
@ -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),
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
#
|
||||
|
Loading…
Reference in New Issue
Block a user