summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Sperling <stsp@cvs.openbsd.org>2016-09-21 13:53:19 +0000
committerStefan Sperling <stsp@cvs.openbsd.org>2016-09-21 13:53:19 +0000
commit873e166844549fd332f5425a0dde679be92fb4af (patch)
treebf16f79eed25a92fa458f40bb1542364e0c93e87
parent28147bb22f2713fdb412e3434641dd71fe6f8039 (diff)
Properly support the mac context command in iwm. This was wrong in many ways.
This commit includes style fixes as well as actual bug fixes. Remove the global in_assoc flag from the softc. We can just pass a fixed argument to functions to indicate whether we're already associated. Remove in_tfsid from the softc as well. It was implicitly set to zero and never changed. A corresponding macro already exists so use it instead. Always copy the BSSID into the mac context command, as the Linux driver does. This helps the firmware during association. Set the firmware state to 'associated' once we've moved to RUN state and our assoc ID is known. Earlier versions of iwm used to set the firmware to 'associated' but this was disabled in r1.91 since it didn't work correctly due to bugs which are now fixed. Use live DTIM information obtained from the AP, rather than using the default DTIM period of our wireless stack. Check return values of functions called after moving to RUN state. ok sthen@
-rw-r--r--sys/dev/pci/if_iwm.c118
-rw-r--r--sys/dev/pci/if_iwmvar.h6
2 files changed, 67 insertions, 57 deletions
diff --git a/sys/dev/pci/if_iwm.c b/sys/dev/pci/if_iwm.c
index cfa244ac24c..f4a3dffb84e 100644
--- a/sys/dev/pci/if_iwm.c
+++ b/sys/dev/pci/if_iwm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwm.c,v 1.136 2016/09/21 13:29:11 stsp Exp $ */
+/* $OpenBSD: if_iwm.c,v 1.137 2016/09/21 13:53:18 stsp Exp $ */
/*
* Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
@@ -402,10 +402,10 @@ int iwm_config_umac_scan(struct iwm_softc *);
int iwm_umac_scan(struct iwm_softc *);
void iwm_ack_rates(struct iwm_softc *, struct iwm_node *, int *, int *);
void iwm_mac_ctxt_cmd_common(struct iwm_softc *, struct iwm_node *,
- struct iwm_mac_ctx_cmd *, uint32_t);
+ struct iwm_mac_ctx_cmd *, uint32_t, int);
void iwm_mac_ctxt_cmd_fill_sta(struct iwm_softc *, struct iwm_node *,
struct iwm_mac_data_sta *, int);
-int iwm_mac_ctxt_cmd(struct iwm_softc *, struct iwm_node *, uint32_t);
+int iwm_mac_ctxt_cmd(struct iwm_softc *, struct iwm_node *, uint32_t, int);
int iwm_update_quotas(struct iwm_softc *, struct iwm_node *);
int iwm_auth(struct iwm_softc *);
int iwm_assoc(struct iwm_softc *);
@@ -2432,7 +2432,7 @@ iwm_htprot_task(void *arg)
int err;
/* This call updates HT protection based on in->in_ni.ni_htop1. */
- err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY);
+ err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY, 1);
if (err)
printf("%s: could not change HT protection: error %d\n",
DEVNAME(sc), err);
@@ -4992,7 +4992,7 @@ iwm_ack_rates(struct iwm_softc *sc, struct iwm_node *in, int *cck_rates,
void
iwm_mac_ctxt_cmd_common(struct iwm_softc *sc, struct iwm_node *in,
- struct iwm_mac_ctx_cmd *cmd, uint32_t action)
+ struct iwm_mac_ctx_cmd *cmd, uint32_t action, int assoc)
{
#define IWM_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */
struct ieee80211com *ic = &sc->sc_ic;
@@ -5005,14 +5005,11 @@ iwm_mac_ctxt_cmd_common(struct iwm_softc *sc, struct iwm_node *in,
cmd->action = htole32(action);
cmd->mac_type = htole32(IWM_FW_MAC_TYPE_BSS_STA);
- cmd->tsf_id = htole32(in->in_tsfid);
+ cmd->tsf_id = htole32(IWM_TSF_ID_A);
IEEE80211_ADDR_COPY(cmd->node_addr, ic->ic_myaddr);
- if (in->in_assoc) {
- IEEE80211_ADDR_COPY(cmd->bssid_addr, ni->ni_bssid);
- } else {
- IEEE80211_ADDR_COPY(cmd->bssid_addr, etherbroadcastaddr);
- }
+ IEEE80211_ADDR_COPY(cmd->bssid_addr, ni->ni_bssid);
+
iwm_ack_rates(sc, in, &cck_ack_rates, &ofdm_ack_rates);
cmd->cck_rates = htole32(cck_ack_rates);
cmd->ofdm_rates = htole32(ofdm_ack_rates);
@@ -5067,45 +5064,47 @@ iwm_mac_ctxt_cmd_common(struct iwm_softc *sc, struct iwm_node *in,
void
iwm_mac_ctxt_cmd_fill_sta(struct iwm_softc *sc, struct iwm_node *in,
- struct iwm_mac_data_sta *ctxt_sta, int force_assoc_off)
+ struct iwm_mac_data_sta *sta, int assoc)
{
struct ieee80211_node *ni = &in->in_ni;
- struct ieee80211com *ic = &sc->sc_ic;
+ uint32_t dtim_off;
+ uint64_t tsf;
- ctxt_sta->is_assoc = htole32(0);
- ctxt_sta->bi = htole32(ni->ni_intval);
- ctxt_sta->bi_reciprocal = htole32(iwm_reciprocal(ni->ni_intval));
- ctxt_sta->dtim_interval = htole32(ni->ni_intval * ic->ic_dtim_period);
- ctxt_sta->dtim_reciprocal =
- htole32(iwm_reciprocal(ni->ni_intval * ic->ic_dtim_period));
+ dtim_off = ni->ni_dtimcount * ni->ni_intval * IEEE80211_DUR_TU;
+ memcpy(&tsf, ni->ni_tstamp, sizeof(tsf));
+ tsf = letoh64(tsf);
- /* 10 = CONN_MAX_LISTEN_INTERVAL */
- ctxt_sta->listen_interval = htole32(10);
- ctxt_sta->assoc_id = htole32(ni->ni_associd);
+ sta->is_assoc = htole32(assoc);
+ sta->dtim_time = htole32(ni->ni_rstamp + dtim_off);
+ sta->dtim_tsf = htole64(tsf + dtim_off);
+ sta->bi = htole32(ni->ni_intval);
+ sta->bi_reciprocal = htole32(iwm_reciprocal(ni->ni_intval));
+ sta->dtim_interval = htole32(ni->ni_intval * ni->ni_dtimperiod);
+ sta->dtim_reciprocal = htole32(iwm_reciprocal(sta->dtim_interval));
+ sta->listen_interval = htole32(10);
+ sta->assoc_id = htole32(ni->ni_associd);
+ sta->assoc_beacon_arrive_time = htole32(ni->ni_rstamp);
}
int
-iwm_mac_ctxt_cmd(struct iwm_softc *sc, struct iwm_node *in, uint32_t action)
+iwm_mac_ctxt_cmd(struct iwm_softc *sc, struct iwm_node *in, uint32_t action,
+ int assoc)
{
+ struct ieee80211_node *ni = &in->in_ni;
struct iwm_mac_ctx_cmd cmd;
memset(&cmd, 0, sizeof(cmd));
- iwm_mac_ctxt_cmd_common(sc, in, &cmd, action);
+ iwm_mac_ctxt_cmd_common(sc, in, &cmd, action, assoc);
/* Allow beacons to pass through as long as we are not associated or we
* do not have dtim period information */
- if (!in->in_assoc || !sc->sc_ic.ic_dtim_period)
+ if (!assoc || !ni->ni_associd || !ni->ni_dtimperiod)
cmd.filter_flags |= htole32(IWM_MAC_FILTER_IN_BEACON);
else
- cmd.filter_flags &= ~htole32(IWM_MAC_FILTER_IN_BEACON);
+ iwm_mac_ctxt_cmd_fill_sta(sc, in, &cmd.sta, assoc);
- /* Fill the data specific for station mode */
- iwm_mac_ctxt_cmd_fill_sta(sc, in,
- &cmd.sta, action == IWM_FW_CTXT_ACTION_ADD);
-
- return iwm_send_cmd_pdu(sc, IWM_MAC_CONTEXT_CMD, 0, sizeof(cmd),
- &cmd);
+ return iwm_send_cmd_pdu(sc, IWM_MAC_CONTEXT_CMD, 0, sizeof(cmd), &cmd);
}
int
@@ -5179,8 +5178,6 @@ iwm_auth(struct iwm_softc *sc)
uint32_t duration;
int err;
- in->in_assoc = 0;
-
err = iwm_sf_config(sc, IWM_SF_FULL_ON);
if (err)
return err;
@@ -5204,7 +5201,7 @@ iwm_auth(struct iwm_softc *sc)
if (err)
return err;
- err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY);
+ err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY, 0);
if (err) {
printf("%s: failed to update MAC\n", DEVNAME(sc));
return err;
@@ -5233,14 +5230,6 @@ iwm_assoc(struct iwm_softc *sc)
if (err)
return err;
- in->in_assoc = 1;
-
- err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY);
- if (err) {
- printf("%s: failed to update MAC\n", DEVNAME(sc));
- return err;
- }
-
return 0;
}
@@ -5444,10 +5433,6 @@ iwm_newstate_task(void *psc)
/* Reset the device if moving out of AUTH, ASSOC, or RUN. */
/* XXX Is there a way to switch states without a full reset? */
if (ostate > IEEE80211_S_SCAN && nstate < ostate) {
- in = (struct iwm_node *)ic->ic_bss;
- if (in)
- in->in_assoc = 0;
-
iwm_stop_device(sc);
iwm_init_hw(sc);
@@ -5501,16 +5486,46 @@ iwm_newstate_task(void *psc)
case IEEE80211_S_RUN:
in = (struct iwm_node *)ic->ic_bss;
- iwm_power_mac_update_mode(sc, in);
+
+ /* We have now been assigned an associd by the AP. */
+ err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY, 1);
+ if (err) {
+ printf("%s: failed to update MAC\n", DEVNAME(sc));
+ return;
+ }
+
+ err = iwm_power_update_device(sc);
+ if (err) {
+ printf("%s: could send power command (error %d)\n",
+ DEVNAME(sc), err);
+ return;
+ }
#ifdef notyet
/*
* Disabled for now. Default beacon filter settings
* prevent net80211 from getting ERP and HT protection
* updates from beacons.
*/
- iwm_enable_beacon_filter(sc, in);
+ err = iwm_enable_beacon_filter(sc, in);
+ if (err) {
+ printf("%s: could not enable beacon filter\n",
+ DEVNAME(sc));
+ return;
+ }
#endif
- iwm_update_quotas(sc, in);
+ err = iwm_power_mac_update_mode(sc, in);
+ if (err) {
+ printf("%s: could not update MAC power (error %d)\n",
+ DEVNAME(sc), err);
+ return;
+ }
+
+ err = iwm_update_quotas(sc, in);
+ if (err) {
+ printf("%s: could not update quotas (error %d)\n",
+ DEVNAME(sc), err);
+ return;
+ }
ieee80211_amrr_node_init(&sc->sc_amrr, &in->in_amn);
@@ -5875,7 +5890,7 @@ iwm_init_hw(struct iwm_softc *sc)
}
}
- err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_ADD);
+ err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_ADD, 0);
if (err) {
printf("%s: could not add MAC context (error %d)\n",
DEVNAME(sc), err);
@@ -6031,7 +6046,6 @@ iwm_stop(struct ifnet *ifp, int disable)
ifq_clr_oactive(&ifp->if_snd);
in->in_phyctxt = NULL;
- in->in_assoc = 0;
task_del(systq, &sc->init_task);
task_del(sc->sc_nswq, &sc->newstate_task);
diff --git a/sys/dev/pci/if_iwmvar.h b/sys/dev/pci/if_iwmvar.h
index 4273254a4c3..42244ab8130 100644
--- a/sys/dev/pci/if_iwmvar.h
+++ b/sys/dev/pci/if_iwmvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwmvar.h,v 1.23 2016/09/12 10:18:26 stsp Exp $ */
+/* $OpenBSD: if_iwmvar.h,v 1.24 2016/09/21 13:53:18 stsp Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
@@ -501,10 +501,6 @@ struct iwm_node {
uint16_t in_id;
uint16_t in_color;
- int in_tsfid;
-
- /* status "bits" */
- int in_assoc;
struct iwm_lq_cmd in_lq;
struct ieee80211_amrr_node in_amn;