DF-5506 / fix.diff
--- a/sys/bus/smbus/amdsmb/amdsmb.c +++ b/sys/bus/smbus/amdsmb/amdsmb.c @@ -211,9 +211,9 @@ { int timeout = 500; - while (timeout-- && AMDSMB_ECINB(sc, EC_SC) & EC_SC_IBF) + while (timeout-- > 0 && AMDSMB_ECINB(sc, EC_SC) & EC_SC_IBF) DELAY(1); - if (timeout == 0) { + if (timeout < 0) { device_printf(sc->smbus, "timeout waiting for IBF to clear\n"); return (1); } @@ -225,9 +225,9 @@ { int timeout = 500; - while (timeout-- && ~AMDSMB_ECINB(sc, EC_SC) & EC_SC_OBF) + while (timeout-- > 0 && ~AMDSMB_ECINB(sc, EC_SC) & EC_SC_OBF) DELAY(1); - if (timeout == 0) { + if (timeout < 0) { device_printf(sc->smbus, "timeout waiting for OBF to set\n"); return (1); } @@ -281,20 +281,23 @@ int error, count; AMDSMB_LOCK_ASSERT(sc); - amdsmb_ec_read(sc, SMB_PRTCL, &temp); + if (amdsmb_ec_read(sc, SMB_PRTCL, &temp) != 0) + return (SMB_EBUSERR); if (temp != 0) { count = 10000; do { DELAY(500); - amdsmb_ec_read(sc, SMB_PRTCL, &temp); - } while (temp != 0 && count--); - if (count == 0) + if (amdsmb_ec_read(sc, SMB_PRTCL, &temp) != 0) + return (SMB_EBUSERR); + } while (temp != 0 && count-- > 0); + if (count < 0) return (SMB_ETIMEOUT); } sts = 0; - amdsmb_ec_read(sc, SMB_STS, &sts); + if (amdsmb_ec_read(sc, SMB_STS, &sts) != 0) + return (SMB_EBUSERR); sts &= SMB_STS_STATUS; AMDSMB_DEBUG(kprintf("amdsmb: STS=0x%x\n", sts)); @@ -531,6 +534,10 @@ if ((error = amdsmb_wait(sc)) == SMB_ENOERR) { amdsmb_ec_read(sc, SMB_BCNT, &len); + if (len > 32) + len = 32; /* hw count is untrusted (DF-1091 family) */ + if (len > *count) + len = *count; /* never report more than we stored */ for (i = 0; i < len; i++) { amdsmb_ec_read(sc, SMB_DATA + i, &data); if (i < *count) |