[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.
This commit is contained in:
parent
c59aca578e
commit
41b24e0917
@ -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
|
||||
};
|
||||
|
@ -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()
|
||||
*/
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user