svn commit: r319577 - in head/sys: conf dev/iwm modules/iwm

Adrian Chadd adrian at FreeBSD.org
Sun Jun 4 21:06:00 UTC 2017


Author: adrian
Date: Sun Jun  4 21:05:58 2017
New Revision: 319577
URL: https://svnweb.freebsd.org/changeset/base/319577

Log:
  [iwm] Move Smart Fifo handling into if_iwm_sf.c, sync with Linux iwlwifi.
  
  * This change also fixes a possible issue in the existing smart-fifo code,
    which set the IWM_SF_CFG_DUMMY_NOTIF_OFF bit on AC8260 chipsets, although
    that's only used in iwlwifi for Family 8000 chipsets connected via SDIO
    interface.
  
  Obtained from:	Dragonflybsd.git cb650b01526b0aeef3c4307d926e7f1428997d50

Added:
  head/sys/dev/iwm/if_iwm_sf.c   (contents, props changed)
  head/sys/dev/iwm/if_iwm_sf.h   (contents, props changed)
Modified:
  head/sys/conf/files
  head/sys/dev/iwm/if_iwm.c
  head/sys/dev/iwm/if_iwm_binding.c
  head/sys/dev/iwm/if_iwmvar.h
  head/sys/modules/iwm/Makefile

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Sun Jun  4 21:02:48 2017	(r319576)
+++ head/sys/conf/files	Sun Jun  4 21:05:58 2017	(r319577)
@@ -1864,6 +1864,7 @@ dev/iwm/if_iwm_phy_ctxt.c	optional iwm
 dev/iwm/if_iwm_phy_db.c		optional iwm
 dev/iwm/if_iwm_power.c		optional iwm
 dev/iwm/if_iwm_scan.c		optional iwm
+dev/iwm/if_iwm_sf.c		optional iwm
 dev/iwm/if_iwm_sta.c		optional iwm
 dev/iwm/if_iwm_time_event.c	optional iwm
 dev/iwm/if_iwm_util.c		optional iwm

Modified: head/sys/dev/iwm/if_iwm.c
==============================================================================
--- head/sys/dev/iwm/if_iwm.c	Sun Jun  4 21:02:48 2017	(r319576)
+++ head/sys/dev/iwm/if_iwm.c	Sun Jun  4 21:05:58 2017	(r319577)
@@ -164,6 +164,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/iwm/if_iwm_time_event.h>
 #include <dev/iwm/if_iwm_power.h>
 #include <dev/iwm/if_iwm_scan.h>
+#include <dev/iwm/if_iwm_sf.h>
 #include <dev/iwm/if_iwm_sta.h>
 
 #include <dev/iwm/if_iwm_pcie_trans.h>
