summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Kondratyev <wulf@FreeBSD.org>2019-11-03 20:53:13 +0000
committerVladimir Kondratyev <wulf@FreeBSD.org>2019-11-03 20:53:13 +0000
commit41b24e091771f231bb1f915ac9921337b95f04f9 (patch)
tree52f59ab927f6f2d2c053c1d0544f34d251b14264
parentc59aca578e9d1b968389d9d27ba8328016c8caf6 (diff)
Notes
-rw-r--r--sys/dev/ichiic/ig4_acpi.c2
-rw-r--r--sys/dev/ichiic/ig4_iic.c51
-rw-r--r--sys/dev/ichiic/ig4_pci.c2
-rw-r--r--sys/dev/ichiic/ig4_var.h2
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_ */