iwm(4) reloads firmware from disk whenever the device is initialized.
This includes suspend/resume, where accessing the disk is not a good idea.
It seems we have been lucky because iwm(4) defers the wakeup step into a
task context, such that disk has resumed when this task gets to run.
But this is not guaranteed and could lead to occasional hangs during resume.
iwx(4) has the opposite problem: It never reloads firmware from disk.
Not even in case the file in /etc/firmware has changed and the interface
is reset with ifconfig down/up.
This patch makes the behaviour consistent across both drivers.
They will reload firmware from disk on down/up, but not during resume.
ok?
diff b81ef55c86817a4ccf18086fd9b7dc3ee49ae415 /usr/src
blob - 0447b445424351f69ada7920a11e56fee7cde77c
file + sys/dev/pci/if_iwm.c
--- sys/dev/pci/if_iwm.c
+++ sys/dev/pci/if_iwm.c
@@ -254,7 +254,7 @@ int iwm_firmware_store_section(struct iwm_softc *, enu
int iwm_set_default_calib(struct iwm_softc *, const void *);
void iwm_fw_info_free(struct iwm_fw_info *);
void iwm_fw_version_str(char *, size_t, uint32_t, uint32_t, uint32_t);
-int iwm_read_firmware(struct iwm_softc *, enum iwm_ucode_type);
+int iwm_read_firmware(struct iwm_softc *);
uint32_t iwm_read_prph_unlocked(struct iwm_softc *, uint32_t);
uint32_t iwm_read_prph(struct iwm_softc *, uint32_t);
void iwm_write_prph_unlocked(struct iwm_softc *, uint32_t, uint32_t);
@@ -681,7 +681,7 @@ iwm_fw_version_str(char *buf, size_t bufsize,
}
int
-iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
+iwm_read_firmware(struct iwm_softc *sc)
{
struct iwm_fw_info *fw = &sc->sc_fw;
struct iwm_tlv_ucode_header *uhdr;
@@ -693,8 +693,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
int err;
size_t len;
- if (fw->fw_status == IWM_FW_STATUS_DONE &&
- ucode_type != IWM_UCODE_TYPE_INIT)
+ if (fw->fw_status == IWM_FW_STATUS_DONE)
return 0;
while (fw->fw_status == IWM_FW_STATUS_INPROGRESS)
@@ -4245,7 +4244,7 @@ iwm_load_ucode_wait_alive(struct iwm_softc *sc,
struct iwm_fw_sects *fw = &sc->sc_fw.fw_sects[ucode_type];
int err;
- err = iwm_read_firmware(sc, ucode_type);
+ err = iwm_read_firmware(sc);
if (err)
return err;
@@ -9991,6 +9990,8 @@ iwm_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
if (!(ifp->if_flags & IFF_RUNNING)) {
+ /* Force reload of firmware image from disk. */
+ sc->sc_fw.fw_status = IWM_FW_STATUS_NONE;
err = iwm_init(ifp);
}
} else {
blob - 096caf79896dcd97f16f0744fb8206ad8a12a9d7
file + sys/dev/pci/if_iwx.c
--- sys/dev/pci/if_iwx.c
+++ sys/dev/pci/if_iwx.c
@@ -8204,6 +8204,8 @@ iwx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
if (!(ifp->if_flags & IFF_RUNNING)) {
+ /* Force reload of firmware image from disk. */
+ sc->sc_fw.fw_status = IWX_FW_STATUS_NONE;
err = iwx_init(ifp);
}
} else {