svn commit: r354302 - head/sys/dev/ichiic
Vladimir Kondratyev
wulf at FreeBSD.org
Sun Nov 3 20:53:14 UTC 2019
Author: wulf
Date: Sun Nov 3 20:53:13 2019
New Revision: 354302
URL: https://svnweb.freebsd.org/changeset/base/354302
Log:
[ig4] Allow enabling of polled mode from iicbus allocation callback
If controller is allocated with IIC_NOWAIT option ig4 enables polled mode
for a period of allocation that makes possible to start I2C transfers
from the contexts where sleeping is not allowed e.g. from ithreads or
callouts.
Modified:
head/sys/dev/ichiic/ig4_acpi.c
head/sys/dev/ichiic/ig4_iic.c
head/sys/dev/ichiic/ig4_pci.c
head/sys/dev/ichiic/ig4_var.h
Modified: head/sys/dev/ichiic/ig4_acpi.c
==============================================================================
--- head/sys/dev/ichiic/ig4_acpi.c Sun Nov 3 20:51:22 2019 (r354301)
+++ head/sys/dev/ichiic/ig4_acpi.c Sun Nov 3 20:53:13 2019 (r354302)
@@ -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
};
Modified: head/sys/dev/ichiic/ig4_iic.c
==============================================================================
--- head/sys/dev/ichiic/ig4_iic.c Sun Nov 3 20:51:22 2019 (r354301)
+++ head/sys/dev/ichiic/ig4_iic.c Sun Nov 3 20:53:13 2019 (r354302)
@@ -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, ui
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, ui
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, ui
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,8 +484,41 @@ ig4iic_reset(device_t dev, u_char speed, u_char addr,
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);
}
/*
Modified: head/sys/dev/ichiic/ig4_pci.c
==============================================================================
--- head/sys/dev/ichiic/ig4_pci.c Sun Nov 3 20:51:22 2019 (r354301)
+++ head/sys/dev/ichiic/ig4_pci.c Sun Nov 3 20:53:13 2019 (r354302)
@@ -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
};
Modified: head/sys/dev/ichiic/ig4_var.h
==============================================================================
--- head/sys/dev/ichiic/ig4_var.h Sun Nov 3 20:51:22 2019 (r354301)
+++ head/sys/dev/ichiic/ig4_var.h Sun Nov 3 20:53:13 2019 (r354302)
@@ -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_ */
More information about the svn-src-all
mailing list