@@ -354,10 +355,6 @@ static void	iwm_setrates(struct iwm_softc *, struct iw
 static int	iwm_media_change(struct ifnet *);
 static int	iwm_newstate(struct ieee80211vap *, enum ieee80211_state, int);
 static void	iwm_endscan_cb(void *, int);
-static void	iwm_mvm_fill_sf_command(struct iwm_softc *,
-					struct iwm_sf_cfg_cmd *,
-					struct ieee80211_node *);
-static int	iwm_mvm_sf_config(struct iwm_softc *, enum iwm_sf_state);
 static int	iwm_send_bt_init_conf(struct iwm_softc *);
 static int	iwm_send_update_mcc_cmd(struct iwm_softc *, const char *);
 static void	iwm_mvm_tt_tx_backoff(struct iwm_softc *, uint32_t);
@@ -2989,11 +2986,6 @@ iwm_run_init_mvm_ucode(struct iwm_softc *sc, int justn
 		goto error;
 	}
 
-	/* Init Smart FIFO. */
-	ret = iwm_mvm_sf_config(sc, IWM_SF_INIT_OFF);
-	if (ret)
-		goto error;
-
 	/* Send TX valid antennas before triggering calibrations */
 	ret = iwm_send_tx_ant_cfg(sc, iwm_mvm_get_valid_tx_ant(sc));
 	if (ret) {
@@ -3991,10 +3983,6 @@ iwm_auth(struct ieee80211vap *vap, struct iwm_softc *s
 		goto out;
 	}
 
-	error = iwm_mvm_sf_config(sc, IWM_SF_FULL_ON);
-	if (error != 0)
-		return error;
-
 	error = iwm_allow_mcast(vap, sc);
 	if (error) {
 		device_printf(sc->sc_dev,
@@ -4469,6 +4457,7 @@ iwm_newstate(struct ieee80211vap *vap, enum ieee80211_
 			    "%s: failed to update MAC: %d\n", __func__, error);
 		}
 
+		iwm_mvm_sf_update(sc, vap, FALSE);
 		iwm_mvm_enable_beacon_filter(sc, ivp);
 		iwm_mvm_power_update_mac(sc);
 		iwm_mvm_update_quotas(sc, ivp);
@@ -4506,143 +4495,7 @@ iwm_endscan_cb(void *arg, int pending)
 	ieee80211_scan_done(TAILQ_FIRST(&ic->ic_vaps));
 }
 
-/*
- * Aging and idle timeouts for the different possible scenarios
- * in default configuration
- */
-static const uint32_t
-iwm_sf_full_timeout_def[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES] = {
-	{
-		htole32(IWM_SF_SINGLE_UNICAST_AGING_TIMER_DEF),
-		htole32(IWM_SF_SINGLE_UNICAST_IDLE_TIMER_DEF)
-	},
-	{
-		htole32(IWM_SF_AGG_UNICAST_AGING_TIMER_DEF),
-		htole32(IWM_SF_AGG_UNICAST_IDLE_TIMER_DEF)
-	},
-	{
-		htole32(IWM_SF_MCAST_AGING_TIMER_DEF),
-		htole32(IWM_SF_MCAST_IDLE_TIMER_DEF)
-	},
-	{
-		htole32(IWM_SF_BA_AGING_TIMER_DEF),
-		htole32(IWM_SF_BA_IDLE_TIMER_DEF)
-	},
-	{
-		htole32(IWM_SF_TX_RE_AGING_TIMER_DEF),
-		htole32(IWM_SF_TX_RE_IDLE_TIMER_DEF)
-	},
-};
-
-/*
- * Aging and idle timeouts for the different possible scenarios
- * in single BSS MAC configuration.
- */
-static const uint32_t
-iwm_sf_full_timeout[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES] = {
-	{
-		htole32(IWM_SF_SINGLE_UNICAST_AGING_TIMER),
-		htole32(IWM_SF_SINGLE_UNICAST_IDLE_TIMER)
-	},
-	{
-		htole32(IWM_SF_AGG_UNICAST_AGING_TIMER),
-		htole32(IWM_SF_AGG_UNICAST_IDLE_TIMER)
-	},
-	{
-		htole32(IWM_SF_MCAST_AGING_TIMER),
-		htole32(IWM_SF_MCAST_IDLE_TIMER)
-	},
-	{
-		htole32(IWM_SF_BA_AGING_TIMER),
-		htole32(IWM_SF_BA_IDLE_TIMER)
-	},
-	{
-		htole32(IWM_SF_TX_RE_AGING_TIMER),
-		htole32(IWM_SF_TX_RE_IDLE_TIMER)
-	},
-};
-
-static void
-iwm_mvm_fill_sf_command(struct iwm_softc *sc, struct iwm_sf_cfg_cmd *sf_cmd,
-    struct ieee80211_node *ni)
-{
-	int i, j, watermark;
-
-	sf_cmd->watermark[IWM_SF_LONG_DELAY_ON] = htole32(IWM_SF_W_MARK_SCAN);
-
-	/*
-	 * If we are in association flow - check antenna configuration
-	 * capabilities of the AP station, and choose the watermark accordingly.
-	 */
-	if (ni) {
-		if (ni->ni_flags & IEEE80211_NODE_HT) {
-#ifdef notyet
-			if (ni->ni_rxmcs[2] != 0)
-				watermark = IWM_SF_W_MARK_MIMO3;
-			else if (ni->ni_rxmcs[1] != 0)
-				watermark = IWM_SF_W_MARK_MIMO2;
-			else
-#endif
-				watermark = IWM_SF_W_MARK_SISO;
-		} else {
-			watermark = IWM_SF_W_MARK_LEGACY;
-		}
-	/* default watermark value for unassociated mode. */
-	} else {
-		watermark = IWM_SF_W_MARK_MIMO2;
-	}
-	sf_cmd->watermark[IWM_SF_FULL_ON] = htole32(watermark);
-
-	for (i = 0; i < IWM_SF_NUM_SCENARIO; i++) {
-		for (j = 0; j < IWM_SF_NUM_TIMEOUT_TYPES; j++) {
-			sf_cmd->long_delay_timeouts[i][j] =
-					htole32(IWM_SF_LONG_DELAY_AGING_TIMER);
-		}
-	}
-
-	if (ni) {
-		memcpy(sf_cmd->full_on_timeouts, iwm_sf_full_timeout,
-		       sizeof(iwm_sf_full_timeout));
-	} else {
-		memcpy(sf_cmd->full_on_timeouts, iwm_sf_full_timeout_def,
-		       sizeof(iwm_sf_full_timeout_def));
-	}
-}
-
 static int
-iwm_mvm_sf_config(struct iwm_softc *sc, enum iwm_sf_state new_state)
-{
-	struct ieee80211com *ic = &sc->sc_ic;
-	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
-	struct iwm_sf_cfg_cmd sf_cmd = {
-		.state = htole32(IWM_SF_FULL_ON),
-	};
-	int ret = 0;
-
-	if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000)
-		sf_cmd.state |= htole32(IWM_SF_CFG_DUMMY_NOTIF_OFF);
-
-	switch (new_state) {
-	case IWM_SF_UNINIT:
-	case IWM_SF_INIT_OFF:
-		iwm_mvm_fill_sf_command(sc, &sf_cmd, NULL);
-		break;
-	case IWM_SF_FULL_ON:
-		iwm_mvm_fill_sf_command(sc, &sf_cmd, vap->iv_bss);
-		break;
-	default:
-		IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE,
-		    "Invalid state: %d. not sending Smart Fifo cmd\n",
-			  new_state);
-		return EINVAL;
-	}
-
-	ret = iwm_mvm_send_cmd_pdu(sc, IWM_REPLY_SF_CFG_CMD, IWM_CMD_ASYNC,
-				   sizeof(sf_cmd), &sf_cmd);
-	return ret;
-}
-
-static int
 iwm_send_bt_init_conf(struct iwm_softc *sc)
 {
 	struct iwm_bt_coex_cmd bt_cmd;
@@ -4743,6 +4596,8 @@ iwm_init_hw(struct iwm_softc *sc)
 	struct ieee80211com *ic = &sc->sc_ic;
 	int error, i, ac;
 
+	sc->sf_state = IWM_SF_UNINIT;
+
 	if ((error = iwm_start_hw(sc)) != 0) {
 		printf("iwm_start_hw: failed %d\n", error);
 		return error;
@@ -4771,6 +4626,10 @@ iwm_init_hw(struct iwm_softc *sc)
 		goto error;
 	}
 
+	error = iwm_mvm_sf_update(sc, NULL, FALSE);
+	if (error)
+		device_printf(sc->sc_dev, "Failed to initialize Smart Fifo\n");
+
 	if ((error = iwm_send_bt_init_conf(sc)) != 0) {
 		device_printf(sc->sc_dev, "bt init conf failed\n");
 		goto error;
@@ -5935,6 +5794,8 @@ iwm_attach(device_t dev)
 		device_printf(dev, "failed to init notification wait struct\n");
 		goto fail;
 	}
+
+	sc->sf_state = IWM_SF_UNINIT;
 
 	/* Init phy db */
 	sc->sc_phy_db = iwm_phy_db_init(sc);

Modified: head/sys/dev/iwm/if_iwm_binding.c
==============================================================================
--- head/sys/dev/iwm/if_iwm_binding.c	Sun Jun  4 21:02:48 2017	(r319576)
+++ head/sys/dev/iwm/if_iwm_binding.c	Sun Jun  4 21:05:58 2017	(r319577)
@@ -140,6 +140,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/iwm/if_iwm_debug.h>
 #include <dev/iwm/if_iwm_util.h>
 #include <dev/iwm/if_iwm_binding.h>
+#include <dev/iwm/if_iwm_sf.h>
 
 /*
  * BEGIN iwlwifi/mvm/binding.c
@@ -223,14 +224,12 @@ iwm_mvm_binding_add_vif(struct iwm_softc *sc, struct i
 	if (!ivp->phy_ctxt)
 		return EINVAL;
 
-#ifdef notyet
 	/*
 	 * Update SF - Disable if needed. if this fails, SF might still be on
 	 * while many macs are bound, which is forbidden - so fail the binding.
 	 */
-	if (iwm_mvm_sf_update(sc, ivp, FALSE))
+	if (iwm_mvm_sf_update(sc, &ivp->iv_vap, FALSE))
 		return EINVAL;
-#endif
 
 	return iwm_mvm_binding_update(sc, ivp, ivp->phy_ctxt, TRUE);
 }
