-/* $OpenBSD: if_iwm.c,v 1.380 2021/11/19 13:05:19 stsp Exp $ */
+/* $OpenBSD: if_iwm.c,v 1.381 2021/11/22 10:23:42 stsp Exp $ */
/*
* Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
void iwm_attach(struct device *, struct device *, void *);
void iwm_init_task(void *);
int iwm_activate(struct device *, int);
-int iwm_resume(struct iwm_softc *);
+void iwm_resume(struct iwm_softc *);
+int iwm_wakeup(struct iwm_softc *);
#if NBPFILTER > 0
void iwm_radiotap_attach(struct iwm_softc *);
iwm_check_rfkill(struct iwm_softc *sc)
{
uint32_t v;
- int s;
int rv;
- s = splnet();
-
/*
* "documentation" is not really helpful here:
* 27: HW_RF_KILL_SW
sc->sc_flags &= ~IWM_FLAG_RFKILL;
}
- splx(s);
return rv;
}
void
iwm_disable_interrupts(struct iwm_softc *sc)
{
- int s = splnet();
-
if (!sc->sc_msix) {
IWM_WRITE(sc, IWM_CSR_INT_MASK, 0);
IWM_WRITE(sc, IWM_CSR_MSIX_HW_INT_MASK_AD,
sc->sc_hw_init_mask);
}
-
- splx(s);
}
void
iwm_init_hw(struct iwm_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
- int err, i, ac, qid;
-
- err = iwm_preinit(sc);
- if (err)
- return err;
-
- err = iwm_start_hw(sc);
- if (err) {
- printf("%s: could not initialize hardware\n", DEVNAME(sc));
- return err;
- }
+ int err, i, ac, qid, s;
err = iwm_run_init_mvm_ucode(sc, 0);
if (err)
}
/* Restart, this time with the regular firmware */
+ s = splnet();
err = iwm_load_ucode_wait_alive(sc, IWM_UCODE_TYPE_REGULAR);
if (err) {
printf("%s: could not load firmware\n", DEVNAME(sc));
- goto err;
+ splx(s);
+ return err;
}
- if (!iwm_nic_lock(sc))
+ if (!iwm_nic_lock(sc)) {
+ splx(s);
return EBUSY;
+ }
err = iwm_send_tx_ant_cfg(sc, iwm_fw_valid_tx_ant(sc));
if (err) {
if (err) {
printf("%s: could not init bt coex (error %d)\n",
DEVNAME(sc), err);
- return err;
+ goto err;
}
if (isset(sc->sc_enabled_capa,
IWM_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT)) {
err = iwm_send_soc_conf(sc);
if (err)
- return err;
+ goto err;
}
if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT)) {
err = iwm_send_dqa_cmd(sc);
if (err)
- return err;
+ goto err;
}
/* Add auxiliary station for scanning */
err:
iwm_nic_unlock(sc);
+ splx(s);
return err;
}
KASSERT(sc->task_refs.refs == 0);
refcnt_init(&sc->task_refs);
+ err = iwm_preinit(sc);
+ if (err)
+ return err;
+
+ err = iwm_start_hw(sc);
+ if (err) {
+ printf("%s: could not initialize hardware\n", DEVNAME(sc));
+ return err;
+ }
+
err = iwm_init_hw(sc);
if (err) {
if (generation == sc->sc_generation)
return;
}
- /* Clear device-specific "PCI retry timeout" register (41h). */
+ /*
+ * We disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state.
+ */
reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);
splx(s);
}
-int
+void
iwm_resume(struct iwm_softc *sc)
{
pcireg_t reg;
- /* Clear device-specific "PCI retry timeout" register (41h). */
+ /*
+ * We disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state.
+ */
reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);
}
iwm_disable_interrupts(sc);
+}
+
+int
+iwm_wakeup(struct iwm_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = &sc->sc_ic.ic_if;
+ int err;
- return iwm_start_hw(sc);
+ refcnt_init(&sc->task_refs);
+
+ err = iwm_start_hw(sc);
+ if (err)
+ return err;
+
+ err = iwm_init_hw(sc);
+ if (err)
+ return err;
+
+ ifq_clr_oactive(&ifp->if_snd);
+ ifp->if_flags |= IFF_RUNNING;
+
+ if (ic->ic_opmode == IEEE80211_M_MONITOR)
+ ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
+ else
+ ieee80211_begin_scan(ifp);
+
+ return 0;
}
int
}
break;
case DVACT_RESUME:
- err = iwm_resume(sc);
- if (err)
- printf("%s: could not initialize hardware\n",
- DEVNAME(sc));
+ iwm_resume(sc);
break;
case DVACT_WAKEUP:
- /* Hardware should be up at this point. */
- if (iwm_set_hw_ready(sc))
- task_add(systq, &sc->init_task);
+ if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP) {
+ err = iwm_wakeup(sc);
+ if (err)
+ printf("%s: could not initialize hardware\n",
+ DEVNAME(sc));
+ }
break;
}