git: ba28690cc6e0 - main - apple_bce: fix cold boot panic in mailbox send

From: Abdelkader Boudih <seuros_at_FreeBSD.org>
Date: Sun, 06 Sep 2026 19:48:31 UTC
The branch main has been updated by seuros:

URL: https://cgit.FreeBSD.org/src/commit/?id=ba28690cc6e0ce6f418122d3db0b1eddec3d93a9

commit ba28690cc6e0ce6f418122d3db0b1eddec3d93a9
Author:     Abdelkader Boudih <seuros@FreeBSD.org>
AuthorDate: 2026-09-06 17:55:02 +0000
Commit:     Abdelkader Boudih <seuros@FreeBSD.org>
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);