@@ -245,13 +244,11 @@ iwm_mvm_binding_remove_vif(struct iwm_softc *sc, struc
 
 	ret = iwm_mvm_binding_update(sc, ivp, ivp->phy_ctxt, FALSE);
 
-#ifdef notyet
 	if (!ret) {
-		if (iwm_mvm_sf_update(sc, ivp, TRUE))
+		if (iwm_mvm_sf_update(sc, &ivp->iv_vap, TRUE))
 			device_printf(sc->sc_dev,
 			    "Failed to update SF state\n");
 	}
-#endif
 
 	return ret;
 }

Added: head/sys/dev/iwm/if_iwm_sf.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/iwm/if_iwm_sf.c	Sun Jun  4 21:05:58 2017	(r319577)
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2014 genua mbh <info at genua.de>
+ * Copyright (c) 2014 Fixup Software Ltd.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*-
+ * Based on BSD-licensed source modules in the Linux iwlwifi driver,
+ * which were used as the reference documentation for this implementation.
+ *
+ * Driver version we are currently based off of is
+ * Linux 4.7.3 (tag id d7f6728f57e3ecbb7ef34eb7d9f564d514775d75)
+ *
+ ******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <linuxwifi at intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_wlan.h"
+#include "opt_iwm.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/firmware.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/mutex.h>
+#include <sys/module.h>
+#include <sys/proc.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/linker.h>
+
+#include <machine/bus.h>
+#include <machine/endian.h>
+#include <machine/resource.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/bpf.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_regdomain.h>
+#include <net80211/ieee80211_ratectl.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/iwm/if_iwmreg.h>
+#include <dev/iwm/if_iwmvar.h>
+#include <dev/iwm/if_iwm_config.h>
+#include <dev/iwm/if_iwm_debug.h>
+#include <dev/iwm/if_iwm_util.h>
+#include <dev/iwm/if_iwm_sf.h>
+
+/*
+ * Aging and idle timeouts for the different possible scenarios
+ * in default configuration
+ */
+static const uint32_t
+sf_full_timeout_def[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES] = {
+	{
+		htole32(IWM_SF_SINGLE_UNICAST_AGING_TIMER_DEF),
+		htole32(IWM_SF_SINGLE_UNICAST_IDLE_TIMER_DEF)
+	},
+	{
+		htole32(IWM_SF_AGG_UNICAST_AGING_TIMER_DEF),
+		htole32(IWM_SF_AGG_UNICAST_IDLE_TIMER_DEF)
+	},
+	{
+		htole32(IWM_SF_MCAST_AGING_TIMER_DEF),
+		htole32(IWM_SF_MCAST_IDLE_TIMER_DEF)
+	},
+	{
+		htole32(IWM_SF_BA_AGING_TIMER_DEF),
+		htole32(IWM_SF_BA_IDLE_TIMER_DEF)
+	},
+	{
+		htole32(IWM_SF_TX_RE_AGING_TIMER_DEF),
+		htole32(IWM_SF_TX_RE_IDLE_TIMER_DEF)
+	},
+};
+
+/*
+ * Aging and idle timeouts for the different possible scenarios
+ * in single BSS MAC configuration.
+ */
+static const uint32_t
+sf_full_timeout[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES] = {
+	{
+		htole32(IWM_SF_SINGLE_UNICAST_AGING_TIMER),
+		htole32(IWM_SF_SINGLE_UNICAST_IDLE_TIMER)
+	},
+	{
+		htole32(IWM_SF_AGG_UNICAST_AGING_TIMER),
+		htole32(IWM_SF_AGG_UNICAST_IDLE_TIMER)
+	},
+	{
+		htole32(IWM_SF_MCAST_AGING_TIMER),
+		htole32(IWM_SF_MCAST_IDLE_TIMER)
+	},
+	{
+		htole32(IWM_SF_BA_AGING_TIMER),
+		htole32(IWM_SF_BA_IDLE_TIMER)
+	},
+	{
+		htole32(IWM_SF_TX_RE_AGING_TIMER),
+		htole32(IWM_SF_TX_RE_IDLE_TIMER)
+	},
+};
+
+static void
+iwm_mvm_fill_sf_command(struct iwm_softc *sc, struct iwm_sf_cfg_cmd *sf_cmd,
+	struct ieee80211_node *ni)
+{
+	int i, j, watermark;
+
+	sf_cmd->watermark[IWM_SF_LONG_DELAY_ON] = htole32(IWM_SF_W_MARK_SCAN);
+
+	/*
+	 * If we are in association flow - check antenna configuration
+	 * capabilities of the AP station, and choose the watermark accordingly.
+	 */
+	if (ni) {
+		if (ni->ni_flags & IEEE80211_NODE_HT) {
+			watermark = IWM_SF_W_MARK_SISO;
+		} else {
+			watermark = IWM_SF_W_MARK_LEGACY;
+		}
+	/* default watermark value for unassociated mode. */
+	} else {
+		watermark = IWM_SF_W_MARK_MIMO2;
+	}
+	sf_cmd->watermark[IWM_SF_FULL_ON] = htole32(watermark);
+
+	for (i = 0; i < IWM_SF_NUM_SCENARIO; i++) {
+		for (j = 0; j < IWM_SF_NUM_TIMEOUT_TYPES; j++) {
+			sf_cmd->long_delay_timeouts[i][j] =
+					htole32(IWM_SF_LONG_DELAY_AGING_TIMER);
+		}
+	}
+
+	if (ni) {
+		_Static_assert(sizeof(sf_full_timeout) == sizeof(uint32_t) *
+		    IWM_SF_NUM_SCENARIO * IWM_SF_NUM_TIMEOUT_TYPES,
+		    "sf_full_timeout has wrong size");
+
+		memcpy(sf_cmd->full_on_timeouts, sf_full_timeout,
+		       sizeof(sf_full_timeout));
+	} else {
+		_Static_assert(sizeof(sf_full_timeout_def) == sizeof(uint32_t) *
+		    IWM_SF_NUM_SCENARIO * IWM_SF_NUM_TIMEOUT_TYPES,
+		    "sf_full_timeout_def has wrong size");
+
+		memcpy(sf_cmd->full_on_timeouts, sf_full_timeout_def,
+		       sizeof(sf_full_timeout_def));
+	}
+}
+
+static int
+iwm_mvm_sf_config(struct iwm_softc *sc, struct ieee80211_node *ni,
+	enum iwm_sf_state new_state)
+{
+	struct iwm_sf_cfg_cmd sf_cmd = {
+		.state = htole32(IWM_SF_FULL_ON),
+	};
+	int ret = 0;
+
+#ifdef notyet	/* only relevant for sdio variants */
+	if (sc->cfg->disable_dummy_notification)
+		sf_cmd.state |= htole32(IWM_SF_CFG_DUMMY_NOTIF_OFF);
+#endif
+
+	/*
+	 * If an associated AP sta changed its antenna configuration, the state
+	 * will remain FULL_ON but SF parameters need to be reconsidered.
+	 */
+	if (new_state != IWM_SF_FULL_ON && sc->sf_state == new_state)
+		return 0;
+
+	switch (new_state) {
+	case IWM_SF_UNINIT:
+		iwm_mvm_fill_sf_command(sc, &sf_cmd, NULL);
+		break;
+	case IWM_SF_FULL_ON:
+		iwm_mvm_fill_sf_command(sc, &sf_cmd, ni);
+		break;
+	case IWM_SF_INIT_OFF:
+		iwm_mvm_fill_sf_command(sc, &sf_cmd, NULL);
+		break;
+	default:
+		device_printf(sc->sc_dev,
+		    "Invalid state: %d. not sending Smart Fifo cmd\n",
+		    new_state);
+		return EINVAL;
+	}
+
+	ret = iwm_mvm_send_cmd_pdu(sc, IWM_REPLY_SF_CFG_CMD, IWM_CMD_ASYNC,
+				   sizeof(sf_cmd), &sf_cmd);
+	if (!ret)
+		sc->sf_state = new_state;
+
+	return ret;
+}
+
+/*
+ * Update Smart fifo:
+ * Count bound interfaces that are not to be removed, ignoring p2p devices,
+ * and set new state accordingly.
+ */
+int
+iwm_mvm_sf_update(struct iwm_softc *sc, struct ieee80211vap *changed_vif,
+	boolean_t remove_vif)
+{
+	enum iwm_sf_state new_state;
+	struct ieee80211_node *ni = NULL;
+	int num_active_macs = 0;
+
+	/* If changed_vif exists and is not to be removed, add to the count */
+	if (changed_vif && !remove_vif)
+		num_active_macs++;
+
+	switch (num_active_macs) {
+	case 0:
+		/* If there are no active macs - change state to SF_INIT_OFF */
+		new_state = IWM_SF_INIT_OFF;
+		break;
+	case 1:
+		if (!changed_vif)
+			return EINVAL;
+		ni = changed_vif->iv_bss;
+		if (ni != NULL && IWM_NODE(ni)->in_assoc &&
+		    changed_vif->iv_dtim_period) {
+			new_state = IWM_SF_FULL_ON;
+		} else {
+			new_state = IWM_SF_INIT_OFF;
+		}
+		break;
+	default:
+		/* If there are multiple active macs - change to SF_UNINIT */
+		new_state = IWM_SF_UNINIT;
+	}
+	return iwm_mvm_sf_config(sc, ni, new_state);
+}

