2 * Copyright (c) 2014 genua mbh <info@genua.de>
3 * Copyright (c) 2014 Fixup Software Ltd.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * Based on BSD-licensed source modules in the Linux iwlwifi driver,
20 * which were used as the reference documentation for this implementation.
22 * Driver version we are currently based off of is
23 * Linux 4.7.3 (tag id d7f6728f57e3ecbb7ef34eb7d9f564d514775d75)
25 ******************************************************************************
27 * This file is provided under a dual BSD/GPLv2 license. When using or
28 * redistributing this file, you may do so under either license.
32 * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
33 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
35 * This program is free software; you can redistribute it and/or modify
36 * it under the terms of version 2 of the GNU General Public License as
37 * published by the Free Software Foundation.
39 * This program is distributed in the hope that it will be useful, but
40 * WITHOUT ANY WARRANTY; without even the implied warranty of
41 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
42 * General Public License for more details.
44 * You should have received a copy of the GNU General Public License
45 * along with this program; if not, write to the Free Software
46 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
49 * The full GNU General Public License is included in this distribution
50 * in the file called COPYING.
52 * Contact Information:
53 * Intel Linux Wireless <linuxwifi@intel.com>
54 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
58 * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
59 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
60 * All rights reserved.
62 * Redistribution and use in source and binary forms, with or without
63 * modification, are permitted provided that the following conditions
66 * * Redistributions of source code must retain the above copyright
67 * notice, this list of conditions and the following disclaimer.
68 * * Redistributions in binary form must reproduce the above copyright
69 * notice, this list of conditions and the following disclaimer in
70 * the documentation and/or other materials provided with the
72 * * Neither the name Intel Corporation nor the names of its
73 * contributors may be used to endorse or promote products derived
74 * from this software without specific prior written permission.
76 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
77 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
78 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
79 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
80 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
81 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
82 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
83 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
84 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
85 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
86 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
88 *****************************************************************************/
90 #include <sys/param.h>
92 #include <sys/endian.h>
93 #include <sys/firmware.h>
94 #include <sys/kernel.h>
95 #include <sys/malloc.h>
98 #include <sys/sysctl.h>
99 #include <sys/linker.h>
101 #include <machine/endian.h>
103 #include <bus/pci/pcivar.h>
104 #include <bus/pci/pcireg.h>
109 #include <net/if_var.h>
110 #include <net/if_arp.h>
111 #include <net/if_dl.h>
112 #include <net/if_media.h>
113 #include <net/if_types.h>
115 #include <netinet/in.h>
116 #include <netinet/in_systm.h>
117 #include <netinet/if_ether.h>
118 #include <netinet/ip.h>
120 #include <netproto/802_11/ieee80211_var.h>
121 #include <netproto/802_11/ieee80211_regdomain.h>
122 #include <netproto/802_11/ieee80211_ratectl.h>
123 #include <netproto/802_11/ieee80211_radiotap.h>
125 #include "if_iwmreg.h"
126 #include "if_iwmvar.h"
127 #include "if_iwm_debug.h"
128 #include "if_iwm_util.h"
129 #include "if_iwm_sf.h"
132 * Aging and idle timeouts for the different possible scenarios
133 * in default configuration
135 static const uint32_t
136 sf_full_timeout_def[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES] = {
138 htole32(IWM_SF_SINGLE_UNICAST_AGING_TIMER_DEF),
139 htole32(IWM_SF_SINGLE_UNICAST_IDLE_TIMER_DEF)
142 htole32(IWM_SF_AGG_UNICAST_AGING_TIMER_DEF),
143 htole32(IWM_SF_AGG_UNICAST_IDLE_TIMER_DEF)
146 htole32(IWM_SF_MCAST_AGING_TIMER_DEF),
147 htole32(IWM_SF_MCAST_IDLE_TIMER_DEF)
150 htole32(IWM_SF_BA_AGING_TIMER_DEF),
151 htole32(IWM_SF_BA_IDLE_TIMER_DEF)
154 htole32(IWM_SF_TX_RE_AGING_TIMER_DEF),
155 htole32(IWM_SF_TX_RE_IDLE_TIMER_DEF)
160 * Aging and idle timeouts for the different possible scenarios
161 * in single BSS MAC configuration.
163 static const uint32_t
164 sf_full_timeout[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES] = {
166 htole32(IWM_SF_SINGLE_UNICAST_AGING_TIMER),
167 htole32(IWM_SF_SINGLE_UNICAST_IDLE_TIMER)
170 htole32(IWM_SF_AGG_UNICAST_AGING_TIMER),
171 htole32(IWM_SF_AGG_UNICAST_IDLE_TIMER)
174 htole32(IWM_SF_MCAST_AGING_TIMER),
175 htole32(IWM_SF_MCAST_IDLE_TIMER)
178 htole32(IWM_SF_BA_AGING_TIMER),
179 htole32(IWM_SF_BA_IDLE_TIMER)
182 htole32(IWM_SF_TX_RE_AGING_TIMER),
183 htole32(IWM_SF_TX_RE_IDLE_TIMER)
188 iwm_mvm_fill_sf_command(struct iwm_softc *sc, struct iwm_sf_cfg_cmd *sf_cmd,
189 struct ieee80211_node *ni)
193 sf_cmd->watermark[IWM_SF_LONG_DELAY_ON] = htole32(IWM_SF_W_MARK_SCAN);
196 * If we are in association flow - check antenna configuration
197 * capabilities of the AP station, and choose the watermark accordingly.
200 if (ni->ni_flags & IEEE80211_NODE_HT) {
201 watermark = IWM_SF_W_MARK_SISO;
203 watermark = IWM_SF_W_MARK_LEGACY;
205 /* default watermark value for unassociated mode. */
207 watermark = IWM_SF_W_MARK_MIMO2;
209 sf_cmd->watermark[IWM_SF_FULL_ON] = htole32(watermark);
211 for (i = 0; i < IWM_SF_NUM_SCENARIO; i++) {
212 for (j = 0; j < IWM_SF_NUM_TIMEOUT_TYPES; j++) {
213 sf_cmd->long_delay_timeouts[i][j] =
214 htole32(IWM_SF_LONG_DELAY_AGING_TIMER);
219 _Static_assert(sizeof(sf_full_timeout) == sizeof(uint32_t) *
220 IWM_SF_NUM_SCENARIO * IWM_SF_NUM_TIMEOUT_TYPES,
221 "sf_full_timeout has wrong size");
223 memcpy(sf_cmd->full_on_timeouts, sf_full_timeout,
224 sizeof(sf_full_timeout));
226 _Static_assert(sizeof(sf_full_timeout_def) == sizeof(uint32_t) *
227 IWM_SF_NUM_SCENARIO * IWM_SF_NUM_TIMEOUT_TYPES,
228 "sf_full_timeout_def has wrong size");
230 memcpy(sf_cmd->full_on_timeouts, sf_full_timeout_def,
231 sizeof(sf_full_timeout_def));
236 iwm_mvm_sf_config(struct iwm_softc *sc, struct ieee80211_node *ni,
237 enum iwm_sf_state new_state)
239 struct iwm_sf_cfg_cmd sf_cmd = {
240 .state = htole32(new_state),
244 #ifdef notyet /* only relevant for sdio variants */
245 if (sc->cfg->disable_dummy_notification)
246 sf_cmd.state |= htole32(IWM_SF_CFG_DUMMY_NOTIF_OFF);
250 * If an associated AP sta changed its antenna configuration, the state
251 * will remain FULL_ON but SF parameters need to be reconsidered.
253 if (new_state != IWM_SF_FULL_ON && sc->sf_state == new_state)
258 iwm_mvm_fill_sf_command(sc, &sf_cmd, NULL);
261 iwm_mvm_fill_sf_command(sc, &sf_cmd, ni);
263 case IWM_SF_INIT_OFF:
264 iwm_mvm_fill_sf_command(sc, &sf_cmd, NULL);
267 device_printf(sc->sc_dev,
268 "Invalid state: %d. not sending Smart Fifo cmd\n",
273 ret = iwm_mvm_send_cmd_pdu(sc, IWM_REPLY_SF_CFG_CMD, IWM_CMD_ASYNC,
274 sizeof(sf_cmd), &sf_cmd);
276 sc->sf_state = new_state;
283 * Count bound interfaces that are not to be removed, ignoring p2p devices,
284 * and set new state accordingly.
287 iwm_mvm_sf_update(struct iwm_softc *sc, struct ieee80211vap *changed_vif,
288 boolean_t remove_vif)
290 enum iwm_sf_state new_state;
291 struct ieee80211_node *ni = NULL;
292 int num_active_macs = 0;
294 /* If changed_vif exists and is not to be removed, add to the count */
295 if (changed_vif && !remove_vif)
298 switch (num_active_macs) {
300 /* If there are no active macs - change state to SF_INIT_OFF */
301 new_state = IWM_SF_INIT_OFF;
306 ni = changed_vif->iv_bss;
307 if (ni != NULL && IWM_NODE(ni)->in_assoc &&
308 changed_vif->iv_dtim_period) {
309 new_state = IWM_SF_FULL_ON;
311 new_state = IWM_SF_INIT_OFF;
315 /* If there are multiple active macs - change to SF_UNINIT */
316 new_state = IWM_SF_UNINIT;
318 return iwm_mvm_sf_config(sc, ni, new_state);