On Mon, Feb 13, 2023 at 01:31:30PM +0100, Stefan Sperling wrote:
> On Sat, Feb 11, 2023 at 06:32:31PM +0300, Vitaliy Makkoveev wrote:
> > Unfortunately the diff doesn't help. I attached photos with debug
> > information and panic report.
> 
> Based on the command code in the firmware trace the error seems to be
> caused by the driver sending this command:
> 
> #define IWX_ADD_STA_KEY       0x17
> 
> It seems the set_key task is running while the driver is in INIT state?
> That is certainly not intended, and it is unclear why this is happening.
> 
> What is the effect of this diff? Do you see the printfs added here?
> 

Still panics. The only printf from your diff I see is "iwx_setkey_task:
in state RUN".

I suspect I found the problem. I made the diff below. It introduced some
debug output to catch thread which sets dram->paging concurrently with
iwx_init_task(). Please note, during this race we have IFF_FLAG set, but
IFF_RUNNING flag not set, so the iwx_init_task() will not call
iwx_stop(), but will call iwx_init().

----[ cut ]----

Index: sys/dev/pci/if_iwx.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwx.c,v
retrieving revision 1.152
diff -u -p -r1.152 if_iwx.c
--- sys/dev/pci/if_iwx.c        24 Jan 2023 16:18:22 -0000      1.152
+++ sys/dev/pci/if_iwx.c        13 Feb 2023 23:37:19 -0000
@@ -8767,6 +8767,7 @@ iwx_init(struct ifnet *ifp)
        struct ieee80211com *ic = &sc->sc_ic;
        int err, generation;
 
+       printf("%s\n", __func__);
        rw_assert_wrlock(&sc->ioctl_rwl);
 
        generation = ++sc->sc_generation;
@@ -8901,6 +8902,7 @@ iwx_stop(struct ifnet *ifp)
        struct iwx_node *in = (void *)ic->ic_bss;
        int i, s = splnet();
 
+       printf("%s\n", __func__);
        rw_assert_wrlock(&sc->ioctl_rwl);
 
        sc->sc_flags |= IWX_FLAG_SHUTDOWN; /* Disallow new tasks. */
@@ -10444,6 +10446,7 @@ iwx_attach_hook(struct device *self)
        struct iwx_softc *sc = (void *)self;
 
        KASSERT(!cold);
+       printf("%s\n", __func__);
 
        iwx_preinit(sc);
 }
@@ -10944,6 +10947,7 @@ iwx_init_task(void *arg1)
        int fatal = (sc->sc_flags & (IWX_FLAG_HW_ERR | IWX_FLAG_RFKILL));
 
        rw_enter_write(&sc->ioctl_rwl);
+       printf("%s\n", __func__);
        if (generation != sc->sc_generation) {
                rw_exit(&sc->ioctl_rwl);
                splx(s);
@@ -11030,10 +11034,12 @@ iwx_activate(struct device *self, int ac
                }
                break;
        case DVACT_RESUME:
+               printf("%s - resume\n", __func__);
                iwx_resume(sc);
                break;
        case DVACT_WAKEUP:
                if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP) {
+                       printf("%s - wakeup\n", __func__);
                        err = iwx_wakeup(sc);
                        if (err)
                                printf("%s: could not initialize hardware\n",

----[ cut ]----

The output on resume was:

iwx_stop
iwx_activate - resume
iwx_activate - wakeup
iwx0: fatal firmware error
iwx_init_task
iwx_init
panic: kernel diagnostic assertion "dram->....

So iwx_activate():

iwx_activate(struct device *self, int act)
{
        /* ... */
        switch (act) {
                /* ... */
        case DVACT_RESUME:
                printf("%s - resume\n", __func__);
                iwx_resume(sc);
                break;
        case DVACT_WAKEUP:
                if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP) {
                        printf("%s - wakeup\n", __func__);
                        err = iwx_wakeup(sc);


iwx_resume() doesn't do any software context allocation, but
iwx_wakeup() does. It calls iwx_init_hw(), ..., iwx_init_fw_sec() which
allocates "dram->paging". So, when iwx_init_task() scheduled by
interrupt started to run, iwx_init_fw_sec() will be entered again, but
with "dram->paging" set.

I hope this information will be useful to you. I'm not familiar with iwm
code, but existing `if_flags' checks looks wrong to me. May be firmware
errors should be handled with special IWX_FLAG_SW_ERR instead.

I could provide panic screenshot if required.

Reply via email to