ichsmb(4) and msleep()

Yuri Pankov yuripv at yuripv.net
Wed Aug 28 11:41:12 UTC 2019


Hans Petter Selasky wrote:
> On 2019-08-28 11:44, Yuri Pankov wrote:
>> Hans Petter Selasky wrote:
>>> On 2019-08-28 11:07, Yuri Pankov wrote:
>>>> I have a "timed sleep before timers are working" panic in ichsmb_readb()
>>>> calling ichsmb_wait() which uses msleep().  That is trying to
>>>> jedec_dimm(4) module so it's trying to attach pretty early in boot.
>>>> What would be the correct replacement for msleep() here?
>>>>
>>>
>>> If you only need a sleep-delay, pause() is the right one. It handles
>>> cold-boot.
>>
>> I guess that won't work here as we need to be waked up by interrupt
>> handler on command completion, and pause() seems to sleep
>> unconditionally for the given time in 'cold' case (if I'm reading the
>> code correctly).
> 
> If you are too early inside a SYSINIT() path, then you cannot use 
> sleeping. You will have to use polling in a loop with a fixed DELAY() to 
> know the timeout.

Thanks for the help.

Something like the following (it seems to work)?


-------------- next part --------------
diff --git a/sys/dev/ichsmb/ichsmb.c b/sys/dev/ichsmb/ichsmb.c
index 5ff54db8600..500df189159 100644
--- a/sys/dev/ichsmb/ichsmb.c
+++ b/sys/dev/ichsmb/ichsmb.c
@@ -608,7 +608,8 @@ ichsmb_device_intr(void *cookie)
 			sc->ich_cmd = -1;
 			bus_write_1(sc->io_res,
 			    ICH_HST_STA, status);
-			wakeup(sc);
+			if (!cold)
+				wakeup(sc);
 			break;
 		}
 
@@ -637,8 +638,25 @@ ichsmb_wait(sc_p sc)
 	KASSERT(sc->ich_cmd != -1,
 	    ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
 	mtx_assert(&sc->mutex, MA_OWNED);
-	error = msleep(sc, &sc->mutex, PZERO, "ichsmb", hz / 4);
-	DBG("msleep -> %d\n", error);
+	if (cold) {
+		const u_int timeout_us = 250000;
+		const u_int delay_us = 500;
+		int i;
+
+		error = EWOULDBLOCK;
+		for (i = 0; i < timeout_us; i += delay_us) {
+			mtx_unlock(&sc->mutex);
+			DELAY(delay_us);
+			mtx_lock(&sc->mutex);
+			if (sc->ich_cmd == -1) {
+				error = 0;
+				break;
+			}
+		}
+	} else {
+		error = msleep(sc, &sc->mutex, PZERO, "ichsmb", hz / 4);
+		DBG("msleep -> %d\n", error);
+	}
 	switch (error) {
 	case 0:
 		smb_error = sc->smb_error;


More information about the freebsd-hackers mailing list