[iwn] fix firmware command use in iwm_auth().
The iwm firmware has separate commands for add, modify and delete for various things (mac, phy context, etc.) The openbsd driver has a habit of just completely resetting the NIC each time, which is technically mostly okay (as long as the reset doesn't actually fail!) but it means a lot of the code is doing ADD when it should do MODIFY. The firmware responds in kind - it just asserts. This fixes auth attempts that occur after the NIC has been already configured. (I'm sure there are more instances of this!) Tested: iwm0: <Intel Dual Band Wireless AC 7260> mem 0xf1400000-0xf1401fff irq 17 at device 0.0 on pci2 iwm0: revision: 0x140, firmware 25.228 (API ver. 9) .. STA mode. Submitted by: Masachika ISHIZUKA <ish@amail.plala.or.jp>
This commit is contained in:
parent
28d7dd9b8b
commit
2d7dec1c18
@ -3159,7 +3159,6 @@ iwm_auth(struct ieee80211vap *vap, struct iwm_softc *sc)
|
||||
struct iwm_node *in;
|
||||
struct iwm_vap *iv = IWM_VAP(vap);
|
||||
uint32_t duration;
|
||||
uint32_t min_duration;
|
||||
int error;
|
||||
|
||||
/*
|
||||
@ -3201,7 +3200,25 @@ iwm_auth(struct ieee80211vap *vap, struct iwm_softc *sc)
|
||||
if (iv->is_uploaded) {
|
||||
if ((error = iwm_mvm_mac_ctxt_changed(sc, vap)) != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: failed to add MAC\n", __func__);
|
||||
"%s: failed to update MAC\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if ((error = iwm_mvm_phy_ctxt_changed(sc, &sc->sc_phyctxt[0],
|
||||
in->in_ni.ni_chan, 1, 1)) != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: failed update phy ctxt\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
in->in_phyctxt = &sc->sc_phyctxt[0];
|
||||
|
||||
if ((error = iwm_mvm_binding_update(sc, in)) != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: binding update cmd\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if ((error = iwm_mvm_update_sta(sc, in)) != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: failed to update sta\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
@ -3210,61 +3227,36 @@ iwm_auth(struct ieee80211vap *vap, struct iwm_softc *sc)
|
||||
"%s: failed to add MAC\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if ((error = iwm_mvm_phy_ctxt_changed(sc, &sc->sc_phyctxt[0],
|
||||
in->in_ni.ni_chan, 1, 1)) != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: failed add phy ctxt\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
in->in_phyctxt = &sc->sc_phyctxt[0];
|
||||
|
||||
if ((error = iwm_mvm_binding_add_vif(sc, in)) != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: binding cmd\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((error = iwm_mvm_add_sta(sc, in)) != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: failed to add MAC\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* a bit superfluous? */
|
||||
while (sc->sc_auth_prot)
|
||||
msleep(&sc->sc_auth_prot, &sc->sc_mtx, 0, "iwmauth", 0);
|
||||
sc->sc_auth_prot = 1;
|
||||
|
||||
duration = min(IWM_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS,
|
||||
200 + in->in_ni.ni_intval);
|
||||
min_duration = min(IWM_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS,
|
||||
100 + in->in_ni.ni_intval);
|
||||
iwm_mvm_protect_session(sc, in, duration, min_duration, 500);
|
||||
|
||||
IWM_DPRINTF(sc, IWM_DEBUG_RESET,
|
||||
"%s: waiting for auth_prot\n", __func__);
|
||||
while (sc->sc_auth_prot != 2) {
|
||||
/*
|
||||
* well, meh, but if the kernel is sleeping for half a
|
||||
* second, we have bigger problems
|
||||
*/
|
||||
if (sc->sc_auth_prot == 0) {
|
||||
if ((error = iwm_mvm_phy_ctxt_changed(sc, &sc->sc_phyctxt[0],
|
||||
in->in_ni.ni_chan, 1, 1)) != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: missed auth window!\n", __func__);
|
||||
"%s: failed add phy ctxt!\n", __func__);
|
||||
error = ETIMEDOUT;
|
||||
goto out;
|
||||
} else if (sc->sc_auth_prot == -1) {
|
||||
}
|
||||
in->in_phyctxt = &sc->sc_phyctxt[0];
|
||||
|
||||
if ((error = iwm_mvm_binding_add_vif(sc, in)) != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: no time event, denied!\n", __func__);
|
||||
sc->sc_auth_prot = 0;
|
||||
error = EAUTH;
|
||||
"%s: binding add cmd\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if ((error = iwm_mvm_add_sta(sc, in)) != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: failed to add sta\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
msleep(&sc->sc_auth_prot, &sc->sc_mtx, 0, "iwmau2", 0);
|
||||
}
|
||||
IWM_DPRINTF(sc, IWM_DEBUG_RESET, "<-%s\n", __func__);
|
||||
|
||||
/*
|
||||
* Prevent the FW from wandering off channel during association
|
||||
* by "protecting" the session with a time event.
|
||||
*/
|
||||
/* XXX duration is in units of TU, not MS */
|
||||
duration = IWM_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS;
|
||||
iwm_mvm_protect_session(sc, in, duration, 500 /* XXX magic number */);
|
||||
DELAY(100);
|
||||
|
||||
error = 0;
|
||||
out:
|
||||
ieee80211_free_node(ni);
|
||||
|
@ -201,13 +201,13 @@ iwm_mvm_binding_cmd(struct iwm_softc *sc, struct iwm_node *in, uint32_t action)
|
||||
}
|
||||
|
||||
int
|
||||
iwm_mvm_binding_update(struct iwm_softc *sc, struct iwm_node *in, int add)
|
||||
iwm_mvm_binding_update(struct iwm_softc *sc, struct iwm_node *in)
|
||||
{
|
||||
return iwm_mvm_binding_cmd(sc, in, IWM_FW_CTXT_ACTION_ADD);
|
||||
return iwm_mvm_binding_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY);
|
||||
}
|
||||
|
||||
int
|
||||
iwm_mvm_binding_add_vif(struct iwm_softc *sc, struct iwm_node *in)
|
||||
{
|
||||
return iwm_mvm_binding_update(sc, in, IWM_FW_CTXT_ACTION_ADD);
|
||||
return iwm_mvm_binding_cmd(sc, in, IWM_FW_CTXT_ACTION_ADD);
|
||||
}
|
||||
|
@ -107,8 +107,7 @@
|
||||
|
||||
extern int iwm_mvm_binding_cmd(struct iwm_softc *sc, struct iwm_node *in,
|
||||
uint32_t action);
|
||||
extern int iwm_mvm_binding_update(struct iwm_softc *sc, struct iwm_node *in,
|
||||
int add);
|
||||
extern int iwm_mvm_binding_update(struct iwm_softc *sc, struct iwm_node *in);
|
||||
extern int iwm_mvm_binding_add_vif(struct iwm_softc *sc, struct iwm_node *in);
|
||||
|
||||
#endif /* __IF_IWM_BINDING_H__ */
|
||||
|
@ -244,7 +244,7 @@ iwm_mvm_time_event_send_add(struct iwm_softc *sc, struct iwm_node *in,
|
||||
|
||||
void
|
||||
iwm_mvm_protect_session(struct iwm_softc *sc, struct iwm_node *in,
|
||||
uint32_t duration, uint32_t min_duration, uint32_t max_delay)
|
||||
uint32_t duration, uint32_t max_delay)
|
||||
{
|
||||
struct iwm_time_event_cmd_v2 time_cmd;
|
||||
|
||||
|
@ -108,6 +108,6 @@
|
||||
#define __IF_IWM_TIME_EVENT_H__
|
||||
|
||||
extern void iwm_mvm_protect_session(struct iwm_softc *sc, struct iwm_node *in,
|
||||
uint32_t duration, uint32_t min_duration, uint32_t max_delay);
|
||||
uint32_t duration, uint32_t max_delay);
|
||||
|
||||
#endif /* __IF_IWM_TIME_EVENT_H__ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user