NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/60914: tps65217pmic: panic after failed read, bus released twice
>Number: 60914
>Category: kern
>Synopsis: tps65217pmic: panic after failed read, bus released twice
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Oct 21 04:10:00 +0000 2026
>Originator: Elias Howell
>Release: NetBSD-current 11.99.9 (20261019), NetBSD 11.0
>Organization:
>Environment:
NetBSD armv7 11.0 NetBSD 11.0 (GENERIC) #0: Thu Jul 30 15:23:12 UTC 2026 mkrepro%mkrepro.NetBSD.org@localhost:/usr/src/sys/arch/evbarm/compile/GENERIC evbarm
NetBSD armv7 11.99.9 NetBSD 11.99.9 (GENERIC) #0: Mon Oct 19 09:38:27 UTC 2026 mkrepro%mkrepro.NetBSD.org@localhost:/usr/src/sys/arch/evbarm/compile/GENERIC evbarm
>Description:
When an i2c read to the TPS65217 fails tps65217pmic_reg_read() calls
iic_release_bus() itself. Most of its callers already took the bus
with tps65217pmic_i2c_lock() and release it again with
tps65217pmic_i2c_unlock(). The bus lock gets released twice. At
attach that gets by because mutex_exit() skips the owner check while
cold (13 failed reads at attach, no panic). On -current GENERIC
(DIAGNOSTIC) the first failed read after that, from the power monitor
task, trips the mutex assertion
tps65217pmic0: cannot execute operation
Mutex error: mutex_vector_exit,749: assertion failed:
MUTEX_OWNER(mtx->mtx_owner) == curthread
panic: lock error: Mutex: mutex_vector_exit,749: ...
netbsd:lockdebug_abort+0xec
netbsd:mutex_abort+0x2c
netbsd:mutex_exit+0x120
netbsd:tps65217pmic_power_monitor_task+0x4c
netbsd:sysmon_task_queue_thread+0x8c
11.0 has the same code. Its GENERIC has no DIAGNOSTIC, so from the
code I'd expect it not to panic and just log "cannot execute
operation", but the lock still gets released twice. Without the owner
check the second mutex_exit() just clears the owner, so if another
thread takes the bus between the two releases, the caller's unlock
drops that thread's lock and two threads are on the bus at once. Not
tested on 11.0, that is from reading the code.
Also in tps65217pmic_power_monitor_task(), if tps65217pmic_i2c_lock()
fails it returns with sc_lock still held and never reschedules the
callout.
print_ppath() calls reg_read at attach without holding the bus. A
failed read there released a bus lock nobody held. With the release
gone from reg_read that goes away. It still reads without taking the
bus. I left that alone since it only runs at attach while cold.
Not fixed here and only from reading the code, I haven't tested it.
tps65217reg_set_voltage() takes the bus then calls
tps65217pmic_set_volt(), which calls tps65217pmic_reg_write_l2(),
which takes the bus again.
>How-To-Repeat:
Attach tps65217pmic where reads to the chip fail. I hit it on a
Netgate SG-1000 booting -current with am335x-boneblack.dtb (with the
Ethernet bits changed), which has tps@24 enabled. The SG-1000 has no
PMIC, U-Boot's "i2c probe" only finds the EEPROM at 0x50 on that bus.
It panics about 4 seconds into boot. I didn't boot 11.0 with tps@24
enabled so I haven't seen what 11.0 does with it.
Some reads at 0x24 look like they work and the power monitor says AC
and USB online then offline when the next read fails. Nothing is
there. Those are reads where ti_iic(4) misses the NACK and returns 0
(PR port-arm/60912) and tps65217pmic_reg_read() returns its uninitialized
rv.
>Fix:
Tested on the SG-1000, -current b91976112 plus this and my am3_prcm
and fdt_i2c patches, tps@24 enabled. Before it panicked about 4
seconds into boot. After, no panic. 31 failed reads in the first 50
seconds with each one logged (13 at attach, 18 from the power monitor).
The power monitor was still polling when the console capture ended
at 55 seconds and the board was still up at 2 minutes.
--- a/sys/dev/i2c/tps65217pmic.c
+++ b/sys/dev/i2c/tps65217pmic.c
@@ -448,6 +448,8 @@ tps65217pmic_power_monitor_task(void *aux)
if (tps65217pmic_i2c_lock(sc) != 0) {
device_printf(sc->sc_dev,
"WARNING: unable to perform power monitor task.\n");
+ mutex_exit(&sc->sc_lock);
+ callout_schedule(&sc->sc_powerpollco, hz);
return;
}
status = tps65217pmic_reg_read(sc, TPS65217PMIC_STATUS);
@@ -770,7 +772,6 @@ tps65217pmic_reg_read(struct tps65217pmic_softc *sc, uint8_t reg)
if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, wbuf,
1, &rv, 1, 0)) {
aprint_error_dev(sc->sc_dev, "cannot execute operation\n");
- iic_release_bus(sc->sc_tag, 0);
return 0;
}
Home |
Main Index |
Thread Index |
Old Index