summaryrefslogtreecommitdiffstats
path: root/sys/dev/smbus/smbconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/smbus/smbconf.c')
-rw-r--r--sys/dev/smbus/smbconf.c90
1 files changed, 47 insertions, 43 deletions
diff --git a/sys/dev/smbus/smbconf.c b/sys/dev/smbus/smbconf.c
index 8a85009..06d225a 100644
--- a/sys/dev/smbus/smbconf.c
+++ b/sys/dev/smbus/smbconf.c
@@ -30,7 +30,9 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/lock.h>
#include <sys/module.h>
+#include <sys/mutex.h>
#include <sys/bus.h>
#include <dev/smbus/smbconf.h>
@@ -43,13 +45,13 @@ __FBSDID("$FreeBSD$");
void
smbus_intr(device_t bus, u_char devaddr, char low, char high, int error)
{
- struct smbus_softc *sc = (struct smbus_softc *)device_get_softc(bus);
+ struct smbus_softc *sc = device_get_softc(bus);
/* call owner's intr routine */
+ mtx_lock(&sc->lock);
if (sc->owner)
SMBUS_INTR(sc->owner, devaddr, low, high, error);
-
- return;
+ mtx_unlock(&sc->lock);
}
/*
@@ -65,17 +67,18 @@ smbus_error(int smb_error)
if (smb_error == SMB_ENOERR)
return (0);
- if (smb_error & (SMB_ENOTSUPP)) {
+ if (smb_error & (SMB_ENOTSUPP))
error = ENODEV;
- } else if (smb_error & (SMB_ENOACK)) {
+ else if (smb_error & (SMB_ENOACK))
error = ENXIO;
- } else if (smb_error & (SMB_ETIMEOUT)) {
+ else if (smb_error & (SMB_ETIMEOUT))
error = EWOULDBLOCK;
- } else if (smb_error & (SMB_EBUSY)) {
+ else if (smb_error & (SMB_EBUSY))
error = EBUSY;
- } else {
+ else if (smb_error & (SMB_EABORT | SMB_EBUSERR | SMB_ECOLLI))
+ error = EIO;
+ else
error = EINVAL;
- }
return (error);
}
@@ -86,16 +89,16 @@ smbus_poll(struct smbus_softc *sc, int how)
int error;
switch (how) {
- case (SMB_WAIT | SMB_INTR):
- error = tsleep(sc, SMBPRI|PCATCH, "smbreq", 0);
+ case SMB_WAIT | SMB_INTR:
+ error = msleep(sc, &sc->lock, SMBPRI|PCATCH, "smbreq", 0);
break;
- case (SMB_WAIT | SMB_NOINTR):
- error = tsleep(sc, SMBPRI, "smbreq", 0);
+ case SMB_WAIT | SMB_NOINTR:
+ error = msleep(sc, &sc->lock, SMBPRI, "smbreq", 0);
break;
default:
- return (EWOULDBLOCK);
+ error = EWOULDBLOCK;
break;
}
@@ -112,35 +115,38 @@ smbus_poll(struct smbus_softc *sc, int how)
int
smbus_request_bus(device_t bus, device_t dev, int how)
{
- struct smbus_softc *sc = (struct smbus_softc *)device_get_softc(bus);
- int s, error = 0;
+ struct smbus_softc *sc = device_get_softc(bus);
+ device_t parent;
+ int error;
/* first, ask the underlying layers if the request is ok */
+ parent = device_get_parent(bus);
+ mtx_lock(&sc->lock);
do {
- error = SMBUS_CALLBACK(device_get_parent(bus),
- SMB_REQUEST_BUS, (caddr_t)&how);
+ mtx_unlock(&sc->lock);
+ error = SMBUS_CALLBACK(parent, SMB_REQUEST_BUS, &how);
+ mtx_lock(&sc->lock);
+
if (error)
error = smbus_poll(sc, how);
} while (error == EWOULDBLOCK);
- while (!error) {
- s = splhigh();
- if (sc->owner && sc->owner != dev) {
- splx(s);
-
+ while (error == 0) {
+ if (sc->owner && sc->owner != dev)
error = smbus_poll(sc, how);
- } else {
+ else {
sc->owner = dev;
-
- splx(s);
- return (0);
+ break;
}
/* free any allocated resource */
- if (error)
- SMBUS_CALLBACK(device_get_parent(bus), SMB_RELEASE_BUS,
- (caddr_t)&how);
+ if (error) {
+ mtx_unlock(&sc->lock);
+ SMBUS_CALLBACK(parent, SMB_RELEASE_BUS, &how);
+ return (error);
+ }
}
+ mtx_unlock(&sc->lock);
return (error);
}
@@ -153,8 +159,8 @@ smbus_request_bus(device_t bus, device_t dev, int how)
int
smbus_release_bus(device_t bus, device_t dev)
{
- struct smbus_softc *sc = (struct smbus_softc *)device_get_softc(bus);
- int s, error;
+ struct smbus_softc *sc = device_get_softc(bus);
+ int error;
/* first, ask the underlying layers if the release is ok */
error = SMBUS_CALLBACK(device_get_parent(bus), SMB_RELEASE_BUS, NULL);
@@ -162,17 +168,15 @@ smbus_release_bus(device_t bus, device_t dev)
if (error)
return (error);
- s = splhigh();
- if (sc->owner != dev) {
- splx(s);
- return (EACCES);
- }
-
- sc->owner = 0;
- splx(s);
+ mtx_lock(&sc->lock);
+ if (sc->owner == dev) {
+ sc->owner = NULL;
- /* wakeup waiting processes */
- wakeup(sc);
+ /* wakeup waiting processes */
+ wakeup(sc);
+ } else
+ error = EACCES;
+ mtx_unlock(&sc->lock);
- return (0);
+ return (error);
}
OpenPOWER on IntegriCloud