--- a/sys/bus/smbus/ichsmb/ichsmb_var.h 2026-10-05 20:08:40.196220622 +0000 +++ b/sys/bus/smbus/ichsmb/ichsmb_var.h 2026-10-05 20:17:56.009094812 +0000 @@ -63,6 +63,7 @@ u_char block_write; /* 0=read, 1=write */ u_char block_data[32]; /* block read/write data */ struct lock mutex; /* device mutex */ + struct lock xfer_lock; /* serializes whole transactions */ }; typedef struct ichsmb_softc *sc_p; --- a/sys/bus/smbus/ichsmb/ichsmb.c 2026-10-05 20:08:40.192220672 +0000 +++ b/sys/bus/smbus/ichsmb/ichsmb.c 2026-10-05 20:18:26.980697730 +0000 @@ -109,6 +109,7 @@ /* Create mutex */ lockinit(&sc->mutex, "ichsmb", 0, LK_CANRECURSE); + lockinit(&sc->xfer_lock, "ichsmbx", 0, 0); /* Add child: an instance of the "smbus" device */ if ((sc->smb = device_add_child(dev, DRIVER_SMBUS, -1)) == NULL) { @@ -137,6 +138,7 @@ return (0); fail: + lockuninit(&sc->xfer_lock); lockuninit(&sc->mutex); return (error); } @@ -171,6 +173,7 @@ int smb_error; DBG("slave=0x%02x how=%d\n", slave, how); + lockmgr(&sc->xfer_lock, LK_EXCLUSIVE); KASSERT(sc->ich_cmd == -1, ("%s: ich_cmd=%d", __func__ , sc->ich_cmd)); switch (how) { @@ -189,6 +192,7 @@ default: smb_error = SMB_ENOTSUPP; } + lockmgr(&sc->xfer_lock, LK_RELEASE); DBG("smb_error=%d\n", smb_error); return (smb_error); } @@ -200,6 +204,7 @@ int smb_error; DBG("slave=0x%02x byte=0x%02x\n", slave, (u_char)byte); + lockmgr(&sc->xfer_lock, LK_EXCLUSIVE); KASSERT(sc->ich_cmd == -1, ("%s: ich_cmd=%d", __func__ , sc->ich_cmd)); lockmgr(&sc->mutex, LK_EXCLUSIVE); @@ -211,6 +216,7 @@ ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd); smb_error = ichsmb_wait(sc); lockmgr(&sc->mutex, LK_RELEASE); + lockmgr(&sc->xfer_lock, LK_RELEASE); DBG("smb_error=%d\n", smb_error); return (smb_error); } @@ -222,6 +228,7 @@ int smb_error; DBG("slave=0x%02x\n", slave); + lockmgr(&sc->xfer_lock, LK_EXCLUSIVE); KASSERT(sc->ich_cmd == -1, ("%s: ich_cmd=%d", __func__ , sc->ich_cmd)); lockmgr(&sc->mutex, LK_EXCLUSIVE); @@ -233,6 +240,7 @@ if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR) *byte = bus_read_1(sc->io_res, ICH_D0); lockmgr(&sc->mutex, LK_RELEASE); + lockmgr(&sc->xfer_lock, LK_RELEASE); DBG("smb_error=%d byte=0x%02x\n", smb_error, (u_char)*byte); return (smb_error); } @@ -245,6 +253,7 @@ DBG("slave=0x%02x cmd=0x%02x byte=0x%02x\n", slave, (u_char)cmd, (u_char)byte); + lockmgr(&sc->xfer_lock, LK_EXCLUSIVE); KASSERT(sc->ich_cmd == -1, ("%s: ich_cmd=%d", __func__ , sc->ich_cmd)); lockmgr(&sc->mutex, LK_EXCLUSIVE); @@ -257,6 +266,7 @@ ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd); smb_error = ichsmb_wait(sc); lockmgr(&sc->mutex, LK_RELEASE); + lockmgr(&sc->xfer_lock, LK_RELEASE); DBG("smb_error=%d\n", smb_error); return (smb_error); } @@ -269,6 +279,7 @@ DBG("slave=0x%02x cmd=0x%02x word=0x%04x\n", slave, (u_char)cmd, (u_int16_t)word); + lockmgr(&sc->xfer_lock, LK_EXCLUSIVE); KASSERT(sc->ich_cmd == -1, ("%s: ich_cmd=%d", __func__ , sc->ich_cmd)); lockmgr(&sc->mutex, LK_EXCLUSIVE); @@ -282,6 +293,7 @@ ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd); smb_error = ichsmb_wait(sc); lockmgr(&sc->mutex, LK_RELEASE); + lockmgr(&sc->xfer_lock, LK_RELEASE); DBG("smb_error=%d\n", smb_error); return (smb_error); } @@ -293,6 +305,7 @@ int smb_error; DBG("slave=0x%02x cmd=0x%02x\n", slave, (u_char)cmd); + lockmgr(&sc->xfer_lock, LK_EXCLUSIVE); KASSERT(sc->ich_cmd == -1, ("%s: ich_cmd=%d", __func__ , sc->ich_cmd)); lockmgr(&sc->mutex, LK_EXCLUSIVE); @@ -305,6 +318,7 @@ if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR) *byte = bus_read_1(sc->io_res, ICH_D0); lockmgr(&sc->mutex, LK_RELEASE); + lockmgr(&sc->xfer_lock, LK_RELEASE); DBG("smb_error=%d byte=0x%02x\n", smb_error, (u_char)*byte); return (smb_error); } @@ -316,6 +330,7 @@ int smb_error; DBG("slave=0x%02x cmd=0x%02x\n", slave, (u_char)cmd); + lockmgr(&sc->xfer_lock, LK_EXCLUSIVE); KASSERT(sc->ich_cmd == -1, ("%s: ich_cmd=%d", __func__ , sc->ich_cmd)); lockmgr(&sc->mutex, LK_EXCLUSIVE); @@ -332,6 +347,7 @@ ICH_D1) << 8); } lockmgr(&sc->mutex, LK_RELEASE); + lockmgr(&sc->xfer_lock, LK_RELEASE); DBG("smb_error=%d word=0x%04x\n", smb_error, (u_int16_t)*word); return (smb_error); } @@ -344,6 +360,7 @@ DBG("slave=0x%02x cmd=0x%02x sdata=0x%04x\n", slave, (u_char)cmd, (u_int16_t)sdata); + lockmgr(&sc->xfer_lock, LK_EXCLUSIVE); KASSERT(sc->ich_cmd == -1, ("%s: ich_cmd=%d", __func__ , sc->ich_cmd)); lockmgr(&sc->mutex, LK_EXCLUSIVE); @@ -362,6 +379,7 @@ ICH_D1) << 8); } lockmgr(&sc->mutex, LK_RELEASE); + lockmgr(&sc->xfer_lock, LK_RELEASE); DBG("smb_error=%d rdata=0x%04x\n", smb_error, (u_int16_t)*rdata); return (smb_error); } @@ -388,10 +406,13 @@ } #undef DISP #endif + lockmgr(&sc->xfer_lock, LK_EXCLUSIVE); KASSERT(sc->ich_cmd == -1, ("%s: ich_cmd=%d", __func__ , sc->ich_cmd)); - if (count < 1 || count > 32) + if (count < 1 || count > 32) { + lockmgr(&sc->xfer_lock, LK_RELEASE); return (SMB_EINVAL); + } bcopy(buf, sc->block_data, count); sc->block_count = count; sc->block_index = 1; @@ -408,6 +429,7 @@ ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd); smb_error = ichsmb_wait(sc); lockmgr(&sc->mutex, LK_RELEASE); + lockmgr(&sc->xfer_lock, LK_RELEASE); DBG("smb_error=%d\n", smb_error); return (smb_error); } @@ -416,13 +438,13 @@ ichsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) { const sc_p sc = device_get_softc(dev); + const u_char expect = (*count >= 1 && *count <= 32) ? *count : 32; int smb_error; DBG("slave=0x%02x cmd=0x%02x count=%d\n", slave, (u_char)cmd, count); + lockmgr(&sc->xfer_lock, LK_EXCLUSIVE); KASSERT(sc->ich_cmd == -1, ("%s: ich_cmd=%d", __func__ , sc->ich_cmd)); - if (*count < 1 || *count > 32) - return (SMB_EINVAL); bzero(sc->block_data, sizeof(sc->block_data)); sc->block_count = 0; sc->block_index = 0; @@ -433,14 +455,15 @@ bus_write_1(sc->io_res, ICH_XMIT_SLVA, slave | ICH_XMIT_SLVA_READ); bus_write_1(sc->io_res, ICH_HST_CMD, cmd); - bus_write_1(sc->io_res, ICH_D0, *count); /* XXX? */ + bus_write_1(sc->io_res, ICH_D0, expect); bus_write_1(sc->io_res, ICH_HST_CNT, ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd); if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR) { - bcopy(sc->block_data, buf, min(sc->block_count, *count)); - *count = sc->block_count; + bcopy(sc->block_data, buf, min(sc->block_count, (int)expect)); + *count = min(sc->block_count, 32); } lockmgr(&sc->mutex, LK_RELEASE); + lockmgr(&sc->xfer_lock, LK_RELEASE); DBG("smb_error=%d\n", smb_error); #if ICHSMB_DEBUG #define DISP(ch) (((ch) < 0x20 || (ch) >= 0x7e) ? '.' : (ch)) @@ -688,6 +711,7 @@ return (error); device_delete_child(dev, sc->smb); ichsmb_release_resources(sc); + lockuninit(&sc->xfer_lock); lockuninit(&sc->mutex); return 0; --- a/sys/dev/smbus/smb/smb.c 2026-10-05 20:08:40.196220622 +0000 +++ b/sys/dev/smbus/smb/smb.c 2026-10-05 20:17:56.017094709 +0000 @@ -214,7 +214,7 @@ device_t smbdev = SMB_DEVICE(minor(dev)); int error; int unit; - u_char bcount; + u_char bcount = 32; /* in/out: the controller driver rewrites it */ if (sc == NULL) return (ENXIO);