svn commit: r241578 - in head/sys/dev/etherswitch: . arswitch
Aleksandr Rybalko
ray at FreeBSD.org
Mon Oct 15 12:20:42 UTC 2012
Author: ray
Date: Mon Oct 15 12:20:40 2012
New Revision: 241578
URL: http://svn.freebsd.org/changeset/base/241578
Log:
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)
Modified:
head/sys/dev/etherswitch/arswitch/arswitch.c
head/sys/dev/etherswitch/arswitch/arswitch_phy.c
head/sys/dev/etherswitch/etherswitch.c
head/sys/dev/etherswitch/etherswitch_if.m
Modified: head/sys/dev/etherswitch/arswitch/arswitch.c
==============================================================================
--- head/sys/dev/etherswitch/arswitch/arswitch.c Mon Oct 15 12:03:11 2012 (r241577)
+++ head/sys/dev/etherswitch/arswitch/arswitch.c Mon Oct 15 12:20:40 2012 (r241578)
@@ -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_sof
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),
Modified: head/sys/dev/etherswitch/arswitch/arswitch_phy.c
==============================================================================
--- head/sys/dev/etherswitch/arswitch/arswitch_phy.c Mon Oct 15 12:03:11 2012 (r241577)
+++ head/sys/dev/etherswitch/arswitch/arswitch_phy.c Mon Oct 15 12:20:40 2012 (r241578)
@@ -75,13 +75,19 @@ static SYSCTL_NODE(_debug, OID_AUTO, ars
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,
(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,
}
if (timeout < 0)
err = EIO;
+out:
DEVERR(dev, err, "arswitch_writephy()=%d: phy=%d.%02x\n", phy, reg);
+ ARSWITCH_UNLOCK(sc);
return (err);
}
Modified: head/sys/dev/etherswitch/etherswitch.c
==============================================================================
--- head/sys/dev/etherswitch/etherswitch.c Mon Oct 15 12:03:11 2012 (r241577)
+++ head/sys/dev/etherswitch/etherswitch.c Mon Oct 15 12:20:40 2012 (r241578)
@@ -213,12 +213,16 @@ etherswitchioctl(struct cdev *cdev, u_lo
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:
Modified: head/sys/dev/etherswitch/etherswitch_if.m
==============================================================================
--- head/sys/dev/etherswitch/etherswitch_if.m Mon Oct 15 12:03:11 2012 (r241577)
+++ head/sys/dev/etherswitch/etherswitch_if.m Mon Oct 15 12:20:40 2012 (r241578)
@@ -11,6 +11,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
#
METHOD etherswitch_info_t* getinfo {
@@ -18,6 +33,20 @@ METHOD etherswitch_info_t* getinfo {
}
#
+# 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
#
METHOD int readreg {
More information about the svn-src-head
mailing list