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 <[email protected]>
+ * 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 <[email protected]>
+ * 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 <[email protected]>
+ * 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
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to