The branch main has been updated by seuros: URL: https://cgit.FreeBSD.org/src/commit/?id=ba28690cc6e0ce6f418122d3db0b1eddec3d93a9
commit ba28690cc6e0ce6f418122d3db0b1eddec3d93a9 Author: Abdelkader Boudih <[email protected]> AuthorDate: 2026-09-06 17:55:02 +0000 Commit: Abdelkader Boudih <[email protected]> CommitDate: 2026-09-06 19:47:44 +0000 apple_bce: fix cold boot panic in mailbox send Poll mailbox reply registers with DELAY() when the system is still cold, falling back to the interrupt-driven sema_timedwait path once timers are available. Reviewed by: adrian Differential Revision: https://reviews.freebsd.org/D58871 --- sys/dev/apple_bce/apple_bce_mailbox.c | 50 ++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/sys/dev/apple_bce/apple_bce_mailbox.c b/sys/dev/apple_bce/apple_bce_mailbox.c index c19a01b7269c..deacb7ed5317 100644 --- a/sys/dev/apple_bce/apple_bce_mailbox.c +++ b/sys/dev/apple_bce/apple_bce_mailbox.c @@ -7,6 +7,7 @@ */ #include <sys/param.h> +#include <sys/systm.h> #include <sys/bus.h> #include <sys/kernel.h> #include <sys/sema.h> @@ -62,20 +63,41 @@ bce_mailbox_send(struct bce_mailbox *mb, uint64_t msg, uint64_t *recv, return (0); } - /* Wait for interrupt-driven reply */ - if (sema_timedwait(&mb->mb_cmpl, hz * timeout_ms / 1000) != 0) { - /* Timeout -- reset to idle */ - atomic_store_int(&mb->status, 0); - return (ETIMEDOUT); - } - - if (atomic_load_int(&mb->status) != 2) { - atomic_store_int(&mb->status, 0); - return (ETIMEDOUT); + if (cold) { + /* + * During early boot, timer-backed sleeps are not available. + * Poll the hardware directly, but account for an installed + * interrupt handler consuming the reply first. + */ + unsigned int waited = 0; + + while (waited < timeout_ms * 1000) { + if (atomic_load_int(&mb->status) == 2) + break; + (void)bce_mailbox_handle_interrupt(mb); + if (atomic_load_int(&mb->status) == 2) + break; + DELAY(100); + waited += 100; + } + if (atomic_load_int(&mb->status) != 2) { + atomic_store_int(&mb->status, 0); + return (ETIMEDOUT); + } + } else { + /* Wait for interrupt-driven reply */ + if (sema_timedwait(&mb->mb_cmpl, + hz * timeout_ms / 1000) != 0) { + atomic_store_int(&mb->status, 0); + return (ETIMEDOUT); + } + if (atomic_load_int(&mb->status) != 2) { + atomic_store_int(&mb->status, 0); + return (ETIMEDOUT); + } } - if (recv != NULL) - *recv = mb->mb_result; + *recv = mb->mb_result; atomic_store_int(&mb->status, 0); return (0); @@ -106,7 +128,9 @@ bce_mailbox_handle_interrupt(struct bce_mailbox *mb) if (atomic_load_int(&mb->status) == 1) { atomic_store_int(&mb->status, 2); - sema_post(&mb->mb_cmpl); + /* A cold sender polls status and must not leave a token. */ + if (!cold) + sema_post(&mb->mb_cmpl); } return (0);
