From owner-svn-src-all@freebsd.org Sun Jun 4 21:06:00 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 5DD81BEF3FA; Sun, 4 Jun 2017 21:06:00 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 286C084C77; Sun, 4 Jun 2017 21:06:00 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v54L5x3W013901; Sun, 4 Jun 2017 21:05:59 GMT (envelope-from adrian@FreeBSD.org) Received: (from adrian@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v54L5wDR013894; Sun, 4 Jun 2017 21:05:58 GMT (envelope-from adrian@FreeBSD.org) Message-Id: <201706042105.v54L5wDR013894@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: adrian set sender to adrian@FreeBSD.org using -f From: Adrian Chadd Date: Sun, 4 Jun 2017 21:05:58 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r319577 - in head/sys: conf dev/iwm modules/iwm X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 04 Jun 2017 21:06:00 -0000 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 #include #include +#include #include #include @@ -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 #include #include +#include /* * 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 + * 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 + * 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 +__FBSDID("$FreeBSD$"); + +#include "opt_wlan.h" +#include "opt_iwm.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * 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 + * 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