diff options
author | Vladimir Kondratyev <wulf@FreeBSD.org> | 2019-11-03 20:53:13 +0000 |
---|---|---|
committer | Vladimir Kondratyev <wulf@FreeBSD.org> | 2019-11-03 20:53:13 +0000 |
commit | 41b24e091771f231bb1f915ac9921337b95f04f9 (patch) | |
tree | 52f59ab927f6f2d2c053c1d0544f34d251b14264 | |
parent | c59aca578e9d1b968389d9d27ba8328016c8caf6 (diff) |
Notes
-rw-r--r-- | sys/dev/ichiic/ig4_acpi.c | 2 | ||||
-rw-r--r-- | sys/dev/ichiic/ig4_iic.c | 51 | ||||
-rw-r--r-- | sys/dev/ichiic/ig4_pci.c | 2 | ||||
-rw-r--r-- | sys/dev/ichiic/ig4_var.h | 2 |
4 files changed, 50 insertions, 7 deletions
diff --git a/sys/dev/ichiic/ig4_acpi.c b/sys/dev/ichiic/ig4_acpi.c index e56b378f1767..2e306505c608 100644 --- a/sys/dev/ichiic/ig4_acpi.c +++ b/sys/dev/ichiic/ig4_acpi.c @@ -154,7 +154,7 @@ static device_method_t ig4iic_acpi_methods[] = { /* iicbus interface */ DEVMETHOD(iicbus_transfer, ig4iic_transfer), DEVMETHOD(iicbus_reset, ig4iic_reset), - DEVMETHOD(iicbus_callback, iicbus_null_callback), + DEVMETHOD(iicbus_callback, ig4iic_callback), DEVMETHOD_END }; diff --git a/sys/dev/ichiic/ig4_iic.c b/sys/dev/ichiic/ig4_iic.c index 9199e23ec346..be409bdee893 100644 --- a/sys/dev/ichiic/ig4_iic.c +++ b/sys/dev/ichiic/ig4_iic.c @@ -72,7 +72,7 @@ __FBSDID("$FreeBSD$"); #define TRANS_PCALL 2 #define TRANS_BLOCK 3 -#define DO_POLL(sc) (cold || kdb_active || SCHEDULER_STOPPED()) +#define DO_POLL(sc) (cold || kdb_active || SCHEDULER_STOPPED() || sc->poll) static void ig4iic_start(void *xdev); static void ig4iic_intr(void *cookie); @@ -350,6 +350,7 @@ ig4iic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) int unit; bool rpstart; bool stop; + bool allocated; /* * The hardware interface imposes limits on allowed I2C messages. @@ -410,7 +411,10 @@ ig4iic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) return (IIC_ENOTSUPP); } - sx_xlock(&sc->call_lock); + /* Check if device is already allocated with iicbus_request_bus() */ + allocated = sx_xlocked(&sc->call_lock) != 0; + if (!allocated) + sx_xlock(&sc->call_lock); /* Debugging - dump registers. */ if (ig4_dump) { @@ -458,7 +462,8 @@ ig4iic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) rpstart = !stop; } - sx_unlock(&sc->call_lock); + if (!allocated) + sx_unlock(&sc->call_lock); return (error); } @@ -466,8 +471,11 @@ int ig4iic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) { ig4iic_softc_t *sc = device_get_softc(dev); + bool allocated; - sx_xlock(&sc->call_lock); + allocated = sx_xlocked(&sc->call_lock) != 0; + if (!allocated) + sx_xlock(&sc->call_lock); /* TODO handle speed configuration? */ if (oldaddr != NULL) @@ -476,10 +484,43 @@ ig4iic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) if (addr == IIC_UNKNOWN) sc->slave_valid = false; - sx_unlock(&sc->call_lock); + if (!allocated) + sx_unlock(&sc->call_lock); return (0); } +int +ig4iic_callback(device_t dev, int index, caddr_t data) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + int error = 0; + int how; + + switch (index) { + case IIC_REQUEST_BUS: + /* force polling if ig4iic is requested with IIC_DONTWAIT */ + how = *(int *)data; + if ((how & IIC_WAIT) == 0) { + if (sx_try_xlock(&sc->call_lock) == 0) + error = IIC_EBUSBSY; + else + sc->poll = true; + } else + sx_xlock(&sc->call_lock); + break; + + case IIC_RELEASE_BUS: + sc->poll = false; + sx_unlock(&sc->call_lock); + break; + + default: + error = errno2iic(EINVAL); + } + + return (error); +} + /* * Called from ig4iic_pci_attach/detach() */ diff --git a/sys/dev/ichiic/ig4_pci.c b/sys/dev/ichiic/ig4_pci.c index 0b1a2ffc6f9e..64e6e994fc78 100644 --- a/sys/dev/ichiic/ig4_pci.c +++ b/sys/dev/ichiic/ig4_pci.c @@ -214,7 +214,7 @@ static device_method_t ig4iic_pci_methods[] = { DEVMETHOD(iicbus_transfer, ig4iic_transfer), DEVMETHOD(iicbus_reset, ig4iic_reset), - DEVMETHOD(iicbus_callback, iicbus_null_callback), + DEVMETHOD(iicbus_callback, ig4iic_callback), DEVMETHOD_END }; diff --git a/sys/dev/ichiic/ig4_var.h b/sys/dev/ichiic/ig4_var.h index e7a2b7b50c06..753498ce1a2d 100644 --- a/sys/dev/ichiic/ig4_var.h +++ b/sys/dev/ichiic/ig4_var.h @@ -67,6 +67,7 @@ struct ig4iic_softc { int slave_valid : 1; int read_started : 1; int write_started : 1; + int poll: 1; /* * Locking semantics: @@ -95,5 +96,6 @@ int ig4iic_detach(ig4iic_softc_t *sc); /* iicbus methods */ extern iicbus_transfer_t ig4iic_transfer; extern iicbus_reset_t ig4iic_reset; +extern iicbus_callback_t ig4iic_callback; #endif /* _ICHIIC_IG4_VAR_H_ */ |