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