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