1 /*-
2 * SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) AND ISC
3 */
4
5 /* $OpenBSD: if_iwx.c,v 1.175 2023/07/05 15:07:28 stsp Exp $ */
6
7 /*
8 *
9 * Copyright (c) 2025 The FreeBSD Foundation
10 *
11 * Portions of this software were developed by Tom Jones <thj@FreeBSD.org>
12 * under sponsorship from the FreeBSD Foundation.
13 *
14 * Permission to use, copy, modify, and distribute this software for any
15 * purpose with or without fee is hereby granted, provided that the above
16 * copyright notice and this permission notice appear in all copies.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
19 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
21 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
24 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 *
26 */
27
28 /*-
29 * Copyright (c) 2024 Future Crew, LLC
30 * Author: Mikhail Pchelin <misha@FreeBSD.org>
31 *
32 * Permission to use, copy, modify, and distribute this software for any
33 * purpose with or without fee is hereby granted, provided that the above
34 * copyright notice and this permission notice appear in all copies.
35 *
36 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
37 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
38 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
39 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
40 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
41 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
42 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
43 */
44
45 /*
46 * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
47 * Author: Stefan Sperling <stsp@openbsd.org>
48 * Copyright (c) 2014 Fixup Software Ltd.
49 * Copyright (c) 2017, 2019, 2020 Stefan Sperling <stsp@openbsd.org>
50 *
51 * Permission to use, copy, modify, and distribute this software for any
52 * purpose with or without fee is hereby granted, provided that the above
53 * copyright notice and this permission notice appear in all copies.
54 *
55 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
56 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
57 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
58 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
59 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
60 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
61 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
62 */
63
64 /*-
65 * Based on BSD-licensed source modules in the Linux iwlwifi driver,
66 * which were used as the reference documentation for this implementation.
67 *
68 ******************************************************************************
69 *
70 * This file is provided under a dual BSD/GPLv2 license. When using or
71 * redistributing this file, you may do so under either license.
72 *
73 * GPL LICENSE SUMMARY
74 *
75 * Copyright(c) 2017 Intel Deutschland GmbH
76 * Copyright(c) 2018 - 2019 Intel Corporation
77 *
78 * This program is free software; you can redistribute it and/or modify
79 * it under the terms of version 2 of the GNU General Public License as
80 * published by the Free Software Foundation.
81 *
82 * This program is distributed in the hope that it will be useful, but
83 * WITHOUT ANY WARRANTY; without even the implied warranty of
84 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
85 * General Public License for more details.
86 *
87 * BSD LICENSE
88 *
89 * Copyright(c) 2017 Intel Deutschland GmbH
90 * Copyright(c) 2018 - 2019 Intel Corporation
91 * All rights reserved.
92 *
93 * Redistribution and use in source and binary forms, with or without
94 * modification, are permitted provided that the following conditions
95 * are met:
96 *
97 * * Redistributions of source code must retain the above copyright
98 * notice, this list of conditions and the following disclaimer.
99 * * Redistributions in binary form must reproduce the above copyright
100 * notice, this list of conditions and the following disclaimer in
101 * the documentation and/or other materials provided with the
102 * distribution.
103 * * Neither the name Intel Corporation nor the names of its
104 * contributors may be used to endorse or promote products derived
105 * from this software without specific prior written permission.
106 *
107 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
108 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
109 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
110 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
111 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
112 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
113 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
114 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
115 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
116 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
117 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
118 *
119 *****************************************************************************
120 */
121
122 /*-
123 * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
124 *
125 * Permission to use, copy, modify, and distribute this software for any
126 * purpose with or without fee is hereby granted, provided that the above
127 * copyright notice and this permission notice appear in all copies.
128 *
129 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
130 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
131 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
132 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
133 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
134 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
135 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
136 */
137
138 #include <sys/param.h>
139 #include <sys/bus.h>
140 #include <sys/module.h>
141 #include <sys/conf.h>
142 #include <sys/kernel.h>
143 #include <sys/malloc.h>
144 #include <sys/mbuf.h>
145 #include <sys/mutex.h>
146 #include <sys/proc.h>
147 #include <sys/rman.h>
148 #include <sys/rwlock.h>
149 #include <sys/socket.h>
150 #include <sys/sockio.h>
151 #include <sys/systm.h>
152 #include <sys/endian.h>
153 #include <sys/linker.h>
154 #include <sys/firmware.h>
155 #include <sys/epoch.h>
156 #include <sys/kdb.h>
157
158 #include <machine/_inttypes.h>
159 #include <machine/bus.h>
160 #include <machine/endian.h>
161 #include <machine/resource.h>
162
163 #include <dev/pci/pcireg.h>
164 #include <dev/pci/pcivar.h>
165
166 #include <net/bpf.h>
167
168 #include <net/if.h>
169 #include <net/if_var.h>
170 #include <net/if_dl.h>
171 #include <net/if_media.h>
172
173 #include <netinet/in.h>
174 #include <netinet/if_ether.h>
175
176 #include <net80211/ieee80211_var.h>
177 #include <net80211/ieee80211_radiotap.h>
178 #include <net80211/ieee80211_regdomain.h>
179 #include <net80211/ieee80211_ratectl.h>
180 #include <net80211/ieee80211_vht.h>
181
182 int iwx_himark = 224;
183 int iwx_lomark = 192;
184
185 #define IWX_FBSD_RSP_V3 3
186 #define IWX_FBSD_RSP_V4 4
187
188 #define DEVNAME(_sc) (device_get_nameunit((_sc)->sc_dev))
189 #define IC2IFP(ic) (((struct ieee80211vap *)TAILQ_FIRST(&(ic)->ic_vaps))->iv_ifp)
190
191 #define le16_to_cpup(_a_) (le16toh(*(const uint16_t *)(_a_)))
192 #define le32_to_cpup(_a_) (le32toh(*(const uint32_t *)(_a_)))
193
194 #include <dev/iwx/if_iwxreg.h>
195 #include <dev/iwx/if_iwxvar.h>
196
197 #include <dev/iwx/if_iwx_debug.h>
198
199 #define PCI_CFG_RETRY_TIMEOUT 0x41
200
201 #define PCI_VENDOR_INTEL 0x8086
202 #define PCI_PRODUCT_INTEL_WL_22500_1 0x2723 /* Wi-Fi 6 AX200 */
203 #define PCI_PRODUCT_INTEL_WL_22500_2 0x02f0 /* Wi-Fi 6 AX201 */
204 #define PCI_PRODUCT_INTEL_WL_22500_3 0xa0f0 /* Wi-Fi 6 AX201 */
205 #define PCI_PRODUCT_INTEL_WL_22500_4 0x34f0 /* Wi-Fi 6 AX201 */
206 #define PCI_PRODUCT_INTEL_WL_22500_5 0x06f0 /* Wi-Fi 6 AX201 */
207 #define PCI_PRODUCT_INTEL_WL_22500_6 0x43f0 /* Wi-Fi 6 AX201 */
208 #define PCI_PRODUCT_INTEL_WL_22500_7 0x3df0 /* Wi-Fi 6 AX201 */
209 #define PCI_PRODUCT_INTEL_WL_22500_8 0x4df0 /* Wi-Fi 6 AX201 */
210 #define PCI_PRODUCT_INTEL_WL_22500_9 0x2725 /* Wi-Fi 6 AX210 */
211 #define PCI_PRODUCT_INTEL_WL_22500_10 0x2726 /* Wi-Fi 6 AX211 */
212 #define PCI_PRODUCT_INTEL_WL_22500_11 0x51f0 /* Wi-Fi 6 AX211 */
213 #define PCI_PRODUCT_INTEL_WL_22500_12 0x7a70 /* Wi-Fi 6 AX211 */
214 #define PCI_PRODUCT_INTEL_WL_22500_13 0x7af0 /* Wi-Fi 6 AX211 */
215 #define PCI_PRODUCT_INTEL_WL_22500_14 0x7e40 /* Wi-Fi 6 AX210 */
216 #define PCI_PRODUCT_INTEL_WL_22500_15 0x7f70 /* Wi-Fi 6 AX211 */
217 #define PCI_PRODUCT_INTEL_WL_22500_16 0x54f0 /* Wi-Fi 6 AX211 */
218 #define PCI_PRODUCT_INTEL_WL_22500_17 0x51f1 /* Wi-Fi 6 AX211 */
219
220 static const struct iwx_devices {
221 uint16_t device;
222 char *name;
223 } iwx_devices[] = {
224 { PCI_PRODUCT_INTEL_WL_22500_1, "Wi-Fi 6 AX200" },
225 { PCI_PRODUCT_INTEL_WL_22500_2, "Wi-Fi 6 AX201" },
226 { PCI_PRODUCT_INTEL_WL_22500_3, "Wi-Fi 6 AX201" },
227 { PCI_PRODUCT_INTEL_WL_22500_4, "Wi-Fi 6 AX201" },
228 { PCI_PRODUCT_INTEL_WL_22500_5, "Wi-Fi 6 AX201" },
229 { PCI_PRODUCT_INTEL_WL_22500_6, "Wi-Fi 6 AX201" },
230 { PCI_PRODUCT_INTEL_WL_22500_7, "Wi-Fi 6 AX201" },
231 { PCI_PRODUCT_INTEL_WL_22500_8, "Wi-Fi 6 AX201" },
232 { PCI_PRODUCT_INTEL_WL_22500_9, "Wi-Fi 6 AX210" },
233 { PCI_PRODUCT_INTEL_WL_22500_10, "Wi-Fi 6 AX211" },
234 { PCI_PRODUCT_INTEL_WL_22500_11, "Wi-Fi 6 AX211" },
235 { PCI_PRODUCT_INTEL_WL_22500_12, "Wi-Fi 6 AX211" },
236 { PCI_PRODUCT_INTEL_WL_22500_13, "Wi-Fi 6 AX211" },
237 { PCI_PRODUCT_INTEL_WL_22500_14, "Wi-Fi 6 AX210" },
238 { PCI_PRODUCT_INTEL_WL_22500_15, "Wi-Fi 6 AX211" },
239 { PCI_PRODUCT_INTEL_WL_22500_16, "Wi-Fi 6 AX211" },
240 { PCI_PRODUCT_INTEL_WL_22500_17, "Wi-Fi 6 AX211" },
241 };
242
243 static const uint8_t iwx_nvm_channels_8000[] = {
244 /* 2.4 GHz */
245 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
246 /* 5 GHz */
247 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92,
248 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
249 149, 153, 157, 161, 165, 169, 173, 177, 181
250 };
251
252 static const uint8_t iwx_nvm_channels_uhb[] = {
253 /* 2.4 GHz */
254 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
255 /* 5 GHz */
256 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92,
257 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
258 149, 153, 157, 161, 165, 169, 173, 177, 181,
259 /* 6-7 GHz */
260 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69,
261 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129,
262 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185,
263 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233
264 };
265
266 #define IWX_NUM_2GHZ_CHANNELS 14
267 #define IWX_NUM_5GHZ_CHANNELS 37
268
269 const struct iwx_rate {
270 uint16_t rate;
271 uint8_t plcp;
272 uint8_t ht_plcp;
273 } iwx_rates[] = {
274 /* Legacy */ /* HT */
275 { 2, IWX_RATE_1M_PLCP, IWX_RATE_HT_SISO_MCS_INV_PLCP },
276 { 4, IWX_RATE_2M_PLCP, IWX_RATE_HT_SISO_MCS_INV_PLCP },
277 { 11, IWX_RATE_5M_PLCP, IWX_RATE_HT_SISO_MCS_INV_PLCP },
278 { 22, IWX_RATE_11M_PLCP, IWX_RATE_HT_SISO_MCS_INV_PLCP },
279 { 12, IWX_RATE_6M_PLCP, IWX_RATE_HT_SISO_MCS_0_PLCP },
280 { 18, IWX_RATE_9M_PLCP, IWX_RATE_HT_SISO_MCS_INV_PLCP },
281 { 24, IWX_RATE_12M_PLCP, IWX_RATE_HT_SISO_MCS_1_PLCP },
282 { 26, IWX_RATE_INVM_PLCP, IWX_RATE_HT_MIMO2_MCS_8_PLCP },
283 { 36, IWX_RATE_18M_PLCP, IWX_RATE_HT_SISO_MCS_2_PLCP },
284 { 48, IWX_RATE_24M_PLCP, IWX_RATE_HT_SISO_MCS_3_PLCP },
285 { 52, IWX_RATE_INVM_PLCP, IWX_RATE_HT_MIMO2_MCS_9_PLCP },
286 { 72, IWX_RATE_36M_PLCP, IWX_RATE_HT_SISO_MCS_4_PLCP },
287 { 78, IWX_RATE_INVM_PLCP, IWX_RATE_HT_MIMO2_MCS_10_PLCP },
288 { 96, IWX_RATE_48M_PLCP, IWX_RATE_HT_SISO_MCS_5_PLCP },
289 { 104, IWX_RATE_INVM_PLCP, IWX_RATE_HT_MIMO2_MCS_11_PLCP },
290 { 108, IWX_RATE_54M_PLCP, IWX_RATE_HT_SISO_MCS_6_PLCP },
291 { 128, IWX_RATE_INVM_PLCP, IWX_RATE_HT_SISO_MCS_7_PLCP },
292 { 156, IWX_RATE_INVM_PLCP, IWX_RATE_HT_MIMO2_MCS_12_PLCP },
293 { 208, IWX_RATE_INVM_PLCP, IWX_RATE_HT_MIMO2_MCS_13_PLCP },
294 { 234, IWX_RATE_INVM_PLCP, IWX_RATE_HT_MIMO2_MCS_14_PLCP },
295 { 260, IWX_RATE_INVM_PLCP, IWX_RATE_HT_MIMO2_MCS_15_PLCP },
296 };
297 #define IWX_RIDX_CCK 0
298 #define IWX_RIDX_OFDM 4
299 #define IWX_RIDX_MAX (nitems(iwx_rates)-1)
300 #define IWX_RIDX_IS_CCK(_i_) ((_i_) < IWX_RIDX_OFDM)
301 #define IWX_RIDX_IS_OFDM(_i_) ((_i_) >= IWX_RIDX_OFDM)
302 #define IWX_RVAL_IS_OFDM(_i_) ((_i_) >= 12 && (_i_) != 22)
303
304 /* Convert an MCS index into an iwx_rates[] index. */
305 const int iwx_mcs2ridx[] = {
306 IWX_RATE_MCS_0_INDEX,
307 IWX_RATE_MCS_1_INDEX,
308 IWX_RATE_MCS_2_INDEX,
309 IWX_RATE_MCS_3_INDEX,
310 IWX_RATE_MCS_4_INDEX,
311 IWX_RATE_MCS_5_INDEX,
312 IWX_RATE_MCS_6_INDEX,
313 IWX_RATE_MCS_7_INDEX,
314 IWX_RATE_MCS_8_INDEX,
315 IWX_RATE_MCS_9_INDEX,
316 IWX_RATE_MCS_10_INDEX,
317 IWX_RATE_MCS_11_INDEX,
318 IWX_RATE_MCS_12_INDEX,
319 IWX_RATE_MCS_13_INDEX,
320 IWX_RATE_MCS_14_INDEX,
321 IWX_RATE_MCS_15_INDEX,
322 };
323
324 static uint8_t iwx_lookup_cmd_ver(struct iwx_softc *, uint8_t, uint8_t);
325 static uint8_t iwx_lookup_notif_ver(struct iwx_softc *, uint8_t, uint8_t);
326 static int iwx_store_cscheme(struct iwx_softc *, const uint8_t *, size_t);
327 #if 0
328 static int iwx_alloc_fw_monitor_block(struct iwx_softc *, uint8_t, uint8_t);
329 static int iwx_alloc_fw_monitor(struct iwx_softc *, uint8_t);
330 #endif
331 static int iwx_apply_debug_destination(struct iwx_softc *);
332 static void iwx_set_ltr(struct iwx_softc *);
333 static int iwx_ctxt_info_init(struct iwx_softc *, const struct iwx_fw_sects *);
334 static int iwx_ctxt_info_gen3_init(struct iwx_softc *,
335 const struct iwx_fw_sects *);
336 static void iwx_ctxt_info_free_fw_img(struct iwx_softc *);
337 static void iwx_ctxt_info_free_paging(struct iwx_softc *);
338 static int iwx_init_fw_sec(struct iwx_softc *, const struct iwx_fw_sects *,
339 struct iwx_context_info_dram *);
340 static void iwx_fw_version_str(char *, size_t, uint32_t, uint32_t, uint32_t);
341 static int iwx_firmware_store_section(struct iwx_softc *, enum iwx_ucode_type,
342 const uint8_t *, size_t);
343 static int iwx_set_default_calib(struct iwx_softc *, const void *);
344 static void iwx_fw_info_free(struct iwx_fw_info *);
345 static int iwx_read_firmware(struct iwx_softc *);
346 static uint32_t iwx_prph_addr_mask(struct iwx_softc *);
347 static uint32_t iwx_read_prph_unlocked(struct iwx_softc *, uint32_t);
348 static uint32_t iwx_read_prph(struct iwx_softc *, uint32_t);
349 static void iwx_write_prph_unlocked(struct iwx_softc *, uint32_t, uint32_t);
350 static void iwx_write_prph(struct iwx_softc *, uint32_t, uint32_t);
351 static uint32_t iwx_read_umac_prph(struct iwx_softc *, uint32_t);
352 static void iwx_write_umac_prph(struct iwx_softc *, uint32_t, uint32_t);
353 static int iwx_read_mem(struct iwx_softc *, uint32_t, void *, int);
354 static int iwx_poll_bit(struct iwx_softc *, int, uint32_t, uint32_t, int);
355 static int iwx_nic_lock(struct iwx_softc *);
356 static void iwx_nic_assert_locked(struct iwx_softc *);
357 static void iwx_nic_unlock(struct iwx_softc *);
358 static int iwx_set_bits_mask_prph(struct iwx_softc *, uint32_t, uint32_t,
359 uint32_t);
360 static int iwx_set_bits_prph(struct iwx_softc *, uint32_t, uint32_t);
361 static int iwx_clear_bits_prph(struct iwx_softc *, uint32_t, uint32_t);
362 static void iwx_dma_map_addr(void *, bus_dma_segment_t *, int, int);
363 static int iwx_dma_contig_alloc(bus_dma_tag_t, struct iwx_dma_info *,
364 bus_size_t, bus_size_t);
365 static void iwx_dma_contig_free(struct iwx_dma_info *);
366 static int iwx_alloc_rx_ring(struct iwx_softc *, struct iwx_rx_ring *);
367 static void iwx_disable_rx_dma(struct iwx_softc *);
368 static void iwx_reset_rx_ring(struct iwx_softc *, struct iwx_rx_ring *);
369 static void iwx_free_rx_ring(struct iwx_softc *, struct iwx_rx_ring *);
370 static int iwx_alloc_tx_ring(struct iwx_softc *, struct iwx_tx_ring *, int);
371 static void iwx_reset_tx_ring(struct iwx_softc *, struct iwx_tx_ring *);
372 static void iwx_free_tx_ring(struct iwx_softc *, struct iwx_tx_ring *);
373 static void iwx_enable_rfkill_int(struct iwx_softc *);
374 static int iwx_check_rfkill(struct iwx_softc *);
375 static void iwx_enable_interrupts(struct iwx_softc *);
376 static void iwx_enable_fwload_interrupt(struct iwx_softc *);
377 #if 0
378 static void iwx_restore_interrupts(struct iwx_softc *);
379 #endif
380 static void iwx_disable_interrupts(struct iwx_softc *);
381 static void iwx_ict_reset(struct iwx_softc *);
382 static int iwx_set_hw_ready(struct iwx_softc *);
383 static int iwx_prepare_card_hw(struct iwx_softc *);
384 static int iwx_force_power_gating(struct iwx_softc *);
385 static void iwx_apm_config(struct iwx_softc *);
386 static int iwx_apm_init(struct iwx_softc *);
387 static void iwx_apm_stop(struct iwx_softc *);
388 static int iwx_allow_mcast(struct iwx_softc *);
389 static void iwx_init_msix_hw(struct iwx_softc *);
390 static void iwx_conf_msix_hw(struct iwx_softc *, int);
391 static int iwx_clear_persistence_bit(struct iwx_softc *);
392 static int iwx_start_hw(struct iwx_softc *);
393 static void iwx_stop_device(struct iwx_softc *);
394 static void iwx_nic_config(struct iwx_softc *);
395 static int iwx_nic_rx_init(struct iwx_softc *);
396 static int iwx_nic_init(struct iwx_softc *);
397 static int iwx_enable_txq(struct iwx_softc *, int, int, int, int);
398 static int iwx_disable_txq(struct iwx_softc *sc, int, int, uint8_t);
399 static void iwx_post_alive(struct iwx_softc *);
400 static int iwx_schedule_session_protection(struct iwx_softc *,
401 struct iwx_node *, uint32_t);
402 static void iwx_unprotect_session(struct iwx_softc *, struct iwx_node *);
403 static void iwx_init_channel_map(struct ieee80211com *, int, int *,
404 struct ieee80211_channel[]);
405 static int iwx_mimo_enabled(struct iwx_softc *);
406 static void iwx_init_reorder_buffer(struct iwx_reorder_buffer *, uint16_t,
407 uint16_t);
408 static void iwx_clear_reorder_buffer(struct iwx_softc *, struct iwx_rxba_data *);
409 static void iwx_sta_rx_agg(struct iwx_softc *, struct ieee80211_node *, uint8_t,
410 uint16_t, uint16_t, int, int);
411 static void iwx_sta_tx_agg_start(struct iwx_softc *,
412 struct ieee80211_node *, uint8_t);
413 static void iwx_ba_rx_task(void *, int);
414 static void iwx_ba_tx_task(void *, int);
415 static void iwx_set_mac_addr_from_csr(struct iwx_softc *, struct iwx_nvm_data *);
416 static int iwx_is_valid_mac_addr(const uint8_t *);
417 static void iwx_flip_hw_address(uint32_t, uint32_t, uint8_t *);
418 static int iwx_nvm_get(struct iwx_softc *);
419 static int iwx_load_firmware(struct iwx_softc *);
420 static int iwx_start_fw(struct iwx_softc *);
421 static int iwx_pnvm_handle_section(struct iwx_softc *, const uint8_t *, size_t);
422 static int iwx_pnvm_parse(struct iwx_softc *, const uint8_t *, size_t);
423 static void iwx_ctxt_info_gen3_set_pnvm(struct iwx_softc *);
424 static int iwx_load_pnvm(struct iwx_softc *);
425 static int iwx_send_tx_ant_cfg(struct iwx_softc *, uint8_t);
426 static int iwx_send_phy_cfg_cmd(struct iwx_softc *);
427 static int iwx_load_ucode_wait_alive(struct iwx_softc *);
428 static int iwx_send_dqa_cmd(struct iwx_softc *);
429 static int iwx_run_init_mvm_ucode(struct iwx_softc *, int);
430 static int iwx_config_ltr(struct iwx_softc *);
431 static void iwx_update_rx_desc(struct iwx_softc *, struct iwx_rx_ring *, int, bus_dma_segment_t *);
432 static int iwx_rx_addbuf(struct iwx_softc *, int, int);
433 static int iwx_rxmq_get_signal_strength(struct iwx_softc *, struct iwx_rx_mpdu_desc *);
434 static void iwx_rx_rx_phy_cmd(struct iwx_softc *, struct iwx_rx_packet *,
435 struct iwx_rx_data *);
436 static int iwx_get_noise(struct iwx_softc *, const struct iwx_statistics_rx_non_phy *);
437 static int iwx_rx_hwdecrypt(struct iwx_softc *, struct mbuf *, uint32_t);
438 #if 0
439 int iwx_ccmp_decap(struct iwx_softc *, struct mbuf *,
440 struct ieee80211_node *, struct ieee80211_rxinfo *);
441 #endif
442 static void iwx_rx_frame(struct iwx_softc *, struct mbuf *, int, uint32_t,
443 int, int, uint32_t, uint8_t);
444 static void iwx_clear_tx_desc(struct iwx_softc *, struct iwx_tx_ring *, int);
445 static void iwx_txd_done(struct iwx_softc *, struct iwx_tx_ring *,
446 struct iwx_tx_data *);
447 static void iwx_txq_advance(struct iwx_softc *, struct iwx_tx_ring *, uint16_t);
448 static void iwx_rx_tx_cmd(struct iwx_softc *, struct iwx_rx_packet *,
449 struct iwx_rx_data *);
450 static void iwx_clear_oactive(struct iwx_softc *, struct iwx_tx_ring *);
451 static void iwx_rx_bmiss(struct iwx_softc *, struct iwx_rx_packet *,
452 struct iwx_rx_data *);
453 static int iwx_binding_cmd(struct iwx_softc *, struct iwx_node *, uint32_t);
454 static uint8_t iwx_get_vht_ctrl_pos(struct ieee80211com *, struct ieee80211_channel *);
455 static int iwx_phy_ctxt_cmd_uhb_v3_v4(struct iwx_softc *,
456 struct iwx_phy_ctxt *, uint8_t, uint8_t, uint32_t, uint8_t, uint8_t, int);
457 #if 0
458 static int iwx_phy_ctxt_cmd_v3_v4(struct iwx_softc *, struct iwx_phy_ctxt *,
459 uint8_t, uint8_t, uint32_t, uint8_t, uint8_t, int);
460 #endif
461 static int iwx_phy_ctxt_cmd(struct iwx_softc *, struct iwx_phy_ctxt *,
462 uint8_t, uint8_t, uint32_t, uint32_t, uint8_t, uint8_t);
463 static int iwx_send_cmd(struct iwx_softc *, struct iwx_host_cmd *);
464 static int iwx_send_cmd_pdu(struct iwx_softc *, uint32_t, uint32_t, uint16_t,
465 const void *);
466 static int iwx_send_cmd_status(struct iwx_softc *, struct iwx_host_cmd *,
467 uint32_t *);
468 static int iwx_send_cmd_pdu_status(struct iwx_softc *, uint32_t, uint16_t,
469 const void *, uint32_t *);
470 static void iwx_free_resp(struct iwx_softc *, struct iwx_host_cmd *);
471 static void iwx_cmd_done(struct iwx_softc *, int, int, int);
472 static uint32_t iwx_fw_rateidx_ofdm(uint8_t);
473 static uint32_t iwx_fw_rateidx_cck(uint8_t);
474 static const struct iwx_rate *iwx_tx_fill_cmd(struct iwx_softc *,
475 struct iwx_node *, struct ieee80211_frame *, uint16_t *, uint32_t *,
476 struct mbuf *);
477 static void iwx_tx_update_byte_tbl(struct iwx_softc *, struct iwx_tx_ring *, int,
478 uint16_t, uint16_t);
479 static int iwx_tx(struct iwx_softc *, struct mbuf *,
480 struct ieee80211_node *);
481 static int iwx_flush_sta_tids(struct iwx_softc *, int, uint16_t);
482 static int iwx_drain_sta(struct iwx_softc *sc, struct iwx_node *, int);
483 static int iwx_flush_sta(struct iwx_softc *, struct iwx_node *);
484 static int iwx_beacon_filter_send_cmd(struct iwx_softc *,
485 struct iwx_beacon_filter_cmd *);
486 static int iwx_update_beacon_abort(struct iwx_softc *, struct iwx_node *,
487 int);
488 static void iwx_power_build_cmd(struct iwx_softc *, struct iwx_node *,
489 struct iwx_mac_power_cmd *);
490 static int iwx_power_mac_update_mode(struct iwx_softc *, struct iwx_node *);
491 static int iwx_power_update_device(struct iwx_softc *);
492 #if 0
493 static int iwx_enable_beacon_filter(struct iwx_softc *, struct iwx_node *);
494 #endif
495 static int iwx_disable_beacon_filter(struct iwx_softc *);
496 static int iwx_add_sta_cmd(struct iwx_softc *, struct iwx_node *, int);
497 static int iwx_rm_sta_cmd(struct iwx_softc *, struct iwx_node *);
498 static int iwx_rm_sta(struct iwx_softc *, struct iwx_node *);
499 static int iwx_fill_probe_req(struct iwx_softc *,
500 struct iwx_scan_probe_req *);
501 static int iwx_config_umac_scan_reduced(struct iwx_softc *);
502 static uint16_t iwx_scan_umac_flags_v2(struct iwx_softc *, int);
503 static void iwx_scan_umac_dwell_v10(struct iwx_softc *,
504 struct iwx_scan_general_params_v10 *, int);
505 static void iwx_scan_umac_fill_general_p_v10(struct iwx_softc *,
506 struct iwx_scan_general_params_v10 *, uint16_t, int);
507 static void iwx_scan_umac_fill_ch_p_v6(struct iwx_softc *,
508 struct iwx_scan_channel_params_v6 *, uint32_t, int);
509 static int iwx_umac_scan_v14(struct iwx_softc *, int);
510 static void iwx_mcc_update(struct iwx_softc *, struct iwx_mcc_chub_notif *);
511 static uint8_t iwx_ridx2rate(struct ieee80211_rateset *, int);
512 static int iwx_rval2ridx(int);
513 static void iwx_ack_rates(struct iwx_softc *, struct iwx_node *, int *,
514 int *);
515 static void iwx_mac_ctxt_cmd_common(struct iwx_softc *, struct iwx_node *,
516 struct iwx_mac_ctx_cmd *, uint32_t);
517 static void iwx_mac_ctxt_cmd_fill_sta(struct iwx_softc *, struct iwx_node *,
518 struct iwx_mac_data_sta *, int);
519 static int iwx_mac_ctxt_cmd(struct iwx_softc *, struct iwx_node *,
520 uint32_t, int);
521 static int iwx_clear_statistics(struct iwx_softc *);
522 static int iwx_scan(struct iwx_softc *);
523 static int iwx_bgscan(struct ieee80211com *);
524 static int iwx_enable_mgmt_queue(struct iwx_softc *);
525 static int iwx_disable_mgmt_queue(struct iwx_softc *);
526 static int iwx_rs_rval2idx(uint8_t);
527 static uint16_t iwx_rs_ht_rates(struct iwx_softc *, struct ieee80211_node *,
528 int);
529 static uint16_t iwx_rs_vht_rates(struct iwx_softc *, struct ieee80211_node *, int);
530 static int iwx_rs_init_v3(struct iwx_softc *, struct iwx_node *);
531 static int iwx_rs_init_v4(struct iwx_softc *, struct iwx_node *);
532 static int iwx_rs_init(struct iwx_softc *, struct iwx_node *);
533 static int iwx_phy_send_rlc(struct iwx_softc *, struct iwx_phy_ctxt *,
534 uint8_t, uint8_t);
535 static int iwx_phy_ctxt_update(struct iwx_softc *, struct iwx_phy_ctxt *,
536 struct ieee80211_channel *, uint8_t, uint8_t, uint32_t, uint8_t,
537 uint8_t);
538 static int iwx_auth(struct ieee80211vap *, struct iwx_softc *);
539 static int iwx_deauth(struct iwx_softc *);
540 static int iwx_run(struct ieee80211vap *, struct iwx_softc *);
541 static int iwx_run_stop(struct iwx_softc *);
542 static struct ieee80211_node * iwx_node_alloc(struct ieee80211vap *,
543 const uint8_t[IEEE80211_ADDR_LEN]);
544 #if 0
545 int iwx_set_key(struct ieee80211com *, struct ieee80211_node *,
546 struct ieee80211_key *);
547 void iwx_setkey_task(void *);
548 void iwx_delete_key(struct ieee80211com *,
549 struct ieee80211_node *, struct ieee80211_key *);
550 #endif
551 static int iwx_newstate(struct ieee80211vap *, enum ieee80211_state, int);
552 static void iwx_endscan(struct iwx_softc *);
553 static void iwx_fill_sf_command(struct iwx_softc *, struct iwx_sf_cfg_cmd *,
554 struct ieee80211_node *);
555 static int iwx_sf_config(struct iwx_softc *, int);
556 static int iwx_send_bt_init_conf(struct iwx_softc *);
557 static int iwx_send_soc_conf(struct iwx_softc *);
558 static int iwx_send_update_mcc_cmd(struct iwx_softc *, const char *);
559 static int iwx_send_temp_report_ths_cmd(struct iwx_softc *);
560 static int iwx_init_hw(struct iwx_softc *);
561 static int iwx_init(struct iwx_softc *);
562 static void iwx_stop(struct iwx_softc *);
563 static void iwx_watchdog(void *);
564 static const char *iwx_desc_lookup(uint32_t);
565 static void iwx_nic_error(struct iwx_softc *);
566 static void iwx_dump_driver_status(struct iwx_softc *);
567 static void iwx_nic_umac_error(struct iwx_softc *);
568 static void iwx_rx_mpdu_mq(struct iwx_softc *, struct mbuf *, void *, size_t);
569 static int iwx_rx_pkt_valid(struct iwx_rx_packet *);
570 static void iwx_rx_pkt(struct iwx_softc *, struct iwx_rx_data *,
571 struct mbuf *);
572 static void iwx_notif_intr(struct iwx_softc *);
573 #if 0
574 /* XXX-THJ - I don't have hardware for this */
575 static int iwx_intr(void *);
576 #endif
577 static void iwx_intr_msix(void *);
578 static int iwx_preinit(struct iwx_softc *);
579 static void iwx_attach_hook(void *);
580 static const struct iwx_device_cfg *iwx_find_device_cfg(struct iwx_softc *);
581 static int iwx_probe(device_t);
582 static int iwx_attach(device_t);
583 static int iwx_detach(device_t);
584
585 /* FreeBSD specific glue */
586 u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN] =
587 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
588
589 u_int8_t etheranyaddr[ETHER_ADDR_LEN] =
590 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
591
592 #if IWX_DEBUG
593 #define DPRINTF(x) do { if (sc->sc_debug == IWX_DEBUG_ANY) { printf x; } } while (0)
594 #else
595 #define DPRINTF(x) do { ; } while (0)
596 #endif
597
598 /* FreeBSD specific functions */
599 static struct ieee80211vap * iwx_vap_create(struct ieee80211com *,
600 const char[IFNAMSIZ], int, enum ieee80211_opmode, int,
601 const uint8_t[IEEE80211_ADDR_LEN], const uint8_t[IEEE80211_ADDR_LEN]);
602 static void iwx_vap_delete(struct ieee80211vap *);
603 static void iwx_parent(struct ieee80211com *);
604 static void iwx_scan_start(struct ieee80211com *);
605 static void iwx_scan_end(struct ieee80211com *);
606 static void iwx_update_mcast(struct ieee80211com *ic);
607 static void iwx_scan_curchan(struct ieee80211_scan_state *, unsigned long);
608 static void iwx_scan_mindwell(struct ieee80211_scan_state *);
609 static void iwx_set_channel(struct ieee80211com *);
610 static void iwx_endscan_cb(void *, int );
611 static int iwx_wme_update(struct ieee80211com *);
612 static int iwx_raw_xmit(struct ieee80211_node *, struct mbuf *,
613 const struct ieee80211_bpf_params *);
614 static int iwx_transmit(struct ieee80211com *, struct mbuf *);
615 static void iwx_start(struct iwx_softc *);
616 static int iwx_ampdu_rx_start(struct ieee80211_node *,
617 struct ieee80211_rx_ampdu *, int, int, int);
618 static void iwx_ampdu_rx_stop(struct ieee80211_node *,
619 struct ieee80211_rx_ampdu *);
620 static int iwx_addba_request(struct ieee80211_node *,
621 struct ieee80211_tx_ampdu *, int, int, int);
622 static int iwx_addba_response(struct ieee80211_node *,
623 struct ieee80211_tx_ampdu *, int, int, int);
624 static void iwx_key_update_begin(struct ieee80211vap *);
625 static void iwx_key_update_end(struct ieee80211vap *);
626 static int iwx_key_alloc(struct ieee80211vap *, struct ieee80211_key *,
627 ieee80211_keyix *,ieee80211_keyix *);
628 static int iwx_key_set(struct ieee80211vap *, const struct ieee80211_key *);
629 static int iwx_key_delete(struct ieee80211vap *,
630 const struct ieee80211_key *);
631 static int iwx_suspend(device_t);
632 static int iwx_resume(device_t);
633 static void iwx_radiotap_attach(struct iwx_softc *);
634
635 /* OpenBSD compat defines */
636 #define IEEE80211_HTOP0_SCO_SCN 0
637 #define IEEE80211_VHTOP0_CHAN_WIDTH_HT 0
638 #define IEEE80211_VHTOP0_CHAN_WIDTH_80 1
639
640 #define IEEE80211_HT_RATESET_SISO 0
641 #define IEEE80211_HT_RATESET_MIMO2 2
642
643 const struct ieee80211_rateset ieee80211_std_rateset_11a =
644 { 8, { 12, 18, 24, 36, 48, 72, 96, 108 } };
645
646 const struct ieee80211_rateset ieee80211_std_rateset_11b =
647 { 4, { 2, 4, 11, 22 } };
648
649 const struct ieee80211_rateset ieee80211_std_rateset_11g =
650 { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
651
652 inline int
ieee80211_has_addr4(const struct ieee80211_frame * wh)653 ieee80211_has_addr4(const struct ieee80211_frame *wh)
654 {
655 return (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) ==
656 IEEE80211_FC1_DIR_DSTODS;
657 }
658
659 static uint8_t
iwx_lookup_cmd_ver(struct iwx_softc * sc,uint8_t grp,uint8_t cmd)660 iwx_lookup_cmd_ver(struct iwx_softc *sc, uint8_t grp, uint8_t cmd)
661 {
662 const struct iwx_fw_cmd_version *entry;
663 int i;
664
665 for (i = 0; i < sc->n_cmd_versions; i++) {
666 entry = &sc->cmd_versions[i];
667 if (entry->group == grp && entry->cmd == cmd)
668 return entry->cmd_ver;
669 }
670
671 return IWX_FW_CMD_VER_UNKNOWN;
672 }
673
674 uint8_t
iwx_lookup_notif_ver(struct iwx_softc * sc,uint8_t grp,uint8_t cmd)675 iwx_lookup_notif_ver(struct iwx_softc *sc, uint8_t grp, uint8_t cmd)
676 {
677 const struct iwx_fw_cmd_version *entry;
678 int i;
679
680 for (i = 0; i < sc->n_cmd_versions; i++) {
681 entry = &sc->cmd_versions[i];
682 if (entry->group == grp && entry->cmd == cmd)
683 return entry->notif_ver;
684 }
685
686 return IWX_FW_CMD_VER_UNKNOWN;
687 }
688
689 static int
iwx_store_cscheme(struct iwx_softc * sc,const uint8_t * data,size_t dlen)690 iwx_store_cscheme(struct iwx_softc *sc, const uint8_t *data, size_t dlen)
691 {
692 const struct iwx_fw_cscheme_list *l = (const void *)data;
693
694 if (dlen < sizeof(*l) ||
695 dlen < sizeof(l->size) + l->size * sizeof(*l->cs))
696 return EINVAL;
697
698 /* we don't actually store anything for now, always use s/w crypto */
699
700 return 0;
701 }
702
703 static int
iwx_ctxt_info_alloc_dma(struct iwx_softc * sc,const struct iwx_fw_onesect * sec,struct iwx_dma_info * dram)704 iwx_ctxt_info_alloc_dma(struct iwx_softc *sc,
705 const struct iwx_fw_onesect *sec, struct iwx_dma_info *dram)
706 {
707 int err = iwx_dma_contig_alloc(sc->sc_dmat, dram, sec->fws_len, 1);
708 if (err) {
709 printf("%s: could not allocate context info DMA memory\n",
710 DEVNAME(sc));
711 return err;
712 }
713
714 memcpy(dram->vaddr, sec->fws_data, sec->fws_len);
715
716 return 0;
717 }
718
719 static void
iwx_ctxt_info_free_paging(struct iwx_softc * sc)720 iwx_ctxt_info_free_paging(struct iwx_softc *sc)
721 {
722 struct iwx_self_init_dram *dram = &sc->init_dram;
723 int i;
724
725 if (!dram->paging)
726 return;
727
728 /* free paging*/
729 for (i = 0; i < dram->paging_cnt; i++)
730 iwx_dma_contig_free(&dram->paging[i]);
731
732 free(dram->paging, M_DEVBUF);
733 dram->paging_cnt = 0;
734 dram->paging = NULL;
735 }
736
737 static int
iwx_get_num_sections(const struct iwx_fw_sects * fws,int start)738 iwx_get_num_sections(const struct iwx_fw_sects *fws, int start)
739 {
740 int i = 0;
741
742 while (start < fws->fw_count &&
743 fws->fw_sect[start].fws_devoff != IWX_CPU1_CPU2_SEPARATOR_SECTION &&
744 fws->fw_sect[start].fws_devoff != IWX_PAGING_SEPARATOR_SECTION) {
745 start++;
746 i++;
747 }
748
749 return i;
750 }
751
752 static int
iwx_init_fw_sec(struct iwx_softc * sc,const struct iwx_fw_sects * fws,struct iwx_context_info_dram * ctxt_dram)753 iwx_init_fw_sec(struct iwx_softc *sc, const struct iwx_fw_sects *fws,
754 struct iwx_context_info_dram *ctxt_dram)
755 {
756 struct iwx_self_init_dram *dram = &sc->init_dram;
757 int i, ret, fw_cnt = 0;
758
759 KASSERT(dram->paging == NULL, ("iwx_init_fw_sec"));
760
761 dram->lmac_cnt = iwx_get_num_sections(fws, 0);
762 /* add 1 due to separator */
763 dram->umac_cnt = iwx_get_num_sections(fws, dram->lmac_cnt + 1);
764 /* add 2 due to separators */
765 dram->paging_cnt = iwx_get_num_sections(fws,
766 dram->lmac_cnt + dram->umac_cnt + 2);
767
768 IWX_UNLOCK(sc);
769 dram->fw = mallocarray(dram->umac_cnt + dram->lmac_cnt,
770 sizeof(*dram->fw), M_DEVBUF, M_ZERO | M_NOWAIT);
771 if (!dram->fw) {
772 printf("%s: could not allocate memory for firmware sections\n",
773 DEVNAME(sc));
774 IWX_LOCK(sc);
775 return ENOMEM;
776 }
777
778 dram->paging = mallocarray(dram->paging_cnt, sizeof(*dram->paging),
779 M_DEVBUF, M_ZERO | M_WAITOK);
780 IWX_LOCK(sc);
781 if (!dram->paging) {
782 printf("%s: could not allocate memory for firmware paging\n",
783 DEVNAME(sc));
784 return ENOMEM;
785 }
786
787 /* initialize lmac sections */
788 for (i = 0; i < dram->lmac_cnt; i++) {
789 ret = iwx_ctxt_info_alloc_dma(sc, &fws->fw_sect[i],
790 &dram->fw[fw_cnt]);
791 if (ret)
792 return ret;
793 ctxt_dram->lmac_img[i] =
794 htole64(dram->fw[fw_cnt].paddr);
795 IWX_DPRINTF(sc, IWX_DEBUG_FIRMWARE_TLV,
796 "%s: firmware LMAC section %d at 0x%llx size %lld\n",
797 __func__, i,
798 (unsigned long long)dram->fw[fw_cnt].paddr,
799 (unsigned long long)dram->fw[fw_cnt].size);
800 fw_cnt++;
801 }
802
803 /* initialize umac sections */
804 for (i = 0; i < dram->umac_cnt; i++) {
805 /* access FW with +1 to make up for lmac separator */
806 ret = iwx_ctxt_info_alloc_dma(sc,
807 &fws->fw_sect[fw_cnt + 1], &dram->fw[fw_cnt]);
808 if (ret)
809 return ret;
810 ctxt_dram->umac_img[i] =
811 htole64(dram->fw[fw_cnt].paddr);
812 IWX_DPRINTF(sc, IWX_DEBUG_FIRMWARE_TLV,
813 "%s: firmware UMAC section %d at 0x%llx size %lld\n",
814 __func__, i,
815 (unsigned long long)dram->fw[fw_cnt].paddr,
816 (unsigned long long)dram->fw[fw_cnt].size);
817 fw_cnt++;
818 }
819
820 /*
821 * Initialize paging.
822 * Paging memory isn't stored in dram->fw as the umac and lmac - it is
823 * stored separately.
824 * This is since the timing of its release is different -
825 * while fw memory can be released on alive, the paging memory can be
826 * freed only when the device goes down.
827 * Given that, the logic here in accessing the fw image is a bit
828 * different - fw_cnt isn't changing so loop counter is added to it.
829 */
830 for (i = 0; i < dram->paging_cnt; i++) {
831 /* access FW with +2 to make up for lmac & umac separators */
832 int fw_idx = fw_cnt + i + 2;
833
834 ret = iwx_ctxt_info_alloc_dma(sc,
835 &fws->fw_sect[fw_idx], &dram->paging[i]);
836 if (ret)
837 return ret;
838
839 ctxt_dram->virtual_img[i] = htole64(dram->paging[i].paddr);
840 IWX_DPRINTF(sc, IWX_DEBUG_FIRMWARE_TLV,
841 "%s: firmware paging section %d at 0x%llx size %lld\n",
842 __func__, i,
843 (unsigned long long)dram->paging[i].paddr,
844 (unsigned long long)dram->paging[i].size);
845 }
846
847 return 0;
848 }
849
850 static void
iwx_fw_version_str(char * buf,size_t bufsize,uint32_t major,uint32_t minor,uint32_t api)851 iwx_fw_version_str(char *buf, size_t bufsize,
852 uint32_t major, uint32_t minor, uint32_t api)
853 {
854 /*
855 * Starting with major version 35 the Linux driver prints the minor
856 * version in hexadecimal.
857 */
858 if (major >= 35)
859 snprintf(buf, bufsize, "%u.%08x.%u", major, minor, api);
860 else
861 snprintf(buf, bufsize, "%u.%u.%u", major, minor, api);
862 }
863 #if 0
864 static int
865 iwx_alloc_fw_monitor_block(struct iwx_softc *sc, uint8_t max_power,
866 uint8_t min_power)
867 {
868 struct iwx_dma_info *fw_mon = &sc->fw_mon;
869 uint32_t size = 0;
870 uint8_t power;
871 int err;
872
873 if (fw_mon->size)
874 return 0;
875
876 for (power = max_power; power >= min_power; power--) {
877 size = (1 << power);
878
879 err = iwx_dma_contig_alloc(sc->sc_dmat, fw_mon, size, 0);
880 if (err)
881 continue;
882
883 IWX_DPRINTF(sc, IWX_DEBUG_FIRMWARE_TLV,
884 "%s: allocated 0x%08x bytes for firmware monitor.\n",
885 DEVNAME(sc), size);
886 break;
887 }
888
889 if (err) {
890 fw_mon->size = 0;
891 return err;
892 }
893
894 if (power != max_power)
895 IWX_DPRINTF(sc, IWX_DEBUG_FIRMWARE_TLV,
896 "%s: Sorry - debug buffer is only %luK while you requested %luK\n",
897 DEVNAME(sc), (unsigned long)(1 << (power - 10)),
898 (unsigned long)(1 << (max_power - 10)));
899
900 return 0;
901 }
902
903 static int
904 iwx_alloc_fw_monitor(struct iwx_softc *sc, uint8_t max_power)
905 {
906 if (!max_power) {
907 /* default max_power is maximum */
908 max_power = 26;
909 } else {
910 max_power += 11;
911 }
912
913 if (max_power > 26) {
914 IWX_DPRINTF(sc, IWX_DEBUG_FIRMWARE_TLV,
915 "%s: External buffer size for monitor is too big %d, "
916 "check the FW TLV\n", DEVNAME(sc), max_power);
917 return 0;
918 }
919
920 if (sc->fw_mon.size)
921 return 0;
922
923 return iwx_alloc_fw_monitor_block(sc, max_power, 11);
924 }
925 #endif
926
927 static int
iwx_apply_debug_destination(struct iwx_softc * sc)928 iwx_apply_debug_destination(struct iwx_softc *sc)
929 {
930 #if 0
931 struct iwx_fw_dbg_dest_tlv_v1 *dest_v1;
932 int i, err;
933 uint8_t mon_mode, size_power, base_shift, end_shift;
934 uint32_t base_reg, end_reg;
935
936 dest_v1 = sc->sc_fw.dbg_dest_tlv_v1;
937 mon_mode = dest_v1->monitor_mode;
938 size_power = dest_v1->size_power;
939 base_reg = le32toh(dest_v1->base_reg);
940 end_reg = le32toh(dest_v1->end_reg);
941 base_shift = dest_v1->base_shift;
942 end_shift = dest_v1->end_shift;
943
944 DPRINTF(("%s: applying debug destination %d\n", DEVNAME(sc), mon_mode));
945
946 if (mon_mode == EXTERNAL_MODE) {
947 err = iwx_alloc_fw_monitor(sc, size_power);
948 if (err)
949 return err;
950 }
951
952 if (!iwx_nic_lock(sc))
953 return EBUSY;
954
955 for (i = 0; i < sc->sc_fw.n_dest_reg; i++) {
956 uint32_t addr, val;
957 uint8_t op;
958
959 addr = le32toh(dest_v1->reg_ops[i].addr);
960 val = le32toh(dest_v1->reg_ops[i].val);
961 op = dest_v1->reg_ops[i].op;
962
963 DPRINTF(("%s: op=%u addr=%u val=%u\n", __func__, op, addr, val));
964 switch (op) {
965 case CSR_ASSIGN:
966 IWX_WRITE(sc, addr, val);
967 break;
968 case CSR_SETBIT:
969 IWX_SETBITS(sc, addr, (1 << val));
970 break;
971 case CSR_CLEARBIT:
972 IWX_CLRBITS(sc, addr, (1 << val));
973 break;
974 case PRPH_ASSIGN:
975 iwx_write_prph(sc, addr, val);
976 break;
977 case PRPH_SETBIT:
978 err = iwx_set_bits_prph(sc, addr, (1 << val));
979 if (err)
980 return err;
981 break;
982 case PRPH_CLEARBIT:
983 err = iwx_clear_bits_prph(sc, addr, (1 << val));
984 if (err)
985 return err;
986 break;
987 case PRPH_BLOCKBIT:
988 if (iwx_read_prph(sc, addr) & (1 << val))
989 goto monitor;
990 break;
991 default:
992 DPRINTF(("%s: FW debug - unknown OP %d\n",
993 DEVNAME(sc), op));
994 break;
995 }
996 }
997
998 monitor:
999 if (mon_mode == EXTERNAL_MODE && sc->fw_mon.size) {
1000 iwx_write_prph(sc, le32toh(base_reg),
1001 sc->fw_mon.paddr >> base_shift);
1002 iwx_write_prph(sc, end_reg,
1003 (sc->fw_mon.paddr + sc->fw_mon.size - 256)
1004 >> end_shift);
1005 }
1006
1007 iwx_nic_unlock(sc);
1008 return 0;
1009 #else
1010 return 0;
1011 #endif
1012 }
1013
1014 static void
iwx_set_ltr(struct iwx_softc * sc)1015 iwx_set_ltr(struct iwx_softc *sc)
1016 {
1017 uint32_t ltr_val = IWX_CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ |
1018 ((IWX_CSR_LTR_LONG_VAL_AD_SCALE_USEC <<
1019 IWX_CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE_SHIFT) &
1020 IWX_CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE_MASK) |
1021 ((250 << IWX_CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL_SHIFT) &
1022 IWX_CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL_MASK) |
1023 IWX_CSR_LTR_LONG_VAL_AD_SNOOP_REQ |
1024 ((IWX_CSR_LTR_LONG_VAL_AD_SCALE_USEC <<
1025 IWX_CSR_LTR_LONG_VAL_AD_SNOOP_SCALE_SHIFT) &
1026 IWX_CSR_LTR_LONG_VAL_AD_SNOOP_SCALE_MASK) |
1027 (250 & IWX_CSR_LTR_LONG_VAL_AD_SNOOP_VAL);
1028
1029 /*
1030 * To workaround hardware latency issues during the boot process,
1031 * initialize the LTR to ~250 usec (see ltr_val above).
1032 * The firmware initializes this again later (to a smaller value).
1033 */
1034 if (!sc->sc_integrated) {
1035 IWX_WRITE(sc, IWX_CSR_LTR_LONG_VAL_AD, ltr_val);
1036 } else if (sc->sc_integrated &&
1037 sc->sc_device_family == IWX_DEVICE_FAMILY_22000) {
1038 iwx_write_prph(sc, IWX_HPM_MAC_LTR_CSR,
1039 IWX_HPM_MAC_LRT_ENABLE_ALL);
1040 iwx_write_prph(sc, IWX_HPM_UMAC_LTR, ltr_val);
1041 }
1042 }
1043
1044 int
iwx_ctxt_info_init(struct iwx_softc * sc,const struct iwx_fw_sects * fws)1045 iwx_ctxt_info_init(struct iwx_softc *sc, const struct iwx_fw_sects *fws)
1046 {
1047 struct iwx_context_info *ctxt_info;
1048 struct iwx_context_info_rbd_cfg *rx_cfg;
1049 uint32_t control_flags = 0;
1050 uint64_t paddr;
1051 int err;
1052
1053 ctxt_info = sc->ctxt_info_dma.vaddr;
1054 memset(ctxt_info, 0, sizeof(*ctxt_info));
1055
1056 ctxt_info->version.version = 0;
1057 ctxt_info->version.mac_id =
1058 htole16((uint16_t)IWX_READ(sc, IWX_CSR_HW_REV));
1059 /* size is in DWs */
1060 ctxt_info->version.size = htole16(sizeof(*ctxt_info) / 4);
1061
1062 KASSERT(IWX_RX_QUEUE_CB_SIZE(IWX_MQ_RX_TABLE_SIZE) < 0xF,
1063 ("IWX_RX_QUEUE_CB_SIZE exceeds rate table size"));
1064
1065 control_flags = IWX_CTXT_INFO_TFD_FORMAT_LONG |
1066 (IWX_RX_QUEUE_CB_SIZE(IWX_MQ_RX_TABLE_SIZE) <<
1067 IWX_CTXT_INFO_RB_CB_SIZE_POS) |
1068 (IWX_CTXT_INFO_RB_SIZE_4K << IWX_CTXT_INFO_RB_SIZE_POS);
1069 ctxt_info->control.control_flags = htole32(control_flags);
1070
1071 /* initialize RX default queue */
1072 rx_cfg = &ctxt_info->rbd_cfg;
1073 rx_cfg->free_rbd_addr = htole64(sc->rxq.free_desc_dma.paddr);
1074 rx_cfg->used_rbd_addr = htole64(sc->rxq.used_desc_dma.paddr);
1075 rx_cfg->status_wr_ptr = htole64(sc->rxq.stat_dma.paddr);
1076
1077 /* initialize TX command queue */
1078 ctxt_info->hcmd_cfg.cmd_queue_addr =
1079 htole64(sc->txq[IWX_DQA_CMD_QUEUE].desc_dma.paddr);
1080 ctxt_info->hcmd_cfg.cmd_queue_size =
1081 IWX_TFD_QUEUE_CB_SIZE(IWX_TX_RING_COUNT);
1082
1083 /* allocate ucode sections in dram and set addresses */
1084 err = iwx_init_fw_sec(sc, fws, &ctxt_info->dram);
1085 if (err) {
1086 iwx_ctxt_info_free_fw_img(sc);
1087 return err;
1088 }
1089
1090 /* Configure debug, if exists */
1091 if (sc->sc_fw.dbg_dest_tlv_v1) {
1092 #if 1
1093 err = iwx_apply_debug_destination(sc);
1094 if (err) {
1095 iwx_ctxt_info_free_fw_img(sc);
1096 return err;
1097 }
1098 #endif
1099 }
1100
1101 /*
1102 * Write the context info DMA base address. The device expects a
1103 * 64-bit address but a simple bus_space_write_8 to this register
1104 * won't work on some devices, such as the AX201.
1105 */
1106 paddr = sc->ctxt_info_dma.paddr;
1107 IWX_WRITE(sc, IWX_CSR_CTXT_INFO_BA, paddr & 0xffffffff);
1108 IWX_WRITE(sc, IWX_CSR_CTXT_INFO_BA + 4, paddr >> 32);
1109
1110 /* kick FW self load */
1111 if (!iwx_nic_lock(sc)) {
1112 iwx_ctxt_info_free_fw_img(sc);
1113 return EBUSY;
1114 }
1115
1116 iwx_set_ltr(sc);
1117 iwx_write_prph(sc, IWX_UREG_CPU_INIT_RUN, 1);
1118 iwx_nic_unlock(sc);
1119
1120 /* Context info will be released upon alive or failure to get one */
1121
1122 return 0;
1123 }
1124
1125 static int
iwx_ctxt_info_gen3_init(struct iwx_softc * sc,const struct iwx_fw_sects * fws)1126 iwx_ctxt_info_gen3_init(struct iwx_softc *sc, const struct iwx_fw_sects *fws)
1127 {
1128 struct iwx_context_info_gen3 *ctxt_info_gen3;
1129 struct iwx_prph_scratch *prph_scratch;
1130 struct iwx_prph_scratch_ctrl_cfg *prph_sc_ctrl;
1131 uint16_t cb_size;
1132 uint32_t control_flags, scratch_size;
1133 uint64_t paddr;
1134 int err;
1135
1136 if (sc->sc_fw.iml == NULL || sc->sc_fw.iml_len == 0) {
1137 printf("%s: no image loader found in firmware file\n",
1138 DEVNAME(sc));
1139 iwx_ctxt_info_free_fw_img(sc);
1140 return EINVAL;
1141 }
1142
1143 err = iwx_dma_contig_alloc(sc->sc_dmat, &sc->iml_dma,
1144 sc->sc_fw.iml_len, 1);
1145 if (err) {
1146 printf("%s: could not allocate DMA memory for "
1147 "firmware image loader\n", DEVNAME(sc));
1148 iwx_ctxt_info_free_fw_img(sc);
1149 return ENOMEM;
1150 }
1151
1152 prph_scratch = sc->prph_scratch_dma.vaddr;
1153 memset(prph_scratch, 0, sizeof(*prph_scratch));
1154 prph_sc_ctrl = &prph_scratch->ctrl_cfg;
1155 prph_sc_ctrl->version.version = 0;
1156 prph_sc_ctrl->version.mac_id = htole16(IWX_READ(sc, IWX_CSR_HW_REV));
1157 prph_sc_ctrl->version.size = htole16(sizeof(*prph_scratch) / 4);
1158
1159 control_flags = IWX_PRPH_SCRATCH_RB_SIZE_4K |
1160 IWX_PRPH_SCRATCH_MTR_MODE |
1161 (IWX_PRPH_MTR_FORMAT_256B & IWX_PRPH_SCRATCH_MTR_FORMAT);
1162 if (sc->sc_imr_enabled)
1163 control_flags |= IWX_PRPH_SCRATCH_IMR_DEBUG_EN;
1164 prph_sc_ctrl->control.control_flags = htole32(control_flags);
1165
1166 /* initialize RX default queue */
1167 prph_sc_ctrl->rbd_cfg.free_rbd_addr =
1168 htole64(sc->rxq.free_desc_dma.paddr);
1169
1170 /* allocate ucode sections in dram and set addresses */
1171 err = iwx_init_fw_sec(sc, fws, &prph_scratch->dram);
1172 if (err) {
1173 iwx_dma_contig_free(&sc->iml_dma);
1174 iwx_ctxt_info_free_fw_img(sc);
1175 return err;
1176 }
1177
1178 ctxt_info_gen3 = sc->ctxt_info_dma.vaddr;
1179 memset(ctxt_info_gen3, 0, sizeof(*ctxt_info_gen3));
1180 ctxt_info_gen3->prph_info_base_addr = htole64(sc->prph_info_dma.paddr);
1181 ctxt_info_gen3->prph_scratch_base_addr =
1182 htole64(sc->prph_scratch_dma.paddr);
1183 scratch_size = sizeof(*prph_scratch);
1184 ctxt_info_gen3->prph_scratch_size = htole32(scratch_size);
1185 ctxt_info_gen3->cr_head_idx_arr_base_addr =
1186 htole64(sc->rxq.stat_dma.paddr);
1187 ctxt_info_gen3->tr_tail_idx_arr_base_addr =
1188 htole64(sc->prph_info_dma.paddr + PAGE_SIZE / 2);
1189 ctxt_info_gen3->cr_tail_idx_arr_base_addr =
1190 htole64(sc->prph_info_dma.paddr + 3 * PAGE_SIZE / 4);
1191 ctxt_info_gen3->mtr_base_addr =
1192 htole64(sc->txq[IWX_DQA_CMD_QUEUE].desc_dma.paddr);
1193 ctxt_info_gen3->mcr_base_addr = htole64(sc->rxq.used_desc_dma.paddr);
1194 cb_size = IWX_TFD_QUEUE_CB_SIZE(IWX_TX_RING_COUNT);
1195 ctxt_info_gen3->mtr_size = htole16(cb_size);
1196 cb_size = IWX_RX_QUEUE_CB_SIZE(IWX_MQ_RX_TABLE_SIZE);
1197 ctxt_info_gen3->mcr_size = htole16(cb_size);
1198
1199 memcpy(sc->iml_dma.vaddr, sc->sc_fw.iml, sc->sc_fw.iml_len);
1200
1201 paddr = sc->ctxt_info_dma.paddr;
1202 IWX_WRITE(sc, IWX_CSR_CTXT_INFO_ADDR, paddr & 0xffffffff);
1203 IWX_WRITE(sc, IWX_CSR_CTXT_INFO_ADDR + 4, paddr >> 32);
1204
1205 paddr = sc->iml_dma.paddr;
1206 IWX_WRITE(sc, IWX_CSR_IML_DATA_ADDR, paddr & 0xffffffff);
1207 IWX_WRITE(sc, IWX_CSR_IML_DATA_ADDR + 4, paddr >> 32);
1208 IWX_WRITE(sc, IWX_CSR_IML_SIZE_ADDR, sc->sc_fw.iml_len);
1209
1210 IWX_SETBITS(sc, IWX_CSR_CTXT_INFO_BOOT_CTRL,
1211 IWX_CSR_AUTO_FUNC_BOOT_ENA);
1212
1213 IWX_DPRINTF(sc, IWX_DEBUG_FIRMWARE_TLV,
1214 "%s:%d kicking fw to get going\n", __func__, __LINE__);
1215
1216 /* kick FW self load */
1217 if (!iwx_nic_lock(sc)) {
1218 iwx_dma_contig_free(&sc->iml_dma);
1219 iwx_ctxt_info_free_fw_img(sc);
1220 return EBUSY;
1221 }
1222 iwx_set_ltr(sc);
1223 iwx_write_umac_prph(sc, IWX_UREG_CPU_INIT_RUN, 1);
1224 iwx_nic_unlock(sc);
1225
1226 /* Context info will be released upon alive or failure to get one */
1227 return 0;
1228 }
1229
1230 static void
iwx_ctxt_info_free_fw_img(struct iwx_softc * sc)1231 iwx_ctxt_info_free_fw_img(struct iwx_softc *sc)
1232 {
1233 struct iwx_self_init_dram *dram = &sc->init_dram;
1234 int i;
1235
1236 if (!dram->fw)
1237 return;
1238
1239 for (i = 0; i < dram->lmac_cnt + dram->umac_cnt; i++)
1240 iwx_dma_contig_free(&dram->fw[i]);
1241
1242 free(dram->fw, M_DEVBUF);
1243 dram->lmac_cnt = 0;
1244 dram->umac_cnt = 0;
1245 dram->fw = NULL;
1246 }
1247
1248 static int
iwx_firmware_store_section(struct iwx_softc * sc,enum iwx_ucode_type type,const uint8_t * data,size_t dlen)1249 iwx_firmware_store_section(struct iwx_softc *sc, enum iwx_ucode_type type,
1250 const uint8_t *data, size_t dlen)
1251 {
1252 struct iwx_fw_sects *fws;
1253 struct iwx_fw_onesect *fwone;
1254
1255 if (type >= IWX_UCODE_TYPE_MAX)
1256 return EINVAL;
1257 if (dlen < sizeof(uint32_t))
1258 return EINVAL;
1259
1260 fws = &sc->sc_fw.fw_sects[type];
1261 IWX_DPRINTF(sc, IWX_DEBUG_FIRMWARE_TLV,
1262 "%s: ucode type %d section %d\n", DEVNAME(sc), type, fws->fw_count);
1263 if (fws->fw_count >= IWX_UCODE_SECT_MAX)
1264 return EINVAL;
1265
1266 fwone = &fws->fw_sect[fws->fw_count];
1267
1268 /* first 32bit are device load offset */
1269 memcpy(&fwone->fws_devoff, data, sizeof(uint32_t));
1270
1271 /* rest is data */
1272 fwone->fws_data = data + sizeof(uint32_t);
1273 fwone->fws_len = dlen - sizeof(uint32_t);
1274
1275 fws->fw_count++;
1276 fws->fw_totlen += fwone->fws_len;
1277
1278 return 0;
1279 }
1280
1281 #define IWX_DEFAULT_SCAN_CHANNELS 40
1282 /* Newer firmware might support more channels. Raise this value if needed. */
1283 #define IWX_MAX_SCAN_CHANNELS 67 /* as of iwx-cc-a0-62 firmware */
1284
1285 struct iwx_tlv_calib_data {
1286 uint32_t ucode_type;
1287 struct iwx_tlv_calib_ctrl calib;
1288 } __packed;
1289
1290 static int
iwx_set_default_calib(struct iwx_softc * sc,const void * data)1291 iwx_set_default_calib(struct iwx_softc *sc, const void *data)
1292 {
1293 const struct iwx_tlv_calib_data *def_calib = data;
1294 uint32_t ucode_type = le32toh(def_calib->ucode_type);
1295
1296 if (ucode_type >= IWX_UCODE_TYPE_MAX)
1297 return EINVAL;
1298
1299 sc->sc_default_calib[ucode_type].flow_trigger =
1300 def_calib->calib.flow_trigger;
1301 sc->sc_default_calib[ucode_type].event_trigger =
1302 def_calib->calib.event_trigger;
1303
1304 return 0;
1305 }
1306
1307 static void
iwx_fw_info_free(struct iwx_fw_info * fw)1308 iwx_fw_info_free(struct iwx_fw_info *fw)
1309 {
1310 free(fw->fw_rawdata, M_DEVBUF);
1311 fw->fw_rawdata = NULL;
1312 fw->fw_rawsize = 0;
1313 /* don't touch fw->fw_status */
1314 memset(fw->fw_sects, 0, sizeof(fw->fw_sects));
1315 free(fw->iml, M_DEVBUF);
1316 fw->iml = NULL;
1317 fw->iml_len = 0;
1318 }
1319
1320 #define IWX_FW_ADDR_CACHE_CONTROL 0xC0000000
1321
1322 static int
iwx_read_firmware(struct iwx_softc * sc)1323 iwx_read_firmware(struct iwx_softc *sc)
1324 {
1325 struct iwx_fw_info *fw = &sc->sc_fw;
1326 const struct iwx_tlv_ucode_header *uhdr;
1327 struct iwx_ucode_tlv tlv;
1328 uint32_t tlv_type;
1329 const uint8_t *data;
1330 int err = 0;
1331 size_t len;
1332 const struct firmware *fwp;
1333
1334 if (fw->fw_status == IWX_FW_STATUS_DONE)
1335 return 0;
1336
1337 fw->fw_status = IWX_FW_STATUS_INPROGRESS;
1338 fwp = firmware_get(sc->sc_fwname);
1339 sc->sc_fwp = fwp;
1340
1341 if (fwp == NULL) {
1342 printf("%s: could not read firmware %s\n",
1343 DEVNAME(sc), sc->sc_fwname);
1344 err = ENOENT;
1345 goto out;
1346 }
1347
1348 IWX_DPRINTF(sc, IWX_DEBUG_FW, "%s:%d %s: using firmware %s\n",
1349 __func__, __LINE__, DEVNAME(sc), sc->sc_fwname);
1350
1351
1352 sc->sc_capaflags = 0;
1353 sc->sc_capa_n_scan_channels = IWX_DEFAULT_SCAN_CHANNELS;
1354 memset(sc->sc_enabled_capa, 0, sizeof(sc->sc_enabled_capa));
1355 memset(sc->sc_ucode_api, 0, sizeof(sc->sc_ucode_api));
1356 sc->n_cmd_versions = 0;
1357
1358 uhdr = (const void *)(fwp->data);
1359 if (*(const uint32_t *)fwp->data != 0
1360 || le32toh(uhdr->magic) != IWX_TLV_UCODE_MAGIC) {
1361 printf("%s: invalid firmware %s\n",
1362 DEVNAME(sc), sc->sc_fwname);
1363 err = EINVAL;
1364 goto out;
1365 }
1366
1367 iwx_fw_version_str(sc->sc_fwver, sizeof(sc->sc_fwver),
1368 IWX_UCODE_MAJOR(le32toh(uhdr->ver)),
1369 IWX_UCODE_MINOR(le32toh(uhdr->ver)),
1370 IWX_UCODE_API(le32toh(uhdr->ver)));
1371
1372 data = uhdr->data;
1373 len = fwp->datasize - sizeof(*uhdr);
1374
1375 while (len >= sizeof(tlv)) {
1376 size_t tlv_len;
1377 const void *tlv_data;
1378
1379 memcpy(&tlv, data, sizeof(tlv));
1380 tlv_len = le32toh(tlv.length);
1381 tlv_type = le32toh(tlv.type);
1382
1383 len -= sizeof(tlv);
1384 data += sizeof(tlv);
1385 tlv_data = data;
1386
1387 if (len < tlv_len) {
1388 printf("%s: firmware too short: %zu bytes\n",
1389 DEVNAME(sc), len);
1390 err = EINVAL;
1391 goto parse_out;
1392 }
1393
1394 switch (tlv_type) {
1395 case IWX_UCODE_TLV_PROBE_MAX_LEN:
1396 if (tlv_len < sizeof(uint32_t)) {
1397 err = EINVAL;
1398 goto parse_out;
1399 }
1400 sc->sc_capa_max_probe_len
1401 = le32toh(*(const uint32_t *)tlv_data);
1402 if (sc->sc_capa_max_probe_len >
1403 IWX_SCAN_OFFLOAD_PROBE_REQ_SIZE) {
1404 err = EINVAL;
1405 goto parse_out;
1406 }
1407 break;
1408 case IWX_UCODE_TLV_PAN:
1409 if (tlv_len) {
1410 err = EINVAL;
1411 goto parse_out;
1412 }
1413 sc->sc_capaflags |= IWX_UCODE_TLV_FLAGS_PAN;
1414 break;
1415 case IWX_UCODE_TLV_FLAGS:
1416 if (tlv_len < sizeof(uint32_t)) {
1417 err = EINVAL;
1418 goto parse_out;
1419 }
1420 /*
1421 * Apparently there can be many flags, but Linux driver
1422 * parses only the first one, and so do we.
1423 *
1424 * XXX: why does this override IWX_UCODE_TLV_PAN?
1425 * Intentional or a bug? Observations from
1426 * current firmware file:
1427 * 1) TLV_PAN is parsed first
1428 * 2) TLV_FLAGS contains TLV_FLAGS_PAN
1429 * ==> this resets TLV_PAN to itself... hnnnk
1430 */
1431 sc->sc_capaflags = le32toh(*(const uint32_t *)tlv_data);
1432 break;
1433 case IWX_UCODE_TLV_CSCHEME:
1434 err = iwx_store_cscheme(sc, tlv_data, tlv_len);
1435 if (err)
1436 goto parse_out;
1437 break;
1438 case IWX_UCODE_TLV_NUM_OF_CPU: {
1439 uint32_t num_cpu;
1440 if (tlv_len != sizeof(uint32_t)) {
1441 err = EINVAL;
1442 goto parse_out;
1443 }
1444 num_cpu = le32toh(*(const uint32_t *)tlv_data);
1445 if (num_cpu < 1 || num_cpu > 2) {
1446 err = EINVAL;
1447 goto parse_out;
1448 }
1449 break;
1450 }
1451 case IWX_UCODE_TLV_SEC_RT:
1452 err = iwx_firmware_store_section(sc,
1453 IWX_UCODE_TYPE_REGULAR, tlv_data, tlv_len);
1454 if (err)
1455 goto parse_out;
1456 break;
1457 case IWX_UCODE_TLV_SEC_INIT:
1458 err = iwx_firmware_store_section(sc,
1459 IWX_UCODE_TYPE_INIT, tlv_data, tlv_len);
1460 if (err)
1461 goto parse_out;
1462 break;
1463 case IWX_UCODE_TLV_SEC_WOWLAN:
1464 err = iwx_firmware_store_section(sc,
1465 IWX_UCODE_TYPE_WOW, tlv_data, tlv_len);
1466 if (err)
1467 goto parse_out;
1468 break;
1469 case IWX_UCODE_TLV_DEF_CALIB:
1470 if (tlv_len != sizeof(struct iwx_tlv_calib_data)) {
1471 err = EINVAL;
1472 goto parse_out;
1473 }
1474 err = iwx_set_default_calib(sc, tlv_data);
1475 if (err)
1476 goto parse_out;
1477 break;
1478 case IWX_UCODE_TLV_PHY_SKU:
1479 if (tlv_len != sizeof(uint32_t)) {
1480 err = EINVAL;
1481 goto parse_out;
1482 }
1483 sc->sc_fw_phy_config = le32toh(*(const uint32_t *)tlv_data);
1484 break;
1485
1486 case IWX_UCODE_TLV_API_CHANGES_SET: {
1487 const struct iwx_ucode_api *api;
1488 int idx, i;
1489 if (tlv_len != sizeof(*api)) {
1490 err = EINVAL;
1491 goto parse_out;
1492 }
1493 api = (const struct iwx_ucode_api *)tlv_data;
1494 idx = le32toh(api->api_index);
1495 if (idx >= howmany(IWX_NUM_UCODE_TLV_API, 32)) {
1496 err = EINVAL;
1497 goto parse_out;
1498 }
1499 for (i = 0; i < 32; i++) {
1500 if ((le32toh(api->api_flags) & (1 << i)) == 0)
1501 continue;
1502 setbit(sc->sc_ucode_api, i + (32 * idx));
1503 }
1504 break;
1505 }
1506
1507 case IWX_UCODE_TLV_ENABLED_CAPABILITIES: {
1508 const struct iwx_ucode_capa *capa;
1509 int idx, i;
1510 if (tlv_len != sizeof(*capa)) {
1511 err = EINVAL;
1512 goto parse_out;
1513 }
1514 capa = (const struct iwx_ucode_capa *)tlv_data;
1515 idx = le32toh(capa->api_index);
1516 if (idx >= howmany(IWX_NUM_UCODE_TLV_CAPA, 32)) {
1517 goto parse_out;
1518 }
1519 for (i = 0; i < 32; i++) {
1520 if ((le32toh(capa->api_capa) & (1 << i)) == 0)
1521 continue;
1522 setbit(sc->sc_enabled_capa, i + (32 * idx));
1523 }
1524 break;
1525 }
1526
1527 case IWX_UCODE_TLV_SDIO_ADMA_ADDR:
1528 case IWX_UCODE_TLV_FW_GSCAN_CAPA:
1529 /* ignore, not used by current driver */
1530 break;
1531
1532 case IWX_UCODE_TLV_SEC_RT_USNIFFER:
1533 err = iwx_firmware_store_section(sc,
1534 IWX_UCODE_TYPE_REGULAR_USNIFFER, tlv_data,
1535 tlv_len);
1536 if (err)
1537 goto parse_out;
1538 break;
1539
1540 case IWX_UCODE_TLV_PAGING:
1541 if (tlv_len != sizeof(uint32_t)) {
1542 err = EINVAL;
1543 goto parse_out;
1544 }
1545 break;
1546
1547 case IWX_UCODE_TLV_N_SCAN_CHANNELS:
1548 if (tlv_len != sizeof(uint32_t)) {
1549 err = EINVAL;
1550 goto parse_out;
1551 }
1552 sc->sc_capa_n_scan_channels =
1553 le32toh(*(const uint32_t *)tlv_data);
1554 if (sc->sc_capa_n_scan_channels > IWX_MAX_SCAN_CHANNELS) {
1555 err = ERANGE;
1556 goto parse_out;
1557 }
1558 break;
1559
1560 case IWX_UCODE_TLV_FW_VERSION:
1561 if (tlv_len != sizeof(uint32_t) * 3) {
1562 err = EINVAL;
1563 goto parse_out;
1564 }
1565
1566 iwx_fw_version_str(sc->sc_fwver, sizeof(sc->sc_fwver),
1567 le32toh(((const uint32_t *)tlv_data)[0]),
1568 le32toh(((const uint32_t *)tlv_data)[1]),
1569 le32toh(((const uint32_t *)tlv_data)[2]));
1570 break;
1571
1572 case IWX_UCODE_TLV_FW_DBG_DEST: {
1573 const struct iwx_fw_dbg_dest_tlv_v1 *dest_v1 = NULL;
1574
1575 fw->dbg_dest_ver = (const uint8_t *)tlv_data;
1576 if (*fw->dbg_dest_ver != 0) {
1577 err = EINVAL;
1578 goto parse_out;
1579 }
1580
1581 if (fw->dbg_dest_tlv_init)
1582 break;
1583 fw->dbg_dest_tlv_init = true;
1584
1585 dest_v1 = (const void *)tlv_data;
1586 fw->dbg_dest_tlv_v1 = dest_v1;
1587 fw->n_dest_reg = tlv_len -
1588 offsetof(struct iwx_fw_dbg_dest_tlv_v1, reg_ops);
1589 fw->n_dest_reg /= sizeof(dest_v1->reg_ops[0]);
1590 IWX_DPRINTF(sc, IWX_DEBUG_FIRMWARE_TLV,
1591 "%s: found debug dest; n_dest_reg=%d\n",
1592 __func__, fw->n_dest_reg);
1593 break;
1594 }
1595
1596 case IWX_UCODE_TLV_FW_DBG_CONF: {
1597 const struct iwx_fw_dbg_conf_tlv *conf = (const void *)tlv_data;
1598
1599 if (!fw->dbg_dest_tlv_init ||
1600 conf->id >= nitems(fw->dbg_conf_tlv) ||
1601 fw->dbg_conf_tlv[conf->id] != NULL)
1602 break;
1603
1604 IWX_DPRINTF(sc, IWX_DEBUG_FIRMWARE_TLV,
1605 "Found debug configuration: %d\n", conf->id);
1606 fw->dbg_conf_tlv[conf->id] = conf;
1607 fw->dbg_conf_tlv_len[conf->id] = tlv_len;
1608 break;
1609 }
1610
1611 case IWX_UCODE_TLV_UMAC_DEBUG_ADDRS: {
1612 const struct iwx_umac_debug_addrs *dbg_ptrs =
1613 (const void *)tlv_data;
1614
1615 if (tlv_len != sizeof(*dbg_ptrs)) {
1616 err = EINVAL;
1617 goto parse_out;
1618 }
1619 if (sc->sc_device_family < IWX_DEVICE_FAMILY_22000)
1620 break;
1621 sc->sc_uc.uc_umac_error_event_table =
1622 le32toh(dbg_ptrs->error_info_addr) &
1623 ~IWX_FW_ADDR_CACHE_CONTROL;
1624 sc->sc_uc.error_event_table_tlv_status |=
1625 IWX_ERROR_EVENT_TABLE_UMAC;
1626 break;
1627 }
1628
1629 case IWX_UCODE_TLV_LMAC_DEBUG_ADDRS: {
1630 const struct iwx_lmac_debug_addrs *dbg_ptrs =
1631 (const void *)tlv_data;
1632
1633 if (tlv_len != sizeof(*dbg_ptrs)) {
1634 err = EINVAL;
1635 goto parse_out;
1636 }
1637 if (sc->sc_device_family < IWX_DEVICE_FAMILY_22000)
1638 break;
1639 sc->sc_uc.uc_lmac_error_event_table[0] =
1640 le32toh(dbg_ptrs->error_event_table_ptr) &
1641 ~IWX_FW_ADDR_CACHE_CONTROL;
1642 sc->sc_uc.error_event_table_tlv_status |=
1643 IWX_ERROR_EVENT_TABLE_LMAC1;
1644 break;
1645 }
1646
1647 case IWX_UCODE_TLV_FW_MEM_SEG:
1648 break;
1649
1650 case IWX_UCODE_TLV_IML:
1651 if (sc->sc_fw.iml != NULL) {
1652 free(fw->iml, M_DEVBUF);
1653 fw->iml_len = 0;
1654 }
1655 sc->sc_fw.iml = malloc(tlv_len, M_DEVBUF,
1656 M_WAITOK | M_ZERO);
1657 if (sc->sc_fw.iml == NULL) {
1658 err = ENOMEM;
1659 goto parse_out;
1660 }
1661 memcpy(sc->sc_fw.iml, tlv_data, tlv_len);
1662 sc->sc_fw.iml_len = tlv_len;
1663 break;
1664
1665 case IWX_UCODE_TLV_CMD_VERSIONS:
1666 if (tlv_len % sizeof(struct iwx_fw_cmd_version)) {
1667 tlv_len /= sizeof(struct iwx_fw_cmd_version);
1668 tlv_len *= sizeof(struct iwx_fw_cmd_version);
1669 }
1670 if (sc->n_cmd_versions != 0) {
1671 err = EINVAL;
1672 goto parse_out;
1673 }
1674 if (tlv_len > sizeof(sc->cmd_versions)) {
1675 err = EINVAL;
1676 goto parse_out;
1677 }
1678 memcpy(&sc->cmd_versions[0], tlv_data, tlv_len);
1679 sc->n_cmd_versions = tlv_len / sizeof(struct iwx_fw_cmd_version);
1680 break;
1681
1682 case IWX_UCODE_TLV_FW_RECOVERY_INFO:
1683 break;
1684
1685 case IWX_UCODE_TLV_FW_FSEQ_VERSION:
1686 case IWX_UCODE_TLV_PHY_INTEGRATION_VERSION:
1687 case IWX_UCODE_TLV_FW_NUM_STATIONS:
1688 case IWX_UCODE_TLV_FW_NUM_BEACONS:
1689 break;
1690
1691 /* undocumented TLVs found in iwx-cc-a0-46 image */
1692 case 58:
1693 case 0x1000003:
1694 case 0x1000004:
1695 break;
1696
1697 /* undocumented TLVs found in iwx-cc-a0-48 image */
1698 case 0x1000000:
1699 case 0x1000002:
1700 break;
1701
1702 case IWX_UCODE_TLV_TYPE_DEBUG_INFO:
1703 case IWX_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
1704 case IWX_UCODE_TLV_TYPE_HCMD:
1705 case IWX_UCODE_TLV_TYPE_REGIONS:
1706 case IWX_UCODE_TLV_TYPE_TRIGGERS:
1707 case IWX_UCODE_TLV_TYPE_CONF_SET:
1708 case IWX_UCODE_TLV_SEC_TABLE_ADDR:
1709 case IWX_UCODE_TLV_D3_KEK_KCK_ADDR:
1710 case IWX_UCODE_TLV_CURRENT_PC:
1711 break;
1712
1713 /* undocumented TLV found in iwx-cc-a0-67 image */
1714 case 0x100000b:
1715 break;
1716
1717 /* undocumented TLV found in iwx-ty-a0-gf-a0-73 image */
1718 case 0x101:
1719 break;
1720
1721 /* undocumented TLV found in iwx-ty-a0-gf-a0-77 image */
1722 case 0x100000c:
1723 break;
1724
1725 /* undocumented TLV found in iwx-ty-a0-gf-a0-89 image */
1726 case 69:
1727 break;
1728
1729 default:
1730 err = EINVAL;
1731 goto parse_out;
1732 }
1733
1734 /*
1735 * Check for size_t overflow and ignore missing padding at
1736 * end of firmware file.
1737 */
1738 if (roundup(tlv_len, 4) > len)
1739 break;
1740
1741 len -= roundup(tlv_len, 4);
1742 data += roundup(tlv_len, 4);
1743 }
1744
1745 KASSERT(err == 0, ("unhandled fw parse error"));
1746
1747 parse_out:
1748 if (err) {
1749 printf("%s: firmware parse error %d, "
1750 "section type %d\n", DEVNAME(sc), err, tlv_type);
1751 }
1752
1753 out:
1754 if (err) {
1755 fw->fw_status = IWX_FW_STATUS_NONE;
1756 if (fw->fw_rawdata != NULL)
1757 iwx_fw_info_free(fw);
1758 } else
1759 fw->fw_status = IWX_FW_STATUS_DONE;
1760 return err;
1761 }
1762
1763 static uint32_t
iwx_prph_addr_mask(struct iwx_softc * sc)1764 iwx_prph_addr_mask(struct iwx_softc *sc)
1765 {
1766 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)
1767 return 0x00ffffff;
1768 else
1769 return 0x000fffff;
1770 }
1771
1772 static uint32_t
iwx_read_prph_unlocked(struct iwx_softc * sc,uint32_t addr)1773 iwx_read_prph_unlocked(struct iwx_softc *sc, uint32_t addr)
1774 {
1775 uint32_t mask = iwx_prph_addr_mask(sc);
1776 IWX_WRITE(sc, IWX_HBUS_TARG_PRPH_RADDR, ((addr & mask) | (3 << 24)));
1777 IWX_BARRIER_READ_WRITE(sc);
1778 return IWX_READ(sc, IWX_HBUS_TARG_PRPH_RDAT);
1779 }
1780
1781 uint32_t
iwx_read_prph(struct iwx_softc * sc,uint32_t addr)1782 iwx_read_prph(struct iwx_softc *sc, uint32_t addr)
1783 {
1784 iwx_nic_assert_locked(sc);
1785 return iwx_read_prph_unlocked(sc, addr);
1786 }
1787
1788 static void
iwx_write_prph_unlocked(struct iwx_softc * sc,uint32_t addr,uint32_t val)1789 iwx_write_prph_unlocked(struct iwx_softc *sc, uint32_t addr, uint32_t val)
1790 {
1791 uint32_t mask = iwx_prph_addr_mask(sc);
1792 IWX_WRITE(sc, IWX_HBUS_TARG_PRPH_WADDR, ((addr & mask) | (3 << 24)));
1793 IWX_BARRIER_WRITE(sc);
1794 IWX_WRITE(sc, IWX_HBUS_TARG_PRPH_WDAT, val);
1795 }
1796
1797 static void
iwx_write_prph(struct iwx_softc * sc,uint32_t addr,uint32_t val)1798 iwx_write_prph(struct iwx_softc *sc, uint32_t addr, uint32_t val)
1799 {
1800 iwx_nic_assert_locked(sc);
1801 iwx_write_prph_unlocked(sc, addr, val);
1802 }
1803
1804 static uint32_t
iwx_read_umac_prph(struct iwx_softc * sc,uint32_t addr)1805 iwx_read_umac_prph(struct iwx_softc *sc, uint32_t addr)
1806 {
1807 return iwx_read_prph(sc, addr + sc->sc_umac_prph_offset);
1808 }
1809
1810 static void
iwx_write_umac_prph(struct iwx_softc * sc,uint32_t addr,uint32_t val)1811 iwx_write_umac_prph(struct iwx_softc *sc, uint32_t addr, uint32_t val)
1812 {
1813 iwx_write_prph(sc, addr + sc->sc_umac_prph_offset, val);
1814 }
1815
1816 static int
iwx_read_mem(struct iwx_softc * sc,uint32_t addr,void * buf,int dwords)1817 iwx_read_mem(struct iwx_softc *sc, uint32_t addr, void *buf, int dwords)
1818 {
1819 int offs, err = 0;
1820 uint32_t *vals = buf;
1821
1822 if (iwx_nic_lock(sc)) {
1823 IWX_WRITE(sc, IWX_HBUS_TARG_MEM_RADDR, addr);
1824 for (offs = 0; offs < dwords; offs++)
1825 vals[offs] = le32toh(IWX_READ(sc, IWX_HBUS_TARG_MEM_RDAT));
1826 iwx_nic_unlock(sc);
1827 } else {
1828 err = EBUSY;
1829 }
1830 return err;
1831 }
1832
1833 static int
iwx_poll_bit(struct iwx_softc * sc,int reg,uint32_t bits,uint32_t mask,int timo)1834 iwx_poll_bit(struct iwx_softc *sc, int reg, uint32_t bits, uint32_t mask,
1835 int timo)
1836 {
1837 for (;;) {
1838 if ((IWX_READ(sc, reg) & mask) == (bits & mask)) {
1839 return 1;
1840 }
1841 if (timo < 10) {
1842 return 0;
1843 }
1844 timo -= 10;
1845 DELAY(10);
1846 }
1847 }
1848
1849 static int
iwx_nic_lock(struct iwx_softc * sc)1850 iwx_nic_lock(struct iwx_softc *sc)
1851 {
1852 if (sc->sc_nic_locks > 0) {
1853 iwx_nic_assert_locked(sc);
1854 sc->sc_nic_locks++;
1855 return 1; /* already locked */
1856 }
1857
1858 IWX_SETBITS(sc, IWX_CSR_GP_CNTRL,
1859 IWX_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1860
1861 DELAY(2);
1862
1863 if (iwx_poll_bit(sc, IWX_CSR_GP_CNTRL,
1864 IWX_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
1865 IWX_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
1866 | IWX_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP, 150000)) {
1867 sc->sc_nic_locks++;
1868 return 1;
1869 }
1870
1871 printf("%s: acquiring device failed\n", DEVNAME(sc));
1872 return 0;
1873 }
1874
1875 static void
iwx_nic_assert_locked(struct iwx_softc * sc)1876 iwx_nic_assert_locked(struct iwx_softc *sc)
1877 {
1878 if (sc->sc_nic_locks <= 0)
1879 panic("%s: nic locks counter %d", DEVNAME(sc), sc->sc_nic_locks);
1880 }
1881
1882 static void
iwx_nic_unlock(struct iwx_softc * sc)1883 iwx_nic_unlock(struct iwx_softc *sc)
1884 {
1885 if (sc->sc_nic_locks > 0) {
1886 if (--sc->sc_nic_locks == 0)
1887 IWX_CLRBITS(sc, IWX_CSR_GP_CNTRL,
1888 IWX_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1889 } else
1890 printf("%s: NIC already unlocked\n", DEVNAME(sc));
1891 }
1892
1893 static int
iwx_set_bits_mask_prph(struct iwx_softc * sc,uint32_t reg,uint32_t bits,uint32_t mask)1894 iwx_set_bits_mask_prph(struct iwx_softc *sc, uint32_t reg, uint32_t bits,
1895 uint32_t mask)
1896 {
1897 uint32_t val;
1898
1899 if (iwx_nic_lock(sc)) {
1900 val = iwx_read_prph(sc, reg) & mask;
1901 val |= bits;
1902 iwx_write_prph(sc, reg, val);
1903 iwx_nic_unlock(sc);
1904 return 0;
1905 }
1906 return EBUSY;
1907 }
1908
1909 static int
iwx_set_bits_prph(struct iwx_softc * sc,uint32_t reg,uint32_t bits)1910 iwx_set_bits_prph(struct iwx_softc *sc, uint32_t reg, uint32_t bits)
1911 {
1912 return iwx_set_bits_mask_prph(sc, reg, bits, ~0);
1913 }
1914
1915 static int
iwx_clear_bits_prph(struct iwx_softc * sc,uint32_t reg,uint32_t bits)1916 iwx_clear_bits_prph(struct iwx_softc *sc, uint32_t reg, uint32_t bits)
1917 {
1918 return iwx_set_bits_mask_prph(sc, reg, 0, ~bits);
1919 }
1920
1921 static void
iwx_dma_map_addr(void * arg,bus_dma_segment_t * segs,int nsegs,int error)1922 iwx_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
1923 {
1924 if (error != 0)
1925 return;
1926 KASSERT(nsegs == 1, ("too many DMA segments, %d should be 1", nsegs));
1927 *(bus_addr_t *)arg = segs[0].ds_addr;
1928 }
1929
1930 static int
iwx_dma_contig_alloc(bus_dma_tag_t tag,struct iwx_dma_info * dma,bus_size_t size,bus_size_t alignment)1931 iwx_dma_contig_alloc(bus_dma_tag_t tag, struct iwx_dma_info *dma,
1932 bus_size_t size, bus_size_t alignment)
1933 {
1934 int error;
1935
1936 dma->tag = NULL;
1937 dma->map = NULL;
1938 dma->size = size;
1939 dma->vaddr = NULL;
1940
1941 error = bus_dma_tag_create(tag, alignment,
1942 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, size,
1943 1, size, 0, NULL, NULL, &dma->tag);
1944 if (error != 0)
1945 goto fail;
1946
1947 error = bus_dmamem_alloc(dma->tag, (void **)&dma->vaddr,
1948 BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, &dma->map);
1949 if (error != 0)
1950 goto fail;
1951
1952 error = bus_dmamap_load(dma->tag, dma->map, dma->vaddr, size,
1953 iwx_dma_map_addr, &dma->paddr, BUS_DMA_NOWAIT);
1954 if (error != 0) {
1955 bus_dmamem_free(dma->tag, dma->vaddr, dma->map);
1956 dma->vaddr = NULL;
1957 goto fail;
1958 }
1959
1960 bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_PREWRITE);
1961
1962 return 0;
1963
1964 fail:
1965 iwx_dma_contig_free(dma);
1966 return error;
1967 }
1968
1969 static void
iwx_dma_contig_free(struct iwx_dma_info * dma)1970 iwx_dma_contig_free(struct iwx_dma_info *dma)
1971 {
1972 if (dma->vaddr != NULL) {
1973 bus_dmamap_sync(dma->tag, dma->map,
1974 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1975 bus_dmamap_unload(dma->tag, dma->map);
1976 bus_dmamem_free(dma->tag, dma->vaddr, dma->map);
1977 dma->vaddr = NULL;
1978 }
1979 if (dma->tag != NULL) {
1980 bus_dma_tag_destroy(dma->tag);
1981 dma->tag = NULL;
1982 }
1983 }
1984
1985 static int
iwx_alloc_rx_ring(struct iwx_softc * sc,struct iwx_rx_ring * ring)1986 iwx_alloc_rx_ring(struct iwx_softc *sc, struct iwx_rx_ring *ring)
1987 {
1988 bus_size_t size;
1989 int i, err;
1990
1991 ring->cur = 0;
1992
1993 /* Allocate RX descriptors (256-byte aligned). */
1994 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)
1995 size = sizeof(struct iwx_rx_transfer_desc);
1996 else
1997 size = sizeof(uint64_t);
1998 err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->free_desc_dma,
1999 size * IWX_RX_MQ_RING_COUNT, 256);
2000 if (err) {
2001 device_printf(sc->sc_dev,
2002 "could not allocate RX ring DMA memory\n");
2003 goto fail;
2004 }
2005 ring->desc = ring->free_desc_dma.vaddr;
2006
2007 /* Allocate RX status area (16-byte aligned). */
2008 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)
2009 size = sizeof(uint16_t);
2010 else
2011 size = sizeof(*ring->stat);
2012 err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->stat_dma, size, 16);
2013 if (err) {
2014 device_printf(sc->sc_dev,
2015 "could not allocate RX status DMA memory\n");
2016 goto fail;
2017 }
2018 ring->stat = ring->stat_dma.vaddr;
2019
2020 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)
2021 size = sizeof(struct iwx_rx_completion_desc);
2022 else
2023 size = sizeof(uint32_t);
2024 err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->used_desc_dma,
2025 size * IWX_RX_MQ_RING_COUNT, 256);
2026 if (err) {
2027 device_printf(sc->sc_dev,
2028 "could not allocate RX ring DMA memory\n");
2029 goto fail;
2030 }
2031
2032 err = bus_dma_tag_create(sc->sc_dmat, 1, 0, BUS_SPACE_MAXADDR_32BIT,
2033 BUS_SPACE_MAXADDR, NULL, NULL, IWX_RBUF_SIZE, 1, IWX_RBUF_SIZE,
2034 0, NULL, NULL, &ring->data_dmat);
2035
2036 for (i = 0; i < IWX_RX_MQ_RING_COUNT; i++) {
2037 struct iwx_rx_data *data = &ring->data[i];
2038
2039 memset(data, 0, sizeof(*data));
2040 err = bus_dmamap_create(ring->data_dmat, 0, &data->map);
2041 if (err) {
2042 device_printf(sc->sc_dev,
2043 "could not create RX buf DMA map\n");
2044 goto fail;
2045 }
2046
2047 err = iwx_rx_addbuf(sc, IWX_RBUF_SIZE, i);
2048 if (err)
2049 goto fail;
2050 }
2051 return 0;
2052
2053 fail: iwx_free_rx_ring(sc, ring);
2054 return err;
2055 }
2056
2057 static void
iwx_disable_rx_dma(struct iwx_softc * sc)2058 iwx_disable_rx_dma(struct iwx_softc *sc)
2059 {
2060 int ntries;
2061
2062 if (iwx_nic_lock(sc)) {
2063 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)
2064 iwx_write_umac_prph(sc, IWX_RFH_RXF_DMA_CFG_GEN3, 0);
2065 else
2066 iwx_write_prph(sc, IWX_RFH_RXF_DMA_CFG, 0);
2067 for (ntries = 0; ntries < 1000; ntries++) {
2068 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {
2069 if (iwx_read_umac_prph(sc,
2070 IWX_RFH_GEN_STATUS_GEN3) & IWX_RXF_DMA_IDLE)
2071 break;
2072 } else {
2073 if (iwx_read_prph(sc, IWX_RFH_GEN_STATUS) &
2074 IWX_RXF_DMA_IDLE)
2075 break;
2076 }
2077 DELAY(10);
2078 }
2079 iwx_nic_unlock(sc);
2080 }
2081 }
2082
2083 static void
iwx_reset_rx_ring(struct iwx_softc * sc,struct iwx_rx_ring * ring)2084 iwx_reset_rx_ring(struct iwx_softc *sc, struct iwx_rx_ring *ring)
2085 {
2086 ring->cur = 0;
2087 bus_dmamap_sync(sc->sc_dmat, ring->stat_dma.map,
2088 BUS_DMASYNC_PREWRITE);
2089 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {
2090 uint16_t *status = sc->rxq.stat_dma.vaddr;
2091 *status = 0;
2092 } else
2093 memset(ring->stat, 0, sizeof(*ring->stat));
2094 bus_dmamap_sync(sc->sc_dmat, ring->stat_dma.map,
2095 BUS_DMASYNC_POSTWRITE);
2096
2097 }
2098
2099 static void
iwx_free_rx_ring(struct iwx_softc * sc,struct iwx_rx_ring * ring)2100 iwx_free_rx_ring(struct iwx_softc *sc, struct iwx_rx_ring *ring)
2101 {
2102 int i;
2103
2104 iwx_dma_contig_free(&ring->free_desc_dma);
2105 iwx_dma_contig_free(&ring->stat_dma);
2106 iwx_dma_contig_free(&ring->used_desc_dma);
2107
2108 for (i = 0; i < IWX_RX_MQ_RING_COUNT; i++) {
2109 struct iwx_rx_data *data = &ring->data[i];
2110 if (data->m != NULL) {
2111 bus_dmamap_sync(ring->data_dmat, data->map,
2112 BUS_DMASYNC_POSTREAD);
2113 bus_dmamap_unload(ring->data_dmat, data->map);
2114 m_freem(data->m);
2115 data->m = NULL;
2116 }
2117 if (data->map != NULL) {
2118 bus_dmamap_destroy(ring->data_dmat, data->map);
2119 data->map = NULL;
2120 }
2121 }
2122 if (ring->data_dmat != NULL) {
2123 bus_dma_tag_destroy(ring->data_dmat);
2124 ring->data_dmat = NULL;
2125 }
2126 }
2127
2128 static int
iwx_alloc_tx_ring(struct iwx_softc * sc,struct iwx_tx_ring * ring,int qid)2129 iwx_alloc_tx_ring(struct iwx_softc *sc, struct iwx_tx_ring *ring, int qid)
2130 {
2131 bus_addr_t paddr;
2132 bus_size_t size;
2133 int i, err;
2134 size_t bc_tbl_size;
2135 bus_size_t bc_align;
2136 size_t mapsize;
2137
2138 ring->qid = qid;
2139 ring->queued = 0;
2140 ring->cur = 0;
2141 ring->cur_hw = 0;
2142 ring->tail = 0;
2143 ring->tail_hw = 0;
2144
2145 /* Allocate TX descriptors (256-byte aligned). */
2146 size = IWX_TX_RING_COUNT * sizeof(struct iwx_tfh_tfd);
2147 err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma, size, 256);
2148 if (err) {
2149 device_printf(sc->sc_dev,
2150 "could not allocate TX ring DMA memory\n");
2151 goto fail;
2152 }
2153 ring->desc = ring->desc_dma.vaddr;
2154
2155 /*
2156 * The hardware supports up to 512 Tx rings which is more
2157 * than we currently need.
2158 *
2159 * In DQA mode we use 1 command queue + 1 default queue for
2160 * management, control, and non-QoS data frames.
2161 * The command is queue sc->txq[0], our default queue is sc->txq[1].
2162 *
2163 * Tx aggregation requires additional queues, one queue per TID for
2164 * which aggregation is enabled. We map TID 0-7 to sc->txq[2:9].
2165 * Firmware may assign its own internal IDs for these queues
2166 * depending on which TID gets aggregation enabled first.
2167 * The driver maintains a table mapping driver-side queue IDs
2168 * to firmware-side queue IDs.
2169 */
2170
2171 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {
2172 bc_tbl_size = sizeof(struct iwx_gen3_bc_tbl_entry) *
2173 IWX_TFD_QUEUE_BC_SIZE_GEN3_AX210;
2174 bc_align = 128;
2175 } else {
2176 bc_tbl_size = sizeof(struct iwx_agn_scd_bc_tbl);
2177 bc_align = 64;
2178 }
2179 err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->bc_tbl, bc_tbl_size,
2180 bc_align);
2181 if (err) {
2182 device_printf(sc->sc_dev,
2183 "could not allocate byte count table DMA memory\n");
2184 goto fail;
2185 }
2186
2187 size = IWX_TX_RING_COUNT * sizeof(struct iwx_device_cmd);
2188 err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->cmd_dma, size,
2189 IWX_FIRST_TB_SIZE_ALIGN);
2190 if (err) {
2191 device_printf(sc->sc_dev,
2192 "could not allocate cmd DMA memory\n");
2193 goto fail;
2194 }
2195 ring->cmd = ring->cmd_dma.vaddr;
2196
2197 /* FW commands may require more mapped space than packets. */
2198 if (qid == IWX_DQA_CMD_QUEUE)
2199 mapsize = (sizeof(struct iwx_cmd_header) +
2200 IWX_MAX_CMD_PAYLOAD_SIZE);
2201 else
2202 mapsize = MCLBYTES;
2203 err = bus_dma_tag_create(sc->sc_dmat, 1, 0, BUS_SPACE_MAXADDR_32BIT,
2204 BUS_SPACE_MAXADDR, NULL, NULL, mapsize, IWX_TFH_NUM_TBS - 2,
2205 mapsize, 0, NULL, NULL, &ring->data_dmat);
2206
2207 paddr = ring->cmd_dma.paddr;
2208 for (i = 0; i < IWX_TX_RING_COUNT; i++) {
2209 struct iwx_tx_data *data = &ring->data[i];
2210
2211 data->cmd_paddr = paddr;
2212 paddr += sizeof(struct iwx_device_cmd);
2213
2214 err = bus_dmamap_create(ring->data_dmat, 0, &data->map);
2215 if (err) {
2216 device_printf(sc->sc_dev,
2217 "could not create TX buf DMA map\n");
2218 goto fail;
2219 }
2220 }
2221 KASSERT(paddr == ring->cmd_dma.paddr + size, ("bad paddr in txr alloc"));
2222 return 0;
2223
2224 fail:
2225 return err;
2226 }
2227
2228 static void
iwx_reset_tx_ring(struct iwx_softc * sc,struct iwx_tx_ring * ring)2229 iwx_reset_tx_ring(struct iwx_softc *sc, struct iwx_tx_ring *ring)
2230 {
2231 int i;
2232
2233 for (i = 0; i < IWX_TX_RING_COUNT; i++) {
2234 struct iwx_tx_data *data = &ring->data[i];
2235
2236 if (data->m != NULL) {
2237 bus_dmamap_sync(ring->data_dmat, data->map,
2238 BUS_DMASYNC_POSTWRITE);
2239 bus_dmamap_unload(ring->data_dmat, data->map);
2240 m_freem(data->m);
2241 data->m = NULL;
2242 }
2243 }
2244
2245 /* Clear byte count table. */
2246 memset(ring->bc_tbl.vaddr, 0, ring->bc_tbl.size);
2247
2248 /* Clear TX descriptors. */
2249 memset(ring->desc, 0, ring->desc_dma.size);
2250 bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
2251 BUS_DMASYNC_PREWRITE);
2252 sc->qfullmsk &= ~(1 << ring->qid);
2253 sc->qenablemsk &= ~(1 << ring->qid);
2254 for (i = 0; i < nitems(sc->aggqid); i++) {
2255 if (sc->aggqid[i] == ring->qid) {
2256 sc->aggqid[i] = 0;
2257 break;
2258 }
2259 }
2260 ring->queued = 0;
2261 ring->cur = 0;
2262 ring->cur_hw = 0;
2263 ring->tail = 0;
2264 ring->tail_hw = 0;
2265 ring->tid = 0;
2266 }
2267
2268 static void
iwx_free_tx_ring(struct iwx_softc * sc,struct iwx_tx_ring * ring)2269 iwx_free_tx_ring(struct iwx_softc *sc, struct iwx_tx_ring *ring)
2270 {
2271 int i;
2272
2273 iwx_dma_contig_free(&ring->desc_dma);
2274 iwx_dma_contig_free(&ring->cmd_dma);
2275 iwx_dma_contig_free(&ring->bc_tbl);
2276
2277 for (i = 0; i < IWX_TX_RING_COUNT; i++) {
2278 struct iwx_tx_data *data = &ring->data[i];
2279
2280 if (data->m != NULL) {
2281 bus_dmamap_sync(ring->data_dmat, data->map,
2282 BUS_DMASYNC_POSTWRITE);
2283 bus_dmamap_unload(ring->data_dmat, data->map);
2284 m_freem(data->m);
2285 data->m = NULL;
2286 }
2287 if (data->map != NULL) {
2288 bus_dmamap_destroy(ring->data_dmat, data->map);
2289 data->map = NULL;
2290 }
2291 }
2292 if (ring->data_dmat != NULL) {
2293 bus_dma_tag_destroy(ring->data_dmat);
2294 ring->data_dmat = NULL;
2295 }
2296 }
2297
2298 static void
iwx_enable_rfkill_int(struct iwx_softc * sc)2299 iwx_enable_rfkill_int(struct iwx_softc *sc)
2300 {
2301 if (!sc->sc_msix) {
2302 sc->sc_intmask = IWX_CSR_INT_BIT_RF_KILL;
2303 IWX_WRITE(sc, IWX_CSR_INT_MASK, sc->sc_intmask);
2304 } else {
2305 IWX_WRITE(sc, IWX_CSR_MSIX_FH_INT_MASK_AD,
2306 sc->sc_fh_init_mask);
2307 IWX_WRITE(sc, IWX_CSR_MSIX_HW_INT_MASK_AD,
2308 ~IWX_MSIX_HW_INT_CAUSES_REG_RF_KILL);
2309 sc->sc_hw_mask = IWX_MSIX_HW_INT_CAUSES_REG_RF_KILL;
2310 }
2311
2312 IWX_SETBITS(sc, IWX_CSR_GP_CNTRL,
2313 IWX_CSR_GP_CNTRL_REG_FLAG_RFKILL_WAKE_L1A_EN);
2314 }
2315
2316 static int
iwx_check_rfkill(struct iwx_softc * sc)2317 iwx_check_rfkill(struct iwx_softc *sc)
2318 {
2319 uint32_t v;
2320 int rv;
2321
2322 /*
2323 * "documentation" is not really helpful here:
2324 * 27: HW_RF_KILL_SW
2325 * Indicates state of (platform's) hardware RF-Kill switch
2326 *
2327 * But apparently when it's off, it's on ...
2328 */
2329 v = IWX_READ(sc, IWX_CSR_GP_CNTRL);
2330 rv = (v & IWX_CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) == 0;
2331 if (rv) {
2332 sc->sc_flags |= IWX_FLAG_RFKILL;
2333 } else {
2334 sc->sc_flags &= ~IWX_FLAG_RFKILL;
2335 }
2336
2337 return rv;
2338 }
2339
2340 static void
iwx_enable_interrupts(struct iwx_softc * sc)2341 iwx_enable_interrupts(struct iwx_softc *sc)
2342 {
2343 if (!sc->sc_msix) {
2344 sc->sc_intmask = IWX_CSR_INI_SET_MASK;
2345 IWX_WRITE(sc, IWX_CSR_INT_MASK, sc->sc_intmask);
2346 } else {
2347 /*
2348 * fh/hw_mask keeps all the unmasked causes.
2349 * Unlike msi, in msix cause is enabled when it is unset.
2350 */
2351 sc->sc_hw_mask = sc->sc_hw_init_mask;
2352 sc->sc_fh_mask = sc->sc_fh_init_mask;
2353 IWX_WRITE(sc, IWX_CSR_MSIX_FH_INT_MASK_AD,
2354 ~sc->sc_fh_mask);
2355 IWX_WRITE(sc, IWX_CSR_MSIX_HW_INT_MASK_AD,
2356 ~sc->sc_hw_mask);
2357 }
2358 }
2359
2360 static void
iwx_enable_fwload_interrupt(struct iwx_softc * sc)2361 iwx_enable_fwload_interrupt(struct iwx_softc *sc)
2362 {
2363 if (!sc->sc_msix) {
2364 sc->sc_intmask = IWX_CSR_INT_BIT_ALIVE | IWX_CSR_INT_BIT_FH_RX;
2365 IWX_WRITE(sc, IWX_CSR_INT_MASK, sc->sc_intmask);
2366 } else {
2367 IWX_WRITE(sc, IWX_CSR_MSIX_HW_INT_MASK_AD,
2368 ~IWX_MSIX_HW_INT_CAUSES_REG_ALIVE);
2369 sc->sc_hw_mask = IWX_MSIX_HW_INT_CAUSES_REG_ALIVE;
2370 /*
2371 * Leave all the FH causes enabled to get the ALIVE
2372 * notification.
2373 */
2374 IWX_WRITE(sc, IWX_CSR_MSIX_FH_INT_MASK_AD,
2375 ~sc->sc_fh_init_mask);
2376 sc->sc_fh_mask = sc->sc_fh_init_mask;
2377 }
2378 }
2379
2380 #if 0
2381 static void
2382 iwx_restore_interrupts(struct iwx_softc *sc)
2383 {
2384 IWX_WRITE(sc, IWX_CSR_INT_MASK, sc->sc_intmask);
2385 }
2386 #endif
2387
2388 static void
iwx_disable_interrupts(struct iwx_softc * sc)2389 iwx_disable_interrupts(struct iwx_softc *sc)
2390 {
2391 if (!sc->sc_msix) {
2392 IWX_WRITE(sc, IWX_CSR_INT_MASK, 0);
2393
2394 /* acknowledge all interrupts */
2395 IWX_WRITE(sc, IWX_CSR_INT, ~0);
2396 IWX_WRITE(sc, IWX_CSR_FH_INT_STATUS, ~0);
2397 } else {
2398 IWX_WRITE(sc, IWX_CSR_MSIX_FH_INT_MASK_AD,
2399 sc->sc_fh_init_mask);
2400 IWX_WRITE(sc, IWX_CSR_MSIX_HW_INT_MASK_AD,
2401 sc->sc_hw_init_mask);
2402 }
2403 }
2404
2405 static void
iwx_ict_reset(struct iwx_softc * sc)2406 iwx_ict_reset(struct iwx_softc *sc)
2407 {
2408 iwx_disable_interrupts(sc);
2409
2410 memset(sc->ict_dma.vaddr, 0, IWX_ICT_SIZE);
2411 sc->ict_cur = 0;
2412
2413 /* Set physical address of ICT (4KB aligned). */
2414 IWX_WRITE(sc, IWX_CSR_DRAM_INT_TBL_REG,
2415 IWX_CSR_DRAM_INT_TBL_ENABLE
2416 | IWX_CSR_DRAM_INIT_TBL_WRAP_CHECK
2417 | IWX_CSR_DRAM_INIT_TBL_WRITE_POINTER
2418 | sc->ict_dma.paddr >> IWX_ICT_PADDR_SHIFT);
2419
2420 /* Switch to ICT interrupt mode in driver. */
2421 sc->sc_flags |= IWX_FLAG_USE_ICT;
2422
2423 IWX_WRITE(sc, IWX_CSR_INT, ~0);
2424 iwx_enable_interrupts(sc);
2425 }
2426
2427 #define IWX_HW_READY_TIMEOUT 50
2428 static int
iwx_set_hw_ready(struct iwx_softc * sc)2429 iwx_set_hw_ready(struct iwx_softc *sc)
2430 {
2431 int ready;
2432
2433 IWX_SETBITS(sc, IWX_CSR_HW_IF_CONFIG_REG,
2434 IWX_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
2435
2436 ready = iwx_poll_bit(sc, IWX_CSR_HW_IF_CONFIG_REG,
2437 IWX_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
2438 IWX_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
2439 IWX_HW_READY_TIMEOUT);
2440 if (ready)
2441 IWX_SETBITS(sc, IWX_CSR_MBOX_SET_REG,
2442 IWX_CSR_MBOX_SET_REG_OS_ALIVE);
2443
2444 DPRINTF(("%s: ready=%d\n", __func__, ready));
2445 return ready;
2446 }
2447 #undef IWX_HW_READY_TIMEOUT
2448
2449 static int
iwx_prepare_card_hw(struct iwx_softc * sc)2450 iwx_prepare_card_hw(struct iwx_softc *sc)
2451 {
2452 int t = 0;
2453 int ntries;
2454
2455 if (iwx_set_hw_ready(sc))
2456 return 0;
2457
2458 IWX_SETBITS(sc, IWX_CSR_DBG_LINK_PWR_MGMT_REG,
2459 IWX_CSR_RESET_LINK_PWR_MGMT_DISABLED);
2460 DELAY(1000);
2461
2462 for (ntries = 0; ntries < 10; ntries++) {
2463 /* If HW is not ready, prepare the conditions to check again */
2464 IWX_SETBITS(sc, IWX_CSR_HW_IF_CONFIG_REG,
2465 IWX_CSR_HW_IF_CONFIG_REG_PREPARE);
2466
2467 do {
2468 if (iwx_set_hw_ready(sc))
2469 return 0;
2470 DELAY(200);
2471 t += 200;
2472 } while (t < 150000);
2473 DELAY(25000);
2474 }
2475
2476 return ETIMEDOUT;
2477 }
2478
2479 static int
iwx_force_power_gating(struct iwx_softc * sc)2480 iwx_force_power_gating(struct iwx_softc *sc)
2481 {
2482 int err;
2483
2484 err = iwx_set_bits_prph(sc, IWX_HPM_HIPM_GEN_CFG,
2485 IWX_HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
2486 if (err)
2487 return err;
2488 DELAY(20);
2489 err = iwx_set_bits_prph(sc, IWX_HPM_HIPM_GEN_CFG,
2490 IWX_HPM_HIPM_GEN_CFG_CR_PG_EN |
2491 IWX_HPM_HIPM_GEN_CFG_CR_SLP_EN);
2492 if (err)
2493 return err;
2494 DELAY(20);
2495 err = iwx_clear_bits_prph(sc, IWX_HPM_HIPM_GEN_CFG,
2496 IWX_HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
2497 return err;
2498 }
2499
2500 static void
iwx_apm_config(struct iwx_softc * sc)2501 iwx_apm_config(struct iwx_softc *sc)
2502 {
2503 uint16_t lctl, cap;
2504 int pcie_ptr;
2505 int error;
2506
2507 /*
2508 * L0S states have been found to be unstable with our devices
2509 * and in newer hardware they are not officially supported at
2510 * all, so we must always set the L0S_DISABLED bit.
2511 */
2512 IWX_SETBITS(sc, IWX_CSR_GIO_REG, IWX_CSR_GIO_REG_VAL_L0S_DISABLED);
2513
2514 error = pci_find_cap(sc->sc_dev, PCIY_EXPRESS, &pcie_ptr);
2515 if (error != 0) {
2516 printf("can't fill pcie_ptr\n");
2517 return;
2518 }
2519
2520 lctl = pci_read_config(sc->sc_dev, pcie_ptr + PCIER_LINK_CTL,
2521 sizeof(lctl));
2522 #define PCI_PCIE_LCSR_ASPM_L0S 0x00000001
2523 sc->sc_pm_support = !(lctl & PCI_PCIE_LCSR_ASPM_L0S);
2524 #define PCI_PCIE_DCSR2 0x28
2525 cap = pci_read_config(sc->sc_dev, pcie_ptr + PCI_PCIE_DCSR2,
2526 sizeof(lctl));
2527 #define PCI_PCIE_DCSR2_LTREN 0x00000400
2528 sc->sc_ltr_enabled = (cap & PCI_PCIE_DCSR2_LTREN) ? 1 : 0;
2529 #define PCI_PCIE_LCSR_ASPM_L1 0x00000002
2530 DPRINTF(("%s: L1 %sabled - LTR %sabled\n",
2531 DEVNAME(sc),
2532 (lctl & PCI_PCIE_LCSR_ASPM_L1) ? "En" : "Dis",
2533 sc->sc_ltr_enabled ? "En" : "Dis"));
2534 #undef PCI_PCIE_LCSR_ASPM_L0S
2535 #undef PCI_PCIE_DCSR2
2536 #undef PCI_PCIE_DCSR2_LTREN
2537 #undef PCI_PCIE_LCSR_ASPM_L1
2538 }
2539
2540 /*
2541 * Start up NIC's basic functionality after it has been reset
2542 * e.g. after platform boot or shutdown.
2543 * NOTE: This does not load uCode nor start the embedded processor
2544 */
2545 static int
iwx_apm_init(struct iwx_softc * sc)2546 iwx_apm_init(struct iwx_softc *sc)
2547 {
2548 int err = 0;
2549
2550 /*
2551 * Disable L0s without affecting L1;
2552 * don't wait for ICH L0s (ICH bug W/A)
2553 */
2554 IWX_SETBITS(sc, IWX_CSR_GIO_CHICKEN_BITS,
2555 IWX_CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
2556
2557 /* Set FH wait threshold to maximum (HW error during stress W/A) */
2558 IWX_SETBITS(sc, IWX_CSR_DBG_HPET_MEM_REG, IWX_CSR_DBG_HPET_MEM_REG_VAL);
2559
2560 /*
2561 * Enable HAP INTA (interrupt from management bus) to
2562 * wake device's PCI Express link L1a -> L0s
2563 */
2564 IWX_SETBITS(sc, IWX_CSR_HW_IF_CONFIG_REG,
2565 IWX_CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
2566
2567 iwx_apm_config(sc);
2568
2569 /*
2570 * Set "initialization complete" bit to move adapter from
2571 * D0U* --> D0A* (powered-up active) state.
2572 */
2573 IWX_SETBITS(sc, IWX_CSR_GP_CNTRL, IWX_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
2574
2575 /*
2576 * Wait for clock stabilization; once stabilized, access to
2577 * device-internal resources is supported, e.g. iwx_write_prph()
2578 * and accesses to uCode SRAM.
2579 */
2580 if (!iwx_poll_bit(sc, IWX_CSR_GP_CNTRL,
2581 IWX_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
2582 IWX_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000)) {
2583 printf("%s: timeout waiting for clock stabilization\n",
2584 DEVNAME(sc));
2585 err = ETIMEDOUT;
2586 goto out;
2587 }
2588 out:
2589 if (err)
2590 printf("%s: apm init error %d\n", DEVNAME(sc), err);
2591 return err;
2592 }
2593
2594 static void
iwx_apm_stop(struct iwx_softc * sc)2595 iwx_apm_stop(struct iwx_softc *sc)
2596 {
2597 IWX_SETBITS(sc, IWX_CSR_DBG_LINK_PWR_MGMT_REG,
2598 IWX_CSR_RESET_LINK_PWR_MGMT_DISABLED);
2599 IWX_SETBITS(sc, IWX_CSR_HW_IF_CONFIG_REG,
2600 IWX_CSR_HW_IF_CONFIG_REG_PREPARE |
2601 IWX_CSR_HW_IF_CONFIG_REG_ENABLE_PME);
2602 DELAY(1000);
2603 IWX_CLRBITS(sc, IWX_CSR_DBG_LINK_PWR_MGMT_REG,
2604 IWX_CSR_RESET_LINK_PWR_MGMT_DISABLED);
2605 DELAY(5000);
2606
2607 /* stop device's busmaster DMA activity */
2608 IWX_SETBITS(sc, IWX_CSR_RESET, IWX_CSR_RESET_REG_FLAG_STOP_MASTER);
2609
2610 if (!iwx_poll_bit(sc, IWX_CSR_RESET,
2611 IWX_CSR_RESET_REG_FLAG_MASTER_DISABLED,
2612 IWX_CSR_RESET_REG_FLAG_MASTER_DISABLED, 100))
2613 printf("%s: timeout waiting for bus master\n", DEVNAME(sc));
2614
2615 /*
2616 * Clear "initialization complete" bit to move adapter from
2617 * D0A* (powered-up Active) --> D0U* (Uninitialized) state.
2618 */
2619 IWX_CLRBITS(sc, IWX_CSR_GP_CNTRL,
2620 IWX_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
2621 }
2622
2623 static void
iwx_init_msix_hw(struct iwx_softc * sc)2624 iwx_init_msix_hw(struct iwx_softc *sc)
2625 {
2626 iwx_conf_msix_hw(sc, 0);
2627
2628 if (!sc->sc_msix)
2629 return;
2630
2631 sc->sc_fh_init_mask = ~IWX_READ(sc, IWX_CSR_MSIX_FH_INT_MASK_AD);
2632 sc->sc_fh_mask = sc->sc_fh_init_mask;
2633 sc->sc_hw_init_mask = ~IWX_READ(sc, IWX_CSR_MSIX_HW_INT_MASK_AD);
2634 sc->sc_hw_mask = sc->sc_hw_init_mask;
2635 }
2636
2637 static void
iwx_conf_msix_hw(struct iwx_softc * sc,int stopped)2638 iwx_conf_msix_hw(struct iwx_softc *sc, int stopped)
2639 {
2640 int vector = 0;
2641
2642 if (!sc->sc_msix) {
2643 /* Newer chips default to MSIX. */
2644 if (!stopped && iwx_nic_lock(sc)) {
2645 iwx_write_umac_prph(sc, IWX_UREG_CHICK,
2646 IWX_UREG_CHICK_MSI_ENABLE);
2647 iwx_nic_unlock(sc);
2648 }
2649 return;
2650 }
2651
2652 if (!stopped && iwx_nic_lock(sc)) {
2653 iwx_write_umac_prph(sc, IWX_UREG_CHICK,
2654 IWX_UREG_CHICK_MSIX_ENABLE);
2655 iwx_nic_unlock(sc);
2656 }
2657
2658 /* Disable all interrupts */
2659 IWX_WRITE(sc, IWX_CSR_MSIX_FH_INT_MASK_AD, ~0);
2660 IWX_WRITE(sc, IWX_CSR_MSIX_HW_INT_MASK_AD, ~0);
2661
2662 /* Map fallback-queue (command/mgmt) to a single vector */
2663 IWX_WRITE_1(sc, IWX_CSR_MSIX_RX_IVAR(0),
2664 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2665 /* Map RSS queue (data) to the same vector */
2666 IWX_WRITE_1(sc, IWX_CSR_MSIX_RX_IVAR(1),
2667 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2668
2669 /* Enable the RX queues cause interrupts */
2670 IWX_CLRBITS(sc, IWX_CSR_MSIX_FH_INT_MASK_AD,
2671 IWX_MSIX_FH_INT_CAUSES_Q0 | IWX_MSIX_FH_INT_CAUSES_Q1);
2672
2673 /* Map non-RX causes to the same vector */
2674 IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_D2S_CH0_NUM),
2675 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2676 IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_D2S_CH1_NUM),
2677 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2678 IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_S2D),
2679 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2680 IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_FH_ERR),
2681 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2682 IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_ALIVE),
2683 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2684 IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_WAKEUP),
2685 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2686 IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_RESET_DONE),
2687 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2688 IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_CT_KILL),
2689 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2690 IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_RF_KILL),
2691 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2692 IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_PERIODIC),
2693 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2694 IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_SW_ERR),
2695 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2696 IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_SCD),
2697 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2698 IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_FH_TX),
2699 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2700 IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_HW_ERR),
2701 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2702 IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_HAP),
2703 vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);
2704
2705 /* Enable non-RX causes interrupts */
2706 IWX_CLRBITS(sc, IWX_CSR_MSIX_FH_INT_MASK_AD,
2707 IWX_MSIX_FH_INT_CAUSES_D2S_CH0_NUM |
2708 IWX_MSIX_FH_INT_CAUSES_D2S_CH1_NUM |
2709 IWX_MSIX_FH_INT_CAUSES_S2D |
2710 IWX_MSIX_FH_INT_CAUSES_FH_ERR);
2711 IWX_CLRBITS(sc, IWX_CSR_MSIX_HW_INT_MASK_AD,
2712 IWX_MSIX_HW_INT_CAUSES_REG_ALIVE |
2713 IWX_MSIX_HW_INT_CAUSES_REG_WAKEUP |
2714 IWX_MSIX_HW_INT_CAUSES_REG_RESET_DONE |
2715 IWX_MSIX_HW_INT_CAUSES_REG_CT_KILL |
2716 IWX_MSIX_HW_INT_CAUSES_REG_RF_KILL |
2717 IWX_MSIX_HW_INT_CAUSES_REG_PERIODIC |
2718 IWX_MSIX_HW_INT_CAUSES_REG_SW_ERR |
2719 IWX_MSIX_HW_INT_CAUSES_REG_SCD |
2720 IWX_MSIX_HW_INT_CAUSES_REG_FH_TX |
2721 IWX_MSIX_HW_INT_CAUSES_REG_HW_ERR |
2722 IWX_MSIX_HW_INT_CAUSES_REG_HAP);
2723 }
2724
2725 static int
iwx_clear_persistence_bit(struct iwx_softc * sc)2726 iwx_clear_persistence_bit(struct iwx_softc *sc)
2727 {
2728 uint32_t hpm, wprot;
2729
2730 hpm = iwx_read_prph_unlocked(sc, IWX_HPM_DEBUG);
2731 if (hpm != 0xa5a5a5a0 && (hpm & IWX_PERSISTENCE_BIT)) {
2732 wprot = iwx_read_prph_unlocked(sc, IWX_PREG_PRPH_WPROT_22000);
2733 if (wprot & IWX_PREG_WFPM_ACCESS) {
2734 printf("%s: cannot clear persistence bit\n",
2735 DEVNAME(sc));
2736 return EPERM;
2737 }
2738 iwx_write_prph_unlocked(sc, IWX_HPM_DEBUG,
2739 hpm & ~IWX_PERSISTENCE_BIT);
2740 }
2741
2742 return 0;
2743 }
2744
2745 static int
iwx_start_hw(struct iwx_softc * sc)2746 iwx_start_hw(struct iwx_softc *sc)
2747 {
2748 int err;
2749
2750 err = iwx_prepare_card_hw(sc);
2751 if (err)
2752 return err;
2753
2754 if (sc->sc_device_family == IWX_DEVICE_FAMILY_22000) {
2755 err = iwx_clear_persistence_bit(sc);
2756 if (err)
2757 return err;
2758 }
2759
2760 /* Reset the entire device */
2761 IWX_SETBITS(sc, IWX_CSR_RESET, IWX_CSR_RESET_REG_FLAG_SW_RESET);
2762 DELAY(5000);
2763
2764 if (sc->sc_device_family == IWX_DEVICE_FAMILY_22000 &&
2765 sc->sc_integrated) {
2766 IWX_SETBITS(sc, IWX_CSR_GP_CNTRL,
2767 IWX_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
2768 DELAY(20);
2769 if (!iwx_poll_bit(sc, IWX_CSR_GP_CNTRL,
2770 IWX_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
2771 IWX_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000)) {
2772 printf("%s: timeout waiting for clock stabilization\n",
2773 DEVNAME(sc));
2774 return ETIMEDOUT;
2775 }
2776
2777 err = iwx_force_power_gating(sc);
2778 if (err)
2779 return err;
2780
2781 /* Reset the entire device */
2782 IWX_SETBITS(sc, IWX_CSR_RESET, IWX_CSR_RESET_REG_FLAG_SW_RESET);
2783 DELAY(5000);
2784 }
2785
2786 err = iwx_apm_init(sc);
2787 if (err)
2788 return err;
2789
2790 iwx_init_msix_hw(sc);
2791
2792 iwx_enable_rfkill_int(sc);
2793 iwx_check_rfkill(sc);
2794
2795 return 0;
2796 }
2797
2798 static void
iwx_stop_device(struct iwx_softc * sc)2799 iwx_stop_device(struct iwx_softc *sc)
2800 {
2801 int i;
2802
2803 iwx_disable_interrupts(sc);
2804 sc->sc_flags &= ~IWX_FLAG_USE_ICT;
2805
2806 iwx_disable_rx_dma(sc);
2807 iwx_reset_rx_ring(sc, &sc->rxq);
2808 for (i = 0; i < nitems(sc->txq); i++)
2809 iwx_reset_tx_ring(sc, &sc->txq[i]);
2810 #if 0
2811 /* XXX-THJ: Tidy up BA state on stop */
2812 for (i = 0; i < IEEE80211_NUM_TID; i++) {
2813 struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[i];
2814 if (ba->ba_state != IEEE80211_BA_AGREED)
2815 continue;
2816 ieee80211_delba_request(ic, ni, 0, 1, i);
2817 }
2818 #endif
2819 /* Make sure (redundant) we've released our request to stay awake */
2820 IWX_CLRBITS(sc, IWX_CSR_GP_CNTRL,
2821 IWX_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
2822 if (sc->sc_nic_locks > 0)
2823 printf("%s: %d active NIC locks forcefully cleared\n",
2824 DEVNAME(sc), sc->sc_nic_locks);
2825 sc->sc_nic_locks = 0;
2826
2827 /* Stop the device, and put it in low power state */
2828 iwx_apm_stop(sc);
2829
2830 /* Reset the on-board processor. */
2831 IWX_SETBITS(sc, IWX_CSR_RESET, IWX_CSR_RESET_REG_FLAG_SW_RESET);
2832 DELAY(5000);
2833
2834 /*
2835 * Upon stop, the IVAR table gets erased, so msi-x won't
2836 * work. This causes a bug in RF-KILL flows, since the interrupt
2837 * that enables radio won't fire on the correct irq, and the
2838 * driver won't be able to handle the interrupt.
2839 * Configure the IVAR table again after reset.
2840 */
2841 iwx_conf_msix_hw(sc, 1);
2842
2843 /*
2844 * Upon stop, the APM issues an interrupt if HW RF kill is set.
2845 * Clear the interrupt again.
2846 */
2847 iwx_disable_interrupts(sc);
2848
2849 /* Even though we stop the HW we still want the RF kill interrupt. */
2850 iwx_enable_rfkill_int(sc);
2851 iwx_check_rfkill(sc);
2852
2853 iwx_prepare_card_hw(sc);
2854
2855 iwx_ctxt_info_free_paging(sc);
2856 iwx_dma_contig_free(&sc->pnvm_dma);
2857 }
2858
2859 static void
iwx_nic_config(struct iwx_softc * sc)2860 iwx_nic_config(struct iwx_softc *sc)
2861 {
2862 uint8_t radio_cfg_type, radio_cfg_step, radio_cfg_dash;
2863 uint32_t mask, val, reg_val = 0;
2864
2865 radio_cfg_type = (sc->sc_fw_phy_config & IWX_FW_PHY_CFG_RADIO_TYPE) >>
2866 IWX_FW_PHY_CFG_RADIO_TYPE_POS;
2867 radio_cfg_step = (sc->sc_fw_phy_config & IWX_FW_PHY_CFG_RADIO_STEP) >>
2868 IWX_FW_PHY_CFG_RADIO_STEP_POS;
2869 radio_cfg_dash = (sc->sc_fw_phy_config & IWX_FW_PHY_CFG_RADIO_DASH) >>
2870 IWX_FW_PHY_CFG_RADIO_DASH_POS;
2871
2872 reg_val |= IWX_CSR_HW_REV_STEP(sc->sc_hw_rev) <<
2873 IWX_CSR_HW_IF_CONFIG_REG_POS_MAC_STEP;
2874 reg_val |= IWX_CSR_HW_REV_DASH(sc->sc_hw_rev) <<
2875 IWX_CSR_HW_IF_CONFIG_REG_POS_MAC_DASH;
2876
2877 /* radio configuration */
2878 reg_val |= radio_cfg_type << IWX_CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE;
2879 reg_val |= radio_cfg_step << IWX_CSR_HW_IF_CONFIG_REG_POS_PHY_STEP;
2880 reg_val |= radio_cfg_dash << IWX_CSR_HW_IF_CONFIG_REG_POS_PHY_DASH;
2881
2882 mask = IWX_CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
2883 IWX_CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP |
2884 IWX_CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP |
2885 IWX_CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH |
2886 IWX_CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE |
2887 IWX_CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
2888 IWX_CSR_HW_IF_CONFIG_REG_BIT_MAC_SI;
2889
2890 val = IWX_READ(sc, IWX_CSR_HW_IF_CONFIG_REG);
2891 val &= ~mask;
2892 val |= reg_val;
2893 IWX_WRITE(sc, IWX_CSR_HW_IF_CONFIG_REG, val);
2894 }
2895
2896 static int
iwx_nic_rx_init(struct iwx_softc * sc)2897 iwx_nic_rx_init(struct iwx_softc *sc)
2898 {
2899 IWX_WRITE_1(sc, IWX_CSR_INT_COALESCING, IWX_HOST_INT_TIMEOUT_DEF);
2900
2901 /*
2902 * We don't configure the RFH; the firmware will do that.
2903 * Rx descriptors are set when firmware sends an ALIVE interrupt.
2904 */
2905 return 0;
2906 }
2907
2908 static int
iwx_nic_init(struct iwx_softc * sc)2909 iwx_nic_init(struct iwx_softc *sc)
2910 {
2911 int err;
2912
2913 iwx_apm_init(sc);
2914 if (sc->sc_device_family < IWX_DEVICE_FAMILY_AX210)
2915 iwx_nic_config(sc);
2916
2917 err = iwx_nic_rx_init(sc);
2918 if (err)
2919 return err;
2920
2921 IWX_SETBITS(sc, IWX_CSR_MAC_SHADOW_REG_CTRL, 0x800fffff);
2922
2923 return 0;
2924 }
2925
2926 /* Map ieee80211_edca_ac categories to firmware Tx FIFO. */
2927 const uint8_t iwx_ac_to_tx_fifo[] = {
2928 IWX_GEN2_EDCA_TX_FIFO_BE,
2929 IWX_GEN2_EDCA_TX_FIFO_BK,
2930 IWX_GEN2_EDCA_TX_FIFO_VI,
2931 IWX_GEN2_EDCA_TX_FIFO_VO,
2932 };
2933
2934 static int
iwx_enable_txq(struct iwx_softc * sc,int sta_id,int qid,int tid,int num_slots)2935 iwx_enable_txq(struct iwx_softc *sc, int sta_id, int qid, int tid,
2936 int num_slots)
2937 {
2938 struct iwx_rx_packet *pkt;
2939 struct iwx_tx_queue_cfg_rsp *resp;
2940 struct iwx_tx_queue_cfg_cmd cmd_v0;
2941 struct iwx_scd_queue_cfg_cmd cmd_v3;
2942 struct iwx_host_cmd hcmd = {
2943 .flags = IWX_CMD_WANT_RESP,
2944 .resp_pkt_len = sizeof(*pkt) + sizeof(*resp),
2945 };
2946 struct iwx_tx_ring *ring = &sc->txq[qid];
2947 int err, fwqid, cmd_ver;
2948 uint32_t wr_idx;
2949 size_t resp_len;
2950
2951 DPRINTF(("%s: tid=%i\n", __func__, tid));
2952 DPRINTF(("%s: qid=%i\n", __func__, qid));
2953 iwx_reset_tx_ring(sc, ring);
2954
2955 cmd_ver = iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP,
2956 IWX_SCD_QUEUE_CONFIG_CMD);
2957 if (cmd_ver == 0 || cmd_ver == IWX_FW_CMD_VER_UNKNOWN) {
2958 memset(&cmd_v0, 0, sizeof(cmd_v0));
2959 cmd_v0.sta_id = sta_id;
2960 cmd_v0.tid = tid;
2961 cmd_v0.flags = htole16(IWX_TX_QUEUE_CFG_ENABLE_QUEUE);
2962 cmd_v0.cb_size = htole32(IWX_TFD_QUEUE_CB_SIZE(num_slots));
2963 cmd_v0.byte_cnt_addr = htole64(ring->bc_tbl.paddr);
2964 cmd_v0.tfdq_addr = htole64(ring->desc_dma.paddr);
2965 hcmd.id = IWX_SCD_QUEUE_CFG;
2966 hcmd.data[0] = &cmd_v0;
2967 hcmd.len[0] = sizeof(cmd_v0);
2968 } else if (cmd_ver == 3) {
2969 memset(&cmd_v3, 0, sizeof(cmd_v3));
2970 cmd_v3.operation = htole32(IWX_SCD_QUEUE_ADD);
2971 cmd_v3.u.add.tfdq_dram_addr = htole64(ring->desc_dma.paddr);
2972 cmd_v3.u.add.bc_dram_addr = htole64(ring->bc_tbl.paddr);
2973 cmd_v3.u.add.cb_size = htole32(IWX_TFD_QUEUE_CB_SIZE(num_slots));
2974 cmd_v3.u.add.flags = htole32(0);
2975 cmd_v3.u.add.sta_mask = htole32(1 << sta_id);
2976 cmd_v3.u.add.tid = tid;
2977 hcmd.id = IWX_WIDE_ID(IWX_DATA_PATH_GROUP,
2978 IWX_SCD_QUEUE_CONFIG_CMD);
2979 hcmd.data[0] = &cmd_v3;
2980 hcmd.len[0] = sizeof(cmd_v3);
2981 } else {
2982 printf("%s: unsupported SCD_QUEUE_CFG command version %d\n",
2983 DEVNAME(sc), cmd_ver);
2984 return ENOTSUP;
2985 }
2986
2987 err = iwx_send_cmd(sc, &hcmd);
2988 if (err)
2989 return err;
2990
2991 pkt = hcmd.resp_pkt;
2992 if (!pkt || (pkt->hdr.flags & IWX_CMD_FAILED_MSK)) {
2993 err = EIO;
2994 goto out;
2995 }
2996
2997 resp_len = iwx_rx_packet_payload_len(pkt);
2998 if (resp_len != sizeof(*resp)) {
2999 err = EIO;
3000 goto out;
3001 }
3002
3003 resp = (void *)pkt->data;
3004 fwqid = le16toh(resp->queue_number);
3005 wr_idx = le16toh(resp->write_pointer);
3006
3007 /* Unlike iwlwifi, we do not support dynamic queue ID assignment. */
3008 if (fwqid != qid) {
3009 DPRINTF(("%s: === fwqid != qid\n", __func__));
3010 err = EIO;
3011 goto out;
3012 }
3013
3014 if (wr_idx != ring->cur_hw) {
3015 DPRINTF(("%s: === (wr_idx != ring->cur_hw)\n", __func__));
3016 err = EIO;
3017 goto out;
3018 }
3019
3020 sc->qenablemsk |= (1 << qid);
3021 ring->tid = tid;
3022 out:
3023 iwx_free_resp(sc, &hcmd);
3024 return err;
3025 }
3026
3027 static int
iwx_disable_txq(struct iwx_softc * sc,int sta_id,int qid,uint8_t tid)3028 iwx_disable_txq(struct iwx_softc *sc, int sta_id, int qid, uint8_t tid)
3029 {
3030 struct iwx_rx_packet *pkt;
3031 struct iwx_tx_queue_cfg_rsp *resp;
3032 struct iwx_tx_queue_cfg_cmd cmd_v0;
3033 struct iwx_scd_queue_cfg_cmd cmd_v3;
3034 struct iwx_host_cmd hcmd = {
3035 .flags = IWX_CMD_WANT_RESP,
3036 .resp_pkt_len = sizeof(*pkt) + sizeof(*resp),
3037 };
3038 struct iwx_tx_ring *ring = &sc->txq[qid];
3039 int err, cmd_ver;
3040
3041 cmd_ver = iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP,
3042 IWX_SCD_QUEUE_CONFIG_CMD);
3043 if (cmd_ver == 0 || cmd_ver == IWX_FW_CMD_VER_UNKNOWN) {
3044 memset(&cmd_v0, 0, sizeof(cmd_v0));
3045 cmd_v0.sta_id = sta_id;
3046 cmd_v0.tid = tid;
3047 cmd_v0.flags = htole16(0); /* clear "queue enabled" flag */
3048 cmd_v0.cb_size = htole32(0);
3049 cmd_v0.byte_cnt_addr = htole64(0);
3050 cmd_v0.tfdq_addr = htole64(0);
3051 hcmd.id = IWX_SCD_QUEUE_CFG;
3052 hcmd.data[0] = &cmd_v0;
3053 hcmd.len[0] = sizeof(cmd_v0);
3054 } else if (cmd_ver == 3) {
3055 memset(&cmd_v3, 0, sizeof(cmd_v3));
3056 cmd_v3.operation = htole32(IWX_SCD_QUEUE_REMOVE);
3057 cmd_v3.u.remove.sta_mask = htole32(1 << sta_id);
3058 cmd_v3.u.remove.tid = tid;
3059 hcmd.id = IWX_WIDE_ID(IWX_DATA_PATH_GROUP,
3060 IWX_SCD_QUEUE_CONFIG_CMD);
3061 hcmd.data[0] = &cmd_v3;
3062 hcmd.len[0] = sizeof(cmd_v3);
3063 } else {
3064 printf("%s: unsupported SCD_QUEUE_CFG command version %d\n",
3065 DEVNAME(sc), cmd_ver);
3066 return ENOTSUP;
3067 }
3068
3069 err = iwx_send_cmd(sc, &hcmd);
3070 if (err)
3071 return err;
3072
3073 pkt = hcmd.resp_pkt;
3074 if (!pkt || (pkt->hdr.flags & IWX_CMD_FAILED_MSK)) {
3075 err = EIO;
3076 goto out;
3077 }
3078
3079 sc->qenablemsk &= ~(1 << qid);
3080 iwx_reset_tx_ring(sc, ring);
3081 out:
3082 iwx_free_resp(sc, &hcmd);
3083 return err;
3084 }
3085
3086 static void
iwx_post_alive(struct iwx_softc * sc)3087 iwx_post_alive(struct iwx_softc *sc)
3088 {
3089 int txcmd_ver;
3090
3091 iwx_ict_reset(sc);
3092
3093 txcmd_ver = iwx_lookup_notif_ver(sc, IWX_LONG_GROUP, IWX_TX_CMD) ;
3094 if (txcmd_ver != IWX_FW_CMD_VER_UNKNOWN && txcmd_ver > 6)
3095 sc->sc_rate_n_flags_version = 2;
3096 else
3097 sc->sc_rate_n_flags_version = 1;
3098
3099 txcmd_ver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_TX_CMD);
3100 }
3101
3102 static int
iwx_schedule_session_protection(struct iwx_softc * sc,struct iwx_node * in,uint32_t duration_tu)3103 iwx_schedule_session_protection(struct iwx_softc *sc, struct iwx_node *in,
3104 uint32_t duration_tu)
3105 {
3106
3107 struct iwx_session_prot_cmd cmd = {
3108 .id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(in->in_id,
3109 in->in_color)),
3110 .action = htole32(IWX_FW_CTXT_ACTION_ADD),
3111 .conf_id = htole32(IWX_SESSION_PROTECT_CONF_ASSOC),
3112 .duration_tu = htole32(duration_tu),
3113 };
3114 uint32_t cmd_id;
3115 int err;
3116
3117 cmd_id = iwx_cmd_id(IWX_SESSION_PROTECTION_CMD, IWX_MAC_CONF_GROUP, 0);
3118 err = iwx_send_cmd_pdu(sc, cmd_id, 0, sizeof(cmd), &cmd);
3119 if (!err)
3120 sc->sc_flags |= IWX_FLAG_TE_ACTIVE;
3121 return err;
3122 }
3123
3124 static void
iwx_unprotect_session(struct iwx_softc * sc,struct iwx_node * in)3125 iwx_unprotect_session(struct iwx_softc *sc, struct iwx_node *in)
3126 {
3127 struct iwx_session_prot_cmd cmd = {
3128 .id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(in->in_id,
3129 in->in_color)),
3130 .action = htole32(IWX_FW_CTXT_ACTION_REMOVE),
3131 .conf_id = htole32(IWX_SESSION_PROTECT_CONF_ASSOC),
3132 .duration_tu = 0,
3133 };
3134 uint32_t cmd_id;
3135
3136 /* Do nothing if the time event has already ended. */
3137 if ((sc->sc_flags & IWX_FLAG_TE_ACTIVE) == 0)
3138 return;
3139
3140 cmd_id = iwx_cmd_id(IWX_SESSION_PROTECTION_CMD, IWX_MAC_CONF_GROUP, 0);
3141 if (iwx_send_cmd_pdu(sc, cmd_id, 0, sizeof(cmd), &cmd) == 0)
3142 sc->sc_flags &= ~IWX_FLAG_TE_ACTIVE;
3143 }
3144
3145 /*
3146 * NVM read access and content parsing. We do not support
3147 * external NVM or writing NVM.
3148 */
3149
3150 static uint8_t
iwx_fw_valid_tx_ant(struct iwx_softc * sc)3151 iwx_fw_valid_tx_ant(struct iwx_softc *sc)
3152 {
3153 uint8_t tx_ant;
3154
3155 tx_ant = ((sc->sc_fw_phy_config & IWX_FW_PHY_CFG_TX_CHAIN)
3156 >> IWX_FW_PHY_CFG_TX_CHAIN_POS);
3157
3158 if (sc->sc_nvm.valid_tx_ant)
3159 tx_ant &= sc->sc_nvm.valid_tx_ant;
3160
3161 return tx_ant;
3162 }
3163
3164 static uint8_t
iwx_fw_valid_rx_ant(struct iwx_softc * sc)3165 iwx_fw_valid_rx_ant(struct iwx_softc *sc)
3166 {
3167 uint8_t rx_ant;
3168
3169 rx_ant = ((sc->sc_fw_phy_config & IWX_FW_PHY_CFG_RX_CHAIN)
3170 >> IWX_FW_PHY_CFG_RX_CHAIN_POS);
3171
3172 if (sc->sc_nvm.valid_rx_ant)
3173 rx_ant &= sc->sc_nvm.valid_rx_ant;
3174
3175 return rx_ant;
3176 }
3177
3178 static void
iwx_init_channel_map(struct ieee80211com * ic,int maxchans,int * nchans,struct ieee80211_channel chans[])3179 iwx_init_channel_map(struct ieee80211com *ic, int maxchans, int *nchans,
3180 struct ieee80211_channel chans[])
3181 {
3182 struct iwx_softc *sc = ic->ic_softc;
3183 struct iwx_nvm_data *data = &sc->sc_nvm;
3184 uint8_t bands[IEEE80211_MODE_BYTES];
3185 const uint8_t *nvm_channels;
3186 uint32_t ch_flags;
3187 int ch_idx, nchan;
3188
3189 if (sc->sc_uhb_supported) {
3190 nchan = nitems(iwx_nvm_channels_uhb);
3191 nvm_channels = iwx_nvm_channels_uhb;
3192 } else {
3193 nchan = nitems(iwx_nvm_channels_8000);
3194 nvm_channels = iwx_nvm_channels_8000;
3195 }
3196
3197 /* 2.4Ghz; 1-13: 11b/g channels. */
3198 if (!data->sku_cap_band_24GHz_enable)
3199 goto band_5;
3200
3201 memset(bands, 0, sizeof(bands));
3202 setbit(bands, IEEE80211_MODE_11B);
3203 setbit(bands, IEEE80211_MODE_11G);
3204 setbit(bands, IEEE80211_MODE_11NG);
3205 for (ch_idx = 0;
3206 ch_idx < IWX_NUM_2GHZ_CHANNELS && ch_idx < nchan;
3207 ch_idx++) {
3208
3209 uint32_t nflags = 0;
3210 int cflags = 0;
3211
3212 if (sc->sc_rsp_vers == IWX_FBSD_RSP_V4) {
3213 ch_flags = le32_to_cpup(
3214 sc->sc_rsp_info.rsp_v4.regulatory.channel_profile + ch_idx);
3215 } else {
3216 ch_flags = le16_to_cpup(
3217 sc->sc_rsp_info.rsp_v3.regulatory.channel_profile + ch_idx);
3218 }
3219 if ((ch_flags & IWX_NVM_CHANNEL_VALID) == 0)
3220 continue;
3221
3222 if ((ch_flags & IWX_NVM_CHANNEL_40MHZ) != 0)
3223 cflags |= NET80211_CBW_FLAG_HT40;
3224
3225 /* XXX-BZ nflags RADAR/DFS/INDOOR */
3226
3227 /* error = */ ieee80211_add_channel_cbw(chans, maxchans, nchans,
3228 nvm_channels[ch_idx],
3229 ieee80211_ieee2mhz(nvm_channels[ch_idx], IEEE80211_CHAN_B),
3230 /* max_power IWL_DEFAULT_MAX_TX_POWER */ 22,
3231 nflags, bands, cflags);
3232 }
3233
3234 band_5:
3235 /* 5Ghz */
3236 if (!data->sku_cap_band_52GHz_enable)
3237 goto band_6;
3238
3239
3240 memset(bands, 0, sizeof(bands));
3241 setbit(bands, IEEE80211_MODE_11A);
3242 setbit(bands, IEEE80211_MODE_11NA);
3243 setbit(bands, IEEE80211_MODE_VHT_5GHZ);
3244
3245 for (ch_idx = IWX_NUM_2GHZ_CHANNELS;
3246 ch_idx < (IWX_NUM_2GHZ_CHANNELS + IWX_NUM_5GHZ_CHANNELS) && ch_idx < nchan;
3247 ch_idx++) {
3248 uint32_t nflags = 0;
3249 int cflags = 0;
3250
3251 if (sc->sc_rsp_vers == IWX_FBSD_RSP_V4)
3252 ch_flags = le32_to_cpup(
3253 sc->sc_rsp_info.rsp_v4.regulatory.channel_profile + ch_idx);
3254 else
3255 ch_flags = le16_to_cpup(
3256 sc->sc_rsp_info.rsp_v3.regulatory.channel_profile + ch_idx);
3257
3258 if ((ch_flags & IWX_NVM_CHANNEL_VALID) == 0)
3259 continue;
3260
3261 if ((ch_flags & IWX_NVM_CHANNEL_40MHZ) != 0)
3262 cflags |= NET80211_CBW_FLAG_HT40;
3263 if ((ch_flags & IWX_NVM_CHANNEL_80MHZ) != 0)
3264 cflags |= NET80211_CBW_FLAG_VHT80;
3265 if ((ch_flags & IWX_NVM_CHANNEL_160MHZ) != 0)
3266 cflags |= NET80211_CBW_FLAG_VHT160;
3267
3268 /* XXX-BZ nflags RADAR/DFS/INDOOR */
3269
3270 /* error = */ ieee80211_add_channel_cbw(chans, maxchans, nchans,
3271 nvm_channels[ch_idx],
3272 ieee80211_ieee2mhz(nvm_channels[ch_idx], IEEE80211_CHAN_A),
3273 /* max_power IWL_DEFAULT_MAX_TX_POWER */ 22,
3274 nflags, bands, cflags);
3275 }
3276 band_6:
3277 /* 6GHz one day ... */
3278 return;
3279 }
3280
3281 static int
iwx_mimo_enabled(struct iwx_softc * sc)3282 iwx_mimo_enabled(struct iwx_softc *sc)
3283 {
3284
3285 return !sc->sc_nvm.sku_cap_mimo_disable;
3286 }
3287
3288 static void
iwx_init_reorder_buffer(struct iwx_reorder_buffer * reorder_buf,uint16_t ssn,uint16_t buf_size)3289 iwx_init_reorder_buffer(struct iwx_reorder_buffer *reorder_buf,
3290 uint16_t ssn, uint16_t buf_size)
3291 {
3292 reorder_buf->head_sn = ssn;
3293 reorder_buf->num_stored = 0;
3294 reorder_buf->buf_size = buf_size;
3295 reorder_buf->last_amsdu = 0;
3296 reorder_buf->last_sub_index = 0;
3297 reorder_buf->removed = 0;
3298 reorder_buf->valid = 0;
3299 reorder_buf->consec_oldsn_drops = 0;
3300 reorder_buf->consec_oldsn_ampdu_gp2 = 0;
3301 reorder_buf->consec_oldsn_prev_drop = 0;
3302 }
3303
3304 static void
iwx_clear_reorder_buffer(struct iwx_softc * sc,struct iwx_rxba_data * rxba)3305 iwx_clear_reorder_buffer(struct iwx_softc *sc, struct iwx_rxba_data *rxba)
3306 {
3307 struct iwx_reorder_buffer *reorder_buf = &rxba->reorder_buf;
3308
3309 reorder_buf->removed = 1;
3310 rxba->baid = IWX_RX_REORDER_DATA_INVALID_BAID;
3311 }
3312
3313 #define IWX_MAX_RX_BA_SESSIONS 16
3314
3315 static struct iwx_rxba_data *
iwx_find_rxba_data(struct iwx_softc * sc,uint8_t tid)3316 iwx_find_rxba_data(struct iwx_softc *sc, uint8_t tid)
3317 {
3318 int i;
3319
3320 for (i = 0; i < nitems(sc->sc_rxba_data); i++) {
3321 if (sc->sc_rxba_data[i].baid ==
3322 IWX_RX_REORDER_DATA_INVALID_BAID)
3323 continue;
3324 if (sc->sc_rxba_data[i].tid == tid)
3325 return &sc->sc_rxba_data[i];
3326 }
3327
3328 return NULL;
3329 }
3330
3331 static int
iwx_sta_rx_agg_baid_cfg_cmd(struct iwx_softc * sc,struct ieee80211_node * ni,uint8_t tid,uint16_t ssn,uint16_t winsize,int timeout_val,int start,uint8_t * baid)3332 iwx_sta_rx_agg_baid_cfg_cmd(struct iwx_softc *sc, struct ieee80211_node *ni,
3333 uint8_t tid, uint16_t ssn, uint16_t winsize, int timeout_val, int start,
3334 uint8_t *baid)
3335 {
3336 struct iwx_rx_baid_cfg_cmd cmd;
3337 uint32_t new_baid = 0;
3338 int err;
3339
3340 IWX_ASSERT_LOCKED(sc);
3341
3342 memset(&cmd, 0, sizeof(cmd));
3343
3344 if (start) {
3345 cmd.action = IWX_RX_BAID_ACTION_ADD;
3346 cmd.alloc.sta_id_mask = htole32(1 << IWX_STATION_ID);
3347 cmd.alloc.tid = tid;
3348 cmd.alloc.ssn = htole16(ssn);
3349 cmd.alloc.win_size = htole16(winsize);
3350 } else {
3351 struct iwx_rxba_data *rxba;
3352
3353 rxba = iwx_find_rxba_data(sc, tid);
3354 if (rxba == NULL)
3355 return ENOENT;
3356 *baid = rxba->baid;
3357
3358 cmd.action = IWX_RX_BAID_ACTION_REMOVE;
3359 if (iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP,
3360 IWX_RX_BAID_ALLOCATION_CONFIG_CMD) == 1) {
3361 cmd.remove_v1.baid = rxba->baid;
3362 } else {
3363 cmd.remove.sta_id_mask = htole32(1 << IWX_STATION_ID);
3364 cmd.remove.tid = tid;
3365 }
3366 }
3367
3368 err = iwx_send_cmd_pdu_status(sc, IWX_WIDE_ID(IWX_DATA_PATH_GROUP,
3369 IWX_RX_BAID_ALLOCATION_CONFIG_CMD), sizeof(cmd), &cmd, &new_baid);
3370 if (err)
3371 return err;
3372
3373 if (start) {
3374 if (new_baid >= nitems(sc->sc_rxba_data))
3375 return ERANGE;
3376 *baid = new_baid;
3377 }
3378
3379 return 0;
3380 }
3381
3382 static void
iwx_sta_rx_agg(struct iwx_softc * sc,struct ieee80211_node * ni,uint8_t tid,uint16_t ssn,uint16_t winsize,int timeout_val,int start)3383 iwx_sta_rx_agg(struct iwx_softc *sc, struct ieee80211_node *ni, uint8_t tid,
3384 uint16_t ssn, uint16_t winsize, int timeout_val, int start)
3385 {
3386 int err;
3387 struct iwx_rxba_data *rxba = NULL;
3388 uint8_t baid = 0;
3389
3390 if (start && sc->sc_rx_ba_sessions >= IWX_MAX_RX_BA_SESSIONS) {
3391 return;
3392 }
3393
3394 if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_BAID_ML_SUPPORT)) {
3395 err = iwx_sta_rx_agg_baid_cfg_cmd(sc, ni, tid, ssn, winsize,
3396 timeout_val, start, &baid);
3397 } else {
3398 panic("sta_rx_agg unsupported hw");
3399 }
3400 if (err) {
3401 DPRINTF(("%s: iwx_sta_rx_agg_sta err=%i\n", __func__, err));
3402 return;
3403 } else
3404 DPRINTF(("%s: iwx_sta_rx_agg_sta success\n", __func__));
3405
3406 rxba = &sc->sc_rxba_data[baid];
3407
3408 /* Deaggregation is done in hardware. */
3409 if (start) {
3410 if (rxba->baid != IWX_RX_REORDER_DATA_INVALID_BAID) {
3411 return;
3412 }
3413 rxba->sta_id = IWX_STATION_ID;
3414 rxba->tid = tid;
3415 rxba->baid = baid;
3416 rxba->timeout = timeout_val;
3417 getmicrouptime(&rxba->last_rx);
3418 iwx_init_reorder_buffer(&rxba->reorder_buf, ssn,
3419 winsize);
3420 if (timeout_val != 0) {
3421 DPRINTF(("%s: timeout_val != 0\n", __func__));
3422 return;
3423 }
3424 } else
3425 iwx_clear_reorder_buffer(sc, rxba);
3426
3427 if (start) {
3428 sc->sc_rx_ba_sessions++;
3429 } else if (sc->sc_rx_ba_sessions > 0)
3430 sc->sc_rx_ba_sessions--;
3431 }
3432
3433 /**
3434 * @brief Allocate an A-MPDU / aggregation session for the given node and TID.
3435 *
3436 * This allocates a TX queue specifically for that TID.
3437 *
3438 * Note that this routine currently doesn't return any status/errors,
3439 * so the caller can't know if the aggregation session was setup or not.
3440 */
3441 static void
iwx_sta_tx_agg_start(struct iwx_softc * sc,struct ieee80211_node * ni,uint8_t tid)3442 iwx_sta_tx_agg_start(struct iwx_softc *sc, struct ieee80211_node *ni,
3443 uint8_t tid)
3444 {
3445 int err, qid;
3446
3447 qid = sc->aggqid[tid];
3448 if (qid == 0) {
3449 /* Firmware should pick the next unused Tx queue. */
3450 qid = fls(sc->qenablemsk);
3451 }
3452
3453 DPRINTF(("%s: qid=%i\n", __func__, qid));
3454
3455 /*
3456 * Simply enable the queue.
3457 * Firmware handles Tx Ba session setup and teardown.
3458 */
3459 if ((sc->qenablemsk & (1 << qid)) == 0) {
3460 if (!iwx_nic_lock(sc)) {
3461 return;
3462 }
3463 err = iwx_enable_txq(sc, IWX_STATION_ID, qid, tid,
3464 IWX_TX_RING_COUNT);
3465 iwx_nic_unlock(sc);
3466 if (err) {
3467 printf("%s: could not enable Tx queue %d "
3468 "(error %d)\n", DEVNAME(sc), qid, err);
3469 return;
3470 }
3471 }
3472 ni->ni_tx_ampdu[tid].txa_flags = IEEE80211_AGGR_RUNNING;
3473 DPRINTF(("%s: will set sc->aggqid[%i]=%i\n", __func__, tid, qid));
3474 sc->aggqid[tid] = qid;
3475 }
3476
3477 static void
iwx_ba_rx_task(void * arg,int npending __unused)3478 iwx_ba_rx_task(void *arg, int npending __unused)
3479 {
3480 struct iwx_softc *sc = arg;
3481 struct ieee80211com *ic = &sc->sc_ic;
3482 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
3483 struct ieee80211_node *ni = vap->iv_bss;
3484 int tid;
3485
3486 IWX_LOCK(sc);
3487 for (tid = 0; tid < IWX_MAX_TID_COUNT; tid++) {
3488 if (sc->sc_flags & IWX_FLAG_SHUTDOWN)
3489 break;
3490 if (sc->ba_rx.start_tidmask & (1 << tid)) {
3491 struct iwx_rx_ba *ba = &sc->ni_rx_ba[tid];
3492 DPRINTF(("%s: ba->ba_flags=%x\n", __func__,
3493 ba->ba_flags));
3494 if (ba->ba_flags == IWX_BA_DONE) {
3495 DPRINTF(("%s: ampdu for tid %i already added\n",
3496 __func__, tid));
3497 break;
3498 }
3499
3500 DPRINTF(("%s: ampdu rx start for tid %i\n", __func__,
3501 tid));
3502 iwx_sta_rx_agg(sc, ni, tid, ba->ba_winstart,
3503 ba->ba_winsize, ba->ba_timeout_val, 1);
3504 sc->ba_rx.start_tidmask &= ~(1 << tid);
3505 ba->ba_flags = IWX_BA_DONE;
3506 } else if (sc->ba_rx.stop_tidmask & (1 << tid)) {
3507 iwx_sta_rx_agg(sc, ni, tid, 0, 0, 0, 0);
3508 sc->ba_rx.stop_tidmask &= ~(1 << tid);
3509 }
3510 }
3511 IWX_UNLOCK(sc);
3512 }
3513
3514 /**
3515 * @brief Task called to setup a deferred block-ack session.
3516 *
3517 * This sets up any/all pending blockack sessions as defined
3518 * in sc->ba_tx.start_tidmask.
3519 *
3520 * Note: the call to iwx_sta_tx_agg_start() isn't being error checked.
3521 */
3522 static void
iwx_ba_tx_task(void * arg,int npending __unused)3523 iwx_ba_tx_task(void *arg, int npending __unused)
3524 {
3525 struct iwx_softc *sc = arg;
3526 struct ieee80211com *ic = &sc->sc_ic;
3527 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
3528 struct ieee80211_node *ni = vap->iv_bss;
3529 uint32_t started_mask = 0;
3530 int tid;
3531
3532 IWX_LOCK(sc);
3533 for (tid = 0; tid < IWX_MAX_TID_COUNT; tid++) {
3534 const struct ieee80211_tx_ampdu *tap;
3535
3536 if (sc->sc_flags & IWX_FLAG_SHUTDOWN)
3537 break;
3538 tap = &ni->ni_tx_ampdu[tid];
3539 if (IEEE80211_AMPDU_RUNNING(tap))
3540 break;
3541 if (sc->ba_tx.start_tidmask & (1 << tid)) {
3542 IWX_DPRINTF(sc, IWX_DEBUG_AMPDU_MGMT,
3543 "%s: ampdu tx start for tid %i\n", __func__, tid);
3544 iwx_sta_tx_agg_start(sc, ni, tid);
3545 sc->ba_tx.start_tidmask &= ~(1 << tid);
3546 started_mask |= (1 << tid);
3547 }
3548 }
3549
3550 IWX_UNLOCK(sc);
3551
3552 /* Iterate over the sessions we started; mark them as active */
3553 for (tid = 0; tid < IWX_MAX_TID_COUNT; tid++) {
3554 if (started_mask & (1 << tid)) {
3555 IWX_DPRINTF(sc, IWX_DEBUG_AMPDU_MGMT,
3556 "%s: informing net80211 to start ampdu on tid %i\n",
3557 __func__, tid);
3558 ieee80211_ampdu_tx_request_active_ext(ni, tid, 1);
3559 }
3560 }
3561 }
3562
3563 static void
iwx_set_mac_addr_from_csr(struct iwx_softc * sc,struct iwx_nvm_data * data)3564 iwx_set_mac_addr_from_csr(struct iwx_softc *sc, struct iwx_nvm_data *data)
3565 {
3566 uint32_t mac_addr0, mac_addr1;
3567
3568 memset(data->hw_addr, 0, sizeof(data->hw_addr));
3569
3570 if (!iwx_nic_lock(sc))
3571 return;
3572
3573 mac_addr0 = htole32(IWX_READ(sc, IWX_CSR_MAC_ADDR0_STRAP(sc)));
3574 mac_addr1 = htole32(IWX_READ(sc, IWX_CSR_MAC_ADDR1_STRAP(sc)));
3575
3576 iwx_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);
3577
3578 /* If OEM fused a valid address, use it instead of the one in OTP. */
3579 if (iwx_is_valid_mac_addr(data->hw_addr)) {
3580 iwx_nic_unlock(sc);
3581 return;
3582 }
3583
3584 mac_addr0 = htole32(IWX_READ(sc, IWX_CSR_MAC_ADDR0_OTP(sc)));
3585 mac_addr1 = htole32(IWX_READ(sc, IWX_CSR_MAC_ADDR1_OTP(sc)));
3586
3587 iwx_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);
3588
3589 iwx_nic_unlock(sc);
3590 }
3591
3592 static int
iwx_is_valid_mac_addr(const uint8_t * addr)3593 iwx_is_valid_mac_addr(const uint8_t *addr)
3594 {
3595 static const uint8_t reserved_mac[] = {
3596 0x02, 0xcc, 0xaa, 0xff, 0xee, 0x00
3597 };
3598
3599 return (memcmp(reserved_mac, addr, ETHER_ADDR_LEN) != 0 &&
3600 memcmp(etherbroadcastaddr, addr, sizeof(etherbroadcastaddr)) != 0 &&
3601 memcmp(etheranyaddr, addr, sizeof(etheranyaddr)) != 0 &&
3602 !ETHER_IS_MULTICAST(addr));
3603 }
3604
3605 static void
iwx_flip_hw_address(uint32_t mac_addr0,uint32_t mac_addr1,uint8_t * dest)3606 iwx_flip_hw_address(uint32_t mac_addr0, uint32_t mac_addr1, uint8_t *dest)
3607 {
3608 const uint8_t *hw_addr;
3609
3610 hw_addr = (const uint8_t *)&mac_addr0;
3611 dest[0] = hw_addr[3];
3612 dest[1] = hw_addr[2];
3613 dest[2] = hw_addr[1];
3614 dest[3] = hw_addr[0];
3615
3616 hw_addr = (const uint8_t *)&mac_addr1;
3617 dest[4] = hw_addr[1];
3618 dest[5] = hw_addr[0];
3619 }
3620
3621 static int
iwx_nvm_get(struct iwx_softc * sc)3622 iwx_nvm_get(struct iwx_softc *sc)
3623 {
3624 struct iwx_nvm_get_info cmd = {};
3625 struct iwx_nvm_data *nvm = &sc->sc_nvm;
3626 struct iwx_host_cmd hcmd = {
3627 .flags = IWX_CMD_WANT_RESP | IWX_CMD_SEND_IN_RFKILL,
3628 .data = { &cmd, },
3629 .len = { sizeof(cmd) },
3630 .id = IWX_WIDE_ID(IWX_REGULATORY_AND_NVM_GROUP,
3631 IWX_NVM_GET_INFO)
3632 };
3633 int err = 0;
3634 uint32_t mac_flags;
3635 /*
3636 * All the values in iwx_nvm_get_info_rsp v4 are the same as
3637 * in v3, except for the channel profile part of the
3638 * regulatory. So we can just access the new struct, with the
3639 * exception of the latter.
3640 */
3641 struct iwx_nvm_get_info_rsp *rsp;
3642 struct iwx_nvm_get_info_rsp_v3 *rsp_v3;
3643 int v4 = isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_REGULATORY_NVM_INFO);
3644 size_t resp_len = v4 ? sizeof(*rsp) : sizeof(*rsp_v3);
3645
3646 hcmd.resp_pkt_len = sizeof(struct iwx_rx_packet) + resp_len;
3647 err = iwx_send_cmd(sc, &hcmd);
3648 if (err) {
3649 printf("%s: failed to send cmd (error %d)", __func__, err);
3650 return err;
3651 }
3652
3653 if (iwx_rx_packet_payload_len(hcmd.resp_pkt) != resp_len) {
3654 printf("%s: iwx_rx_packet_payload_len=%d\n", __func__,
3655 iwx_rx_packet_payload_len(hcmd.resp_pkt));
3656 printf("%s: resp_len=%zu\n", __func__, resp_len);
3657 err = EIO;
3658 goto out;
3659 }
3660
3661 memset(nvm, 0, sizeof(*nvm));
3662
3663 iwx_set_mac_addr_from_csr(sc, nvm);
3664 if (!iwx_is_valid_mac_addr(nvm->hw_addr)) {
3665 printf("%s: no valid mac address was found\n", DEVNAME(sc));
3666 err = EINVAL;
3667 goto out;
3668 }
3669
3670 rsp = (void *)hcmd.resp_pkt->data;
3671
3672 /* Initialize general data */
3673 nvm->nvm_version = le16toh(rsp->general.nvm_version);
3674 nvm->n_hw_addrs = rsp->general.n_hw_addrs;
3675
3676 /* Initialize MAC sku data */
3677 mac_flags = le32toh(rsp->mac_sku.mac_sku_flags);
3678 nvm->sku_cap_11ac_enable =
3679 !!(mac_flags & IWX_NVM_MAC_SKU_FLAGS_802_11AC_ENABLED);
3680 nvm->sku_cap_11n_enable =
3681 !!(mac_flags & IWX_NVM_MAC_SKU_FLAGS_802_11N_ENABLED);
3682 nvm->sku_cap_11ax_enable =
3683 !!(mac_flags & IWX_NVM_MAC_SKU_FLAGS_802_11AX_ENABLED);
3684 nvm->sku_cap_band_24GHz_enable =
3685 !!(mac_flags & IWX_NVM_MAC_SKU_FLAGS_BAND_2_4_ENABLED);
3686 nvm->sku_cap_band_52GHz_enable =
3687 !!(mac_flags & IWX_NVM_MAC_SKU_FLAGS_BAND_5_2_ENABLED);
3688 nvm->sku_cap_mimo_disable =
3689 !!(mac_flags & IWX_NVM_MAC_SKU_FLAGS_MIMO_DISABLED);
3690
3691 /* Initialize PHY sku data */
3692 nvm->valid_tx_ant = (uint8_t)le32toh(rsp->phy_sku.tx_chains);
3693 nvm->valid_rx_ant = (uint8_t)le32toh(rsp->phy_sku.rx_chains);
3694
3695 if (le32toh(rsp->regulatory.lar_enabled) &&
3696 isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_LAR_SUPPORT)) {
3697 nvm->lar_enabled = 1;
3698 }
3699
3700 memcpy(&sc->sc_rsp_info, rsp, resp_len);
3701 if (v4) {
3702 sc->sc_rsp_vers = IWX_FBSD_RSP_V4;
3703 } else {
3704 sc->sc_rsp_vers = IWX_FBSD_RSP_V3;
3705 }
3706 out:
3707 iwx_free_resp(sc, &hcmd);
3708 return err;
3709 }
3710
3711 static int
iwx_load_firmware(struct iwx_softc * sc)3712 iwx_load_firmware(struct iwx_softc *sc)
3713 {
3714 struct iwx_fw_sects *fws;
3715 int err;
3716
3717 IWX_ASSERT_LOCKED(sc)
3718
3719 sc->sc_uc.uc_intr = 0;
3720 sc->sc_uc.uc_ok = 0;
3721
3722 fws = &sc->sc_fw.fw_sects[IWX_UCODE_TYPE_REGULAR];
3723 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)
3724 err = iwx_ctxt_info_gen3_init(sc, fws);
3725 else
3726 err = iwx_ctxt_info_init(sc, fws);
3727 if (err) {
3728 printf("%s: could not init context info\n", DEVNAME(sc));
3729 return err;
3730 }
3731
3732 /* wait for the firmware to load */
3733 err = msleep(&sc->sc_uc, &sc->sc_mtx, 0, "iwxuc", hz);
3734 if (err || !sc->sc_uc.uc_ok) {
3735 printf("%s: firmware upload failed, %d\n", DEVNAME(sc), err);
3736 iwx_ctxt_info_free_paging(sc);
3737 }
3738
3739 iwx_dma_contig_free(&sc->iml_dma);
3740 iwx_ctxt_info_free_fw_img(sc);
3741
3742 if (!sc->sc_uc.uc_ok)
3743 return EINVAL;
3744
3745 return err;
3746 }
3747
3748 static int
iwx_start_fw(struct iwx_softc * sc)3749 iwx_start_fw(struct iwx_softc *sc)
3750 {
3751 int err;
3752
3753 IWX_WRITE(sc, IWX_CSR_INT, ~0);
3754
3755 iwx_disable_interrupts(sc);
3756
3757 /* make sure rfkill handshake bits are cleared */
3758 IWX_WRITE(sc, IWX_CSR_UCODE_DRV_GP1_CLR, IWX_CSR_UCODE_SW_BIT_RFKILL);
3759 IWX_WRITE(sc, IWX_CSR_UCODE_DRV_GP1_CLR,
3760 IWX_CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
3761
3762 /* clear (again), then enable firmware load interrupt */
3763 IWX_WRITE(sc, IWX_CSR_INT, ~0);
3764
3765 err = iwx_nic_init(sc);
3766 if (err) {
3767 printf("%s: unable to init nic\n", DEVNAME(sc));
3768 return err;
3769 }
3770
3771 iwx_enable_fwload_interrupt(sc);
3772
3773 return iwx_load_firmware(sc);
3774 }
3775
3776 static int
iwx_pnvm_handle_section(struct iwx_softc * sc,const uint8_t * data,size_t len)3777 iwx_pnvm_handle_section(struct iwx_softc *sc, const uint8_t *data,
3778 size_t len)
3779 {
3780 const struct iwx_ucode_tlv *tlv;
3781 uint32_t sha1 = 0;
3782 uint16_t mac_type = 0, rf_id = 0;
3783 uint8_t *pnvm_data = NULL, *tmp;
3784 int hw_match = 0;
3785 uint32_t size = 0;
3786 int err;
3787
3788 while (len >= sizeof(*tlv)) {
3789 uint32_t tlv_len, tlv_type;
3790
3791 len -= sizeof(*tlv);
3792 tlv = (const void *)data;
3793
3794 tlv_len = le32toh(tlv->length);
3795 tlv_type = le32toh(tlv->type);
3796
3797 if (len < tlv_len) {
3798 printf("%s: invalid TLV len: %zd/%u\n",
3799 DEVNAME(sc), len, tlv_len);
3800 err = EINVAL;
3801 goto out;
3802 }
3803
3804 data += sizeof(*tlv);
3805
3806 switch (tlv_type) {
3807 case IWX_UCODE_TLV_PNVM_VERSION:
3808 if (tlv_len < sizeof(uint32_t))
3809 break;
3810
3811 sha1 = le32_to_cpup((const uint32_t *)data);
3812 break;
3813 case IWX_UCODE_TLV_HW_TYPE:
3814 if (tlv_len < 2 * sizeof(uint16_t))
3815 break;
3816
3817 if (hw_match)
3818 break;
3819
3820 mac_type = le16_to_cpup((const uint16_t *)data);
3821 rf_id = le16_to_cpup((const uint16_t *)(data +
3822 sizeof(uint16_t)));
3823
3824 if (mac_type == IWX_CSR_HW_REV_TYPE(sc->sc_hw_rev) &&
3825 rf_id == IWX_CSR_HW_RFID_TYPE(sc->sc_hw_rf_id))
3826 hw_match = 1;
3827 break;
3828 case IWX_UCODE_TLV_SEC_RT: {
3829 const struct iwx_pnvm_section *section;
3830 uint32_t data_len;
3831
3832 section = (const void *)data;
3833 data_len = tlv_len - sizeof(*section);
3834
3835 /* TODO: remove, this is a deprecated separator */
3836 if (le32_to_cpup((const uint32_t *)data) == 0xddddeeee)
3837 break;
3838
3839 tmp = malloc(size + data_len, M_DEVBUF,
3840 M_WAITOK | M_ZERO);
3841 if (tmp == NULL) {
3842 err = ENOMEM;
3843 goto out;
3844 }
3845 // XXX:misha pnvm_data is NULL and size is 0 at first pass
3846 memcpy(tmp, pnvm_data, size);
3847 memcpy(tmp + size, section->data, data_len);
3848 free(pnvm_data, M_DEVBUF);
3849 pnvm_data = tmp;
3850 size += data_len;
3851 break;
3852 }
3853 case IWX_UCODE_TLV_PNVM_SKU:
3854 /* New PNVM section started, stop parsing. */
3855 goto done;
3856 default:
3857 break;
3858 }
3859
3860 if (roundup(tlv_len, 4) > len)
3861 break;
3862 len -= roundup(tlv_len, 4);
3863 data += roundup(tlv_len, 4);
3864 }
3865 done:
3866 if (!hw_match || size == 0) {
3867 err = ENOENT;
3868 goto out;
3869 }
3870
3871 err = iwx_dma_contig_alloc(sc->sc_dmat, &sc->pnvm_dma, size, 1);
3872 if (err) {
3873 printf("%s: could not allocate DMA memory for PNVM\n",
3874 DEVNAME(sc));
3875 err = ENOMEM;
3876 goto out;
3877 }
3878 memcpy(sc->pnvm_dma.vaddr, pnvm_data, size);
3879 iwx_ctxt_info_gen3_set_pnvm(sc);
3880 sc->sc_pnvm_ver = sha1;
3881 out:
3882 free(pnvm_data, M_DEVBUF);
3883 return err;
3884 }
3885
3886 static int
iwx_pnvm_parse(struct iwx_softc * sc,const uint8_t * data,size_t len)3887 iwx_pnvm_parse(struct iwx_softc *sc, const uint8_t *data, size_t len)
3888 {
3889 const struct iwx_ucode_tlv *tlv;
3890
3891 while (len >= sizeof(*tlv)) {
3892 uint32_t tlv_len, tlv_type;
3893
3894 len -= sizeof(*tlv);
3895 tlv = (const void *)data;
3896
3897 tlv_len = le32toh(tlv->length);
3898 tlv_type = le32toh(tlv->type);
3899
3900 if (len < tlv_len || roundup(tlv_len, 4) > len)
3901 return EINVAL;
3902
3903 if (tlv_type == IWX_UCODE_TLV_PNVM_SKU) {
3904 const struct iwx_sku_id *sku_id =
3905 (const void *)(data + sizeof(*tlv));
3906
3907 data += sizeof(*tlv) + roundup(tlv_len, 4);
3908 len -= roundup(tlv_len, 4);
3909
3910 if (sc->sc_sku_id[0] == le32toh(sku_id->data[0]) &&
3911 sc->sc_sku_id[1] == le32toh(sku_id->data[1]) &&
3912 sc->sc_sku_id[2] == le32toh(sku_id->data[2]) &&
3913 iwx_pnvm_handle_section(sc, data, len) == 0)
3914 return 0;
3915 } else {
3916 data += sizeof(*tlv) + roundup(tlv_len, 4);
3917 len -= roundup(tlv_len, 4);
3918 }
3919 }
3920
3921 return ENOENT;
3922 }
3923
3924 /* Make AX210 firmware loading context point at PNVM image in DMA memory. */
3925 static void
iwx_ctxt_info_gen3_set_pnvm(struct iwx_softc * sc)3926 iwx_ctxt_info_gen3_set_pnvm(struct iwx_softc *sc)
3927 {
3928 struct iwx_prph_scratch *prph_scratch;
3929 struct iwx_prph_scratch_ctrl_cfg *prph_sc_ctrl;
3930
3931 prph_scratch = sc->prph_scratch_dma.vaddr;
3932 prph_sc_ctrl = &prph_scratch->ctrl_cfg;
3933
3934 prph_sc_ctrl->pnvm_cfg.pnvm_base_addr = htole64(sc->pnvm_dma.paddr);
3935 prph_sc_ctrl->pnvm_cfg.pnvm_size = htole32(sc->pnvm_dma.size);
3936
3937 bus_dmamap_sync(sc->sc_dmat, sc->pnvm_dma.map, BUS_DMASYNC_PREWRITE);
3938 }
3939
3940 /*
3941 * Load platform-NVM (non-volatile-memory) data from the filesystem.
3942 * This data apparently contains regulatory information and affects device
3943 * channel configuration.
3944 * The SKU of AX210 devices tells us which PNVM file section is needed.
3945 * Pre-AX210 devices store NVM data onboard.
3946 */
3947 static int
iwx_load_pnvm(struct iwx_softc * sc)3948 iwx_load_pnvm(struct iwx_softc *sc)
3949 {
3950 const int wait_flags = IWX_PNVM_COMPLETE;
3951 int err = 0;
3952 const struct firmware *pnvm;
3953
3954 if (sc->sc_sku_id[0] == 0 &&
3955 sc->sc_sku_id[1] == 0 &&
3956 sc->sc_sku_id[2] == 0)
3957 return 0;
3958
3959 if (sc->sc_pnvm_name) {
3960 if (sc->pnvm_dma.vaddr == NULL) {
3961 IWX_UNLOCK(sc);
3962 pnvm = firmware_get(sc->sc_pnvm_name);
3963 if (pnvm == NULL) {
3964 printf("%s: could not read %s (error %d)\n",
3965 DEVNAME(sc), sc->sc_pnvm_name, err);
3966 IWX_LOCK(sc);
3967 return EINVAL;
3968 }
3969 sc->sc_pnvm = pnvm;
3970
3971 err = iwx_pnvm_parse(sc, pnvm->data, pnvm->datasize);
3972 IWX_LOCK(sc);
3973 if (err && err != ENOENT) {
3974 return EINVAL;
3975 }
3976 } else
3977 iwx_ctxt_info_gen3_set_pnvm(sc);
3978 }
3979
3980 if (!iwx_nic_lock(sc)) {
3981 return EBUSY;
3982 }
3983
3984 /*
3985 * If we don't have a platform NVM file simply ask firmware
3986 * to proceed without it.
3987 */
3988
3989 iwx_write_umac_prph(sc, IWX_UREG_DOORBELL_TO_ISR6,
3990 IWX_UREG_DOORBELL_TO_ISR6_PNVM);
3991
3992 /* Wait for the pnvm complete notification from firmware. */
3993 while ((sc->sc_init_complete & wait_flags) != wait_flags) {
3994 err = msleep(&sc->sc_init_complete, &sc->sc_mtx, 0, "iwxinit", 2 * hz);
3995 if (err)
3996 break;
3997 }
3998
3999 iwx_nic_unlock(sc);
4000
4001 return err;
4002 }
4003
4004 static int
iwx_send_tx_ant_cfg(struct iwx_softc * sc,uint8_t valid_tx_ant)4005 iwx_send_tx_ant_cfg(struct iwx_softc *sc, uint8_t valid_tx_ant)
4006 {
4007 struct iwx_tx_ant_cfg_cmd tx_ant_cmd = {
4008 .valid = htole32(valid_tx_ant),
4009 };
4010
4011 return iwx_send_cmd_pdu(sc, IWX_TX_ANT_CONFIGURATION_CMD,
4012 0, sizeof(tx_ant_cmd), &tx_ant_cmd);
4013 }
4014
4015 static int
iwx_send_phy_cfg_cmd(struct iwx_softc * sc)4016 iwx_send_phy_cfg_cmd(struct iwx_softc *sc)
4017 {
4018 struct iwx_phy_cfg_cmd phy_cfg_cmd;
4019
4020 phy_cfg_cmd.phy_cfg = htole32(sc->sc_fw_phy_config);
4021 phy_cfg_cmd.calib_control.event_trigger =
4022 sc->sc_default_calib[IWX_UCODE_TYPE_REGULAR].event_trigger;
4023 phy_cfg_cmd.calib_control.flow_trigger =
4024 sc->sc_default_calib[IWX_UCODE_TYPE_REGULAR].flow_trigger;
4025
4026 return iwx_send_cmd_pdu(sc, IWX_PHY_CONFIGURATION_CMD, 0,
4027 sizeof(phy_cfg_cmd), &phy_cfg_cmd);
4028 }
4029
4030 static int
iwx_send_dqa_cmd(struct iwx_softc * sc)4031 iwx_send_dqa_cmd(struct iwx_softc *sc)
4032 {
4033 struct iwx_dqa_enable_cmd dqa_cmd = {
4034 .cmd_queue = htole32(IWX_DQA_CMD_QUEUE),
4035 };
4036 uint32_t cmd_id;
4037
4038 cmd_id = iwx_cmd_id(IWX_DQA_ENABLE_CMD, IWX_DATA_PATH_GROUP, 0);
4039 return iwx_send_cmd_pdu(sc, cmd_id, 0, sizeof(dqa_cmd), &dqa_cmd);
4040 }
4041
4042 static int
iwx_load_ucode_wait_alive(struct iwx_softc * sc)4043 iwx_load_ucode_wait_alive(struct iwx_softc *sc)
4044 {
4045 int err;
4046
4047 IWX_UNLOCK(sc);
4048 err = iwx_read_firmware(sc);
4049 IWX_LOCK(sc);
4050 if (err)
4051 return err;
4052
4053 err = iwx_start_fw(sc);
4054 if (err)
4055 return err;
4056
4057 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {
4058 err = iwx_load_pnvm(sc);
4059 if (err)
4060 return err;
4061 }
4062
4063 iwx_post_alive(sc);
4064
4065 return 0;
4066 }
4067
4068 static int
iwx_run_init_mvm_ucode(struct iwx_softc * sc,int readnvm)4069 iwx_run_init_mvm_ucode(struct iwx_softc *sc, int readnvm)
4070 {
4071 const int wait_flags = IWX_INIT_COMPLETE;
4072 struct iwx_nvm_access_complete_cmd nvm_complete = {};
4073 struct iwx_init_extended_cfg_cmd init_cfg = {
4074 .init_flags = htole32(IWX_INIT_NVM),
4075 };
4076
4077 int err;
4078
4079 if ((sc->sc_flags & IWX_FLAG_RFKILL) && !readnvm) {
4080 printf("%s: radio is disabled by hardware switch\n",
4081 DEVNAME(sc));
4082 return EPERM;
4083 }
4084
4085 sc->sc_init_complete = 0;
4086 err = iwx_load_ucode_wait_alive(sc);
4087 if (err) {
4088 IWX_DPRINTF(sc, IWX_DEBUG_FIRMWARE_TLV,
4089 "%s: failed to load init firmware\n", DEVNAME(sc));
4090 return err;
4091 } else {
4092 IWX_DPRINTF(sc, IWX_DEBUG_FIRMWARE_TLV,
4093 "%s: successfully loaded init firmware\n", __func__);
4094 }
4095
4096 /*
4097 * Send init config command to mark that we are sending NVM
4098 * access commands
4099 */
4100 err = iwx_send_cmd_pdu(sc, IWX_WIDE_ID(IWX_SYSTEM_GROUP,
4101 IWX_INIT_EXTENDED_CFG_CMD), 0, sizeof(init_cfg), &init_cfg);
4102 if (err) {
4103 printf("%s: IWX_INIT_EXTENDED_CFG_CMD error=%d\n", __func__,
4104 err);
4105 return err;
4106 }
4107
4108 err = iwx_send_cmd_pdu(sc, IWX_WIDE_ID(IWX_REGULATORY_AND_NVM_GROUP,
4109 IWX_NVM_ACCESS_COMPLETE), 0, sizeof(nvm_complete), &nvm_complete);
4110 if (err) {
4111 return err;
4112 }
4113
4114 /* Wait for the init complete notification from the firmware. */
4115 while ((sc->sc_init_complete & wait_flags) != wait_flags) {
4116 err = msleep(&sc->sc_init_complete, &sc->sc_mtx, 0, "iwxinit", 2 * hz);
4117 if (err) {
4118 DPRINTF(("%s: will return err=%d\n", __func__, err));
4119 return err;
4120 } else {
4121 DPRINTF(("%s: sc_init_complete == IWX_INIT_COMPLETE\n",
4122 __func__));
4123 }
4124 }
4125
4126 if (readnvm) {
4127 err = iwx_nvm_get(sc);
4128 DPRINTF(("%s: err=%d\n", __func__, err));
4129 if (err) {
4130 printf("%s: failed to read nvm (error %d)\n",
4131 DEVNAME(sc), err);
4132 return err;
4133 } else {
4134 DPRINTF(("%s: successfully read nvm\n", DEVNAME(sc)));
4135 }
4136 IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, sc->sc_nvm.hw_addr);
4137 }
4138 return 0;
4139 }
4140
4141 static int
iwx_config_ltr(struct iwx_softc * sc)4142 iwx_config_ltr(struct iwx_softc *sc)
4143 {
4144 struct iwx_ltr_config_cmd cmd = {
4145 .flags = htole32(IWX_LTR_CFG_FLAG_FEATURE_ENABLE),
4146 };
4147
4148 if (!sc->sc_ltr_enabled)
4149 return 0;
4150
4151 return iwx_send_cmd_pdu(sc, IWX_LTR_CONFIG, 0, sizeof(cmd), &cmd);
4152 }
4153
4154 static void
iwx_update_rx_desc(struct iwx_softc * sc,struct iwx_rx_ring * ring,int idx,bus_dma_segment_t * seg)4155 iwx_update_rx_desc(struct iwx_softc *sc, struct iwx_rx_ring *ring, int idx,
4156 bus_dma_segment_t *seg)
4157 {
4158 struct iwx_rx_data *data = &ring->data[idx];
4159
4160 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {
4161 struct iwx_rx_transfer_desc *desc = ring->desc;
4162 desc[idx].rbid = htole16(idx & 0xffff);
4163 desc[idx].addr = htole64((*seg).ds_addr);
4164 bus_dmamap_sync(ring->data_dmat, data->map,
4165 BUS_DMASYNC_PREWRITE);
4166 } else {
4167 ((uint64_t *)ring->desc)[idx] =
4168 htole64((*seg).ds_addr);
4169 bus_dmamap_sync(ring->data_dmat, data->map,
4170 BUS_DMASYNC_PREWRITE);
4171 }
4172 }
4173
4174 static int
iwx_rx_addbuf(struct iwx_softc * sc,int size,int idx)4175 iwx_rx_addbuf(struct iwx_softc *sc, int size, int idx)
4176 {
4177 struct iwx_rx_ring *ring = &sc->rxq;
4178 struct iwx_rx_data *data = &ring->data[idx];
4179 struct mbuf *m;
4180 int err;
4181 int fatal = 0;
4182 bus_dma_segment_t seg;
4183 int nsegs;
4184
4185 m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, IWX_RBUF_SIZE);
4186 if (m == NULL)
4187 return ENOBUFS;
4188
4189 if (data->m != NULL) {
4190 bus_dmamap_unload(ring->data_dmat, data->map);
4191 fatal = 1;
4192 }
4193
4194 m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
4195 err = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m, &seg,
4196 &nsegs, BUS_DMA_NOWAIT);
4197 if (err) {
4198 /* XXX */
4199 if (fatal)
4200 panic("could not load RX mbuf");
4201 m_freem(m);
4202 return err;
4203 }
4204 data->m = m;
4205 bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREREAD);
4206
4207 /* Update RX descriptor. */
4208 iwx_update_rx_desc(sc, ring, idx, &seg);
4209 return 0;
4210 }
4211
4212 /*
4213 * @brief Return a single signal strength for the given frame.
4214 *
4215 * The firmware communicates up an energy field which is the negative of
4216 * the dBm value. Ie, the number is positive and it increases as the
4217 * signal level decreases.
4218 *
4219 * Fetch the two values, map 0 (inactive antenna) to -256 dBm which is a
4220 * very small number, negate a non-zero value so it's mapped into a dBm
4221 * value, then choose the maximum value to return.
4222 */
4223 static int
iwx_rxmq_get_signal_strength(struct iwx_softc * sc,struct iwx_rx_mpdu_desc * desc)4224 iwx_rxmq_get_signal_strength(struct iwx_softc *sc,
4225 struct iwx_rx_mpdu_desc *desc)
4226 {
4227 int energy_a, energy_b;
4228
4229 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {
4230 energy_a = desc->v3.energy_a;
4231 energy_b = desc->v3.energy_b;
4232 } else {
4233 energy_a = desc->v1.energy_a;
4234 energy_b = desc->v1.energy_b;
4235 }
4236 energy_a = energy_a ? -energy_a : -256;
4237 energy_b = energy_b ? -energy_b : -256;
4238 return MAX(energy_a, energy_b);
4239 }
4240
4241 /**
4242 * @brief Calculate an RSSI from the given signal level and noise floor.
4243 *
4244 * This calculates an RSSI and clamps it at IWX_RSSI_MINIMUM at the lower level
4245 * and IWX_RSSI_MAXIMUM at the upper level.
4246 *
4247 * All units are in dBm.
4248 */
4249 static int
iwx_calculate_rssi(struct iwx_softc * sc,int ss,int nf)4250 iwx_calculate_rssi(struct iwx_softc *sc, int ss, int nf)
4251 {
4252 int rssi = (ss - nf);
4253 if (rssi < IWX_RSSI_MINIMUM)
4254 rssi = IWX_RSSI_MINIMUM;
4255 else if (rssi > IWX_RSSI_MAXIMUM)
4256 rssi = IWX_RSSI_MAXIMUM;
4257
4258 return (rssi);
4259 }
4260
4261 static int
iwx_rxmq_get_chains(struct iwx_softc * sc,struct iwx_rx_mpdu_desc * desc)4262 iwx_rxmq_get_chains(struct iwx_softc *sc,
4263 struct iwx_rx_mpdu_desc *desc)
4264 {
4265
4266 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)
4267 return ((desc->v3.rate_n_flags & IWX_RATE_MCS_ANT_AB_MSK) >>
4268 IWX_RATE_MCS_ANT_POS);
4269 else
4270 return ((desc->v1.rate_n_flags & IWX_RATE_MCS_ANT_AB_MSK) >>
4271 IWX_RATE_MCS_ANT_POS);
4272 }
4273
4274 static void
iwx_rx_rx_phy_cmd(struct iwx_softc * sc,struct iwx_rx_packet * pkt,struct iwx_rx_data * data)4275 iwx_rx_rx_phy_cmd(struct iwx_softc *sc, struct iwx_rx_packet *pkt,
4276 struct iwx_rx_data *data)
4277 {
4278 struct iwx_rx_phy_info *phy_info = (void *)pkt->data;
4279 struct iwx_cmd_header *cmd_hdr = &pkt->hdr;
4280 int qid = cmd_hdr->qid;
4281 struct iwx_tx_ring *ring = &sc->txq[qid];
4282
4283 bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREREAD);
4284 memcpy(&sc->sc_last_phy_info, phy_info, sizeof(sc->sc_last_phy_info));
4285 }
4286
4287 /*
4288 * @brief Retrieve the average noise (in dBm) among receivers.
4289 *
4290 * Note: This routine calculates the noise floor sum incorrectly, as
4291 * you can't just linearly add the logarithm based dB units together.
4292 *
4293 * If no noise floor is available then this routine will return -127.
4294 */
4295 static int
iwx_get_noise(struct iwx_softc * sc,const struct iwx_statistics_rx_non_phy * stats)4296 iwx_get_noise(struct iwx_softc *sc,
4297 const struct iwx_statistics_rx_non_phy *stats)
4298 {
4299 int i, total, nbant, noise, ret;
4300
4301 total = nbant = noise = 0;
4302 for (i = 0; i < 3; i++) {
4303 noise = le32toh(stats->beacon_silence_rssi[i]) & 0xff;
4304 if (noise) {
4305 total += noise;
4306 nbant++;
4307 }
4308 }
4309
4310 /* There should be at least one antenna but check anyway. */
4311 if (nbant == 0)
4312 ret = -127;
4313 else if (total == 0)
4314 ret = -127;
4315 else
4316 ret = (total / nbant) - 127;
4317
4318 return (ret);
4319 }
4320
4321 #if 0
4322 int
4323 iwx_ccmp_decap(struct iwx_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
4324 struct ieee80211_rxinfo *rxi)
4325 {
4326 struct ieee80211com *ic = &sc->sc_ic;
4327 struct ieee80211_key *k;
4328 struct ieee80211_frame *wh;
4329 uint64_t pn, *prsc;
4330 uint8_t *ivp;
4331 uint8_t tid;
4332 int hdrlen, hasqos;
4333
4334 wh = mtod(m, struct ieee80211_frame *);
4335 hdrlen = ieee80211_get_hdrlen(wh);
4336 ivp = (uint8_t *)wh + hdrlen;
4337
4338 /* find key for decryption */
4339 k = ieee80211_get_rxkey(ic, m, ni);
4340 if (k == NULL || k->k_cipher != IEEE80211_CIPHER_CCMP)
4341 return 1;
4342
4343 /* Check that ExtIV bit is be set. */
4344 if (!(ivp[3] & IEEE80211_WEP_EXTIV))
4345 return 1;
4346
4347 hasqos = ieee80211_has_qos(wh);
4348 tid = hasqos ? ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;
4349 prsc = &k->k_rsc[tid];
4350
4351 /* Extract the 48-bit PN from the CCMP header. */
4352 pn = (uint64_t)ivp[0] |
4353 (uint64_t)ivp[1] << 8 |
4354 (uint64_t)ivp[4] << 16 |
4355 (uint64_t)ivp[5] << 24 |
4356 (uint64_t)ivp[6] << 32 |
4357 (uint64_t)ivp[7] << 40;
4358 if (rxi->rxi_flags & IEEE80211_RXI_HWDEC_SAME_PN) {
4359 if (pn < *prsc) {
4360 ic->ic_stats.is_ccmp_replays++;
4361 return 1;
4362 }
4363 } else if (pn <= *prsc) {
4364 ic->ic_stats.is_ccmp_replays++;
4365 return 1;
4366 }
4367 /* Last seen packet number is updated in ieee80211_inputm(). */
4368
4369 /*
4370 * Some firmware versions strip the MIC, and some don't. It is not
4371 * clear which of the capability flags could tell us what to expect.
4372 * For now, keep things simple and just leave the MIC in place if
4373 * it is present.
4374 *
4375 * The IV will be stripped by ieee80211_inputm().
4376 */
4377 return 0;
4378 }
4379 #endif
4380
4381 static int
iwx_rx_hwdecrypt(struct iwx_softc * sc,struct mbuf * m,uint32_t rx_pkt_status)4382 iwx_rx_hwdecrypt(struct iwx_softc *sc, struct mbuf *m, uint32_t rx_pkt_status)
4383 {
4384 struct ieee80211_frame *wh;
4385 int ret = 0;
4386 uint8_t type, subtype;
4387
4388 wh = mtod(m, struct ieee80211_frame *);
4389
4390 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
4391 if (type == IEEE80211_FC0_TYPE_CTL) {
4392 return 0;
4393 }
4394
4395 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
4396 if (IEEE80211_QOS_HAS_SEQ(wh) && (subtype & IEEE80211_FC0_SUBTYPE_NODATA)) {
4397 return 0;
4398 }
4399
4400
4401 if (((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
4402 IEEE80211_FC0_TYPE_CTL)
4403 && (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) {
4404 if ((rx_pkt_status & IWX_RX_MPDU_RES_STATUS_SEC_ENC_MSK) !=
4405 IWX_RX_MPDU_RES_STATUS_SEC_CCM_ENC) {
4406 DPRINTF(("%s: not IWX_RX_MPDU_RES_STATUS_SEC_CCM_ENC\n", __func__));
4407 ret = 1;
4408 goto out;
4409 }
4410 /* Check whether decryption was successful or not. */
4411 if ((rx_pkt_status &
4412 (IWX_RX_MPDU_RES_STATUS_DEC_DONE |
4413 IWX_RX_MPDU_RES_STATUS_MIC_OK)) !=
4414 (IWX_RX_MPDU_RES_STATUS_DEC_DONE |
4415 IWX_RX_MPDU_RES_STATUS_MIC_OK)) {
4416 DPRINTF(("%s: not IWX_RX_MPDU_RES_STATUS_MIC_OK\n", __func__));
4417 ret = 1;
4418 goto out;
4419 }
4420 }
4421 out:
4422 return ret;
4423 }
4424
4425 static void
iwx_rx_frame(struct iwx_softc * sc,struct mbuf * m,int chanidx,uint32_t rx_pkt_status,int is_shortpre,int rate_n_flags,uint32_t device_timestamp,uint8_t rssi)4426 iwx_rx_frame(struct iwx_softc *sc, struct mbuf *m, int chanidx,
4427 uint32_t rx_pkt_status, int is_shortpre, int rate_n_flags,
4428 uint32_t device_timestamp, uint8_t rssi)
4429 {
4430 struct ieee80211com *ic = &sc->sc_ic;
4431 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
4432 struct ieee80211_frame *wh;
4433 struct ieee80211_node *ni;
4434
4435 /*
4436 * We need to turn the hardware provided channel index into a channel
4437 * and then find it in our ic_channels array
4438 */
4439 if (chanidx < 0 || chanidx >= nitems(ic->ic_channels)) {
4440 /*
4441 * OpenBSD points this at the ibss chan, which it defaults to
4442 * channel 1 and then never touches again. Skip a step.
4443 */
4444 printf("iwx: %s:%d controlling chanidx to 1 (%d)\n", __func__, __LINE__, chanidx);
4445 chanidx = 1;
4446 }
4447
4448 int channel = chanidx;
4449 for (int i = 0; i < ic->ic_nchans; i++) {
4450 if (ic->ic_channels[i].ic_ieee == channel) {
4451 chanidx = i;
4452 }
4453 }
4454 ic->ic_curchan = &ic->ic_channels[chanidx];
4455
4456 wh = mtod(m, struct ieee80211_frame *);
4457 ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
4458
4459 #if 0 /* XXX hw decrypt */
4460 if ((rxi->rxi_flags & IEEE80211_RXI_HWDEC) &&
4461 iwx_ccmp_decap(sc, m, ni, rxi) != 0) {
4462 m_freem(m);
4463 ieee80211_release_node(ic, ni);
4464 return;
4465 }
4466 #endif
4467 if (ieee80211_radiotap_active_vap(vap)) {
4468 struct iwx_rx_radiotap_header *tap = &sc->sc_rxtap;
4469 uint16_t chan_flags;
4470 int have_legacy_rate = 1;
4471 uint8_t mcs, rate;
4472
4473 tap->wr_flags = 0;
4474 if (is_shortpre)
4475 tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
4476 tap->wr_chan_freq =
4477 htole16(ic->ic_channels[chanidx].ic_freq);
4478 chan_flags = ic->ic_channels[chanidx].ic_flags;
4479 #if 0
4480 if (ic->ic_curmode != IEEE80211_MODE_11N &&
4481 ic->ic_curmode != IEEE80211_MODE_11AC) {
4482 chan_flags &= ~IEEE80211_CHAN_HT;
4483 chan_flags &= ~IEEE80211_CHAN_40MHZ;
4484 }
4485 if (ic->ic_curmode != IEEE80211_MODE_11AC)
4486 chan_flags &= ~IEEE80211_CHAN_VHT;
4487 #else
4488 chan_flags &= ~IEEE80211_CHAN_HT;
4489 #endif
4490 tap->wr_chan_flags = htole16(chan_flags);
4491 tap->wr_dbm_antsignal = rssi;
4492 tap->wr_dbm_antnoise = (int8_t)sc->sc_noise;
4493 tap->wr_tsft = device_timestamp;
4494
4495 if (sc->sc_rate_n_flags_version >= 2) {
4496 uint32_t mod_type = (rate_n_flags &
4497 IWX_RATE_MCS_MOD_TYPE_MSK);
4498 const struct ieee80211_rateset *rs = NULL;
4499 uint32_t ridx;
4500 have_legacy_rate = (mod_type == IWX_RATE_MCS_CCK_MSK ||
4501 mod_type == IWX_RATE_MCS_LEGACY_OFDM_MSK);
4502 mcs = (rate_n_flags & IWX_RATE_HT_MCS_CODE_MSK);
4503 ridx = (rate_n_flags & IWX_RATE_LEGACY_RATE_MSK);
4504 if (mod_type == IWX_RATE_MCS_CCK_MSK)
4505 rs = &ieee80211_std_rateset_11b;
4506 else if (mod_type == IWX_RATE_MCS_LEGACY_OFDM_MSK)
4507 rs = &ieee80211_std_rateset_11a;
4508 if (rs && ridx < rs->rs_nrates) {
4509 rate = (rs->rs_rates[ridx] &
4510 IEEE80211_RATE_VAL);
4511 } else
4512 rate = 0;
4513 } else {
4514 have_legacy_rate = ((rate_n_flags &
4515 (IWX_RATE_MCS_HT_MSK_V1 |
4516 IWX_RATE_MCS_VHT_MSK_V1)) == 0);
4517 mcs = (rate_n_flags &
4518 (IWX_RATE_HT_MCS_RATE_CODE_MSK_V1 |
4519 IWX_RATE_HT_MCS_NSS_MSK_V1));
4520 rate = (rate_n_flags & IWX_RATE_LEGACY_RATE_MSK_V1);
4521 }
4522 if (!have_legacy_rate) {
4523 tap->wr_rate = (0x80 | mcs);
4524 } else {
4525 switch (rate) {
4526 /* CCK rates. */
4527 case 10: tap->wr_rate = 2; break;
4528 case 20: tap->wr_rate = 4; break;
4529 case 55: tap->wr_rate = 11; break;
4530 case 110: tap->wr_rate = 22; break;
4531 /* OFDM rates. */
4532 case 0xd: tap->wr_rate = 12; break;
4533 case 0xf: tap->wr_rate = 18; break;
4534 case 0x5: tap->wr_rate = 24; break;
4535 case 0x7: tap->wr_rate = 36; break;
4536 case 0x9: tap->wr_rate = 48; break;
4537 case 0xb: tap->wr_rate = 72; break;
4538 case 0x1: tap->wr_rate = 96; break;
4539 case 0x3: tap->wr_rate = 108; break;
4540 /* Unknown rate: should not happen. */
4541 default: tap->wr_rate = 0;
4542 }
4543 // XXX hack - this needs rebased with the new rate stuff anyway
4544 tap->wr_rate = rate;
4545 }
4546 }
4547
4548 IWX_UNLOCK(sc);
4549 if (ni == NULL) {
4550 if (ieee80211_input_mimo_all(ic, m) == -1)
4551 printf("%s:%d input_all returned -1\n", __func__, __LINE__);
4552 } else {
4553
4554 if (ieee80211_input_mimo(ni, m) == -1)
4555 printf("%s:%d input_all returned -1\n", __func__, __LINE__);
4556 ieee80211_free_node(ni);
4557 }
4558 IWX_LOCK(sc);
4559 }
4560
4561 static void
iwx_rx_mpdu_mq(struct iwx_softc * sc,struct mbuf * m,void * pktdata,size_t maxlen)4562 iwx_rx_mpdu_mq(struct iwx_softc *sc, struct mbuf *m, void *pktdata,
4563 size_t maxlen)
4564 {
4565 struct ieee80211com *ic = &sc->sc_ic;
4566 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
4567 struct ieee80211_node *ni = vap->iv_bss;
4568 struct ieee80211_key *k;
4569 struct ieee80211_rx_stats rxs;
4570 struct iwx_rx_mpdu_desc *desc;
4571 uint32_t len, hdrlen, rate_n_flags, device_timestamp;
4572 int rssi;
4573 uint8_t chanidx;
4574 uint16_t phy_info;
4575 size_t desc_size;
4576 int pad = 0;
4577
4578 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)
4579 desc_size = sizeof(*desc);
4580 else
4581 desc_size = IWX_RX_DESC_SIZE_V1;
4582
4583 if (maxlen < desc_size) {
4584 m_freem(m);
4585 return; /* drop */
4586 }
4587
4588 desc = (struct iwx_rx_mpdu_desc *)pktdata;
4589
4590 if (!(desc->status & htole16(IWX_RX_MPDU_RES_STATUS_CRC_OK)) ||
4591 !(desc->status & htole16(IWX_RX_MPDU_RES_STATUS_OVERRUN_OK))) {
4592 printf("%s: Bad CRC or FIFO: 0x%08X\n", __func__, desc->status);
4593 m_freem(m);
4594 return; /* drop */
4595 }
4596
4597 len = le16toh(desc->mpdu_len);
4598 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
4599 /* Allow control frames in monitor mode. */
4600 if (len < sizeof(struct ieee80211_frame_cts)) {
4601 m_freem(m);
4602 return;
4603 }
4604
4605 } else if (len < sizeof(struct ieee80211_frame)) {
4606 m_freem(m);
4607 return;
4608 }
4609 if (len > maxlen - desc_size) {
4610 m_freem(m);
4611 return;
4612 }
4613
4614 // TODO: arithmetic on a pointer to void is a GNU extension
4615 m->m_data = (char *)pktdata + desc_size;
4616 m->m_pkthdr.len = m->m_len = len;
4617
4618 /* Account for padding following the frame header. */
4619 if (desc->mac_flags2 & IWX_RX_MPDU_MFLG2_PAD) {
4620 struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
4621 int type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
4622 if (type == IEEE80211_FC0_TYPE_CTL) {
4623 switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
4624 case IEEE80211_FC0_SUBTYPE_CTS:
4625 hdrlen = sizeof(struct ieee80211_frame_cts);
4626 break;
4627 case IEEE80211_FC0_SUBTYPE_ACK:
4628 hdrlen = sizeof(struct ieee80211_frame_ack);
4629 break;
4630 default:
4631 hdrlen = sizeof(struct ieee80211_frame_min);
4632 break;
4633 }
4634 } else
4635 hdrlen = ieee80211_hdrsize(wh);
4636
4637 if ((le16toh(desc->status) &
4638 IWX_RX_MPDU_RES_STATUS_SEC_ENC_MSK) ==
4639 IWX_RX_MPDU_RES_STATUS_SEC_CCM_ENC) {
4640 // CCMP header length
4641 hdrlen += 8;
4642 }
4643
4644 memmove(m->m_data + 2, m->m_data, hdrlen);
4645 m_adj(m, 2);
4646
4647 }
4648
4649 if ((le16toh(desc->status) &
4650 IWX_RX_MPDU_RES_STATUS_SEC_ENC_MSK) ==
4651 IWX_RX_MPDU_RES_STATUS_SEC_CCM_ENC) {
4652 pad = 1;
4653 }
4654
4655 /* If it's a HT node then perform re-order processing */
4656 if (ni->ni_flags & IEEE80211_NODE_HT)
4657 m->m_flags |= M_AMPDU;
4658
4659 /*
4660 * Hardware de-aggregates A-MSDUs and copies the same MAC header
4661 * in place for each subframe. But it leaves the 'A-MSDU present'
4662 * bit set in the frame header. We need to clear this bit ourselves.
4663 * (XXX This workaround is not required on AX200/AX201 devices that
4664 * have been tested by me, but it's unclear when this problem was
4665 * fixed in the hardware. It definitely affects the 9k generation.
4666 * Leaving this in place for now since some 9k/AX200 hybrids seem
4667 * to exist that we may eventually add support for.)
4668 *
4669 * And we must allow the same CCMP PN for subframes following the
4670 * first subframe. Otherwise they would be discarded as replays.
4671 */
4672 if (desc->mac_flags2 & IWX_RX_MPDU_MFLG2_AMSDU) {
4673 struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
4674 uint8_t subframe_idx = (desc->amsdu_info &
4675 IWX_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK);
4676 uint8_t *qos;
4677
4678 rxs.c_pktflags |= IEEE80211_RX_F_AMSDU;
4679 if (subframe_idx > 0)
4680 rxs.c_pktflags |= IEEE80211_RX_F_AMSDU_MORE;
4681
4682 /* XXX should keep driver statistics about this */
4683 IWX_DPRINTF(sc, IWX_DEBUG_AMPDU_MGMT,
4684 "%s: === IWX_RX_MPDU_MFLG2_AMSDU\n", __func__);
4685
4686 qos = ieee80211_getqos(wh);
4687 qos[0] &= ~IEEE80211_QOS_AMSDU;
4688 }
4689
4690 /*
4691 * Verify decryption before duplicate detection. The latter uses
4692 * the TID supplied in QoS frame headers and this TID is implicitly
4693 * verified as part of the CCMP nonce.
4694 */
4695 k = ieee80211_crypto_get_txkey(ni, m);
4696 if (k != NULL &&
4697 (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_AES_CCM) &&
4698 iwx_rx_hwdecrypt(sc, m, le16toh(desc->status)/*, &rxi*/)) {
4699 DPRINTF(("%s: iwx_rx_hwdecrypt failed\n", __func__));
4700 m_freem(m);
4701 return;
4702 }
4703
4704 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {
4705 rate_n_flags = le32toh(desc->v3.rate_n_flags);
4706 chanidx = desc->v3.channel;
4707 device_timestamp = le32toh(desc->v3.gp2_on_air_rise);
4708 } else {
4709 rate_n_flags = le32toh(desc->v1.rate_n_flags);
4710 chanidx = desc->v1.channel;
4711 device_timestamp = le32toh(desc->v1.gp2_on_air_rise);
4712 }
4713
4714 phy_info = le16toh(desc->phy_info);
4715
4716 /* note: RSSI here is absolute signal strength, not relative */
4717 rssi = iwx_rxmq_get_signal_strength(sc, desc);
4718
4719 memset(&rxs, 0, sizeof(rxs));
4720 rxs.r_flags |= IEEE80211_R_IEEE | IEEE80211_R_FREQ;
4721 rxs.r_flags |= IEEE80211_R_BAND;
4722 rxs.r_flags |= IEEE80211_R_NF | IEEE80211_R_RSSI;
4723 rxs.r_flags |= IEEE80211_R_TSF32 | IEEE80211_R_TSF_START;
4724
4725 rxs.c_ieee = chanidx;
4726 rxs.c_freq = ieee80211_ieee2mhz(rxs.c_ieee,
4727 chanidx <= 14 ? IEEE80211_CHAN_2GHZ : IEEE80211_CHAN_5GHZ);
4728 rxs.c_band = chanidx <= 14 ? IEEE80211_CHAN_2GHZ : IEEE80211_CHAN_5GHZ;
4729 rxs.c_rx_tsf = device_timestamp;
4730 rxs.c_chain = iwx_rxmq_get_chains(sc, desc);
4731 if (rxs.c_chain != 0)
4732 rxs.r_flags |= IEEE80211_R_C_CHAIN;
4733
4734 /* noise floor is in 1dB units */
4735 if (sc->sc_noise < IWX_DEFAULT_NF)
4736 /*
4737 * For now choose /a/ default, net80211 expects nf to be passed
4738 * in various places and older drivers fake NF values where
4739 * needed.
4740 */
4741 rxs.c_nf = IWX_DEFAULT_NF;
4742 else
4743 rxs.c_nf = sc->sc_noise;
4744
4745 /* rssi is in 1/2db units relative to the noise floor */
4746 rxs.c_rssi = iwx_calculate_rssi(sc, rssi, rxs.c_nf) * 2;
4747
4748 if (pad) {
4749 rxs.c_pktflags |= IEEE80211_RX_F_DECRYPTED;
4750 rxs.c_pktflags |= IEEE80211_RX_F_IV_STRIP;
4751 }
4752
4753 if (ieee80211_add_rx_params(m, &rxs) == 0) {
4754 printf("%s: ieee80211_add_rx_params failed\n", __func__);
4755 return;
4756 }
4757
4758 ieee80211_add_rx_params(m, &rxs);
4759
4760 #if 0
4761 if (iwx_rx_reorder(sc, m, chanidx, desc,
4762 (phy_info & IWX_RX_MPDU_PHY_SHORT_PREAMBLE),
4763 rate_n_flags, device_timestamp, &rxi, ml))
4764 return;
4765 #endif
4766
4767 if (pad) {
4768 #define TRIM 8
4769 struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
4770 hdrlen = ieee80211_hdrsize(wh);
4771 memmove(m->m_data + TRIM, m->m_data, hdrlen);
4772 m_adj(m, TRIM);
4773 #undef TRIM
4774 }
4775
4776 iwx_rx_frame(sc, m, chanidx, le16toh(desc->status),
4777 (phy_info & IWX_RX_MPDU_PHY_SHORT_PREAMBLE),
4778 rate_n_flags, device_timestamp, rssi);
4779 }
4780
4781 static void
iwx_clear_tx_desc(struct iwx_softc * sc,struct iwx_tx_ring * ring,int idx)4782 iwx_clear_tx_desc(struct iwx_softc *sc, struct iwx_tx_ring *ring, int idx)
4783 {
4784 struct iwx_tfh_tfd *desc = &ring->desc[idx];
4785 uint8_t num_tbs = le16toh(desc->num_tbs) & 0x1f;
4786 int i;
4787
4788 /* First TB is never cleared - it is bidirectional DMA data. */
4789 for (i = 1; i < num_tbs; i++) {
4790 struct iwx_tfh_tb *tb = &desc->tbs[i];
4791 memset(tb, 0, sizeof(*tb));
4792 }
4793 desc->num_tbs = htole16(1);
4794
4795 bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
4796 BUS_DMASYNC_PREWRITE);
4797 }
4798
4799 static void
iwx_txd_done(struct iwx_softc * sc,struct iwx_tx_ring * ring,struct iwx_tx_data * txd)4800 iwx_txd_done(struct iwx_softc *sc, struct iwx_tx_ring *ring,
4801 struct iwx_tx_data *txd)
4802 {
4803 bus_dmamap_sync(ring->data_dmat, txd->map, BUS_DMASYNC_POSTWRITE);
4804 bus_dmamap_unload(ring->data_dmat, txd->map);
4805
4806 ieee80211_tx_complete(&txd->in->in_ni, txd->m, 0);
4807 txd->m = NULL;
4808 txd->in = NULL;
4809 }
4810
4811 static void
iwx_txq_advance(struct iwx_softc * sc,struct iwx_tx_ring * ring,uint16_t idx)4812 iwx_txq_advance(struct iwx_softc *sc, struct iwx_tx_ring *ring, uint16_t idx)
4813 {
4814 struct iwx_tx_data *txd;
4815
4816 while (ring->tail_hw != idx) {
4817 txd = &ring->data[ring->tail];
4818 if (txd->m != NULL) {
4819 iwx_clear_tx_desc(sc, ring, ring->tail);
4820 iwx_tx_update_byte_tbl(sc, ring, ring->tail, 0, 0);
4821 iwx_txd_done(sc, ring, txd);
4822 ring->queued--;
4823 if (ring->queued < 0)
4824 panic("caught negative queue count");
4825 }
4826 ring->tail = (ring->tail + 1) % IWX_TX_RING_COUNT;
4827 ring->tail_hw = (ring->tail_hw + 1) % sc->max_tfd_queue_size;
4828 }
4829 }
4830
4831 static void
iwx_rx_tx_cmd(struct iwx_softc * sc,struct iwx_rx_packet * pkt,struct iwx_rx_data * data)4832 iwx_rx_tx_cmd(struct iwx_softc *sc, struct iwx_rx_packet *pkt,
4833 struct iwx_rx_data *data)
4834 {
4835 struct ieee80211com *ic = &sc->sc_ic;
4836 struct ifnet *ifp = IC2IFP(ic);
4837 struct iwx_cmd_header *cmd_hdr = &pkt->hdr;
4838 int qid = cmd_hdr->qid, status, txfail;
4839 struct iwx_tx_ring *ring = &sc->txq[qid];
4840 struct iwx_tx_resp *tx_resp = (void *)pkt->data;
4841 uint32_t ssn;
4842 uint32_t len = iwx_rx_packet_len(pkt);
4843 int idx = cmd_hdr->idx;
4844 struct iwx_tx_data *txd = &ring->data[idx];
4845 struct mbuf *m = txd->m;
4846
4847 bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD);
4848
4849 /* Sanity checks. */
4850 if (sizeof(*tx_resp) > len)
4851 return;
4852 if (qid < IWX_FIRST_AGG_TX_QUEUE && tx_resp->frame_count > 1)
4853 return;
4854 if (qid >= IWX_FIRST_AGG_TX_QUEUE && sizeof(*tx_resp) + sizeof(ssn) +
4855 tx_resp->frame_count * sizeof(tx_resp->status) > len)
4856 return;
4857
4858 sc->sc_tx_timer[qid] = 0;
4859
4860 if (tx_resp->frame_count > 1) /* A-MPDU */
4861 return;
4862
4863 status = le16toh(tx_resp->status.status) & IWX_TX_STATUS_MSK;
4864 txfail = (status != IWX_TX_STATUS_SUCCESS &&
4865 status != IWX_TX_STATUS_DIRECT_DONE);
4866
4867 #ifdef __not_yet__
4868 /* TODO: Replace accounting below with ieee80211_tx_complete() */
4869 ieee80211_tx_complete(&in->in_ni, m, txfail);
4870 #else
4871 if (txfail)
4872 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
4873 else {
4874 if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len);
4875 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
4876 if (m->m_flags & M_MCAST)
4877 if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1);
4878 }
4879 #endif
4880 /*
4881 * On hardware supported by iwx(4) the SSN counter corresponds
4882 * to a Tx ring index rather than a sequence number.
4883 * Frames up to this index (non-inclusive) can now be freed.
4884 */
4885 memcpy(&ssn, &tx_resp->status + tx_resp->frame_count, sizeof(ssn));
4886 ssn = le32toh(ssn);
4887 if (ssn < sc->max_tfd_queue_size) {
4888 iwx_txq_advance(sc, ring, ssn);
4889 iwx_clear_oactive(sc, ring);
4890 }
4891 }
4892
4893 static void
iwx_clear_oactive(struct iwx_softc * sc,struct iwx_tx_ring * ring)4894 iwx_clear_oactive(struct iwx_softc *sc, struct iwx_tx_ring *ring)
4895 {
4896 IWX_ASSERT_LOCKED(sc);
4897
4898 if (ring->queued < iwx_lomark) {
4899 sc->qfullmsk &= ~(1 << ring->qid);
4900 if (sc->qfullmsk == 0 /* && ifq_is_oactive(&ifp->if_snd) */) {
4901 /*
4902 * Well, we're in interrupt context, but then again
4903 * I guess net80211 does all sorts of stunts in
4904 * interrupt context, so maybe this is no biggie.
4905 */
4906 iwx_start(sc);
4907 }
4908 }
4909 }
4910
4911 static void
iwx_rx_compressed_ba(struct iwx_softc * sc,struct iwx_rx_packet * pkt)4912 iwx_rx_compressed_ba(struct iwx_softc *sc, struct iwx_rx_packet *pkt)
4913 {
4914 struct iwx_compressed_ba_notif *ba_res = (void *)pkt->data;
4915 struct ieee80211com *ic = &sc->sc_ic;
4916 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
4917 struct iwx_node *in = IWX_NODE(vap->iv_bss);
4918 struct ieee80211_node *ni = &in->in_ni;
4919 struct iwx_tx_ring *ring;
4920 uint16_t i, tfd_cnt, ra_tid_cnt, idx;
4921 int qid;
4922
4923 // if (ic->ic_state != IEEE80211_S_RUN)
4924 // return;
4925
4926 if (iwx_rx_packet_payload_len(pkt) < sizeof(*ba_res))
4927 return;
4928
4929 if (ba_res->sta_id != IWX_STATION_ID)
4930 return;
4931
4932 in = (void *)ni;
4933
4934 tfd_cnt = le16toh(ba_res->tfd_cnt);
4935 ra_tid_cnt = le16toh(ba_res->ra_tid_cnt);
4936 if (!tfd_cnt || iwx_rx_packet_payload_len(pkt) < (sizeof(*ba_res) +
4937 sizeof(ba_res->ra_tid[0]) * ra_tid_cnt +
4938 sizeof(ba_res->tfd[0]) * tfd_cnt))
4939 return;
4940
4941 for (i = 0; i < tfd_cnt; i++) {
4942 struct iwx_compressed_ba_tfd *ba_tfd = &ba_res->tfd[i];
4943 uint8_t tid;
4944
4945 tid = ba_tfd->tid;
4946 if (tid >= nitems(sc->aggqid))
4947 continue;
4948
4949 qid = sc->aggqid[tid];
4950 if (qid != htole16(ba_tfd->q_num))
4951 continue;
4952
4953 ring = &sc->txq[qid];
4954
4955 #if 0
4956 ba = &ni->ni_tx_ba[tid];
4957 if (ba->ba_state != IEEE80211_BA_AGREED)
4958 continue;
4959 #endif
4960 idx = le16toh(ba_tfd->tfd_index);
4961 sc->sc_tx_timer[qid] = 0;
4962 iwx_txq_advance(sc, ring, idx);
4963 iwx_clear_oactive(sc, ring);
4964 }
4965 }
4966
4967 static void
iwx_rx_bmiss(struct iwx_softc * sc,struct iwx_rx_packet * pkt,struct iwx_rx_data * data)4968 iwx_rx_bmiss(struct iwx_softc *sc, struct iwx_rx_packet *pkt,
4969 struct iwx_rx_data *data)
4970 {
4971 struct ieee80211com *ic = &sc->sc_ic;
4972 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
4973 struct iwx_missed_beacons_notif *mbn = (void *)pkt->data;
4974 uint32_t missed;
4975
4976 if ((ic->ic_opmode != IEEE80211_M_STA) ||
4977 (vap->iv_state != IEEE80211_S_RUN))
4978 return;
4979
4980 bus_dmamap_sync(sc->rxq.data_dmat, data->map,
4981 BUS_DMASYNC_POSTREAD);
4982
4983 IWX_DPRINTF(sc, IWX_DEBUG_BEACON,
4984 "%s: mac_id=%u, cmslrx=%u, cmb=%u, neb=%d, nrb=%u\n",
4985 __func__,
4986 le32toh(mbn->mac_id),
4987 le32toh(mbn->consec_missed_beacons_since_last_rx),
4988 le32toh(mbn->consec_missed_beacons),
4989 le32toh(mbn->num_expected_beacons),
4990 le32toh(mbn->num_recvd_beacons));
4991
4992 missed = le32toh(mbn->consec_missed_beacons_since_last_rx);
4993 if (missed > vap->iv_bmissthreshold) {
4994 ieee80211_beacon_miss(ic);
4995 }
4996 }
4997
4998 static int
iwx_binding_cmd(struct iwx_softc * sc,struct iwx_node * in,uint32_t action)4999 iwx_binding_cmd(struct iwx_softc *sc, struct iwx_node *in, uint32_t action)
5000 {
5001 struct iwx_binding_cmd cmd;
5002 struct ieee80211com *ic = &sc->sc_ic;
5003 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
5004 struct iwx_vap *ivp = IWX_VAP(vap);
5005 struct iwx_phy_ctxt *phyctxt = ivp->phy_ctxt;
5006 uint32_t mac_id = IWX_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color);
5007 int i, err, active = (sc->sc_flags & IWX_FLAG_BINDING_ACTIVE);
5008 uint32_t status;
5009
5010 if (action == IWX_FW_CTXT_ACTION_ADD && active)
5011 panic("binding already added");
5012 if (action == IWX_FW_CTXT_ACTION_REMOVE && !active)
5013 panic("binding already removed");
5014
5015 if (phyctxt == NULL) /* XXX race with iwx_stop() */
5016 return EINVAL;
5017
5018 memset(&cmd, 0, sizeof(cmd));
5019
5020 cmd.id_and_color
5021 = htole32(IWX_FW_CMD_ID_AND_COLOR(phyctxt->id, phyctxt->color));
5022 cmd.action = htole32(action);
5023 cmd.phy = htole32(IWX_FW_CMD_ID_AND_COLOR(phyctxt->id, phyctxt->color));
5024
5025 cmd.macs[0] = htole32(mac_id);
5026 for (i = 1; i < IWX_MAX_MACS_IN_BINDING; i++)
5027 cmd.macs[i] = htole32(IWX_FW_CTXT_INVALID);
5028
5029 if (IEEE80211_IS_CHAN_2GHZ(phyctxt->channel) ||
5030 !isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_CDB_SUPPORT))
5031 cmd.lmac_id = htole32(IWX_LMAC_24G_INDEX);
5032 else
5033 cmd.lmac_id = htole32(IWX_LMAC_5G_INDEX);
5034
5035 status = 0;
5036 err = iwx_send_cmd_pdu_status(sc, IWX_BINDING_CONTEXT_CMD, sizeof(cmd),
5037 &cmd, &status);
5038 if (err == 0 && status != 0)
5039 err = EIO;
5040
5041 return err;
5042 }
5043
5044 static uint8_t
iwx_get_vht_ctrl_pos(struct ieee80211com * ic,struct ieee80211_channel * chan)5045 iwx_get_vht_ctrl_pos(struct ieee80211com *ic, struct ieee80211_channel *chan)
5046 {
5047 int ctlchan = ieee80211_chan2ieee(ic, chan);
5048 int midpoint = chan->ic_vht_ch_freq1;
5049
5050 /*
5051 * The FW is expected to check the control channel position only
5052 * when in HT/VHT and the channel width is not 20MHz. Return
5053 * this value as the default one:
5054 */
5055 uint8_t pos = IWX_PHY_VHT_CTRL_POS_1_BELOW;
5056
5057 switch (ctlchan - midpoint) {
5058 case -6:
5059 pos = IWX_PHY_VHT_CTRL_POS_2_BELOW;
5060 break;
5061 case -2:
5062 pos = IWX_PHY_VHT_CTRL_POS_1_BELOW;
5063 break;
5064 case 2:
5065 pos = IWX_PHY_VHT_CTRL_POS_1_ABOVE;
5066 break;
5067 case 6:
5068 pos = IWX_PHY_VHT_CTRL_POS_2_ABOVE;
5069 break;
5070 default:
5071 break;
5072 }
5073
5074 return pos;
5075 }
5076
5077 static int
iwx_phy_ctxt_cmd_uhb_v3_v4(struct iwx_softc * sc,struct iwx_phy_ctxt * ctxt,uint8_t chains_static,uint8_t chains_dynamic,uint32_t action,uint8_t sco,uint8_t vht_chan_width,int cmdver)5078 iwx_phy_ctxt_cmd_uhb_v3_v4(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt,
5079 uint8_t chains_static, uint8_t chains_dynamic, uint32_t action, uint8_t sco,
5080 uint8_t vht_chan_width, int cmdver)
5081 {
5082 struct ieee80211com *ic = &sc->sc_ic;
5083 struct iwx_phy_context_cmd_uhb cmd;
5084 uint8_t active_cnt, idle_cnt;
5085 struct ieee80211_channel *chan = ctxt->channel;
5086
5087 memset(&cmd, 0, sizeof(cmd));
5088 cmd.id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(ctxt->id,
5089 ctxt->color));
5090 cmd.action = htole32(action);
5091
5092 if (IEEE80211_IS_CHAN_2GHZ(chan) ||
5093 !isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_CDB_SUPPORT))
5094 cmd.lmac_id = htole32(IWX_LMAC_24G_INDEX);
5095 else
5096 cmd.lmac_id = htole32(IWX_LMAC_5G_INDEX);
5097
5098 cmd.ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?
5099 IWX_PHY_BAND_24 : IWX_PHY_BAND_5;
5100 cmd.ci.channel = htole32(ieee80211_chan2ieee(ic, chan));
5101
5102 if (IEEE80211_IS_CHAN_VHT80(chan)) {
5103 cmd.ci.ctrl_pos = iwx_get_vht_ctrl_pos(ic, chan);
5104 cmd.ci.width = IWX_PHY_VHT_CHANNEL_MODE80;
5105 } else if (IEEE80211_IS_CHAN_HT40(chan)) {
5106 cmd.ci.width = IWX_PHY_VHT_CHANNEL_MODE40;
5107 if (IEEE80211_IS_CHAN_HT40D(chan))
5108 cmd.ci.ctrl_pos = IWX_PHY_VHT_CTRL_POS_1_ABOVE;
5109 else
5110 cmd.ci.ctrl_pos = IWX_PHY_VHT_CTRL_POS_1_BELOW;
5111 } else {
5112 cmd.ci.width = IWX_PHY_VHT_CHANNEL_MODE20;
5113 cmd.ci.ctrl_pos = IWX_PHY_VHT_CTRL_POS_1_BELOW;
5114 }
5115
5116 if (cmdver < 4 && iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP,
5117 IWX_RLC_CONFIG_CMD) != 2) {
5118 idle_cnt = chains_static;
5119 active_cnt = chains_dynamic;
5120 cmd.rxchain_info = htole32(iwx_fw_valid_rx_ant(sc) <<
5121 IWX_PHY_RX_CHAIN_VALID_POS);
5122 cmd.rxchain_info |= htole32(idle_cnt <<
5123 IWX_PHY_RX_CHAIN_CNT_POS);
5124 cmd.rxchain_info |= htole32(active_cnt <<
5125 IWX_PHY_RX_CHAIN_MIMO_CNT_POS);
5126 }
5127
5128 return iwx_send_cmd_pdu(sc, IWX_PHY_CONTEXT_CMD, 0, sizeof(cmd), &cmd);
5129 }
5130
5131 #if 0
5132 int
5133 iwx_phy_ctxt_cmd_v3_v4(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt,
5134 uint8_t chains_static, uint8_t chains_dynamic, uint32_t action, uint8_t sco,
5135 uint8_t vht_chan_width, int cmdver)
5136 {
5137 struct ieee80211com *ic = &sc->sc_ic;
5138 struct iwx_phy_context_cmd cmd;
5139 uint8_t active_cnt, idle_cnt;
5140 struct ieee80211_channel *chan = ctxt->channel;
5141
5142 memset(&cmd, 0, sizeof(cmd));
5143 cmd.id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(ctxt->id,
5144 ctxt->color));
5145 cmd.action = htole32(action);
5146
5147 if (IEEE80211_IS_CHAN_2GHZ(ctxt->channel) ||
5148 !isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_CDB_SUPPORT))
5149 cmd.lmac_id = htole32(IWX_LMAC_24G_INDEX);
5150 else
5151 cmd.lmac_id = htole32(IWX_LMAC_5G_INDEX);
5152
5153 cmd.ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?
5154 IWX_PHY_BAND_24 : IWX_PHY_BAND_5;
5155 cmd.ci.channel = ieee80211_chan2ieee(ic, chan);
5156 if (vht_chan_width == IEEE80211_VHTOP0_CHAN_WIDTH_80) {
5157 cmd.ci.ctrl_pos = iwx_get_vht_ctrl_pos(ic, chan);
5158 cmd.ci.width = IWX_PHY_VHT_CHANNEL_MODE80;
5159 } else if (chan->ic_flags & IEEE80211_CHAN_40MHZ) {
5160 if (sco == IEEE80211_HTOP0_SCO_SCA) {
5161 /* secondary chan above -> control chan below */
5162 cmd.ci.ctrl_pos = IWX_PHY_VHT_CTRL_POS_1_BELOW;
5163 cmd.ci.width = IWX_PHY_VHT_CHANNEL_MODE40;
5164 } else if (sco == IEEE80211_HTOP0_SCO_SCB) {
5165 /* secondary chan below -> control chan above */
5166 cmd.ci.ctrl_pos = IWX_PHY_VHT_CTRL_POS_1_ABOVE;
5167 cmd.ci.width = IWX_PHY_VHT_CHANNEL_MODE40;
5168 } else {
5169 cmd.ci.width = IWX_PHY_VHT_CHANNEL_MODE20;
5170 cmd.ci.ctrl_pos = IWX_PHY_VHT_CTRL_POS_1_BELOW;
5171 }
5172 } else {
5173 cmd.ci.width = IWX_PHY_VHT_CHANNEL_MODE20;
5174 cmd.ci.ctrl_pos = IWX_PHY_VHT_CTRL_POS_1_BELOW;
5175 }
5176
5177 if (cmdver < 4 && iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP,
5178 IWX_RLC_CONFIG_CMD) != 2) {
5179 idle_cnt = chains_static;
5180 active_cnt = chains_dynamic;
5181 cmd.rxchain_info = htole32(iwx_fw_valid_rx_ant(sc) <<
5182 IWX_PHY_RX_CHAIN_VALID_POS);
5183 cmd.rxchain_info |= htole32(idle_cnt <<
5184 IWX_PHY_RX_CHAIN_CNT_POS);
5185 cmd.rxchain_info |= htole32(active_cnt <<
5186 IWX_PHY_RX_CHAIN_MIMO_CNT_POS);
5187 }
5188
5189 return iwx_send_cmd_pdu(sc, IWX_PHY_CONTEXT_CMD, 0, sizeof(cmd), &cmd);
5190 }
5191 #endif
5192
5193 static int
iwx_phy_ctxt_cmd(struct iwx_softc * sc,struct iwx_phy_ctxt * ctxt,uint8_t chains_static,uint8_t chains_dynamic,uint32_t action,uint32_t apply_time,uint8_t sco,uint8_t vht_chan_width)5194 iwx_phy_ctxt_cmd(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt,
5195 uint8_t chains_static, uint8_t chains_dynamic, uint32_t action,
5196 uint32_t apply_time, uint8_t sco, uint8_t vht_chan_width)
5197 {
5198 int cmdver;
5199
5200 cmdver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_PHY_CONTEXT_CMD);
5201 if (cmdver != 3 && cmdver != 4) {
5202 printf("%s: firmware does not support phy-context-cmd v3/v4\n",
5203 DEVNAME(sc));
5204 return ENOTSUP;
5205 }
5206
5207 /*
5208 * Intel increased the size of the fw_channel_info struct and neglected
5209 * to bump the phy_context_cmd struct, which contains an fw_channel_info
5210 * member in the middle.
5211 * To keep things simple we use a separate function to handle the larger
5212 * variant of the phy context command.
5213 */
5214 if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS)) {
5215 return iwx_phy_ctxt_cmd_uhb_v3_v4(sc, ctxt, chains_static,
5216 chains_dynamic, action, sco, vht_chan_width, cmdver);
5217 } else
5218 panic("Unsupported old hardware contact thj@");
5219
5220 #if 0
5221 return iwx_phy_ctxt_cmd_v3_v4(sc, ctxt, chains_static, chains_dynamic,
5222 action, sco, vht_chan_width, cmdver);
5223 #endif
5224 }
5225
5226 static int
iwx_send_cmd(struct iwx_softc * sc,struct iwx_host_cmd * hcmd)5227 iwx_send_cmd(struct iwx_softc *sc, struct iwx_host_cmd *hcmd)
5228 {
5229 struct iwx_tx_ring *ring = &sc->txq[IWX_DQA_CMD_QUEUE];
5230 struct iwx_tfh_tfd *desc;
5231 struct iwx_tx_data *txdata;
5232 struct iwx_device_cmd *cmd;
5233 struct mbuf *m;
5234 bus_addr_t paddr;
5235 uint64_t addr;
5236 int err = 0, i, paylen, off/*, s*/;
5237 int idx, code, async, group_id;
5238 size_t hdrlen, datasz;
5239 uint8_t *data;
5240 int generation = sc->sc_generation;
5241 bus_dma_segment_t seg[10];
5242 int nsegs;
5243
5244 code = hcmd->id;
5245 async = hcmd->flags & IWX_CMD_ASYNC;
5246 idx = ring->cur;
5247
5248 for (i = 0, paylen = 0; i < nitems(hcmd->len); i++) {
5249 paylen += hcmd->len[i];
5250 }
5251
5252 /* If this command waits for a response, allocate response buffer. */
5253 hcmd->resp_pkt = NULL;
5254 if (hcmd->flags & IWX_CMD_WANT_RESP) {
5255 uint8_t *resp_buf;
5256 KASSERT(!async, ("async command want response"));
5257 KASSERT(hcmd->resp_pkt_len >= sizeof(struct iwx_rx_packet),
5258 ("wrong pkt len 1"));
5259 KASSERT(hcmd->resp_pkt_len <= IWX_CMD_RESP_MAX,
5260 ("wrong pkt len 2"));
5261 if (sc->sc_cmd_resp_pkt[idx] != NULL)
5262 return ENOSPC;
5263 resp_buf = malloc(hcmd->resp_pkt_len, M_DEVBUF,
5264 M_NOWAIT | M_ZERO);
5265 if (resp_buf == NULL)
5266 return ENOMEM;
5267 sc->sc_cmd_resp_pkt[idx] = resp_buf;
5268 sc->sc_cmd_resp_len[idx] = hcmd->resp_pkt_len;
5269 } else {
5270 sc->sc_cmd_resp_pkt[idx] = NULL;
5271 }
5272
5273 desc = &ring->desc[idx];
5274 txdata = &ring->data[idx];
5275
5276 /*
5277 * XXX Intel inside (tm)
5278 * Firmware API versions >= 50 reject old-style commands in
5279 * group 0 with a "BAD_COMMAND" firmware error. We must pretend
5280 * that such commands were in the LONG_GROUP instead in order
5281 * for firmware to accept them.
5282 */
5283 if (iwx_cmd_groupid(code) == 0) {
5284 code = IWX_WIDE_ID(IWX_LONG_GROUP, code);
5285 txdata->flags |= IWX_TXDATA_FLAG_CMD_IS_NARROW;
5286 } else
5287 txdata->flags &= ~IWX_TXDATA_FLAG_CMD_IS_NARROW;
5288
5289 group_id = iwx_cmd_groupid(code);
5290
5291 hdrlen = sizeof(cmd->hdr_wide);
5292 datasz = sizeof(cmd->data_wide);
5293
5294 if (paylen > datasz) {
5295 /* Command is too large to fit in pre-allocated space. */
5296 size_t totlen = hdrlen + paylen;
5297 if (paylen > IWX_MAX_CMD_PAYLOAD_SIZE) {
5298 printf("%s: firmware command too long (%zd bytes)\n",
5299 DEVNAME(sc), totlen);
5300 err = EINVAL;
5301 goto out;
5302 }
5303 if (totlen > IWX_RBUF_SIZE)
5304 panic("totlen > IWX_RBUF_SIZE");
5305 m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, IWX_RBUF_SIZE);
5306 if (m == NULL) {
5307 printf("%s: could not get fw cmd mbuf (%i bytes)\n",
5308 DEVNAME(sc), IWX_RBUF_SIZE);
5309 err = ENOMEM;
5310 goto out;
5311 }
5312 m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
5313 err = bus_dmamap_load_mbuf_sg(ring->data_dmat, txdata->map, m,
5314 seg, &nsegs, BUS_DMA_NOWAIT);
5315 if (nsegs > 20)
5316 panic("nsegs > 20");
5317 DPRINTF(("%s: nsegs=%i\n", __func__, nsegs));
5318 if (err) {
5319 printf("%s: could not load fw cmd mbuf (%zd bytes)\n",
5320 DEVNAME(sc), totlen);
5321 m_freem(m);
5322 goto out;
5323 }
5324 txdata->m = m; /* mbuf will be freed in iwx_cmd_done() */
5325 cmd = mtod(m, struct iwx_device_cmd *);
5326 paddr = seg[0].ds_addr;
5327 } else {
5328 cmd = &ring->cmd[idx];
5329 paddr = txdata->cmd_paddr;
5330 }
5331
5332 memset(cmd, 0, sizeof(*cmd));
5333 cmd->hdr_wide.opcode = iwx_cmd_opcode(code);
5334 cmd->hdr_wide.group_id = group_id;
5335 cmd->hdr_wide.qid = ring->qid;
5336 cmd->hdr_wide.idx = idx;
5337 cmd->hdr_wide.length = htole16(paylen);
5338 cmd->hdr_wide.version = iwx_cmd_version(code);
5339 data = cmd->data_wide;
5340
5341 for (i = 0, off = 0; i < nitems(hcmd->data); i++) {
5342 if (hcmd->len[i] == 0)
5343 continue;
5344 memcpy(data + off, hcmd->data[i], hcmd->len[i]);
5345 off += hcmd->len[i];
5346 }
5347 KASSERT(off == paylen, ("off %d != paylen %d", off, paylen));
5348
5349 desc->tbs[0].tb_len = htole16(MIN(hdrlen + paylen, IWX_FIRST_TB_SIZE));
5350 addr = htole64(paddr);
5351 memcpy(&desc->tbs[0].addr, &addr, sizeof(addr));
5352 if (hdrlen + paylen > IWX_FIRST_TB_SIZE) {
5353 DPRINTF(("%s: hdrlen=%zu paylen=%d\n", __func__, hdrlen,
5354 paylen));
5355 desc->tbs[1].tb_len = htole16(hdrlen + paylen -
5356 IWX_FIRST_TB_SIZE);
5357 addr = htole64(paddr + IWX_FIRST_TB_SIZE);
5358 memcpy(&desc->tbs[1].addr, &addr, sizeof(addr));
5359 desc->num_tbs = htole16(2);
5360 } else
5361 desc->num_tbs = htole16(1);
5362
5363 if (paylen > datasz) {
5364 bus_dmamap_sync(ring->data_dmat, txdata->map,
5365 BUS_DMASYNC_PREWRITE);
5366 } else {
5367 bus_dmamap_sync(ring->cmd_dma.tag, ring->cmd_dma.map,
5368 BUS_DMASYNC_PREWRITE);
5369 }
5370 bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
5371 BUS_DMASYNC_PREWRITE);
5372
5373 /* Kick command ring. */
5374 ring->queued++;
5375 ring->cur = (ring->cur + 1) % IWX_TX_RING_COUNT;
5376 ring->cur_hw = (ring->cur_hw + 1) % sc->max_tfd_queue_size;
5377 DPRINTF(("%s: ring->cur_hw=%i\n", __func__, ring->cur_hw));
5378 IWX_WRITE(sc, IWX_HBUS_TARG_WRPTR, ring->qid << 16 | ring->cur_hw);
5379
5380 if (!async) {
5381 err = msleep(desc, &sc->sc_mtx, PCATCH, "iwxcmd", hz);
5382 if (err == 0) {
5383 /* if hardware is no longer up, return error */
5384 if (generation != sc->sc_generation) {
5385 err = ENXIO;
5386 goto out;
5387 }
5388
5389 /* Response buffer will be freed in iwx_free_resp(). */
5390 hcmd->resp_pkt = (void *)sc->sc_cmd_resp_pkt[idx];
5391 sc->sc_cmd_resp_pkt[idx] = NULL;
5392 } else if (generation == sc->sc_generation) {
5393 free(sc->sc_cmd_resp_pkt[idx], M_DEVBUF);
5394 sc->sc_cmd_resp_pkt[idx] = NULL;
5395 }
5396 }
5397 out:
5398 return err;
5399 }
5400
5401 static int
iwx_send_cmd_pdu(struct iwx_softc * sc,uint32_t id,uint32_t flags,uint16_t len,const void * data)5402 iwx_send_cmd_pdu(struct iwx_softc *sc, uint32_t id, uint32_t flags,
5403 uint16_t len, const void *data)
5404 {
5405 struct iwx_host_cmd cmd = {
5406 .id = id,
5407 .len = { len, },
5408 .data = { data, },
5409 .flags = flags,
5410 };
5411
5412 return iwx_send_cmd(sc, &cmd);
5413 }
5414
5415 static int
iwx_send_cmd_status(struct iwx_softc * sc,struct iwx_host_cmd * cmd,uint32_t * status)5416 iwx_send_cmd_status(struct iwx_softc *sc, struct iwx_host_cmd *cmd,
5417 uint32_t *status)
5418 {
5419 struct iwx_rx_packet *pkt;
5420 struct iwx_cmd_response *resp;
5421 int err, resp_len;
5422
5423 KASSERT(((cmd->flags & IWX_CMD_WANT_RESP) == 0), ("IWX_CMD_WANT_RESP"));
5424 cmd->flags |= IWX_CMD_WANT_RESP;
5425 cmd->resp_pkt_len = sizeof(*pkt) + sizeof(*resp);
5426
5427 err = iwx_send_cmd(sc, cmd);
5428 if (err)
5429 return err;
5430
5431 pkt = cmd->resp_pkt;
5432 if (pkt == NULL || (pkt->hdr.flags & IWX_CMD_FAILED_MSK))
5433 return EIO;
5434
5435 resp_len = iwx_rx_packet_payload_len(pkt);
5436 if (resp_len != sizeof(*resp)) {
5437 iwx_free_resp(sc, cmd);
5438 return EIO;
5439 }
5440
5441 resp = (void *)pkt->data;
5442 *status = le32toh(resp->status);
5443 iwx_free_resp(sc, cmd);
5444 return err;
5445 }
5446
5447 static int
iwx_send_cmd_pdu_status(struct iwx_softc * sc,uint32_t id,uint16_t len,const void * data,uint32_t * status)5448 iwx_send_cmd_pdu_status(struct iwx_softc *sc, uint32_t id, uint16_t len,
5449 const void *data, uint32_t *status)
5450 {
5451 struct iwx_host_cmd cmd = {
5452 .id = id,
5453 .len = { len, },
5454 .data = { data, },
5455 };
5456
5457 return iwx_send_cmd_status(sc, &cmd, status);
5458 }
5459
5460 static void
iwx_free_resp(struct iwx_softc * sc,struct iwx_host_cmd * hcmd)5461 iwx_free_resp(struct iwx_softc *sc, struct iwx_host_cmd *hcmd)
5462 {
5463 KASSERT((hcmd->flags & (IWX_CMD_WANT_RESP)) == IWX_CMD_WANT_RESP,
5464 ("hcmd flags !IWX_CMD_WANT_RESP"));
5465 free(hcmd->resp_pkt, M_DEVBUF);
5466 hcmd->resp_pkt = NULL;
5467 }
5468
5469 static void
iwx_cmd_done(struct iwx_softc * sc,int qid,int idx,int code)5470 iwx_cmd_done(struct iwx_softc *sc, int qid, int idx, int code)
5471 {
5472 struct iwx_tx_ring *ring = &sc->txq[IWX_DQA_CMD_QUEUE];
5473 struct iwx_tx_data *data;
5474
5475 if (qid != IWX_DQA_CMD_QUEUE) {
5476 return; /* Not a command ack. */
5477 }
5478
5479 data = &ring->data[idx];
5480
5481 if (data->m != NULL) {
5482 bus_dmamap_sync(ring->data_dmat, data->map,
5483 BUS_DMASYNC_POSTWRITE);
5484 bus_dmamap_unload(ring->data_dmat, data->map);
5485 m_freem(data->m);
5486 data->m = NULL;
5487 }
5488 wakeup(&ring->desc[idx]);
5489
5490 DPRINTF(("%s: command 0x%x done\n", __func__, code));
5491 if (ring->queued == 0) {
5492 DPRINTF(("%s: unexpected firmware response to command 0x%x\n",
5493 DEVNAME(sc), code));
5494 } else if (ring->queued > 0)
5495 ring->queued--;
5496 }
5497
5498 static uint32_t
iwx_fw_rateidx_ofdm(uint8_t rval)5499 iwx_fw_rateidx_ofdm(uint8_t rval)
5500 {
5501 /* Firmware expects indices which match our 11a rate set. */
5502 const struct ieee80211_rateset *rs = &ieee80211_std_rateset_11a;
5503 int i;
5504
5505 for (i = 0; i < rs->rs_nrates; i++) {
5506 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rval)
5507 return i;
5508 }
5509
5510 return 0;
5511 }
5512
5513 static uint32_t
iwx_fw_rateidx_cck(uint8_t rval)5514 iwx_fw_rateidx_cck(uint8_t rval)
5515 {
5516 /* Firmware expects indices which match our 11b rate set. */
5517 const struct ieee80211_rateset *rs = &ieee80211_std_rateset_11b;
5518 int i;
5519
5520 for (i = 0; i < rs->rs_nrates; i++) {
5521 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rval)
5522 return i;
5523 }
5524
5525 return 0;
5526 }
5527
5528 static int
iwx_min_basic_rate(struct ieee80211com * ic)5529 iwx_min_basic_rate(struct ieee80211com *ic)
5530 {
5531 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
5532 struct ieee80211_node *ni = vap->iv_bss;
5533 struct ieee80211_rateset *rs = &ni->ni_rates;
5534 struct ieee80211_channel *c = ni->ni_chan;
5535 int i, min, rval;
5536
5537 min = -1;
5538
5539 if (c == IEEE80211_CHAN_ANYC) {
5540 printf("%s: channel is IEEE80211_CHAN_ANYC\n", __func__);
5541 return -1;
5542 }
5543
5544 for (i = 0; i < rs->rs_nrates; i++) {
5545 if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0)
5546 continue;
5547 rval = (rs->rs_rates[i] & IEEE80211_RATE_VAL);
5548 if (min == -1)
5549 min = rval;
5550 else if (rval < min)
5551 min = rval;
5552 }
5553
5554 /* Default to 1 Mbit/s on 2GHz and 6 Mbit/s on 5GHz. */
5555 if (min == -1)
5556 min = IEEE80211_IS_CHAN_2GHZ(c) ? 2 : 12;
5557
5558 return min;
5559 }
5560
5561 /*
5562 * Determine the Tx command flags and Tx rate+flags to use.
5563 * Return the selected Tx rate.
5564 */
5565 static const struct iwx_rate *
iwx_tx_fill_cmd(struct iwx_softc * sc,struct iwx_node * in,struct ieee80211_frame * wh,uint16_t * flags,uint32_t * rate_n_flags,struct mbuf * m)5566 iwx_tx_fill_cmd(struct iwx_softc *sc, struct iwx_node *in,
5567 struct ieee80211_frame *wh, uint16_t *flags, uint32_t *rate_n_flags,
5568 struct mbuf *m)
5569 {
5570 struct ieee80211com *ic = &sc->sc_ic;
5571 struct ieee80211_node *ni = &in->in_ni;
5572 struct ieee80211_rateset *rs = &ni->ni_rates;
5573 const struct iwx_rate *rinfo = NULL;
5574 int type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
5575 int ridx = iwx_min_basic_rate(ic);
5576 int min_ridx, rate_flags;
5577 uint8_t rval;
5578
5579 /* We're in the process of clearing the node, no channel already */
5580 if (ridx == -1)
5581 return NULL;
5582
5583 min_ridx = iwx_rval2ridx(ridx);
5584
5585 *flags = 0;
5586
5587 if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
5588 type != IEEE80211_FC0_TYPE_DATA) {
5589 /* for non-data, use the lowest supported rate */
5590 ridx = min_ridx;
5591 *flags |= IWX_TX_FLAGS_CMD_RATE;
5592 } else if (ni->ni_flags & IEEE80211_NODE_VHT) {
5593 /* TODO: VHT - the ridx / rate array doesn't have VHT rates yet */
5594 ridx = iwx_min_basic_rate(ic);
5595 } else if (ni->ni_flags & IEEE80211_NODE_HT) {
5596 ridx = iwx_mcs2ridx[ieee80211_node_get_txrate_dot11rate(ni)
5597 & ~IEEE80211_RATE_MCS];
5598 } else {
5599 rval = (rs->rs_rates[ieee80211_node_get_txrate_dot11rate(ni)]
5600 & IEEE80211_RATE_VAL);
5601 ridx = iwx_rval2ridx(rval);
5602 if (ridx < min_ridx)
5603 ridx = min_ridx;
5604 }
5605
5606 if (m->m_flags & M_EAPOL)
5607 *flags |= IWX_TX_FLAGS_HIGH_PRI;
5608
5609 rinfo = &iwx_rates[ridx];
5610
5611 /*
5612 * Do not fill rate_n_flags if firmware controls the Tx rate.
5613 * For data frames we rely on Tx rate scaling in firmware by default.
5614 */
5615 if ((*flags & IWX_TX_FLAGS_CMD_RATE) == 0) {
5616 *rate_n_flags = 0;
5617 return rinfo;
5618 }
5619
5620 /*
5621 * Forcing a CCK/OFDM legacy rate is important for management frames.
5622 * Association will only succeed if we do this correctly.
5623 */
5624
5625 IWX_DPRINTF(sc, IWX_DEBUG_TXRATE,"%s%d:: min_ridx=%i\n", __func__, __LINE__, min_ridx);
5626 IWX_DPRINTF(sc, IWX_DEBUG_TXRATE, "%s:%d: ridx=%i\n", __func__, __LINE__, ridx);
5627 rate_flags = IWX_RATE_MCS_ANT_A_MSK;
5628 if (IWX_RIDX_IS_CCK(ridx)) {
5629 if (sc->sc_rate_n_flags_version >= 2)
5630 rate_flags |= IWX_RATE_MCS_CCK_MSK;
5631 else
5632 rate_flags |= IWX_RATE_MCS_CCK_MSK_V1;
5633 } else if (sc->sc_rate_n_flags_version >= 2)
5634 rate_flags |= IWX_RATE_MCS_LEGACY_OFDM_MSK;
5635
5636 rval = (rs->rs_rates[ieee80211_node_get_txrate_dot11rate(ni)]
5637 & IEEE80211_RATE_VAL);
5638 IWX_DPRINTF(sc, IWX_DEBUG_TXRATE, "%s:%d: rval=%i dot11 %d\n", __func__, __LINE__,
5639 rval, rs->rs_rates[ieee80211_node_get_txrate_dot11rate(ni)]);
5640
5641 if (sc->sc_rate_n_flags_version >= 2) {
5642 if (rate_flags & IWX_RATE_MCS_LEGACY_OFDM_MSK) {
5643 rate_flags |= (iwx_fw_rateidx_ofdm(rval) &
5644 IWX_RATE_LEGACY_RATE_MSK);
5645 } else {
5646 rate_flags |= (iwx_fw_rateidx_cck(rval) &
5647 IWX_RATE_LEGACY_RATE_MSK);
5648 }
5649 } else
5650 rate_flags |= rinfo->plcp;
5651
5652 *rate_n_flags = rate_flags;
5653 IWX_DPRINTF(sc, IWX_DEBUG_TXRATE, "%s:%d flags=0x%x\n",
5654 __func__, __LINE__,*flags);
5655 IWX_DPRINTF(sc, IWX_DEBUG_TXRATE, "%s:%d rate_n_flags=0x%x\n",
5656 __func__, __LINE__, *rate_n_flags);
5657
5658 if (sc->sc_debug & IWX_DEBUG_TXRATE)
5659 print_ratenflags(__func__, __LINE__,
5660 *rate_n_flags, sc->sc_rate_n_flags_version);
5661
5662 return rinfo;
5663 }
5664
5665 static void
iwx_tx_update_byte_tbl(struct iwx_softc * sc,struct iwx_tx_ring * txq,int idx,uint16_t byte_cnt,uint16_t num_tbs)5666 iwx_tx_update_byte_tbl(struct iwx_softc *sc, struct iwx_tx_ring *txq,
5667 int idx, uint16_t byte_cnt, uint16_t num_tbs)
5668 {
5669 uint8_t filled_tfd_size, num_fetch_chunks;
5670 uint16_t len = byte_cnt;
5671 uint16_t bc_ent;
5672
5673 filled_tfd_size = offsetof(struct iwx_tfh_tfd, tbs) +
5674 num_tbs * sizeof(struct iwx_tfh_tb);
5675 /*
5676 * filled_tfd_size contains the number of filled bytes in the TFD.
5677 * Dividing it by 64 will give the number of chunks to fetch
5678 * to SRAM- 0 for one chunk, 1 for 2 and so on.
5679 * If, for example, TFD contains only 3 TBs then 32 bytes
5680 * of the TFD are used, and only one chunk of 64 bytes should
5681 * be fetched
5682 */
5683 num_fetch_chunks = howmany(filled_tfd_size, 64) - 1;
5684
5685 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {
5686 struct iwx_gen3_bc_tbl_entry *scd_bc_tbl = txq->bc_tbl.vaddr;
5687 /* Starting from AX210, the HW expects bytes */
5688 bc_ent = htole16(len | (num_fetch_chunks << 14));
5689 scd_bc_tbl[idx].tfd_offset = bc_ent;
5690 } else {
5691 struct iwx_agn_scd_bc_tbl *scd_bc_tbl = txq->bc_tbl.vaddr;
5692 /* Before AX210, the HW expects DW */
5693 len = howmany(len, 4);
5694 bc_ent = htole16(len | (num_fetch_chunks << 12));
5695 scd_bc_tbl->tfd_offset[idx] = bc_ent;
5696 }
5697
5698 bus_dmamap_sync(sc->sc_dmat, txq->bc_tbl.map, BUS_DMASYNC_PREWRITE);
5699 }
5700
5701 static int
iwx_tx(struct iwx_softc * sc,struct mbuf * m,struct ieee80211_node * ni)5702 iwx_tx(struct iwx_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
5703 {
5704 struct ieee80211com *ic = &sc->sc_ic;
5705 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
5706 struct iwx_node *in = (void *)ni;
5707 struct iwx_tx_ring *ring;
5708 struct iwx_tx_data *data;
5709 struct iwx_tfh_tfd *desc;
5710 struct iwx_device_cmd *cmd;
5711 struct ieee80211_frame *wh;
5712 struct ieee80211_key *k = NULL;
5713 const struct iwx_rate *rinfo;
5714 uint64_t paddr;
5715 u_int hdrlen;
5716 uint32_t rate_n_flags;
5717 uint16_t num_tbs, flags, offload_assist = 0;
5718 int i, totlen, err, pad, qid;
5719 #define IWM_MAX_SCATTER 20
5720 bus_dma_segment_t *seg, segs[IWM_MAX_SCATTER];
5721 int nsegs;
5722 struct mbuf *m1;
5723 size_t txcmd_size;
5724
5725 IWX_ASSERT_LOCKED(sc);
5726
5727 wh = mtod(m, struct ieee80211_frame *);
5728 hdrlen = ieee80211_anyhdrsize(wh);
5729
5730 qid = sc->first_data_qid;
5731
5732 /* Put QoS frames on the data queue which maps to their TID. */
5733 if (IEEE80211_QOS_HAS_SEQ(wh)) {
5734 uint16_t qos = ieee80211_gettid(wh);
5735 uint8_t tid = qos & IEEE80211_QOS_TID;
5736 struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[tid];
5737
5738 /*
5739 * Note: we're currently putting all frames into one queue
5740 * except for A-MPDU queues. We should be able to choose
5741 * other WME queues but first we need to verify they've been
5742 * correctly setup for data.
5743 */
5744
5745 /*
5746 * Only QoS data goes into an A-MPDU queue;
5747 * don't add QoS null, the other data types, etc.
5748 */
5749 if (IEEE80211_AMPDU_RUNNING(tap) &&
5750 IEEE80211_IS_QOSDATA(wh) &&
5751 !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
5752 sc->aggqid[tid] != 0) {
5753 qid = sc->aggqid[tid];
5754 }
5755 }
5756
5757 ring = &sc->txq[qid];
5758 desc = &ring->desc[ring->cur];
5759 memset(desc, 0, sizeof(*desc));
5760 data = &ring->data[ring->cur];
5761
5762 cmd = &ring->cmd[ring->cur];
5763 cmd->hdr.code = IWX_TX_CMD;
5764 cmd->hdr.flags = 0;
5765 cmd->hdr.qid = ring->qid;
5766 cmd->hdr.idx = ring->cur;
5767
5768 rinfo = iwx_tx_fill_cmd(sc, in, wh, &flags, &rate_n_flags, m);
5769 if (rinfo == NULL)
5770 return EINVAL;
5771
5772 /* Offloaded sequence number assignment; non-AMPDU case */
5773 if ((m->m_flags & M_AMPDU_MPDU) == 0)
5774 ieee80211_output_seqno_assign(ni, -1, m);
5775
5776 /* Radiotap */
5777 if (ieee80211_radiotap_active_vap(vap)) {
5778 struct iwx_tx_radiotap_header *tap = &sc->sc_txtap;
5779
5780 tap->wt_flags = 0;
5781 tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq);
5782 tap->wt_chan_flags = htole16(ni->ni_chan->ic_flags);
5783 tap->wt_rate = rinfo->rate;
5784 if (k != NULL)
5785 tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
5786 ieee80211_radiotap_tx(vap, m);
5787 }
5788
5789 /* Encrypt - CCMP via direct HW path, TKIP/WEP indirected openbsd-style for now */
5790 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
5791 k = ieee80211_crypto_get_txkey(ni, m);
5792 if (k == NULL) {
5793 printf("%s: k is NULL!\n", __func__);
5794 m_freem(m);
5795 return (ENOBUFS);
5796 } else if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_AES_CCM) {
5797 k->wk_keytsc++;
5798 } else {
5799 k->wk_cipher->ic_encap(k, m);
5800
5801 /* 802.11 headers may have moved */
5802 wh = mtod(m, struct ieee80211_frame *);
5803 flags |= IWX_TX_FLAGS_ENCRYPT_DIS;
5804 }
5805 } else
5806 flags |= IWX_TX_FLAGS_ENCRYPT_DIS;
5807
5808 totlen = m->m_pkthdr.len;
5809
5810 if (hdrlen & 3) {
5811 /* First segment length must be a multiple of 4. */
5812 pad = 4 - (hdrlen & 3);
5813 offload_assist |= IWX_TX_CMD_OFFLD_PAD;
5814 } else
5815 pad = 0;
5816
5817 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {
5818 struct iwx_tx_cmd_gen3 *tx = (void *)cmd->data;
5819 memset(tx, 0, sizeof(*tx));
5820 tx->len = htole16(totlen);
5821 tx->offload_assist = htole32(offload_assist);
5822 tx->flags = htole16(flags);
5823 tx->rate_n_flags = htole32(rate_n_flags);
5824 memcpy(tx->hdr, wh, hdrlen);
5825 txcmd_size = sizeof(*tx);
5826 } else {
5827 struct iwx_tx_cmd_gen2 *tx = (void *)cmd->data;
5828 memset(tx, 0, sizeof(*tx));
5829 tx->len = htole16(totlen);
5830 tx->offload_assist = htole16(offload_assist);
5831 tx->flags = htole32(flags);
5832 tx->rate_n_flags = htole32(rate_n_flags);
5833 memcpy(tx->hdr, wh, hdrlen);
5834 txcmd_size = sizeof(*tx);
5835 }
5836
5837 /* Trim 802.11 header. */
5838 m_adj(m, hdrlen);
5839
5840 err = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m, segs,
5841 &nsegs, BUS_DMA_NOWAIT);
5842 if (err && err != EFBIG) {
5843 printf("%s: can't map mbuf (error %d)\n", DEVNAME(sc), err);
5844 m_freem(m);
5845 return err;
5846 }
5847 if (err) {
5848 /* Too many DMA segments, linearize mbuf. */
5849 m1 = m_collapse(m, M_NOWAIT, IWM_MAX_SCATTER - 2);
5850 if (m1 == NULL) {
5851 printf("%s: could not defrag mbufs\n", __func__);
5852 m_freem(m);
5853 return (ENOBUFS);
5854 }
5855 m = m1;
5856 err = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m,
5857 segs, &nsegs, BUS_DMA_NOWAIT);
5858 if (err) {
5859 printf("%s: can't map mbuf (error %d)\n", __func__,
5860 err);
5861 m_freem(m);
5862 return (err);
5863 }
5864 }
5865 data->m = m;
5866 data->in = in;
5867
5868 /* Fill TX descriptor. */
5869 num_tbs = 2 + nsegs;
5870 desc->num_tbs = htole16(num_tbs);
5871
5872 desc->tbs[0].tb_len = htole16(IWX_FIRST_TB_SIZE);
5873 paddr = htole64(data->cmd_paddr);
5874 memcpy(&desc->tbs[0].addr, &paddr, sizeof(paddr));
5875 #if __SIZEOF_SIZE_T__ > 4
5876 if (data->cmd_paddr >> 32 != (data->cmd_paddr +
5877 le32toh(desc->tbs[0].tb_len)) >> 32)
5878 DPRINTF(("%s: TB0 crosses 32bit boundary\n", __func__));
5879 #endif
5880 desc->tbs[1].tb_len = htole16(sizeof(struct iwx_cmd_header) +
5881 txcmd_size + hdrlen + pad - IWX_FIRST_TB_SIZE);
5882 paddr = htole64(data->cmd_paddr + IWX_FIRST_TB_SIZE);
5883 memcpy(&desc->tbs[1].addr, &paddr, sizeof(paddr));
5884
5885 #if __SIZEOF_SIZE_T__ > 4
5886 if (data->cmd_paddr >> 32 != (data->cmd_paddr +
5887 le32toh(desc->tbs[1].tb_len)) >> 32)
5888 DPRINTF(("%s: TB1 crosses 32bit boundary\n", __func__));
5889 #endif
5890
5891 /* Other DMA segments are for data payload. */
5892 for (i = 0; i < nsegs; i++) {
5893 seg = &segs[i];
5894 desc->tbs[i + 2].tb_len = htole16(seg->ds_len);
5895 paddr = htole64(seg->ds_addr);
5896 memcpy(&desc->tbs[i + 2].addr, &paddr, sizeof(paddr));
5897 #if __SIZEOF_SIZE_T__ > 4
5898 if (data->cmd_paddr >> 32 != (data->cmd_paddr +
5899 le32toh(desc->tbs[i + 2].tb_len)) >> 32)
5900 DPRINTF(("%s: TB%d crosses 32bit boundary\n", __func__,
5901 i + 2));
5902 #endif
5903 }
5904
5905 bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREWRITE);
5906 bus_dmamap_sync(ring->cmd_dma.tag, ring->cmd_dma.map,
5907 BUS_DMASYNC_PREWRITE);
5908 bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
5909 BUS_DMASYNC_PREWRITE);
5910
5911 iwx_tx_update_byte_tbl(sc, ring, ring->cur, totlen, num_tbs);
5912
5913 /* Kick TX ring. */
5914 ring->cur = (ring->cur + 1) % IWX_TX_RING_COUNT;
5915 ring->cur_hw = (ring->cur_hw + 1) % sc->max_tfd_queue_size;
5916 IWX_WRITE(sc, IWX_HBUS_TARG_WRPTR, ring->qid << 16 | ring->cur_hw);
5917
5918 /* Mark TX ring as full if we reach a certain threshold. */
5919 if (++ring->queued > iwx_himark) {
5920 sc->qfullmsk |= 1 << ring->qid;
5921 }
5922
5923 sc->sc_tx_timer[ring->qid] = 15;
5924
5925 return 0;
5926 }
5927
5928 static int
iwx_flush_sta_tids(struct iwx_softc * sc,int sta_id,uint16_t tids)5929 iwx_flush_sta_tids(struct iwx_softc *sc, int sta_id, uint16_t tids)
5930 {
5931 struct iwx_rx_packet *pkt;
5932 struct iwx_tx_path_flush_cmd_rsp *resp;
5933 struct iwx_tx_path_flush_cmd flush_cmd = {
5934 .sta_id = htole32(sta_id),
5935 .tid_mask = htole16(tids),
5936 };
5937 struct iwx_host_cmd hcmd = {
5938 .id = IWX_TXPATH_FLUSH,
5939 .len = { sizeof(flush_cmd), },
5940 .data = { &flush_cmd, },
5941 .flags = IWX_CMD_WANT_RESP,
5942 .resp_pkt_len = sizeof(*pkt) + sizeof(*resp),
5943 };
5944 int err, resp_len, i, num_flushed_queues;
5945
5946 err = iwx_send_cmd(sc, &hcmd);
5947 if (err)
5948 return err;
5949
5950 pkt = hcmd.resp_pkt;
5951 if (!pkt || (pkt->hdr.flags & IWX_CMD_FAILED_MSK)) {
5952 err = EIO;
5953 goto out;
5954 }
5955
5956 resp_len = iwx_rx_packet_payload_len(pkt);
5957 /* Some firmware versions don't provide a response. */
5958 if (resp_len == 0)
5959 goto out;
5960 else if (resp_len != sizeof(*resp)) {
5961 err = EIO;
5962 goto out;
5963 }
5964
5965 resp = (void *)pkt->data;
5966
5967 if (le16toh(resp->sta_id) != sta_id) {
5968 err = EIO;
5969 goto out;
5970 }
5971
5972 num_flushed_queues = le16toh(resp->num_flushed_queues);
5973 if (num_flushed_queues > IWX_TX_FLUSH_QUEUE_RSP) {
5974 err = EIO;
5975 goto out;
5976 }
5977
5978 for (i = 0; i < num_flushed_queues; i++) {
5979 struct iwx_flush_queue_info *queue_info = &resp->queues[i];
5980 uint16_t tid = le16toh(queue_info->tid);
5981 uint16_t read_after = le16toh(queue_info->read_after_flush);
5982 uint16_t qid = le16toh(queue_info->queue_num);
5983 struct iwx_tx_ring *txq;
5984
5985 if (qid >= nitems(sc->txq))
5986 continue;
5987
5988 txq = &sc->txq[qid];
5989 if (tid != txq->tid)
5990 continue;
5991
5992 iwx_txq_advance(sc, txq, read_after);
5993 }
5994 out:
5995 iwx_free_resp(sc, &hcmd);
5996 return err;
5997 }
5998
5999 #define IWX_FLUSH_WAIT_MS 2000
6000
6001 static int
iwx_drain_sta(struct iwx_softc * sc,struct iwx_node * in,int drain)6002 iwx_drain_sta(struct iwx_softc *sc, struct iwx_node* in, int drain)
6003 {
6004 struct iwx_add_sta_cmd cmd;
6005 int err;
6006 uint32_t status;
6007
6008 memset(&cmd, 0, sizeof(cmd));
6009 cmd.mac_id_n_color = htole32(IWX_FW_CMD_ID_AND_COLOR(in->in_id,
6010 in->in_color));
6011 cmd.sta_id = IWX_STATION_ID;
6012 cmd.add_modify = IWX_STA_MODE_MODIFY;
6013 cmd.station_flags = drain ? htole32(IWX_STA_FLG_DRAIN_FLOW) : 0;
6014 cmd.station_flags_msk = htole32(IWX_STA_FLG_DRAIN_FLOW);
6015
6016 status = IWX_ADD_STA_SUCCESS;
6017 err = iwx_send_cmd_pdu_status(sc, IWX_ADD_STA,
6018 sizeof(cmd), &cmd, &status);
6019 if (err) {
6020 printf("%s: could not update sta (error %d)\n",
6021 DEVNAME(sc), err);
6022 return err;
6023 }
6024
6025 switch (status & IWX_ADD_STA_STATUS_MASK) {
6026 case IWX_ADD_STA_SUCCESS:
6027 break;
6028 default:
6029 err = EIO;
6030 printf("%s: Couldn't %s draining for station\n",
6031 DEVNAME(sc), drain ? "enable" : "disable");
6032 break;
6033 }
6034
6035 return err;
6036 }
6037
6038 static int
iwx_flush_sta(struct iwx_softc * sc,struct iwx_node * in)6039 iwx_flush_sta(struct iwx_softc *sc, struct iwx_node *in)
6040 {
6041 int err;
6042
6043 IWX_ASSERT_LOCKED(sc);
6044
6045 sc->sc_flags |= IWX_FLAG_TXFLUSH;
6046
6047 err = iwx_drain_sta(sc, in, 1);
6048 if (err)
6049 goto done;
6050
6051 err = iwx_flush_sta_tids(sc, IWX_STATION_ID, 0xffff);
6052 if (err) {
6053 printf("%s: could not flush Tx path (error %d)\n",
6054 DEVNAME(sc), err);
6055 goto done;
6056 }
6057
6058 /*
6059 * XXX-THJ: iwx_wait_tx_queues_empty was here, but it was a nope in the
6060 * fc drive rand has has been replaced in OpenBSD.
6061 */
6062
6063 err = iwx_drain_sta(sc, in, 0);
6064 done:
6065 sc->sc_flags &= ~IWX_FLAG_TXFLUSH;
6066 return err;
6067 }
6068
6069 #define IWX_POWER_KEEP_ALIVE_PERIOD_SEC 25
6070
6071 static int
iwx_beacon_filter_send_cmd(struct iwx_softc * sc,struct iwx_beacon_filter_cmd * cmd)6072 iwx_beacon_filter_send_cmd(struct iwx_softc *sc,
6073 struct iwx_beacon_filter_cmd *cmd)
6074 {
6075 return iwx_send_cmd_pdu(sc, IWX_REPLY_BEACON_FILTERING_CMD,
6076 0, sizeof(struct iwx_beacon_filter_cmd), cmd);
6077 }
6078
6079 static int
iwx_update_beacon_abort(struct iwx_softc * sc,struct iwx_node * in,int enable)6080 iwx_update_beacon_abort(struct iwx_softc *sc, struct iwx_node *in, int enable)
6081 {
6082 struct iwx_beacon_filter_cmd cmd = {
6083 IWX_BF_CMD_CONFIG_DEFAULTS,
6084 .bf_enable_beacon_filter = htole32(1),
6085 .ba_enable_beacon_abort = htole32(enable),
6086 };
6087
6088 if (!sc->sc_bf.bf_enabled)
6089 return 0;
6090
6091 sc->sc_bf.ba_enabled = enable;
6092 return iwx_beacon_filter_send_cmd(sc, &cmd);
6093 }
6094
6095 static void
iwx_power_build_cmd(struct iwx_softc * sc,struct iwx_node * in,struct iwx_mac_power_cmd * cmd)6096 iwx_power_build_cmd(struct iwx_softc *sc, struct iwx_node *in,
6097 struct iwx_mac_power_cmd *cmd)
6098 {
6099 struct ieee80211com *ic = &sc->sc_ic;
6100 struct ieee80211_node *ni = &in->in_ni;
6101 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
6102 int dtim_period, dtim_msec, keep_alive;
6103
6104 cmd->id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(in->in_id,
6105 in->in_color));
6106 if (vap->iv_dtim_period)
6107 dtim_period = vap->iv_dtim_period;
6108 else
6109 dtim_period = 1;
6110
6111 /*
6112 * Regardless of power management state the driver must set
6113 * keep alive period. FW will use it for sending keep alive NDPs
6114 * immediately after association. Check that keep alive period
6115 * is at least 3 * DTIM.
6116 */
6117 dtim_msec = dtim_period * ni->ni_intval;
6118 keep_alive = MAX(3 * dtim_msec, 1000 * IWX_POWER_KEEP_ALIVE_PERIOD_SEC);
6119 keep_alive = roundup(keep_alive, 1000) / 1000;
6120 cmd->keep_alive_seconds = htole16(keep_alive);
6121
6122 if (ic->ic_opmode != IEEE80211_M_MONITOR)
6123 cmd->flags = htole16(IWX_POWER_FLAGS_POWER_SAVE_ENA_MSK);
6124 }
6125
6126 static int
iwx_power_mac_update_mode(struct iwx_softc * sc,struct iwx_node * in)6127 iwx_power_mac_update_mode(struct iwx_softc *sc, struct iwx_node *in)
6128 {
6129 int err;
6130 int ba_enable;
6131 struct iwx_mac_power_cmd cmd;
6132
6133 memset(&cmd, 0, sizeof(cmd));
6134
6135 iwx_power_build_cmd(sc, in, &cmd);
6136
6137 err = iwx_send_cmd_pdu(sc, IWX_MAC_PM_POWER_TABLE, 0,
6138 sizeof(cmd), &cmd);
6139 if (err != 0)
6140 return err;
6141
6142 ba_enable = !!(cmd.flags &
6143 htole16(IWX_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK));
6144 return iwx_update_beacon_abort(sc, in, ba_enable);
6145 }
6146
6147 static int
iwx_power_update_device(struct iwx_softc * sc)6148 iwx_power_update_device(struct iwx_softc *sc)
6149 {
6150 struct iwx_device_power_cmd cmd = { };
6151 struct ieee80211com *ic = &sc->sc_ic;
6152
6153 if (ic->ic_opmode != IEEE80211_M_MONITOR)
6154 cmd.flags = htole16(IWX_DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
6155
6156 return iwx_send_cmd_pdu(sc,
6157 IWX_POWER_TABLE_CMD, 0, sizeof(cmd), &cmd);
6158 }
6159 #if 0
6160 static int
6161 iwx_enable_beacon_filter(struct iwx_softc *sc, struct iwx_node *in)
6162 {
6163 struct iwx_beacon_filter_cmd cmd = {
6164 IWX_BF_CMD_CONFIG_DEFAULTS,
6165 .bf_enable_beacon_filter = htole32(1),
6166 .ba_enable_beacon_abort = htole32(sc->sc_bf.ba_enabled),
6167 };
6168 int err;
6169
6170 err = iwx_beacon_filter_send_cmd(sc, &cmd);
6171 if (err == 0)
6172 sc->sc_bf.bf_enabled = 1;
6173
6174 return err;
6175 }
6176 #endif
6177 static int
iwx_disable_beacon_filter(struct iwx_softc * sc)6178 iwx_disable_beacon_filter(struct iwx_softc *sc)
6179 {
6180 struct iwx_beacon_filter_cmd cmd;
6181 int err;
6182
6183 memset(&cmd, 0, sizeof(cmd));
6184
6185 err = iwx_beacon_filter_send_cmd(sc, &cmd);
6186 if (err == 0)
6187 sc->sc_bf.bf_enabled = 0;
6188
6189 return err;
6190 }
6191
6192 static int
iwx_add_sta_cmd(struct iwx_softc * sc,struct iwx_node * in,int update)6193 iwx_add_sta_cmd(struct iwx_softc *sc, struct iwx_node *in, int update)
6194 {
6195 struct iwx_add_sta_cmd add_sta_cmd;
6196 int err, i;
6197 uint32_t status, aggsize;
6198 const uint32_t max_aggsize = (IWX_STA_FLG_MAX_AGG_SIZE_64K >>
6199 IWX_STA_FLG_MAX_AGG_SIZE_SHIFT);
6200 struct ieee80211com *ic = &sc->sc_ic;
6201 struct ieee80211_node *ni = &in->in_ni;
6202 struct ieee80211_htrateset *htrs = &ni->ni_htrates;
6203
6204 if (!update && (sc->sc_flags & IWX_FLAG_STA_ACTIVE))
6205 panic("STA already added");
6206
6207 memset(&add_sta_cmd, 0, sizeof(add_sta_cmd));
6208
6209 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
6210 add_sta_cmd.sta_id = IWX_MONITOR_STA_ID;
6211 add_sta_cmd.station_type = IWX_STA_GENERAL_PURPOSE;
6212 } else {
6213 add_sta_cmd.sta_id = IWX_STATION_ID;
6214 add_sta_cmd.station_type = IWX_STA_LINK;
6215 }
6216 add_sta_cmd.mac_id_n_color
6217 = htole32(IWX_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));
6218 if (!update) {
6219 if (ic->ic_opmode == IEEE80211_M_MONITOR)
6220 IEEE80211_ADDR_COPY(&add_sta_cmd.addr,
6221 etheranyaddr);
6222 else
6223 IEEE80211_ADDR_COPY(&add_sta_cmd.addr,
6224 in->in_macaddr);
6225 }
6226 DPRINTF(("%s: add_sta_cmd.addr=%s\n", __func__,
6227 ether_sprintf(add_sta_cmd.addr)));
6228 add_sta_cmd.add_modify = update ? 1 : 0;
6229 add_sta_cmd.station_flags_msk
6230 |= htole32(IWX_STA_FLG_FAT_EN_MSK | IWX_STA_FLG_MIMO_EN_MSK);
6231
6232 if (in->in_ni.ni_flags & IEEE80211_NODE_HT) {
6233 add_sta_cmd.station_flags_msk
6234 |= htole32(IWX_STA_FLG_MAX_AGG_SIZE_MSK |
6235 IWX_STA_FLG_AGG_MPDU_DENS_MSK);
6236
6237 if (iwx_mimo_enabled(sc)) {
6238 if (ni->ni_flags & IEEE80211_NODE_VHT) {
6239 add_sta_cmd.station_flags |=
6240 htole32(IWX_STA_FLG_MIMO_EN_MIMO2);
6241 } else {
6242 int hasmimo = 0;
6243 for (i = 0; i < htrs->rs_nrates; i++) {
6244 if (htrs->rs_rates[i] > 7) {
6245 hasmimo = 1;
6246 break;
6247 }
6248 }
6249 if (hasmimo) {
6250 add_sta_cmd.station_flags |=
6251 htole32(IWX_STA_FLG_MIMO_EN_MIMO2);
6252 }
6253 }
6254 }
6255
6256 if (ni->ni_flags & IEEE80211_NODE_HT &&
6257 IEEE80211_IS_CHAN_HT40(ni->ni_chan)) {
6258 add_sta_cmd.station_flags |= htole32(
6259 IWX_STA_FLG_FAT_EN_40MHZ);
6260 }
6261
6262
6263 if (ni->ni_flags & IEEE80211_NODE_VHT) {
6264 if (IEEE80211_IS_CHAN_VHT80(ni->ni_chan)) {
6265 add_sta_cmd.station_flags |= htole32(
6266 IWX_STA_FLG_FAT_EN_80MHZ);
6267 }
6268 // XXX-misha: TODO get real ampdu size
6269 aggsize = max_aggsize;
6270 } else {
6271 aggsize = _IEEE80211_MASKSHIFT(le16toh(ni->ni_htparam),
6272 IEEE80211_HTCAP_MAXRXAMPDU);
6273 }
6274
6275 if (aggsize > max_aggsize)
6276 aggsize = max_aggsize;
6277 add_sta_cmd.station_flags |= htole32((aggsize <<
6278 IWX_STA_FLG_MAX_AGG_SIZE_SHIFT) &
6279 IWX_STA_FLG_MAX_AGG_SIZE_MSK);
6280
6281 switch (_IEEE80211_MASKSHIFT(le16toh(ni->ni_htparam),
6282 IEEE80211_HTCAP_MPDUDENSITY)) {
6283 case IEEE80211_HTCAP_MPDUDENSITY_2:
6284 add_sta_cmd.station_flags
6285 |= htole32(IWX_STA_FLG_AGG_MPDU_DENS_2US);
6286 break;
6287 case IEEE80211_HTCAP_MPDUDENSITY_4:
6288 add_sta_cmd.station_flags
6289 |= htole32(IWX_STA_FLG_AGG_MPDU_DENS_4US);
6290 break;
6291 case IEEE80211_HTCAP_MPDUDENSITY_8:
6292 add_sta_cmd.station_flags
6293 |= htole32(IWX_STA_FLG_AGG_MPDU_DENS_8US);
6294 break;
6295 case IEEE80211_HTCAP_MPDUDENSITY_16:
6296 add_sta_cmd.station_flags
6297 |= htole32(IWX_STA_FLG_AGG_MPDU_DENS_16US);
6298 break;
6299 default:
6300 break;
6301 }
6302 }
6303
6304 status = IWX_ADD_STA_SUCCESS;
6305 err = iwx_send_cmd_pdu_status(sc, IWX_ADD_STA, sizeof(add_sta_cmd),
6306 &add_sta_cmd, &status);
6307 if (!err && (status & IWX_ADD_STA_STATUS_MASK) != IWX_ADD_STA_SUCCESS)
6308 err = EIO;
6309
6310 return err;
6311 }
6312
6313 static int
iwx_rm_sta_cmd(struct iwx_softc * sc,struct iwx_node * in)6314 iwx_rm_sta_cmd(struct iwx_softc *sc, struct iwx_node *in)
6315 {
6316 struct ieee80211com *ic = &sc->sc_ic;
6317 struct iwx_rm_sta_cmd rm_sta_cmd;
6318 int err;
6319
6320 if ((sc->sc_flags & IWX_FLAG_STA_ACTIVE) == 0)
6321 panic("sta already removed");
6322
6323 memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd));
6324 if (ic->ic_opmode == IEEE80211_M_MONITOR)
6325 rm_sta_cmd.sta_id = IWX_MONITOR_STA_ID;
6326 else
6327 rm_sta_cmd.sta_id = IWX_STATION_ID;
6328
6329 err = iwx_send_cmd_pdu(sc, IWX_REMOVE_STA, 0, sizeof(rm_sta_cmd),
6330 &rm_sta_cmd);
6331
6332 return err;
6333 }
6334
6335 static int
iwx_rm_sta(struct iwx_softc * sc,struct iwx_node * in)6336 iwx_rm_sta(struct iwx_softc *sc, struct iwx_node *in)
6337 {
6338 int err, i, cmd_ver;
6339
6340 err = iwx_flush_sta(sc, in);
6341 if (err) {
6342 printf("%s: could not flush Tx path (error %d)\n",
6343 DEVNAME(sc), err);
6344 return err;
6345 }
6346
6347 /*
6348 * New SCD_QUEUE_CONFIG API requires explicit queue removal
6349 * before a station gets removed.
6350 */
6351 cmd_ver = iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP,
6352 IWX_SCD_QUEUE_CONFIG_CMD);
6353 if (cmd_ver != 0 && cmd_ver != IWX_FW_CMD_VER_UNKNOWN) {
6354 err = iwx_disable_mgmt_queue(sc);
6355 if (err)
6356 return err;
6357 for (i = IWX_FIRST_AGG_TX_QUEUE;
6358 i < IWX_LAST_AGG_TX_QUEUE; i++) {
6359 struct iwx_tx_ring *ring = &sc->txq[i];
6360 if ((sc->qenablemsk & (1 << i)) == 0)
6361 continue;
6362 err = iwx_disable_txq(sc, IWX_STATION_ID,
6363 ring->qid, ring->tid);
6364 if (err) {
6365 printf("%s: could not disable Tx queue %d "
6366 "(error %d)\n", DEVNAME(sc), ring->qid,
6367 err);
6368 return err;
6369 }
6370 }
6371 }
6372
6373 err = iwx_rm_sta_cmd(sc, in);
6374 if (err) {
6375 printf("%s: could not remove STA (error %d)\n",
6376 DEVNAME(sc), err);
6377 return err;
6378 }
6379
6380 in->in_flags = 0;
6381
6382 sc->sc_rx_ba_sessions = 0;
6383 sc->ba_rx.start_tidmask = 0;
6384 sc->ba_rx.stop_tidmask = 0;
6385 memset(sc->aggqid, 0, sizeof(sc->aggqid));
6386 sc->ba_tx.start_tidmask = 0;
6387 sc->ba_tx.stop_tidmask = 0;
6388 for (i = IWX_FIRST_AGG_TX_QUEUE; i < IWX_LAST_AGG_TX_QUEUE; i++)
6389 sc->qenablemsk &= ~(1 << i);
6390
6391 #if 0
6392 for (i = 0; i < IEEE80211_NUM_TID; i++) {
6393 struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[i];
6394 if (ba->ba_state != IEEE80211_BA_AGREED)
6395 continue;
6396 ieee80211_delba_request(ic, ni, 0, 1, i);
6397 }
6398 #endif
6399 /* Clear ampdu rx state (GOS-1525) */
6400 for (i = 0; i < IWX_MAX_TID_COUNT; i++) {
6401 struct iwx_rx_ba *ba = &sc->ni_rx_ba[i];
6402 ba->ba_flags = 0;
6403 }
6404
6405 return 0;
6406 }
6407
6408 static uint8_t
iwx_umac_scan_fill_channels(struct iwx_softc * sc,struct iwx_scan_channel_cfg_umac * chan,size_t chan_nitems,int n_ssids,uint32_t channel_cfg_flags)6409 iwx_umac_scan_fill_channels(struct iwx_softc *sc,
6410 struct iwx_scan_channel_cfg_umac *chan, size_t chan_nitems,
6411 int n_ssids, uint32_t channel_cfg_flags)
6412 {
6413 struct ieee80211com *ic = &sc->sc_ic;
6414 struct ieee80211_scan_state *ss = ic->ic_scan;
6415 struct ieee80211_channel *c;
6416 uint8_t nchan;
6417 int j;
6418
6419 for (nchan = j = 0;
6420 j < ss->ss_last &&
6421 nchan < sc->sc_capa_n_scan_channels;
6422 j++) {
6423 uint8_t channel_num;
6424
6425 c = ss->ss_chans[j];
6426 channel_num = ieee80211_mhz2ieee(c->ic_freq, 0);
6427 if (isset(sc->sc_ucode_api,
6428 IWX_UCODE_TLV_API_SCAN_EXT_CHAN_VER)) {
6429 chan->v2.channel_num = channel_num;
6430 if (IEEE80211_IS_CHAN_2GHZ(c))
6431 chan->v2.band = IWX_PHY_BAND_24;
6432 else
6433 chan->v2.band = IWX_PHY_BAND_5;
6434 chan->v2.iter_count = 1;
6435 chan->v2.iter_interval = 0;
6436 } else {
6437 chan->v1.channel_num = channel_num;
6438 chan->v1.iter_count = 1;
6439 chan->v1.iter_interval = htole16(0);
6440 }
6441 chan->flags |= htole32(channel_cfg_flags);
6442 chan++;
6443 nchan++;
6444 }
6445
6446 return nchan;
6447 }
6448
6449 static int
iwx_fill_probe_req(struct iwx_softc * sc,struct iwx_scan_probe_req * preq)6450 iwx_fill_probe_req(struct iwx_softc *sc, struct iwx_scan_probe_req *preq)
6451 {
6452 struct ieee80211com *ic = &sc->sc_ic;
6453 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
6454 struct ieee80211_frame *wh = (struct ieee80211_frame *)preq->buf;
6455 struct ieee80211_rateset *rs;
6456 size_t remain = sizeof(preq->buf);
6457 uint8_t *frm, *pos;
6458
6459 memset(preq, 0, sizeof(*preq));
6460
6461 if (remain < sizeof(*wh) + 2)
6462 return ENOBUFS;
6463
6464 /*
6465 * Build a probe request frame. Most of the following code is a
6466 * copy & paste of what is done in net80211.
6467 */
6468 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
6469 IEEE80211_FC0_SUBTYPE_PROBE_REQ;
6470 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
6471 IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr);
6472 IEEE80211_ADDR_COPY(wh->i_addr2, vap ? vap->iv_myaddr : ic->ic_macaddr);
6473 IEEE80211_ADDR_COPY(wh->i_addr3, etherbroadcastaddr);
6474 *(uint16_t *)&wh->i_dur[0] = 0; /* filled by HW */
6475 *(uint16_t *)&wh->i_seq[0] = 0; /* filled by HW */
6476
6477 frm = (uint8_t *)(wh + 1);
6478 *frm++ = IEEE80211_ELEMID_SSID;
6479 *frm++ = 0;
6480 /* hardware inserts SSID */
6481
6482 /* Tell the firmware where the MAC header is. */
6483 preq->mac_header.offset = 0;
6484 preq->mac_header.len = htole16(frm - (uint8_t *)wh);
6485 remain -= frm - (uint8_t *)wh;
6486
6487 /* Fill in 2GHz IEs and tell firmware where they are. */
6488 rs = &ic->ic_sup_rates[IEEE80211_MODE_11G];
6489 if (rs->rs_nrates > IEEE80211_RATE_SIZE) {
6490 if (remain < 4 + rs->rs_nrates)
6491 return ENOBUFS;
6492 } else if (remain < 2 + rs->rs_nrates)
6493 return ENOBUFS;
6494 preq->band_data[0].offset = htole16(frm - (uint8_t *)wh);
6495 pos = frm;
6496 frm = ieee80211_add_rates(frm, rs);
6497 if (rs->rs_nrates > IEEE80211_RATE_SIZE)
6498 frm = ieee80211_add_xrates(frm, rs);
6499 remain -= frm - pos;
6500
6501 if (isset(sc->sc_enabled_capa,
6502 IWX_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT)) {
6503 if (remain < 3)
6504 return ENOBUFS;
6505 *frm++ = IEEE80211_ELEMID_DSPARMS;
6506 *frm++ = 1;
6507 *frm++ = 0;
6508 remain -= 3;
6509 }
6510 preq->band_data[0].len = htole16(frm - pos);
6511
6512 if (sc->sc_nvm.sku_cap_band_52GHz_enable) {
6513 /* Fill in 5GHz IEs. */
6514 rs = &ic->ic_sup_rates[IEEE80211_MODE_11A];
6515 if (rs->rs_nrates > IEEE80211_RATE_SIZE) {
6516 if (remain < 4 + rs->rs_nrates)
6517 return ENOBUFS;
6518 } else if (remain < 2 + rs->rs_nrates)
6519 return ENOBUFS;
6520 preq->band_data[1].offset = htole16(frm - (uint8_t *)wh);
6521 pos = frm;
6522 frm = ieee80211_add_rates(frm, rs);
6523 if (rs->rs_nrates > IEEE80211_RATE_SIZE)
6524 frm = ieee80211_add_xrates(frm, rs);
6525 preq->band_data[1].len = htole16(frm - pos);
6526 remain -= frm - pos;
6527 if (vap->iv_vht_flags & IEEE80211_FVHT_VHT) {
6528 if (remain < 14)
6529 return ENOBUFS;
6530 frm = ieee80211_add_vhtcap(frm, vap->iv_bss);
6531 remain -= frm - pos;
6532 preq->band_data[1].len = htole16(frm - pos);
6533 }
6534 }
6535
6536 /* Send 11n IEs on both 2GHz and 5GHz bands. */
6537 preq->common_data.offset = htole16(frm - (uint8_t *)wh);
6538 pos = frm;
6539 if (vap->iv_flags_ht & IEEE80211_FHT_HT) {
6540 if (remain < 28)
6541 return ENOBUFS;
6542 frm = ieee80211_add_htcap(frm, vap->iv_bss);
6543 /* XXX add WME info? */
6544 remain -= frm - pos;
6545 }
6546
6547 preq->common_data.len = htole16(frm - pos);
6548
6549 return 0;
6550 }
6551
6552 static int
iwx_config_umac_scan_reduced(struct iwx_softc * sc)6553 iwx_config_umac_scan_reduced(struct iwx_softc *sc)
6554 {
6555 struct iwx_scan_config scan_cfg;
6556 struct iwx_host_cmd hcmd = {
6557 .id = iwx_cmd_id(IWX_SCAN_CFG_CMD, IWX_LONG_GROUP, 0),
6558 .len[0] = sizeof(scan_cfg),
6559 .data[0] = &scan_cfg,
6560 .flags = 0,
6561 };
6562 int cmdver;
6563
6564 if (!isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_REDUCED_SCAN_CONFIG)) {
6565 printf("%s: firmware does not support reduced scan config\n",
6566 DEVNAME(sc));
6567 return ENOTSUP;
6568 }
6569
6570 memset(&scan_cfg, 0, sizeof(scan_cfg));
6571
6572 /*
6573 * SCAN_CFG version >= 5 implies that the broadcast
6574 * STA ID field is deprecated.
6575 */
6576 cmdver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_SCAN_CFG_CMD);
6577 if (cmdver == IWX_FW_CMD_VER_UNKNOWN || cmdver < 5)
6578 scan_cfg.bcast_sta_id = 0xff;
6579
6580 scan_cfg.tx_chains = htole32(iwx_fw_valid_tx_ant(sc));
6581 scan_cfg.rx_chains = htole32(iwx_fw_valid_rx_ant(sc));
6582
6583 return iwx_send_cmd(sc, &hcmd);
6584 }
6585
6586 static uint16_t
iwx_scan_umac_flags_v2(struct iwx_softc * sc,int bgscan)6587 iwx_scan_umac_flags_v2(struct iwx_softc *sc, int bgscan)
6588 {
6589 struct ieee80211com *ic = &sc->sc_ic;
6590 struct ieee80211_scan_state *ss = ic->ic_scan;
6591 uint16_t flags = 0;
6592
6593 if (ss->ss_nssid == 0) {
6594 DPRINTF(("%s: Passive scan started\n", __func__));
6595 flags |= IWX_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE;
6596 }
6597
6598 flags |= IWX_UMAC_SCAN_GEN_FLAGS_V2_PASS_ALL;
6599 flags |= IWX_UMAC_SCAN_GEN_FLAGS_V2_NTFY_ITER_COMPLETE;
6600 flags |= IWX_UMAC_SCAN_GEN_FLAGS_V2_ADAPTIVE_DWELL;
6601
6602 return flags;
6603 }
6604
6605 #define IWX_SCAN_DWELL_ACTIVE 10
6606 #define IWX_SCAN_DWELL_PASSIVE 110
6607
6608 /* adaptive dwell max budget time [TU] for full scan */
6609 #define IWX_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 300
6610 /* adaptive dwell max budget time [TU] for directed scan */
6611 #define IWX_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN 100
6612 /* adaptive dwell default high band APs number */
6613 #define IWX_SCAN_ADWELL_DEFAULT_HB_N_APS 8
6614 /* adaptive dwell default low band APs number */
6615 #define IWX_SCAN_ADWELL_DEFAULT_LB_N_APS 2
6616 /* adaptive dwell default APs number in social channels (1, 6, 11) */
6617 #define IWX_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL 10
6618 /* adaptive dwell number of APs override for p2p friendly GO channels */
6619 #define IWX_SCAN_ADWELL_N_APS_GO_FRIENDLY 10
6620 /* adaptive dwell number of APs override for social channels */
6621 #define IWX_SCAN_ADWELL_N_APS_SOCIAL_CHS 2
6622
6623 static void
iwx_scan_umac_dwell_v10(struct iwx_softc * sc,struct iwx_scan_general_params_v10 * general_params,int bgscan)6624 iwx_scan_umac_dwell_v10(struct iwx_softc *sc,
6625 struct iwx_scan_general_params_v10 *general_params, int bgscan)
6626 {
6627 uint32_t suspend_time, max_out_time;
6628 uint8_t active_dwell, passive_dwell;
6629
6630 active_dwell = IWX_SCAN_DWELL_ACTIVE;
6631 passive_dwell = IWX_SCAN_DWELL_PASSIVE;
6632
6633 general_params->adwell_default_social_chn =
6634 IWX_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL;
6635 general_params->adwell_default_2g = IWX_SCAN_ADWELL_DEFAULT_LB_N_APS;
6636 general_params->adwell_default_5g = IWX_SCAN_ADWELL_DEFAULT_HB_N_APS;
6637
6638 if (bgscan)
6639 general_params->adwell_max_budget =
6640 htole16(IWX_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN);
6641 else
6642 general_params->adwell_max_budget =
6643 htole16(IWX_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN);
6644
6645 general_params->scan_priority = htole32(IWX_SCAN_PRIORITY_EXT_6);
6646 if (bgscan) {
6647 max_out_time = htole32(120);
6648 suspend_time = htole32(120);
6649 } else {
6650 max_out_time = htole32(0);
6651 suspend_time = htole32(0);
6652 }
6653 general_params->max_out_of_time[IWX_SCAN_LB_LMAC_IDX] =
6654 htole32(max_out_time);
6655 general_params->suspend_time[IWX_SCAN_LB_LMAC_IDX] =
6656 htole32(suspend_time);
6657 general_params->max_out_of_time[IWX_SCAN_HB_LMAC_IDX] =
6658 htole32(max_out_time);
6659 general_params->suspend_time[IWX_SCAN_HB_LMAC_IDX] =
6660 htole32(suspend_time);
6661
6662 general_params->active_dwell[IWX_SCAN_LB_LMAC_IDX] = active_dwell;
6663 general_params->passive_dwell[IWX_SCAN_LB_LMAC_IDX] = passive_dwell;
6664 general_params->active_dwell[IWX_SCAN_HB_LMAC_IDX] = active_dwell;
6665 general_params->passive_dwell[IWX_SCAN_HB_LMAC_IDX] = passive_dwell;
6666 }
6667
6668 static void
iwx_scan_umac_fill_general_p_v10(struct iwx_softc * sc,struct iwx_scan_general_params_v10 * gp,uint16_t gen_flags,int bgscan)6669 iwx_scan_umac_fill_general_p_v10(struct iwx_softc *sc,
6670 struct iwx_scan_general_params_v10 *gp, uint16_t gen_flags, int bgscan)
6671 {
6672 iwx_scan_umac_dwell_v10(sc, gp, bgscan);
6673
6674 gp->flags = htole16(gen_flags);
6675
6676 if (gen_flags & IWX_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1)
6677 gp->num_of_fragments[IWX_SCAN_LB_LMAC_IDX] = 3;
6678 if (gen_flags & IWX_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2)
6679 gp->num_of_fragments[IWX_SCAN_HB_LMAC_IDX] = 3;
6680
6681 gp->scan_start_mac_id = 0;
6682 }
6683
6684 static void
iwx_scan_umac_fill_ch_p_v6(struct iwx_softc * sc,struct iwx_scan_channel_params_v6 * cp,uint32_t channel_cfg_flags,int n_ssid)6685 iwx_scan_umac_fill_ch_p_v6(struct iwx_softc *sc,
6686 struct iwx_scan_channel_params_v6 *cp, uint32_t channel_cfg_flags,
6687 int n_ssid)
6688 {
6689 cp->flags = IWX_SCAN_CHANNEL_FLAG_ENABLE_CHAN_ORDER;
6690
6691 cp->count = iwx_umac_scan_fill_channels(sc, cp->channel_config,
6692 nitems(cp->channel_config), n_ssid, channel_cfg_flags);
6693
6694 cp->n_aps_override[0] = IWX_SCAN_ADWELL_N_APS_GO_FRIENDLY;
6695 cp->n_aps_override[1] = IWX_SCAN_ADWELL_N_APS_SOCIAL_CHS;
6696 }
6697
6698 static int
iwx_umac_scan_v14(struct iwx_softc * sc,int bgscan)6699 iwx_umac_scan_v14(struct iwx_softc *sc, int bgscan)
6700 {
6701 struct ieee80211com *ic = &sc->sc_ic;
6702 struct ieee80211_scan_state *ss = ic->ic_scan;
6703 struct iwx_host_cmd hcmd = {
6704 .id = iwx_cmd_id(IWX_SCAN_REQ_UMAC, IWX_LONG_GROUP, 0),
6705 .len = { 0, },
6706 .data = { NULL, },
6707 .flags = 0,
6708 };
6709 struct iwx_scan_req_umac_v14 *cmd = &sc->sc_umac_v14_cmd;
6710 struct iwx_scan_req_params_v14 *scan_p;
6711 int err, async = bgscan, n_ssid = 0;
6712 uint16_t gen_flags;
6713 uint32_t bitmap_ssid = 0;
6714
6715 IWX_ASSERT_LOCKED(sc);
6716
6717 bzero(cmd, sizeof(struct iwx_scan_req_umac_v14));
6718
6719 scan_p = &cmd->scan_params;
6720
6721 cmd->ooc_priority = htole32(IWX_SCAN_PRIORITY_EXT_6);
6722 cmd->uid = htole32(0);
6723
6724 gen_flags = iwx_scan_umac_flags_v2(sc, bgscan);
6725 iwx_scan_umac_fill_general_p_v10(sc, &scan_p->general_params,
6726 gen_flags, bgscan);
6727
6728 scan_p->periodic_params.schedule[0].interval = htole16(0);
6729 scan_p->periodic_params.schedule[0].iter_count = 1;
6730
6731 err = iwx_fill_probe_req(sc, &scan_p->probe_params.preq);
6732 if (err) {
6733 printf("%s: iwx_fill_probe_req failed (error %d)\n", __func__,
6734 err);
6735 return err;
6736 }
6737
6738 for (int i=0; i < ss->ss_nssid; i++) {
6739 scan_p->probe_params.direct_scan[i].id = IEEE80211_ELEMID_SSID;
6740 scan_p->probe_params.direct_scan[i].len =
6741 MIN(ss->ss_ssid[i].len, IEEE80211_NWID_LEN);
6742 DPRINTF(("%s: Active scan started for ssid ", __func__));
6743 memcpy(scan_p->probe_params.direct_scan[i].ssid,
6744 ss->ss_ssid[i].ssid, ss->ss_ssid[i].len);
6745 n_ssid++;
6746 bitmap_ssid |= (1 << i);
6747 }
6748 DPRINTF(("%s: bitmap_ssid=0x%x\n", __func__, bitmap_ssid));
6749
6750 iwx_scan_umac_fill_ch_p_v6(sc, &scan_p->channel_params, bitmap_ssid,
6751 n_ssid);
6752
6753 hcmd.len[0] = sizeof(*cmd);
6754 hcmd.data[0] = (void *)cmd;
6755 hcmd.flags |= async ? IWX_CMD_ASYNC : 0;
6756
6757 err = iwx_send_cmd(sc, &hcmd);
6758 return err;
6759 }
6760
6761 static void
iwx_mcc_update(struct iwx_softc * sc,struct iwx_mcc_chub_notif * notif)6762 iwx_mcc_update(struct iwx_softc *sc, struct iwx_mcc_chub_notif *notif)
6763 {
6764 char alpha2[3];
6765
6766 snprintf(alpha2, sizeof(alpha2), "%c%c",
6767 (le16toh(notif->mcc) & 0xff00) >> 8, le16toh(notif->mcc) & 0xff);
6768
6769 IWX_DPRINTF(sc, IWX_DEBUG_FW, "%s: firmware has detected regulatory domain '%s' "
6770 "(0x%x)\n", DEVNAME(sc), alpha2, le16toh(notif->mcc));
6771
6772 /* TODO: Schedule a task to send MCC_UPDATE_CMD? */
6773 }
6774
6775 uint8_t
iwx_ridx2rate(struct ieee80211_rateset * rs,int ridx)6776 iwx_ridx2rate(struct ieee80211_rateset *rs, int ridx)
6777 {
6778 int i;
6779 uint8_t rval;
6780
6781 for (i = 0; i < rs->rs_nrates; i++) {
6782 rval = (rs->rs_rates[i] & IEEE80211_RATE_VAL);
6783 if (rval == iwx_rates[ridx].rate)
6784 return rs->rs_rates[i];
6785 }
6786
6787 return 0;
6788 }
6789
6790 static int
iwx_rval2ridx(int rval)6791 iwx_rval2ridx(int rval)
6792 {
6793 int ridx;
6794
6795 for (ridx = 0; ridx < nitems(iwx_rates); ridx++) {
6796 if (iwx_rates[ridx].plcp == IWX_RATE_INVM_PLCP)
6797 continue;
6798 if (rval == iwx_rates[ridx].rate)
6799 break;
6800 }
6801
6802 return ridx;
6803 }
6804
6805 static void
iwx_ack_rates(struct iwx_softc * sc,struct iwx_node * in,int * cck_rates,int * ofdm_rates)6806 iwx_ack_rates(struct iwx_softc *sc, struct iwx_node *in, int *cck_rates,
6807 int *ofdm_rates)
6808 {
6809 struct ieee80211_node *ni = &in->in_ni;
6810 struct ieee80211_rateset *rs = &ni->ni_rates;
6811 int lowest_present_ofdm = -1;
6812 int lowest_present_cck = -1;
6813 uint8_t cck = 0;
6814 uint8_t ofdm = 0;
6815 int i;
6816
6817 if (ni->ni_chan == IEEE80211_CHAN_ANYC ||
6818 IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) {
6819 for (i = IWX_FIRST_CCK_RATE; i < IWX_FIRST_OFDM_RATE; i++) {
6820 if ((iwx_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0)
6821 continue;
6822 cck |= (1 << i);
6823 if (lowest_present_cck == -1 || lowest_present_cck > i)
6824 lowest_present_cck = i;
6825 }
6826 }
6827 for (i = IWX_FIRST_OFDM_RATE; i <= IWX_LAST_NON_HT_RATE; i++) {
6828 if ((iwx_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0)
6829 continue;
6830 ofdm |= (1 << (i - IWX_FIRST_OFDM_RATE));
6831 if (lowest_present_ofdm == -1 || lowest_present_ofdm > i)
6832 lowest_present_ofdm = i;
6833 }
6834
6835 /*
6836 * Now we've got the basic rates as bitmaps in the ofdm and cck
6837 * variables. This isn't sufficient though, as there might not
6838 * be all the right rates in the bitmap. E.g. if the only basic
6839 * rates are 5.5 Mbps and 11 Mbps, we still need to add 1 Mbps
6840 * and 6 Mbps because the 802.11-2007 standard says in 9.6:
6841 *
6842 * [...] a STA responding to a received frame shall transmit
6843 * its Control Response frame [...] at the highest rate in the
6844 * BSSBasicRateSet parameter that is less than or equal to the
6845 * rate of the immediately previous frame in the frame exchange
6846 * sequence ([...]) and that is of the same modulation class
6847 * ([...]) as the received frame. If no rate contained in the
6848 * BSSBasicRateSet parameter meets these conditions, then the
6849 * control frame sent in response to a received frame shall be
6850 * transmitted at the highest mandatory rate of the PHY that is
6851 * less than or equal to the rate of the received frame, and
6852 * that is of the same modulation class as the received frame.
6853 *
6854 * As a consequence, we need to add all mandatory rates that are
6855 * lower than all of the basic rates to these bitmaps.
6856 */
6857
6858 if (IWX_RATE_24M_INDEX < lowest_present_ofdm)
6859 ofdm |= IWX_RATE_BIT_MSK(24) >> IWX_FIRST_OFDM_RATE;
6860 if (IWX_RATE_12M_INDEX < lowest_present_ofdm)
6861 ofdm |= IWX_RATE_BIT_MSK(12) >> IWX_FIRST_OFDM_RATE;
6862 /* 6M already there or needed so always add */
6863 ofdm |= IWX_RATE_BIT_MSK(6) >> IWX_FIRST_OFDM_RATE;
6864
6865 /*
6866 * CCK is a bit more complex with DSSS vs. HR/DSSS vs. ERP.
6867 * Note, however:
6868 * - if no CCK rates are basic, it must be ERP since there must
6869 * be some basic rates at all, so they're OFDM => ERP PHY
6870 * (or we're in 5 GHz, and the cck bitmap will never be used)
6871 * - if 11M is a basic rate, it must be ERP as well, so add 5.5M
6872 * - if 5.5M is basic, 1M and 2M are mandatory
6873 * - if 2M is basic, 1M is mandatory
6874 * - if 1M is basic, that's the only valid ACK rate.
6875 * As a consequence, it's not as complicated as it sounds, just add
6876 * any lower rates to the ACK rate bitmap.
6877 */
6878 if (IWX_RATE_11M_INDEX < lowest_present_cck)
6879 cck |= IWX_RATE_BIT_MSK(11) >> IWX_FIRST_CCK_RATE;
6880 if (IWX_RATE_5M_INDEX < lowest_present_cck)
6881 cck |= IWX_RATE_BIT_MSK(5) >> IWX_FIRST_CCK_RATE;
6882 if (IWX_RATE_2M_INDEX < lowest_present_cck)
6883 cck |= IWX_RATE_BIT_MSK(2) >> IWX_FIRST_CCK_RATE;
6884 /* 1M already there or needed so always add */
6885 cck |= IWX_RATE_BIT_MSK(1) >> IWX_FIRST_CCK_RATE;
6886
6887 *cck_rates = cck;
6888 *ofdm_rates = ofdm;
6889 }
6890
6891 static void
iwx_mac_ctxt_cmd_common(struct iwx_softc * sc,struct iwx_node * in,struct iwx_mac_ctx_cmd * cmd,uint32_t action)6892 iwx_mac_ctxt_cmd_common(struct iwx_softc *sc, struct iwx_node *in,
6893 struct iwx_mac_ctx_cmd *cmd, uint32_t action)
6894 {
6895 #define IWX_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */
6896 struct ieee80211com *ic = &sc->sc_ic;
6897 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
6898 struct ieee80211_node *ni = vap->iv_bss;
6899 int cck_ack_rates, ofdm_ack_rates;
6900
6901 cmd->id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(in->in_id,
6902 in->in_color));
6903 cmd->action = htole32(action);
6904
6905 if (action == IWX_FW_CTXT_ACTION_REMOVE)
6906 return;
6907
6908 if (ic->ic_opmode == IEEE80211_M_MONITOR)
6909 cmd->mac_type = htole32(IWX_FW_MAC_TYPE_LISTENER);
6910 else if (ic->ic_opmode == IEEE80211_M_STA)
6911 cmd->mac_type = htole32(IWX_FW_MAC_TYPE_BSS_STA);
6912 else
6913 panic("unsupported operating mode %d", ic->ic_opmode);
6914 cmd->tsf_id = htole32(IWX_TSF_ID_A);
6915
6916 IEEE80211_ADDR_COPY(cmd->node_addr, vap->iv_myaddr);
6917 DPRINTF(("%s: cmd->node_addr=%s\n", __func__,
6918 ether_sprintf(cmd->node_addr)));
6919 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
6920 IEEE80211_ADDR_COPY(cmd->bssid_addr, etherbroadcastaddr);
6921 return;
6922 }
6923
6924 IEEE80211_ADDR_COPY(cmd->bssid_addr, in->in_macaddr);
6925 DPRINTF(("%s: cmd->bssid_addr=%s\n", __func__,
6926 ether_sprintf(cmd->bssid_addr)));
6927 iwx_ack_rates(sc, in, &cck_ack_rates, &ofdm_ack_rates);
6928 cmd->cck_rates = htole32(cck_ack_rates);
6929 cmd->ofdm_rates = htole32(ofdm_ack_rates);
6930
6931 cmd->cck_short_preamble
6932 = htole32((ic->ic_flags & IEEE80211_F_SHPREAMBLE)
6933 ? IWX_MAC_FLG_SHORT_PREAMBLE : 0);
6934 cmd->short_slot
6935 = htole32((ic->ic_flags & IEEE80211_F_SHSLOT)
6936 ? IWX_MAC_FLG_SHORT_SLOT : 0);
6937
6938 struct chanAccParams chp;
6939 ieee80211_wme_vap_getparams(vap, &chp);
6940
6941 for (int i = 0; i < WME_NUM_AC; i++) {
6942 int txf = iwx_ac_to_tx_fifo[i];
6943 cmd->ac[txf].cw_min = IWX_EXP2(chp.cap_wmeParams[i].wmep_logcwmin);
6944 cmd->ac[txf].cw_max = IWX_EXP2(chp.cap_wmeParams[i].wmep_logcwmax);
6945 cmd->ac[txf].aifsn = chp.cap_wmeParams[i].wmep_aifsn;
6946 cmd->ac[txf].fifos_mask = (1 << txf);
6947 cmd->ac[txf].edca_txop = chp.cap_wmeParams[i].wmep_txopLimit;
6948
6949 cmd->ac[txf].edca_txop = htole16(chp.cap_wmeParams[i].wmep_txopLimit * 32);
6950 }
6951
6952 if (ni->ni_flags & IEEE80211_NODE_QOS) {
6953 DPRINTF(("%s: === IEEE80211_NODE_QOS\n", __func__));
6954 cmd->qos_flags |= htole32(IWX_MAC_QOS_FLG_UPDATE_EDCA);
6955 }
6956
6957 if (ni->ni_flags & IEEE80211_NODE_HT) {
6958 switch (vap->iv_curhtprotmode) {
6959 case IEEE80211_HTINFO_OPMODE_PURE:
6960 break;
6961 case IEEE80211_HTINFO_OPMODE_PROTOPT:
6962 case IEEE80211_HTINFO_OPMODE_MIXED:
6963 cmd->protection_flags |=
6964 htole32(IWX_MAC_PROT_FLG_HT_PROT |
6965 IWX_MAC_PROT_FLG_FAT_PROT);
6966 break;
6967 case IEEE80211_HTINFO_OPMODE_HT20PR:
6968 if (in->in_phyctxt &&
6969 (in->in_phyctxt->sco == IEEE80211_HTINFO_2NDCHAN_ABOVE ||
6970 in->in_phyctxt->sco == IEEE80211_HTINFO_2NDCHAN_BELOW)) {
6971 cmd->protection_flags |=
6972 htole32(IWX_MAC_PROT_FLG_HT_PROT |
6973 IWX_MAC_PROT_FLG_FAT_PROT);
6974 }
6975 break;
6976 default:
6977 break;
6978 }
6979 cmd->qos_flags |= htole32(IWX_MAC_QOS_FLG_TGN);
6980 DPRINTF(("%s: === IWX_MAC_QOS_FLG_TGN\n", __func__));
6981 }
6982
6983 if (ic->ic_flags & IEEE80211_F_USEPROT)
6984 cmd->protection_flags |= htole32(IWX_MAC_PROT_FLG_TGG_PROTECT);
6985 cmd->filter_flags = htole32(IWX_MAC_FILTER_ACCEPT_GRP);
6986 #undef IWX_EXP2
6987 }
6988
6989 static void
iwx_mac_ctxt_cmd_fill_sta(struct iwx_softc * sc,struct iwx_node * in,struct iwx_mac_data_sta * sta,int assoc)6990 iwx_mac_ctxt_cmd_fill_sta(struct iwx_softc *sc, struct iwx_node *in,
6991 struct iwx_mac_data_sta *sta, int assoc)
6992 {
6993 struct ieee80211_node *ni = &in->in_ni;
6994 struct ieee80211com *ic = &sc->sc_ic;
6995 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
6996 uint32_t dtim_off;
6997 uint64_t tsf;
6998 int dtim_period;
6999
7000 dtim_off = ni->ni_dtim_count * ni->ni_intval * IEEE80211_DUR_TU;
7001 tsf = le64toh(ni->ni_tstamp.tsf);
7002 dtim_period = vap->iv_dtim_period;
7003
7004 sta->is_assoc = htole32(assoc);
7005
7006 if (assoc) {
7007 sta->dtim_time = htole32(tsf + dtim_off);
7008 sta->dtim_tsf = htole64(tsf + dtim_off);
7009 // XXX: unset in iwm
7010 sta->assoc_beacon_arrive_time = 0;
7011 }
7012 sta->bi = htole32(ni->ni_intval);
7013 sta->dtim_interval = htole32(ni->ni_intval * dtim_period);
7014 sta->data_policy = htole32(0);
7015 sta->listen_interval = htole32(10);
7016 sta->assoc_id = htole32(ni->ni_associd);
7017 }
7018
7019 static int
iwx_mac_ctxt_cmd(struct iwx_softc * sc,struct iwx_node * in,uint32_t action,int assoc)7020 iwx_mac_ctxt_cmd(struct iwx_softc *sc, struct iwx_node *in, uint32_t action,
7021 int assoc)
7022 {
7023 struct ieee80211com *ic = &sc->sc_ic;
7024 struct ieee80211_node *ni = &in->in_ni;
7025 struct iwx_mac_ctx_cmd cmd;
7026 int active = (sc->sc_flags & IWX_FLAG_MAC_ACTIVE);
7027
7028 if (action == IWX_FW_CTXT_ACTION_ADD && active)
7029 panic("MAC already added");
7030 if (action == IWX_FW_CTXT_ACTION_REMOVE && !active)
7031 panic("MAC already removed");
7032
7033 memset(&cmd, 0, sizeof(cmd));
7034
7035 iwx_mac_ctxt_cmd_common(sc, in, &cmd, action);
7036
7037 if (action == IWX_FW_CTXT_ACTION_REMOVE) {
7038 return iwx_send_cmd_pdu(sc, IWX_MAC_CONTEXT_CMD, 0,
7039 sizeof(cmd), &cmd);
7040 }
7041
7042 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
7043 cmd.filter_flags |= htole32(IWX_MAC_FILTER_IN_PROMISC |
7044 IWX_MAC_FILTER_IN_CONTROL_AND_MGMT |
7045 IWX_MAC_FILTER_ACCEPT_GRP |
7046 IWX_MAC_FILTER_IN_BEACON |
7047 IWX_MAC_FILTER_IN_PROBE_REQUEST |
7048 IWX_MAC_FILTER_IN_CRC32);
7049 // XXX: dtim period is in vap
7050 } else if (!assoc || !ni->ni_associd /*|| !ni->ni_dtimperiod*/) {
7051 /*
7052 * Allow beacons to pass through as long as we are not
7053 * associated or we do not have dtim period information.
7054 */
7055 cmd.filter_flags |= htole32(IWX_MAC_FILTER_IN_BEACON);
7056 }
7057 iwx_mac_ctxt_cmd_fill_sta(sc, in, &cmd.sta, assoc);
7058 return iwx_send_cmd_pdu(sc, IWX_MAC_CONTEXT_CMD, 0, sizeof(cmd), &cmd);
7059 }
7060
7061 static int
iwx_clear_statistics(struct iwx_softc * sc)7062 iwx_clear_statistics(struct iwx_softc *sc)
7063 {
7064 struct iwx_statistics_cmd scmd = {
7065 .flags = htole32(IWX_STATISTICS_FLG_CLEAR)
7066 };
7067 struct iwx_host_cmd cmd = {
7068 .id = IWX_STATISTICS_CMD,
7069 .len[0] = sizeof(scmd),
7070 .data[0] = &scmd,
7071 .flags = IWX_CMD_WANT_RESP,
7072 .resp_pkt_len = sizeof(struct iwx_notif_statistics),
7073 };
7074 int err;
7075
7076 err = iwx_send_cmd(sc, &cmd);
7077 if (err)
7078 return err;
7079
7080 iwx_free_resp(sc, &cmd);
7081 return 0;
7082 }
7083
7084 static int
iwx_scan(struct iwx_softc * sc)7085 iwx_scan(struct iwx_softc *sc)
7086 {
7087 int err;
7088 err = iwx_umac_scan_v14(sc, 0);
7089
7090 if (err) {
7091 printf("%s: could not initiate scan\n", DEVNAME(sc));
7092 return err;
7093 }
7094 return 0;
7095 }
7096
7097 static int
iwx_bgscan(struct ieee80211com * ic)7098 iwx_bgscan(struct ieee80211com *ic)
7099 {
7100 struct iwx_softc *sc = ic->ic_softc;
7101 int err;
7102
7103 err = iwx_umac_scan_v14(sc, 1);
7104 if (err) {
7105 printf("%s: could not initiate scan\n", DEVNAME(sc));
7106 return err;
7107 }
7108 return 0;
7109 }
7110
7111 static int
iwx_enable_mgmt_queue(struct iwx_softc * sc)7112 iwx_enable_mgmt_queue(struct iwx_softc *sc)
7113 {
7114 int err;
7115
7116 sc->first_data_qid = IWX_DQA_CMD_QUEUE + 1;
7117
7118 /*
7119 * Non-QoS frames use the "MGMT" TID and queue.
7120 * Other TIDs and data queues are reserved for QoS data frames.
7121 */
7122 err = iwx_enable_txq(sc, IWX_STATION_ID, sc->first_data_qid,
7123 IWX_MGMT_TID, IWX_TX_RING_COUNT);
7124 if (err) {
7125 printf("%s: could not enable Tx queue %d (error %d)\n",
7126 DEVNAME(sc), sc->first_data_qid, err);
7127 return err;
7128 }
7129
7130 return 0;
7131 }
7132
7133 static int
iwx_disable_mgmt_queue(struct iwx_softc * sc)7134 iwx_disable_mgmt_queue(struct iwx_softc *sc)
7135 {
7136 int err, cmd_ver;
7137
7138 /* Explicit removal is only required with old SCD_QUEUE_CFG command. */
7139 cmd_ver = iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP,
7140 IWX_SCD_QUEUE_CONFIG_CMD);
7141 if (cmd_ver == 0 || cmd_ver == IWX_FW_CMD_VER_UNKNOWN)
7142 return 0;
7143
7144 sc->first_data_qid = IWX_DQA_CMD_QUEUE + 1;
7145
7146 err = iwx_disable_txq(sc, IWX_STATION_ID, sc->first_data_qid,
7147 IWX_MGMT_TID);
7148 if (err) {
7149 printf("%s: could not disable Tx queue %d (error %d)\n",
7150 DEVNAME(sc), sc->first_data_qid, err);
7151 return err;
7152 }
7153
7154 return 0;
7155 }
7156
7157 static int
iwx_rs_rval2idx(uint8_t rval)7158 iwx_rs_rval2idx(uint8_t rval)
7159 {
7160 /* Firmware expects indices which match our 11g rate set. */
7161 const struct ieee80211_rateset *rs = &ieee80211_std_rateset_11g;
7162 int i;
7163
7164 for (i = 0; i < rs->rs_nrates; i++) {
7165 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rval)
7166 return i;
7167 }
7168
7169 return -1;
7170 }
7171
7172 static uint16_t
iwx_rs_ht_rates(struct iwx_softc * sc,struct ieee80211_node * ni,int rsidx)7173 iwx_rs_ht_rates(struct iwx_softc *sc, struct ieee80211_node *ni, int rsidx)
7174 {
7175 uint16_t htrates = 0;
7176 struct ieee80211_htrateset *htrs = &ni->ni_htrates;
7177 int i;
7178
7179 if (rsidx == IEEE80211_HT_RATESET_SISO) {
7180 for (i = 0; i < htrs->rs_nrates; i++) {
7181 if (htrs->rs_rates[i] <= 7)
7182 htrates |= (1 << htrs->rs_rates[i]);
7183 }
7184 } else if (rsidx == IEEE80211_HT_RATESET_MIMO2) {
7185 for (i = 0; i < htrs->rs_nrates; i++) {
7186 if (htrs->rs_rates[i] > 7 && htrs->rs_rates[i] <= 15)
7187 htrates |= (1 << (htrs->rs_rates[i] - 8));
7188 }
7189 } else
7190 panic(("iwx_rs_ht_rates"));
7191
7192 IWX_DPRINTF(sc, IWX_DEBUG_TXRATE,
7193 "%s:%d rsidx=%i htrates=0x%x\n", __func__, __LINE__, rsidx, htrates);
7194
7195 return htrates;
7196 }
7197
7198 uint16_t
iwx_rs_vht_rates(struct iwx_softc * sc,struct ieee80211_node * ni,int num_ss)7199 iwx_rs_vht_rates(struct iwx_softc *sc, struct ieee80211_node *ni, int num_ss)
7200 {
7201 uint16_t rx_mcs;
7202 int max_mcs = -1;
7203 #define IEEE80211_VHT_MCS_FOR_SS_MASK(n) (0x3 << (2*((n)-1)))
7204 #define IEEE80211_VHT_MCS_FOR_SS_SHIFT(n) (2*((n)-1))
7205 rx_mcs = (ni->ni_vht_mcsinfo.tx_mcs_map &
7206 IEEE80211_VHT_MCS_FOR_SS_MASK(num_ss)) >>
7207 IEEE80211_VHT_MCS_FOR_SS_SHIFT(num_ss);
7208
7209 switch (rx_mcs) {
7210 case IEEE80211_VHT_MCS_NOT_SUPPORTED:
7211 break;
7212 case IEEE80211_VHT_MCS_SUPPORT_0_7:
7213 max_mcs = 7;
7214 break;
7215 case IEEE80211_VHT_MCS_SUPPORT_0_8:
7216 max_mcs = 8;
7217 break;
7218 case IEEE80211_VHT_MCS_SUPPORT_0_9:
7219 /* Disable VHT MCS 9 for 20MHz-only stations. */
7220 if ((ni->ni_htcap & IEEE80211_HTCAP_CHWIDTH40) == 0)
7221 max_mcs = 8;
7222 else
7223 max_mcs = 9;
7224 break;
7225 default:
7226 /* Should not happen; Values above cover the possible range. */
7227 panic("invalid VHT Rx MCS value %u", rx_mcs);
7228 }
7229
7230 return ((1 << (max_mcs + 1)) - 1);
7231 }
7232
7233 static int
iwx_rs_init_v3(struct iwx_softc * sc,struct iwx_node * in)7234 iwx_rs_init_v3(struct iwx_softc *sc, struct iwx_node *in)
7235 {
7236 #if 1
7237 panic("iwx: Trying to init rate set on untested version");
7238 #else
7239 struct ieee80211_node *ni = &in->in_ni;
7240 struct ieee80211_rateset *rs = &ni->ni_rates;
7241 struct iwx_tlc_config_cmd_v3 cfg_cmd;
7242 uint32_t cmd_id;
7243 int i;
7244 size_t cmd_size = sizeof(cfg_cmd);
7245
7246 memset(&cfg_cmd, 0, sizeof(cfg_cmd));
7247
7248 for (i = 0; i < rs->rs_nrates; i++) {
7249 uint8_t rval = rs->rs_rates[i] & IEEE80211_RATE_VAL;
7250 int idx = iwx_rs_rval2idx(rval);
7251 if (idx == -1)
7252 return EINVAL;
7253 cfg_cmd.non_ht_rates |= (1 << idx);
7254 }
7255
7256 if (ni->ni_flags & IEEE80211_NODE_VHT) {
7257 cfg_cmd.mode = IWX_TLC_MNG_MODE_VHT;
7258 cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_MCS_PER_BW_80] =
7259 htole16(iwx_rs_vht_rates(sc, ni, 1));
7260 cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_MCS_PER_BW_80] =
7261 htole16(iwx_rs_vht_rates(sc, ni, 2));
7262 } else if (ni->ni_flags & IEEE80211_NODE_HT) {
7263 cfg_cmd.mode = IWX_TLC_MNG_MODE_HT;
7264 cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_MCS_PER_BW_80] =
7265 htole16(iwx_rs_ht_rates(sc, ni,
7266 IEEE80211_HT_RATESET_SISO));
7267 cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_MCS_PER_BW_80] =
7268 htole16(iwx_rs_ht_rates(sc, ni,
7269 IEEE80211_HT_RATESET_MIMO2));
7270 } else
7271 cfg_cmd.mode = IWX_TLC_MNG_MODE_NON_HT;
7272
7273 cfg_cmd.sta_id = IWX_STATION_ID;
7274 if (in->in_phyctxt->vht_chan_width == IEEE80211_VHTOP0_CHAN_WIDTH_80)
7275 cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_80MHZ;
7276 else if (in->in_phyctxt->sco == IEEE80211_HTOP0_SCO_SCA ||
7277 in->in_phyctxt->sco == IEEE80211_HTOP0_SCO_SCB)
7278 cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_40MHZ;
7279 else
7280 cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_20MHZ;
7281 cfg_cmd.chains = IWX_TLC_MNG_CHAIN_A_MSK | IWX_TLC_MNG_CHAIN_B_MSK;
7282 if (ni->ni_flags & IEEE80211_NODE_VHT)
7283 cfg_cmd.max_mpdu_len = htole16(3895);
7284 else
7285 cfg_cmd.max_mpdu_len = htole16(3839);
7286 if (ni->ni_flags & IEEE80211_NODE_HT) {
7287 if (ieee80211_node_supports_ht_sgi20(ni)) {
7288 cfg_cmd.sgi_ch_width_supp |= (1 <<
7289 IWX_TLC_MNG_CH_WIDTH_20MHZ);
7290 }
7291 if (ieee80211_node_supports_ht_sgi40(ni)) {
7292 cfg_cmd.sgi_ch_width_supp |= (1 <<
7293 IWX_TLC_MNG_CH_WIDTH_40MHZ);
7294 }
7295 }
7296 if ((ni->ni_flags & IEEE80211_NODE_VHT) &&
7297 ieee80211_node_supports_vht_sgi80(ni))
7298 cfg_cmd.sgi_ch_width_supp |= (1 << IWX_TLC_MNG_CH_WIDTH_80MHZ);
7299
7300 cmd_id = iwx_cmd_id(IWX_TLC_MNG_CONFIG_CMD, IWX_DATA_PATH_GROUP, 0);
7301 return iwx_send_cmd_pdu(sc, cmd_id, IWX_CMD_ASYNC, cmd_size, &cfg_cmd);
7302 #endif
7303 }
7304
7305 static int
iwx_rs_init_v4(struct iwx_softc * sc,struct iwx_node * in)7306 iwx_rs_init_v4(struct iwx_softc *sc, struct iwx_node *in)
7307 {
7308 struct ieee80211_node *ni = &in->in_ni;
7309 struct ieee80211_rateset *rs = &ni->ni_rates;
7310 struct ieee80211_htrateset *htrs = &ni->ni_htrates;
7311 struct iwx_tlc_config_cmd_v4 cfg_cmd;
7312 uint32_t cmd_id;
7313 int i;
7314 int sgi80 = 0;
7315 size_t cmd_size = sizeof(cfg_cmd);
7316
7317 memset(&cfg_cmd, 0, sizeof(cfg_cmd));
7318
7319 for (i = 0; i < rs->rs_nrates; i++) {
7320 uint8_t rval = rs->rs_rates[i] & IEEE80211_RATE_VAL;
7321 int idx = iwx_rs_rval2idx(rval);
7322 if (idx == -1)
7323 return EINVAL;
7324 cfg_cmd.non_ht_rates |= (1 << idx);
7325 }
7326 for (i = 0; i < htrs->rs_nrates; i++) {
7327 DPRINTF(("%s: htrate=%i\n", __func__, htrs->rs_rates[i]));
7328 }
7329
7330 if (ni->ni_flags & IEEE80211_NODE_VHT) {
7331 cfg_cmd.mode = IWX_TLC_MNG_MODE_VHT;
7332 cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_MCS_PER_BW_80] =
7333 htole16(iwx_rs_vht_rates(sc, ni, 1));
7334 cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_MCS_PER_BW_80] =
7335 htole16(iwx_rs_vht_rates(sc, ni, 2));
7336
7337 IWX_DPRINTF(sc, IWX_DEBUG_TXRATE, "%s:%d SISO=0x%x\n",
7338 __func__, __LINE__,
7339 cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_MCS_PER_BW_80]);
7340 IWX_DPRINTF(sc, IWX_DEBUG_TXRATE, "%s:%d MIMO2=0x%x\n",
7341 __func__, __LINE__,
7342 cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_MCS_PER_BW_80]);
7343 } else if (ni->ni_flags & IEEE80211_NODE_HT) {
7344 cfg_cmd.mode = IWX_TLC_MNG_MODE_HT;
7345 cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_MCS_PER_BW_80] =
7346 htole16(iwx_rs_ht_rates(sc, ni,
7347 IEEE80211_HT_RATESET_SISO));
7348 cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_MCS_PER_BW_80] =
7349 htole16(iwx_rs_ht_rates(sc, ni,
7350 IEEE80211_HT_RATESET_MIMO2));
7351
7352 IWX_DPRINTF(sc, IWX_DEBUG_TXRATE, "%s:%d SISO=0x%x\n",
7353 __func__, __LINE__,
7354 cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_MCS_PER_BW_80]);
7355 IWX_DPRINTF(sc, IWX_DEBUG_TXRATE, "%s:%d MIMO2=0x%x\n",
7356 __func__, __LINE__,
7357 cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_MCS_PER_BW_80]);
7358 } else
7359 cfg_cmd.mode = IWX_TLC_MNG_MODE_NON_HT;
7360
7361 cfg_cmd.sta_id = IWX_STATION_ID;
7362 #if 0
7363 if (in->in_phyctxt->vht_chan_width == IEEE80211_VHTOP0_CHAN_WIDTH_80)
7364 cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_80MHZ;
7365 else if (in->in_phyctxt->sco == IEEE80211_HTOP0_SCO_SCA ||
7366 in->in_phyctxt->sco == IEEE80211_HTOP0_SCO_SCB)
7367 cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_40MHZ;
7368 else
7369 cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_20MHZ;
7370 #endif
7371 if (IEEE80211_IS_CHAN_VHT80(in->in_ni.ni_chan)) {
7372 cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_80MHZ;
7373 } else if (IEEE80211_IS_CHAN_HT40(in->in_ni.ni_chan)) {
7374 cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_40MHZ;
7375 } else {
7376 cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_20MHZ;
7377 }
7378
7379 cfg_cmd.chains = IWX_TLC_MNG_CHAIN_A_MSK | IWX_TLC_MNG_CHAIN_B_MSK;
7380 if (ni->ni_flags & IEEE80211_NODE_VHT)
7381 cfg_cmd.max_mpdu_len = htole16(3895);
7382 else
7383 cfg_cmd.max_mpdu_len = htole16(3839);
7384 if (ni->ni_flags & IEEE80211_NODE_HT) {
7385 if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) {
7386 cfg_cmd.sgi_ch_width_supp |= (1 <<
7387 IWX_TLC_MNG_CH_WIDTH_20MHZ);
7388 }
7389 if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) {
7390 cfg_cmd.sgi_ch_width_supp |= (1 <<
7391 IWX_TLC_MNG_CH_WIDTH_40MHZ);
7392 }
7393 }
7394 sgi80 = _IEEE80211_MASKSHIFT(ni->ni_vhtcap,
7395 IEEE80211_VHTCAP_SHORT_GI_80);
7396 if ((ni->ni_flags & IEEE80211_NODE_VHT) && sgi80) {
7397 cfg_cmd.sgi_ch_width_supp |= (1 << IWX_TLC_MNG_CH_WIDTH_80MHZ);
7398 }
7399
7400 cmd_id = iwx_cmd_id(IWX_TLC_MNG_CONFIG_CMD, IWX_DATA_PATH_GROUP, 0);
7401 return iwx_send_cmd_pdu(sc, cmd_id, IWX_CMD_ASYNC, cmd_size, &cfg_cmd);
7402 }
7403
7404 static int
iwx_rs_init(struct iwx_softc * sc,struct iwx_node * in)7405 iwx_rs_init(struct iwx_softc *sc, struct iwx_node *in)
7406 {
7407 int cmd_ver;
7408
7409 cmd_ver = iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP,
7410 IWX_TLC_MNG_CONFIG_CMD);
7411 if (cmd_ver == 4)
7412 return iwx_rs_init_v4(sc, in);
7413 else
7414 return iwx_rs_init_v3(sc, in);
7415 }
7416
7417
7418 /**
7419 * @brief Turn the given TX rate control notification into an ieee80211_node_txrate
7420 *
7421 * This populates the given txrate node with the TX rate control notification.
7422 *
7423 * @param sc driver softc
7424 * @param notif firmware notification
7425 * @param ni ieee80211_node update
7426 * @returns true if updated, false if not
7427 */
7428 static bool
iwx_rs_update_node_txrate(struct iwx_softc * sc,const struct iwx_tlc_update_notif * notif,struct ieee80211_node * ni)7429 iwx_rs_update_node_txrate(struct iwx_softc *sc,
7430 const struct iwx_tlc_update_notif *notif, struct ieee80211_node *ni)
7431 {
7432 struct ieee80211com *ic = &sc->sc_ic;
7433 /* XXX TODO: create an inline function in if_iwxreg.h? */
7434 static int cck_idx_to_rate[] = { 2, 4, 11, 22, 2, 2, 2, 2 };
7435 static int ofdm_idx_to_rate[] = { 12, 18, 24, 36, 48, 72, 96, 108 };
7436
7437 uint32_t rate_n_flags;
7438 uint32_t type;
7439
7440 /* Extract the rate and command version */
7441 rate_n_flags = le32toh(notif->rate);
7442
7443 if (sc->sc_rate_n_flags_version != 2) {
7444 net80211_ic_printf(ic,
7445 "%s: unsupported rate_n_flags version (%d)\n",
7446 __func__,
7447 sc->sc_rate_n_flags_version);
7448 return (false);
7449 }
7450
7451 if (sc->sc_debug & IWX_DEBUG_TXRATE)
7452 print_ratenflags(__func__, __LINE__,
7453 rate_n_flags, sc->sc_rate_n_flags_version);
7454
7455 type = (rate_n_flags & IWX_RATE_MCS_MOD_TYPE_MSK);
7456 switch (type) {
7457 case IWX_RATE_MCS_CCK_MSK:
7458 ieee80211_node_set_txrate_dot11rate(ni,
7459 cck_idx_to_rate[rate_n_flags & IWX_RATE_LEGACY_RATE_MSK]);
7460 return (true);
7461 case IWX_RATE_MCS_LEGACY_OFDM_MSK:
7462 ieee80211_node_set_txrate_dot11rate(ni,
7463 ofdm_idx_to_rate[rate_n_flags & IWX_RATE_LEGACY_RATE_MSK]);
7464 return (true);
7465 case IWX_RATE_MCS_HT_MSK:
7466 /*
7467 * TODO: the current API doesn't include channel width
7468 * and other flags, so we can't accurately store them yet!
7469 *
7470 * channel width: (flags & IWX_RATE_MCS_CHAN_WIDTH_MSK)
7471 * >> IWX_RATE_MCS_CHAN_WIDTH_POS)
7472 * LDPC: (flags & (1 << 16))
7473 */
7474 ieee80211_node_set_txrate_ht_mcsrate(ni,
7475 IWX_RATE_HT_MCS_INDEX(rate_n_flags));
7476 return (true);
7477 case IWX_RATE_MCS_VHT_MSK:
7478 /* TODO: same comment on channel width, etc above */
7479 ieee80211_node_set_txrate_vht_rate(ni,
7480 IWX_RATE_VHT_MCS_CODE(rate_n_flags),
7481 IWX_RATE_VHT_MCS_NSS(rate_n_flags));
7482 return (true);
7483 default:
7484 net80211_ic_printf(ic,
7485 "%s: unsupported chosen rate type in "
7486 "IWX_RATE_MCS_MOD_TYPE (%d)\n", __func__,
7487 type >> IWX_RATE_MCS_MOD_TYPE_POS);
7488 return (false);
7489 }
7490
7491 /* Default: if we get here, we didn't successfully update anything */
7492 return (false);
7493 }
7494
7495 /**
7496 * @brief Process a firmware rate control update and update net80211.
7497 *
7498 * Since firmware is doing rate control, this just needs to update
7499 * the txrate in the ieee80211_node entry.
7500 */
7501 static void
iwx_rs_update(struct iwx_softc * sc,struct iwx_tlc_update_notif * notif)7502 iwx_rs_update(struct iwx_softc *sc, struct iwx_tlc_update_notif *notif)
7503 {
7504 struct ieee80211com *ic = &sc->sc_ic;
7505 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
7506 /* XXX TODO: get a node ref! */
7507 struct ieee80211_node *ni = (void *)vap->iv_bss;
7508
7509 /*
7510 * For now the iwx driver only supports a single vdev with a single
7511 * node; it doesn't yet support ibss/hostap/multiple vdevs.
7512 */
7513 if (notif->sta_id != IWX_STATION_ID ||
7514 (le32toh(notif->flags) & IWX_TLC_NOTIF_FLAG_RATE) == 0)
7515 return;
7516
7517 iwx_rs_update_node_txrate(sc, notif, ni);
7518 }
7519
7520 static int
iwx_phy_send_rlc(struct iwx_softc * sc,struct iwx_phy_ctxt * phyctxt,uint8_t chains_static,uint8_t chains_dynamic)7521 iwx_phy_send_rlc(struct iwx_softc *sc, struct iwx_phy_ctxt *phyctxt,
7522 uint8_t chains_static, uint8_t chains_dynamic)
7523 {
7524 struct iwx_rlc_config_cmd cmd;
7525 uint32_t cmd_id;
7526 uint8_t active_cnt, idle_cnt;
7527
7528 memset(&cmd, 0, sizeof(cmd));
7529
7530 idle_cnt = chains_static;
7531 active_cnt = chains_dynamic;
7532
7533 cmd.phy_id = htole32(phyctxt->id);
7534 cmd.rlc.rx_chain_info = htole32(iwx_fw_valid_rx_ant(sc) <<
7535 IWX_PHY_RX_CHAIN_VALID_POS);
7536 cmd.rlc.rx_chain_info |= htole32(idle_cnt << IWX_PHY_RX_CHAIN_CNT_POS);
7537 cmd.rlc.rx_chain_info |= htole32(active_cnt <<
7538 IWX_PHY_RX_CHAIN_MIMO_CNT_POS);
7539
7540 cmd_id = iwx_cmd_id(IWX_RLC_CONFIG_CMD, IWX_DATA_PATH_GROUP, 2);
7541 return iwx_send_cmd_pdu(sc, cmd_id, 0, sizeof(cmd), &cmd);
7542 }
7543
7544 static int
iwx_phy_ctxt_update(struct iwx_softc * sc,struct iwx_phy_ctxt * phyctxt,struct ieee80211_channel * chan,uint8_t chains_static,uint8_t chains_dynamic,uint32_t apply_time,uint8_t sco,uint8_t vht_chan_width)7545 iwx_phy_ctxt_update(struct iwx_softc *sc, struct iwx_phy_ctxt *phyctxt,
7546 struct ieee80211_channel *chan, uint8_t chains_static,
7547 uint8_t chains_dynamic, uint32_t apply_time, uint8_t sco,
7548 uint8_t vht_chan_width)
7549 {
7550 uint16_t band_flags = (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ);
7551 int err;
7552
7553 if (chan == IEEE80211_CHAN_ANYC) {
7554 printf("%s: GOS-3833: IEEE80211_CHAN_ANYC triggered\n",
7555 DEVNAME(sc));
7556 return EIO;
7557 }
7558
7559 if (isset(sc->sc_enabled_capa,
7560 IWX_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT) &&
7561 (phyctxt->channel->ic_flags & band_flags) !=
7562 (chan->ic_flags & band_flags)) {
7563 err = iwx_phy_ctxt_cmd(sc, phyctxt, chains_static,
7564 chains_dynamic, IWX_FW_CTXT_ACTION_REMOVE, apply_time, sco,
7565 vht_chan_width);
7566 if (err) {
7567 printf("%s: could not remove PHY context "
7568 "(error %d)\n", DEVNAME(sc), err);
7569 return err;
7570 }
7571 phyctxt->channel = chan;
7572 err = iwx_phy_ctxt_cmd(sc, phyctxt, chains_static,
7573 chains_dynamic, IWX_FW_CTXT_ACTION_ADD, apply_time, sco,
7574 vht_chan_width);
7575 if (err) {
7576 printf("%s: could not add PHY context "
7577 "(error %d)\n", DEVNAME(sc), err);
7578 return err;
7579 }
7580 } else {
7581 phyctxt->channel = chan;
7582 err = iwx_phy_ctxt_cmd(sc, phyctxt, chains_static,
7583 chains_dynamic, IWX_FW_CTXT_ACTION_MODIFY, apply_time, sco,
7584 vht_chan_width);
7585 if (err) {
7586 printf("%s: could not update PHY context (error %d)\n",
7587 DEVNAME(sc), err);
7588 return err;
7589 }
7590 }
7591
7592 phyctxt->sco = sco;
7593 phyctxt->vht_chan_width = vht_chan_width;
7594
7595 DPRINTF(("%s: phyctxt->channel->ic_ieee=%d\n", __func__,
7596 phyctxt->channel->ic_ieee));
7597 DPRINTF(("%s: phyctxt->sco=%d\n", __func__, phyctxt->sco));
7598 DPRINTF(("%s: phyctxt->vht_chan_width=%d\n", __func__,
7599 phyctxt->vht_chan_width));
7600
7601 if (iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP,
7602 IWX_RLC_CONFIG_CMD) == 2)
7603 return iwx_phy_send_rlc(sc, phyctxt,
7604 chains_static, chains_dynamic);
7605
7606 return 0;
7607 }
7608
7609 static int
iwx_auth(struct ieee80211vap * vap,struct iwx_softc * sc)7610 iwx_auth(struct ieee80211vap *vap, struct iwx_softc *sc)
7611 {
7612 struct ieee80211com *ic = &sc->sc_ic;
7613 struct iwx_node *in;
7614 struct iwx_vap *ivp = IWX_VAP(vap);
7615 struct ieee80211_node *ni;
7616 uint32_t duration;
7617 int generation = sc->sc_generation, err;
7618
7619 IWX_ASSERT_LOCKED(sc);
7620
7621 ni = ieee80211_ref_node(vap->iv_bss);
7622 in = IWX_NODE(ni);
7623
7624 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
7625 err = iwx_phy_ctxt_update(sc, &sc->sc_phyctxt[0],
7626 ic->ic_bsschan, 1, 1, 0, IEEE80211_HTOP0_SCO_SCN,
7627 IEEE80211_VHTOP0_CHAN_WIDTH_HT);
7628 if (err)
7629 return err;
7630 } else {
7631 err = iwx_phy_ctxt_update(sc, &sc->sc_phyctxt[0],
7632 in->in_ni.ni_chan, 1, 1, 0, IEEE80211_HTOP0_SCO_SCN,
7633 IEEE80211_VHTOP0_CHAN_WIDTH_HT);
7634 if (err)
7635 return err;
7636 }
7637 ivp->phy_ctxt = &sc->sc_phyctxt[0];
7638 IEEE80211_ADDR_COPY(in->in_macaddr, in->in_ni.ni_macaddr);
7639 DPRINTF(("%s: in-in_macaddr=%s\n", __func__,
7640 ether_sprintf(in->in_macaddr)));
7641
7642 err = iwx_mac_ctxt_cmd(sc, in, IWX_FW_CTXT_ACTION_ADD, 0);
7643 if (err) {
7644 printf("%s: could not add MAC context (error %d)\n",
7645 DEVNAME(sc), err);
7646 return err;
7647 }
7648 sc->sc_flags |= IWX_FLAG_MAC_ACTIVE;
7649
7650 err = iwx_binding_cmd(sc, in, IWX_FW_CTXT_ACTION_ADD);
7651 if (err) {
7652 printf("%s: could not add binding (error %d)\n",
7653 DEVNAME(sc), err);
7654 goto rm_mac_ctxt;
7655 }
7656 sc->sc_flags |= IWX_FLAG_BINDING_ACTIVE;
7657
7658 err = iwx_add_sta_cmd(sc, in, 0);
7659 if (err) {
7660 printf("%s: could not add sta (error %d)\n",
7661 DEVNAME(sc), err);
7662 goto rm_binding;
7663 }
7664 sc->sc_flags |= IWX_FLAG_STA_ACTIVE;
7665
7666 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
7667 err = iwx_enable_txq(sc, IWX_MONITOR_STA_ID,
7668 IWX_DQA_INJECT_MONITOR_QUEUE, IWX_MGMT_TID,
7669 IWX_TX_RING_COUNT);
7670 if (err)
7671 goto rm_sta;
7672 return 0;
7673 }
7674
7675 err = iwx_enable_mgmt_queue(sc);
7676 if (err)
7677 goto rm_sta;
7678
7679 err = iwx_clear_statistics(sc);
7680 if (err)
7681 goto rm_mgmt_queue;
7682
7683 /*
7684 * Prevent the FW from wandering off channel during association
7685 * by "protecting" the session with a time event.
7686 */
7687 if (in->in_ni.ni_intval)
7688 duration = in->in_ni.ni_intval * 9;
7689 else
7690 duration = 900;
7691 return iwx_schedule_session_protection(sc, in, duration);
7692
7693 rm_mgmt_queue:
7694 if (generation == sc->sc_generation)
7695 iwx_disable_mgmt_queue(sc);
7696 rm_sta:
7697 if (generation == sc->sc_generation) {
7698 iwx_rm_sta_cmd(sc, in);
7699 sc->sc_flags &= ~IWX_FLAG_STA_ACTIVE;
7700 }
7701 rm_binding:
7702 if (generation == sc->sc_generation) {
7703 iwx_binding_cmd(sc, in, IWX_FW_CTXT_ACTION_REMOVE);
7704 sc->sc_flags &= ~IWX_FLAG_BINDING_ACTIVE;
7705 }
7706 rm_mac_ctxt:
7707 if (generation == sc->sc_generation) {
7708 iwx_mac_ctxt_cmd(sc, in, IWX_FW_CTXT_ACTION_REMOVE, 0);
7709 sc->sc_flags &= ~IWX_FLAG_MAC_ACTIVE;
7710 }
7711 return err;
7712 }
7713
7714 static int
iwx_deauth(struct iwx_softc * sc)7715 iwx_deauth(struct iwx_softc *sc)
7716 {
7717 struct ieee80211com *ic = &sc->sc_ic;
7718 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
7719 struct iwx_node *in = IWX_NODE(vap->iv_bss);
7720 int err;
7721
7722 IWX_ASSERT_LOCKED(sc);
7723
7724 iwx_unprotect_session(sc, in);
7725
7726 if (sc->sc_flags & IWX_FLAG_STA_ACTIVE) {
7727 err = iwx_rm_sta(sc, in);
7728 if (err)
7729 return err;
7730 sc->sc_flags &= ~IWX_FLAG_STA_ACTIVE;
7731 }
7732
7733 if (sc->sc_flags & IWX_FLAG_BINDING_ACTIVE) {
7734 err = iwx_binding_cmd(sc, in, IWX_FW_CTXT_ACTION_REMOVE);
7735 if (err) {
7736 printf("%s: could not remove binding (error %d)\n",
7737 DEVNAME(sc), err);
7738 return err;
7739 }
7740 sc->sc_flags &= ~IWX_FLAG_BINDING_ACTIVE;
7741 }
7742
7743 DPRINTF(("%s: IWX_FLAG_MAC_ACTIVE=%d\n", __func__, sc->sc_flags &
7744 IWX_FLAG_MAC_ACTIVE));
7745 if (sc->sc_flags & IWX_FLAG_MAC_ACTIVE) {
7746 err = iwx_mac_ctxt_cmd(sc, in, IWX_FW_CTXT_ACTION_REMOVE, 0);
7747 if (err) {
7748 printf("%s: could not remove MAC context (error %d)\n",
7749 DEVNAME(sc), err);
7750 return err;
7751 }
7752 sc->sc_flags &= ~IWX_FLAG_MAC_ACTIVE;
7753 }
7754
7755 /* Move unused PHY context to a default channel. */
7756 //TODO uncommented in obsd, but stays on the way of auth->auth
7757 err = iwx_phy_ctxt_update(sc, &sc->sc_phyctxt[0],
7758 &ic->ic_channels[1], 1, 1, 0, IEEE80211_HTOP0_SCO_SCN,
7759 IEEE80211_VHTOP0_CHAN_WIDTH_HT);
7760 if (err)
7761 return err;
7762
7763 return 0;
7764 }
7765
7766 static int
iwx_run(struct ieee80211vap * vap,struct iwx_softc * sc)7767 iwx_run(struct ieee80211vap *vap, struct iwx_softc *sc)
7768 {
7769 struct ieee80211com *ic = &sc->sc_ic;
7770 struct iwx_node *in = IWX_NODE(vap->iv_bss);
7771 struct ieee80211_node *ni = &in->in_ni;
7772 struct iwx_vap *ivp = IWX_VAP(vap);
7773 int err;
7774
7775 IWX_ASSERT_LOCKED(sc);
7776
7777 if (ni->ni_flags & IEEE80211_NODE_HT) {
7778 uint8_t chains = iwx_mimo_enabled(sc) ? 2 : 1;
7779 uint8_t sco, vht_chan_width;
7780 sco = IEEE80211_HTOP0_SCO_SCN;
7781 if ((ni->ni_flags & IEEE80211_NODE_VHT) &&
7782 IEEE80211_IS_CHAN_VHT80(ni->ni_chan))
7783 vht_chan_width = IEEE80211_VHTOP0_CHAN_WIDTH_80;
7784 else
7785 vht_chan_width = IEEE80211_VHTOP0_CHAN_WIDTH_HT;
7786 err = iwx_phy_ctxt_update(sc, ivp->phy_ctxt,
7787 ivp->phy_ctxt->channel, chains, chains,
7788 0, sco, vht_chan_width);
7789 if (err) {
7790 printf("%s: failed to update PHY\n", DEVNAME(sc));
7791 return err;
7792 }
7793 }
7794
7795 /* Update STA again to apply HT and VHT settings. */
7796 err = iwx_add_sta_cmd(sc, in, 1);
7797 if (err) {
7798 printf("%s: could not update STA (error %d)\n",
7799 DEVNAME(sc), err);
7800 return err;
7801 }
7802
7803 /* We have now been assigned an associd by the AP. */
7804 err = iwx_mac_ctxt_cmd(sc, in, IWX_FW_CTXT_ACTION_MODIFY, 1);
7805 if (err) {
7806 printf("%s: failed to update MAC\n", DEVNAME(sc));
7807 return err;
7808 }
7809
7810 err = iwx_sf_config(sc, IWX_SF_FULL_ON);
7811 if (err) {
7812 printf("%s: could not set sf full on (error %d)\n",
7813 DEVNAME(sc), err);
7814 return err;
7815 }
7816
7817 err = iwx_allow_mcast(sc);
7818 if (err) {
7819 printf("%s: could not allow mcast (error %d)\n",
7820 DEVNAME(sc), err);
7821 return err;
7822 }
7823
7824 err = iwx_power_update_device(sc);
7825 if (err) {
7826 printf("%s: could not send power command (error %d)\n",
7827 DEVNAME(sc), err);
7828 return err;
7829 }
7830 #ifdef notyet
7831 /*
7832 * Disabled for now. Default beacon filter settings
7833 * prevent net80211 from getting ERP and HT protection
7834 * updates from beacons.
7835 */
7836 err = iwx_enable_beacon_filter(sc, in);
7837 if (err) {
7838 printf("%s: could not enable beacon filter\n",
7839 DEVNAME(sc));
7840 return err;
7841 }
7842 #endif
7843 err = iwx_power_mac_update_mode(sc, in);
7844 if (err) {
7845 printf("%s: could not update MAC power (error %d)\n",
7846 DEVNAME(sc), err);
7847 return err;
7848 }
7849
7850 if (ic->ic_opmode == IEEE80211_M_MONITOR)
7851 return 0;
7852
7853 err = iwx_rs_init(sc, in);
7854 if (err) {
7855 printf("%s: could not init rate scaling (error %d)\n",
7856 DEVNAME(sc), err);
7857 return err;
7858 }
7859
7860 return 0;
7861 }
7862
7863 static int
iwx_run_stop(struct iwx_softc * sc)7864 iwx_run_stop(struct iwx_softc *sc)
7865 {
7866 struct ieee80211com *ic = &sc->sc_ic;
7867 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
7868 struct iwx_node *in = IWX_NODE(vap->iv_bss);
7869 struct ieee80211_node *ni = &in->in_ni;
7870 int err, i;
7871
7872 IWX_ASSERT_LOCKED(sc);
7873
7874 err = iwx_flush_sta(sc, in);
7875 if (err) {
7876 printf("%s: could not flush Tx path (error %d)\n",
7877 DEVNAME(sc), err);
7878 return err;
7879 }
7880
7881 /*
7882 * Stop Rx BA sessions now. We cannot rely on the BA task
7883 * for this when moving out of RUN state since it runs in a
7884 * separate thread.
7885 * Note that in->in_ni (struct ieee80211_node) already represents
7886 * our new access point in case we are roaming between APs.
7887 * This means we cannot rely on struct ieee802111_node to tell
7888 * us which BA sessions exist.
7889 */
7890 // TODO agg
7891 for (i = 0; i < nitems(sc->sc_rxba_data); i++) {
7892 struct iwx_rxba_data *rxba = &sc->sc_rxba_data[i];
7893 if (rxba->baid == IWX_RX_REORDER_DATA_INVALID_BAID)
7894 continue;
7895 iwx_sta_rx_agg(sc, ni, rxba->tid, 0, 0, 0, 0);
7896 }
7897
7898 err = iwx_sf_config(sc, IWX_SF_INIT_OFF);
7899 if (err)
7900 return err;
7901
7902 err = iwx_disable_beacon_filter(sc);
7903 if (err) {
7904 printf("%s: could not disable beacon filter (error %d)\n",
7905 DEVNAME(sc), err);
7906 return err;
7907 }
7908
7909 /* Mark station as disassociated. */
7910 err = iwx_mac_ctxt_cmd(sc, in, IWX_FW_CTXT_ACTION_MODIFY, 0);
7911 if (err) {
7912 printf("%s: failed to update MAC\n", DEVNAME(sc));
7913 return err;
7914 }
7915
7916 return 0;
7917 }
7918
7919 static struct ieee80211_node *
iwx_node_alloc(struct ieee80211vap * vap,const uint8_t mac[IEEE80211_ADDR_LEN])7920 iwx_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
7921 {
7922 return malloc(sizeof (struct iwx_node), M_80211_NODE,
7923 M_NOWAIT | M_ZERO);
7924 }
7925
7926 #if 0
7927 int
7928 iwx_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
7929 struct ieee80211_key *k)
7930 {
7931 struct iwx_softc *sc = ic->ic_softc;
7932 struct iwx_node *in = (void *)ni;
7933 struct iwx_setkey_task_arg *a;
7934 int err;
7935
7936 if (k->k_cipher != IEEE80211_CIPHER_CCMP) {
7937 /* Fallback to software crypto for other ciphers. */
7938 err = ieee80211_set_key(ic, ni, k);
7939 if (!err && in != NULL && (k->k_flags & IEEE80211_KEY_GROUP))
7940 in->in_flags |= IWX_NODE_FLAG_HAVE_GROUP_KEY;
7941 return err;
7942 }
7943
7944 if (sc->setkey_nkeys >= nitems(sc->setkey_arg))
7945 return ENOSPC;
7946
7947 a = &sc->setkey_arg[sc->setkey_cur];
7948 a->sta_id = IWX_STATION_ID;
7949 a->ni = ni;
7950 a->k = k;
7951 sc->setkey_cur = (sc->setkey_cur + 1) % nitems(sc->setkey_arg);
7952 sc->setkey_nkeys++;
7953 iwx_add_task(sc, systq, &sc->setkey_task);
7954 return EBUSY;
7955 }
7956
7957 int
7958 iwx_add_sta_key(struct iwx_softc *sc, int sta_id, struct ieee80211_node *ni,
7959 struct ieee80211_key *k)
7960 {
7961 struct ieee80211com *ic = &sc->sc_ic;
7962 struct iwx_node *in = (void *)ni;
7963 struct iwx_add_sta_key_cmd cmd;
7964 uint32_t status;
7965 const int want_keymask = (IWX_NODE_FLAG_HAVE_PAIRWISE_KEY |
7966 IWX_NODE_FLAG_HAVE_GROUP_KEY);
7967 int err;
7968
7969 /*
7970 * Keys are stored in 'ni' so 'k' is valid if 'ni' is valid.
7971 * Currently we only implement station mode where 'ni' is always
7972 * ic->ic_bss so there is no need to validate arguments beyond this:
7973 */
7974 KASSERT(ni == ic->ic_bss);
7975
7976 memset(&cmd, 0, sizeof(cmd));
7977
7978 cmd.common.key_flags = htole16(IWX_STA_KEY_FLG_CCM |
7979 IWX_STA_KEY_FLG_WEP_KEY_MAP |
7980 ((k->k_id << IWX_STA_KEY_FLG_KEYID_POS) &
7981 IWX_STA_KEY_FLG_KEYID_MSK));
7982 if (k->k_flags & IEEE80211_KEY_GROUP) {
7983 cmd.common.key_offset = 1;
7984 cmd.common.key_flags |= htole16(IWX_STA_KEY_MULTICAST);
7985 } else
7986 cmd.common.key_offset = 0;
7987
7988 memcpy(cmd.common.key, k->k_key, MIN(sizeof(cmd.common.key), k->k_len));
7989 cmd.common.sta_id = sta_id;
7990
7991 cmd.transmit_seq_cnt = htole64(k->k_tsc);
7992
7993 status = IWX_ADD_STA_SUCCESS;
7994 err = iwx_send_cmd_pdu_status(sc, IWX_ADD_STA_KEY, sizeof(cmd), &cmd,
7995 &status);
7996 if (sc->sc_flags & IWX_FLAG_SHUTDOWN)
7997 return ECANCELED;
7998 if (!err && (status & IWX_ADD_STA_STATUS_MASK) != IWX_ADD_STA_SUCCESS)
7999 err = EIO;
8000 if (err) {
8001 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
8002 IEEE80211_REASON_AUTH_LEAVE);
8003 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
8004 return err;
8005 }
8006
8007 if (k->k_flags & IEEE80211_KEY_GROUP)
8008 in->in_flags |= IWX_NODE_FLAG_HAVE_GROUP_KEY;
8009 else
8010 in->in_flags |= IWX_NODE_FLAG_HAVE_PAIRWISE_KEY;
8011
8012 if ((in->in_flags & want_keymask) == want_keymask) {
8013 DPRINTF(("marking port %s valid\n",
8014 ether_sprintf(ni->ni_macaddr)));
8015 ni->ni_port_valid = 1;
8016 ieee80211_set_link_state(ic, LINK_STATE_UP);
8017 }
8018
8019 return 0;
8020 }
8021
8022 void
8023 iwx_setkey_task(void *arg)
8024 {
8025 struct iwx_softc *sc = arg;
8026 struct iwx_setkey_task_arg *a;
8027 int err = 0, s = splnet();
8028
8029 while (sc->setkey_nkeys > 0) {
8030 if (err || (sc->sc_flags & IWX_FLAG_SHUTDOWN))
8031 break;
8032 a = &sc->setkey_arg[sc->setkey_tail];
8033 err = iwx_add_sta_key(sc, a->sta_id, a->ni, a->k);
8034 a->sta_id = 0;
8035 a->ni = NULL;
8036 a->k = NULL;
8037 sc->setkey_tail = (sc->setkey_tail + 1) %
8038 nitems(sc->setkey_arg);
8039 sc->setkey_nkeys--;
8040 }
8041
8042 refcnt_rele_wake(&sc->task_refs);
8043 splx(s);
8044 }
8045
8046 void
8047 iwx_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
8048 struct ieee80211_key *k)
8049 {
8050 struct iwx_softc *sc = ic->ic_softc;
8051 struct iwx_add_sta_key_cmd cmd;
8052
8053 if (k->k_cipher != IEEE80211_CIPHER_CCMP) {
8054 /* Fallback to software crypto for other ciphers. */
8055 ieee80211_delete_key(ic, ni, k);
8056 return;
8057 }
8058
8059 if ((sc->sc_flags & IWX_FLAG_STA_ACTIVE) == 0)
8060 return;
8061
8062 memset(&cmd, 0, sizeof(cmd));
8063
8064 cmd.common.key_flags = htole16(IWX_STA_KEY_NOT_VALID |
8065 IWX_STA_KEY_FLG_NO_ENC | IWX_STA_KEY_FLG_WEP_KEY_MAP |
8066 ((k->k_id << IWX_STA_KEY_FLG_KEYID_POS) &
8067 IWX_STA_KEY_FLG_KEYID_MSK));
8068 memcpy(cmd.common.key, k->k_key, MIN(sizeof(cmd.common.key), k->k_len));
8069 if (k->k_flags & IEEE80211_KEY_GROUP)
8070 cmd.common.key_offset = 1;
8071 else
8072 cmd.common.key_offset = 0;
8073 cmd.common.sta_id = IWX_STATION_ID;
8074
8075 iwx_send_cmd_pdu(sc, IWX_ADD_STA_KEY, IWX_CMD_ASYNC, sizeof(cmd), &cmd);
8076 }
8077 #endif
8078
8079 static int
iwx_newstate_sub(struct ieee80211vap * vap,enum ieee80211_state nstate)8080 iwx_newstate_sub(struct ieee80211vap *vap, enum ieee80211_state nstate)
8081 {
8082 struct ieee80211com *ic = vap->iv_ic;
8083 struct iwx_softc *sc = ic->ic_softc;
8084 enum ieee80211_state ostate = vap->iv_state;
8085 int err = 0;
8086
8087 IWX_LOCK(sc);
8088
8089 if (nstate <= ostate || nstate > IEEE80211_S_RUN) {
8090 switch (ostate) {
8091 case IEEE80211_S_RUN:
8092 err = iwx_run_stop(sc);
8093 if (err)
8094 goto out;
8095 /* FALLTHROUGH */
8096 case IEEE80211_S_ASSOC:
8097 case IEEE80211_S_AUTH:
8098 if (nstate <= IEEE80211_S_AUTH) {
8099 err = iwx_deauth(sc);
8100 if (err)
8101 goto out;
8102 }
8103 /* FALLTHROUGH */
8104 case IEEE80211_S_SCAN:
8105 case IEEE80211_S_INIT:
8106 default:
8107 break;
8108 }
8109 //
8110 // /* Die now if iwx_stop() was called while we were sleeping. */
8111 // if (sc->sc_flags & IWX_FLAG_SHUTDOWN) {
8112 // refcnt_rele_wake(&sc->task_refs);
8113 // splx(s);
8114 // return;
8115 // }
8116 }
8117
8118 switch (nstate) {
8119 case IEEE80211_S_INIT:
8120 break;
8121
8122 case IEEE80211_S_SCAN:
8123 break;
8124
8125 case IEEE80211_S_AUTH:
8126 err = iwx_auth(vap, sc);
8127 break;
8128
8129 case IEEE80211_S_ASSOC:
8130 break;
8131
8132 case IEEE80211_S_RUN:
8133 err = iwx_run(vap, sc);
8134 break;
8135 default:
8136 break;
8137 }
8138
8139 out:
8140 IWX_UNLOCK(sc);
8141
8142 return (err);
8143 }
8144
8145 static int
iwx_newstate(struct ieee80211vap * vap,enum ieee80211_state nstate,int arg)8146 iwx_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8147 {
8148 struct iwx_vap *ivp = IWX_VAP(vap);
8149 struct ieee80211com *ic = vap->iv_ic;
8150 enum ieee80211_state ostate = vap->iv_state;
8151 int err;
8152
8153 /*
8154 * Prevent attempts to transition towards the same state, unless
8155 * we are scanning in which case a SCAN -> SCAN transition
8156 * triggers another scan iteration. And AUTH -> AUTH is needed
8157 * to support band-steering.
8158 */
8159 if (ostate == nstate && nstate != IEEE80211_S_SCAN &&
8160 nstate != IEEE80211_S_AUTH)
8161 return 0;
8162 IEEE80211_UNLOCK(ic);
8163 err = iwx_newstate_sub(vap, nstate);
8164 IEEE80211_LOCK(ic);
8165 if (err == 0)
8166 err = ivp->iv_newstate(vap, nstate, arg);
8167
8168 return (err);
8169 }
8170
8171 static void
iwx_endscan(struct iwx_softc * sc)8172 iwx_endscan(struct iwx_softc *sc)
8173 {
8174 struct ieee80211com *ic = &sc->sc_ic;
8175 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
8176
8177 if ((sc->sc_flags & (IWX_FLAG_SCANNING | IWX_FLAG_BGSCAN)) == 0)
8178 return;
8179
8180 sc->sc_flags &= ~(IWX_FLAG_SCANNING | IWX_FLAG_BGSCAN);
8181
8182 ieee80211_scan_done(TAILQ_FIRST(&ic->ic_vaps));
8183 wakeup(&vap->iv_state); /* wake up iwx_newstate */
8184 }
8185
8186 /*
8187 * Aging and idle timeouts for the different possible scenarios
8188 * in default configuration
8189 */
8190 static const uint32_t
8191 iwx_sf_full_timeout_def[IWX_SF_NUM_SCENARIO][IWX_SF_NUM_TIMEOUT_TYPES] = {
8192 {
8193 htole32(IWX_SF_SINGLE_UNICAST_AGING_TIMER_DEF),
8194 htole32(IWX_SF_SINGLE_UNICAST_IDLE_TIMER_DEF)
8195 },
8196 {
8197 htole32(IWX_SF_AGG_UNICAST_AGING_TIMER_DEF),
8198 htole32(IWX_SF_AGG_UNICAST_IDLE_TIMER_DEF)
8199 },
8200 {
8201 htole32(IWX_SF_MCAST_AGING_TIMER_DEF),
8202 htole32(IWX_SF_MCAST_IDLE_TIMER_DEF)
8203 },
8204 {
8205 htole32(IWX_SF_BA_AGING_TIMER_DEF),
8206 htole32(IWX_SF_BA_IDLE_TIMER_DEF)
8207 },
8208 {
8209 htole32(IWX_SF_TX_RE_AGING_TIMER_DEF),
8210 htole32(IWX_SF_TX_RE_IDLE_TIMER_DEF)
8211 },
8212 };
8213
8214 /*
8215 * Aging and idle timeouts for the different possible scenarios
8216 * in single BSS MAC configuration.
8217 */
8218 static const uint32_t
8219 iwx_sf_full_timeout[IWX_SF_NUM_SCENARIO][IWX_SF_NUM_TIMEOUT_TYPES] = {
8220 {
8221 htole32(IWX_SF_SINGLE_UNICAST_AGING_TIMER),
8222 htole32(IWX_SF_SINGLE_UNICAST_IDLE_TIMER)
8223 },
8224 {
8225 htole32(IWX_SF_AGG_UNICAST_AGING_TIMER),
8226 htole32(IWX_SF_AGG_UNICAST_IDLE_TIMER)
8227 },
8228 {
8229 htole32(IWX_SF_MCAST_AGING_TIMER),
8230 htole32(IWX_SF_MCAST_IDLE_TIMER)
8231 },
8232 {
8233 htole32(IWX_SF_BA_AGING_TIMER),
8234 htole32(IWX_SF_BA_IDLE_TIMER)
8235 },
8236 {
8237 htole32(IWX_SF_TX_RE_AGING_TIMER),
8238 htole32(IWX_SF_TX_RE_IDLE_TIMER)
8239 },
8240 };
8241
8242 static void
iwx_fill_sf_command(struct iwx_softc * sc,struct iwx_sf_cfg_cmd * sf_cmd,struct ieee80211_node * ni)8243 iwx_fill_sf_command(struct iwx_softc *sc, struct iwx_sf_cfg_cmd *sf_cmd,
8244 struct ieee80211_node *ni)
8245 {
8246 int i, j, watermark;
8247
8248 sf_cmd->watermark[IWX_SF_LONG_DELAY_ON] = htole32(IWX_SF_W_MARK_SCAN);
8249
8250 /*
8251 * If we are in association flow - check antenna configuration
8252 * capabilities of the AP station, and choose the watermark accordingly.
8253 */
8254 if (ni) {
8255 if (ni->ni_flags & IEEE80211_NODE_HT) {
8256 struct ieee80211_htrateset *htrs = &ni->ni_htrates;
8257 int hasmimo = 0;
8258 for (i = 0; i < htrs->rs_nrates; i++) {
8259 if (htrs->rs_rates[i] > 7) {
8260 hasmimo = 1;
8261 break;
8262 }
8263 }
8264 if (hasmimo)
8265 watermark = IWX_SF_W_MARK_MIMO2;
8266 else
8267 watermark = IWX_SF_W_MARK_SISO;
8268 } else {
8269 watermark = IWX_SF_W_MARK_LEGACY;
8270 }
8271 /* default watermark value for unassociated mode. */
8272 } else {
8273 watermark = IWX_SF_W_MARK_MIMO2;
8274 }
8275 sf_cmd->watermark[IWX_SF_FULL_ON] = htole32(watermark);
8276
8277 for (i = 0; i < IWX_SF_NUM_SCENARIO; i++) {
8278 for (j = 0; j < IWX_SF_NUM_TIMEOUT_TYPES; j++) {
8279 sf_cmd->long_delay_timeouts[i][j] =
8280 htole32(IWX_SF_LONG_DELAY_AGING_TIMER);
8281 }
8282 }
8283
8284 if (ni) {
8285 memcpy(sf_cmd->full_on_timeouts, iwx_sf_full_timeout,
8286 sizeof(iwx_sf_full_timeout));
8287 } else {
8288 memcpy(sf_cmd->full_on_timeouts, iwx_sf_full_timeout_def,
8289 sizeof(iwx_sf_full_timeout_def));
8290 }
8291
8292 }
8293
8294 static int
iwx_sf_config(struct iwx_softc * sc,int new_state)8295 iwx_sf_config(struct iwx_softc *sc, int new_state)
8296 {
8297 struct ieee80211com *ic = &sc->sc_ic;
8298 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
8299 struct ieee80211_node *ni = vap->iv_bss;
8300 struct iwx_sf_cfg_cmd sf_cmd = {
8301 .state = htole32(new_state),
8302 };
8303 int err = 0;
8304
8305 switch (new_state) {
8306 case IWX_SF_UNINIT:
8307 case IWX_SF_INIT_OFF:
8308 iwx_fill_sf_command(sc, &sf_cmd, NULL);
8309 break;
8310 case IWX_SF_FULL_ON:
8311 iwx_fill_sf_command(sc, &sf_cmd, ni);
8312 break;
8313 default:
8314 return EINVAL;
8315 }
8316
8317 err = iwx_send_cmd_pdu(sc, IWX_REPLY_SF_CFG_CMD, IWX_CMD_ASYNC,
8318 sizeof(sf_cmd), &sf_cmd);
8319 return err;
8320 }
8321
8322 static int
iwx_send_bt_init_conf(struct iwx_softc * sc)8323 iwx_send_bt_init_conf(struct iwx_softc *sc)
8324 {
8325 struct iwx_bt_coex_cmd bt_cmd;
8326
8327 bzero(&bt_cmd, sizeof(struct iwx_bt_coex_cmd));
8328
8329 bt_cmd.mode = htole32(IWX_BT_COEX_NW);
8330 bt_cmd.enabled_modules |= BT_COEX_SYNC2SCO_ENABLED;
8331 bt_cmd.enabled_modules |= BT_COEX_HIGH_BAND_RET;
8332
8333
8334 return iwx_send_cmd_pdu(sc, IWX_BT_CONFIG, 0, sizeof(bt_cmd),
8335 &bt_cmd);
8336 }
8337
8338 static int
iwx_send_soc_conf(struct iwx_softc * sc)8339 iwx_send_soc_conf(struct iwx_softc *sc)
8340 {
8341 struct iwx_soc_configuration_cmd cmd;
8342 int err;
8343 uint32_t cmd_id, flags = 0;
8344
8345 memset(&cmd, 0, sizeof(cmd));
8346
8347 /*
8348 * In VER_1 of this command, the discrete value is considered
8349 * an integer; In VER_2, it's a bitmask. Since we have only 2
8350 * values in VER_1, this is backwards-compatible with VER_2,
8351 * as long as we don't set any other flag bits.
8352 */
8353 if (!sc->sc_integrated) { /* VER_1 */
8354 flags = IWX_SOC_CONFIG_CMD_FLAGS_DISCRETE;
8355 } else { /* VER_2 */
8356 uint8_t scan_cmd_ver;
8357 if (sc->sc_ltr_delay != IWX_SOC_FLAGS_LTR_APPLY_DELAY_NONE)
8358 flags |= (sc->sc_ltr_delay &
8359 IWX_SOC_FLAGS_LTR_APPLY_DELAY_MASK);
8360 scan_cmd_ver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP,
8361 IWX_SCAN_REQ_UMAC);
8362 if (scan_cmd_ver != IWX_FW_CMD_VER_UNKNOWN &&
8363 scan_cmd_ver >= 2 && sc->sc_low_latency_xtal)
8364 flags |= IWX_SOC_CONFIG_CMD_FLAGS_LOW_LATENCY;
8365 }
8366 cmd.flags = htole32(flags);
8367
8368 cmd.latency = htole32(sc->sc_xtal_latency);
8369
8370 cmd_id = iwx_cmd_id(IWX_SOC_CONFIGURATION_CMD, IWX_SYSTEM_GROUP, 0);
8371 err = iwx_send_cmd_pdu(sc, cmd_id, 0, sizeof(cmd), &cmd);
8372 if (err)
8373 printf("%s: failed to set soc latency: %d\n", DEVNAME(sc), err);
8374 return err;
8375 }
8376
8377 static int
iwx_send_update_mcc_cmd(struct iwx_softc * sc,const char * alpha2)8378 iwx_send_update_mcc_cmd(struct iwx_softc *sc, const char *alpha2)
8379 {
8380 struct iwx_mcc_update_cmd mcc_cmd;
8381 struct iwx_host_cmd hcmd = {
8382 .id = IWX_MCC_UPDATE_CMD,
8383 .flags = IWX_CMD_WANT_RESP,
8384 .data = { &mcc_cmd },
8385 };
8386 struct iwx_rx_packet *pkt;
8387 struct iwx_mcc_update_resp *resp;
8388 size_t resp_len;
8389 int err;
8390
8391 memset(&mcc_cmd, 0, sizeof(mcc_cmd));
8392 mcc_cmd.mcc = htole16(alpha2[0] << 8 | alpha2[1]);
8393 if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_WIFI_MCC_UPDATE) ||
8394 isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_LAR_MULTI_MCC))
8395 mcc_cmd.source_id = IWX_MCC_SOURCE_GET_CURRENT;
8396 else
8397 mcc_cmd.source_id = IWX_MCC_SOURCE_OLD_FW;
8398
8399 hcmd.len[0] = sizeof(struct iwx_mcc_update_cmd);
8400 hcmd.resp_pkt_len = IWX_CMD_RESP_MAX;
8401
8402 err = iwx_send_cmd(sc, &hcmd);
8403 if (err)
8404 return err;
8405
8406 pkt = hcmd.resp_pkt;
8407 if (!pkt || (pkt->hdr.flags & IWX_CMD_FAILED_MSK)) {
8408 err = EIO;
8409 goto out;
8410 }
8411
8412 resp_len = iwx_rx_packet_payload_len(pkt);
8413 if (resp_len < sizeof(*resp)) {
8414 err = EIO;
8415 goto out;
8416 }
8417
8418 resp = (void *)pkt->data;
8419 if (resp_len != sizeof(*resp) +
8420 resp->n_channels * sizeof(resp->channels[0])) {
8421 err = EIO;
8422 goto out;
8423 }
8424
8425 DPRINTF(("MCC status=0x%x mcc=0x%x cap=0x%x time=0x%x geo_info=0x%x source_id=0x%d n_channels=%u\n",
8426 resp->status, resp->mcc, resp->cap, resp->time, resp->geo_info, resp->source_id, resp->n_channels));
8427
8428 out:
8429 iwx_free_resp(sc, &hcmd);
8430
8431 return err;
8432 }
8433
8434 static int
iwx_send_temp_report_ths_cmd(struct iwx_softc * sc)8435 iwx_send_temp_report_ths_cmd(struct iwx_softc *sc)
8436 {
8437 struct iwx_temp_report_ths_cmd cmd;
8438 int err;
8439
8440 /*
8441 * In order to give responsibility for critical-temperature-kill
8442 * and TX backoff to FW we need to send an empty temperature
8443 * reporting command at init time.
8444 */
8445 memset(&cmd, 0, sizeof(cmd));
8446
8447 err = iwx_send_cmd_pdu(sc,
8448 IWX_WIDE_ID(IWX_PHY_OPS_GROUP, IWX_TEMP_REPORTING_THRESHOLDS_CMD),
8449 0, sizeof(cmd), &cmd);
8450 if (err)
8451 printf("%s: TEMP_REPORT_THS_CMD command failed (error %d)\n",
8452 DEVNAME(sc), err);
8453
8454 return err;
8455 }
8456
8457 static int
iwx_init_hw(struct iwx_softc * sc)8458 iwx_init_hw(struct iwx_softc *sc)
8459 {
8460 struct ieee80211com *ic = &sc->sc_ic;
8461 int err = 0, i;
8462
8463 err = iwx_run_init_mvm_ucode(sc, 0);
8464 if (err)
8465 return err;
8466
8467 if (!iwx_nic_lock(sc))
8468 return EBUSY;
8469
8470 err = iwx_send_tx_ant_cfg(sc, iwx_fw_valid_tx_ant(sc));
8471 if (err) {
8472 printf("%s: could not init tx ant config (error %d)\n",
8473 DEVNAME(sc), err);
8474 goto err;
8475 }
8476
8477 if (sc->sc_tx_with_siso_diversity) {
8478 err = iwx_send_phy_cfg_cmd(sc);
8479 if (err) {
8480 printf("%s: could not send phy config (error %d)\n",
8481 DEVNAME(sc), err);
8482 goto err;
8483 }
8484 }
8485
8486 err = iwx_send_bt_init_conf(sc);
8487 if (err) {
8488 printf("%s: could not init bt coex (error %d)\n",
8489 DEVNAME(sc), err);
8490 return err;
8491 }
8492
8493 err = iwx_send_soc_conf(sc);
8494 if (err) {
8495 printf("%s: iwx_send_soc_conf failed\n", __func__);
8496 return err;
8497 }
8498
8499 if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_DQA_SUPPORT)) {
8500 printf("%s: === IWX_UCODE_TLV_CAPA_DQA_SUPPORT\n", __func__);
8501 err = iwx_send_dqa_cmd(sc);
8502 if (err) {
8503 printf("%s: IWX_UCODE_TLV_CAPA_DQA_SUPPORT "
8504 "failed (error %d)\n", __func__, err);
8505 return err;
8506 }
8507 }
8508 // TODO phyctxt
8509 for (i = 0; i < IWX_NUM_PHY_CTX; i++) {
8510 /*
8511 * The channel used here isn't relevant as it's
8512 * going to be overwritten in the other flows.
8513 * For now use the first channel we have.
8514 */
8515 sc->sc_phyctxt[i].id = i;
8516 sc->sc_phyctxt[i].channel = &ic->ic_channels[1];
8517 err = iwx_phy_ctxt_cmd(sc, &sc->sc_phyctxt[i], 1, 1,
8518 IWX_FW_CTXT_ACTION_ADD, 0, 0, 0);
8519 if (err) {
8520 printf("%s: could not add phy context %d (error %d)\n",
8521 DEVNAME(sc), i, err);
8522 goto err;
8523 }
8524 if (iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP,
8525 IWX_RLC_CONFIG_CMD) == 2) {
8526 err = iwx_phy_send_rlc(sc, &sc->sc_phyctxt[i], 1, 1);
8527 if (err) {
8528 printf("%s: could not configure RLC for PHY "
8529 "%d (error %d)\n", DEVNAME(sc), i, err);
8530 goto err;
8531 }
8532 }
8533 }
8534
8535 err = iwx_config_ltr(sc);
8536 if (err) {
8537 printf("%s: PCIe LTR configuration failed (error %d)\n",
8538 DEVNAME(sc), err);
8539 }
8540
8541 if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_CT_KILL_BY_FW)) {
8542 err = iwx_send_temp_report_ths_cmd(sc);
8543 if (err) {
8544 printf("%s: iwx_send_temp_report_ths_cmd failed\n",
8545 __func__);
8546 goto err;
8547 }
8548 }
8549
8550 err = iwx_power_update_device(sc);
8551 if (err) {
8552 printf("%s: could not send power command (error %d)\n",
8553 DEVNAME(sc), err);
8554 goto err;
8555 }
8556
8557 if (sc->sc_nvm.lar_enabled) {
8558 err = iwx_send_update_mcc_cmd(sc, "ZZ");
8559 if (err) {
8560 printf("%s: could not init LAR (error %d)\n",
8561 DEVNAME(sc), err);
8562 goto err;
8563 }
8564 }
8565
8566 err = iwx_config_umac_scan_reduced(sc);
8567 if (err) {
8568 printf("%s: could not configure scan (error %d)\n",
8569 DEVNAME(sc), err);
8570 goto err;
8571 }
8572
8573 err = iwx_disable_beacon_filter(sc);
8574 if (err) {
8575 printf("%s: could not disable beacon filter (error %d)\n",
8576 DEVNAME(sc), err);
8577 goto err;
8578 }
8579
8580 err:
8581 iwx_nic_unlock(sc);
8582 return err;
8583 }
8584
8585 /* Allow multicast from our BSSID. */
8586 static int
iwx_allow_mcast(struct iwx_softc * sc)8587 iwx_allow_mcast(struct iwx_softc *sc)
8588 {
8589 struct ieee80211com *ic = &sc->sc_ic;
8590 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
8591 struct iwx_node *in = IWX_NODE(vap->iv_bss);
8592 struct iwx_mcast_filter_cmd *cmd;
8593 size_t size;
8594 int err;
8595
8596 size = roundup(sizeof(*cmd), 4);
8597 cmd = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
8598 if (cmd == NULL)
8599 return ENOMEM;
8600 cmd->filter_own = 1;
8601 cmd->port_id = 0;
8602 cmd->count = 0;
8603 cmd->pass_all = 1;
8604 IEEE80211_ADDR_COPY(cmd->bssid, in->in_macaddr);
8605
8606 err = iwx_send_cmd_pdu(sc, IWX_MCAST_FILTER_CMD,
8607 0, size, cmd);
8608 free(cmd, M_DEVBUF);
8609 return err;
8610 }
8611
8612 static int
iwx_init(struct iwx_softc * sc)8613 iwx_init(struct iwx_softc *sc)
8614 {
8615 int err, generation;
8616 generation = ++sc->sc_generation;
8617 iwx_preinit(sc);
8618
8619 err = iwx_start_hw(sc);
8620 if (err) {
8621 printf("%s: iwx_start_hw failed\n", __func__);
8622 return err;
8623 }
8624
8625 err = iwx_init_hw(sc);
8626 if (err) {
8627 if (generation == sc->sc_generation)
8628 iwx_stop_device(sc);
8629 printf("%s: iwx_init_hw failed (error %d)\n", __func__, err);
8630 return err;
8631 }
8632
8633 sc->sc_flags |= IWX_FLAG_HW_INITED;
8634 callout_reset(&sc->watchdog_to, hz, iwx_watchdog, sc);
8635
8636 return 0;
8637 }
8638
8639 static void
iwx_start(struct iwx_softc * sc)8640 iwx_start(struct iwx_softc *sc)
8641 {
8642 struct ieee80211_node *ni;
8643 struct mbuf *m;
8644
8645 IWX_ASSERT_LOCKED(sc);
8646
8647 while (sc->qfullmsk == 0 && (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
8648 ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
8649 if (iwx_tx(sc, m, ni) != 0) {
8650 if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
8651 continue;
8652 }
8653 }
8654 }
8655
8656 static void
iwx_stop(struct iwx_softc * sc)8657 iwx_stop(struct iwx_softc *sc)
8658 {
8659 struct ieee80211com *ic = &sc->sc_ic;
8660 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
8661 struct iwx_vap *ivp = IWX_VAP(vap);
8662
8663 iwx_stop_device(sc);
8664
8665 /* Reset soft state. */
8666 sc->sc_generation++;
8667 ivp->phy_ctxt = NULL;
8668
8669 sc->sc_flags &= ~(IWX_FLAG_SCANNING | IWX_FLAG_BGSCAN);
8670 sc->sc_flags &= ~IWX_FLAG_MAC_ACTIVE;
8671 sc->sc_flags &= ~IWX_FLAG_BINDING_ACTIVE;
8672 sc->sc_flags &= ~IWX_FLAG_STA_ACTIVE;
8673 sc->sc_flags &= ~IWX_FLAG_TE_ACTIVE;
8674 sc->sc_flags &= ~IWX_FLAG_HW_ERR;
8675 sc->sc_flags &= ~IWX_FLAG_SHUTDOWN;
8676 sc->sc_flags &= ~IWX_FLAG_TXFLUSH;
8677
8678 sc->sc_rx_ba_sessions = 0;
8679 sc->ba_rx.start_tidmask = 0;
8680 sc->ba_rx.stop_tidmask = 0;
8681 memset(sc->aggqid, 0, sizeof(sc->aggqid));
8682 sc->ba_tx.start_tidmask = 0;
8683 sc->ba_tx.stop_tidmask = 0;
8684 }
8685
8686 static void
iwx_watchdog(void * arg)8687 iwx_watchdog(void *arg)
8688 {
8689 struct iwx_softc *sc = arg;
8690 struct ieee80211com *ic = &sc->sc_ic;
8691 int i;
8692
8693 /*
8694 * We maintain a separate timer for each Tx queue because
8695 * Tx aggregation queues can get "stuck" while other queues
8696 * keep working. The Linux driver uses a similar workaround.
8697 */
8698 for (i = 0; i < nitems(sc->sc_tx_timer); i++) {
8699 if (sc->sc_tx_timer[i] > 0) {
8700 if (--sc->sc_tx_timer[i] == 0) {
8701 printf("%s: device timeout\n", DEVNAME(sc));
8702
8703 iwx_nic_error(sc);
8704 iwx_dump_driver_status(sc);
8705 ieee80211_restart_all(ic);
8706 return;
8707 }
8708 }
8709 }
8710 callout_reset(&sc->watchdog_to, hz, iwx_watchdog, sc);
8711 }
8712
8713 /*
8714 * Note: This structure is read from the device with IO accesses,
8715 * and the reading already does the endian conversion. As it is
8716 * read with uint32_t-sized accesses, any members with a different size
8717 * need to be ordered correctly though!
8718 */
8719 struct iwx_error_event_table {
8720 uint32_t valid; /* (nonzero) valid, (0) log is empty */
8721 uint32_t error_id; /* type of error */
8722 uint32_t trm_hw_status0; /* TRM HW status */
8723 uint32_t trm_hw_status1; /* TRM HW status */
8724 uint32_t blink2; /* branch link */
8725 uint32_t ilink1; /* interrupt link */
8726 uint32_t ilink2; /* interrupt link */
8727 uint32_t data1; /* error-specific data */
8728 uint32_t data2; /* error-specific data */
8729 uint32_t data3; /* error-specific data */
8730 uint32_t bcon_time; /* beacon timer */
8731 uint32_t tsf_low; /* network timestamp function timer */
8732 uint32_t tsf_hi; /* network timestamp function timer */
8733 uint32_t gp1; /* GP1 timer register */
8734 uint32_t gp2; /* GP2 timer register */
8735 uint32_t fw_rev_type; /* firmware revision type */
8736 uint32_t major; /* uCode version major */
8737 uint32_t minor; /* uCode version minor */
8738 uint32_t hw_ver; /* HW Silicon version */
8739 uint32_t brd_ver; /* HW board version */
8740 uint32_t log_pc; /* log program counter */
8741 uint32_t frame_ptr; /* frame pointer */
8742 uint32_t stack_ptr; /* stack pointer */
8743 uint32_t hcmd; /* last host command header */
8744 uint32_t isr0; /* isr status register LMPM_NIC_ISR0:
8745 * rxtx_flag */
8746 uint32_t isr1; /* isr status register LMPM_NIC_ISR1:
8747 * host_flag */
8748 uint32_t isr2; /* isr status register LMPM_NIC_ISR2:
8749 * enc_flag */
8750 uint32_t isr3; /* isr status register LMPM_NIC_ISR3:
8751 * time_flag */
8752 uint32_t isr4; /* isr status register LMPM_NIC_ISR4:
8753 * wico interrupt */
8754 uint32_t last_cmd_id; /* last HCMD id handled by the firmware */
8755 uint32_t wait_event; /* wait event() caller address */
8756 uint32_t l2p_control; /* L2pControlField */
8757 uint32_t l2p_duration; /* L2pDurationField */
8758 uint32_t l2p_mhvalid; /* L2pMhValidBits */
8759 uint32_t l2p_addr_match; /* L2pAddrMatchStat */
8760 uint32_t lmpm_pmg_sel; /* indicate which clocks are turned on
8761 * (LMPM_PMG_SEL) */
8762 uint32_t u_timestamp; /* indicate when the date and time of the
8763 * compilation */
8764 uint32_t flow_handler; /* FH read/write pointers, RX credit */
8765 } __packed /* LOG_ERROR_TABLE_API_S_VER_3 */;
8766
8767 /*
8768 * UMAC error struct - relevant starting from family 8000 chip.
8769 * Note: This structure is read from the device with IO accesses,
8770 * and the reading already does the endian conversion. As it is
8771 * read with u32-sized accesses, any members with a different size
8772 * need to be ordered correctly though!
8773 */
8774 struct iwx_umac_error_event_table {
8775 uint32_t valid; /* (nonzero) valid, (0) log is empty */
8776 uint32_t error_id; /* type of error */
8777 uint32_t blink1; /* branch link */
8778 uint32_t blink2; /* branch link */
8779 uint32_t ilink1; /* interrupt link */
8780 uint32_t ilink2; /* interrupt link */
8781 uint32_t data1; /* error-specific data */
8782 uint32_t data2; /* error-specific data */
8783 uint32_t data3; /* error-specific data */
8784 uint32_t umac_major;
8785 uint32_t umac_minor;
8786 uint32_t frame_pointer; /* core register 27*/
8787 uint32_t stack_pointer; /* core register 28 */
8788 uint32_t cmd_header; /* latest host cmd sent to UMAC */
8789 uint32_t nic_isr_pref; /* ISR status register */
8790 } __packed;
8791
8792 #define ERROR_START_OFFSET (1 * sizeof(uint32_t))
8793 #define ERROR_ELEM_SIZE (7 * sizeof(uint32_t))
8794
8795 static void
iwx_nic_umac_error(struct iwx_softc * sc)8796 iwx_nic_umac_error(struct iwx_softc *sc)
8797 {
8798 struct iwx_umac_error_event_table table;
8799 uint32_t base;
8800
8801 base = sc->sc_uc.uc_umac_error_event_table;
8802
8803 if (base < 0x400000) {
8804 printf("%s: Invalid error log pointer 0x%08x\n",
8805 DEVNAME(sc), base);
8806 return;
8807 }
8808
8809 if (iwx_read_mem(sc, base, &table, sizeof(table)/sizeof(uint32_t))) {
8810 printf("%s: reading errlog failed\n", DEVNAME(sc));
8811 return;
8812 }
8813
8814 if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
8815 printf("%s: Start UMAC Error Log Dump:\n", DEVNAME(sc));
8816 printf("%s: Status: 0x%x, count: %d\n", DEVNAME(sc),
8817 sc->sc_flags, table.valid);
8818 }
8819
8820 printf("%s: 0x%08X | %s\n", DEVNAME(sc), table.error_id,
8821 iwx_desc_lookup(table.error_id));
8822 printf("%s: 0x%08X | umac branchlink1\n", DEVNAME(sc), table.blink1);
8823 printf("%s: 0x%08X | umac branchlink2\n", DEVNAME(sc), table.blink2);
8824 printf("%s: 0x%08X | umac interruptlink1\n", DEVNAME(sc), table.ilink1);
8825 printf("%s: 0x%08X | umac interruptlink2\n", DEVNAME(sc), table.ilink2);
8826 printf("%s: 0x%08X | umac data1\n", DEVNAME(sc), table.data1);
8827 printf("%s: 0x%08X | umac data2\n", DEVNAME(sc), table.data2);
8828 printf("%s: 0x%08X | umac data3\n", DEVNAME(sc), table.data3);
8829 printf("%s: 0x%08X | umac major\n", DEVNAME(sc), table.umac_major);
8830 printf("%s: 0x%08X | umac minor\n", DEVNAME(sc), table.umac_minor);
8831 printf("%s: 0x%08X | frame pointer\n", DEVNAME(sc),
8832 table.frame_pointer);
8833 printf("%s: 0x%08X | stack pointer\n", DEVNAME(sc),
8834 table.stack_pointer);
8835 printf("%s: 0x%08X | last host cmd\n", DEVNAME(sc), table.cmd_header);
8836 printf("%s: 0x%08X | isr status reg\n", DEVNAME(sc),
8837 table.nic_isr_pref);
8838 }
8839
8840 #define IWX_FW_SYSASSERT_CPU_MASK 0xf0000000
8841 static struct {
8842 const char *name;
8843 uint8_t num;
8844 } advanced_lookup[] = {
8845 { "NMI_INTERRUPT_WDG", 0x34 },
8846 { "SYSASSERT", 0x35 },
8847 { "UCODE_VERSION_MISMATCH", 0x37 },
8848 { "BAD_COMMAND", 0x38 },
8849 { "BAD_COMMAND", 0x39 },
8850 { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
8851 { "FATAL_ERROR", 0x3D },
8852 { "NMI_TRM_HW_ERR", 0x46 },
8853 { "NMI_INTERRUPT_TRM", 0x4C },
8854 { "NMI_INTERRUPT_BREAK_POINT", 0x54 },
8855 { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C },
8856 { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 },
8857 { "NMI_INTERRUPT_HOST", 0x66 },
8858 { "NMI_INTERRUPT_LMAC_FATAL", 0x70 },
8859 { "NMI_INTERRUPT_UMAC_FATAL", 0x71 },
8860 { "NMI_INTERRUPT_OTHER_LMAC_FATAL", 0x73 },
8861 { "NMI_INTERRUPT_ACTION_PT", 0x7C },
8862 { "NMI_INTERRUPT_UNKNOWN", 0x84 },
8863 { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 },
8864 { "ADVANCED_SYSASSERT", 0 },
8865 };
8866
8867 static const char *
iwx_desc_lookup(uint32_t num)8868 iwx_desc_lookup(uint32_t num)
8869 {
8870 int i;
8871
8872 for (i = 0; i < nitems(advanced_lookup) - 1; i++)
8873 if (advanced_lookup[i].num ==
8874 (num & ~IWX_FW_SYSASSERT_CPU_MASK))
8875 return advanced_lookup[i].name;
8876
8877 /* No entry matches 'num', so it is the last: ADVANCED_SYSASSERT */
8878 return advanced_lookup[i].name;
8879 }
8880
8881 /*
8882 * Support for dumping the error log seemed like a good idea ...
8883 * but it's mostly hex junk and the only sensible thing is the
8884 * hw/ucode revision (which we know anyway). Since it's here,
8885 * I'll just leave it in, just in case e.g. the Intel guys want to
8886 * help us decipher some "ADVANCED_SYSASSERT" later.
8887 */
8888 static void
iwx_nic_error(struct iwx_softc * sc)8889 iwx_nic_error(struct iwx_softc *sc)
8890 {
8891 struct iwx_error_event_table table;
8892 uint32_t base;
8893
8894 printf("%s: dumping device error log\n", DEVNAME(sc));
8895 printf("%s: GOS-3758: 1\n", __func__);
8896 base = sc->sc_uc.uc_lmac_error_event_table[0];
8897 printf("%s: GOS-3758: 2\n", __func__);
8898 if (base < 0x400000) {
8899 printf("%s: Invalid error log pointer 0x%08x\n",
8900 DEVNAME(sc), base);
8901 return;
8902 }
8903
8904 printf("%s: GOS-3758: 3\n", __func__);
8905 if (iwx_read_mem(sc, base, &table, sizeof(table)/sizeof(uint32_t))) {
8906 printf("%s: reading errlog failed\n", DEVNAME(sc));
8907 return;
8908 }
8909
8910 printf("%s: GOS-3758: 4\n", __func__);
8911 if (!table.valid) {
8912 printf("%s: errlog not found, skipping\n", DEVNAME(sc));
8913 return;
8914 }
8915
8916 printf("%s: GOS-3758: 5\n", __func__);
8917 if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
8918 printf("%s: Start Error Log Dump:\n", DEVNAME(sc));
8919 printf("%s: Status: 0x%x, count: %d\n", DEVNAME(sc),
8920 sc->sc_flags, table.valid);
8921 }
8922
8923 printf("%s: GOS-3758: 6\n", __func__);
8924 printf("%s: 0x%08X | %-28s\n", DEVNAME(sc), table.error_id,
8925 iwx_desc_lookup(table.error_id));
8926 printf("%s: %08X | trm_hw_status0\n", DEVNAME(sc),
8927 table.trm_hw_status0);
8928 printf("%s: %08X | trm_hw_status1\n", DEVNAME(sc),
8929 table.trm_hw_status1);
8930 printf("%s: %08X | branchlink2\n", DEVNAME(sc), table.blink2);
8931 printf("%s: %08X | interruptlink1\n", DEVNAME(sc), table.ilink1);
8932 printf("%s: %08X | interruptlink2\n", DEVNAME(sc), table.ilink2);
8933 printf("%s: %08X | data1\n", DEVNAME(sc), table.data1);
8934 printf("%s: %08X | data2\n", DEVNAME(sc), table.data2);
8935 printf("%s: %08X | data3\n", DEVNAME(sc), table.data3);
8936 printf("%s: %08X | beacon time\n", DEVNAME(sc), table.bcon_time);
8937 printf("%s: %08X | tsf low\n", DEVNAME(sc), table.tsf_low);
8938 printf("%s: %08X | tsf hi\n", DEVNAME(sc), table.tsf_hi);
8939 printf("%s: %08X | time gp1\n", DEVNAME(sc), table.gp1);
8940 printf("%s: %08X | time gp2\n", DEVNAME(sc), table.gp2);
8941 printf("%s: %08X | uCode revision type\n", DEVNAME(sc),
8942 table.fw_rev_type);
8943 printf("%s: %08X | uCode version major\n", DEVNAME(sc),
8944 table.major);
8945 printf("%s: %08X | uCode version minor\n", DEVNAME(sc),
8946 table.minor);
8947 printf("%s: %08X | hw version\n", DEVNAME(sc), table.hw_ver);
8948 printf("%s: %08X | board version\n", DEVNAME(sc), table.brd_ver);
8949 printf("%s: %08X | hcmd\n", DEVNAME(sc), table.hcmd);
8950 printf("%s: %08X | isr0\n", DEVNAME(sc), table.isr0);
8951 printf("%s: %08X | isr1\n", DEVNAME(sc), table.isr1);
8952 printf("%s: %08X | isr2\n", DEVNAME(sc), table.isr2);
8953 printf("%s: %08X | isr3\n", DEVNAME(sc), table.isr3);
8954 printf("%s: %08X | isr4\n", DEVNAME(sc), table.isr4);
8955 printf("%s: %08X | last cmd Id\n", DEVNAME(sc), table.last_cmd_id);
8956 printf("%s: %08X | wait_event\n", DEVNAME(sc), table.wait_event);
8957 printf("%s: %08X | l2p_control\n", DEVNAME(sc), table.l2p_control);
8958 printf("%s: %08X | l2p_duration\n", DEVNAME(sc), table.l2p_duration);
8959 printf("%s: %08X | l2p_mhvalid\n", DEVNAME(sc), table.l2p_mhvalid);
8960 printf("%s: %08X | l2p_addr_match\n", DEVNAME(sc), table.l2p_addr_match);
8961 printf("%s: %08X | lmpm_pmg_sel\n", DEVNAME(sc), table.lmpm_pmg_sel);
8962 printf("%s: %08X | timestamp\n", DEVNAME(sc), table.u_timestamp);
8963 printf("%s: %08X | flow_handler\n", DEVNAME(sc), table.flow_handler);
8964
8965 if (sc->sc_uc.uc_umac_error_event_table)
8966 iwx_nic_umac_error(sc);
8967 }
8968
8969 static void
iwx_dump_driver_status(struct iwx_softc * sc)8970 iwx_dump_driver_status(struct iwx_softc *sc)
8971 {
8972 struct ieee80211com *ic = &sc->sc_ic;
8973 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
8974 enum ieee80211_state state = vap->iv_state;
8975 int i;
8976
8977 printf("driver status:\n");
8978 for (i = 0; i < nitems(sc->txq); i++) {
8979 struct iwx_tx_ring *ring = &sc->txq[i];
8980 printf(" tx ring %2d: qid=%-2d cur=%-3d "
8981 "cur_hw=%-3d queued=%-3d\n",
8982 i, ring->qid, ring->cur, ring->cur_hw,
8983 ring->queued);
8984 }
8985 printf(" rx ring: cur=%d\n", sc->rxq.cur);
8986 printf(" 802.11 state %s\n", ieee80211_state_name[state]);
8987 }
8988
8989 #define SYNC_RESP_STRUCT(_var_, _pkt_) \
8990 do { \
8991 bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); \
8992 _var_ = (void *)((_pkt_)+1); \
8993 } while (/*CONSTCOND*/0)
8994
8995 static int
iwx_rx_pkt_valid(struct iwx_rx_packet * pkt)8996 iwx_rx_pkt_valid(struct iwx_rx_packet *pkt)
8997 {
8998 int qid, idx, code;
8999
9000 qid = pkt->hdr.qid & ~0x80;
9001 idx = pkt->hdr.idx;
9002 code = IWX_WIDE_ID(pkt->hdr.flags, pkt->hdr.code);
9003
9004 return (!(qid == 0 && idx == 0 && code == 0) &&
9005 pkt->len_n_flags != htole32(IWX_FH_RSCSR_FRAME_INVALID));
9006 }
9007
9008 static void
iwx_rx_pkt(struct iwx_softc * sc,struct iwx_rx_data * data,struct mbuf * ml)9009 iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *data, struct mbuf *ml)
9010 {
9011 struct ieee80211com *ic = &sc->sc_ic;
9012 struct iwx_rx_packet *pkt, *nextpkt;
9013 uint32_t offset = 0, nextoff = 0, nmpdu = 0, len;
9014 struct mbuf *m0, *m;
9015 const size_t minsz = sizeof(pkt->len_n_flags) + sizeof(pkt->hdr);
9016 int qid, idx, code, handled = 1;
9017
9018 m0 = data->m;
9019 while (m0 && offset + minsz < IWX_RBUF_SIZE) {
9020 pkt = (struct iwx_rx_packet *)(m0->m_data + offset);
9021 qid = pkt->hdr.qid;
9022 idx = pkt->hdr.idx;
9023 code = IWX_WIDE_ID(pkt->hdr.flags, pkt->hdr.code);
9024
9025 if (!iwx_rx_pkt_valid(pkt))
9026 break;
9027
9028 /*
9029 * XXX Intel inside (tm)
9030 * Any commands in the LONG_GROUP could actually be in the
9031 * LEGACY group. Firmware API versions >= 50 reject commands
9032 * in group 0, forcing us to use this hack.
9033 */
9034 if (iwx_cmd_groupid(code) == IWX_LONG_GROUP) {
9035 struct iwx_tx_ring *ring = &sc->txq[qid];
9036 struct iwx_tx_data *txdata = &ring->data[idx];
9037 if (txdata->flags & IWX_TXDATA_FLAG_CMD_IS_NARROW)
9038 code = iwx_cmd_opcode(code);
9039 }
9040
9041 len = sizeof(pkt->len_n_flags) + iwx_rx_packet_len(pkt);
9042 if (len < minsz || len > (IWX_RBUF_SIZE - offset))
9043 break;
9044
9045 // TODO ???
9046 if (code == IWX_REPLY_RX_MPDU_CMD && ++nmpdu == 1) {
9047 /* Take mbuf m0 off the RX ring. */
9048 if (iwx_rx_addbuf(sc, IWX_RBUF_SIZE, sc->rxq.cur)) {
9049 break;
9050 }
9051 KASSERT((data->m != m0), ("%s: data->m != m0", __func__));
9052 }
9053
9054 switch (code) {
9055 case IWX_REPLY_RX_PHY_CMD:
9056 /* XXX-THJ: I've not managed to hit this path in testing */
9057 iwx_rx_rx_phy_cmd(sc, pkt, data);
9058 break;
9059
9060 case IWX_REPLY_RX_MPDU_CMD: {
9061 size_t maxlen = IWX_RBUF_SIZE - offset - minsz;
9062 nextoff = offset +
9063 roundup(len, IWX_FH_RSCSR_FRAME_ALIGN);
9064 nextpkt = (struct iwx_rx_packet *)
9065 (m0->m_data + nextoff);
9066 /* AX210 devices ship only one packet per Rx buffer. */
9067 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210 ||
9068 nextoff + minsz >= IWX_RBUF_SIZE ||
9069 !iwx_rx_pkt_valid(nextpkt)) {
9070 /* No need to copy last frame in buffer. */
9071 if (offset > 0)
9072 m_adj(m0, offset);
9073 iwx_rx_mpdu_mq(sc, m0, pkt->data, maxlen);
9074 m0 = NULL; /* stack owns m0 now; abort loop */
9075 } else {
9076 /*
9077 * Create an mbuf which points to the current
9078 * packet. Always copy from offset zero to
9079 * preserve m_pkthdr.
9080 */
9081 m = m_copym(m0, 0, M_COPYALL, M_NOWAIT);
9082 if (m == NULL) {
9083 m_freem(m0);
9084 m0 = NULL;
9085 break;
9086 }
9087 m_adj(m, offset);
9088 iwx_rx_mpdu_mq(sc, m, pkt->data, maxlen);
9089 }
9090 break;
9091 }
9092
9093 // case IWX_BAR_FRAME_RELEASE:
9094 // iwx_rx_bar_frame_release(sc, pkt, ml);
9095 // break;
9096 //
9097 case IWX_TX_CMD:
9098 iwx_rx_tx_cmd(sc, pkt, data);
9099 break;
9100
9101 case IWX_BA_NOTIF:
9102 iwx_rx_compressed_ba(sc, pkt);
9103 break;
9104
9105 case IWX_MISSED_BEACONS_NOTIFICATION:
9106 IWX_DPRINTF(sc, IWX_DEBUG_BEACON,
9107 "%s: IWX_MISSED_BEACONS_NOTIFICATION\n",
9108 __func__);
9109 iwx_rx_bmiss(sc, pkt, data);
9110 break;
9111
9112 case IWX_MFUART_LOAD_NOTIFICATION:
9113 break;
9114
9115 case IWX_ALIVE: {
9116 struct iwx_alive_resp_v4 *resp4;
9117 struct iwx_alive_resp_v5 *resp5;
9118 struct iwx_alive_resp_v6 *resp6;
9119
9120 DPRINTF(("%s: firmware alive\n", __func__));
9121 sc->sc_uc.uc_ok = 0;
9122
9123 /*
9124 * For v5 and above, we can check the version, for older
9125 * versions we need to check the size.
9126 */
9127 if (iwx_lookup_notif_ver(sc, IWX_LEGACY_GROUP,
9128 IWX_ALIVE) == 6) {
9129 SYNC_RESP_STRUCT(resp6, pkt);
9130 if (iwx_rx_packet_payload_len(pkt) !=
9131 sizeof(*resp6)) {
9132 sc->sc_uc.uc_intr = 1;
9133 wakeup(&sc->sc_uc);
9134 break;
9135 }
9136 sc->sc_uc.uc_lmac_error_event_table[0] = le32toh(
9137 resp6->lmac_data[0].dbg_ptrs.error_event_table_ptr);
9138 sc->sc_uc.uc_lmac_error_event_table[1] = le32toh(
9139 resp6->lmac_data[1].dbg_ptrs.error_event_table_ptr);
9140 sc->sc_uc.uc_log_event_table = le32toh(
9141 resp6->lmac_data[0].dbg_ptrs.log_event_table_ptr);
9142 sc->sc_uc.uc_umac_error_event_table = le32toh(
9143 resp6->umac_data.dbg_ptrs.error_info_addr);
9144 sc->sc_sku_id[0] =
9145 le32toh(resp6->sku_id.data[0]);
9146 sc->sc_sku_id[1] =
9147 le32toh(resp6->sku_id.data[1]);
9148 sc->sc_sku_id[2] =
9149 le32toh(resp6->sku_id.data[2]);
9150 if (resp6->status == IWX_ALIVE_STATUS_OK) {
9151 sc->sc_uc.uc_ok = 1;
9152 }
9153 } else if (iwx_lookup_notif_ver(sc, IWX_LEGACY_GROUP,
9154 IWX_ALIVE) == 5) {
9155 SYNC_RESP_STRUCT(resp5, pkt);
9156 if (iwx_rx_packet_payload_len(pkt) !=
9157 sizeof(*resp5)) {
9158 sc->sc_uc.uc_intr = 1;
9159 wakeup(&sc->sc_uc);
9160 break;
9161 }
9162 sc->sc_uc.uc_lmac_error_event_table[0] = le32toh(
9163 resp5->lmac_data[0].dbg_ptrs.error_event_table_ptr);
9164 sc->sc_uc.uc_lmac_error_event_table[1] = le32toh(
9165 resp5->lmac_data[1].dbg_ptrs.error_event_table_ptr);
9166 sc->sc_uc.uc_log_event_table = le32toh(
9167 resp5->lmac_data[0].dbg_ptrs.log_event_table_ptr);
9168 sc->sc_uc.uc_umac_error_event_table = le32toh(
9169 resp5->umac_data.dbg_ptrs.error_info_addr);
9170 sc->sc_sku_id[0] =
9171 le32toh(resp5->sku_id.data[0]);
9172 sc->sc_sku_id[1] =
9173 le32toh(resp5->sku_id.data[1]);
9174 sc->sc_sku_id[2] =
9175 le32toh(resp5->sku_id.data[2]);
9176 if (resp5->status == IWX_ALIVE_STATUS_OK)
9177 sc->sc_uc.uc_ok = 1;
9178 } else if (iwx_rx_packet_payload_len(pkt) == sizeof(*resp4)) {
9179 SYNC_RESP_STRUCT(resp4, pkt);
9180 sc->sc_uc.uc_lmac_error_event_table[0] = le32toh(
9181 resp4->lmac_data[0].dbg_ptrs.error_event_table_ptr);
9182 sc->sc_uc.uc_lmac_error_event_table[1] = le32toh(
9183 resp4->lmac_data[1].dbg_ptrs.error_event_table_ptr);
9184 sc->sc_uc.uc_log_event_table = le32toh(
9185 resp4->lmac_data[0].dbg_ptrs.log_event_table_ptr);
9186 sc->sc_uc.uc_umac_error_event_table = le32toh(
9187 resp4->umac_data.dbg_ptrs.error_info_addr);
9188 if (resp4->status == IWX_ALIVE_STATUS_OK)
9189 sc->sc_uc.uc_ok = 1;
9190 } else
9191 printf("unknown payload version");
9192
9193 sc->sc_uc.uc_intr = 1;
9194 wakeup(&sc->sc_uc);
9195 break;
9196 }
9197
9198 /*
9199 * TODO: is this the right struct to use? Look at what
9200 * mvm is doing for statistics notification (eg
9201 * iwl_mvm_handle_rx_statistics() .
9202 */
9203 case IWX_STATISTICS_NOTIFICATION: {
9204 struct iwx_notif_statistics *stats;
9205 SYNC_RESP_STRUCT(stats, pkt);
9206 memcpy(&sc->sc_stats, stats, sizeof(sc->sc_stats));
9207 sc->sc_noise = iwx_get_noise(sc, &stats->rx.general);
9208 break;
9209 }
9210
9211 case IWX_DTS_MEASUREMENT_NOTIFICATION:
9212 case IWX_WIDE_ID(IWX_PHY_OPS_GROUP,
9213 IWX_DTS_MEASUREMENT_NOTIF_WIDE):
9214 case IWX_WIDE_ID(IWX_PHY_OPS_GROUP,
9215 IWX_TEMP_REPORTING_THRESHOLDS_CMD):
9216 break;
9217
9218 case IWX_WIDE_ID(IWX_PHY_OPS_GROUP,
9219 IWX_CT_KILL_NOTIFICATION): {
9220 struct iwx_ct_kill_notif *notif;
9221 SYNC_RESP_STRUCT(notif, pkt);
9222 printf("%s: device at critical temperature (%u degC), "
9223 "stopping device\n",
9224 DEVNAME(sc), le16toh(notif->temperature));
9225 sc->sc_flags |= IWX_FLAG_HW_ERR;
9226 ieee80211_restart_all(ic);
9227 break;
9228 }
9229
9230 case IWX_WIDE_ID(IWX_DATA_PATH_GROUP,
9231 IWX_SCD_QUEUE_CONFIG_CMD):
9232 case IWX_WIDE_ID(IWX_DATA_PATH_GROUP,
9233 IWX_RX_BAID_ALLOCATION_CONFIG_CMD):
9234 case IWX_WIDE_ID(IWX_MAC_CONF_GROUP,
9235 IWX_SESSION_PROTECTION_CMD):
9236 case IWX_WIDE_ID(IWX_REGULATORY_AND_NVM_GROUP,
9237 IWX_NVM_GET_INFO):
9238 case IWX_ADD_STA_KEY:
9239 case IWX_PHY_CONFIGURATION_CMD:
9240 case IWX_TX_ANT_CONFIGURATION_CMD:
9241 case IWX_ADD_STA:
9242 case IWX_MAC_CONTEXT_CMD:
9243 case IWX_REPLY_SF_CFG_CMD:
9244 case IWX_POWER_TABLE_CMD:
9245 case IWX_LTR_CONFIG:
9246 case IWX_PHY_CONTEXT_CMD:
9247 case IWX_BINDING_CONTEXT_CMD:
9248 case IWX_WIDE_ID(IWX_LONG_GROUP, IWX_SCAN_CFG_CMD):
9249 case IWX_WIDE_ID(IWX_LONG_GROUP, IWX_SCAN_REQ_UMAC):
9250 case IWX_WIDE_ID(IWX_LONG_GROUP, IWX_SCAN_ABORT_UMAC):
9251 case IWX_REPLY_BEACON_FILTERING_CMD:
9252 case IWX_MAC_PM_POWER_TABLE:
9253 case IWX_TIME_QUOTA_CMD:
9254 case IWX_REMOVE_STA:
9255 case IWX_TXPATH_FLUSH:
9256 case IWX_BT_CONFIG:
9257 case IWX_MCC_UPDATE_CMD:
9258 case IWX_TIME_EVENT_CMD:
9259 case IWX_STATISTICS_CMD:
9260 case IWX_SCD_QUEUE_CFG: {
9261 size_t pkt_len;
9262
9263 if (sc->sc_cmd_resp_pkt[idx] == NULL)
9264 break;
9265
9266 bus_dmamap_sync(sc->rxq.data_dmat, data->map,
9267 BUS_DMASYNC_POSTREAD);
9268
9269 pkt_len = sizeof(pkt->len_n_flags) +
9270 iwx_rx_packet_len(pkt);
9271
9272 if ((pkt->hdr.flags & IWX_CMD_FAILED_MSK) ||
9273 pkt_len < sizeof(*pkt) ||
9274 pkt_len > sc->sc_cmd_resp_len[idx]) {
9275 free(sc->sc_cmd_resp_pkt[idx], M_DEVBUF);
9276 sc->sc_cmd_resp_pkt[idx] = NULL;
9277 break;
9278 }
9279
9280 bus_dmamap_sync(sc->rxq.data_dmat, data->map,
9281 BUS_DMASYNC_POSTREAD);
9282 memcpy(sc->sc_cmd_resp_pkt[idx], pkt, pkt_len);
9283 break;
9284 }
9285
9286 case IWX_INIT_COMPLETE_NOTIF:
9287 sc->sc_init_complete |= IWX_INIT_COMPLETE;
9288 wakeup(&sc->sc_init_complete);
9289 break;
9290
9291 case IWX_SCAN_COMPLETE_UMAC: {
9292 DPRINTF(("%s: >>> IWX_SCAN_COMPLETE_UMAC\n", __func__));
9293 struct iwx_umac_scan_complete *notif __attribute__((unused));
9294 SYNC_RESP_STRUCT(notif, pkt);
9295 DPRINTF(("%s: scan complete notif->status=%d\n", __func__,
9296 notif->status));
9297 ieee80211_runtask(&sc->sc_ic, &sc->sc_es_task);
9298 iwx_endscan(sc);
9299 break;
9300 }
9301
9302 case IWX_SCAN_ITERATION_COMPLETE_UMAC: {
9303 DPRINTF(("%s: >>> IWX_SCAN_ITERATION_COMPLETE_UMAC\n",
9304 __func__));
9305 struct iwx_umac_scan_iter_complete_notif *notif __attribute__((unused));
9306 SYNC_RESP_STRUCT(notif, pkt);
9307 DPRINTF(("%s: iter scan complete notif->status=%d\n", __func__,
9308 notif->status));
9309 iwx_endscan(sc);
9310 break;
9311 }
9312
9313 case IWX_MCC_CHUB_UPDATE_CMD: {
9314 struct iwx_mcc_chub_notif *notif;
9315 SYNC_RESP_STRUCT(notif, pkt);
9316 iwx_mcc_update(sc, notif);
9317 break;
9318 }
9319
9320 case IWX_REPLY_ERROR: {
9321 struct iwx_error_resp *resp;
9322 SYNC_RESP_STRUCT(resp, pkt);
9323 printf("%s: firmware error 0x%x, cmd 0x%x\n",
9324 DEVNAME(sc), le32toh(resp->error_type),
9325 resp->cmd_id);
9326 break;
9327 }
9328
9329 case IWX_TIME_EVENT_NOTIFICATION: {
9330 struct iwx_time_event_notif *notif;
9331 uint32_t action;
9332 SYNC_RESP_STRUCT(notif, pkt);
9333
9334 if (sc->sc_time_event_uid != le32toh(notif->unique_id))
9335 break;
9336 action = le32toh(notif->action);
9337 if (action & IWX_TE_V2_NOTIF_HOST_EVENT_END)
9338 sc->sc_flags &= ~IWX_FLAG_TE_ACTIVE;
9339 break;
9340 }
9341
9342 case IWX_WIDE_ID(IWX_MAC_CONF_GROUP,
9343 IWX_SESSION_PROTECTION_NOTIF): {
9344 struct iwx_session_prot_notif *notif;
9345 uint32_t status, start, conf_id;
9346
9347 SYNC_RESP_STRUCT(notif, pkt);
9348
9349 status = le32toh(notif->status);
9350 start = le32toh(notif->start);
9351 conf_id = le32toh(notif->conf_id);
9352 /* Check for end of successful PROTECT_CONF_ASSOC. */
9353 if (status == 1 && start == 0 &&
9354 conf_id == IWX_SESSION_PROTECT_CONF_ASSOC)
9355 sc->sc_flags &= ~IWX_FLAG_TE_ACTIVE;
9356 break;
9357 }
9358
9359 case IWX_WIDE_ID(IWX_SYSTEM_GROUP,
9360 IWX_FSEQ_VER_MISMATCH_NOTIFICATION):
9361 break;
9362
9363 /*
9364 * Firmware versions 21 and 22 generate some DEBUG_LOG_MSG
9365 * messages. Just ignore them for now.
9366 */
9367 case IWX_DEBUG_LOG_MSG:
9368 break;
9369
9370 case IWX_MCAST_FILTER_CMD:
9371 break;
9372
9373 case IWX_WIDE_ID(IWX_DATA_PATH_GROUP, IWX_DQA_ENABLE_CMD):
9374 break;
9375
9376 case IWX_WIDE_ID(IWX_SYSTEM_GROUP, IWX_SOC_CONFIGURATION_CMD):
9377 break;
9378
9379 case IWX_WIDE_ID(IWX_SYSTEM_GROUP, IWX_INIT_EXTENDED_CFG_CMD):
9380 break;
9381
9382 case IWX_WIDE_ID(IWX_REGULATORY_AND_NVM_GROUP,
9383 IWX_NVM_ACCESS_COMPLETE):
9384 break;
9385
9386 case IWX_WIDE_ID(IWX_DATA_PATH_GROUP, IWX_RX_NO_DATA_NOTIF):
9387 break; /* happens in monitor mode; ignore for now */
9388
9389 case IWX_WIDE_ID(IWX_DATA_PATH_GROUP, IWX_TLC_MNG_CONFIG_CMD):
9390 break;
9391
9392 case IWX_WIDE_ID(IWX_DATA_PATH_GROUP,
9393 IWX_TLC_MNG_UPDATE_NOTIF): {
9394 struct iwx_tlc_update_notif *notif;
9395 SYNC_RESP_STRUCT(notif, pkt);
9396 (void)notif;
9397 if (iwx_rx_packet_payload_len(pkt) == sizeof(*notif))
9398 iwx_rs_update(sc, notif);
9399 break;
9400 }
9401
9402 case IWX_WIDE_ID(IWX_DATA_PATH_GROUP, IWX_RLC_CONFIG_CMD):
9403 break;
9404
9405 /* undocumented notification from iwx-ty-a0-gf-a0-77 image */
9406 case IWX_WIDE_ID(IWX_DATA_PATH_GROUP, 0xf8):
9407 break;
9408
9409 case IWX_WIDE_ID(IWX_REGULATORY_AND_NVM_GROUP,
9410 IWX_PNVM_INIT_COMPLETE):
9411 DPRINTF(("%s: IWX_PNVM_INIT_COMPLETE\n", __func__));
9412 sc->sc_init_complete |= IWX_PNVM_COMPLETE;
9413 wakeup(&sc->sc_init_complete);
9414 break;
9415
9416 default:
9417 handled = 0;
9418 /* XXX wulf: Get rid of bluetooth-related spam */
9419 if ((code == 0xc2 && pkt->len_n_flags == 0x0000000c) ||
9420 (code == 0xce && pkt->len_n_flags == 0x2000002c))
9421 break;
9422 printf("%s: unhandled firmware response 0x%x/0x%x "
9423 "rx ring %d[%d]\n",
9424 DEVNAME(sc), code, pkt->len_n_flags,
9425 (qid & ~0x80), idx);
9426 break;
9427 }
9428
9429 /*
9430 * uCode sets bit 0x80 when it originates the notification,
9431 * i.e. when the notification is not a direct response to a
9432 * command sent by the driver.
9433 * For example, uCode issues IWX_REPLY_RX when it sends a
9434 * received frame to the driver.
9435 */
9436 if (handled && !(qid & (1 << 7))) {
9437 iwx_cmd_done(sc, qid, idx, code);
9438 }
9439
9440 offset += roundup(len, IWX_FH_RSCSR_FRAME_ALIGN);
9441
9442 /* AX210 devices ship only one packet per Rx buffer. */
9443 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)
9444 break;
9445 }
9446
9447 if (m0 && m0 != data->m)
9448 m_freem(m0);
9449 }
9450
9451 static void
iwx_notif_intr(struct iwx_softc * sc)9452 iwx_notif_intr(struct iwx_softc *sc)
9453 {
9454 struct mbuf m;
9455 uint16_t hw;
9456
9457 bus_dmamap_sync(sc->rxq.stat_dma.tag, sc->rxq.stat_dma.map,
9458 BUS_DMASYNC_POSTREAD);
9459
9460 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {
9461 uint16_t *status = sc->rxq.stat_dma.vaddr;
9462 hw = le16toh(*status) & 0xfff;
9463 } else
9464 hw = le16toh(sc->rxq.stat->closed_rb_num) & 0xfff;
9465 hw &= (IWX_RX_MQ_RING_COUNT - 1);
9466 while (sc->rxq.cur != hw) {
9467 struct iwx_rx_data *data = &sc->rxq.data[sc->rxq.cur];
9468
9469 bus_dmamap_sync(sc->rxq.data_dmat, data->map,
9470 BUS_DMASYNC_POSTREAD);
9471
9472 iwx_rx_pkt(sc, data, &m);
9473 sc->rxq.cur = (sc->rxq.cur + 1) % IWX_RX_MQ_RING_COUNT;
9474 }
9475
9476 /*
9477 * Tell the firmware what we have processed.
9478 * Seems like the hardware gets upset unless we align the write by 8??
9479 */
9480 hw = (hw == 0) ? IWX_RX_MQ_RING_COUNT - 1 : hw - 1;
9481 IWX_WRITE(sc, IWX_RFH_Q0_FRBDCB_WIDX_TRG, hw & ~7);
9482 }
9483
9484 #if 0
9485 int
9486 iwx_intr(void *arg)
9487 {
9488 struct iwx_softc *sc = arg;
9489 struct ieee80211com *ic = &sc->sc_ic;
9490 struct ifnet *ifp = IC2IFP(ic);
9491 int r1, r2, rv = 0;
9492
9493 IWX_WRITE(sc, IWX_CSR_INT_MASK, 0);
9494
9495 if (sc->sc_flags & IWX_FLAG_USE_ICT) {
9496 uint32_t *ict = sc->ict_dma.vaddr;
9497 int tmp;
9498
9499 tmp = htole32(ict[sc->ict_cur]);
9500 if (!tmp)
9501 goto out_ena;
9502
9503 /*
9504 * ok, there was something. keep plowing until we have all.
9505 */
9506 r1 = r2 = 0;
9507 while (tmp) {
9508 r1 |= tmp;
9509 ict[sc->ict_cur] = 0;
9510 sc->ict_cur = (sc->ict_cur+1) % IWX_ICT_COUNT;
9511 tmp = htole32(ict[sc->ict_cur]);
9512 }
9513
9514 /* this is where the fun begins. don't ask */
9515 if (r1 == 0xffffffff)
9516 r1 = 0;
9517
9518 /* i am not expected to understand this */
9519 if (r1 & 0xc0000)
9520 r1 |= 0x8000;
9521 r1 = (0xff & r1) | ((0xff00 & r1) << 16);
9522 } else {
9523 r1 = IWX_READ(sc, IWX_CSR_INT);
9524 if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0)
9525 goto out;
9526 r2 = IWX_READ(sc, IWX_CSR_FH_INT_STATUS);
9527 }
9528 if (r1 == 0 && r2 == 0) {
9529 goto out_ena;
9530 }
9531
9532 IWX_WRITE(sc, IWX_CSR_INT, r1 | ~sc->sc_intmask);
9533
9534 if (r1 & IWX_CSR_INT_BIT_ALIVE) {
9535 #if 0
9536 int i;
9537 /* Firmware has now configured the RFH. */
9538 for (i = 0; i < IWX_RX_MQ_RING_COUNT; i++)
9539 iwx_update_rx_desc(sc, &sc->rxq, i);
9540 #endif
9541 IWX_WRITE(sc, IWX_RFH_Q0_FRBDCB_WIDX_TRG, 8);
9542 }
9543
9544
9545 if (r1 & IWX_CSR_INT_BIT_RF_KILL) {
9546 iwx_check_rfkill(sc);
9547 rv = 1;
9548 goto out_ena;
9549 }
9550
9551 if (r1 & IWX_CSR_INT_BIT_SW_ERR) {
9552 if (ifp->if_flags & IFF_DEBUG) {
9553 iwx_nic_error(sc);
9554 iwx_dump_driver_status(sc);
9555 }
9556 printf("%s: fatal firmware error\n", DEVNAME(sc));
9557 ieee80211_restart_all(ic);
9558 rv = 1;
9559 goto out;
9560
9561 }
9562
9563 if (r1 & IWX_CSR_INT_BIT_HW_ERR) {
9564 printf("%s: hardware error, stopping device \n", DEVNAME(sc));
9565 iwx_stop(sc);
9566 rv = 1;
9567 goto out;
9568 }
9569
9570 /* firmware chunk loaded */
9571 if (r1 & IWX_CSR_INT_BIT_FH_TX) {
9572 IWX_WRITE(sc, IWX_CSR_FH_INT_STATUS, IWX_CSR_FH_INT_TX_MASK);
9573
9574 sc->sc_fw_chunk_done = 1;
9575 wakeup(&sc->sc_fw);
9576 }
9577
9578 if (r1 & (IWX_CSR_INT_BIT_FH_RX | IWX_CSR_INT_BIT_SW_RX |
9579 IWX_CSR_INT_BIT_RX_PERIODIC)) {
9580 if (r1 & (IWX_CSR_INT_BIT_FH_RX | IWX_CSR_INT_BIT_SW_RX)) {
9581 IWX_WRITE(sc, IWX_CSR_FH_INT_STATUS, IWX_CSR_FH_INT_RX_MASK);
9582 }
9583 if (r1 & IWX_CSR_INT_BIT_RX_PERIODIC) {
9584 IWX_WRITE(sc, IWX_CSR_INT, IWX_CSR_INT_BIT_RX_PERIODIC);
9585 }
9586
9587 /* Disable periodic interrupt; we use it as just a one-shot. */
9588 IWX_WRITE_1(sc, IWX_CSR_INT_PERIODIC_REG, IWX_CSR_INT_PERIODIC_DIS);
9589
9590 /*
9591 * Enable periodic interrupt in 8 msec only if we received
9592 * real RX interrupt (instead of just periodic int), to catch
9593 * any dangling Rx interrupt. If it was just the periodic
9594 * interrupt, there was no dangling Rx activity, and no need
9595 * to extend the periodic interrupt; one-shot is enough.
9596 */
9597 if (r1 & (IWX_CSR_INT_BIT_FH_RX | IWX_CSR_INT_BIT_SW_RX))
9598 IWX_WRITE_1(sc, IWX_CSR_INT_PERIODIC_REG,
9599 IWX_CSR_INT_PERIODIC_ENA);
9600
9601 iwx_notif_intr(sc);
9602 }
9603
9604 rv = 1;
9605
9606 out_ena:
9607 iwx_restore_interrupts(sc);
9608 out:
9609 return rv;
9610 }
9611 #endif
9612
9613 static void
iwx_intr_msix(void * arg)9614 iwx_intr_msix(void *arg)
9615 {
9616 struct iwx_softc *sc = arg;
9617 struct ieee80211com *ic = &sc->sc_ic;
9618 uint32_t inta_fh, inta_hw;
9619 int vector = 0;
9620
9621 IWX_LOCK(sc);
9622
9623 inta_fh = IWX_READ(sc, IWX_CSR_MSIX_FH_INT_CAUSES_AD);
9624 inta_hw = IWX_READ(sc, IWX_CSR_MSIX_HW_INT_CAUSES_AD);
9625 IWX_WRITE(sc, IWX_CSR_MSIX_FH_INT_CAUSES_AD, inta_fh);
9626 IWX_WRITE(sc, IWX_CSR_MSIX_HW_INT_CAUSES_AD, inta_hw);
9627 inta_fh &= sc->sc_fh_mask;
9628 inta_hw &= sc->sc_hw_mask;
9629
9630 if (inta_fh & IWX_MSIX_FH_INT_CAUSES_Q0 ||
9631 inta_fh & IWX_MSIX_FH_INT_CAUSES_Q1) {
9632 iwx_notif_intr(sc);
9633 }
9634
9635 /* firmware chunk loaded */
9636 if (inta_fh & IWX_MSIX_FH_INT_CAUSES_D2S_CH0_NUM) {
9637 sc->sc_fw_chunk_done = 1;
9638 wakeup(&sc->sc_fw);
9639 }
9640
9641 if ((inta_fh & IWX_MSIX_FH_INT_CAUSES_FH_ERR) ||
9642 (inta_hw & IWX_MSIX_HW_INT_CAUSES_REG_SW_ERR) ||
9643 (inta_hw & IWX_MSIX_HW_INT_CAUSES_REG_SW_ERR_V2)) {
9644 if (sc->sc_debug) {
9645 iwx_nic_error(sc);
9646 iwx_dump_driver_status(sc);
9647 }
9648 printf("%s: fatal firmware error\n", DEVNAME(sc));
9649 ieee80211_restart_all(ic);
9650 goto out;
9651 }
9652
9653 if (inta_hw & IWX_MSIX_HW_INT_CAUSES_REG_RF_KILL) {
9654 iwx_check_rfkill(sc);
9655 }
9656
9657 if (inta_hw & IWX_MSIX_HW_INT_CAUSES_REG_HW_ERR) {
9658 printf("%s: hardware error, stopping device \n", DEVNAME(sc));
9659 sc->sc_flags |= IWX_FLAG_HW_ERR;
9660 iwx_stop(sc);
9661 goto out;
9662 }
9663
9664 if (inta_hw & IWX_MSIX_HW_INT_CAUSES_REG_ALIVE) {
9665 IWX_DPRINTF(sc, IWX_DEBUG_TRACE,
9666 "%s:%d WARNING: Skipping rx desc update\n",
9667 __func__, __LINE__);
9668 #if 0
9669 /*
9670 * XXX-THJ: we don't have the dma segment handy. This is hacked
9671 * out in the fc release, return to it if we ever get this
9672 * warning.
9673 */
9674 /* Firmware has now configured the RFH. */
9675 for (int i = 0; i < IWX_RX_MQ_RING_COUNT; i++)
9676 iwx_update_rx_desc(sc, &sc->rxq, i);
9677 #endif
9678 IWX_WRITE(sc, IWX_RFH_Q0_FRBDCB_WIDX_TRG, 8);
9679 }
9680
9681 /*
9682 * Before sending the interrupt the HW disables it to prevent
9683 * a nested interrupt. This is done by writing 1 to the corresponding
9684 * bit in the mask register. After handling the interrupt, it should be
9685 * re-enabled by clearing this bit. This register is defined as
9686 * write 1 clear (W1C) register, meaning that it's being clear
9687 * by writing 1 to the bit.
9688 */
9689 IWX_WRITE(sc, IWX_CSR_MSIX_AUTOMASK_ST_AD, 1 << vector);
9690 out:
9691 IWX_UNLOCK(sc);
9692 return;
9693 }
9694
9695 /*
9696 * The device info table below contains device-specific config overrides.
9697 * The most important parameter derived from this table is the name of the
9698 * firmware image to load.
9699 *
9700 * The Linux iwlwifi driver uses an "old" and a "new" device info table.
9701 * The "old" table matches devices based on PCI vendor/product IDs only.
9702 * The "new" table extends this with various device parameters derived
9703 * from MAC type, and RF type.
9704 *
9705 * In iwlwifi "old" and "new" tables share the same array, where "old"
9706 * entries contain dummy values for data defined only for "new" entries.
9707 * As of 2022, Linux developers are still in the process of moving entries
9708 * from "old" to "new" style and it looks like this effort has stalled in
9709 * in some work-in-progress state for quite a while. Linux commits moving
9710 * entries from "old" to "new" have at times been reverted due to regressions.
9711 * Part of this complexity comes from iwlwifi supporting both iwm(4) and iwx(4)
9712 * devices in the same driver.
9713 *
9714 * Our table below contains mostly "new" entries declared in iwlwifi
9715 * with the _IWL_DEV_INFO() macro (with a leading underscore).
9716 * Other devices are matched based on PCI vendor/product ID as usual,
9717 * unless matching specific PCI subsystem vendor/product IDs is required.
9718 *
9719 * Some "old"-style entries are required to identify the firmware image to use.
9720 * Others might be used to print a specific marketing name into Linux dmesg,
9721 * but we can't be sure whether the corresponding devices would be matched
9722 * correctly in the absence of their entries. So we include them just in case.
9723 */
9724
9725 struct iwx_dev_info {
9726 uint16_t device;
9727 uint16_t subdevice;
9728 uint16_t mac_type;
9729 uint16_t rf_type;
9730 uint8_t mac_step;
9731 uint8_t rf_id;
9732 uint8_t no_160;
9733 uint8_t cores;
9734 uint8_t cdb;
9735 uint8_t jacket;
9736 const struct iwx_device_cfg *cfg;
9737 };
9738
9739 #define _IWX_DEV_INFO(_device, _subdevice, _mac_type, _mac_step, _rf_type, \
9740 _rf_id, _no_160, _cores, _cdb, _jacket, _cfg) \
9741 { .device = (_device), .subdevice = (_subdevice), .cfg = &(_cfg), \
9742 .mac_type = _mac_type, .rf_type = _rf_type, \
9743 .no_160 = _no_160, .cores = _cores, .rf_id = _rf_id, \
9744 .mac_step = _mac_step, .cdb = _cdb, .jacket = _jacket }
9745
9746 #define IWX_DEV_INFO(_device, _subdevice, _cfg) \
9747 _IWX_DEV_INFO(_device, _subdevice, IWX_CFG_ANY, IWX_CFG_ANY, \
9748 IWX_CFG_ANY, IWX_CFG_ANY, IWX_CFG_ANY, IWX_CFG_ANY, \
9749 IWX_CFG_ANY, IWX_CFG_ANY, _cfg)
9750
9751 /*
9752 * When adding entries to this table keep in mind that entries must
9753 * be listed in the same order as in the Linux driver. Code walks this
9754 * table backwards and uses the first matching entry it finds.
9755 * Device firmware must be available in fw_update(8).
9756 */
9757 static const struct iwx_dev_info iwx_dev_info_table[] = {
9758 /* So with HR */
9759 IWX_DEV_INFO(0x2725, 0x0090, iwx_2ax_cfg_so_gf_a0),
9760 IWX_DEV_INFO(0x2725, 0x0020, iwx_2ax_cfg_ty_gf_a0),
9761 IWX_DEV_INFO(0x2725, 0x2020, iwx_2ax_cfg_ty_gf_a0),
9762 IWX_DEV_INFO(0x2725, 0x0024, iwx_2ax_cfg_ty_gf_a0),
9763 IWX_DEV_INFO(0x2725, 0x0310, iwx_2ax_cfg_ty_gf_a0),
9764 IWX_DEV_INFO(0x2725, 0x0510, iwx_2ax_cfg_ty_gf_a0),
9765 IWX_DEV_INFO(0x2725, 0x0A10, iwx_2ax_cfg_ty_gf_a0),
9766 IWX_DEV_INFO(0x2725, 0xE020, iwx_2ax_cfg_ty_gf_a0),
9767 IWX_DEV_INFO(0x2725, 0xE024, iwx_2ax_cfg_ty_gf_a0),
9768 IWX_DEV_INFO(0x2725, 0x4020, iwx_2ax_cfg_ty_gf_a0),
9769 IWX_DEV_INFO(0x2725, 0x6020, iwx_2ax_cfg_ty_gf_a0),
9770 IWX_DEV_INFO(0x2725, 0x6024, iwx_2ax_cfg_ty_gf_a0),
9771 IWX_DEV_INFO(0x2725, 0x1673, iwx_2ax_cfg_ty_gf_a0), /* killer_1675w */
9772 IWX_DEV_INFO(0x2725, 0x1674, iwx_2ax_cfg_ty_gf_a0), /* killer_1675x */
9773 IWX_DEV_INFO(0x51f0, 0x1691, iwx_2ax_cfg_so_gf4_a0), /* killer_1690s */
9774 IWX_DEV_INFO(0x51f0, 0x1692, iwx_2ax_cfg_so_gf4_a0), /* killer_1690i */
9775 IWX_DEV_INFO(0x51f1, 0x1691, iwx_2ax_cfg_so_gf4_a0),
9776 IWX_DEV_INFO(0x51f1, 0x1692, iwx_2ax_cfg_so_gf4_a0),
9777 IWX_DEV_INFO(0x54f0, 0x1691, iwx_2ax_cfg_so_gf4_a0), /* killer_1690s */
9778 IWX_DEV_INFO(0x54f0, 0x1692, iwx_2ax_cfg_so_gf4_a0), /* killer_1690i */
9779 IWX_DEV_INFO(0x7a70, 0x0090, iwx_2ax_cfg_so_gf_a0_long),
9780 IWX_DEV_INFO(0x7a70, 0x0098, iwx_2ax_cfg_so_gf_a0_long),
9781 IWX_DEV_INFO(0x7a70, 0x00b0, iwx_2ax_cfg_so_gf4_a0_long),
9782 IWX_DEV_INFO(0x7a70, 0x0310, iwx_2ax_cfg_so_gf_a0_long),
9783 IWX_DEV_INFO(0x7a70, 0x0510, iwx_2ax_cfg_so_gf_a0_long),
9784 IWX_DEV_INFO(0x7a70, 0x0a10, iwx_2ax_cfg_so_gf_a0_long),
9785 IWX_DEV_INFO(0x7af0, 0x0090, iwx_2ax_cfg_so_gf_a0),
9786 IWX_DEV_INFO(0x7af0, 0x0098, iwx_2ax_cfg_so_gf_a0),
9787 IWX_DEV_INFO(0x7af0, 0x00b0, iwx_2ax_cfg_so_gf4_a0),
9788 IWX_DEV_INFO(0x7a70, 0x1691, iwx_2ax_cfg_so_gf4_a0), /* killer_1690s */
9789 IWX_DEV_INFO(0x7a70, 0x1692, iwx_2ax_cfg_so_gf4_a0), /* killer_1690i */
9790 IWX_DEV_INFO(0x7af0, 0x0310, iwx_2ax_cfg_so_gf_a0),
9791 IWX_DEV_INFO(0x7af0, 0x0510, iwx_2ax_cfg_so_gf_a0),
9792 IWX_DEV_INFO(0x7af0, 0x0a10, iwx_2ax_cfg_so_gf_a0),
9793 IWX_DEV_INFO(0x7f70, 0x1691, iwx_2ax_cfg_so_gf4_a0), /* killer_1690s */
9794 IWX_DEV_INFO(0x7f70, 0x1692, iwx_2ax_cfg_so_gf4_a0), /* killer_1690i */
9795
9796 /* So with GF2 */
9797 IWX_DEV_INFO(0x2726, 0x1671, iwx_2ax_cfg_so_gf_a0), /* killer_1675s */
9798 IWX_DEV_INFO(0x2726, 0x1672, iwx_2ax_cfg_so_gf_a0), /* killer_1675i */
9799 IWX_DEV_INFO(0x51f0, 0x1671, iwx_2ax_cfg_so_gf_a0), /* killer_1675s */
9800 IWX_DEV_INFO(0x51f0, 0x1672, iwx_2ax_cfg_so_gf_a0), /* killer_1675i */
9801 IWX_DEV_INFO(0x54f0, 0x1671, iwx_2ax_cfg_so_gf_a0), /* killer_1675s */
9802 IWX_DEV_INFO(0x54f0, 0x1672, iwx_2ax_cfg_so_gf_a0), /* killer_1675i */
9803 IWX_DEV_INFO(0x7a70, 0x1671, iwx_2ax_cfg_so_gf_a0), /* killer_1675s */
9804 IWX_DEV_INFO(0x7a70, 0x1672, iwx_2ax_cfg_so_gf_a0), /* killer_1675i */
9805 IWX_DEV_INFO(0x7af0, 0x1671, iwx_2ax_cfg_so_gf_a0), /* killer_1675s */
9806 IWX_DEV_INFO(0x7af0, 0x1672, iwx_2ax_cfg_so_gf_a0), /* killer_1675i */
9807 IWX_DEV_INFO(0x7f70, 0x1671, iwx_2ax_cfg_so_gf_a0), /* killer_1675s */
9808 IWX_DEV_INFO(0x7f70, 0x1672, iwx_2ax_cfg_so_gf_a0), /* killer_1675i */
9809
9810 /* Qu with Jf, C step */
9811 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9812 IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,
9813 IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1,
9814 IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9815 IWX_CFG_ANY, iwx_9560_qu_c0_jf_b0_cfg), /* 9461_160 */
9816 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9817 IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,
9818 IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1,
9819 IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9820 IWX_CFG_ANY, iwx_9560_qu_c0_jf_b0_cfg), /* iwl9461 */
9821 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9822 IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,
9823 IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1_DIV,
9824 IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9825 IWX_CFG_ANY, iwx_9560_qu_c0_jf_b0_cfg), /* 9462_160 */
9826 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9827 IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,
9828 IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1_DIV,
9829 IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9830 IWX_CFG_ANY, iwx_9560_qu_c0_jf_b0_cfg), /* 9462 */
9831 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9832 IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,
9833 IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF,
9834 IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9835 IWX_CFG_ANY, iwx_9560_qu_c0_jf_b0_cfg), /* 9560_160 */
9836 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9837 IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,
9838 IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF,
9839 IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9840 IWX_CFG_ANY, iwx_9560_qu_c0_jf_b0_cfg), /* 9560 */
9841 _IWX_DEV_INFO(IWX_CFG_ANY, 0x1551,
9842 IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,
9843 IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF,
9844 IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9845 IWX_CFG_ANY,
9846 iwx_9560_qu_c0_jf_b0_cfg), /* 9560_killer_1550s */
9847 _IWX_DEV_INFO(IWX_CFG_ANY, 0x1552,
9848 IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,
9849 IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF,
9850 IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9851 IWX_CFG_ANY,
9852 iwx_9560_qu_c0_jf_b0_cfg), /* 9560_killer_1550i */
9853
9854 /* QuZ with Jf */
9855 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9856 IWX_CFG_MAC_TYPE_QUZ, IWX_CFG_ANY,
9857 IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF,
9858 IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9859 IWX_CFG_ANY, iwx_9560_quz_a0_jf_b0_cfg), /* 9461_160 */
9860 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9861 IWX_CFG_MAC_TYPE_QUZ, IWX_CFG_ANY,
9862 IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF,
9863 IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9864 IWX_CFG_ANY, iwx_9560_quz_a0_jf_b0_cfg), /* 9461 */
9865 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9866 IWX_CFG_MAC_TYPE_QUZ, IWX_CFG_ANY,
9867 IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1_DIV,
9868 IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9869 IWX_CFG_ANY, iwx_9560_quz_a0_jf_b0_cfg), /* 9462_160 */
9870 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9871 IWX_CFG_MAC_TYPE_QUZ, IWX_CFG_ANY,
9872 IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1_DIV,
9873 IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9874 IWX_CFG_ANY, iwx_9560_quz_a0_jf_b0_cfg), /* 9462 */
9875 _IWX_DEV_INFO(IWX_CFG_ANY, 0x1551,
9876 IWX_CFG_MAC_TYPE_QUZ, IWX_CFG_ANY,
9877 IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF,
9878 IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9879 IWX_CFG_ANY,
9880 iwx_9560_quz_a0_jf_b0_cfg), /* killer_1550s */
9881 _IWX_DEV_INFO(IWX_CFG_ANY, 0x1552,
9882 IWX_CFG_MAC_TYPE_QUZ, IWX_CFG_ANY,
9883 IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF,
9884 IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9885 IWX_CFG_ANY,
9886 iwx_9560_quz_a0_jf_b0_cfg), /* 9560_killer_1550i */
9887
9888 /* Qu with Hr, B step */
9889 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9890 IWX_CFG_MAC_TYPE_QU, IWX_SILICON_B_STEP,
9891 IWX_CFG_RF_TYPE_HR1, IWX_CFG_ANY,
9892 IWX_CFG_ANY, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY,
9893 iwx_qu_b0_hr1_b0), /* AX101 */
9894 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9895 IWX_CFG_MAC_TYPE_QU, IWX_SILICON_B_STEP,
9896 IWX_CFG_RF_TYPE_HR2, IWX_CFG_ANY,
9897 IWX_CFG_NO_160, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY,
9898 iwx_qu_b0_hr_b0), /* AX203 */
9899
9900 /* Qu with Hr, C step */
9901 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9902 IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,
9903 IWX_CFG_RF_TYPE_HR1, IWX_CFG_ANY,
9904 IWX_CFG_ANY, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY,
9905 iwx_qu_c0_hr1_b0), /* AX101 */
9906 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9907 IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,
9908 IWX_CFG_RF_TYPE_HR2, IWX_CFG_ANY,
9909 IWX_CFG_NO_160, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY,
9910 iwx_qu_c0_hr_b0), /* AX203 */
9911 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9912 IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,
9913 IWX_CFG_RF_TYPE_HR2, IWX_CFG_ANY,
9914 IWX_CFG_160, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY,
9915 iwx_qu_c0_hr_b0), /* AX201 */
9916
9917 /* QuZ with Hr */
9918 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9919 IWX_CFG_MAC_TYPE_QUZ, IWX_CFG_ANY,
9920 IWX_CFG_RF_TYPE_HR1, IWX_CFG_ANY,
9921 IWX_CFG_ANY, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY,
9922 iwx_quz_a0_hr1_b0), /* AX101 */
9923 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9924 IWX_CFG_MAC_TYPE_QUZ, IWX_SILICON_B_STEP,
9925 IWX_CFG_RF_TYPE_HR2, IWX_CFG_ANY,
9926 IWX_CFG_NO_160, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY,
9927 iwx_cfg_quz_a0_hr_b0), /* AX203 */
9928
9929 /* SoF with JF2 */
9930 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9931 IWX_CFG_MAC_TYPE_SOF, IWX_CFG_ANY,
9932 IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF,
9933 IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9934 IWX_CFG_ANY, iwx_2ax_cfg_so_jf_b0), /* 9560_160 */
9935 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9936 IWX_CFG_MAC_TYPE_SOF, IWX_CFG_ANY,
9937 IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF,
9938 IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9939 IWX_CFG_ANY, iwx_2ax_cfg_so_jf_b0), /* 9560 */
9940
9941 /* SoF with JF */
9942 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9943 IWX_CFG_MAC_TYPE_SOF, IWX_CFG_ANY,
9944 IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1,
9945 IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9946 IWX_CFG_ANY, iwx_2ax_cfg_so_jf_b0), /* 9461_160 */
9947 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9948 IWX_CFG_MAC_TYPE_SOF, IWX_CFG_ANY,
9949 IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1_DIV,
9950 IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9951 IWX_CFG_ANY, iwx_2ax_cfg_so_jf_b0), /* 9462_160 */
9952 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9953 IWX_CFG_MAC_TYPE_SOF, IWX_CFG_ANY,
9954 IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1,
9955 IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9956 IWX_CFG_ANY, iwx_2ax_cfg_so_jf_b0), /* 9461_name */
9957 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9958 IWX_CFG_MAC_TYPE_SOF, IWX_CFG_ANY,
9959 IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1_DIV,
9960 IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
9961 IWX_CFG_ANY, iwx_2ax_cfg_so_jf_b0), /* 9462 */
9962
9963 /* So with Hr */
9964 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9965 IWX_CFG_MAC_TYPE_SO, IWX_CFG_ANY,
9966 IWX_CFG_RF_TYPE_HR2, IWX_CFG_ANY,
9967 IWX_CFG_NO_160, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY,
9968 iwx_cfg_so_a0_hr_b0), /* AX203 */
9969 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9970 IWX_CFG_MAC_TYPE_SO, IWX_CFG_ANY,
9971 IWX_CFG_RF_TYPE_HR1, IWX_CFG_ANY,
9972 IWX_CFG_160, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY,
9973 iwx_cfg_so_a0_hr_b0), /* ax101 */
9974 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9975 IWX_CFG_MAC_TYPE_SO, IWX_CFG_ANY,
9976 IWX_CFG_RF_TYPE_HR2, IWX_CFG_ANY,
9977 IWX_CFG_160, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY,
9978 iwx_cfg_so_a0_hr_b0), /* ax201 */
9979
9980 /* So-F with Hr */
9981 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9982 IWX_CFG_MAC_TYPE_SOF, IWX_CFG_ANY,
9983 IWX_CFG_RF_TYPE_HR2, IWX_CFG_ANY,
9984 IWX_CFG_NO_160, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY,
9985 iwx_cfg_so_a0_hr_b0), /* AX203 */
9986 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9987 IWX_CFG_MAC_TYPE_SOF, IWX_CFG_ANY,
9988 IWX_CFG_RF_TYPE_HR1, IWX_CFG_ANY,
9989 IWX_CFG_160, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY,
9990 iwx_cfg_so_a0_hr_b0), /* AX101 */
9991 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9992 IWX_CFG_MAC_TYPE_SOF, IWX_CFG_ANY,
9993 IWX_CFG_RF_TYPE_HR2, IWX_CFG_ANY,
9994 IWX_CFG_160, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY,
9995 iwx_cfg_so_a0_hr_b0), /* AX201 */
9996
9997 /* So-F with GF */
9998 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
9999 IWX_CFG_MAC_TYPE_SOF, IWX_CFG_ANY,
10000 IWX_CFG_RF_TYPE_GF, IWX_CFG_ANY,
10001 IWX_CFG_160, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY,
10002 iwx_2ax_cfg_so_gf_a0), /* AX211 */
10003 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
10004 IWX_CFG_MAC_TYPE_SOF, IWX_CFG_ANY,
10005 IWX_CFG_RF_TYPE_GF, IWX_CFG_ANY,
10006 IWX_CFG_160, IWX_CFG_ANY, IWX_CFG_CDB, IWX_CFG_ANY,
10007 iwx_2ax_cfg_so_gf4_a0), /* AX411 */
10008
10009 /* So with GF */
10010 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
10011 IWX_CFG_MAC_TYPE_SO, IWX_CFG_ANY,
10012 IWX_CFG_RF_TYPE_GF, IWX_CFG_ANY,
10013 IWX_CFG_160, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY,
10014 iwx_2ax_cfg_so_gf_a0), /* AX211 */
10015 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
10016 IWX_CFG_MAC_TYPE_SO, IWX_CFG_ANY,
10017 IWX_CFG_RF_TYPE_GF, IWX_CFG_ANY,
10018 IWX_CFG_160, IWX_CFG_ANY, IWX_CFG_CDB, IWX_CFG_ANY,
10019 iwx_2ax_cfg_so_gf4_a0), /* AX411 */
10020
10021 /* So with JF2 */
10022 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
10023 IWX_CFG_MAC_TYPE_SO, IWX_CFG_ANY,
10024 IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF,
10025 IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
10026 IWX_CFG_ANY, iwx_2ax_cfg_so_jf_b0), /* 9560_160 */
10027 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
10028 IWX_CFG_MAC_TYPE_SO, IWX_CFG_ANY,
10029 IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF,
10030 IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
10031 IWX_CFG_ANY, iwx_2ax_cfg_so_jf_b0), /* 9560 */
10032
10033 /* So with JF */
10034 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
10035 IWX_CFG_MAC_TYPE_SO, IWX_CFG_ANY,
10036 IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1,
10037 IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
10038 IWX_CFG_ANY, iwx_2ax_cfg_so_jf_b0), /* 9461_160 */
10039 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
10040 IWX_CFG_MAC_TYPE_SO, IWX_CFG_ANY,
10041 IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1_DIV,
10042 IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
10043 IWX_CFG_ANY, iwx_2ax_cfg_so_jf_b0), /* 9462_160 */
10044 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
10045 IWX_CFG_MAC_TYPE_SO, IWX_CFG_ANY,
10046 IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1,
10047 IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
10048 IWX_CFG_ANY, iwx_2ax_cfg_so_jf_b0), /* iwl9461 */
10049 _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY,
10050 IWX_CFG_MAC_TYPE_SO, IWX_CFG_ANY,
10051 IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1_DIV,
10052 IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB,
10053 IWX_CFG_ANY, iwx_2ax_cfg_so_jf_b0), /* 9462 */
10054 };
10055
10056 static int
iwx_preinit(struct iwx_softc * sc)10057 iwx_preinit(struct iwx_softc *sc)
10058 {
10059 struct ieee80211com *ic = &sc->sc_ic;
10060 int err;
10061
10062 err = iwx_prepare_card_hw(sc);
10063 if (err) {
10064 printf("%s: could not initialize hardware\n", DEVNAME(sc));
10065 return err;
10066 }
10067
10068 if (sc->attached) {
10069 return 0;
10070 }
10071
10072 err = iwx_start_hw(sc);
10073 if (err) {
10074 printf("%s: could not initialize hardware\n", DEVNAME(sc));
10075 return err;
10076 }
10077
10078 err = iwx_run_init_mvm_ucode(sc, 1);
10079 iwx_stop_device(sc);
10080 if (err) {
10081 printf("%s: failed to stop device\n", DEVNAME(sc));
10082 return err;
10083 }
10084
10085 /* Print version info and MAC address on first successful fw load. */
10086 sc->attached = 1;
10087 if (sc->sc_pnvm_ver) {
10088 printf("%s: hw rev 0x%x, fw %s, pnvm %08x, "
10089 "address %s\n",
10090 DEVNAME(sc), sc->sc_hw_rev & IWX_CSR_HW_REV_TYPE_MSK,
10091 sc->sc_fwver, sc->sc_pnvm_ver,
10092 ether_sprintf(sc->sc_nvm.hw_addr));
10093 } else {
10094 printf("%s: hw rev 0x%x, fw %s, address %s\n",
10095 DEVNAME(sc), sc->sc_hw_rev & IWX_CSR_HW_REV_TYPE_MSK,
10096 sc->sc_fwver, ether_sprintf(sc->sc_nvm.hw_addr));
10097 }
10098
10099 /* not all hardware can do 5GHz band */
10100 if (!sc->sc_nvm.sku_cap_band_52GHz_enable)
10101 memset(&ic->ic_sup_rates[IEEE80211_MODE_11A], 0,
10102 sizeof(ic->ic_sup_rates[IEEE80211_MODE_11A]));
10103
10104 return 0;
10105 }
10106
10107 static void
iwx_attach_hook(void * self)10108 iwx_attach_hook(void *self)
10109 {
10110 struct iwx_softc *sc = (void *)self;
10111 struct ieee80211com *ic = &sc->sc_ic;
10112 int err;
10113
10114 IWX_LOCK(sc);
10115 err = iwx_preinit(sc);
10116 IWX_UNLOCK(sc);
10117 if (err != 0)
10118 goto out;
10119
10120 iwx_init_channel_map(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans,
10121 ic->ic_channels);
10122
10123 ieee80211_ifattach(ic);
10124 ic->ic_vap_create = iwx_vap_create;
10125 ic->ic_vap_delete = iwx_vap_delete;
10126 ic->ic_raw_xmit = iwx_raw_xmit;
10127 ic->ic_node_alloc = iwx_node_alloc;
10128 ic->ic_scan_start = iwx_scan_start;
10129 ic->ic_scan_end = iwx_scan_end;
10130 ic->ic_update_mcast = iwx_update_mcast;
10131 ic->ic_getradiocaps = iwx_init_channel_map;
10132
10133 ic->ic_set_channel = iwx_set_channel;
10134 ic->ic_scan_curchan = iwx_scan_curchan;
10135 ic->ic_scan_mindwell = iwx_scan_mindwell;
10136 ic->ic_wme.wme_update = iwx_wme_update;
10137 ic->ic_parent = iwx_parent;
10138 ic->ic_transmit = iwx_transmit;
10139
10140 sc->sc_ampdu_rx_start = ic->ic_ampdu_rx_start;
10141 ic->ic_ampdu_rx_start = iwx_ampdu_rx_start;
10142 sc->sc_ampdu_rx_stop = ic->ic_ampdu_rx_stop;
10143 ic->ic_ampdu_rx_stop = iwx_ampdu_rx_stop;
10144
10145 sc->sc_addba_request = ic->ic_addba_request;
10146 ic->ic_addba_request = iwx_addba_request;
10147 sc->sc_addba_response = ic->ic_addba_response;
10148 ic->ic_addba_response = iwx_addba_response;
10149
10150 iwx_radiotap_attach(sc);
10151 ieee80211_announce(ic);
10152 out:
10153 config_intrhook_disestablish(&sc->sc_preinit_hook);
10154 }
10155
10156 const struct iwx_device_cfg *
iwx_find_device_cfg(struct iwx_softc * sc)10157 iwx_find_device_cfg(struct iwx_softc *sc)
10158 {
10159 uint16_t sdev_id, mac_type, rf_type;
10160 uint8_t mac_step, cdb, jacket, rf_id, no_160, cores;
10161 int i;
10162
10163 sdev_id = pci_get_subdevice(sc->sc_dev);
10164 mac_type = IWX_CSR_HW_REV_TYPE(sc->sc_hw_rev);
10165 mac_step = IWX_CSR_HW_REV_STEP(sc->sc_hw_rev << 2);
10166 rf_type = IWX_CSR_HW_RFID_TYPE(sc->sc_hw_rf_id);
10167 cdb = IWX_CSR_HW_RFID_IS_CDB(sc->sc_hw_rf_id);
10168 jacket = IWX_CSR_HW_RFID_IS_JACKET(sc->sc_hw_rf_id);
10169
10170 rf_id = IWX_SUBDEVICE_RF_ID(sdev_id);
10171 no_160 = IWX_SUBDEVICE_NO_160(sdev_id);
10172 cores = IWX_SUBDEVICE_CORES(sdev_id);
10173
10174 for (i = nitems(iwx_dev_info_table) - 1; i >= 0; i--) {
10175 const struct iwx_dev_info *dev_info = &iwx_dev_info_table[i];
10176
10177 if (dev_info->device != (uint16_t)IWX_CFG_ANY &&
10178 dev_info->device != sc->sc_pid)
10179 continue;
10180
10181 if (dev_info->subdevice != (uint16_t)IWX_CFG_ANY &&
10182 dev_info->subdevice != sdev_id)
10183 continue;
10184
10185 if (dev_info->mac_type != (uint16_t)IWX_CFG_ANY &&
10186 dev_info->mac_type != mac_type)
10187 continue;
10188
10189 if (dev_info->mac_step != (uint8_t)IWX_CFG_ANY &&
10190 dev_info->mac_step != mac_step)
10191 continue;
10192
10193 if (dev_info->rf_type != (uint16_t)IWX_CFG_ANY &&
10194 dev_info->rf_type != rf_type)
10195 continue;
10196
10197 if (dev_info->cdb != (uint8_t)IWX_CFG_ANY &&
10198 dev_info->cdb != cdb)
10199 continue;
10200
10201 if (dev_info->jacket != (uint8_t)IWX_CFG_ANY &&
10202 dev_info->jacket != jacket)
10203 continue;
10204
10205 if (dev_info->rf_id != (uint8_t)IWX_CFG_ANY &&
10206 dev_info->rf_id != rf_id)
10207 continue;
10208
10209 if (dev_info->no_160 != (uint8_t)IWX_CFG_ANY &&
10210 dev_info->no_160 != no_160)
10211 continue;
10212
10213 if (dev_info->cores != (uint8_t)IWX_CFG_ANY &&
10214 dev_info->cores != cores)
10215 continue;
10216
10217 return dev_info->cfg;
10218 }
10219
10220 return NULL;
10221 }
10222
10223 static int
iwx_probe(device_t dev)10224 iwx_probe(device_t dev)
10225 {
10226 int i;
10227
10228 for (i = 0; i < nitems(iwx_devices); i++) {
10229 if (pci_get_vendor(dev) == PCI_VENDOR_INTEL &&
10230 pci_get_device(dev) == iwx_devices[i].device) {
10231 device_set_desc(dev, iwx_devices[i].name);
10232
10233 /*
10234 * Due to significant existing deployments using
10235 * iwlwifi lower the priority of iwx.
10236 *
10237 * This inverts the advice in bus.h where drivers
10238 * supporting newer hardware should return
10239 * BUS_PROBE_DEFAULT and drivers for older devices
10240 * return BUS_PROBE_LOW_PRIORITY.
10241 *
10242 */
10243 return (BUS_PROBE_LOW_PRIORITY);
10244 }
10245 }
10246
10247 return (ENXIO);
10248 }
10249
10250 static int
iwx_attach(device_t dev)10251 iwx_attach(device_t dev)
10252 {
10253 struct iwx_softc *sc = device_get_softc(dev);
10254 struct ieee80211com *ic = &sc->sc_ic;
10255 const struct iwx_device_cfg *cfg;
10256 int err;
10257 int txq_i, i, j;
10258 size_t ctxt_info_size;
10259 int rid;
10260 int count;
10261 int error;
10262 sc->sc_dev = dev;
10263 sc->sc_pid = pci_get_device(dev);
10264 sc->sc_dmat = bus_get_dma_tag(sc->sc_dev);
10265
10266 TASK_INIT(&sc->sc_es_task, 0, iwx_endscan_cb, sc);
10267 IWX_LOCK_INIT(sc);
10268 mbufq_init(&sc->sc_snd, ifqmaxlen);
10269 TASK_INIT(&sc->ba_rx_task, 0, iwx_ba_rx_task, sc);
10270 TASK_INIT(&sc->ba_tx_task, 0, iwx_ba_tx_task, sc);
10271 sc->sc_tq = taskqueue_create("iwm_taskq", M_WAITOK,
10272 taskqueue_thread_enqueue, &sc->sc_tq);
10273 error = taskqueue_start_threads(&sc->sc_tq, 1, 0, "iwm_taskq");
10274 if (error != 0) {
10275 device_printf(dev, "can't start taskq thread, error %d\n",
10276 error);
10277 return (ENXIO);
10278 }
10279
10280 pci_find_cap(dev, PCIY_EXPRESS, &sc->sc_cap_off);
10281 if (sc->sc_cap_off == 0) {
10282 device_printf(dev, "PCIe capability structure not found!\n");
10283 return (ENXIO);
10284 }
10285
10286 /*
10287 * We disable the RETRY_TIMEOUT register (0x41) to keep
10288 * PCI Tx retries from interfering with C3 CPU state.
10289 */
10290 pci_write_config(dev, PCI_CFG_RETRY_TIMEOUT, 0x00, 1);
10291
10292 if (pci_msix_count(dev)) {
10293 sc->sc_msix = 1;
10294 } else {
10295 device_printf(dev, "no MSI-X found\n");
10296 return (ENXIO);
10297 }
10298
10299 pci_enable_busmaster(dev);
10300 rid = PCIR_BAR(0);
10301 sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
10302 RF_ACTIVE);
10303 if (sc->sc_mem == NULL) {
10304 device_printf(sc->sc_dev, "can't map mem space\n");
10305 return (ENXIO);
10306 }
10307 sc->sc_st = rman_get_bustag(sc->sc_mem);
10308 sc->sc_sh = rman_get_bushandle(sc->sc_mem);
10309
10310 count = 1;
10311 rid = 0;
10312 if (pci_alloc_msix(dev, &count) == 0)
10313 rid = 1;
10314 DPRINTF(("%s: count=%d\n", __func__, count));
10315 sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE |
10316 (rid != 0 ? 0 : RF_SHAREABLE));
10317 if (sc->sc_irq == NULL) {
10318 device_printf(dev, "can't map interrupt\n");
10319 return (ENXIO);
10320 }
10321 error = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_NET | INTR_MPSAFE,
10322 NULL, iwx_intr_msix, sc, &sc->sc_ih);
10323 if (error != 0) {
10324 device_printf(dev, "can't establish interrupt\n");
10325 return (ENXIO);
10326 }
10327
10328 /* Clear pending interrupts. */
10329 IWX_WRITE(sc, IWX_CSR_INT_MASK, 0);
10330 IWX_WRITE(sc, IWX_CSR_INT, ~0);
10331 IWX_WRITE(sc, IWX_CSR_FH_INT_STATUS, ~0);
10332
10333 sc->sc_hw_rev = IWX_READ(sc, IWX_CSR_HW_REV);
10334 DPRINTF(("%s: sc->sc_hw_rev=%d\n", __func__, sc->sc_hw_rev));
10335 sc->sc_hw_rf_id = IWX_READ(sc, IWX_CSR_HW_RF_ID);
10336 DPRINTF(("%s: sc->sc_hw_rf_id =%d\n", __func__, sc->sc_hw_rf_id));
10337
10338 /*
10339 * In the 8000 HW family the format of the 4 bytes of CSR_HW_REV have
10340 * changed, and now the revision step also includes bit 0-1 (no more
10341 * "dash" value). To keep hw_rev backwards compatible - we'll store it
10342 * in the old format.
10343 */
10344 sc->sc_hw_rev = (sc->sc_hw_rev & 0xfff0) |
10345 (IWX_CSR_HW_REV_STEP(sc->sc_hw_rev << 2) << 2);
10346
10347 switch (sc->sc_pid) {
10348 case PCI_PRODUCT_INTEL_WL_22500_1:
10349 sc->sc_fwname = IWX_CC_A_FW;
10350 sc->sc_device_family = IWX_DEVICE_FAMILY_22000;
10351 sc->sc_integrated = 0;
10352 sc->sc_ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_NONE;
10353 sc->sc_low_latency_xtal = 0;
10354 sc->sc_xtal_latency = 0;
10355 sc->sc_tx_with_siso_diversity = 0;
10356 sc->sc_uhb_supported = 0;
10357 break;
10358 case PCI_PRODUCT_INTEL_WL_22500_2:
10359 case PCI_PRODUCT_INTEL_WL_22500_5:
10360 /* These devices should be QuZ only. */
10361 if (sc->sc_hw_rev != IWX_CSR_HW_REV_TYPE_QUZ) {
10362 device_printf(dev, "unsupported AX201 adapter\n");
10363 return (ENXIO);
10364 }
10365 sc->sc_fwname = IWX_QUZ_A_HR_B_FW;
10366 sc->sc_device_family = IWX_DEVICE_FAMILY_22000;
10367 sc->sc_integrated = 1;
10368 sc->sc_ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_200;
10369 sc->sc_low_latency_xtal = 0;
10370 sc->sc_xtal_latency = 500;
10371 sc->sc_tx_with_siso_diversity = 0;
10372 sc->sc_uhb_supported = 0;
10373 break;
10374 case PCI_PRODUCT_INTEL_WL_22500_3:
10375 if (sc->sc_hw_rev == IWX_CSR_HW_REV_TYPE_QU_C0)
10376 sc->sc_fwname = IWX_QU_C_HR_B_FW;
10377 else if (sc->sc_hw_rev == IWX_CSR_HW_REV_TYPE_QUZ)
10378 sc->sc_fwname = IWX_QUZ_A_HR_B_FW;
10379 else
10380 sc->sc_fwname = IWX_QU_B_HR_B_FW;
10381 sc->sc_device_family = IWX_DEVICE_FAMILY_22000;
10382 sc->sc_integrated = 1;
10383 sc->sc_ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_200;
10384 sc->sc_low_latency_xtal = 0;
10385 sc->sc_xtal_latency = 500;
10386 sc->sc_tx_with_siso_diversity = 0;
10387 sc->sc_uhb_supported = 0;
10388 break;
10389 case PCI_PRODUCT_INTEL_WL_22500_4:
10390 case PCI_PRODUCT_INTEL_WL_22500_7:
10391 case PCI_PRODUCT_INTEL_WL_22500_8:
10392 if (sc->sc_hw_rev == IWX_CSR_HW_REV_TYPE_QU_C0)
10393 sc->sc_fwname = IWX_QU_C_HR_B_FW;
10394 else if (sc->sc_hw_rev == IWX_CSR_HW_REV_TYPE_QUZ)
10395 sc->sc_fwname = IWX_QUZ_A_HR_B_FW;
10396 else
10397 sc->sc_fwname = IWX_QU_B_HR_B_FW;
10398 sc->sc_device_family = IWX_DEVICE_FAMILY_22000;
10399 sc->sc_integrated = 1;
10400 sc->sc_ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_1820;
10401 sc->sc_low_latency_xtal = 0;
10402 sc->sc_xtal_latency = 1820;
10403 sc->sc_tx_with_siso_diversity = 0;
10404 sc->sc_uhb_supported = 0;
10405 break;
10406 case PCI_PRODUCT_INTEL_WL_22500_6:
10407 if (sc->sc_hw_rev == IWX_CSR_HW_REV_TYPE_QU_C0)
10408 sc->sc_fwname = IWX_QU_C_HR_B_FW;
10409 else if (sc->sc_hw_rev == IWX_CSR_HW_REV_TYPE_QUZ)
10410 sc->sc_fwname = IWX_QUZ_A_HR_B_FW;
10411 else
10412 sc->sc_fwname = IWX_QU_B_HR_B_FW;
10413 sc->sc_device_family = IWX_DEVICE_FAMILY_22000;
10414 sc->sc_integrated = 1;
10415 sc->sc_ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_2500;
10416 sc->sc_low_latency_xtal = 1;
10417 sc->sc_xtal_latency = 12000;
10418 sc->sc_tx_with_siso_diversity = 0;
10419 sc->sc_uhb_supported = 0;
10420 break;
10421 case PCI_PRODUCT_INTEL_WL_22500_9:
10422 case PCI_PRODUCT_INTEL_WL_22500_10:
10423 case PCI_PRODUCT_INTEL_WL_22500_11:
10424 case PCI_PRODUCT_INTEL_WL_22500_13:
10425 /* _14 is an MA device, not yet supported */
10426 case PCI_PRODUCT_INTEL_WL_22500_15:
10427 case PCI_PRODUCT_INTEL_WL_22500_16:
10428 sc->sc_fwname = IWX_SO_A_GF_A_FW;
10429 sc->sc_pnvm_name = IWX_SO_A_GF_A_PNVM;
10430 sc->sc_device_family = IWX_DEVICE_FAMILY_AX210;
10431 sc->sc_integrated = 0;
10432 sc->sc_ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_NONE;
10433 sc->sc_low_latency_xtal = 0;
10434 sc->sc_xtal_latency = 0;
10435 sc->sc_tx_with_siso_diversity = 0;
10436 sc->sc_uhb_supported = 1;
10437 break;
10438 case PCI_PRODUCT_INTEL_WL_22500_12:
10439 case PCI_PRODUCT_INTEL_WL_22500_17:
10440 sc->sc_fwname = IWX_SO_A_GF_A_FW;
10441 sc->sc_pnvm_name = IWX_SO_A_GF_A_PNVM;
10442 sc->sc_device_family = IWX_DEVICE_FAMILY_AX210;
10443 sc->sc_integrated = 1;
10444 sc->sc_ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_2500;
10445 sc->sc_low_latency_xtal = 1;
10446 sc->sc_xtal_latency = 12000;
10447 sc->sc_tx_with_siso_diversity = 0;
10448 sc->sc_uhb_supported = 0;
10449 sc->sc_imr_enabled = 1;
10450 break;
10451 default:
10452 device_printf(dev, "unknown adapter type\n");
10453 return (ENXIO);
10454 }
10455
10456 cfg = iwx_find_device_cfg(sc);
10457 DPRINTF(("%s: cfg=%p\n", __func__, cfg));
10458 if (cfg) {
10459 sc->sc_fwname = cfg->fw_name;
10460 sc->sc_pnvm_name = cfg->pnvm_name;
10461 sc->sc_tx_with_siso_diversity = cfg->tx_with_siso_diversity;
10462 sc->sc_uhb_supported = cfg->uhb_supported;
10463 if (cfg->xtal_latency) {
10464 sc->sc_xtal_latency = cfg->xtal_latency;
10465 sc->sc_low_latency_xtal = cfg->low_latency_xtal;
10466 }
10467 }
10468
10469 sc->mac_addr_from_csr = 0x380; /* differs on BZ hw generation */
10470
10471 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {
10472 sc->sc_umac_prph_offset = 0x300000;
10473 sc->max_tfd_queue_size = IWX_TFD_QUEUE_SIZE_MAX_GEN3;
10474 } else
10475 sc->max_tfd_queue_size = IWX_TFD_QUEUE_SIZE_MAX;
10476
10477 /* Allocate DMA memory for loading firmware. */
10478 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)
10479 ctxt_info_size = sizeof(struct iwx_context_info_gen3);
10480 else
10481 ctxt_info_size = sizeof(struct iwx_context_info);
10482 err = iwx_dma_contig_alloc(sc->sc_dmat, &sc->ctxt_info_dma,
10483 ctxt_info_size, 1);
10484 if (err) {
10485 device_printf(dev,
10486 "could not allocate memory for loading firmware\n");
10487 return (ENXIO);
10488 }
10489
10490 if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {
10491 err = iwx_dma_contig_alloc(sc->sc_dmat, &sc->prph_scratch_dma,
10492 sizeof(struct iwx_prph_scratch), 1);
10493 if (err) {
10494 device_printf(dev,
10495 "could not allocate prph scratch memory\n");
10496 goto fail1;
10497 }
10498
10499 /*
10500 * Allocate prph information. The driver doesn't use this.
10501 * We use the second half of this page to give the device
10502 * some dummy TR/CR tail pointers - which shouldn't be
10503 * necessary as we don't use this, but the hardware still
10504 * reads/writes there and we can't let it go do that with
10505 * a NULL pointer.
10506 */
10507 KASSERT((sizeof(struct iwx_prph_info) < PAGE_SIZE / 2),
10508 ("iwx_prph_info has wrong size"));
10509 err = iwx_dma_contig_alloc(sc->sc_dmat, &sc->prph_info_dma,
10510 PAGE_SIZE, 1);
10511 if (err) {
10512 device_printf(dev,
10513 "could not allocate prph info memory\n");
10514 goto fail1;
10515 }
10516 }
10517
10518 /* Allocate interrupt cause table (ICT).*/
10519 err = iwx_dma_contig_alloc(sc->sc_dmat, &sc->ict_dma,
10520 IWX_ICT_SIZE, 1<<IWX_ICT_PADDR_SHIFT);
10521 if (err) {
10522 device_printf(dev, "could not allocate ICT table\n");
10523 goto fail1;
10524 }
10525
10526 for (txq_i = 0; txq_i < nitems(sc->txq); txq_i++) {
10527 err = iwx_alloc_tx_ring(sc, &sc->txq[txq_i], txq_i);
10528 if (err) {
10529 device_printf(dev, "could not allocate TX ring %d\n",
10530 txq_i);
10531 goto fail4;
10532 }
10533 }
10534
10535 err = iwx_alloc_rx_ring(sc, &sc->rxq);
10536 if (err) {
10537 device_printf(sc->sc_dev, "could not allocate RX ring\n");
10538 goto fail4;
10539 }
10540
10541 #ifdef IWX_DEBUG
10542 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
10543 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "debug",
10544 CTLFLAG_RWTUN, &sc->sc_debug, 0, "bitmask to control debugging");
10545
10546 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
10547 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "himark",
10548 CTLFLAG_RW, &iwx_himark, 0, "queues high watermark");
10549 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
10550 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "lomark",
10551 CTLFLAG_RW, &iwx_lomark, 0, "queues low watermark");
10552
10553 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
10554 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "qfullmsk",
10555 CTLFLAG_RD, &sc->qfullmsk, 0, "queue fullmask");
10556
10557 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
10558 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "queue0",
10559 CTLFLAG_RD, &sc->txq[0].queued, 0, "queue 0");
10560 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
10561 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "queue1",
10562 CTLFLAG_RD, &sc->txq[1].queued, 0, "queue 1");
10563 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
10564 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "queue2",
10565 CTLFLAG_RD, &sc->txq[2].queued, 0, "queue 2");
10566 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
10567 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "queue3",
10568 CTLFLAG_RD, &sc->txq[3].queued, 0, "queue 3");
10569 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
10570 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "queue4",
10571 CTLFLAG_RD, &sc->txq[4].queued, 0, "queue 4");
10572 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
10573 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "queue5",
10574 CTLFLAG_RD, &sc->txq[5].queued, 0, "queue 5");
10575 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
10576 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "queue6",
10577 CTLFLAG_RD, &sc->txq[6].queued, 0, "queue 6");
10578 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
10579 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "queue7",
10580 CTLFLAG_RD, &sc->txq[7].queued, 0, "queue 7");
10581 #endif
10582 ic->ic_softc = sc;
10583 ic->ic_name = device_get_nameunit(sc->sc_dev);
10584 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
10585 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
10586
10587 /* Set device capabilities. */
10588 ic->ic_caps =
10589 IEEE80211_C_STA |
10590 IEEE80211_C_MONITOR |
10591 IEEE80211_C_WPA | /* WPA/RSN */
10592 IEEE80211_C_WME |
10593 IEEE80211_C_PMGT |
10594 IEEE80211_C_SHSLOT | /* short slot time supported */
10595 IEEE80211_C_SHPREAMBLE | /* short preamble supported */
10596 IEEE80211_C_BGSCAN /* capable of bg scanning */
10597 ;
10598 ic->ic_flags_ext = IEEE80211_FEXT_SCAN_OFFLOAD;
10599 /* Enable seqno offload */
10600 ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD;
10601 /* Don't send null data frames; let firmware do it */
10602 ic->ic_flags_ext |= IEEE80211_FEXT_NO_NULLDATA;
10603
10604 ic->ic_txstream = 2;
10605 ic->ic_rxstream = 2;
10606 ic->ic_htcaps |= IEEE80211_HTC_HT
10607 | IEEE80211_HTCAP_SMPS_OFF
10608 | IEEE80211_HTCAP_SHORTGI20 /* short GI in 20MHz */
10609 | IEEE80211_HTCAP_SHORTGI40 /* short GI in 40MHz */
10610 | IEEE80211_HTCAP_CHWIDTH40 /* 40MHz channel width*/
10611 | IEEE80211_HTC_AMPDU /* tx A-MPDU */
10612 // | IEEE80211_HTC_RX_AMSDU_AMPDU /* TODO: hw reorder */
10613 | IEEE80211_HTCAP_MAXAMSDU_3839; /* max A-MSDU length */
10614
10615 ic->ic_cryptocaps |= IEEE80211_CRYPTO_AES_CCM;
10616
10617 /*
10618 * XXX: setupcurchan() expects vhtcaps to be non-zero
10619 * https://bugs.freebsd.org/274156
10620 */
10621 ic->ic_vht_cap.vht_cap_info |= IEEE80211_VHTCAP_MAX_MPDU_LENGTH_3895
10622 | IEEE80211_VHTCAP_SHORT_GI_80
10623 | 3 << IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK_S
10624 | IEEE80211_VHTCAP_RX_ANTENNA_PATTERN
10625 | IEEE80211_VHTCAP_TX_ANTENNA_PATTERN;
10626
10627 ic->ic_flags_ext |= IEEE80211_FEXT_VHT;
10628 int mcsmap = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 |
10629 IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 |
10630 IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 |
10631 IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |
10632 IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 |
10633 IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 |
10634 IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |
10635 IEEE80211_VHT_MCS_NOT_SUPPORTED << 14;
10636 ic->ic_vht_cap.supp_mcs.tx_mcs_map = htole16(mcsmap);
10637 ic->ic_vht_cap.supp_mcs.rx_mcs_map = htole16(mcsmap);
10638
10639 callout_init_mtx(&sc->watchdog_to, &sc->sc_mtx, 0);
10640 for (i = 0; i < nitems(sc->sc_rxba_data); i++) {
10641 struct iwx_rxba_data *rxba = &sc->sc_rxba_data[i];
10642 rxba->baid = IWX_RX_REORDER_DATA_INVALID_BAID;
10643 rxba->sc = sc;
10644 for (j = 0; j < nitems(rxba->entries); j++)
10645 mbufq_init(&rxba->entries[j].frames, ifqmaxlen);
10646 }
10647
10648 /* Initialize to something to have a chance to get S:N values. */
10649 sc->sc_noise = IWX_DEFAULT_NF;
10650
10651 sc->sc_preinit_hook.ich_func = iwx_attach_hook;
10652 sc->sc_preinit_hook.ich_arg = sc;
10653 if (config_intrhook_establish(&sc->sc_preinit_hook) != 0) {
10654 device_printf(dev,
10655 "config_intrhook_establish failed\n");
10656 goto fail4;
10657 }
10658
10659 return (0);
10660
10661 fail4:
10662 while (--txq_i >= 0)
10663 iwx_free_tx_ring(sc, &sc->txq[txq_i]);
10664 iwx_free_rx_ring(sc, &sc->rxq);
10665 if (sc->ict_dma.vaddr != NULL)
10666 iwx_dma_contig_free(&sc->ict_dma);
10667
10668 fail1:
10669 iwx_dma_contig_free(&sc->ctxt_info_dma);
10670 iwx_dma_contig_free(&sc->prph_scratch_dma);
10671 iwx_dma_contig_free(&sc->prph_info_dma);
10672 return (ENXIO);
10673 }
10674
10675 static int
iwx_detach(device_t dev)10676 iwx_detach(device_t dev)
10677 {
10678 struct iwx_softc *sc = device_get_softc(dev);
10679 int txq_i;
10680
10681 iwx_stop_device(sc);
10682
10683 taskqueue_drain_all(sc->sc_tq);
10684 taskqueue_free(sc->sc_tq);
10685
10686 ieee80211_ifdetach(&sc->sc_ic);
10687
10688 callout_drain(&sc->watchdog_to);
10689
10690 for (txq_i = 0; txq_i < nitems(sc->txq); txq_i++)
10691 iwx_free_tx_ring(sc, &sc->txq[txq_i]);
10692 iwx_free_rx_ring(sc, &sc->rxq);
10693
10694 if (sc->sc_fwp != NULL) {
10695 firmware_put(sc->sc_fwp, FIRMWARE_UNLOAD);
10696 sc->sc_fwp = NULL;
10697 }
10698
10699 if (sc->sc_pnvm != NULL) {
10700 firmware_put(sc->sc_pnvm, FIRMWARE_UNLOAD);
10701 sc->sc_pnvm = NULL;
10702 }
10703
10704 if (sc->sc_irq != NULL) {
10705 bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih);
10706 bus_release_resource(dev, SYS_RES_IRQ,
10707 rman_get_rid(sc->sc_irq), sc->sc_irq);
10708 pci_release_msi(dev);
10709 }
10710 if (sc->sc_mem != NULL)
10711 bus_release_resource(dev, SYS_RES_MEMORY,
10712 rman_get_rid(sc->sc_mem), sc->sc_mem);
10713
10714 IWX_LOCK_DESTROY(sc);
10715
10716 return (0);
10717 }
10718
10719 static void
iwx_radiotap_attach(struct iwx_softc * sc)10720 iwx_radiotap_attach(struct iwx_softc *sc)
10721 {
10722 struct ieee80211com *ic = &sc->sc_ic;
10723
10724 IWX_DPRINTF(sc, IWX_DEBUG_RESET | IWX_DEBUG_TRACE,
10725 "->%s begin\n", __func__);
10726
10727 ieee80211_radiotap_attach(ic,
10728 &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
10729 IWX_TX_RADIOTAP_PRESENT,
10730 &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
10731 IWX_RX_RADIOTAP_PRESENT);
10732
10733 IWX_DPRINTF(sc, IWX_DEBUG_RESET | IWX_DEBUG_TRACE,
10734 "->%s end\n", __func__);
10735 }
10736
10737 struct ieee80211vap *
iwx_vap_create(struct ieee80211com * ic,const char name[IFNAMSIZ],int unit,enum ieee80211_opmode opmode,int flags,const uint8_t bssid[IEEE80211_ADDR_LEN],const uint8_t mac[IEEE80211_ADDR_LEN])10738 iwx_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
10739 enum ieee80211_opmode opmode, int flags,
10740 const uint8_t bssid[IEEE80211_ADDR_LEN],
10741 const uint8_t mac[IEEE80211_ADDR_LEN])
10742 {
10743 struct iwx_vap *ivp;
10744 struct ieee80211vap *vap;
10745
10746 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
10747 return NULL;
10748 ivp = malloc(sizeof(struct iwx_vap), M_80211_VAP, M_WAITOK | M_ZERO);
10749 vap = &ivp->iv_vap;
10750 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
10751 vap->iv_bmissthreshold = 10; /* override default */
10752 /* Override with driver methods. */
10753 ivp->iv_newstate = vap->iv_newstate;
10754 vap->iv_newstate = iwx_newstate;
10755
10756 ivp->id = IWX_DEFAULT_MACID;
10757 ivp->color = IWX_DEFAULT_COLOR;
10758
10759 ivp->have_wme = TRUE;
10760 ivp->ps_disabled = FALSE;
10761
10762 vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_64K;
10763 vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_4;
10764
10765 /* h/w crypto support */
10766 vap->iv_key_alloc = iwx_key_alloc;
10767 vap->iv_key_delete = iwx_key_delete;
10768 vap->iv_key_set = iwx_key_set;
10769 vap->iv_key_update_begin = iwx_key_update_begin;
10770 vap->iv_key_update_end = iwx_key_update_end;
10771
10772 ieee80211_ratectl_init(vap);
10773 /* Complete setup. */
10774 ieee80211_vap_attach(vap, ieee80211_media_change,
10775 ieee80211_media_status, mac);
10776 ic->ic_opmode = opmode;
10777
10778 return vap;
10779 }
10780
10781 static void
iwx_vap_delete(struct ieee80211vap * vap)10782 iwx_vap_delete(struct ieee80211vap *vap)
10783 {
10784 struct iwx_vap *ivp = IWX_VAP(vap);
10785
10786 ieee80211_ratectl_deinit(vap);
10787 ieee80211_vap_detach(vap);
10788 free(ivp, M_80211_VAP);
10789 }
10790
10791 static void
iwx_parent(struct ieee80211com * ic)10792 iwx_parent(struct ieee80211com *ic)
10793 {
10794 struct iwx_softc *sc = ic->ic_softc;
10795 IWX_LOCK(sc);
10796
10797 if (sc->sc_flags & IWX_FLAG_HW_INITED) {
10798 iwx_stop(sc);
10799 sc->sc_flags &= ~IWX_FLAG_HW_INITED;
10800 } else {
10801 iwx_init(sc);
10802 ieee80211_start_all(ic);
10803 }
10804 IWX_UNLOCK(sc);
10805 }
10806
10807 static int
iwx_suspend(device_t dev)10808 iwx_suspend(device_t dev)
10809 {
10810 struct iwx_softc *sc = device_get_softc(dev);
10811 struct ieee80211com *ic = &sc->sc_ic;
10812
10813 /*
10814 * Suspend everything first, then shutdown hardware if it's
10815 * still up.
10816 */
10817 ieee80211_suspend_all(ic);
10818
10819 if (sc->sc_flags & IWX_FLAG_HW_INITED) {
10820 iwx_stop(sc);
10821 sc->sc_flags &= ~IWX_FLAG_HW_INITED;
10822 }
10823 return (0);
10824 }
10825
10826 static int
iwx_resume(device_t dev)10827 iwx_resume(device_t dev)
10828 {
10829 struct iwx_softc *sc = device_get_softc(dev);
10830 struct ieee80211com *ic = &sc->sc_ic;
10831
10832 /*
10833 * We disable the RETRY_TIMEOUT register (0x41) to keep
10834 * PCI Tx retries from interfering with C3 CPU state.
10835 */
10836 pci_write_config(dev, PCI_CFG_RETRY_TIMEOUT, 0x00, 1);
10837
10838 IWX_LOCK(sc);
10839
10840 /* Stop the hardware here if it's still thought of as "up" */
10841 if (sc->sc_flags & IWX_FLAG_HW_INITED) {
10842 iwx_stop(sc);
10843 sc->sc_flags &= ~IWX_FLAG_HW_INITED;
10844 }
10845
10846 IWX_UNLOCK(sc);
10847
10848 /* Start the VAPs, which will bring the hardware back up again */
10849 ieee80211_resume_all(ic);
10850 return (0);
10851 }
10852
10853 static void
iwx_scan_start(struct ieee80211com * ic)10854 iwx_scan_start(struct ieee80211com *ic)
10855 {
10856 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
10857 struct iwx_softc *sc = ic->ic_softc;
10858 int err;
10859
10860 IWX_LOCK(sc);
10861 if ((ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN) == 0)
10862 err = iwx_scan(sc);
10863 else
10864 err = iwx_bgscan(ic);
10865 IWX_UNLOCK(sc);
10866 if (err)
10867 ieee80211_cancel_scan(vap);
10868
10869 return;
10870 }
10871
10872 static void
iwx_update_mcast(struct ieee80211com * ic)10873 iwx_update_mcast(struct ieee80211com *ic)
10874 {
10875 }
10876
10877 static void
iwx_scan_curchan(struct ieee80211_scan_state * ss,unsigned long maxdwell)10878 iwx_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
10879 {
10880 }
10881
10882 static void
iwx_scan_mindwell(struct ieee80211_scan_state * ss)10883 iwx_scan_mindwell(struct ieee80211_scan_state *ss)
10884 {
10885 }
10886
10887 static void
iwx_scan_end(struct ieee80211com * ic)10888 iwx_scan_end(struct ieee80211com *ic)
10889 {
10890 iwx_endscan(ic->ic_softc);
10891 }
10892
10893 static void
iwx_set_channel(struct ieee80211com * ic)10894 iwx_set_channel(struct ieee80211com *ic)
10895 {
10896 #if 0
10897 struct iwx_softc *sc = ic->ic_softc;
10898 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
10899
10900 IWX_DPRINTF(sc, IWX_DEBUG_NI , "%s:%d NOT IMPLEMENTED\n", __func__, __LINE__);
10901 iwx_phy_ctxt_task((void *)sc);
10902 #endif
10903 }
10904
10905 static void
iwx_endscan_cb(void * arg,int pending)10906 iwx_endscan_cb(void *arg, int pending)
10907 {
10908 struct iwx_softc *sc = arg;
10909 struct ieee80211com *ic = &sc->sc_ic;
10910
10911 DPRINTF(("scan ended\n"));
10912 ieee80211_scan_done(TAILQ_FIRST(&ic->ic_vaps));
10913 }
10914
10915 static int
iwx_wme_update(struct ieee80211com * ic)10916 iwx_wme_update(struct ieee80211com *ic)
10917 {
10918 return 0;
10919 }
10920
10921 static int
iwx_raw_xmit(struct ieee80211_node * ni,struct mbuf * m,const struct ieee80211_bpf_params * params)10922 iwx_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
10923 const struct ieee80211_bpf_params *params)
10924 {
10925 struct ieee80211com *ic = ni->ni_ic;
10926 struct iwx_softc *sc = ic->ic_softc;
10927 int err;
10928
10929 IWX_LOCK(sc);
10930 if (sc->sc_flags & IWX_FLAG_STA_ACTIVE) {
10931 err = iwx_tx(sc, m, ni);
10932 IWX_UNLOCK(sc);
10933 return err;
10934 } else {
10935 IWX_UNLOCK(sc);
10936 return EIO;
10937 }
10938 }
10939
10940 static int
iwx_transmit(struct ieee80211com * ic,struct mbuf * m)10941 iwx_transmit(struct ieee80211com *ic, struct mbuf *m)
10942 {
10943 struct iwx_softc *sc = ic->ic_softc;
10944 int error;
10945
10946 // TODO: mbufq_enqueue in iwm
10947 // TODO dequeue in iwm_start, counters, locking
10948 IWX_LOCK(sc);
10949 error = mbufq_enqueue(&sc->sc_snd, m);
10950 if (error) {
10951 IWX_UNLOCK(sc);
10952 return (error);
10953 }
10954
10955 iwx_start(sc);
10956 IWX_UNLOCK(sc);
10957 return (0);
10958 }
10959
10960 static int
iwx_ampdu_rx_start(struct ieee80211_node * ni,struct ieee80211_rx_ampdu * rap,int baparamset,int batimeout,int baseqctl)10961 iwx_ampdu_rx_start(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap,
10962 int baparamset, int batimeout, int baseqctl)
10963 {
10964 struct ieee80211com *ic = ni->ni_ic;
10965 struct iwx_softc *sc = ic->ic_softc;
10966 int tid;
10967
10968 tid = _IEEE80211_MASKSHIFT(le16toh(baparamset), IEEE80211_BAPS_TID);
10969 sc->ni_rx_ba[tid].ba_winstart =
10970 _IEEE80211_MASKSHIFT(le16toh(baseqctl), IEEE80211_BASEQ_START);
10971 sc->ni_rx_ba[tid].ba_winsize =
10972 _IEEE80211_MASKSHIFT(le16toh(baparamset), IEEE80211_BAPS_BUFSIZ);
10973 sc->ni_rx_ba[tid].ba_timeout_val = batimeout;
10974
10975 if (sc->sc_rx_ba_sessions >= IWX_MAX_RX_BA_SESSIONS ||
10976 tid >= IWX_MAX_TID_COUNT)
10977 return ENOSPC;
10978
10979 if (sc->ba_rx.start_tidmask & (1 << tid)) {
10980 DPRINTF(("%s: tid %d already added\n", __func__, tid));
10981 return EBUSY;
10982 }
10983 DPRINTF(("%s: sc->ba_rx.start_tidmask=%x\n", __func__, sc->ba_rx.start_tidmask));
10984
10985 sc->ba_rx.start_tidmask |= (1 << tid);
10986 DPRINTF(("%s: tid=%i\n", __func__, tid));
10987 DPRINTF(("%s: ba_winstart=%i\n", __func__, sc->ni_rx_ba[tid].ba_winstart));
10988 DPRINTF(("%s: ba_winsize=%i\n", __func__, sc->ni_rx_ba[tid].ba_winsize));
10989 DPRINTF(("%s: ba_timeout_val=%i\n", __func__, sc->ni_rx_ba[tid].ba_timeout_val));
10990
10991 taskqueue_enqueue(sc->sc_tq, &sc->ba_rx_task);
10992
10993 // TODO:misha move to ba_task (serialize)
10994 sc->sc_ampdu_rx_start(ni, rap, baparamset, batimeout, baseqctl);
10995
10996 return (0);
10997 }
10998
10999 static void
iwx_ampdu_rx_stop(struct ieee80211_node * ni,struct ieee80211_rx_ampdu * rap)11000 iwx_ampdu_rx_stop(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap)
11001 {
11002 return;
11003 }
11004
11005 /**
11006 * @brief Called by net80211 to request an A-MPDU session be established.
11007 *
11008 * This is called by net80211 to see if an A-MPDU session can be established.
11009 * However, the iwx(4) firmware will take care of establishing the BA
11010 * session for us. net80211 doesn't have to send any action frames here;
11011 * it just needs to plumb up the ampdu session once the BA has been sent.
11012 *
11013 * If we return 0 here then the firmware will set up the state but net80211
11014 * will not; so it's on us to actually complete it via a call to
11015 * ieee80211_ampdu_tx_request_active_ext() .
11016 *
11017 * @param ni ieee80211_node to establish A-MPDU session for
11018 * @param tap pointer to the per-TID state struct
11019 * @param dialogtoken dialogtoken field from the BA request
11020 * @param baparamset baparamset field from the BA request
11021 * @param batimeout batimeout field from the BA request
11022 *
11023 * @returns 0 so net80211 doesn't send the BA action frame to establish A-MPDU.
11024 */
11025 static int
iwx_addba_request(struct ieee80211_node * ni,struct ieee80211_tx_ampdu * tap,int dialogtoken,int baparamset,int batimeout)11026 iwx_addba_request(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
11027 int dialogtoken, int baparamset, int batimeout)
11028 {
11029 struct iwx_softc *sc = ni->ni_ic->ic_softc;
11030 int tid;
11031
11032 tid = _IEEE80211_MASKSHIFT(le16toh(baparamset), IEEE80211_BAPS_TID);
11033 IWX_DPRINTF(sc, IWX_DEBUG_AMPDU_MGMT,
11034 "%s: queuing AMPDU start on tid %i\n", __func__, tid);
11035
11036 /* There's no nice way right now to tell net80211 that we're in the
11037 * middle of an asynchronous ADDBA setup session. So, bump the timeout
11038 * to hz ticks, hopefully we'll get a response by then.
11039 */
11040 tap->txa_nextrequest = ticks + hz;
11041
11042 IWX_LOCK(sc);
11043 sc->ba_tx.start_tidmask |= (1 << tid);
11044 IWX_UNLOCK(sc);
11045
11046 taskqueue_enqueue(sc->sc_tq, &sc->ba_tx_task);
11047
11048 return (0);
11049 }
11050
11051
11052 static int
iwx_addba_response(struct ieee80211_node * ni,struct ieee80211_tx_ampdu * tap,int code,int baparamset,int batimeout)11053 iwx_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
11054 int code, int baparamset, int batimeout)
11055 {
11056 return 0;
11057 }
11058
11059 static void
iwx_key_update_begin(struct ieee80211vap * vap)11060 iwx_key_update_begin(struct ieee80211vap *vap)
11061 {
11062 return;
11063 }
11064
11065 static void
iwx_key_update_end(struct ieee80211vap * vap)11066 iwx_key_update_end(struct ieee80211vap *vap)
11067 {
11068 return;
11069 }
11070
11071 static int
iwx_key_alloc(struct ieee80211vap * vap,struct ieee80211_key * k,ieee80211_keyix * keyix,ieee80211_keyix * rxkeyix)11072 iwx_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
11073 ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
11074 {
11075
11076 if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_AES_CCM) {
11077 return (1);
11078 }
11079
11080 if (ieee80211_is_key_unicast(vap, k)) {
11081 *keyix = 0; /* NB: use key index 0 for ucast key */
11082 } else if (ieee80211_is_key_global(vap, k)) {
11083 *keyix = ieee80211_crypto_get_key_wepidx(vap, k);
11084 } else {
11085 net80211_vap_printf(vap, "%s: invalid crypto key type\n",
11086 __func__);
11087 return (0);
11088 }
11089 *rxkeyix = IEEE80211_KEYIX_NONE; /* XXX maybe *keyix? */
11090 return (1);
11091 }
11092
11093 static int
iwx_key_set(struct ieee80211vap * vap,const struct ieee80211_key * k)11094 iwx_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k)
11095 {
11096 struct ieee80211com *ic = vap->iv_ic;
11097 struct iwx_softc *sc = ic->ic_softc;
11098 struct iwx_add_sta_key_cmd cmd;
11099 uint32_t status;
11100 int err;
11101 int id;
11102
11103 if (k->wk_cipher->ic_cipher != IEEE80211_CIPHER_AES_CCM) {
11104 return 1;
11105 }
11106
11107 /*
11108 * Keys are stored in 'ni' so 'k' is valid if 'ni' is valid.
11109 * Currently we only implement station mode where 'ni' is always
11110 * ic->ic_bss so there is no need to validate arguments beyond this:
11111 */
11112
11113 memset(&cmd, 0, sizeof(cmd));
11114
11115 if (ieee80211_is_key_global(vap, k)) {
11116 id = ieee80211_crypto_get_key_wepidx(vap, k);
11117 IWX_DPRINTF(sc, IWX_DEBUG_KEYMGMT, "%s: adding group key\n",
11118 __func__);
11119 } else if (ieee80211_is_key_unicast(vap, k)) {
11120 IWX_DPRINTF(sc, IWX_DEBUG_KEYMGMT, "%s: adding key\n",
11121 __func__);
11122 id = 0; /* net80211 currently only supports unicast key 0 */
11123 } else {
11124 net80211_vap_printf(vap, "%s: unknown key type\n", __func__);
11125 return (ENXIO);
11126 }
11127
11128 IWX_LOCK(sc);
11129
11130 cmd.common.key_flags = htole16(IWX_STA_KEY_FLG_CCM |
11131 IWX_STA_KEY_FLG_WEP_KEY_MAP |
11132 ((id << IWX_STA_KEY_FLG_KEYID_POS) &
11133 IWX_STA_KEY_FLG_KEYID_MSK));
11134 if (ieee80211_is_key_global(vap, k)) {
11135 cmd.common.key_offset = 1;
11136 cmd.common.key_flags |= htole16(IWX_STA_KEY_MULTICAST);
11137 } else if (ieee80211_is_key_unicast(vap, k)) {
11138 cmd.common.key_offset = 0;
11139 } else {
11140 net80211_vap_printf(vap, "%s: unknown key type\n", __func__);
11141 IWX_UNLOCK(sc);
11142 return (ENXIO);
11143 }
11144 memcpy(cmd.common.key, ieee80211_crypto_get_key_data(k),
11145 MIN(sizeof(cmd.common.key), ieee80211_crypto_get_key_len(k)));
11146 IWX_DPRINTF(sc, IWX_DEBUG_KEYMGMT, "%s: key: id=%d, len=%i, key=%*D\n",
11147 __func__, id,
11148 ieee80211_crypto_get_key_len(k),
11149 ieee80211_crypto_get_key_len(k),
11150 (const unsigned char *) ieee80211_crypto_get_key_data(k), "");
11151 cmd.common.sta_id = IWX_STATION_ID;
11152
11153 cmd.transmit_seq_cnt = htole64(k->wk_keytsc);
11154 IWX_DPRINTF(sc, IWX_DEBUG_KEYMGMT, "%s: k->wk_keytsc=%" PRIu64 "\n",
11155 __func__, k->wk_keytsc);
11156
11157 status = IWX_ADD_STA_SUCCESS;
11158 err = iwx_send_cmd_pdu_status(sc, IWX_ADD_STA_KEY, sizeof(cmd), &cmd,
11159 &status);
11160 if (!err && (status & IWX_ADD_STA_STATUS_MASK) != IWX_ADD_STA_SUCCESS)
11161 err = EIO;
11162 if (err) {
11163 net80211_vap_printf(vap,
11164 "%s: can't set wpa2 keys (error %d)\n", __func__, err);
11165 IWX_UNLOCK(sc);
11166 return err;
11167 } else
11168 IWX_DPRINTF(sc, IWX_DEBUG_KEYMGMT,
11169 "%s: key added successfully\n", __func__);
11170 IWX_UNLOCK(sc);
11171 return (1);
11172 }
11173
11174 static int
iwx_key_delete(struct ieee80211vap * vap,const struct ieee80211_key * k)11175 iwx_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
11176 {
11177 /*
11178 * Note: since there's no key allocations to track - it's either
11179 * the 4 static WEP keys or the single unicast key - there's nothing
11180 * else to do here.
11181 *
11182 * This would need some further work to support IBSS/mesh/AP modes.
11183 */
11184 return (1);
11185 }
11186
11187 static device_method_t iwx_pci_methods[] = {
11188 /* Device interface */
11189 DEVMETHOD(device_probe, iwx_probe),
11190 DEVMETHOD(device_attach, iwx_attach),
11191 DEVMETHOD(device_detach, iwx_detach),
11192 DEVMETHOD(device_suspend, iwx_suspend),
11193 DEVMETHOD(device_resume, iwx_resume),
11194
11195 DEVMETHOD_END
11196 };
11197
11198 static driver_t iwx_pci_driver = {
11199 "iwx",
11200 iwx_pci_methods,
11201 sizeof (struct iwx_softc)
11202 };
11203
11204 DRIVER_MODULE(iwx, pci, iwx_pci_driver, NULL, NULL);
11205 MODULE_PNP_INFO("U16:device;D:#;T:vendor=0x8086", pci, iwx_pci_driver,
11206 iwx_devices, nitems(iwx_devices));
11207 MODULE_DEPEND(iwx, firmware, 1, 1, 1);
11208 MODULE_DEPEND(iwx, pci, 1, 1, 1);
11209 MODULE_DEPEND(iwx, wlan, 1, 1, 1);
11210