Turns out only one of the three ral(4) backend drivers had the proper checks to handle cards that have disappeared in the interrupt handler. This diff adds the necessary code to the other two. This makes my CardBus ral(4) detach properly even if the interface is up:
ral0 at cardbus0 dev 0 function 0 "Ralink RT2561S" rev 0x00: irq 11, address 00:0e:2e:a8:46:c5 ral0: MAC/BBP RT2561C, RF RT2527 ral0 detached ok? P.S. I'm not a big fan of __predict_false(), but it is consistent with the code that's already there in rt2860.c. Index: rt2560.c =================================================================== RCS file: /cvs/src/sys/dev/ic/rt2560.c,v retrieving revision 1.54 diff -u -p -r1.54 rt2560.c --- rt2560.c 28 Aug 2010 18:08:07 -0000 1.54 +++ rt2560.c 4 Sep 2010 20:13:00 -0000 @@ -1337,7 +1337,10 @@ rt2560_intr(void *arg) struct ifnet *ifp = &sc->sc_ic.ic_if; uint32_t r; - if ((r = RAL_READ(sc, RT2560_CSR7)) == 0) + r = RAL_READ(sc, RT2560_CSR7); + if (__predict_false(r == 0xffffffff)) + return 0; /* device likely went away */ + if (r == 0) return 0; /* not for us */ /* disable interrupts */ Index: rt2661.c =================================================================== RCS file: /cvs/src/sys/dev/ic/rt2661.c,v retrieving revision 1.60 diff -u -p -r1.60 rt2661.c --- rt2661.c 28 Aug 2010 18:08:07 -0000 1.60 +++ rt2661.c 4 Sep 2010 20:13:01 -0000 @@ -1247,6 +1247,8 @@ rt2661_intr(void *arg) r1 = RAL_READ(sc, RT2661_INT_SOURCE_CSR); r2 = RAL_READ(sc, RT2661_MCU_INT_SOURCE_CSR); + if (__predict_false(r1 == 0xffffffff && r2 == 0xffffffff)) + return 0; /* device likely went away */ if (r1 == 0 && r2 == 0) return 0; /* not for us */