diff --git a/sys/dev/ichiic/ig4_iic.c b/sys/dev/ichiic/ig4_iic.c --- a/sys/dev/ichiic/ig4_iic.c +++ b/sys/dev/ichiic/ig4_iic.c @@ -537,7 +537,6 @@ int unit; bool rpstart; bool stop; - bool allocated; /* * The hardware interface imposes limits on allowed I2C messages. @@ -599,9 +598,7 @@ } /* Check if device is already allocated with iicbus_request_bus() */ - allocated = sx_xlocked(&sc->call_lock) != 0; - if (!allocated) - sx_xlock(&sc->call_lock); + sx_xlock(&sc->bus_lock); /* Debugging - dump registers. */ if (ig4_dump) { @@ -679,8 +676,7 @@ device_printf(dev, "Warning: NACK for slave address 0x%x\n", msgs[i].slave >> 1); - if (!allocated) - sx_unlock(&sc->call_lock); + sx_unlock(&sc->bus_lock); return (error); } @@ -688,11 +684,8 @@ ig4iic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) { ig4iic_softc_t *sc = device_get_softc(dev); - bool allocated; - allocated = sx_xlocked(&sc->call_lock) != 0; - if (!allocated) - sx_xlock(&sc->call_lock); + sx_xlock(&sc->bus_lock); /* TODO handle speed configuration? */ if (oldaddr != NULL) @@ -701,8 +694,7 @@ if (addr == IIC_UNKNOWN) sc->slave_valid = false; - if (!allocated) - sx_unlock(&sc->call_lock); + sx_unlock(&sc->bus_lock); return (0); } @@ -1035,8 +1027,9 @@ { int error; - mtx_init(&sc->io_lock, "IG4 I/O lock", NULL, MTX_SPIN); sx_init(&sc->call_lock, "IG4 call lock"); + sx_init(&sc->bus_lock, "IG4 bus lock"); + mtx_init(&sc->io_lock, "IG4 I/O lock", NULL, MTX_SPIN); ig4iic_get_config(sc); @@ -1095,15 +1088,18 @@ bus_teardown_intr(sc->dev, sc->intr_res, sc->intr_handle); sx_xlock(&sc->call_lock); + sx_xlock(&sc->bus_lock); sc->iicbus = NULL; sc->intr_handle = NULL; reg_write(sc, IG4_REG_INTR_MASK, 0); set_controller(sc, 0); + sx_xunlock(&sc->bus_lock); sx_xunlock(&sc->call_lock); mtx_destroy(&sc->io_lock); + sx_destroy(&sc->bus_lock); sx_destroy(&sc->call_lock); return (0); @@ -1117,7 +1113,7 @@ /* suspend all children */ error = bus_generic_suspend(sc->dev); - sx_xlock(&sc->call_lock); + sx_xlock(&sc->bus_lock); set_controller(sc, 0); if (IG4_HAS_ADDREGS(sc->version)) { /* @@ -1131,7 +1127,7 @@ */ reg_write(sc, IG4_REG_RESETS_SKL, IG4_RESETS_ASSERT_SKL); } - sx_xunlock(&sc->call_lock); + sx_xunlock(&sc->bus_lock); return (error); } @@ -1140,10 +1136,10 @@ { int error; - sx_xlock(&sc->call_lock); + sx_xlock(&sc->bus_lock); if (ig4iic_set_config(sc, IG4_HAS_ADDREGS(sc->version))) device_printf(sc->dev, "controller error during resume\n"); - sx_xunlock(&sc->call_lock); + sx_xunlock(&sc->bus_lock); error = bus_generic_resume(sc->dev); diff --git a/sys/dev/ichiic/ig4_var.h b/sys/dev/ichiic/ig4_var.h --- a/sys/dev/ichiic/ig4_var.h +++ b/sys/dev/ichiic/ig4_var.h @@ -102,12 +102,16 @@ * with the controller acquire an exclusive lock on call_lock * to prevent interleaving of calls to the interface. * + * Bus_lock provides exclusive access to the bus as call_lock + * is used by an API which is only advisory. + * * io_lock is used as condition variable to synchronize active process * with the interrupt handler. It should not be used for tasks other * than waiting for interrupt and passing parameters to and from * it's handler. */ struct sx call_lock; + struct sx bus_lock; struct mtx io_lock; };