1 /* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
4 * Copyright (c) 2014 genua mbh <info@genua.de>
5 * Copyright (c) 2014 Fixup Software Ltd.
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Based on BSD-licensed source modules in the Linux iwlwifi driver,
22 * which were used as the reference documentation for this implementation.
24 * Driver version we are currently based off of is
25 * Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
27 ***********************************************************************
29 * This file is provided under a dual BSD/GPLv2 license. When using or
30 * redistributing this file, you may do so under either license.
34 * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
36 * This program is free software; you can redistribute it and/or modify
37 * it under the terms of version 2 of the GNU General Public License as
38 * published by the Free Software Foundation.
40 * This program is distributed in the hope that it will be useful, but
41 * WITHOUT ANY WARRANTY; without even the implied warranty of
42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43 * General Public License for more details.
45 * You should have received a copy of the GNU General Public License
46 * along with this program; if not, write to the Free Software
47 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
50 * The full GNU General Public License is included in this distribution
51 * in the file called COPYING.
53 * Contact Information:
54 * Intel Linux Wireless <ilw@linux.intel.com>
55 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
60 * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
61 * All rights reserved.
63 * Redistribution and use in source and binary forms, with or without
64 * modification, are permitted provided that the following conditions
67 * * Redistributions of source code must retain the above copyright
68 * notice, this list of conditions and the following disclaimer.
69 * * Redistributions in binary form must reproduce the above copyright
70 * notice, this list of conditions and the following disclaimer in
71 * the documentation and/or other materials provided with the
73 * * Neither the name Intel Corporation nor the names of its
74 * contributors may be used to endorse or promote products derived
75 * from this software without specific prior written permission.
77 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
78 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
79 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
80 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
81 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
82 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
83 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
84 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
85 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
86 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
87 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
91 * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
93 * Permission to use, copy, modify, and distribute this software for any
94 * purpose with or without fee is hereby granted, provided that the above
95 * copyright notice and this permission notice appear in all copies.
97 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
98 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
99 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
100 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
101 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
102 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
103 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
105 #include <sys/cdefs.h>
106 __FBSDID("$FreeBSD$");
108 #include <sys/param.h>
110 #include <sys/endian.h>
111 #include <sys/firmware.h>
112 #include <sys/kernel.h>
113 #include <sys/malloc.h>
114 #include <sys/mbuf.h>
115 #include <sys/rman.h>
116 #include <sys/sysctl.h>
117 #include <sys/linker.h>
119 #include <machine/endian.h>
121 #include <bus/pci/pcivar.h>
122 #include <bus/pci/pcireg.h>
127 #include <net/if_var.h>
128 #include <net/if_arp.h>
129 #include <net/if_dl.h>
130 #include <net/if_media.h>
131 #include <net/if_types.h>
133 #include <netinet/in.h>
134 #include <netinet/in_systm.h>
135 #include <netinet/if_ether.h>
136 #include <netinet/ip.h>
138 #include <netproto/802_11/ieee80211_var.h>
139 #include <netproto/802_11/ieee80211_regdomain.h>
140 #include <netproto/802_11/ieee80211_ratectl.h>
141 #include <netproto/802_11/ieee80211_radiotap.h>
143 #include "if_iwmreg.h"
144 #include "if_iwmvar.h"
145 #include "if_iwm_debug.h"
146 #include "if_iwm_notif_wait.h"
147 #include "if_iwm_util.h"
148 #include "if_iwm_scan.h"
150 #define IWM_DENSE_EBS_SCAN_RATIO 5
151 #define IWM_SPARSE_EBS_SCAN_RATIO 1
154 iwm_mvm_scan_rx_chain(struct iwm_softc
*sc
)
159 rx_ant
= iwm_mvm_get_valid_rx_ant(sc
);
160 rx_chain
= rx_ant
<< IWM_PHY_RX_CHAIN_VALID_POS
;
161 rx_chain
|= rx_ant
<< IWM_PHY_RX_CHAIN_FORCE_MIMO_SEL_POS
;
162 rx_chain
|= rx_ant
<< IWM_PHY_RX_CHAIN_FORCE_SEL_POS
;
163 rx_chain
|= 0x1 << IWM_PHY_RX_CHAIN_DRIVER_FORCE_POS
;
164 return htole16(rx_chain
);
168 iwm_mvm_scan_rxon_flags(struct ieee80211_channel
*c
)
170 if (IEEE80211_IS_CHAN_2GHZ(c
))
171 return htole32(IWM_PHY_BAND_24
);
173 return htole32(IWM_PHY_BAND_5
);
177 iwm_mvm_scan_rate_n_flags(struct iwm_softc
*sc
, int flags
, int no_cck
)
182 for (i
= 0, ind
= sc
->sc_scan_last_antenna
;
183 i
< IWM_RATE_MCS_ANT_NUM
; i
++) {
184 ind
= (ind
+ 1) % IWM_RATE_MCS_ANT_NUM
;
185 if (iwm_mvm_get_valid_tx_ant(sc
) & (1 << ind
)) {
186 sc
->sc_scan_last_antenna
= ind
;
190 tx_ant
= (1 << sc
->sc_scan_last_antenna
) << IWM_RATE_MCS_ANT_POS
;
192 if ((flags
& IEEE80211_CHAN_2GHZ
) && !no_cck
)
193 return htole32(IWM_RATE_1M_PLCP
| IWM_RATE_MCS_CCK_MSK
|
196 return htole32(IWM_RATE_6M_PLCP
| tx_ant
);
199 static inline boolean_t
200 iwm_mvm_rrm_scan_needed(struct iwm_softc
*sc
)
202 /* require rrm scan whenever the fw supports it */
203 return fw_has_capa(&sc
->ucode_capa
,
204 IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT
);
209 iwm_mvm_ebs_status_str(enum iwm_scan_ebs_status status
)
212 case IWM_SCAN_EBS_SUCCESS
:
214 case IWM_SCAN_EBS_INACTIVE
:
216 case IWM_SCAN_EBS_FAILED
:
217 case IWM_SCAN_EBS_CHAN_NOT_FOUND
:
225 iwm_mvm_rx_lmac_scan_complete_notif(struct iwm_softc
*sc
,
226 struct iwm_rx_packet
*pkt
)
228 struct iwm_periodic_scan_complete
*scan_notif
= (void *)pkt
->data
;
230 boolean_t aborted
= (scan_notif
->status
== IWM_SCAN_OFFLOAD_ABORTED
);
233 /* If this happens, the firmware has mistakenly sent an LMAC
234 * notification during UMAC scans -- warn and ignore it.
236 if (fw_has_capa(&sc
->ucode_capa
, IWM_UCODE_TLV_CAPA_UMAC_SCAN
)) {
237 device_printf(sc
->sc_dev
,
238 "%s: Mistakenly got LMAC notification during UMAC scan\n",
243 IWM_DPRINTF(sc
, IWM_DEBUG_SCAN
, "Regular scan %s, EBS status %s (FW)\n",
244 aborted
? "aborted" : "completed",
245 iwm_mvm_ebs_status_str(scan_notif
->ebs_status
));
247 sc
->last_ebs_successful
=
248 scan_notif
->ebs_status
== IWM_SCAN_EBS_SUCCESS
||
249 scan_notif
->ebs_status
== IWM_SCAN_EBS_INACTIVE
;
254 iwm_mvm_rx_umac_scan_complete_notif(struct iwm_softc
*sc
,
255 struct iwm_rx_packet
*pkt
)
257 struct iwm_umac_scan_complete
*notif
= (void *)pkt
->data
;
259 uint32_t uid
= le32toh(notif
->uid
);
260 boolean_t aborted
= (notif
->status
== IWM_SCAN_OFFLOAD_ABORTED
);
263 IWM_DPRINTF(sc
, IWM_DEBUG_SCAN
,
264 "Scan completed, uid %u, status %s, EBS status %s\n",
266 aborted
? "aborted" : "completed",
267 iwm_mvm_ebs_status_str(notif
->ebs_status
));
269 if (notif
->ebs_status
!= IWM_SCAN_EBS_SUCCESS
&&
270 notif
->ebs_status
!= IWM_SCAN_EBS_INACTIVE
)
271 sc
->last_ebs_successful
= FALSE
;
275 iwm_mvm_scan_skip_channel(struct ieee80211_channel
*c
)
277 if (IEEE80211_IS_CHAN_2GHZ(c
) && IEEE80211_IS_CHAN_B(c
))
279 else if (IEEE80211_IS_CHAN_5GHZ(c
) && IEEE80211_IS_CHAN_A(c
))
286 iwm_mvm_lmac_scan_fill_channels(struct iwm_softc
*sc
,
287 struct iwm_scan_channel_cfg_lmac
*chan
, int n_ssids
)
289 struct ieee80211com
*ic
= &sc
->sc_ic
;
290 struct ieee80211_scan_state
*ss
= ic
->ic_scan
;
291 struct ieee80211_channel
*c
;
296 j
< ss
->ss_last
&& nchan
< sc
->ucode_capa
.n_scan_channels
; j
++) {
299 * Catch other channels, in case we have 900MHz channels or
300 * something in the chanlist.
302 if (!IEEE80211_IS_CHAN_2GHZ(c
) && !IEEE80211_IS_CHAN_5GHZ(c
)) {
303 IWM_DPRINTF(sc
, IWM_DEBUG_RESET
| IWM_DEBUG_EEPROM
,
304 "%s: skipping channel (freq=%d, ieee=%d, flags=0x%08x)\n",
305 __func__
, c
->ic_freq
, c
->ic_ieee
, c
->ic_flags
);
309 IWM_DPRINTF(sc
, IWM_DEBUG_RESET
| IWM_DEBUG_EEPROM
,
310 "Adding channel %d (%d Mhz) to the list\n",
312 chan
->channel_num
= htole16(ieee80211_mhz2ieee(c
->ic_freq
, 0));
313 chan
->iter_count
= htole16(1);
314 chan
->iter_interval
= htole32(0);
315 chan
->flags
= htole32(IWM_UNIFIED_SCAN_CHANNEL_PARTIAL
);
316 #if 0 /* makes scanning while associated less useful */
318 chan
->flags
|= htole32(1 << 1); /* select SSID 0 */
328 iwm_mvm_umac_scan_fill_channels(struct iwm_softc
*sc
,
329 struct iwm_scan_channel_cfg_umac
*chan
, int n_ssids
)
331 struct ieee80211com
*ic
= &sc
->sc_ic
;
332 struct ieee80211_scan_state
*ss
= ic
->ic_scan
;
333 struct ieee80211_channel
*c
;
338 j
< ss
->ss_last
&& nchan
< sc
->ucode_capa
.n_scan_channels
; j
++) {
341 * Catch other channels, in case we have 900MHz channels or
342 * something in the chanlist.
344 if (!IEEE80211_IS_CHAN_2GHZ(c
) && !IEEE80211_IS_CHAN_5GHZ(c
)) {
345 IWM_DPRINTF(sc
, IWM_DEBUG_RESET
| IWM_DEBUG_EEPROM
,
346 "%s: skipping channel (freq=%d, ieee=%d, flags=0x%08x)\n",
347 __func__
, c
->ic_freq
, c
->ic_ieee
, c
->ic_flags
);
351 IWM_DPRINTF(sc
, IWM_DEBUG_RESET
| IWM_DEBUG_EEPROM
,
352 "Adding channel %d (%d Mhz) to the list\n",
354 chan
->channel_num
= ieee80211_mhz2ieee(c
->ic_freq
, 0);
355 chan
->iter_count
= 1;
356 chan
->iter_interval
= htole16(0);
357 chan
->flags
= htole32(0);
358 #if 0 /* makes scanning while associated less useful */
360 chan
->flags
= htole32(1 << 0); /* select SSID 0 */
370 iwm_mvm_fill_probe_req(struct iwm_softc
*sc
, struct iwm_scan_probe_req
*preq
)
372 struct ieee80211com
*ic
= &sc
->sc_ic
;
373 struct ieee80211vap
*vap
= TAILQ_FIRST(&ic
->ic_vaps
);
374 struct ieee80211_frame
*wh
= (struct ieee80211_frame
*)preq
->buf
;
375 struct ieee80211_rateset
*rs
;
376 size_t remain
= sizeof(preq
->buf
);
379 const uint8_t *ssid
= NULL
;
381 memset(preq
, 0, sizeof(*preq
));
383 /* Ensure enough space for header and SSID IE. */
384 if (remain
< sizeof(*wh
) + 2 + ssid_len
)
388 * Build a probe request frame. Most of the following code is a
389 * copy & paste of what is done in net80211.
391 wh
->i_fc
[0] = IEEE80211_FC0_VERSION_0
| IEEE80211_FC0_TYPE_MGT
|
392 IEEE80211_FC0_SUBTYPE_PROBE_REQ
;
393 wh
->i_fc
[1] = IEEE80211_FC1_DIR_NODS
;
394 IEEE80211_ADDR_COPY(wh
->i_addr1
, ieee80211broadcastaddr
);
395 IEEE80211_ADDR_COPY(wh
->i_addr2
, vap
? vap
->iv_myaddr
: ic
->ic_macaddr
);
396 IEEE80211_ADDR_COPY(wh
->i_addr3
, ieee80211broadcastaddr
);
397 *(uint16_t *)&wh
->i_dur
[0] = 0; /* filled by HW */
398 *(uint16_t *)&wh
->i_seq
[0] = 0; /* filled by HW */
400 frm
= (uint8_t *)(wh
+ 1);
401 frm
= ieee80211_add_ssid(frm
, ssid
, ssid_len
);
403 /* Tell the firmware where the MAC header is. */
404 preq
->mac_header
.offset
= 0;
405 preq
->mac_header
.len
= htole16(frm
- (uint8_t *)wh
);
406 remain
-= frm
- (uint8_t *)wh
;
408 /* Fill in 2GHz IEs and tell firmware where they are. */
409 rs
= &ic
->ic_sup_rates
[IEEE80211_MODE_11G
];
410 if (rs
->rs_nrates
> IEEE80211_RATE_SIZE
) {
411 if (remain
< 4 + rs
->rs_nrates
)
413 } else if (remain
< 2 + rs
->rs_nrates
) {
416 preq
->band_data
[0].offset
= htole16(frm
- (uint8_t *)wh
);
418 frm
= ieee80211_add_rates(frm
, rs
);
419 if (rs
->rs_nrates
> IEEE80211_RATE_SIZE
)
420 frm
= ieee80211_add_xrates(frm
, rs
);
421 preq
->band_data
[0].len
= htole16(frm
- pos
);
424 if (iwm_mvm_rrm_scan_needed(sc
)) {
427 *frm
++ = IEEE80211_ELEMID_DSPARMS
;
433 if (sc
->nvm_data
->sku_cap_band_52GHz_enable
) {
434 /* Fill in 5GHz IEs. */
435 rs
= &ic
->ic_sup_rates
[IEEE80211_MODE_11A
];
436 if (rs
->rs_nrates
> IEEE80211_RATE_SIZE
) {
437 if (remain
< 4 + rs
->rs_nrates
)
439 } else if (remain
< 2 + rs
->rs_nrates
) {
442 preq
->band_data
[1].offset
= htole16(frm
- (uint8_t *)wh
);
444 frm
= ieee80211_add_rates(frm
, rs
);
445 if (rs
->rs_nrates
> IEEE80211_RATE_SIZE
)
446 frm
= ieee80211_add_xrates(frm
, rs
);
447 preq
->band_data
[1].len
= htole16(frm
- pos
);
451 /* Send 11n IEs on both 2GHz and 5GHz bands. */
452 preq
->common_data
.offset
= htole16(frm
- (uint8_t *)wh
);
455 if (ic
->ic_flags
& IEEE80211_F_HTON
) {
458 frm
= ieee80211_add_htcaps(frm
, ic
);
459 /* XXX add WME info? */
462 preq
->common_data
.len
= htole16(frm
- pos
);
468 iwm_mvm_config_umac_scan(struct iwm_softc
*sc
)
470 struct ieee80211com
*ic
= &sc
->sc_ic
;
471 struct ieee80211vap
*vap
= TAILQ_FIRST(&ic
->ic_vaps
);
473 struct iwm_scan_config
*scan_config
;
476 struct ieee80211_channel
*c
;
477 struct iwm_host_cmd hcmd
= {
478 .id
= iwm_cmd_id(IWM_SCAN_CFG_CMD
, IWM_ALWAYS_LONG_GROUP
, 0),
479 .flags
= IWM_CMD_SYNC
,
481 static const uint32_t rates
= (IWM_SCAN_CONFIG_RATE_1M
|
482 IWM_SCAN_CONFIG_RATE_2M
| IWM_SCAN_CONFIG_RATE_5M
|
483 IWM_SCAN_CONFIG_RATE_11M
| IWM_SCAN_CONFIG_RATE_6M
|
484 IWM_SCAN_CONFIG_RATE_9M
| IWM_SCAN_CONFIG_RATE_12M
|
485 IWM_SCAN_CONFIG_RATE_18M
| IWM_SCAN_CONFIG_RATE_24M
|
486 IWM_SCAN_CONFIG_RATE_36M
| IWM_SCAN_CONFIG_RATE_48M
|
487 IWM_SCAN_CONFIG_RATE_54M
);
489 cmd_size
= sizeof(*scan_config
) + sc
->ucode_capa
.n_scan_channels
;
491 scan_config
= kmalloc(cmd_size
, M_DEVBUF
, M_INTWAIT
| M_ZERO
);
492 if (scan_config
== NULL
)
495 scan_config
->tx_chains
= htole32(iwm_mvm_get_valid_tx_ant(sc
));
496 scan_config
->rx_chains
= htole32(iwm_mvm_get_valid_rx_ant(sc
));
497 scan_config
->legacy_rates
= htole32(rates
|
498 IWM_SCAN_CONFIG_SUPPORTED_RATE(rates
));
500 /* These timings correspond to iwlwifi's UNASSOC scan. */
501 scan_config
->dwell_active
= 10;
502 scan_config
->dwell_passive
= 110;
503 scan_config
->dwell_fragmented
= 44;
504 scan_config
->dwell_extended
= 90;
505 scan_config
->out_of_channel_time
= htole32(0);
506 scan_config
->suspend_time
= htole32(0);
508 IEEE80211_ADDR_COPY(scan_config
->mac_addr
,
509 vap
? vap
->iv_myaddr
: ic
->ic_macaddr
);
511 scan_config
->bcast_sta_id
= sc
->sc_aux_sta
.sta_id
;
512 scan_config
->channel_flags
= IWM_CHANNEL_FLAG_EBS
|
513 IWM_CHANNEL_FLAG_ACCURATE_EBS
| IWM_CHANNEL_FLAG_EBS_ADD
|
514 IWM_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE
;
517 j
< ic
->ic_nchans
&& nchan
< sc
->ucode_capa
.n_scan_channels
; j
++) {
518 c
= &ic
->ic_channels
[j
];
519 /* For 2GHz, only populate 11b channels */
520 /* For 5GHz, only populate 11a channels */
522 * Catch other channels, in case we have 900MHz channels or
523 * something in the chanlist.
525 if (iwm_mvm_scan_skip_channel(c
))
527 scan_config
->channel_array
[nchan
++] =
528 ieee80211_mhz2ieee(c
->ic_freq
, 0);
531 scan_config
->flags
= htole32(IWM_SCAN_CONFIG_FLAG_ACTIVATE
|
532 IWM_SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS
|
533 IWM_SCAN_CONFIG_FLAG_SET_TX_CHAINS
|
534 IWM_SCAN_CONFIG_FLAG_SET_RX_CHAINS
|
535 IWM_SCAN_CONFIG_FLAG_SET_AUX_STA_ID
|
536 IWM_SCAN_CONFIG_FLAG_SET_ALL_TIMES
|
537 IWM_SCAN_CONFIG_FLAG_SET_LEGACY_RATES
|
538 IWM_SCAN_CONFIG_FLAG_SET_MAC_ADDR
|
539 IWM_SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS
|
540 IWM_SCAN_CONFIG_N_CHANNELS(nchan
) |
541 IWM_SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED
);
543 hcmd
.data
[0] = scan_config
;
544 hcmd
.len
[0] = cmd_size
;
546 IWM_DPRINTF(sc
, IWM_DEBUG_SCAN
, "Sending UMAC scan config\n");
548 ret
= iwm_send_cmd(sc
, &hcmd
);
550 IWM_DPRINTF(sc
, IWM_DEBUG_SCAN
,
551 "UMAC scan config was sent successfully\n");
553 kfree(scan_config
, M_DEVBUF
);
558 iwm_mvm_scan_use_ebs(struct iwm_softc
*sc
)
560 const struct iwm_ucode_capabilities
*capa
= &sc
->ucode_capa
;
562 /* We can only use EBS if:
563 * 1. the feature is supported;
564 * 2. the last EBS was successful;
565 * 3. if only single scan, the single scan EBS API is supported;
566 * 4. it's not a p2p find operation.
568 return ((capa
->flags
& IWM_UCODE_TLV_FLAGS_EBS_SUPPORT
) &&
569 sc
->last_ebs_successful
);
573 iwm_mvm_umac_scan(struct iwm_softc
*sc
)
575 struct iwm_host_cmd hcmd
= {
576 .id
= iwm_cmd_id(IWM_SCAN_REQ_UMAC
, IWM_ALWAYS_LONG_GROUP
, 0),
579 .flags
= IWM_CMD_SYNC
,
581 struct iwm_scan_req_umac
*req
;
582 struct iwm_scan_req_umac_tail
*tail
;
585 const uint8_t *ssid
= NULL
;
588 req_len
= sizeof(struct iwm_scan_req_umac
) +
589 (sizeof(struct iwm_scan_channel_cfg_umac
) *
590 sc
->ucode_capa
.n_scan_channels
) +
591 sizeof(struct iwm_scan_req_umac_tail
);
592 if (req_len
> IWM_MAX_CMD_PAYLOAD_SIZE
)
594 req
= kmalloc(req_len
, M_DEVBUF
, M_INTWAIT
| M_ZERO
);
598 hcmd
.len
[0] = (uint16_t)req_len
;
599 hcmd
.data
[0] = (void *)req
;
601 IWM_DPRINTF(sc
, IWM_DEBUG_SCAN
, "Handling ieee80211 scan request\n");
603 /* These timings correspond to iwlwifi's UNASSOC scan. */
604 req
->active_dwell
= 10;
605 req
->passive_dwell
= 110;
606 req
->fragmented_dwell
= 44;
607 req
->extended_dwell
= 90;
608 req
->max_out_time
= 0;
609 req
->suspend_time
= 0;
611 req
->scan_priority
= htole32(IWM_SCAN_PRIORITY_HIGH
);
612 req
->ooc_priority
= htole32(IWM_SCAN_PRIORITY_HIGH
);
614 req
->n_channels
= iwm_mvm_umac_scan_fill_channels(sc
,
615 (struct iwm_scan_channel_cfg_umac
*)req
->data
, ssid_len
!= 0);
617 req
->general_flags
= htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASS_ALL
|
618 IWM_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE
|
619 IWM_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL
);
621 if (iwm_mvm_rrm_scan_needed(sc
))
622 req
->general_flags
|=
623 htole32(IWM_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED
);
625 tail
= (void *)((char *)&req
->data
+
626 sizeof(struct iwm_scan_channel_cfg_umac
) *
627 sc
->ucode_capa
.n_scan_channels
);
629 /* Check if we're doing an active directed scan. */
631 tail
->direct_scan
[0].id
= IEEE80211_ELEMID_SSID
;
632 tail
->direct_scan
[0].len
= ssid_len
;
633 memcpy(tail
->direct_scan
[0].ssid
, ssid
, ssid_len
);
634 req
->general_flags
|=
635 htole32(IWM_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT
);
637 req
->general_flags
|= htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASSIVE
);
640 if (iwm_mvm_scan_use_ebs(sc
))
641 req
->channel_flags
= IWM_SCAN_CHANNEL_FLAG_EBS
|
642 IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE
|
643 IWM_SCAN_CHANNEL_FLAG_CACHE_ADD
;
645 ret
= iwm_mvm_fill_probe_req(sc
, &tail
->preq
);
647 kfree(req
, M_DEVBUF
);
651 /* Specify the scan plan: We'll do one iteration. */
652 tail
->schedule
[0].interval
= 0;
653 tail
->schedule
[0].iter_count
= 1;
655 ret
= iwm_send_cmd(sc
, &hcmd
);
657 IWM_DPRINTF(sc
, IWM_DEBUG_SCAN
,
658 "Scan request was sent successfully\n");
659 kfree(req
, M_DEVBUF
);
664 iwm_mvm_lmac_scan(struct iwm_softc
*sc
)
666 struct iwm_host_cmd hcmd
= {
667 .id
= IWM_SCAN_OFFLOAD_REQUEST_CMD
,
670 .flags
= IWM_CMD_SYNC
,
672 struct iwm_scan_req_lmac
*req
;
676 const uint8_t *ssid
= NULL
;
678 IWM_DPRINTF(sc
, IWM_DEBUG_SCAN
,
679 "Handling ieee80211 scan request\n");
681 req_len
= sizeof(struct iwm_scan_req_lmac
) +
682 (sizeof(struct iwm_scan_channel_cfg_lmac
) *
683 sc
->ucode_capa
.n_scan_channels
) + sizeof(struct iwm_scan_probe_req
);
684 if (req_len
> IWM_MAX_CMD_PAYLOAD_SIZE
)
686 req
= kmalloc(req_len
, M_DEVBUF
, M_INTWAIT
| M_ZERO
);
690 hcmd
.len
[0] = (uint16_t)req_len
;
691 hcmd
.data
[0] = (void *)req
;
693 /* These timings correspond to iwlwifi's UNASSOC scan. */
694 req
->active_dwell
= 10;
695 req
->passive_dwell
= 110;
696 req
->fragmented_dwell
= 44;
697 req
->extended_dwell
= 90;
698 req
->max_out_time
= 0;
699 req
->suspend_time
= 0;
701 req
->scan_prio
= htole32(IWM_SCAN_PRIORITY_HIGH
);
702 req
->rx_chain_select
= iwm_mvm_scan_rx_chain(sc
);
703 req
->iter_num
= htole32(1);
706 req
->scan_flags
= htole32(IWM_MVM_LMAC_SCAN_FLAG_PASS_ALL
|
707 IWM_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE
|
708 IWM_MVM_LMAC_SCAN_FLAG_EXTENDED_DWELL
);
710 req
->scan_flags
|= htole32(IWM_MVM_LMAC_SCAN_FLAG_PASSIVE
);
713 htole32(IWM_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION
);
714 if (iwm_mvm_rrm_scan_needed(sc
))
715 req
->scan_flags
|= htole32(IWM_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED
);
717 req
->flags
= iwm_mvm_scan_rxon_flags(sc
->sc_ic
.ic_scan
->ss_chans
[0]);
719 htole32(IWM_MAC_FILTER_ACCEPT_GRP
| IWM_MAC_FILTER_IN_BEACON
);
721 /* Tx flags 2 GHz. */
722 req
->tx_cmd
[0].tx_flags
= htole32(IWM_TX_CMD_FLG_SEQ_CTL
|
723 IWM_TX_CMD_FLG_BT_DIS
);
724 req
->tx_cmd
[0].rate_n_flags
=
725 iwm_mvm_scan_rate_n_flags(sc
, IEEE80211_CHAN_2GHZ
, 1/*XXX*/);
726 req
->tx_cmd
[0].sta_id
= sc
->sc_aux_sta
.sta_id
;
728 /* Tx flags 5 GHz. */
729 req
->tx_cmd
[1].tx_flags
= htole32(IWM_TX_CMD_FLG_SEQ_CTL
|
730 IWM_TX_CMD_FLG_BT_DIS
);
731 req
->tx_cmd
[1].rate_n_flags
=
732 iwm_mvm_scan_rate_n_flags(sc
, IEEE80211_CHAN_5GHZ
, 1/*XXX*/);
733 req
->tx_cmd
[1].sta_id
= sc
->sc_aux_sta
.sta_id
;
735 /* Check if we're doing an active directed scan. */
737 req
->direct_scan
[0].id
= IEEE80211_ELEMID_SSID
;
738 req
->direct_scan
[0].len
= ssid_len
;
739 memcpy(req
->direct_scan
[0].ssid
, ssid
, ssid_len
);
742 req
->n_channels
= iwm_mvm_lmac_scan_fill_channels(sc
,
743 (struct iwm_scan_channel_cfg_lmac
*)req
->data
,
746 ret
= iwm_mvm_fill_probe_req(sc
,
747 (struct iwm_scan_probe_req
*)(req
->data
+
748 (sizeof(struct iwm_scan_channel_cfg_lmac
) *
749 sc
->ucode_capa
.n_scan_channels
)));
751 kfree(req
, M_DEVBUF
);
755 /* Specify the scan plan: We'll do one iteration. */
756 req
->schedule
[0].iterations
= 1;
757 req
->schedule
[0].full_scan_mul
= 1;
759 if (iwm_mvm_scan_use_ebs(sc
)) {
760 req
->channel_opt
[0].flags
=
761 htole16(IWM_SCAN_CHANNEL_FLAG_EBS
|
762 IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE
|
763 IWM_SCAN_CHANNEL_FLAG_CACHE_ADD
);
764 req
->channel_opt
[0].non_ebs_ratio
=
765 htole16(IWM_DENSE_EBS_SCAN_RATIO
);
766 req
->channel_opt
[1].flags
=
767 htole16(IWM_SCAN_CHANNEL_FLAG_EBS
|
768 IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE
|
769 IWM_SCAN_CHANNEL_FLAG_CACHE_ADD
);
770 req
->channel_opt
[1].non_ebs_ratio
=
771 htole16(IWM_SPARSE_EBS_SCAN_RATIO
);
774 ret
= iwm_send_cmd(sc
, &hcmd
);
776 IWM_DPRINTF(sc
, IWM_DEBUG_SCAN
,
777 "Scan request was sent successfully\n");
779 kfree(req
, M_DEVBUF
);
784 iwm_mvm_lmac_scan_abort(struct iwm_softc
*sc
)
787 struct iwm_host_cmd hcmd
= {
788 .id
= IWM_SCAN_OFFLOAD_ABORT_CMD
,
791 .flags
= IWM_CMD_SYNC
,
795 ret
= iwm_mvm_send_cmd_status(sc
, &hcmd
, &status
);
799 if (status
!= IWM_CAN_ABORT_STATUS
) {
801 * The scan abort will return 1 for success or
802 * 2 for "failure". A failure condition can be
803 * due to simply not being in an active scan which
804 * can occur if we send the scan abort before the
805 * microcode has notified us that a scan is completed.
807 IWM_DPRINTF(sc
, IWM_DEBUG_SCAN
,
808 "SCAN OFFLOAD ABORT ret %d.\n", status
);
816 iwm_mvm_umac_scan_abort(struct iwm_softc
*sc
)
818 struct iwm_umac_scan_abort cmd
= {};
822 cmd
.uid
= htole32(uid
);
824 IWM_DPRINTF(sc
, IWM_DEBUG_SCAN
, "Sending scan abort, uid %u\n", uid
);
826 ret
= iwm_mvm_send_cmd_pdu(sc
,
827 iwm_cmd_id(IWM_SCAN_ABORT_UMAC
,
828 IWM_ALWAYS_LONG_GROUP
, 0),
829 0, sizeof(cmd
), &cmd
);
835 iwm_mvm_scan_stop_wait(struct iwm_softc
*sc
)
837 struct iwm_notification_wait wait_scan_done
;
838 static const uint16_t scan_done_notif
[] = { IWM_SCAN_COMPLETE_UMAC
,
839 IWM_SCAN_OFFLOAD_COMPLETE
, };
842 iwm_init_notification_wait(sc
->sc_notif_wait
, &wait_scan_done
,
843 scan_done_notif
, NELEM(scan_done_notif
),
846 IWM_DPRINTF(sc
, IWM_DEBUG_SCAN
, "Preparing to stop scan\n");
848 if (fw_has_capa(&sc
->ucode_capa
, IWM_UCODE_TLV_CAPA_UMAC_SCAN
))
849 ret
= iwm_mvm_umac_scan_abort(sc
);
851 ret
= iwm_mvm_lmac_scan_abort(sc
);
854 IWM_DPRINTF(sc
, IWM_DEBUG_SCAN
, "couldn't stop scan\n");
855 iwm_remove_notification(sc
->sc_notif_wait
, &wait_scan_done
);
860 ret
= iwm_wait_notification(sc
->sc_notif_wait
, &wait_scan_done
, hz
);