Added: head/sys/dev/iwm/if_iwm_sf.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/iwm/if_iwm_sf.h	Sun Jun  4 21:05:58 2017	(r319577)
@@ -0,0 +1,82 @@
+/*-
+ * Based on BSD-licensed source modules in the Linux iwlwifi driver,
+ * which were used as the reference documentation for this implementation.
+ *
+ * Driver version we are currently based off of is
+ * Linux 4.7.3 (tag id d7f6728f57e3ecbb7ef34eb7d9f564d514775d75)
+ *
+ ***********************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2016        Intel Deutschland GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <linuxwifi at intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2016        Intel Deutschland GmbH
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef	__IF_IWM_SF_H__
+#define	__IF_IWM_SF_H__
+
+extern	int iwm_mvm_sf_update(struct iwm_softc *sc,
+			      struct ieee80211vap *changed_vif,
+			      boolean_t remove_vif);
+
+#endif	/* __IF_IWM_SF_H__ */

Modified: head/sys/dev/iwm/if_iwmvar.h
==============================================================================
--- head/sys/dev/iwm/if_iwmvar.h	Sun Jun  4 21:02:48 2017	(r319576)
+++ head/sys/dev/iwm/if_iwmvar.h	Sun Jun  4 21:05:58 2017	(r319577)
@@ -558,6 +558,9 @@ struct iwm_softc {
 
 	boolean_t		last_ebs_successful;
 
+	/* last smart fifo state that was successfully sent to firmware */
+	enum iwm_sf_state	sf_state;
+
 	/* Indicate if device power save is allowed */
 	boolean_t		sc_ps_disabled;
 };

Modified: head/sys/modules/iwm/Makefile
==============================================================================
--- head/sys/modules/iwm/Makefile	Sun Jun  4 21:02:48 2017	(r319576)
+++ head/sys/modules/iwm/Makefile	Sun Jun  4 21:05:58 2017	(r319577)
@@ -7,7 +7,7 @@ KMOD=	if_iwm
 SRCS=	if_iwm.c if_iwm_binding.c if_iwm_util.c if_iwm_phy_db.c
 SRCS+=	if_iwm_mac_ctxt.c if_iwm_phy_ctxt.c if_iwm_time_event.c
 SRCS+=	if_iwm_power.c if_iwm_scan.c if_iwm_led.c if_iwm_notif_wait.c
-SRCS+=	if_iwm_7000.c if_iwm_8000.c if_iwm_fw.c if_iwm_sta.c
+SRCS+=	if_iwm_7000.c if_iwm_8000.c if_iwm_fw.c if_iwm_sta.c if_iwm_sf.c
 # bus layer
 SRCS+=	if_iwm_pcie_trans.c
 SRCS+=	device_if.h bus_if.h pci_if.h opt_wlan.h opt_iwm.h


More information about the svn-src-all mailing list