Coming from an UP and RUNNING interface, turning off the hardware kill
switch removes the RUNNING flag and powers down the device.

Iff still UP, switching it back on should set RUNNING again to ensure
seemless operation at runtime.

We can do this by fixing the interrupt handler which currently only
cares about the on->off edge, effectively leaving the device powered
down and unitialized after the off->on edge.

Diff below schedules iwm_init() unconditionally on receiving the RF_KILL
interrupt; it'll take care of everything else.  Jumping to the `out'
label is omitted for simplicity here, it is crucial to restore
restore interrupts in this case.  See the end of iwm_intr() inlined here
for ease of review:

         out_ena:
                iwm_restore_interrupts(sc);
         out:
                return rv;
        }


With this, I can toggle my X230's hardware switch to kill the wifi and
toggle it back again to get an uplink again without having to pull it
up manually.

See if_iwn.c revision 1.204 from 11.01.2019 for a pure iwn(4) equivalent
(note how the commit's message last sentence
"iwm(4) already behaves this way." is an obvious lie;  I got confused
during development of that commit.)

Tested with

iwm0 at pci2 dev 0 function 0 "Intel Dual Band Wireless AC 7260" rev 0xbb, msi
iwm0: hw rev 0x140, fw ver 16.242414.0, address xx:xx:xx:xx:xx:xx

OK?

NB: This does not fix the resume path yet.  Toggling the switch
off, suspending, toggling it back on and resuming will currently still
leave the device powered down.  I have a separate diff for that in the
queue (equivalent to if_iwn.c revision 1.207 from 26.02.2019).

Index: if_iwm.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
retrieving revision 1.237
diff -u -p -r1.237 if_iwm.c
--- if_iwm.c    27 Feb 2019 07:47:57 -0000      1.237
+++ if_iwm.c    1 Apr 2019 07:06:20 -0000
@@ -7339,11 +7339,8 @@ iwm_intr(void *arg)
 
        if (r1 & IWM_CSR_INT_BIT_RF_KILL) {
                handled |= IWM_CSR_INT_BIT_RF_KILL;
-               if (iwm_check_rfkill(sc)) {
-                       task_add(systq, &sc->init_task);
-                       rv = 1;
-                       goto out;
-               }
+               iwm_check_rfkill(sc);
+               task_add(systq, &sc->init_task);
        }
 
        if (r1 & IWM_CSR_INT_BIT_SW_ERR) {

Reply via email to