Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 12 May 2017 06:31:58 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r318228 - head/sys/dev/iwm
Message-ID:  <201705120631.v4C6VwJk073411@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Fri May 12 06:31:57 2017
New Revision: 318228
URL: https://svnweb.freebsd.org/changeset/base/318228

Log:
  [iwm] Make powersaving more similar to Linux iwlwifi behaviour.
  
  * Add a per-vap ps_disabled flag, and use it for a workaround which fixes
    an association issue when powersaving is enabled.
  
  * Compute flag that should correpsond to the mvmif->bss_conf.ps flag in
    Linux's iwlwifi (e.g. this disallows powersaving when not associated
    yet).
  
  Inspired-By: Linux iwlwifi
  
  Obtained from:	dragonflybsd.git dc2e69bdfe8c9d7049c8a28da0adffbfbc6de5c0

Modified:
  head/sys/dev/iwm/if_iwm.c
  head/sys/dev/iwm/if_iwm_power.c
  head/sys/dev/iwm/if_iwmvar.h

Modified: head/sys/dev/iwm/if_iwm.c
==============================================================================
--- head/sys/dev/iwm/if_iwm.c	Fri May 12 06:30:50 2017	(r318227)
+++ head/sys/dev/iwm/if_iwm.c	Fri May 12 06:31:57 2017	(r318228)
@@ -4044,7 +4044,15 @@ iwm_auth(struct ieee80211vap *vap, struc
 		    "%s: binding update cmd\n", __func__);
 		goto out;
 	}
-	if ((error = iwm_mvm_power_update_mac(sc)) != 0) {
+	/*
+	 * Authentication becomes unreliable when powersaving is left enabled
+	 * here. Powersaving will be activated again when association has
+	 * finished or is aborted.
+	 */
+	iv->ps_disabled = TRUE;
+	error = iwm_mvm_power_update_mac(sc);
+	iv->ps_disabled = FALSE;
+	if (error != 0) {
 		device_printf(sc->sc_dev,
 		    "%s: failed to update power management\n",
 		    __func__);
@@ -6277,6 +6285,7 @@ iwm_vap_create(struct ieee80211com *ic, 
 	ivp->color = IWM_DEFAULT_COLOR;
 
 	ivp->have_wme = FALSE;
+	ivp->ps_disabled = FALSE;
 
 	ieee80211_ratectl_init(vap);
 	/* Complete setup. */

Modified: head/sys/dev/iwm/if_iwm_power.c
==============================================================================
--- head/sys/dev/iwm/if_iwm_power.c	Fri May 12 06:30:50 2017	(r318227)
+++ head/sys/dev/iwm/if_iwm_power.c	Fri May 12 06:31:57 2017	(r318228)
@@ -285,6 +285,7 @@ iwm_mvm_power_build_cmd(struct iwm_softc
 	struct ieee80211_node *ni = vap->iv_bss;
 	int dtimper, dtimper_msec;
 	int keep_alive;
+	boolean_t bss_conf_ps = FALSE;
 
 	cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(ivp->id,
 	    ivp->color));
@@ -306,6 +307,14 @@ iwm_mvm_power_build_cmd(struct iwm_softc
 		return;
 
 	cmd->flags |= htole16(IWM_POWER_FLAGS_POWER_SAVE_ENA_MSK);
+
+	if (IWM_NODE(ni)->in_assoc &&
+	    (vap->iv_flags & IEEE80211_F_PMGTON) != 0) {
+		bss_conf_ps = TRUE;
+	}
+	if (!bss_conf_ps)
+		return;
+
 	cmd->flags |= htole16(IWM_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
 
 	iwm_mvm_power_config_skip_dtim(sc, cmd);
@@ -370,15 +379,18 @@ iwm_mvm_disable_beacon_filter(struct iwm
 static int
 iwm_mvm_power_set_ps(struct iwm_softc *sc)
 {
-	struct ieee80211vap *vap = TAILQ_FIRST(&sc->sc_ic.ic_vaps);
+	struct ieee80211vap *vap;
 	boolean_t disable_ps;
 	int ret;
 
 	/* disable PS if CAM */
 	disable_ps = (iwm_power_scheme == IWM_POWER_SCHEME_CAM);
 	/* ...or if any of the vifs require PS to be off */
-	if (vap != NULL && (vap->iv_flags & IEEE80211_F_PMGTON) == 0)
-		disable_ps = TRUE;
+	TAILQ_FOREACH(vap, &sc->sc_ic.ic_vaps, iv_next) {
+		struct iwm_vap *ivp = IWM_VAP(vap);
+		if (ivp->phy_ctxt != NULL && ivp->ps_disabled)
+			disable_ps = TRUE;
+	}
 
 	/* update device power state if it has changed */
 	if (sc->sc_ps_disabled != disable_ps) {
@@ -402,11 +414,18 @@ iwm_mvm_power_set_ba(struct iwm_softc *s
 		IWM_BF_CMD_CONFIG_DEFAULTS,
 		.bf_enable_beacon_filter = htole32(1),
 	};
+	struct ieee80211vap *vap = &ivp->iv_vap;
+	struct ieee80211_node *ni = vap->iv_bss;
+	boolean_t bss_conf_ps = FALSE;
 
 	if (!sc->sc_bf.bf_enabled)
 		return 0;
 
-	sc->sc_bf.ba_enabled = !sc->sc_ps_disabled;
+	if (ni != NULL && IWM_NODE(ni)->in_assoc &&
+	    (vap->iv_flags & IEEE80211_F_PMGTON) != 0) {
+		bss_conf_ps = TRUE;
+	}
+	sc->sc_bf.ba_enabled = !sc->sc_ps_disabled && bss_conf_ps;
 
 	return _iwm_mvm_enable_beacon_filter(sc, ivp, &cmd);
 }

Modified: head/sys/dev/iwm/if_iwmvar.h
==============================================================================
--- head/sys/dev/iwm/if_iwmvar.h	Fri May 12 06:30:50 2017	(r318227)
+++ head/sys/dev/iwm/if_iwmvar.h	Fri May 12 06:31:57 2017	(r318228)
@@ -390,6 +390,9 @@ struct iwm_vap {
 		uint16_t edca_txop;
 		uint8_t aifsn;
 	} queue_params[WME_NUM_AC];
+
+	/* indicates that this interface requires PS to be disabled */
+	boolean_t		ps_disabled;
 };
 #define IWM_VAP(_vap)		((struct iwm_vap *)(_vap))
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201705120631.v4C6VwJk073411>