FreeBSD kernel iwm device code
if_iwm_sf.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014 genua mbh <info@genua.de>
3 * Copyright (c) 2014 Fixup Software Ltd.
4 *
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.
8 *
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.
16 */
17
18/*-
19 * Based on BSD-licensed source modules in the Linux iwlwifi driver,
20 * which were used as the reference documentation for this implementation.
21 *
22 * Driver version we are currently based off of is
23 * Linux 4.7.3 (tag id d7f6728f57e3ecbb7ef34eb7d9f564d514775d75)
24 *
25 ******************************************************************************
26 *
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.
29 *
30 * GPL LICENSE SUMMARY
31 *
32 * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
33 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
34 *
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.
38 *
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.
43 *
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,
47 * USA
48 *
49 * The full GNU General Public License is included in this distribution
50 * in the file called COPYING.
51 *
52 * Contact Information:
53 * Intel Linux Wireless <linuxwifi@intel.com>
54 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
55 *
56 * BSD LICENSE
57 *
58 * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
59 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
60 * All rights reserved.
61 *
62 * Redistribution and use in source and binary forms, with or without
63 * modification, are permitted provided that the following conditions
64 * are met:
65 *
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
71 * distribution.
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.
75 *
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.
87 *
88 *****************************************************************************/
89
90#include <sys/cdefs.h>
91__FBSDID("$FreeBSD$");
92
93#include "opt_wlan.h"
94#include "opt_iwm.h"
95
96#include <sys/param.h>
97#include <sys/bus.h>
98#include <sys/conf.h>
99#include <sys/endian.h>
100#include <sys/firmware.h>
101#include <sys/kernel.h>
102#include <sys/malloc.h>
103#include <sys/mbuf.h>
104#include <sys/mutex.h>
105#include <sys/module.h>
106#include <sys/proc.h>
107#include <sys/rman.h>
108#include <sys/socket.h>
109#include <sys/sockio.h>
110#include <sys/sysctl.h>
111#include <sys/linker.h>
112
113#include <machine/bus.h>
114#include <machine/endian.h>
115#include <machine/resource.h>
116
117#include <net/if.h>
118#include <net/if_var.h>
119#include <net/if_arp.h>
120#include <net/if_dl.h>
121#include <net/if_media.h>
122#include <net/if_types.h>
123#include <net/bpf.h>
124
125#include <netinet/in.h>
126#include <netinet/in_systm.h>
127#include <netinet/if_ether.h>
128#include <netinet/ip.h>
129
130#include <net80211/ieee80211_var.h>
131#include <net80211/ieee80211_regdomain.h>
132#include <net80211/ieee80211_ratectl.h>
133#include <net80211/ieee80211_radiotap.h>
134
135#include <dev/iwm/if_iwmreg.h>
136#include <dev/iwm/if_iwmvar.h>
138#include <dev/iwm/if_iwm_debug.h>
139#include <dev/iwm/if_iwm_util.h>
140#include <dev/iwm/if_iwm_sf.h>
141
142/*
143 * Aging and idle timeouts for the different possible scenarios
144 * in default configuration
145 */
146static const uint32_t
148 {
151 },
152 {
155 },
156 {
159 },
160 {
163 },
164 {
167 },
168};
169
170/*
171 * Aging and idle timeouts for the different possible scenarios
172 * in single BSS MAC configuration.
173 */
174static const uint32_t
176 {
179 },
180 {
183 },
184 {
187 },
188 {
189 htole32(IWM_SF_BA_AGING_TIMER),
190 htole32(IWM_SF_BA_IDLE_TIMER)
191 },
192 {
195 },
196};
197
198static void
200 struct ieee80211_node *ni)
201{
202 int i, j, watermark;
203
205
206 /*
207 * If we are in association flow - check antenna configuration
208 * capabilities of the AP station, and choose the watermark accordingly.
209 */
210 if (ni) {
211 if (ni->ni_flags & IEEE80211_NODE_HT) {
212 watermark = IWM_SF_W_MARK_SISO;
213 } else {
214 watermark = IWM_SF_W_MARK_LEGACY;
215 }
216 /* default watermark value for unassociated mode. */
217 } else {
218 watermark = IWM_SF_W_MARK_MIMO2;
219 }
220 sf_cmd->watermark[IWM_SF_FULL_ON] = htole32(watermark);
221
222 for (i = 0; i < IWM_SF_NUM_SCENARIO; i++) {
223 for (j = 0; j < IWM_SF_NUM_TIMEOUT_TYPES; j++) {
224 sf_cmd->long_delay_timeouts[i][j] =
226 }
227 }
228
229 if (ni) {
230 _Static_assert(sizeof(sf_full_timeout) == sizeof(uint32_t) *
232 "sf_full_timeout has wrong size");
233
234 memcpy(sf_cmd->full_on_timeouts, sf_full_timeout,
235 sizeof(sf_full_timeout));
236 } else {
237 _Static_assert(sizeof(sf_full_timeout_def) == sizeof(uint32_t) *
239 "sf_full_timeout_def has wrong size");
240
242 sizeof(sf_full_timeout_def));
243 }
244}
245
246static int
247iwm_sf_config(struct iwm_softc *sc, struct ieee80211_node *ni,
248 enum iwm_sf_state new_state)
249{
250 struct iwm_sf_cfg_cmd sf_cmd = {
251 .state = htole32(new_state),
252 };
253 int ret = 0;
254
255#ifdef notyet /* only relevant for sdio variants */
256 if (sc->cfg->disable_dummy_notification)
257 sf_cmd.state |= htole32(IWM_SF_CFG_DUMMY_NOTIF_OFF);
258#endif
259
260 /*
261 * If an associated AP sta changed its antenna configuration, the state
262 * will remain FULL_ON but SF parameters need to be reconsidered.
263 */
264 if (new_state != IWM_SF_FULL_ON && sc->sf_state == new_state)
265 return 0;
266
267 switch (new_state) {
268 case IWM_SF_UNINIT:
269 iwm_fill_sf_command(sc, &sf_cmd, NULL);
270 break;
271 case IWM_SF_FULL_ON:
272 iwm_fill_sf_command(sc, &sf_cmd, ni);
273 break;
274 case IWM_SF_INIT_OFF:
275 iwm_fill_sf_command(sc, &sf_cmd, NULL);
276 break;
277 default:
278 device_printf(sc->sc_dev,
279 "Invalid state: %d. not sending Smart Fifo cmd\n",
280 new_state);
281 return EINVAL;
282 }
283
285 sizeof(sf_cmd), &sf_cmd);
286 if (!ret)
287 sc->sf_state = new_state;
288
289 return ret;
290}
291
292/*
293 * Update Smart fifo:
294 * Count bound interfaces that are not to be removed, ignoring p2p devices,
295 * and set new state accordingly.
296 */
297int
298iwm_sf_update(struct iwm_softc *sc, struct ieee80211vap *changed_vif,
299 boolean_t remove_vif)
300{
301 enum iwm_sf_state new_state;
302 struct ieee80211_node *ni = NULL;
303 int num_active_macs = 0;
304
305 /* If changed_vif exists and is not to be removed, add to the count */
306 if (changed_vif && !remove_vif)
307 num_active_macs++;
308
309 switch (num_active_macs) {
310 case 0:
311 /* If there are no active macs - change state to SF_INIT_OFF */
312 new_state = IWM_SF_INIT_OFF;
313 break;
314 case 1:
315 if (!changed_vif)
316 return EINVAL;
317 ni = changed_vif->iv_bss;
318 if (ni != NULL && IWM_NODE(ni)->in_assoc &&
319 changed_vif->iv_dtim_period) {
320 new_state = IWM_SF_FULL_ON;
321 } else {
322 new_state = IWM_SF_INIT_OFF;
323 }
324 break;
325 default:
326 /* If there are multiple active macs - change to SF_UNINIT */
327 new_state = IWM_SF_UNINIT;
328 }
329 return iwm_sf_config(sc, ni, new_state);
330}
_Static_assert(nitems(iwm_nvm_channels)<=IWM_NUM_CHANNELS, "IWM_NUM_CHANNELS is too small")
int iwm_sf_update(struct iwm_softc *sc, struct ieee80211vap *changed_vif, boolean_t remove_vif)
Definition: if_iwm_sf.c:298
static const uint32_t sf_full_timeout_def[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES]
Definition: if_iwm_sf.c:147
__FBSDID("$FreeBSD$")
static void iwm_fill_sf_command(struct iwm_softc *sc, struct iwm_sf_cfg_cmd *sf_cmd, struct ieee80211_node *ni)
Definition: if_iwm_sf.c:199
static int iwm_sf_config(struct iwm_softc *sc, struct ieee80211_node *ni, enum iwm_sf_state new_state)
Definition: if_iwm_sf.c:247
static const uint32_t sf_full_timeout[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES]
Definition: if_iwm_sf.c:175
int iwm_send_cmd_pdu(struct iwm_softc *sc, uint32_t id, uint32_t flags, uint16_t len, const void *data)
Definition: if_iwm_util.c:349
#define IWM_SF_LONG_DELAY_AGING_TIMER
Definition: if_iwmreg.h:3782
#define IWM_SF_BA_IDLE_TIMER_DEF
Definition: if_iwmreg.h:3765
#define IWM_SF_TX_RE_IDLE_TIMER_DEF
Definition: if_iwmreg.h:3767
#define IWM_SF_BA_IDLE_TIMER
Definition: if_iwmreg.h:3777
#define IWM_SF_SINGLE_UNICAST_AGING_TIMER
Definition: if_iwmreg.h:3772
#define IWM_SF_BA_AGING_TIMER
Definition: if_iwmreg.h:3778
#define IWM_SF_SINGLE_UNICAST_AGING_TIMER_DEF
Definition: if_iwmreg.h:3760
#define IWM_SF_W_MARK_SISO
Definition: if_iwmreg.h:3752
#define IWM_SF_CFG_DUMMY_NOTIF_OFF
Definition: if_iwmreg.h:3784
#define IWM_SF_TX_RE_AGING_TIMER
Definition: if_iwmreg.h:3780
#define IWM_SF_TX_RE_IDLE_TIMER
Definition: if_iwmreg.h:3779
#define IWM_SF_MCAST_IDLE_TIMER_DEF
Definition: if_iwmreg.h:3763
#define IWM_SF_MCAST_IDLE_TIMER
Definition: if_iwmreg.h:3775
#define IWM_SF_AGG_UNICAST_IDLE_TIMER
Definition: if_iwmreg.h:3773
#define IWM_SF_SINGLE_UNICAST_IDLE_TIMER
Definition: if_iwmreg.h:3771
#define IWM_SF_W_MARK_LEGACY
Definition: if_iwmreg.h:3755
#define IWM_SF_BA_AGING_TIMER_DEF
Definition: if_iwmreg.h:3766
#define IWM_SF_AGG_UNICAST_AGING_TIMER
Definition: if_iwmreg.h:3774
#define IWM_SF_TX_RE_AGING_TIMER_DEF
Definition: if_iwmreg.h:3768
#define IWM_SF_W_MARK_SCAN
Definition: if_iwmreg.h:3756
#define IWM_SF_W_MARK_MIMO2
Definition: if_iwmreg.h:3753
#define IWM_SF_MCAST_AGING_TIMER
Definition: if_iwmreg.h:3776
@ IWM_SF_NUM_SCENARIO
Definition: if_iwmreg.h:3745
#define IWM_SF_AGG_UNICAST_AGING_TIMER_DEF
Definition: if_iwmreg.h:3762
iwm_sf_state
Definition: if_iwmreg.h:3730
@ IWM_SF_LONG_DELAY_ON
Definition: if_iwmreg.h:3731
@ IWM_SF_FULL_ON
Definition: if_iwmreg.h:3732
@ IWM_SF_INIT_OFF
Definition: if_iwmreg.h:3734
@ IWM_SF_UNINIT
Definition: if_iwmreg.h:3733
#define IWM_SF_AGG_UNICAST_IDLE_TIMER_DEF
Definition: if_iwmreg.h:3761
#define IWM_SF_MCAST_AGING_TIMER_DEF
Definition: if_iwmreg.h:3764
#define IWM_REPLY_SF_CFG_CMD
Definition: if_iwmreg.h:2093
#define IWM_SF_NUM_TIMEOUT_TYPES
Definition: if_iwmreg.h:3749
#define IWM_SF_SINGLE_UNICAST_IDLE_TIMER_DEF
Definition: if_iwmreg.h:3759
#define IWM_NODE(_ni)
Definition: if_iwmvar.h:392
@ IWM_CMD_ASYNC
Definition: if_iwmvar.h:325
uint32_t state
Definition: if_iwmreg.h:3795
uint32_t watermark[IWM_SF_TRANSIENT_STATES_NUMBER]
Definition: if_iwmreg.h:3796
uint32_t full_on_timeouts[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES]
Definition: if_iwmreg.h:3798
uint32_t long_delay_timeouts[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES]
Definition: if_iwmreg.h:3797
enum iwm_sf_state sf_state
Definition: if_iwmvar.h:543
device_t sc_dev
Definition: if_iwmvar.h:408
const struct iwm_cfg * cfg
Definition: if_iwmvar.h:484