if_iwm.c revision 1.94 1 1.94 mlelstv /* $NetBSD: if_iwm.c,v 1.94 2026/09/02 04:48:07 mlelstv Exp $ */
2 1.56 nonaka /* OpenBSD: if_iwm.c,v 1.148 2016/11/19 21:07:08 stsp Exp */
3 1.45 nonaka #define IEEE80211_NO_HT
4 1.1 pooka /*
5 1.45 nonaka * Copyright (c) 2014, 2016 genua gmbh <info (at) genua.de>
6 1.45 nonaka * Author: Stefan Sperling <stsp (at) openbsd.org>
7 1.1 pooka * Copyright (c) 2014 Fixup Software Ltd.
8 1.1 pooka *
9 1.1 pooka * Permission to use, copy, modify, and distribute this software for any
10 1.1 pooka * purpose with or without fee is hereby granted, provided that the above
11 1.1 pooka * copyright notice and this permission notice appear in all copies.
12 1.1 pooka *
13 1.1 pooka * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 1.1 pooka * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 1.1 pooka * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 1.1 pooka * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 1.1 pooka * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 1.1 pooka * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 1.1 pooka * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 1.1 pooka */
21 1.1 pooka
22 1.1 pooka /*-
23 1.1 pooka * Based on BSD-licensed source modules in the Linux iwlwifi driver,
24 1.1 pooka * which were used as the reference documentation for this implementation.
25 1.1 pooka *
26 1.1 pooka ***********************************************************************
27 1.1 pooka *
28 1.1 pooka * This file is provided under a dual BSD/GPLv2 license. When using or
29 1.1 pooka * redistributing this file, you may do so under either license.
30 1.1 pooka *
31 1.1 pooka * GPL LICENSE SUMMARY
32 1.1 pooka *
33 1.71 nonaka * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
34 1.45 nonaka * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
35 1.71 nonaka * Copyright(c) 2016 Intel Deutschland GmbH
36 1.1 pooka *
37 1.1 pooka * This program is free software; you can redistribute it and/or modify
38 1.1 pooka * it under the terms of version 2 of the GNU General Public License as
39 1.1 pooka * published by the Free Software Foundation.
40 1.1 pooka *
41 1.1 pooka * This program is distributed in the hope that it will be useful, but
42 1.1 pooka * WITHOUT ANY WARRANTY; without even the implied warranty of
43 1.1 pooka * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 1.1 pooka * General Public License for more details.
45 1.1 pooka *
46 1.1 pooka * You should have received a copy of the GNU General Public License
47 1.1 pooka * along with this program; if not, write to the Free Software
48 1.1 pooka * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
49 1.1 pooka * USA
50 1.1 pooka *
51 1.1 pooka * The full GNU General Public License is included in this distribution
52 1.1 pooka * in the file called COPYING.
53 1.1 pooka *
54 1.1 pooka * Contact Information:
55 1.71 nonaka * Intel Linux Wireless <linuxwifi (at) intel.com>
56 1.1 pooka * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
57 1.1 pooka *
58 1.1 pooka * BSD LICENSE
59 1.1 pooka *
60 1.71 nonaka * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
61 1.45 nonaka * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
62 1.71 nonaka * Copyright(c) 2016 Intel Deutschland GmbH
63 1.1 pooka * All rights reserved.
64 1.1 pooka *
65 1.1 pooka * Redistribution and use in source and binary forms, with or without
66 1.1 pooka * modification, are permitted provided that the following conditions
67 1.1 pooka * are met:
68 1.1 pooka *
69 1.1 pooka * * Redistributions of source code must retain the above copyright
70 1.1 pooka * notice, this list of conditions and the following disclaimer.
71 1.1 pooka * * Redistributions in binary form must reproduce the above copyright
72 1.1 pooka * notice, this list of conditions and the following disclaimer in
73 1.1 pooka * the documentation and/or other materials provided with the
74 1.1 pooka * distribution.
75 1.1 pooka * * Neither the name Intel Corporation nor the names of its
76 1.1 pooka * contributors may be used to endorse or promote products derived
77 1.1 pooka * from this software without specific prior written permission.
78 1.1 pooka *
79 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
80 1.1 pooka * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
81 1.1 pooka * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
82 1.1 pooka * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
83 1.1 pooka * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
84 1.1 pooka * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
85 1.1 pooka * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
86 1.1 pooka * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
87 1.1 pooka * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
88 1.1 pooka * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
89 1.1 pooka * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
90 1.1 pooka */
91 1.1 pooka
92 1.1 pooka /*-
93 1.1 pooka * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini (at) free.fr>
94 1.1 pooka *
95 1.1 pooka * Permission to use, copy, modify, and distribute this software for any
96 1.1 pooka * purpose with or without fee is hereby granted, provided that the above
97 1.1 pooka * copyright notice and this permission notice appear in all copies.
98 1.1 pooka *
99 1.1 pooka * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
100 1.1 pooka * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
101 1.1 pooka * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
102 1.1 pooka * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
103 1.1 pooka * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
104 1.1 pooka * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
105 1.1 pooka * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
106 1.1 pooka */
107 1.1 pooka
108 1.1 pooka #include <sys/cdefs.h>
109 1.94 mlelstv __KERNEL_RCSID(0, "$NetBSD: if_iwm.c,v 1.94 2026/09/02 04:48:07 mlelstv Exp $");
110 1.1 pooka
111 1.1 pooka #include <sys/param.h>
112 1.1 pooka #include <sys/conf.h>
113 1.1 pooka #include <sys/kernel.h>
114 1.1 pooka #include <sys/kmem.h>
115 1.1 pooka #include <sys/mbuf.h>
116 1.1 pooka #include <sys/mutex.h>
117 1.1 pooka #include <sys/proc.h>
118 1.1 pooka #include <sys/socket.h>
119 1.1 pooka #include <sys/sockio.h>
120 1.32 nonaka #include <sys/sysctl.h>
121 1.1 pooka #include <sys/systm.h>
122 1.1 pooka
123 1.1 pooka #include <sys/cpu.h>
124 1.1 pooka #include <sys/bus.h>
125 1.1 pooka #include <sys/workqueue.h>
126 1.1 pooka #include <machine/endian.h>
127 1.66 nonaka #include <sys/intr.h>
128 1.1 pooka
129 1.1 pooka #include <dev/pci/pcireg.h>
130 1.1 pooka #include <dev/pci/pcivar.h>
131 1.1 pooka #include <dev/pci/pcidevs.h>
132 1.1 pooka #include <dev/firmload.h>
133 1.1 pooka
134 1.1 pooka #include <net/bpf.h>
135 1.1 pooka #include <net/if.h>
136 1.1 pooka #include <net/if_dl.h>
137 1.1 pooka #include <net/if_media.h>
138 1.1 pooka #include <net/if_ether.h>
139 1.1 pooka
140 1.1 pooka #include <netinet/in.h>
141 1.1 pooka #include <netinet/ip.h>
142 1.1 pooka
143 1.1 pooka #include <net80211/ieee80211_var.h>
144 1.1 pooka #include <net80211/ieee80211_amrr.h>
145 1.1 pooka #include <net80211/ieee80211_radiotap.h>
146 1.1 pooka
147 1.1 pooka #define DEVNAME(_s) device_xname((_s)->sc_dev)
148 1.1 pooka #define IC2IFP(_ic_) ((_ic_)->ic_ifp)
149 1.1 pooka
150 1.1 pooka #define le16_to_cpup(_a_) (le16toh(*(const uint16_t *)(_a_)))
151 1.1 pooka #define le32_to_cpup(_a_) (le32toh(*(const uint32_t *)(_a_)))
152 1.1 pooka
153 1.1 pooka #ifdef IWM_DEBUG
154 1.1 pooka #define DPRINTF(x) do { if (iwm_debug > 0) printf x; } while (0)
155 1.1 pooka #define DPRINTFN(n, x) do { if (iwm_debug >= (n)) printf x; } while (0)
156 1.32 nonaka int iwm_debug = 0;
157 1.1 pooka #else
158 1.1 pooka #define DPRINTF(x) do { ; } while (0)
159 1.1 pooka #define DPRINTFN(n, x) do { ; } while (0)
160 1.1 pooka #endif
161 1.1 pooka
162 1.1 pooka #include <dev/pci/if_iwmreg.h>
163 1.1 pooka #include <dev/pci/if_iwmvar.h>
164 1.1 pooka
165 1.91 mlelstv static const u_int8_t etheranyaddr[ETHER_ADDR_LEN] = {
166 1.91 mlelstv 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
167 1.91 mlelstv };
168 1.91 mlelstv
169 1.4 nonaka static const uint8_t iwm_nvm_channels[] = {
170 1.1 pooka /* 2.4 GHz */
171 1.1 pooka 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
172 1.1 pooka /* 5 GHz */
173 1.45 nonaka 36, 40, 44, 48, 52, 56, 60, 64,
174 1.1 pooka 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
175 1.1 pooka 149, 153, 157, 161, 165
176 1.1 pooka };
177 1.45 nonaka
178 1.45 nonaka static const uint8_t iwm_nvm_channels_8000[] = {
179 1.45 nonaka /* 2.4 GHz */
180 1.45 nonaka 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
181 1.45 nonaka /* 5 GHz */
182 1.45 nonaka 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92,
183 1.45 nonaka 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
184 1.45 nonaka 149, 153, 157, 161, 165, 169, 173, 177, 181
185 1.45 nonaka };
186 1.45 nonaka
187 1.1 pooka #define IWM_NUM_2GHZ_CHANNELS 14
188 1.1 pooka
189 1.4 nonaka static const struct iwm_rate {
190 1.91 mlelstv uint16_t rate;
191 1.1 pooka uint8_t plcp;
192 1.45 nonaka uint8_t ht_plcp;
193 1.1 pooka } iwm_rates[] = {
194 1.45 nonaka /* Legacy */ /* HT */
195 1.45 nonaka { 2, IWM_RATE_1M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP },
196 1.45 nonaka { 4, IWM_RATE_2M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP },
197 1.45 nonaka { 11, IWM_RATE_5M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP },
198 1.45 nonaka { 22, IWM_RATE_11M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP },
199 1.45 nonaka { 12, IWM_RATE_6M_PLCP, IWM_RATE_HT_SISO_MCS_0_PLCP },
200 1.45 nonaka { 18, IWM_RATE_9M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP },
201 1.45 nonaka { 24, IWM_RATE_12M_PLCP, IWM_RATE_HT_SISO_MCS_1_PLCP },
202 1.91 mlelstv { 26, IWM_RATE_INVM_PLCP, IWM_RATE_HT_MIMO2_MCS_0_PLCP },
203 1.45 nonaka { 36, IWM_RATE_18M_PLCP, IWM_RATE_HT_SISO_MCS_2_PLCP },
204 1.45 nonaka { 48, IWM_RATE_24M_PLCP, IWM_RATE_HT_SISO_MCS_3_PLCP },
205 1.91 mlelstv { 52, IWM_RATE_INVM_PLCP, IWM_RATE_HT_MIMO2_MCS_1_PLCP },
206 1.45 nonaka { 72, IWM_RATE_36M_PLCP, IWM_RATE_HT_SISO_MCS_4_PLCP },
207 1.91 mlelstv { 78, IWM_RATE_INVM_PLCP, IWM_RATE_HT_MIMO2_MCS_2_PLCP },
208 1.45 nonaka { 96, IWM_RATE_48M_PLCP, IWM_RATE_HT_SISO_MCS_5_PLCP },
209 1.91 mlelstv { 104, IWM_RATE_INVM_PLCP, IWM_RATE_HT_MIMO2_MCS_3_PLCP },
210 1.45 nonaka { 108, IWM_RATE_54M_PLCP, IWM_RATE_HT_SISO_MCS_6_PLCP },
211 1.45 nonaka { 128, IWM_RATE_INVM_PLCP, IWM_RATE_HT_SISO_MCS_7_PLCP },
212 1.91 mlelstv { 156, IWM_RATE_INVM_PLCP, IWM_RATE_HT_MIMO2_MCS_4_PLCP },
213 1.91 mlelstv { 208, IWM_RATE_INVM_PLCP, IWM_RATE_HT_MIMO2_MCS_5_PLCP },
214 1.91 mlelstv { 234, IWM_RATE_INVM_PLCP, IWM_RATE_HT_MIMO2_MCS_6_PLCP },
215 1.91 mlelstv { 260, IWM_RATE_INVM_PLCP, IWM_RATE_HT_MIMO2_MCS_7_PLCP },
216 1.1 pooka };
217 1.1 pooka #define IWM_RIDX_CCK 0
218 1.1 pooka #define IWM_RIDX_OFDM 4
219 1.1 pooka #define IWM_RIDX_MAX (__arraycount(iwm_rates)-1)
220 1.1 pooka #define IWM_RIDX_IS_CCK(_i_) ((_i_) < IWM_RIDX_OFDM)
221 1.1 pooka #define IWM_RIDX_IS_OFDM(_i_) ((_i_) >= IWM_RIDX_OFDM)
222 1.91 mlelstv #define IWM_RVAL_IS_OFDM(_i_) ((_i_) >= 12 && (_i_) != 22)
223 1.1 pooka
224 1.45 nonaka #ifndef IEEE80211_NO_HT
225 1.45 nonaka /* Convert an MCS index into an iwm_rates[] index. */
226 1.45 nonaka static const int iwm_mcs2ridx[] = {
227 1.45 nonaka IWM_RATE_MCS_0_INDEX,
228 1.45 nonaka IWM_RATE_MCS_1_INDEX,
229 1.45 nonaka IWM_RATE_MCS_2_INDEX,
230 1.45 nonaka IWM_RATE_MCS_3_INDEX,
231 1.45 nonaka IWM_RATE_MCS_4_INDEX,
232 1.45 nonaka IWM_RATE_MCS_5_INDEX,
233 1.45 nonaka IWM_RATE_MCS_6_INDEX,
234 1.45 nonaka IWM_RATE_MCS_7_INDEX,
235 1.91 mlelstv IWM_RATE_MCS_8_INDEX,
236 1.91 mlelstv IWM_RATE_MCS_9_INDEX,
237 1.91 mlelstv IWM_RATE_MCS_10_INDEX,
238 1.91 mlelstv IWM_RATE_MCS_11_INDEX,
239 1.91 mlelstv IWM_RATE_MCS_12_INDEX,
240 1.91 mlelstv IWM_RATE_MCS_13_INDEX,
241 1.91 mlelstv IWM_RATE_MCS_14_INDEX,
242 1.91 mlelstv IWM_RATE_MCS_15_INDEX,
243 1.45 nonaka };
244 1.45 nonaka #endif
245 1.45 nonaka
246 1.45 nonaka struct iwm_nvm_section {
247 1.45 nonaka uint16_t length;
248 1.45 nonaka uint8_t *data;
249 1.45 nonaka };
250 1.45 nonaka
251 1.1 pooka struct iwm_newstate_state {
252 1.1 pooka struct work ns_wk;
253 1.1 pooka enum ieee80211_state ns_nstate;
254 1.1 pooka int ns_arg;
255 1.1 pooka int ns_generation;
256 1.1 pooka };
257 1.1 pooka
258 1.91 mlelstv #ifndef IEEE80211_NO_HT
259 1.91 mlelstv static int iwm_is_mimo_ht_plcp(uint8_t);
260 1.91 mlelstv static int iwm_is_mimo_ht_mcs(int);
261 1.91 mlelstv #endif
262 1.4 nonaka static int iwm_store_cscheme(struct iwm_softc *, uint8_t *, size_t);
263 1.4 nonaka static int iwm_firmware_store_section(struct iwm_softc *,
264 1.4 nonaka enum iwm_ucode_type, uint8_t *, size_t);
265 1.4 nonaka static int iwm_set_default_calib(struct iwm_softc *, const void *);
266 1.91 mlelstv static void iwm_fw_info_free(struct iwm_fw_info *);
267 1.91 mlelstv static void iwm_fw_version_str(char *, size_t, uint32_t, uint32_t, uint32_t);
268 1.61 nonaka static int iwm_read_firmware(struct iwm_softc *, enum iwm_ucode_type);
269 1.4 nonaka static uint32_t iwm_read_prph(struct iwm_softc *, uint32_t);
270 1.4 nonaka static void iwm_write_prph(struct iwm_softc *, uint32_t, uint32_t);
271 1.4 nonaka static int iwm_read_mem(struct iwm_softc *, uint32_t, void *, int);
272 1.4 nonaka static int iwm_write_mem(struct iwm_softc *, uint32_t, const void *, int);
273 1.4 nonaka static int iwm_write_mem32(struct iwm_softc *, uint32_t, uint32_t);
274 1.4 nonaka static int iwm_poll_bit(struct iwm_softc *, int, uint32_t, uint32_t, int);
275 1.4 nonaka static int iwm_nic_lock(struct iwm_softc *);
276 1.4 nonaka static void iwm_nic_unlock(struct iwm_softc *);
277 1.91 mlelstv static int iwm_set_bits_mask_prph(struct iwm_softc *, uint32_t, uint32_t,
278 1.8 nonaka uint32_t);
279 1.91 mlelstv static int iwm_set_bits_prph(struct iwm_softc *, uint32_t, uint32_t);
280 1.91 mlelstv static int iwm_clear_bits_prph(struct iwm_softc *, uint32_t, uint32_t);
281 1.4 nonaka static int iwm_dma_contig_alloc(bus_dma_tag_t, struct iwm_dma_info *,
282 1.4 nonaka bus_size_t, bus_size_t);
283 1.4 nonaka static void iwm_dma_contig_free(struct iwm_dma_info *);
284 1.4 nonaka static int iwm_alloc_rx_ring(struct iwm_softc *, struct iwm_rx_ring *);
285 1.45 nonaka static void iwm_disable_rx_dma(struct iwm_softc *);
286 1.4 nonaka static void iwm_reset_rx_ring(struct iwm_softc *, struct iwm_rx_ring *);
287 1.4 nonaka static void iwm_free_rx_ring(struct iwm_softc *, struct iwm_rx_ring *);
288 1.4 nonaka static int iwm_alloc_tx_ring(struct iwm_softc *, struct iwm_tx_ring *,
289 1.4 nonaka int);
290 1.4 nonaka static void iwm_reset_tx_ring(struct iwm_softc *, struct iwm_tx_ring *);
291 1.4 nonaka static void iwm_free_tx_ring(struct iwm_softc *, struct iwm_tx_ring *);
292 1.4 nonaka static void iwm_enable_rfkill_int(struct iwm_softc *);
293 1.4 nonaka static int iwm_check_rfkill(struct iwm_softc *);
294 1.4 nonaka static void iwm_enable_interrupts(struct iwm_softc *);
295 1.91 mlelstv static void iwm_enable_fwload_interrupt(struct iwm_softc *);
296 1.4 nonaka static void iwm_restore_interrupts(struct iwm_softc *);
297 1.4 nonaka static void iwm_disable_interrupts(struct iwm_softc *);
298 1.4 nonaka static void iwm_ict_reset(struct iwm_softc *);
299 1.4 nonaka static int iwm_set_hw_ready(struct iwm_softc *);
300 1.4 nonaka static int iwm_prepare_card_hw(struct iwm_softc *);
301 1.4 nonaka static void iwm_apm_config(struct iwm_softc *);
302 1.4 nonaka static int iwm_apm_init(struct iwm_softc *);
303 1.4 nonaka static void iwm_apm_stop(struct iwm_softc *);
304 1.11 nonaka static int iwm_allow_mcast(struct iwm_softc *);
305 1.4 nonaka static int iwm_start_hw(struct iwm_softc *);
306 1.4 nonaka static void iwm_stop_device(struct iwm_softc *);
307 1.45 nonaka static void iwm_nic_config(struct iwm_softc *);
308 1.4 nonaka static int iwm_nic_rx_init(struct iwm_softc *);
309 1.91 mlelstv static int iwm_nic_rx_legacy_init(struct iwm_softc *);
310 1.4 nonaka static int iwm_nic_tx_init(struct iwm_softc *);
311 1.4 nonaka static int iwm_nic_init(struct iwm_softc *);
312 1.91 mlelstv static int iwm_enable_ac_txq(struct iwm_softc *, int, int);
313 1.91 mlelstv static int iwm_enable_txq(struct iwm_softc *, int, int, int,
314 1.91 mlelstv int, uint8_t, uint16_t);
315 1.4 nonaka static int iwm_post_alive(struct iwm_softc *);
316 1.45 nonaka static struct iwm_phy_db_entry *
317 1.45 nonaka iwm_phy_db_get_section(struct iwm_softc *,
318 1.45 nonaka enum iwm_phy_db_section_type, uint16_t);
319 1.45 nonaka static int iwm_phy_db_set_section(struct iwm_softc *,
320 1.45 nonaka struct iwm_calib_res_notif_phy_db *, uint16_t);
321 1.4 nonaka static int iwm_is_valid_channel(uint16_t);
322 1.4 nonaka static uint8_t iwm_ch_id_to_ch_index(uint16_t);
323 1.4 nonaka static uint16_t iwm_channel_id_to_papd(uint16_t);
324 1.4 nonaka static uint16_t iwm_channel_id_to_txp(struct iwm_softc *, uint16_t);
325 1.4 nonaka static int iwm_phy_db_get_section_data(struct iwm_softc *, uint32_t,
326 1.4 nonaka uint8_t **, uint16_t *, uint16_t);
327 1.4 nonaka static int iwm_send_phy_db_cmd(struct iwm_softc *, uint16_t, uint16_t,
328 1.4 nonaka void *);
329 1.45 nonaka static int iwm_phy_db_send_all_channel_groups(struct iwm_softc *,
330 1.45 nonaka enum iwm_phy_db_section_type, uint8_t);
331 1.4 nonaka static int iwm_send_phy_db_data(struct iwm_softc *);
332 1.45 nonaka static int iwm_send_time_event_cmd(struct iwm_softc *,
333 1.91 mlelstv const struct iwm_time_event_cmd *);
334 1.45 nonaka static void iwm_protect_session(struct iwm_softc *, struct iwm_node *,
335 1.45 nonaka uint32_t, uint32_t);
336 1.91 mlelstv static void iwm_unprotect_session(struct iwm_softc *, struct iwm_node *);
337 1.4 nonaka static int iwm_nvm_read_chunk(struct iwm_softc *, uint16_t, uint16_t,
338 1.4 nonaka uint16_t, uint8_t *, uint16_t *);
339 1.4 nonaka static int iwm_nvm_read_section(struct iwm_softc *, uint16_t, uint8_t *,
340 1.45 nonaka uint16_t *, size_t);
341 1.45 nonaka static void iwm_init_channel_map(struct iwm_softc *, const uint16_t * const,
342 1.45 nonaka const uint8_t *, size_t);
343 1.91 mlelstv static int iwm_mimo_enabled(struct iwm_softc *);
344 1.45 nonaka #ifndef IEEE80211_NO_HT
345 1.45 nonaka static void iwm_setup_ht_rates(struct iwm_softc *);
346 1.45 nonaka static void iwm_htprot_task(void *);
347 1.45 nonaka static void iwm_update_htprot(struct ieee80211com *,
348 1.45 nonaka struct ieee80211_node *);
349 1.45 nonaka static int iwm_ampdu_rx_start(struct ieee80211com *,
350 1.45 nonaka struct ieee80211_node *, uint8_t);
351 1.45 nonaka static void iwm_ampdu_rx_stop(struct ieee80211com *,
352 1.45 nonaka struct ieee80211_node *, uint8_t);
353 1.45 nonaka static void iwm_sta_rx_agg(struct iwm_softc *, struct ieee80211_node *,
354 1.45 nonaka uint8_t, uint16_t, int);
355 1.91 mlelstv #if 0
356 1.45 nonaka static int iwm_ampdu_tx_start(struct ieee80211com *,
357 1.45 nonaka struct ieee80211_node *, uint8_t);
358 1.45 nonaka static void iwm_ampdu_tx_stop(struct ieee80211com *,
359 1.45 nonaka struct ieee80211_node *, uint8_t);
360 1.45 nonaka #endif
361 1.45 nonaka static void iwm_ba_task(void *);
362 1.45 nonaka #endif
363 1.45 nonaka
364 1.4 nonaka static int iwm_parse_nvm_data(struct iwm_softc *, const uint16_t *,
365 1.91 mlelstv const uint16_t *, const uint16_t *,
366 1.91 mlelstv const uint16_t *, const uint16_t *,
367 1.91 mlelstv const uint16_t *, int);
368 1.45 nonaka static void iwm_set_hw_address_8000(struct iwm_softc *,
369 1.45 nonaka struct iwm_nvm_data *, const uint16_t *, const uint16_t *);
370 1.45 nonaka static int iwm_parse_nvm_sections(struct iwm_softc *,
371 1.45 nonaka struct iwm_nvm_section *);
372 1.4 nonaka static int iwm_nvm_init(struct iwm_softc *);
373 1.45 nonaka static int iwm_firmware_load_sect(struct iwm_softc *, uint32_t,
374 1.45 nonaka const uint8_t *, uint32_t);
375 1.4 nonaka static int iwm_firmware_load_chunk(struct iwm_softc *, uint32_t,
376 1.4 nonaka const uint8_t *, uint32_t);
377 1.45 nonaka static int iwm_load_firmware_7000(struct iwm_softc *, enum iwm_ucode_type);
378 1.45 nonaka static int iwm_load_cpu_sections_8000(struct iwm_softc *,
379 1.45 nonaka struct iwm_fw_sects *, int , int *);
380 1.45 nonaka static int iwm_load_firmware_8000(struct iwm_softc *, enum iwm_ucode_type);
381 1.4 nonaka static int iwm_load_firmware(struct iwm_softc *, enum iwm_ucode_type);
382 1.4 nonaka static int iwm_start_fw(struct iwm_softc *, enum iwm_ucode_type);
383 1.4 nonaka static int iwm_send_tx_ant_cfg(struct iwm_softc *, uint8_t);
384 1.4 nonaka static int iwm_send_phy_cfg_cmd(struct iwm_softc *);
385 1.45 nonaka static int iwm_load_ucode_wait_alive(struct iwm_softc *,
386 1.4 nonaka enum iwm_ucode_type);
387 1.91 mlelstv static int iwm_send_dqa_cmd(struct iwm_softc *);
388 1.4 nonaka static int iwm_run_init_mvm_ucode(struct iwm_softc *, int);
389 1.91 mlelstv #ifdef notyet
390 1.91 mlelstv static int iwm_config_ltr(struct iwm_softc *);
391 1.91 mlelstv #endif
392 1.4 nonaka static int iwm_rx_addbuf(struct iwm_softc *, int, int);
393 1.45 nonaka static int iwm_calc_rssi(struct iwm_softc *, struct iwm_rx_phy_info *);
394 1.45 nonaka static int iwm_get_signal_strength(struct iwm_softc *,
395 1.4 nonaka struct iwm_rx_phy_info *);
396 1.45 nonaka static void iwm_rx_rx_phy_cmd(struct iwm_softc *,
397 1.4 nonaka struct iwm_rx_packet *, struct iwm_rx_data *);
398 1.45 nonaka static int iwm_get_noise(const struct iwm_statistics_rx_non_phy *);
399 1.45 nonaka static void iwm_rx_rx_mpdu(struct iwm_softc *, struct iwm_rx_packet *,
400 1.4 nonaka struct iwm_rx_data *);
401 1.45 nonaka static void iwm_rx_tx_cmd_single(struct iwm_softc *, struct iwm_rx_packet *, struct iwm_node *);
402 1.45 nonaka static void iwm_rx_tx_cmd(struct iwm_softc *, struct iwm_rx_packet *,
403 1.4 nonaka struct iwm_rx_data *);
404 1.45 nonaka static int iwm_binding_cmd(struct iwm_softc *, struct iwm_node *,
405 1.4 nonaka uint32_t);
406 1.45 nonaka static void iwm_phy_ctxt_cmd_hdr(struct iwm_softc *, struct iwm_phy_ctxt *,
407 1.45 nonaka struct iwm_phy_context_cmd *, uint32_t, uint32_t);
408 1.45 nonaka static void iwm_phy_ctxt_cmd_data(struct iwm_softc *,
409 1.4 nonaka struct iwm_phy_context_cmd *, struct ieee80211_channel *,
410 1.4 nonaka uint8_t, uint8_t);
411 1.45 nonaka static int iwm_phy_ctxt_cmd(struct iwm_softc *, struct iwm_phy_ctxt *,
412 1.45 nonaka uint8_t, uint8_t, uint32_t, uint32_t);
413 1.4 nonaka static int iwm_send_cmd(struct iwm_softc *, struct iwm_host_cmd *);
414 1.45 nonaka static int iwm_send_cmd_pdu(struct iwm_softc *, uint32_t, uint32_t,
415 1.4 nonaka uint16_t, const void *);
416 1.45 nonaka static int iwm_send_cmd_status(struct iwm_softc *, struct iwm_host_cmd *,
417 1.45 nonaka uint32_t *);
418 1.45 nonaka static int iwm_send_cmd_pdu_status(struct iwm_softc *, uint32_t, uint16_t,
419 1.45 nonaka const void *, uint32_t *);
420 1.4 nonaka static void iwm_free_resp(struct iwm_softc *, struct iwm_host_cmd *);
421 1.45 nonaka static void iwm_cmd_done(struct iwm_softc *, int qid, int idx);
422 1.4 nonaka static void iwm_update_sched(struct iwm_softc *, int, int, uint8_t,
423 1.4 nonaka uint16_t);
424 1.45 nonaka static const struct iwm_rate *
425 1.45 nonaka iwm_tx_fill_cmd(struct iwm_softc *, struct iwm_node *,
426 1.45 nonaka struct ieee80211_frame *, struct iwm_tx_cmd *);
427 1.4 nonaka static int iwm_tx(struct iwm_softc *, struct mbuf *,
428 1.4 nonaka struct ieee80211_node *, int);
429 1.45 nonaka static void iwm_led_enable(struct iwm_softc *);
430 1.45 nonaka static void iwm_led_disable(struct iwm_softc *);
431 1.45 nonaka static int iwm_led_is_enabled(struct iwm_softc *);
432 1.45 nonaka static void iwm_led_blink_timeout(void *);
433 1.45 nonaka static void iwm_led_blink_start(struct iwm_softc *);
434 1.45 nonaka static void iwm_led_blink_stop(struct iwm_softc *);
435 1.45 nonaka static int iwm_beacon_filter_send_cmd(struct iwm_softc *,
436 1.4 nonaka struct iwm_beacon_filter_cmd *);
437 1.45 nonaka static void iwm_beacon_filter_set_cqm_params(struct iwm_softc *,
438 1.4 nonaka struct iwm_node *, struct iwm_beacon_filter_cmd *);
439 1.45 nonaka static int iwm_update_beacon_abort(struct iwm_softc *, struct iwm_node *,
440 1.45 nonaka int);
441 1.45 nonaka static void iwm_power_build_cmd(struct iwm_softc *, struct iwm_node *,
442 1.4 nonaka struct iwm_mac_power_cmd *);
443 1.45 nonaka static int iwm_power_mac_update_mode(struct iwm_softc *,
444 1.4 nonaka struct iwm_node *);
445 1.45 nonaka static int iwm_power_update_device(struct iwm_softc *);
446 1.45 nonaka #ifdef notyet
447 1.45 nonaka static int iwm_enable_beacon_filter(struct iwm_softc *, struct iwm_node *);
448 1.45 nonaka #endif
449 1.45 nonaka static int iwm_disable_beacon_filter(struct iwm_softc *);
450 1.45 nonaka static int iwm_add_sta_cmd(struct iwm_softc *, struct iwm_node *, int);
451 1.45 nonaka static int iwm_add_aux_sta(struct iwm_softc *);
452 1.45 nonaka static uint16_t iwm_scan_rx_chain(struct iwm_softc *);
453 1.45 nonaka static uint32_t iwm_scan_rate_n_flags(struct iwm_softc *, int, int);
454 1.45 nonaka static uint8_t iwm_lmac_scan_fill_channels(struct iwm_softc *,
455 1.45 nonaka struct iwm_scan_channel_cfg_lmac *, int);
456 1.45 nonaka static int iwm_fill_probe_req(struct iwm_softc *,
457 1.45 nonaka struct iwm_scan_probe_req *);
458 1.91 mlelstv static int iwm_fill_probe_req_v1(struct iwm_softc *,
459 1.91 mlelstv struct iwm_scan_probe_req_v1 *);
460 1.45 nonaka static int iwm_lmac_scan(struct iwm_softc *);
461 1.45 nonaka static int iwm_config_umac_scan(struct iwm_softc *);
462 1.45 nonaka static int iwm_umac_scan(struct iwm_softc *);
463 1.91 mlelstv static void iwm_mcc_update(struct iwm_softc *, struct iwm_mcc_chub_notif *);
464 1.45 nonaka static uint8_t iwm_ridx2rate(struct ieee80211_rateset *, int);
465 1.45 nonaka static void iwm_ack_rates(struct iwm_softc *, struct iwm_node *, int *,
466 1.4 nonaka int *);
467 1.45 nonaka static void iwm_mac_ctxt_cmd_common(struct iwm_softc *, struct iwm_node *,
468 1.45 nonaka struct iwm_mac_ctx_cmd *, uint32_t, int);
469 1.45 nonaka static void iwm_mac_ctxt_cmd_fill_sta(struct iwm_softc *, struct iwm_node *,
470 1.45 nonaka struct iwm_mac_data_sta *, int);
471 1.45 nonaka static int iwm_mac_ctxt_cmd(struct iwm_softc *, struct iwm_node *,
472 1.45 nonaka uint32_t, int);
473 1.91 mlelstv static void iwm_rx_missed_beacons_notif(struct iwm_softc *,
474 1.91 mlelstv struct iwm_missed_beacons_notif *);
475 1.45 nonaka static int iwm_update_quotas(struct iwm_softc *, struct iwm_node *);
476 1.91 mlelstv static int iwm_scan(struct iwm_softc *);
477 1.91 mlelstv static int iwm_phy_ctxt_update(struct iwm_softc *, struct iwm_phy_ctxt *,
478 1.91 mlelstv struct ieee80211_channel *, uint8_t, uint8_t, uint32_t);
479 1.4 nonaka static int iwm_auth(struct iwm_softc *);
480 1.91 mlelstv #ifdef notyet
481 1.91 mlelstv static int iwm_deauth(struct iwm_softc *);
482 1.91 mlelstv #endif
483 1.91 mlelstv static int iwm_run(struct iwm_softc *);
484 1.91 mlelstv #ifdef notyet
485 1.91 mlelstv static int iwm_run_stop(struct iwm_softc *);
486 1.91 mlelstv #endif
487 1.4 nonaka static int iwm_assoc(struct iwm_softc *);
488 1.4 nonaka static void iwm_calib_timeout(void *);
489 1.91 mlelstv static int iwm_setrates_task(struct iwm_softc *);
490 1.91 mlelstv static void iwm_setrates_cb(struct work *, void *);
491 1.45 nonaka static int iwm_setrates(struct iwm_node *);
492 1.4 nonaka static int iwm_media_change(struct ifnet *);
493 1.65 nonaka static int iwm_do_newstate(struct ieee80211com *, enum ieee80211_state,
494 1.65 nonaka int);
495 1.5 nonaka static void iwm_newstate_cb(struct work *, void *);
496 1.4 nonaka static int iwm_newstate(struct ieee80211com *, enum ieee80211_state, int);
497 1.50 nonaka static void iwm_endscan(struct iwm_softc *);
498 1.45 nonaka static void iwm_fill_sf_command(struct iwm_softc *, struct iwm_sf_cfg_cmd *,
499 1.45 nonaka struct ieee80211_node *);
500 1.45 nonaka static int iwm_sf_config(struct iwm_softc *, int);
501 1.45 nonaka static int iwm_send_bt_init_conf(struct iwm_softc *);
502 1.91 mlelstv static int iwm_send_soc_conf(struct iwm_softc *);
503 1.45 nonaka static int iwm_send_update_mcc_cmd(struct iwm_softc *, const char *);
504 1.91 mlelstv static int iwm_send_temp_report_ths_cmd(struct iwm_softc *);
505 1.45 nonaka static void iwm_tt_tx_backoff(struct iwm_softc *, uint32_t);
506 1.4 nonaka static int iwm_init_hw(struct iwm_softc *);
507 1.4 nonaka static int iwm_init(struct ifnet *);
508 1.4 nonaka static void iwm_start(struct ifnet *);
509 1.4 nonaka static void iwm_stop(struct ifnet *, int);
510 1.4 nonaka static void iwm_watchdog(struct ifnet *);
511 1.4 nonaka static int iwm_ioctl(struct ifnet *, u_long, void *);
512 1.4 nonaka static const char *iwm_desc_lookup(uint32_t);
513 1.4 nonaka static void iwm_nic_error(struct iwm_softc *);
514 1.91 mlelstv static void iwm_dump_driver_status(struct iwm_softc *);
515 1.45 nonaka static void iwm_nic_umac_error(struct iwm_softc *);
516 1.91 mlelstv static void iwm_rx_pkt(struct iwm_softc *, struct iwm_rx_data *);
517 1.4 nonaka static void iwm_notif_intr(struct iwm_softc *);
518 1.61 nonaka static int iwm_intr(void *);
519 1.50 nonaka static void iwm_softintr(void *);
520 1.91 mlelstv static int iwm_preinit(struct iwm_softc *, bool);
521 1.4 nonaka static void iwm_attach_hook(device_t);
522 1.4 nonaka static void iwm_attach(device_t, device_t, void *);
523 1.87 riastrad static int iwm_config_complete(struct iwm_softc *);
524 1.4 nonaka #if 0
525 1.4 nonaka static void iwm_init_task(void *);
526 1.4 nonaka static int iwm_activate(device_t, enum devact);
527 1.4 nonaka static void iwm_wakeup(struct iwm_softc *);
528 1.4 nonaka #endif
529 1.4 nonaka static void iwm_radiotap_attach(struct iwm_softc *);
530 1.36 nonaka static int iwm_sysctl_fw_loaded_handler(SYSCTLFN_PROTO);
531 1.36 nonaka
532 1.36 nonaka static int iwm_sysctl_root_num;
533 1.60 nonaka static int iwm_lar_disable;
534 1.1 pooka
535 1.61 nonaka #ifndef IWM_DEFAULT_MCC
536 1.61 nonaka #define IWM_DEFAULT_MCC "ZZ"
537 1.61 nonaka #endif
538 1.61 nonaka static char iwm_default_mcc[3] = IWM_DEFAULT_MCC;
539 1.61 nonaka
540 1.1 pooka static int
541 1.1 pooka iwm_firmload(struct iwm_softc *sc)
542 1.1 pooka {
543 1.1 pooka struct iwm_fw_info *fw = &sc->sc_fw;
544 1.1 pooka firmware_handle_t fwh;
545 1.45 nonaka int err;
546 1.1 pooka
547 1.36 nonaka if (ISSET(sc->sc_flags, IWM_FLAG_FW_LOADED))
548 1.36 nonaka return 0;
549 1.36 nonaka
550 1.1 pooka /* Open firmware image. */
551 1.45 nonaka err = firmware_open("if_iwm", sc->sc_fwname, &fwh);
552 1.45 nonaka if (err) {
553 1.1 pooka aprint_error_dev(sc->sc_dev,
554 1.1 pooka "could not get firmware handle %s\n", sc->sc_fwname);
555 1.45 nonaka return err;
556 1.1 pooka }
557 1.1 pooka
558 1.36 nonaka if (fw->fw_rawdata != NULL && fw->fw_rawsize > 0) {
559 1.36 nonaka kmem_free(fw->fw_rawdata, fw->fw_rawsize);
560 1.36 nonaka fw->fw_rawdata = NULL;
561 1.36 nonaka }
562 1.36 nonaka
563 1.1 pooka fw->fw_rawsize = firmware_get_size(fwh);
564 1.1 pooka /*
565 1.1 pooka * Well, this is how the Linux driver checks it ....
566 1.1 pooka */
567 1.1 pooka if (fw->fw_rawsize < sizeof(uint32_t)) {
568 1.1 pooka aprint_error_dev(sc->sc_dev,
569 1.1 pooka "firmware too short: %zd bytes\n", fw->fw_rawsize);
570 1.45 nonaka err = EINVAL;
571 1.1 pooka goto out;
572 1.1 pooka }
573 1.1 pooka
574 1.1 pooka /* Read the firmware. */
575 1.1 pooka fw->fw_rawdata = kmem_alloc(fw->fw_rawsize, KM_SLEEP);
576 1.45 nonaka err = firmware_read(fwh, 0, fw->fw_rawdata, fw->fw_rawsize);
577 1.45 nonaka if (err) {
578 1.1 pooka aprint_error_dev(sc->sc_dev,
579 1.1 pooka "could not read firmware %s\n", sc->sc_fwname);
580 1.1 pooka goto out;
581 1.1 pooka }
582 1.1 pooka
583 1.36 nonaka SET(sc->sc_flags, IWM_FLAG_FW_LOADED);
584 1.1 pooka out:
585 1.1 pooka /* caller will release memory, if necessary */
586 1.1 pooka
587 1.1 pooka firmware_close(fwh);
588 1.45 nonaka return err;
589 1.1 pooka }
590 1.1 pooka
591 1.1 pooka /*
592 1.1 pooka * just maintaining status quo.
593 1.1 pooka */
594 1.1 pooka static void
595 1.45 nonaka iwm_fix_channel(struct iwm_softc *sc, struct mbuf *m)
596 1.1 pooka {
597 1.45 nonaka struct ieee80211com *ic = &sc->sc_ic;
598 1.1 pooka struct ieee80211_frame *wh;
599 1.1 pooka uint8_t subtype;
600 1.1 pooka
601 1.1 pooka wh = mtod(m, struct ieee80211_frame *);
602 1.1 pooka
603 1.1 pooka if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT)
604 1.1 pooka return;
605 1.1 pooka
606 1.1 pooka subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
607 1.1 pooka
608 1.1 pooka if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
609 1.1 pooka subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
610 1.1 pooka return;
611 1.1 pooka
612 1.45 nonaka int chan = le32toh(sc->sc_last_phy_info.channel);
613 1.45 nonaka if (chan < __arraycount(ic->ic_channels))
614 1.45 nonaka ic->ic_curchan = &ic->ic_channels[chan];
615 1.1 pooka }
616 1.1 pooka
617 1.91 mlelstv #ifdef notyet
618 1.91 mlelstv static uint8_t
619 1.91 mlelstv iwm_lookup_cmd_ver(struct iwm_softc *sc, uint8_t grp, uint8_t cmd)
620 1.91 mlelstv {
621 1.91 mlelstv const struct iwm_fw_cmd_version *entry;
622 1.91 mlelstv int i;
623 1.91 mlelstv
624 1.91 mlelstv for (i = 0; i < sc->n_cmd_versions; i++) {
625 1.91 mlelstv entry = &sc->cmd_versions[i];
626 1.91 mlelstv if (entry->group == grp && entry->cmd == cmd)
627 1.91 mlelstv return entry->cmd_ver;
628 1.91 mlelstv }
629 1.91 mlelstv
630 1.91 mlelstv return IWM_FW_CMD_VER_UNKNOWN;
631 1.91 mlelstv }
632 1.91 mlelstv
633 1.91 mlelstv static int
634 1.91 mlelstv iwm_is_mimo_ht_plcp(uint8_t ht_plcp)
635 1.91 mlelstv {
636 1.91 mlelstv return (ht_plcp != IWM_RATE_HT_SISO_MCS_INV_PLCP &&
637 1.91 mlelstv (ht_plcp & IWM_RATE_HT_MCS_NSS_MSK));
638 1.91 mlelstv }
639 1.91 mlelstv
640 1.91 mlelstv static int
641 1.91 mlelstv iwm_is_mimo_ht_mcs(int mcs)
642 1.91 mlelstv {
643 1.91 mlelstv int ridx = iwm_ht_mcs2ridx[mcs];
644 1.91 mlelstv return iwm_is_mimo_ht_plcp(iwm_rates[ridx].ht_plcp);
645 1.91 mlelstv
646 1.91 mlelstv }
647 1.91 mlelstv #endif
648 1.91 mlelstv
649 1.4 nonaka static int
650 1.1 pooka iwm_store_cscheme(struct iwm_softc *sc, uint8_t *data, size_t dlen)
651 1.1 pooka {
652 1.45 nonaka struct iwm_fw_cscheme_list *l = (struct iwm_fw_cscheme_list *)data;
653 1.1 pooka
654 1.1 pooka if (dlen < sizeof(*l) ||
655 1.1 pooka dlen < sizeof(l->size) + l->size * sizeof(*l->cs))
656 1.1 pooka return EINVAL;
657 1.1 pooka
658 1.1 pooka /* we don't actually store anything for now, always use s/w crypto */
659 1.1 pooka
660 1.1 pooka return 0;
661 1.1 pooka }
662 1.1 pooka
663 1.4 nonaka static int
664 1.45 nonaka iwm_firmware_store_section(struct iwm_softc *sc, enum iwm_ucode_type type,
665 1.45 nonaka uint8_t *data, size_t dlen)
666 1.1 pooka {
667 1.1 pooka struct iwm_fw_sects *fws;
668 1.1 pooka struct iwm_fw_onesect *fwone;
669 1.1 pooka
670 1.1 pooka if (type >= IWM_UCODE_TYPE_MAX)
671 1.1 pooka return EINVAL;
672 1.1 pooka if (dlen < sizeof(uint32_t))
673 1.1 pooka return EINVAL;
674 1.1 pooka
675 1.1 pooka fws = &sc->sc_fw.fw_sects[type];
676 1.1 pooka if (fws->fw_count >= IWM_UCODE_SECT_MAX)
677 1.1 pooka return EINVAL;
678 1.1 pooka
679 1.1 pooka fwone = &fws->fw_sect[fws->fw_count];
680 1.1 pooka
681 1.1 pooka /* first 32bit are device load offset */
682 1.1 pooka memcpy(&fwone->fws_devoff, data, sizeof(uint32_t));
683 1.1 pooka
684 1.1 pooka /* rest is data */
685 1.1 pooka fwone->fws_data = data + sizeof(uint32_t);
686 1.1 pooka fwone->fws_len = dlen - sizeof(uint32_t);
687 1.1 pooka
688 1.1 pooka /* for freeing the buffer during driver unload */
689 1.1 pooka fwone->fws_alloc = data;
690 1.1 pooka fwone->fws_allocsize = dlen;
691 1.1 pooka
692 1.1 pooka fws->fw_count++;
693 1.1 pooka fws->fw_totlen += fwone->fws_len;
694 1.1 pooka
695 1.1 pooka return 0;
696 1.1 pooka }
697 1.1 pooka
698 1.1 pooka struct iwm_tlv_calib_data {
699 1.1 pooka uint32_t ucode_type;
700 1.1 pooka struct iwm_tlv_calib_ctrl calib;
701 1.1 pooka } __packed;
702 1.1 pooka
703 1.4 nonaka static int
704 1.1 pooka iwm_set_default_calib(struct iwm_softc *sc, const void *data)
705 1.1 pooka {
706 1.1 pooka const struct iwm_tlv_calib_data *def_calib = data;
707 1.1 pooka uint32_t ucode_type = le32toh(def_calib->ucode_type);
708 1.1 pooka
709 1.1 pooka if (ucode_type >= IWM_UCODE_TYPE_MAX) {
710 1.45 nonaka DPRINTF(("%s: Wrong ucode_type %u for default calibration.\n",
711 1.45 nonaka DEVNAME(sc), ucode_type));
712 1.1 pooka return EINVAL;
713 1.1 pooka }
714 1.1 pooka
715 1.1 pooka sc->sc_default_calib[ucode_type].flow_trigger =
716 1.1 pooka def_calib->calib.flow_trigger;
717 1.1 pooka sc->sc_default_calib[ucode_type].event_trigger =
718 1.1 pooka def_calib->calib.event_trigger;
719 1.1 pooka
720 1.1 pooka return 0;
721 1.1 pooka }
722 1.1 pooka
723 1.91 mlelstv static void
724 1.91 mlelstv iwm_fw_info_free(struct iwm_fw_info *fw)
725 1.91 mlelstv {
726 1.91 mlelstv kmem_free(fw->fw_rawdata, fw->fw_rawsize);
727 1.91 mlelstv fw->fw_rawdata = NULL;
728 1.91 mlelstv fw->fw_rawsize = 0;
729 1.91 mlelstv /* don't touch fw->fw_status */
730 1.91 mlelstv memset(fw->fw_sects, 0, sizeof(fw->fw_sects));
731 1.91 mlelstv }
732 1.91 mlelstv
733 1.91 mlelstv static void
734 1.91 mlelstv iwm_fw_version_str(char *buf, size_t bufsize,
735 1.91 mlelstv uint32_t major, uint32_t minor, uint32_t api)
736 1.91 mlelstv {
737 1.91 mlelstv /*
738 1.91 mlelstv * Starting with major version 35 the Linux driver prints the minor
739 1.91 mlelstv * version in hexadecimal.
740 1.91 mlelstv */
741 1.91 mlelstv if (major >= 35)
742 1.91 mlelstv snprintf(buf, bufsize, "%u.%08x.%u", major, minor, api);
743 1.91 mlelstv else
744 1.91 mlelstv snprintf(buf, bufsize, "%u.%u.%u", major, minor, api);
745 1.91 mlelstv }
746 1.91 mlelstv
747 1.4 nonaka static int
748 1.61 nonaka iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
749 1.1 pooka {
750 1.1 pooka struct iwm_fw_info *fw = &sc->sc_fw;
751 1.8 nonaka struct iwm_tlv_ucode_header *uhdr;
752 1.8 nonaka struct iwm_ucode_tlv tlv;
753 1.1 pooka enum iwm_ucode_tlv_type tlv_type;
754 1.1 pooka uint8_t *data;
755 1.91 mlelstv int err;
756 1.2 nonaka size_t len;
757 1.1 pooka
758 1.91 mlelstv if (fw->fw_status == IWM_FW_STATUS_DONE)
759 1.61 nonaka return 0;
760 1.61 nonaka
761 1.91 mlelstv while (fw->fw_status == IWM_FW_STATUS_INPROGRESS)
762 1.91 mlelstv tsleep(&sc->sc_fw, 0, "iwmfwp", 0);
763 1.91 mlelstv fw->fw_status = IWM_FW_STATUS_INPROGRESS;
764 1.1 pooka
765 1.91 mlelstv if (fw->fw_status == IWM_FW_STATUS_DONE)
766 1.1 pooka return 0;
767 1.1 pooka
768 1.91 mlelstv if (fw->fw_rawdata != NULL) {
769 1.91 mlelstv iwm_fw_info_free(fw);
770 1.91 mlelstv CLR(sc->sc_flags, IWM_FLAG_FW_LOADED);
771 1.91 mlelstv }
772 1.91 mlelstv
773 1.45 nonaka err = iwm_firmload(sc);
774 1.45 nonaka if (err) {
775 1.3 nonaka aprint_error_dev(sc->sc_dev,
776 1.3 nonaka "could not read firmware %s (error %d)\n",
777 1.45 nonaka sc->sc_fwname, err);
778 1.1 pooka goto out;
779 1.1 pooka }
780 1.1 pooka
781 1.45 nonaka sc->sc_capaflags = 0;
782 1.91 mlelstv sc->sc_capa_n_scan_channels = IWM_DEFAULT_SCAN_CHANNELS;
783 1.45 nonaka memset(sc->sc_enabled_capa, 0, sizeof(sc->sc_enabled_capa));
784 1.91 mlelstv memset(sc->sc_ucode_api, 0, sizeof(sc->sc_ucode_api));
785 1.91 mlelstv sc->n_cmd_versions = 0;
786 1.1 pooka
787 1.1 pooka uhdr = (void *)fw->fw_rawdata;
788 1.1 pooka if (*(uint32_t *)fw->fw_rawdata != 0
789 1.1 pooka || le32toh(uhdr->magic) != IWM_TLV_UCODE_MAGIC) {
790 1.3 nonaka aprint_error_dev(sc->sc_dev, "invalid firmware %s\n",
791 1.3 nonaka sc->sc_fwname);
792 1.45 nonaka err = EINVAL;
793 1.1 pooka goto out;
794 1.1 pooka }
795 1.1 pooka
796 1.91 mlelstv iwm_fw_version_str(sc->sc_fwver, sizeof(sc->sc_fwver),
797 1.45 nonaka IWM_UCODE_MAJOR(le32toh(uhdr->ver)),
798 1.45 nonaka IWM_UCODE_MINOR(le32toh(uhdr->ver)),
799 1.45 nonaka IWM_UCODE_API(le32toh(uhdr->ver)));
800 1.91 mlelstv
801 1.1 pooka data = uhdr->data;
802 1.1 pooka len = fw->fw_rawsize - sizeof(*uhdr);
803 1.1 pooka
804 1.1 pooka while (len >= sizeof(tlv)) {
805 1.2 nonaka size_t tlv_len;
806 1.1 pooka void *tlv_data;
807 1.1 pooka
808 1.1 pooka memcpy(&tlv, data, sizeof(tlv));
809 1.1 pooka tlv_len = le32toh(tlv.length);
810 1.1 pooka tlv_type = le32toh(tlv.type);
811 1.1 pooka
812 1.1 pooka len -= sizeof(tlv);
813 1.1 pooka data += sizeof(tlv);
814 1.1 pooka tlv_data = data;
815 1.1 pooka
816 1.1 pooka if (len < tlv_len) {
817 1.3 nonaka aprint_error_dev(sc->sc_dev,
818 1.3 nonaka "firmware too short: %zu bytes\n", len);
819 1.45 nonaka err = EINVAL;
820 1.1 pooka goto parse_out;
821 1.1 pooka }
822 1.1 pooka
823 1.45 nonaka switch (tlv_type) {
824 1.1 pooka case IWM_UCODE_TLV_PROBE_MAX_LEN:
825 1.1 pooka if (tlv_len < sizeof(uint32_t)) {
826 1.45 nonaka err = EINVAL;
827 1.1 pooka goto parse_out;
828 1.1 pooka }
829 1.1 pooka sc->sc_capa_max_probe_len
830 1.1 pooka = le32toh(*(uint32_t *)tlv_data);
831 1.1 pooka /* limit it to something sensible */
832 1.45 nonaka if (sc->sc_capa_max_probe_len >
833 1.45 nonaka IWM_SCAN_OFFLOAD_PROBE_REQ_SIZE) {
834 1.45 nonaka err = EINVAL;
835 1.1 pooka goto parse_out;
836 1.1 pooka }
837 1.1 pooka break;
838 1.1 pooka case IWM_UCODE_TLV_PAN:
839 1.1 pooka if (tlv_len) {
840 1.45 nonaka err = EINVAL;
841 1.1 pooka goto parse_out;
842 1.1 pooka }
843 1.1 pooka sc->sc_capaflags |= IWM_UCODE_TLV_FLAGS_PAN;
844 1.1 pooka break;
845 1.1 pooka case IWM_UCODE_TLV_FLAGS:
846 1.1 pooka if (tlv_len < sizeof(uint32_t)) {
847 1.45 nonaka err = EINVAL;
848 1.1 pooka goto parse_out;
849 1.1 pooka }
850 1.71 nonaka if (tlv_len % sizeof(uint32_t)) {
851 1.71 nonaka err = EINVAL;
852 1.71 nonaka goto parse_out;
853 1.71 nonaka }
854 1.1 pooka /*
855 1.1 pooka * Apparently there can be many flags, but Linux driver
856 1.1 pooka * parses only the first one, and so do we.
857 1.1 pooka *
858 1.1 pooka * XXX: why does this override IWM_UCODE_TLV_PAN?
859 1.1 pooka * Intentional or a bug? Observations from
860 1.1 pooka * current firmware file:
861 1.1 pooka * 1) TLV_PAN is parsed first
862 1.1 pooka * 2) TLV_FLAGS contains TLV_FLAGS_PAN
863 1.1 pooka * ==> this resets TLV_PAN to itself... hnnnk
864 1.1 pooka */
865 1.1 pooka sc->sc_capaflags = le32toh(*(uint32_t *)tlv_data);
866 1.1 pooka break;
867 1.1 pooka case IWM_UCODE_TLV_CSCHEME:
868 1.45 nonaka err = iwm_store_cscheme(sc, tlv_data, tlv_len);
869 1.45 nonaka if (err)
870 1.1 pooka goto parse_out;
871 1.1 pooka break;
872 1.45 nonaka case IWM_UCODE_TLV_NUM_OF_CPU: {
873 1.45 nonaka uint32_t num_cpu;
874 1.1 pooka if (tlv_len != sizeof(uint32_t)) {
875 1.45 nonaka err = EINVAL;
876 1.1 pooka goto parse_out;
877 1.1 pooka }
878 1.45 nonaka num_cpu = le32toh(*(uint32_t *)tlv_data);
879 1.91 mlelstv if (num_cpu < 1 || num_cpu > 2) {
880 1.45 nonaka err = EINVAL;
881 1.1 pooka goto parse_out;
882 1.1 pooka }
883 1.1 pooka break;
884 1.45 nonaka }
885 1.1 pooka case IWM_UCODE_TLV_SEC_RT:
886 1.45 nonaka err = iwm_firmware_store_section(sc,
887 1.45 nonaka IWM_UCODE_TYPE_REGULAR, tlv_data, tlv_len);
888 1.45 nonaka if (err)
889 1.1 pooka goto parse_out;
890 1.1 pooka break;
891 1.1 pooka case IWM_UCODE_TLV_SEC_INIT:
892 1.45 nonaka err = iwm_firmware_store_section(sc,
893 1.45 nonaka IWM_UCODE_TYPE_INIT, tlv_data, tlv_len);
894 1.45 nonaka if (err)
895 1.1 pooka goto parse_out;
896 1.1 pooka break;
897 1.1 pooka case IWM_UCODE_TLV_SEC_WOWLAN:
898 1.45 nonaka err = iwm_firmware_store_section(sc,
899 1.45 nonaka IWM_UCODE_TYPE_WOW, tlv_data, tlv_len);
900 1.45 nonaka if (err)
901 1.1 pooka goto parse_out;
902 1.1 pooka break;
903 1.1 pooka case IWM_UCODE_TLV_DEF_CALIB:
904 1.1 pooka if (tlv_len != sizeof(struct iwm_tlv_calib_data)) {
905 1.45 nonaka err = EINVAL;
906 1.1 pooka goto parse_out;
907 1.1 pooka }
908 1.45 nonaka err = iwm_set_default_calib(sc, tlv_data);
909 1.45 nonaka if (err)
910 1.1 pooka goto parse_out;
911 1.1 pooka break;
912 1.1 pooka case IWM_UCODE_TLV_PHY_SKU:
913 1.1 pooka if (tlv_len != sizeof(uint32_t)) {
914 1.45 nonaka err = EINVAL;
915 1.1 pooka goto parse_out;
916 1.1 pooka }
917 1.1 pooka sc->sc_fw_phy_config = le32toh(*(uint32_t *)tlv_data);
918 1.1 pooka break;
919 1.1 pooka
920 1.45 nonaka case IWM_UCODE_TLV_API_CHANGES_SET: {
921 1.45 nonaka struct iwm_ucode_api *api;
922 1.71 nonaka uint32_t idx, bits;
923 1.71 nonaka int i;
924 1.45 nonaka if (tlv_len != sizeof(*api)) {
925 1.45 nonaka err = EINVAL;
926 1.45 nonaka goto parse_out;
927 1.45 nonaka }
928 1.45 nonaka api = (struct iwm_ucode_api *)tlv_data;
929 1.71 nonaka idx = le32toh(api->api_index);
930 1.71 nonaka bits = le32toh(api->api_flags);
931 1.71 nonaka if (idx >= howmany(IWM_NUM_UCODE_TLV_API, 32)) {
932 1.61 nonaka err = EINVAL;
933 1.45 nonaka goto parse_out;
934 1.45 nonaka }
935 1.71 nonaka for (i = 0; i < 32; i++) {
936 1.71 nonaka if (!ISSET(bits, __BIT(i)))
937 1.71 nonaka continue;
938 1.71 nonaka setbit(sc->sc_ucode_api, i + (32 * idx));
939 1.71 nonaka }
940 1.45 nonaka break;
941 1.45 nonaka }
942 1.45 nonaka
943 1.45 nonaka case IWM_UCODE_TLV_ENABLED_CAPABILITIES: {
944 1.45 nonaka struct iwm_ucode_capa *capa;
945 1.71 nonaka uint32_t idx, bits;
946 1.71 nonaka int i;
947 1.45 nonaka if (tlv_len != sizeof(*capa)) {
948 1.45 nonaka err = EINVAL;
949 1.45 nonaka goto parse_out;
950 1.45 nonaka }
951 1.45 nonaka capa = (struct iwm_ucode_capa *)tlv_data;
952 1.45 nonaka idx = le32toh(capa->api_index);
953 1.71 nonaka bits = le32toh(capa->api_capa);
954 1.45 nonaka if (idx >= howmany(IWM_NUM_UCODE_TLV_CAPA, 32)) {
955 1.61 nonaka err = EINVAL;
956 1.45 nonaka goto parse_out;
957 1.45 nonaka }
958 1.45 nonaka for (i = 0; i < 32; i++) {
959 1.71 nonaka if (!ISSET(bits, __BIT(i)))
960 1.45 nonaka continue;
961 1.45 nonaka setbit(sc->sc_enabled_capa, i + (32 * idx));
962 1.45 nonaka }
963 1.45 nonaka break;
964 1.45 nonaka }
965 1.45 nonaka
966 1.91 mlelstv case IWM_UCODE_TLV_CMD_VERSIONS:
967 1.91 mlelstv if (tlv_len % sizeof(struct iwm_fw_cmd_version)) {
968 1.91 mlelstv tlv_len /= sizeof(struct iwm_fw_cmd_version);
969 1.91 mlelstv tlv_len *= sizeof(struct iwm_fw_cmd_version);
970 1.91 mlelstv }
971 1.91 mlelstv if (sc->n_cmd_versions != 0) {
972 1.91 mlelstv err = EINVAL;
973 1.91 mlelstv goto parse_out;
974 1.91 mlelstv }
975 1.91 mlelstv if (tlv_len > sizeof(sc->cmd_versions)) {
976 1.91 mlelstv err = EINVAL;
977 1.91 mlelstv goto parse_out;
978 1.91 mlelstv }
979 1.91 mlelstv memcpy(&sc->cmd_versions[0], tlv_data, tlv_len);
980 1.91 mlelstv sc->n_cmd_versions = tlv_len / sizeof(struct iwm_fw_cmd_version);
981 1.91 mlelstv break;
982 1.91 mlelstv
983 1.45 nonaka case IWM_UCODE_TLV_SDIO_ADMA_ADDR:
984 1.45 nonaka case IWM_UCODE_TLV_FW_GSCAN_CAPA:
985 1.71 nonaka case IWM_UCODE_TLV_FW_MEM_SEG:
986 1.1 pooka /* ignore, not used by current driver */
987 1.1 pooka break;
988 1.1 pooka
989 1.45 nonaka case IWM_UCODE_TLV_SEC_RT_USNIFFER:
990 1.45 nonaka err = iwm_firmware_store_section(sc,
991 1.45 nonaka IWM_UCODE_TYPE_REGULAR_USNIFFER, tlv_data,
992 1.45 nonaka tlv_len);
993 1.45 nonaka if (err)
994 1.45 nonaka goto parse_out;
995 1.45 nonaka break;
996 1.45 nonaka
997 1.71 nonaka case IWM_UCODE_TLV_PAGING: {
998 1.71 nonaka uint32_t paging_mem_size;
999 1.71 nonaka if (tlv_len != sizeof(paging_mem_size)) {
1000 1.71 nonaka err = EINVAL;
1001 1.71 nonaka goto parse_out;
1002 1.71 nonaka }
1003 1.71 nonaka paging_mem_size = le32toh(*(uint32_t *)tlv_data);
1004 1.71 nonaka if (paging_mem_size > IWM_MAX_PAGING_IMAGE_SIZE) {
1005 1.71 nonaka err = EINVAL;
1006 1.71 nonaka goto parse_out;
1007 1.71 nonaka }
1008 1.71 nonaka if (paging_mem_size & (IWM_FW_PAGING_SIZE - 1)) {
1009 1.71 nonaka err = EINVAL;
1010 1.71 nonaka goto parse_out;
1011 1.71 nonaka }
1012 1.71 nonaka fw->fw_sects[IWM_UCODE_TYPE_REGULAR].paging_mem_size =
1013 1.71 nonaka paging_mem_size;
1014 1.71 nonaka fw->fw_sects[IWM_UCODE_TYPE_REGULAR_USNIFFER].paging_mem_size =
1015 1.71 nonaka paging_mem_size;
1016 1.71 nonaka break;
1017 1.71 nonaka }
1018 1.71 nonaka
1019 1.45 nonaka case IWM_UCODE_TLV_N_SCAN_CHANNELS:
1020 1.45 nonaka if (tlv_len != sizeof(uint32_t)) {
1021 1.45 nonaka err = EINVAL;
1022 1.45 nonaka goto parse_out;
1023 1.45 nonaka }
1024 1.45 nonaka sc->sc_capa_n_scan_channels =
1025 1.45 nonaka le32toh(*(uint32_t *)tlv_data);
1026 1.91 mlelstv if (sc->sc_capa_n_scan_channels > IWM_MAX_SCAN_CHANNELS) {
1027 1.91 mlelstv err = ERANGE;
1028 1.91 mlelstv goto parse_out;
1029 1.91 mlelstv }
1030 1.45 nonaka break;
1031 1.45 nonaka
1032 1.45 nonaka case IWM_UCODE_TLV_FW_VERSION:
1033 1.45 nonaka if (tlv_len != sizeof(uint32_t) * 3) {
1034 1.45 nonaka err = EINVAL;
1035 1.45 nonaka goto parse_out;
1036 1.45 nonaka }
1037 1.91 mlelstv
1038 1.91 mlelstv iwm_fw_version_str(sc->sc_fwver, sizeof(sc->sc_fwver),
1039 1.45 nonaka le32toh(((uint32_t *)tlv_data)[0]),
1040 1.45 nonaka le32toh(((uint32_t *)tlv_data)[1]),
1041 1.45 nonaka le32toh(((uint32_t *)tlv_data)[2]));
1042 1.45 nonaka break;
1043 1.45 nonaka
1044 1.1 pooka default:
1045 1.2 nonaka DPRINTF(("%s: unknown firmware section %d, abort\n",
1046 1.2 nonaka DEVNAME(sc), tlv_type));
1047 1.45 nonaka err = EINVAL;
1048 1.1 pooka goto parse_out;
1049 1.1 pooka }
1050 1.1 pooka
1051 1.91 mlelstv /*
1052 1.91 mlelstv * Check for size_t overflow and ignore missing padding at
1053 1.91 mlelstv * end of firmware file.
1054 1.91 mlelstv */
1055 1.91 mlelstv if (roundup(tlv_len, 4) > len)
1056 1.91 mlelstv break;
1057 1.91 mlelstv
1058 1.1 pooka len -= roundup(tlv_len, 4);
1059 1.1 pooka data += roundup(tlv_len, 4);
1060 1.1 pooka }
1061 1.1 pooka
1062 1.45 nonaka KASSERT(err == 0);
1063 1.1 pooka
1064 1.1 pooka parse_out:
1065 1.45 nonaka if (err) {
1066 1.91 mlelstv aprint_error_dev(sc->sc_dev, "firmware parse error %d, "
1067 1.91 mlelstv "section type %d\n", err, tlv_type);
1068 1.1 pooka }
1069 1.1 pooka
1070 1.1 pooka if (!(sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)) {
1071 1.3 nonaka aprint_error_dev(sc->sc_dev,
1072 1.3 nonaka "device uses unsupported power ops\n");
1073 1.45 nonaka err = ENOTSUP;
1074 1.1 pooka }
1075 1.1 pooka
1076 1.1 pooka out:
1077 1.91 mlelstv if (err) {
1078 1.2 nonaka fw->fw_status = IWM_FW_STATUS_NONE;
1079 1.91 mlelstv if (fw->fw_rawdata != NULL) {
1080 1.91 mlelstv iwm_fw_info_free(fw);
1081 1.91 mlelstv CLR(sc->sc_flags, IWM_FLAG_FW_LOADED);
1082 1.91 mlelstv }
1083 1.91 mlelstv } else {
1084 1.1 pooka fw->fw_status = IWM_FW_STATUS_DONE;
1085 1.91 mlelstv }
1086 1.1 pooka wakeup(&sc->sc_fw);
1087 1.1 pooka
1088 1.45 nonaka return err;
1089 1.1 pooka }
1090 1.1 pooka
1091 1.4 nonaka static uint32_t
1092 1.1 pooka iwm_read_prph(struct iwm_softc *sc, uint32_t addr)
1093 1.1 pooka {
1094 1.1 pooka IWM_WRITE(sc,
1095 1.1 pooka IWM_HBUS_TARG_PRPH_RADDR, ((addr & 0x000fffff) | (3 << 24)));
1096 1.1 pooka IWM_BARRIER_READ_WRITE(sc);
1097 1.1 pooka return IWM_READ(sc, IWM_HBUS_TARG_PRPH_RDAT);
1098 1.1 pooka }
1099 1.1 pooka
1100 1.4 nonaka static void
1101 1.1 pooka iwm_write_prph(struct iwm_softc *sc, uint32_t addr, uint32_t val)
1102 1.1 pooka {
1103 1.1 pooka IWM_WRITE(sc,
1104 1.1 pooka IWM_HBUS_TARG_PRPH_WADDR, ((addr & 0x000fffff) | (3 << 24)));
1105 1.1 pooka IWM_BARRIER_WRITE(sc);
1106 1.1 pooka IWM_WRITE(sc, IWM_HBUS_TARG_PRPH_WDAT, val);
1107 1.1 pooka }
1108 1.1 pooka
1109 1.4 nonaka static int
1110 1.1 pooka iwm_read_mem(struct iwm_softc *sc, uint32_t addr, void *buf, int dwords)
1111 1.1 pooka {
1112 1.53 nonaka int offs;
1113 1.1 pooka uint32_t *vals = buf;
1114 1.1 pooka
1115 1.1 pooka if (iwm_nic_lock(sc)) {
1116 1.1 pooka IWM_WRITE(sc, IWM_HBUS_TARG_MEM_RADDR, addr);
1117 1.1 pooka for (offs = 0; offs < dwords; offs++)
1118 1.1 pooka vals[offs] = IWM_READ(sc, IWM_HBUS_TARG_MEM_RDAT);
1119 1.1 pooka iwm_nic_unlock(sc);
1120 1.53 nonaka return 0;
1121 1.1 pooka }
1122 1.53 nonaka return EBUSY;
1123 1.1 pooka }
1124 1.1 pooka
1125 1.4 nonaka static int
1126 1.1 pooka iwm_write_mem(struct iwm_softc *sc, uint32_t addr, const void *buf, int dwords)
1127 1.1 pooka {
1128 1.5 nonaka int offs;
1129 1.1 pooka const uint32_t *vals = buf;
1130 1.1 pooka
1131 1.1 pooka if (iwm_nic_lock(sc)) {
1132 1.1 pooka IWM_WRITE(sc, IWM_HBUS_TARG_MEM_WADDR, addr);
1133 1.1 pooka /* WADDR auto-increments */
1134 1.1 pooka for (offs = 0; offs < dwords; offs++) {
1135 1.1 pooka uint32_t val = vals ? vals[offs] : 0;
1136 1.1 pooka IWM_WRITE(sc, IWM_HBUS_TARG_MEM_WDAT, val);
1137 1.1 pooka }
1138 1.1 pooka iwm_nic_unlock(sc);
1139 1.53 nonaka return 0;
1140 1.1 pooka }
1141 1.53 nonaka return EBUSY;
1142 1.1 pooka }
1143 1.1 pooka
1144 1.4 nonaka static int
1145 1.1 pooka iwm_write_mem32(struct iwm_softc *sc, uint32_t addr, uint32_t val)
1146 1.1 pooka {
1147 1.1 pooka return iwm_write_mem(sc, addr, &val, 1);
1148 1.1 pooka }
1149 1.1 pooka
1150 1.4 nonaka static int
1151 1.45 nonaka iwm_poll_bit(struct iwm_softc *sc, int reg, uint32_t bits, uint32_t mask,
1152 1.45 nonaka int timo)
1153 1.1 pooka {
1154 1.1 pooka for (;;) {
1155 1.1 pooka if ((IWM_READ(sc, reg) & mask) == (bits & mask)) {
1156 1.1 pooka return 1;
1157 1.1 pooka }
1158 1.1 pooka if (timo < 10) {
1159 1.1 pooka return 0;
1160 1.1 pooka }
1161 1.1 pooka timo -= 10;
1162 1.1 pooka DELAY(10);
1163 1.1 pooka }
1164 1.1 pooka }
1165 1.1 pooka
1166 1.4 nonaka static int
1167 1.1 pooka iwm_nic_lock(struct iwm_softc *sc)
1168 1.1 pooka {
1169 1.1 pooka
1170 1.91 mlelstv mutex_enter(&sc->sc_nic_mtx);
1171 1.91 mlelstv if (sc->sc_nic_locks++ > 0) {
1172 1.91 mlelstv mutex_exit(&sc->sc_nic_mtx);
1173 1.59 nonaka return 1;
1174 1.91 mlelstv }
1175 1.59 nonaka
1176 1.1 pooka IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
1177 1.1 pooka IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1178 1.1 pooka
1179 1.91 mlelstv mutex_exit(&sc->sc_nic_mtx);
1180 1.91 mlelstv
1181 1.91 mlelstv if (sc->sc_device_family >= IWM_DEVICE_FAMILY_8000)
1182 1.45 nonaka DELAY(2);
1183 1.45 nonaka
1184 1.1 pooka if (iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
1185 1.1 pooka IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
1186 1.1 pooka IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
1187 1.91 mlelstv | IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP, 150000)) {
1188 1.91 mlelstv return 1;
1189 1.1 pooka }
1190 1.1 pooka
1191 1.91 mlelstv mutex_enter(&sc->sc_nic_mtx);
1192 1.91 mlelstv IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
1193 1.91 mlelstv IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1194 1.91 mlelstv --sc->sc_nic_locks;
1195 1.91 mlelstv mutex_exit(&sc->sc_nic_mtx);
1196 1.91 mlelstv
1197 1.91 mlelstv device_printf(sc->sc_dev, "acquiring device failed\n");
1198 1.91 mlelstv return 0;
1199 1.1 pooka }
1200 1.1 pooka
1201 1.4 nonaka static void
1202 1.1 pooka iwm_nic_unlock(struct iwm_softc *sc)
1203 1.1 pooka {
1204 1.91 mlelstv int err = 1;
1205 1.59 nonaka
1206 1.91 mlelstv mutex_enter(&sc->sc_nic_mtx);
1207 1.91 mlelstv if (sc->sc_nic_locks > 0) {
1208 1.91 mlelstv if (--sc->sc_nic_locks == 0) {
1209 1.91 mlelstv IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
1210 1.91 mlelstv IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1211 1.91 mlelstv }
1212 1.91 mlelstv err = 0;
1213 1.91 mlelstv }
1214 1.91 mlelstv mutex_exit(&sc->sc_nic_mtx);
1215 1.59 nonaka
1216 1.91 mlelstv if (err)
1217 1.91 mlelstv device_printf(sc->sc_dev, "NIC already unlocked\n");
1218 1.1 pooka }
1219 1.1 pooka
1220 1.91 mlelstv static int
1221 1.45 nonaka iwm_set_bits_mask_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits,
1222 1.45 nonaka uint32_t mask)
1223 1.1 pooka {
1224 1.1 pooka uint32_t val;
1225 1.1 pooka
1226 1.1 pooka if (iwm_nic_lock(sc)) {
1227 1.1 pooka val = iwm_read_prph(sc, reg) & mask;
1228 1.1 pooka val |= bits;
1229 1.1 pooka iwm_write_prph(sc, reg, val);
1230 1.1 pooka iwm_nic_unlock(sc);
1231 1.91 mlelstv return 0;
1232 1.1 pooka }
1233 1.91 mlelstv return EBUSY;
1234 1.1 pooka }
1235 1.1 pooka
1236 1.91 mlelstv static int
1237 1.1 pooka iwm_set_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits)
1238 1.1 pooka {
1239 1.91 mlelstv return iwm_set_bits_mask_prph(sc, reg, bits, ~0);
1240 1.1 pooka }
1241 1.1 pooka
1242 1.91 mlelstv static int
1243 1.1 pooka iwm_clear_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits)
1244 1.1 pooka {
1245 1.91 mlelstv return iwm_set_bits_mask_prph(sc, reg, 0, ~bits);
1246 1.1 pooka }
1247 1.1 pooka
1248 1.4 nonaka static int
1249 1.1 pooka iwm_dma_contig_alloc(bus_dma_tag_t tag, struct iwm_dma_info *dma,
1250 1.1 pooka bus_size_t size, bus_size_t alignment)
1251 1.1 pooka {
1252 1.45 nonaka int nsegs, err;
1253 1.1 pooka void *va;
1254 1.1 pooka
1255 1.1 pooka dma->tag = tag;
1256 1.1 pooka dma->size = size;
1257 1.1 pooka
1258 1.45 nonaka err = bus_dmamap_create(tag, size, 1, size, 0, BUS_DMA_NOWAIT,
1259 1.1 pooka &dma->map);
1260 1.45 nonaka if (err)
1261 1.1 pooka goto fail;
1262 1.1 pooka
1263 1.45 nonaka err = bus_dmamem_alloc(tag, size, alignment, 0, &dma->seg, 1, &nsegs,
1264 1.1 pooka BUS_DMA_NOWAIT);
1265 1.45 nonaka if (err)
1266 1.1 pooka goto fail;
1267 1.1 pooka
1268 1.45 nonaka err = bus_dmamem_map(tag, &dma->seg, 1, size, &va, BUS_DMA_NOWAIT);
1269 1.45 nonaka if (err)
1270 1.1 pooka goto fail;
1271 1.1 pooka dma->vaddr = va;
1272 1.1 pooka
1273 1.45 nonaka err = bus_dmamap_load(tag, dma->map, dma->vaddr, size, NULL,
1274 1.1 pooka BUS_DMA_NOWAIT);
1275 1.45 nonaka if (err)
1276 1.1 pooka goto fail;
1277 1.1 pooka
1278 1.1 pooka memset(dma->vaddr, 0, size);
1279 1.1 pooka bus_dmamap_sync(tag, dma->map, 0, size, BUS_DMASYNC_PREWRITE);
1280 1.1 pooka dma->paddr = dma->map->dm_segs[0].ds_addr;
1281 1.1 pooka
1282 1.1 pooka return 0;
1283 1.1 pooka
1284 1.1 pooka fail: iwm_dma_contig_free(dma);
1285 1.45 nonaka return err;
1286 1.1 pooka }
1287 1.1 pooka
1288 1.4 nonaka static void
1289 1.1 pooka iwm_dma_contig_free(struct iwm_dma_info *dma)
1290 1.1 pooka {
1291 1.1 pooka if (dma->map != NULL) {
1292 1.1 pooka if (dma->vaddr != NULL) {
1293 1.1 pooka bus_dmamap_sync(dma->tag, dma->map, 0, dma->size,
1294 1.1 pooka BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1295 1.1 pooka bus_dmamap_unload(dma->tag, dma->map);
1296 1.1 pooka bus_dmamem_unmap(dma->tag, dma->vaddr, dma->size);
1297 1.1 pooka bus_dmamem_free(dma->tag, &dma->seg, 1);
1298 1.1 pooka dma->vaddr = NULL;
1299 1.1 pooka }
1300 1.1 pooka bus_dmamap_destroy(dma->tag, dma->map);
1301 1.1 pooka dma->map = NULL;
1302 1.1 pooka }
1303 1.1 pooka }
1304 1.1 pooka
1305 1.4 nonaka static int
1306 1.1 pooka iwm_alloc_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring)
1307 1.1 pooka {
1308 1.1 pooka bus_size_t size;
1309 1.45 nonaka int i, err;
1310 1.1 pooka
1311 1.1 pooka ring->cur = 0;
1312 1.1 pooka
1313 1.1 pooka /* Allocate RX descriptors (256-byte aligned). */
1314 1.1 pooka size = IWM_RX_RING_COUNT * sizeof(uint32_t);
1315 1.45 nonaka err = iwm_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma, size, 256);
1316 1.45 nonaka if (err) {
1317 1.3 nonaka aprint_error_dev(sc->sc_dev,
1318 1.3 nonaka "could not allocate RX ring DMA memory\n");
1319 1.1 pooka goto fail;
1320 1.1 pooka }
1321 1.1 pooka ring->desc = ring->desc_dma.vaddr;
1322 1.1 pooka
1323 1.1 pooka /* Allocate RX status area (16-byte aligned). */
1324 1.45 nonaka err = iwm_dma_contig_alloc(sc->sc_dmat, &ring->stat_dma,
1325 1.1 pooka sizeof(*ring->stat), 16);
1326 1.45 nonaka if (err) {
1327 1.3 nonaka aprint_error_dev(sc->sc_dev,
1328 1.3 nonaka "could not allocate RX status DMA memory\n");
1329 1.1 pooka goto fail;
1330 1.1 pooka }
1331 1.1 pooka ring->stat = ring->stat_dma.vaddr;
1332 1.1 pooka
1333 1.1 pooka for (i = 0; i < IWM_RX_RING_COUNT; i++) {
1334 1.1 pooka struct iwm_rx_data *data = &ring->data[i];
1335 1.1 pooka
1336 1.1 pooka memset(data, 0, sizeof(*data));
1337 1.45 nonaka err = bus_dmamap_create(sc->sc_dmat, IWM_RBUF_SIZE, 1,
1338 1.1 pooka IWM_RBUF_SIZE, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
1339 1.1 pooka &data->map);
1340 1.45 nonaka if (err) {
1341 1.3 nonaka aprint_error_dev(sc->sc_dev,
1342 1.3 nonaka "could not create RX buf DMA map\n");
1343 1.1 pooka goto fail;
1344 1.1 pooka }
1345 1.1 pooka
1346 1.45 nonaka err = iwm_rx_addbuf(sc, IWM_RBUF_SIZE, i);
1347 1.45 nonaka if (err)
1348 1.1 pooka goto fail;
1349 1.1 pooka }
1350 1.1 pooka return 0;
1351 1.1 pooka
1352 1.1 pooka fail: iwm_free_rx_ring(sc, ring);
1353 1.45 nonaka return err;
1354 1.1 pooka }
1355 1.1 pooka
1356 1.4 nonaka static void
1357 1.45 nonaka iwm_disable_rx_dma(struct iwm_softc *sc)
1358 1.1 pooka {
1359 1.1 pooka int ntries;
1360 1.1 pooka
1361 1.1 pooka if (iwm_nic_lock(sc)) {
1362 1.1 pooka IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
1363 1.1 pooka for (ntries = 0; ntries < 1000; ntries++) {
1364 1.1 pooka if (IWM_READ(sc, IWM_FH_MEM_RSSR_RX_STATUS_REG) &
1365 1.1 pooka IWM_FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE)
1366 1.1 pooka break;
1367 1.1 pooka DELAY(10);
1368 1.1 pooka }
1369 1.1 pooka iwm_nic_unlock(sc);
1370 1.1 pooka }
1371 1.45 nonaka }
1372 1.45 nonaka
1373 1.45 nonaka void
1374 1.45 nonaka iwm_reset_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring)
1375 1.45 nonaka {
1376 1.1 pooka ring->cur = 0;
1377 1.91 mlelstv bus_dmamap_sync(sc->sc_dmat, ring->stat_dma.map, 0,
1378 1.91 mlelstv ring->stat_dma.size, BUS_DMASYNC_PREWRITE);
1379 1.45 nonaka memset(ring->stat, 0, sizeof(*ring->stat));
1380 1.45 nonaka bus_dmamap_sync(sc->sc_dmat, ring->stat_dma.map, 0,
1381 1.91 mlelstv ring->stat_dma.size, BUS_DMASYNC_POSTWRITE);
1382 1.1 pooka }
1383 1.1 pooka
1384 1.4 nonaka static void
1385 1.1 pooka iwm_free_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring)
1386 1.1 pooka {
1387 1.1 pooka int i;
1388 1.1 pooka
1389 1.1 pooka iwm_dma_contig_free(&ring->desc_dma);
1390 1.1 pooka iwm_dma_contig_free(&ring->stat_dma);
1391 1.1 pooka
1392 1.1 pooka for (i = 0; i < IWM_RX_RING_COUNT; i++) {
1393 1.1 pooka struct iwm_rx_data *data = &ring->data[i];
1394 1.1 pooka
1395 1.1 pooka if (data->m != NULL) {
1396 1.89 mlelstv bus_size_t sz = data->m->m_pkthdr.len;
1397 1.1 pooka bus_dmamap_sync(sc->sc_dmat, data->map, 0,
1398 1.89 mlelstv sz, BUS_DMASYNC_POSTREAD);
1399 1.1 pooka bus_dmamap_unload(sc->sc_dmat, data->map);
1400 1.1 pooka m_freem(data->m);
1401 1.45 nonaka data->m = NULL;
1402 1.1 pooka }
1403 1.45 nonaka if (data->map != NULL) {
1404 1.1 pooka bus_dmamap_destroy(sc->sc_dmat, data->map);
1405 1.45 nonaka data->map = NULL;
1406 1.45 nonaka }
1407 1.1 pooka }
1408 1.1 pooka }
1409 1.1 pooka
1410 1.4 nonaka static int
1411 1.1 pooka iwm_alloc_tx_ring(struct iwm_softc *sc, struct iwm_tx_ring *ring, int qid)
1412 1.1 pooka {
1413 1.1 pooka bus_addr_t paddr;
1414 1.1 pooka bus_size_t size;
1415 1.61 nonaka int i, err, nsegs;
1416 1.1 pooka
1417 1.1 pooka ring->qid = qid;
1418 1.1 pooka ring->queued = 0;
1419 1.1 pooka ring->cur = 0;
1420 1.1 pooka
1421 1.1 pooka /* Allocate TX descriptors (256-byte aligned). */
1422 1.1 pooka size = IWM_TX_RING_COUNT * sizeof (struct iwm_tfd);
1423 1.45 nonaka err = iwm_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma, size, 256);
1424 1.45 nonaka if (err) {
1425 1.3 nonaka aprint_error_dev(sc->sc_dev,
1426 1.3 nonaka "could not allocate TX ring DMA memory\n");
1427 1.1 pooka goto fail;
1428 1.1 pooka }
1429 1.1 pooka ring->desc = ring->desc_dma.vaddr;
1430 1.1 pooka
1431 1.1 pooka /*
1432 1.91 mlelstv * There is no need to allocate DMA buffers for unused rings.
1433 1.91 mlelstv * 7k/8k/9k hardware supports up to 31 Tx rings which is more
1434 1.91 mlelstv * than we currently need.
1435 1.91 mlelstv *
1436 1.91 mlelstv * In DQA mode we use 1 command queue + 4 DQA mgmt/data queues.
1437 1.91 mlelstv * The command is queue 0 (sc->txq[0]), and 4 mgmt/data frame queues
1438 1.91 mlelstv * are sc->tqx[IWM_DQA_MIN_MGMT_QUEUE + ac], i.e. sc->txq[5:8],
1439 1.91 mlelstv * in order to provide one queue per EDCA category.
1440 1.91 mlelstv * Tx aggregation requires additional queues, one queue per TID for
1441 1.91 mlelstv * which aggregation is enabled. We map TID 0-7 to sc->txq[10:17].
1442 1.91 mlelstv *
1443 1.91 mlelstv * In non-DQA mode, we use rings 0 through 9 (0-3 are EDCA, 9 is cmd),
1444 1.91 mlelstv * and Tx aggregation is not supported.
1445 1.91 mlelstv *
1446 1.91 mlelstv * Unfortunately, we cannot tell if DQA will be used until the
1447 1.91 mlelstv * firmware gets loaded later, so just allocate sufficient rings
1448 1.91 mlelstv * in order to satisfy both cases.
1449 1.1 pooka */
1450 1.91 mlelstv if (qid > IWM_LAST_AGG_TX_QUEUE)
1451 1.1 pooka return 0;
1452 1.1 pooka
1453 1.1 pooka size = IWM_TX_RING_COUNT * sizeof(struct iwm_device_cmd);
1454 1.45 nonaka err = iwm_dma_contig_alloc(sc->sc_dmat, &ring->cmd_dma, size, 4);
1455 1.45 nonaka if (err) {
1456 1.3 nonaka aprint_error_dev(sc->sc_dev,
1457 1.3 nonaka "could not allocate TX cmd DMA memory\n");
1458 1.1 pooka goto fail;
1459 1.1 pooka }
1460 1.1 pooka ring->cmd = ring->cmd_dma.vaddr;
1461 1.1 pooka
1462 1.1 pooka paddr = ring->cmd_dma.paddr;
1463 1.1 pooka for (i = 0; i < IWM_TX_RING_COUNT; i++) {
1464 1.1 pooka struct iwm_tx_data *data = &ring->data[i];
1465 1.45 nonaka size_t mapsize;
1466 1.1 pooka
1467 1.1 pooka data->cmd_paddr = paddr;
1468 1.1 pooka data->scratch_paddr = paddr + sizeof(struct iwm_cmd_header)
1469 1.1 pooka + offsetof(struct iwm_tx_cmd, scratch);
1470 1.1 pooka paddr += sizeof(struct iwm_device_cmd);
1471 1.1 pooka
1472 1.45 nonaka /* FW commands may require more mapped space than packets. */
1473 1.91 mlelstv if (qid == IWM_CMD_QUEUE || qid == IWM_DQA_CMD_QUEUE) {
1474 1.61 nonaka mapsize = IWM_RBUF_SIZE;
1475 1.61 nonaka nsegs = 1;
1476 1.61 nonaka } else {
1477 1.45 nonaka mapsize = MCLBYTES;
1478 1.61 nonaka nsegs = IWM_NUM_OF_TBS - 2;
1479 1.61 nonaka }
1480 1.91 mlelstv err = bus_dmamap_create(sc->sc_dmat, mapsize,
1481 1.91 mlelstv nsegs, mapsize, 0, BUS_DMA_NOWAIT,
1482 1.91 mlelstv &data->map);
1483 1.45 nonaka if (err) {
1484 1.3 nonaka aprint_error_dev(sc->sc_dev,
1485 1.3 nonaka "could not create TX buf DMA map\n");
1486 1.1 pooka goto fail;
1487 1.1 pooka }
1488 1.1 pooka }
1489 1.1 pooka KASSERT(paddr == ring->cmd_dma.paddr + size);
1490 1.1 pooka return 0;
1491 1.1 pooka
1492 1.1 pooka fail: iwm_free_tx_ring(sc, ring);
1493 1.45 nonaka return err;
1494 1.1 pooka }
1495 1.1 pooka
1496 1.4 nonaka static void
1497 1.1 pooka iwm_reset_tx_ring(struct iwm_softc *sc, struct iwm_tx_ring *ring)
1498 1.1 pooka {
1499 1.1 pooka int i;
1500 1.1 pooka
1501 1.1 pooka for (i = 0; i < IWM_TX_RING_COUNT; i++) {
1502 1.1 pooka struct iwm_tx_data *data = &ring->data[i];
1503 1.1 pooka
1504 1.1 pooka if (data->m != NULL) {
1505 1.1 pooka bus_dmamap_sync(sc->sc_dmat, data->map, 0,
1506 1.91 mlelstv data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1507 1.1 pooka bus_dmamap_unload(sc->sc_dmat, data->map);
1508 1.1 pooka m_freem(data->m);
1509 1.1 pooka data->m = NULL;
1510 1.1 pooka }
1511 1.1 pooka }
1512 1.1 pooka /* Clear TX descriptors. */
1513 1.1 pooka memset(ring->desc, 0, ring->desc_dma.size);
1514 1.1 pooka bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0,
1515 1.1 pooka ring->desc_dma.size, BUS_DMASYNC_PREWRITE);
1516 1.1 pooka sc->qfullmsk &= ~(1 << ring->qid);
1517 1.91 mlelstv
1518 1.91 mlelstv /* 7000 family NICs are locked while commands are in progress. */
1519 1.91 mlelstv if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
1520 1.91 mlelstv if (ring->qid == sc->cmdqid && ring->queued > 0) {
1521 1.91 mlelstv iwm_nic_unlock(sc);
1522 1.91 mlelstv }
1523 1.91 mlelstv }
1524 1.1 pooka ring->queued = 0;
1525 1.1 pooka ring->cur = 0;
1526 1.1 pooka }
1527 1.1 pooka
1528 1.4 nonaka static void
1529 1.1 pooka iwm_free_tx_ring(struct iwm_softc *sc, struct iwm_tx_ring *ring)
1530 1.1 pooka {
1531 1.1 pooka int i;
1532 1.1 pooka
1533 1.1 pooka iwm_dma_contig_free(&ring->desc_dma);
1534 1.1 pooka iwm_dma_contig_free(&ring->cmd_dma);
1535 1.1 pooka
1536 1.1 pooka for (i = 0; i < IWM_TX_RING_COUNT; i++) {
1537 1.1 pooka struct iwm_tx_data *data = &ring->data[i];
1538 1.1 pooka
1539 1.1 pooka if (data->m != NULL) {
1540 1.1 pooka bus_dmamap_sync(sc->sc_dmat, data->map, 0,
1541 1.91 mlelstv data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1542 1.1 pooka bus_dmamap_unload(sc->sc_dmat, data->map);
1543 1.1 pooka m_freem(data->m);
1544 1.57 nonaka data->m = NULL;
1545 1.1 pooka }
1546 1.45 nonaka if (data->map != NULL) {
1547 1.1 pooka bus_dmamap_destroy(sc->sc_dmat, data->map);
1548 1.45 nonaka data->map = NULL;
1549 1.45 nonaka }
1550 1.1 pooka }
1551 1.1 pooka }
1552 1.1 pooka
1553 1.4 nonaka static void
1554 1.1 pooka iwm_enable_rfkill_int(struct iwm_softc *sc)
1555 1.1 pooka {
1556 1.1 pooka sc->sc_intmask = IWM_CSR_INT_BIT_RF_KILL;
1557 1.1 pooka IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);
1558 1.1 pooka }
1559 1.1 pooka
1560 1.4 nonaka static int
1561 1.1 pooka iwm_check_rfkill(struct iwm_softc *sc)
1562 1.1 pooka {
1563 1.1 pooka uint32_t v;
1564 1.1 pooka int rv;
1565 1.8 nonaka
1566 1.1 pooka /*
1567 1.1 pooka * "documentation" is not really helpful here:
1568 1.1 pooka * 27: HW_RF_KILL_SW
1569 1.1 pooka * Indicates state of (platform's) hardware RF-Kill switch
1570 1.1 pooka *
1571 1.1 pooka * But apparently when it's off, it's on ...
1572 1.1 pooka */
1573 1.1 pooka v = IWM_READ(sc, IWM_CSR_GP_CNTRL);
1574 1.1 pooka rv = (v & IWM_CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) == 0;
1575 1.1 pooka if (rv) {
1576 1.1 pooka sc->sc_flags |= IWM_FLAG_RFKILL;
1577 1.1 pooka } else {
1578 1.1 pooka sc->sc_flags &= ~IWM_FLAG_RFKILL;
1579 1.1 pooka }
1580 1.1 pooka
1581 1.1 pooka return rv;
1582 1.1 pooka }
1583 1.1 pooka
1584 1.4 nonaka static void
1585 1.1 pooka iwm_enable_interrupts(struct iwm_softc *sc)
1586 1.1 pooka {
1587 1.1 pooka sc->sc_intmask = IWM_CSR_INI_SET_MASK;
1588 1.1 pooka IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);
1589 1.1 pooka }
1590 1.1 pooka
1591 1.4 nonaka static void
1592 1.91 mlelstv iwm_enable_fwload_interrupt(struct iwm_softc *sc)
1593 1.91 mlelstv {
1594 1.91 mlelstv
1595 1.91 mlelstv sc->sc_intmask = IWM_CSR_INT_BIT_FH_TX;
1596 1.91 mlelstv IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);
1597 1.91 mlelstv }
1598 1.91 mlelstv
1599 1.91 mlelstv static void
1600 1.1 pooka iwm_restore_interrupts(struct iwm_softc *sc)
1601 1.1 pooka {
1602 1.1 pooka IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);
1603 1.1 pooka }
1604 1.1 pooka
1605 1.4 nonaka static void
1606 1.1 pooka iwm_disable_interrupts(struct iwm_softc *sc)
1607 1.1 pooka {
1608 1.1 pooka IWM_WRITE(sc, IWM_CSR_INT_MASK, 0);
1609 1.1 pooka
1610 1.1 pooka /* acknowledge all interrupts */
1611 1.1 pooka IWM_WRITE(sc, IWM_CSR_INT, ~0);
1612 1.1 pooka IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, ~0);
1613 1.1 pooka }
1614 1.1 pooka
1615 1.4 nonaka static void
1616 1.1 pooka iwm_ict_reset(struct iwm_softc *sc)
1617 1.1 pooka {
1618 1.1 pooka iwm_disable_interrupts(sc);
1619 1.1 pooka
1620 1.1 pooka memset(sc->ict_dma.vaddr, 0, IWM_ICT_SIZE);
1621 1.89 mlelstv bus_dmamap_sync(sc->sc_dmat, sc->ict_dma.map, 0, sc->ict_dma.size,
1622 1.45 nonaka BUS_DMASYNC_PREWRITE);
1623 1.1 pooka sc->ict_cur = 0;
1624 1.1 pooka
1625 1.45 nonaka /* Set physical address of ICT (4KB aligned). */
1626 1.1 pooka IWM_WRITE(sc, IWM_CSR_DRAM_INT_TBL_REG,
1627 1.1 pooka IWM_CSR_DRAM_INT_TBL_ENABLE
1628 1.1 pooka | IWM_CSR_DRAM_INIT_TBL_WRAP_CHECK
1629 1.45 nonaka | IWM_CSR_DRAM_INIT_TBL_WRITE_POINTER
1630 1.1 pooka | sc->ict_dma.paddr >> IWM_ICT_PADDR_SHIFT);
1631 1.1 pooka
1632 1.1 pooka /* Switch to ICT interrupt mode in driver. */
1633 1.1 pooka sc->sc_flags |= IWM_FLAG_USE_ICT;
1634 1.1 pooka
1635 1.1 pooka IWM_WRITE(sc, IWM_CSR_INT, ~0);
1636 1.1 pooka iwm_enable_interrupts(sc);
1637 1.1 pooka }
1638 1.1 pooka
1639 1.1 pooka #define IWM_HW_READY_TIMEOUT 50
1640 1.4 nonaka static int
1641 1.1 pooka iwm_set_hw_ready(struct iwm_softc *sc)
1642 1.1 pooka {
1643 1.45 nonaka int ready;
1644 1.45 nonaka
1645 1.1 pooka IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
1646 1.1 pooka IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
1647 1.1 pooka
1648 1.45 nonaka ready = iwm_poll_bit(sc, IWM_CSR_HW_IF_CONFIG_REG,
1649 1.1 pooka IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
1650 1.1 pooka IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
1651 1.1 pooka IWM_HW_READY_TIMEOUT);
1652 1.45 nonaka if (ready)
1653 1.45 nonaka IWM_SETBITS(sc, IWM_CSR_MBOX_SET_REG,
1654 1.45 nonaka IWM_CSR_MBOX_SET_REG_OS_ALIVE);
1655 1.45 nonaka
1656 1.45 nonaka return ready;
1657 1.1 pooka }
1658 1.1 pooka #undef IWM_HW_READY_TIMEOUT
1659 1.1 pooka
1660 1.4 nonaka static int
1661 1.1 pooka iwm_prepare_card_hw(struct iwm_softc *sc)
1662 1.1 pooka {
1663 1.1 pooka int t = 0;
1664 1.91 mlelstv int ntries;
1665 1.1 pooka
1666 1.10 nonaka if (iwm_set_hw_ready(sc))
1667 1.45 nonaka return 0;
1668 1.45 nonaka
1669 1.91 mlelstv IWM_SETBITS(sc, IWM_CSR_DBG_LINK_PWR_MGMT_REG,
1670 1.91 mlelstv IWM_CSR_RESET_LINK_PWR_MGMT_DISABLED);
1671 1.91 mlelstv DELAY(1000);
1672 1.91 mlelstv
1673 1.91 mlelstv for (ntries = 0; ntries < 10; ntries++) {
1674 1.91 mlelstv /* If HW is not ready, prepare the conditions to check again */
1675 1.91 mlelstv IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
1676 1.91 mlelstv IWM_CSR_HW_IF_CONFIG_REG_PREPARE);
1677 1.91 mlelstv
1678 1.91 mlelstv do {
1679 1.91 mlelstv if (iwm_set_hw_ready(sc))
1680 1.91 mlelstv return 0;
1681 1.91 mlelstv DELAY(200);
1682 1.91 mlelstv t += 200;
1683 1.91 mlelstv } while (t < 150000);
1684 1.91 mlelstv DELAY(25000);
1685 1.91 mlelstv }
1686 1.1 pooka
1687 1.45 nonaka return ETIMEDOUT;
1688 1.1 pooka }
1689 1.1 pooka
1690 1.4 nonaka static void
1691 1.1 pooka iwm_apm_config(struct iwm_softc *sc)
1692 1.1 pooka {
1693 1.1 pooka pcireg_t reg;
1694 1.1 pooka
1695 1.1 pooka reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
1696 1.1 pooka sc->sc_cap_off + PCIE_LCSR);
1697 1.1 pooka if (reg & PCIE_LCSR_ASPM_L1) {
1698 1.1 pooka /* Um the Linux driver prints "Disabling L0S for this one ... */
1699 1.1 pooka IWM_SETBITS(sc, IWM_CSR_GIO_REG,
1700 1.1 pooka IWM_CSR_GIO_REG_VAL_L0S_ENABLED);
1701 1.1 pooka } else {
1702 1.1 pooka /* ... and "Enabling" here */
1703 1.1 pooka IWM_CLRBITS(sc, IWM_CSR_GIO_REG,
1704 1.1 pooka IWM_CSR_GIO_REG_VAL_L0S_ENABLED);
1705 1.1 pooka }
1706 1.91 mlelstv
1707 1.91 mlelstv #ifdef notyet
1708 1.91 mlelstv reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
1709 1.91 mlelstv sc->sc_cap_off + PCIE_DCSR2);
1710 1.91 mlelstv sc->sc_ltr_enabled = (reg & PCIE_DCSR2_LTR_MEC) ? 1 : 0;
1711 1.91 mlelstv DPRINTF(("%s: L1 %sabled - LTR %sabled\n",
1712 1.91 mlelstv DEVNAME(sc),
1713 1.91 mlelstv (lctl & PCI_PCIE_LCSR_ASPM_L1) ? "En" : "Dis",
1714 1.91 mlelstv sc->sc_ltr_enabled ? "En" : "Dis"));
1715 1.91 mlelstv #endif
1716 1.1 pooka }
1717 1.1 pooka
1718 1.1 pooka /*
1719 1.1 pooka * Start up NIC's basic functionality after it has been reset
1720 1.45 nonaka * e.g. after platform boot or shutdown.
1721 1.1 pooka * NOTE: This does not load uCode nor start the embedded processor
1722 1.1 pooka */
1723 1.4 nonaka static int
1724 1.1 pooka iwm_apm_init(struct iwm_softc *sc)
1725 1.1 pooka {
1726 1.45 nonaka int err = 0;
1727 1.1 pooka
1728 1.45 nonaka /* Disable L0S exit timer (platform NMI workaround) */
1729 1.91 mlelstv if (sc->sc_device_family < IWM_DEVICE_FAMILY_8000) {
1730 1.45 nonaka IWM_SETBITS(sc, IWM_CSR_GIO_CHICKEN_BITS,
1731 1.45 nonaka IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
1732 1.61 nonaka }
1733 1.1 pooka
1734 1.1 pooka /*
1735 1.1 pooka * Disable L0s without affecting L1;
1736 1.1 pooka * don't wait for ICH L0s (ICH bug W/A)
1737 1.1 pooka */
1738 1.1 pooka IWM_SETBITS(sc, IWM_CSR_GIO_CHICKEN_BITS,
1739 1.1 pooka IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
1740 1.1 pooka
1741 1.1 pooka /* Set FH wait threshold to maximum (HW error during stress W/A) */
1742 1.1 pooka IWM_SETBITS(sc, IWM_CSR_DBG_HPET_MEM_REG, IWM_CSR_DBG_HPET_MEM_REG_VAL);
1743 1.1 pooka
1744 1.1 pooka /*
1745 1.1 pooka * Enable HAP INTA (interrupt from management bus) to
1746 1.1 pooka * wake device's PCI Express link L1a -> L0s
1747 1.1 pooka */
1748 1.1 pooka IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
1749 1.1 pooka IWM_CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
1750 1.1 pooka
1751 1.1 pooka iwm_apm_config(sc);
1752 1.1 pooka
1753 1.45 nonaka #if 0 /* not for 7k/8k */
1754 1.1 pooka /* Configure analog phase-lock-loop before activating to D0A */
1755 1.1 pooka if (trans->cfg->base_params->pll_cfg_val)
1756 1.1 pooka IWM_SETBITS(trans, IWM_CSR_ANA_PLL_CFG,
1757 1.1 pooka trans->cfg->base_params->pll_cfg_val);
1758 1.1 pooka #endif
1759 1.1 pooka
1760 1.1 pooka /*
1761 1.1 pooka * Set "initialization complete" bit to move adapter from
1762 1.1 pooka * D0U* --> D0A* (powered-up active) state.
1763 1.1 pooka */
1764 1.1 pooka IWM_SETBITS(sc, IWM_CSR_GP_CNTRL, IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
1765 1.1 pooka
1766 1.1 pooka /*
1767 1.1 pooka * Wait for clock stabilization; once stabilized, access to
1768 1.1 pooka * device-internal resources is supported, e.g. iwm_write_prph()
1769 1.1 pooka * and accesses to uCode SRAM.
1770 1.1 pooka */
1771 1.1 pooka if (!iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
1772 1.1 pooka IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
1773 1.1 pooka IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000)) {
1774 1.3 nonaka aprint_error_dev(sc->sc_dev,
1775 1.3 nonaka "timeout waiting for clock stabilization\n");
1776 1.45 nonaka err = ETIMEDOUT;
1777 1.1 pooka goto out;
1778 1.1 pooka }
1779 1.1 pooka
1780 1.17 nonaka if (sc->host_interrupt_operation_mode) {
1781 1.17 nonaka /*
1782 1.17 nonaka * This is a bit of an abuse - This is needed for 7260 / 3160
1783 1.17 nonaka * only check host_interrupt_operation_mode even if this is
1784 1.17 nonaka * not related to host_interrupt_operation_mode.
1785 1.17 nonaka *
1786 1.17 nonaka * Enable the oscillator to count wake up time for L1 exit. This
1787 1.17 nonaka * consumes slightly more power (100uA) - but allows to be sure
1788 1.17 nonaka * that we wake up from L1 on time.
1789 1.17 nonaka *
1790 1.17 nonaka * This looks weird: read twice the same register, discard the
1791 1.17 nonaka * value, set a bit, and yet again, read that same register
1792 1.17 nonaka * just to discard the value. But that's the way the hardware
1793 1.17 nonaka * seems to like it.
1794 1.17 nonaka */
1795 1.91 mlelstv if (iwm_nic_lock(sc)) {
1796 1.91 mlelstv iwm_read_prph(sc, IWM_OSC_CLK);
1797 1.91 mlelstv iwm_read_prph(sc, IWM_OSC_CLK);
1798 1.91 mlelstv iwm_nic_unlock(sc);
1799 1.91 mlelstv }
1800 1.91 mlelstv err = iwm_set_bits_prph(sc, IWM_OSC_CLK,
1801 1.91 mlelstv IWM_OSC_CLK_FORCE_CONTROL);
1802 1.91 mlelstv if (err)
1803 1.91 mlelstv goto out;
1804 1.91 mlelstv if (iwm_nic_lock(sc)) {
1805 1.91 mlelstv iwm_read_prph(sc, IWM_OSC_CLK);
1806 1.91 mlelstv iwm_read_prph(sc, IWM_OSC_CLK);
1807 1.91 mlelstv iwm_nic_unlock(sc);
1808 1.91 mlelstv }
1809 1.17 nonaka }
1810 1.1 pooka
1811 1.1 pooka /*
1812 1.1 pooka * Enable DMA clock and wait for it to stabilize.
1813 1.1 pooka *
1814 1.1 pooka * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits
1815 1.1 pooka * do not disable clocks. This preserves any hardware bits already
1816 1.1 pooka * set by default in "CLK_CTRL_REG" after reset.
1817 1.1 pooka */
1818 1.45 nonaka if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
1819 1.91 mlelstv if (iwm_nic_lock(sc)) {
1820 1.91 mlelstv iwm_write_prph(sc, IWM_APMG_CLK_EN_REG,
1821 1.91 mlelstv IWM_APMG_CLK_VAL_DMA_CLK_RQT);
1822 1.91 mlelstv iwm_nic_unlock(sc);
1823 1.91 mlelstv }
1824 1.45 nonaka DELAY(20);
1825 1.45 nonaka
1826 1.45 nonaka /* Disable L1-Active */
1827 1.91 mlelstv err = iwm_set_bits_prph(sc, IWM_APMG_PCIDEV_STT_REG,
1828 1.45 nonaka IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
1829 1.91 mlelstv if (err)
1830 1.91 mlelstv goto out;
1831 1.45 nonaka
1832 1.45 nonaka /* Clear the interrupt in APMG if the NIC is in RFKILL */
1833 1.91 mlelstv if (iwm_nic_lock(sc)) {
1834 1.91 mlelstv iwm_write_prph(sc, IWM_APMG_RTC_INT_STT_REG,
1835 1.91 mlelstv IWM_APMG_RTC_INT_STT_RFKILL);
1836 1.91 mlelstv iwm_nic_unlock(sc);
1837 1.91 mlelstv }
1838 1.45 nonaka }
1839 1.1 pooka out:
1840 1.45 nonaka if (err)
1841 1.45 nonaka aprint_error_dev(sc->sc_dev, "apm init error %d\n", err);
1842 1.45 nonaka return err;
1843 1.1 pooka }
1844 1.1 pooka
1845 1.4 nonaka static void
1846 1.1 pooka iwm_apm_stop(struct iwm_softc *sc)
1847 1.1 pooka {
1848 1.91 mlelstv IWM_SETBITS(sc, IWM_CSR_DBG_LINK_PWR_MGMT_REG,
1849 1.91 mlelstv IWM_CSR_RESET_LINK_PWR_MGMT_DISABLED);
1850 1.91 mlelstv IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
1851 1.91 mlelstv IWM_CSR_HW_IF_CONFIG_REG_PREPARE |
1852 1.91 mlelstv IWM_CSR_HW_IF_CONFIG_REG_ENABLE_PME);
1853 1.91 mlelstv DELAY(1000);
1854 1.91 mlelstv IWM_CLRBITS(sc, IWM_CSR_DBG_LINK_PWR_MGMT_REG,
1855 1.91 mlelstv IWM_CSR_RESET_LINK_PWR_MGMT_DISABLED);
1856 1.91 mlelstv DELAY(5000);
1857 1.91 mlelstv
1858 1.1 pooka /* stop device's busmaster DMA activity */
1859 1.1 pooka IWM_SETBITS(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_STOP_MASTER);
1860 1.1 pooka
1861 1.1 pooka if (!iwm_poll_bit(sc, IWM_CSR_RESET,
1862 1.1 pooka IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED,
1863 1.1 pooka IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED, 100))
1864 1.3 nonaka aprint_error_dev(sc->sc_dev, "timeout waiting for master\n");
1865 1.3 nonaka DPRINTF(("iwm apm stop\n"));
1866 1.91 mlelstv
1867 1.91 mlelstv /*
1868 1.91 mlelstv * Clear "initialization complete" bit to move adapter from
1869 1.91 mlelstv * D0A* (powered-up Active) --> D0U* (Uninitialized) state.
1870 1.91 mlelstv */
1871 1.91 mlelstv IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
1872 1.91 mlelstv IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
1873 1.1 pooka }
1874 1.1 pooka
1875 1.4 nonaka static int
1876 1.1 pooka iwm_start_hw(struct iwm_softc *sc)
1877 1.1 pooka {
1878 1.45 nonaka int err;
1879 1.1 pooka
1880 1.45 nonaka err = iwm_prepare_card_hw(sc);
1881 1.45 nonaka if (err)
1882 1.45 nonaka return err;
1883 1.1 pooka
1884 1.8 nonaka /* Reset the entire device */
1885 1.45 nonaka IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_SW_RESET);
1886 1.91 mlelstv DELAY(5000);
1887 1.1 pooka
1888 1.45 nonaka err = iwm_apm_init(sc);
1889 1.45 nonaka if (err)
1890 1.45 nonaka return err;
1891 1.1 pooka
1892 1.1 pooka iwm_enable_rfkill_int(sc);
1893 1.1 pooka iwm_check_rfkill(sc);
1894 1.1 pooka
1895 1.1 pooka return 0;
1896 1.1 pooka }
1897 1.1 pooka
1898 1.4 nonaka static void
1899 1.1 pooka iwm_stop_device(struct iwm_softc *sc)
1900 1.1 pooka {
1901 1.1 pooka int chnl, ntries;
1902 1.1 pooka int qid;
1903 1.1 pooka
1904 1.1 pooka iwm_disable_interrupts(sc);
1905 1.1 pooka sc->sc_flags &= ~IWM_FLAG_USE_ICT;
1906 1.1 pooka
1907 1.1 pooka /* Stop all DMA channels. */
1908 1.1 pooka if (iwm_nic_lock(sc)) {
1909 1.91 mlelstv /* Deactivate TX scheduler. */
1910 1.91 mlelstv iwm_write_prph(sc, IWM_SCD_TXFACT, 0);
1911 1.91 mlelstv
1912 1.1 pooka for (chnl = 0; chnl < IWM_FH_TCSR_CHNL_NUM; chnl++) {
1913 1.1 pooka IWM_WRITE(sc,
1914 1.1 pooka IWM_FH_TCSR_CHNL_TX_CONFIG_REG(chnl), 0);
1915 1.1 pooka for (ntries = 0; ntries < 200; ntries++) {
1916 1.1 pooka uint32_t r;
1917 1.1 pooka
1918 1.1 pooka r = IWM_READ(sc, IWM_FH_TSSR_TX_STATUS_REG);
1919 1.1 pooka if (r & IWM_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(
1920 1.1 pooka chnl))
1921 1.1 pooka break;
1922 1.1 pooka DELAY(20);
1923 1.1 pooka }
1924 1.1 pooka }
1925 1.1 pooka iwm_nic_unlock(sc);
1926 1.1 pooka }
1927 1.45 nonaka iwm_disable_rx_dma(sc);
1928 1.1 pooka iwm_reset_rx_ring(sc, &sc->rxq);
1929 1.1 pooka
1930 1.1 pooka for (qid = 0; qid < __arraycount(sc->txq); qid++)
1931 1.1 pooka iwm_reset_tx_ring(sc, &sc->txq[qid]);
1932 1.1 pooka
1933 1.61 nonaka if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
1934 1.61 nonaka /* Power-down device's busmaster DMA clocks */
1935 1.61 nonaka if (iwm_nic_lock(sc)) {
1936 1.61 nonaka iwm_write_prph(sc, IWM_APMG_CLK_DIS_REG,
1937 1.61 nonaka IWM_APMG_CLK_VAL_DMA_CLK_RQT);
1938 1.61 nonaka iwm_nic_unlock(sc);
1939 1.61 nonaka }
1940 1.91 mlelstv DELAY(5);
1941 1.61 nonaka }
1942 1.1 pooka
1943 1.1 pooka /* Make sure (redundant) we've released our request to stay awake */
1944 1.1 pooka IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
1945 1.1 pooka IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1946 1.91 mlelstv if (sc->sc_nic_locks > 0)
1947 1.91 mlelstv device_printf(sc->sc_dev, "%d active NIC locks cleared\n",
1948 1.91 mlelstv sc->sc_nic_locks);
1949 1.91 mlelstv sc->sc_nic_locks = 0;
1950 1.1 pooka
1951 1.1 pooka /* Stop the device, and put it in low power state */
1952 1.1 pooka iwm_apm_stop(sc);
1953 1.1 pooka
1954 1.91 mlelstv /* Reset the on-board processor. */
1955 1.91 mlelstv IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_SW_RESET);
1956 1.91 mlelstv DELAY(5000);
1957 1.91 mlelstv
1958 1.45 nonaka /*
1959 1.45 nonaka * Upon stop, the APM issues an interrupt if HW RF kill is set.
1960 1.8 nonaka * Clean again the interrupt here
1961 1.8 nonaka */
1962 1.1 pooka iwm_disable_interrupts(sc);
1963 1.1 pooka
1964 1.45 nonaka /* Even though we stop the HW we still want the RF kill interrupt. */
1965 1.1 pooka iwm_enable_rfkill_int(sc);
1966 1.1 pooka iwm_check_rfkill(sc);
1967 1.91 mlelstv
1968 1.91 mlelstv iwm_prepare_card_hw(sc);
1969 1.1 pooka }
1970 1.1 pooka
1971 1.4 nonaka static void
1972 1.45 nonaka iwm_nic_config(struct iwm_softc *sc)
1973 1.1 pooka {
1974 1.1 pooka uint8_t radio_cfg_type, radio_cfg_step, radio_cfg_dash;
1975 1.91 mlelstv uint32_t mask, val, reg_val = 0;
1976 1.1 pooka
1977 1.1 pooka radio_cfg_type = (sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RADIO_TYPE) >>
1978 1.1 pooka IWM_FW_PHY_CFG_RADIO_TYPE_POS;
1979 1.1 pooka radio_cfg_step = (sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RADIO_STEP) >>
1980 1.1 pooka IWM_FW_PHY_CFG_RADIO_STEP_POS;
1981 1.1 pooka radio_cfg_dash = (sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RADIO_DASH) >>
1982 1.1 pooka IWM_FW_PHY_CFG_RADIO_DASH_POS;
1983 1.1 pooka
1984 1.1 pooka reg_val |= IWM_CSR_HW_REV_STEP(sc->sc_hw_rev) <<
1985 1.1 pooka IWM_CSR_HW_IF_CONFIG_REG_POS_MAC_STEP;
1986 1.1 pooka reg_val |= IWM_CSR_HW_REV_DASH(sc->sc_hw_rev) <<
1987 1.1 pooka IWM_CSR_HW_IF_CONFIG_REG_POS_MAC_DASH;
1988 1.1 pooka
1989 1.1 pooka /* radio configuration */
1990 1.1 pooka reg_val |= radio_cfg_type << IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE;
1991 1.1 pooka reg_val |= radio_cfg_step << IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_STEP;
1992 1.1 pooka reg_val |= radio_cfg_dash << IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_DASH;
1993 1.1 pooka
1994 1.91 mlelstv mask = IWM_CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
1995 1.91 mlelstv IWM_CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP |
1996 1.91 mlelstv IWM_CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP |
1997 1.91 mlelstv IWM_CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH |
1998 1.91 mlelstv IWM_CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE |
1999 1.91 mlelstv IWM_CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
2000 1.91 mlelstv IWM_CSR_HW_IF_CONFIG_REG_BIT_MAC_SI;
2001 1.91 mlelstv
2002 1.91 mlelstv val = IWM_READ(sc, IWM_CSR_HW_IF_CONFIG_REG);
2003 1.91 mlelstv val &= ~mask;
2004 1.91 mlelstv val |= reg_val;
2005 1.91 mlelstv IWM_WRITE(sc, IWM_CSR_HW_IF_CONFIG_REG, val);
2006 1.1 pooka
2007 1.8 nonaka DPRINTF(("Radio type=0x%x-0x%x-0x%x\n", radio_cfg_type,
2008 1.8 nonaka radio_cfg_step, radio_cfg_dash));
2009 1.1 pooka
2010 1.1 pooka /*
2011 1.1 pooka * W/A : NIC is stuck in a reset state after Early PCIe power off
2012 1.1 pooka * (PCIe power is lost before PERST# is asserted), causing ME FW
2013 1.1 pooka * to lose ownership and not being able to obtain it back.
2014 1.1 pooka */
2015 1.61 nonaka if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
2016 1.45 nonaka iwm_set_bits_mask_prph(sc, IWM_APMG_PS_CTRL_REG,
2017 1.45 nonaka IWM_APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
2018 1.45 nonaka ~IWM_APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
2019 1.61 nonaka }
2020 1.1 pooka }
2021 1.1 pooka
2022 1.4 nonaka static int
2023 1.1 pooka iwm_nic_rx_init(struct iwm_softc *sc)
2024 1.1 pooka {
2025 1.91 mlelstv return iwm_nic_rx_legacy_init(sc);
2026 1.91 mlelstv }
2027 1.1 pooka
2028 1.91 mlelstv static int
2029 1.91 mlelstv iwm_nic_rx_legacy_init(struct iwm_softc *sc)
2030 1.91 mlelstv {
2031 1.1 pooka memset(sc->rxq.stat, 0, sizeof(*sc->rxq.stat));
2032 1.45 nonaka bus_dmamap_sync(sc->sc_dmat, sc->rxq.stat_dma.map,
2033 1.45 nonaka 0, sc->rxq.stat_dma.size,
2034 1.45 nonaka BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2035 1.1 pooka
2036 1.45 nonaka iwm_disable_rx_dma(sc);
2037 1.91 mlelstv
2038 1.91 mlelstv if (!iwm_nic_lock(sc))
2039 1.91 mlelstv return EBUSY;
2040 1.91 mlelstv
2041 1.1 pooka IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_RBDCB_WPTR, 0);
2042 1.1 pooka IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_FLUSH_RB_REQ, 0);
2043 1.1 pooka IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_RDPTR, 0);
2044 1.1 pooka IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
2045 1.1 pooka
2046 1.1 pooka /* Set physical address of RX ring (256-byte aligned). */
2047 1.1 pooka IWM_WRITE(sc,
2048 1.1 pooka IWM_FH_RSCSR_CHNL0_RBDCB_BASE_REG, sc->rxq.desc_dma.paddr >> 8);
2049 1.1 pooka
2050 1.1 pooka /* Set physical address of RX status (16-byte aligned). */
2051 1.1 pooka IWM_WRITE(sc,
2052 1.1 pooka IWM_FH_RSCSR_CHNL0_STTS_WPTR_REG, sc->rxq.stat_dma.paddr >> 4);
2053 1.1 pooka
2054 1.1 pooka /* Enable RX. */
2055 1.1 pooka IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG,
2056 1.1 pooka IWM_FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
2057 1.1 pooka IWM_FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | /* HW bug */
2058 1.1 pooka IWM_FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
2059 1.45 nonaka IWM_FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
2060 1.91 mlelstv (IWM_RX_RB_TIMEOUT << IWM_FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS) |
2061 1.61 nonaka IWM_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K |
2062 1.1 pooka IWM_RX_QUEUE_SIZE_LOG << IWM_FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS);
2063 1.1 pooka
2064 1.1 pooka IWM_WRITE_1(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_TIMEOUT_DEF);
2065 1.17 nonaka
2066 1.17 nonaka /* W/A for interrupt coalescing bug in 7260 and 3160 */
2067 1.17 nonaka if (sc->host_interrupt_operation_mode)
2068 1.17 nonaka IWM_SETBITS(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_OPER_MODE);
2069 1.1 pooka
2070 1.91 mlelstv iwm_nic_unlock(sc);
2071 1.91 mlelstv
2072 1.1 pooka /*
2073 1.45 nonaka * This value should initially be 0 (before preparing any RBs),
2074 1.45 nonaka * and should be 8 after preparing the first 8 RBs (for example).
2075 1.1 pooka */
2076 1.1 pooka IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_WPTR, 8);
2077 1.1 pooka
2078 1.1 pooka return 0;
2079 1.1 pooka }
2080 1.1 pooka
2081 1.4 nonaka static int
2082 1.1 pooka iwm_nic_tx_init(struct iwm_softc *sc)
2083 1.1 pooka {
2084 1.91 mlelstv int qid, err;
2085 1.1 pooka
2086 1.1 pooka if (!iwm_nic_lock(sc))
2087 1.1 pooka return EBUSY;
2088 1.1 pooka
2089 1.1 pooka /* Deactivate TX scheduler. */
2090 1.1 pooka iwm_write_prph(sc, IWM_SCD_TXFACT, 0);
2091 1.1 pooka
2092 1.1 pooka /* Set physical address of "keep warm" page (16-byte aligned). */
2093 1.1 pooka IWM_WRITE(sc, IWM_FH_KW_MEM_ADDR_REG, sc->kw_dma.paddr >> 4);
2094 1.1 pooka
2095 1.1 pooka for (qid = 0; qid < __arraycount(sc->txq); qid++) {
2096 1.1 pooka struct iwm_tx_ring *txq = &sc->txq[qid];
2097 1.1 pooka
2098 1.1 pooka /* Set physical address of TX ring (256-byte aligned). */
2099 1.1 pooka IWM_WRITE(sc, IWM_FH_MEM_CBBC_QUEUE(qid),
2100 1.1 pooka txq->desc_dma.paddr >> 8);
2101 1.9 nonaka DPRINTF(("loading ring %d descriptors (%p) at %"PRIxMAX"\n",
2102 1.9 nonaka qid, txq->desc, (uintmax_t)(txq->desc_dma.paddr >> 8)));
2103 1.1 pooka }
2104 1.45 nonaka
2105 1.91 mlelstv err = iwm_set_bits_prph(sc, IWM_SCD_GP_CTRL,
2106 1.91 mlelstv IWM_SCD_GP_CTRL_AUTO_ACTIVE_MODE |
2107 1.91 mlelstv IWM_SCD_GP_CTRL_ENABLE_31_QUEUES);
2108 1.45 nonaka
2109 1.1 pooka iwm_nic_unlock(sc);
2110 1.1 pooka
2111 1.91 mlelstv return err;
2112 1.1 pooka }
2113 1.1 pooka
2114 1.4 nonaka static int
2115 1.1 pooka iwm_nic_init(struct iwm_softc *sc)
2116 1.1 pooka {
2117 1.45 nonaka int err;
2118 1.1 pooka
2119 1.1 pooka iwm_apm_init(sc);
2120 1.61 nonaka if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
2121 1.45 nonaka iwm_set_bits_mask_prph(sc, IWM_APMG_PS_CTRL_REG,
2122 1.45 nonaka IWM_APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
2123 1.45 nonaka ~IWM_APMG_PS_CTRL_MSK_PWR_SRC);
2124 1.61 nonaka }
2125 1.1 pooka
2126 1.45 nonaka iwm_nic_config(sc);
2127 1.1 pooka
2128 1.45 nonaka err = iwm_nic_rx_init(sc);
2129 1.45 nonaka if (err)
2130 1.45 nonaka return err;
2131 1.1 pooka
2132 1.45 nonaka err = iwm_nic_tx_init(sc);
2133 1.45 nonaka if (err)
2134 1.45 nonaka return err;
2135 1.1 pooka
2136 1.1 pooka DPRINTF(("shadow registers enabled\n"));
2137 1.1 pooka IWM_SETBITS(sc, IWM_CSR_MAC_SHADOW_REG_CTRL, 0x800fffff);
2138 1.1 pooka
2139 1.8 nonaka return 0;
2140 1.1 pooka }
2141 1.1 pooka
2142 1.45 nonaka static const uint8_t iwm_ac_to_tx_fifo[] = {
2143 1.45 nonaka IWM_TX_FIFO_BE,
2144 1.45 nonaka IWM_TX_FIFO_BK,
2145 1.91 mlelstv IWM_TX_FIFO_VI,
2146 1.91 mlelstv IWM_TX_FIFO_VO,
2147 1.1 pooka };
2148 1.1 pooka
2149 1.45 nonaka static int
2150 1.91 mlelstv iwm_enable_ac_txq(struct iwm_softc *sc, int qid, int fifo)
2151 1.1 pooka {
2152 1.91 mlelstv int err;
2153 1.1 pooka
2154 1.45 nonaka IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, qid << 8 | 0);
2155 1.91 mlelstv
2156 1.91 mlelstv iwm_write_prph(sc, IWM_SCD_QUEUE_STATUS_BITS(qid),
2157 1.91 mlelstv (0 << IWM_SCD_QUEUE_STTS_REG_POS_ACTIVE)
2158 1.91 mlelstv | (1 << IWM_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
2159 1.45 nonaka
2160 1.91 mlelstv err = iwm_clear_bits_prph(sc, IWM_SCD_AGGR_SEL, (1 << qid));
2161 1.91 mlelstv if (err) {
2162 1.91 mlelstv return err;
2163 1.91 mlelstv }
2164 1.45 nonaka
2165 1.91 mlelstv iwm_write_prph(sc, IWM_SCD_QUEUE_RDPTR(qid), 0);
2166 1.91 mlelstv
2167 1.91 mlelstv iwm_write_mem32(sc,
2168 1.91 mlelstv sc->sched_base + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid), 0);
2169 1.91 mlelstv
2170 1.91 mlelstv /* Set scheduler window size and frame limit. */
2171 1.91 mlelstv iwm_write_mem32(sc,
2172 1.91 mlelstv sc->sched_base + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid) +
2173 1.91 mlelstv sizeof(uint32_t),
2174 1.91 mlelstv ((IWM_FRAME_LIMIT << IWM_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
2175 1.91 mlelstv IWM_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
2176 1.91 mlelstv ((IWM_FRAME_LIMIT
2177 1.91 mlelstv << IWM_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
2178 1.91 mlelstv IWM_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
2179 1.91 mlelstv
2180 1.91 mlelstv iwm_write_prph(sc, IWM_SCD_QUEUE_STATUS_BITS(qid),
2181 1.91 mlelstv (1 << IWM_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
2182 1.91 mlelstv (fifo << IWM_SCD_QUEUE_STTS_REG_POS_TXF) |
2183 1.91 mlelstv (1 << IWM_SCD_QUEUE_STTS_REG_POS_WSL) |
2184 1.91 mlelstv IWM_SCD_QUEUE_STTS_REG_MSK);
2185 1.91 mlelstv
2186 1.91 mlelstv if (qid == sc->cmdqid) {
2187 1.91 mlelstv iwm_write_prph(sc, IWM_SCD_EN_CTRL,
2188 1.91 mlelstv iwm_read_prph(sc, IWM_SCD_EN_CTRL) | (1 << qid));
2189 1.91 mlelstv }
2190 1.61 nonaka
2191 1.91 mlelstv return 0;
2192 1.91 mlelstv }
2193 1.45 nonaka
2194 1.91 mlelstv static int
2195 1.91 mlelstv iwm_enable_txq(struct iwm_softc *sc, int sta_id, int qid, int fifo,
2196 1.91 mlelstv int aggregate, uint8_t tid, uint16_t ssn)
2197 1.91 mlelstv {
2198 1.91 mlelstv struct iwm_tx_ring *ring = &sc->txq[qid];
2199 1.91 mlelstv struct iwm_scd_txq_cfg_cmd cmd;
2200 1.91 mlelstv int err, idx, scd_bug;
2201 1.45 nonaka
2202 1.91 mlelstv /*
2203 1.91 mlelstv * If we need to move the SCD write pointer by steps of
2204 1.91 mlelstv * 0x40, 0x80 or 0xc0, it gets stuck.
2205 1.91 mlelstv * This is really ugly, but this is the easiest way out for
2206 1.91 mlelstv * this sad hardware issue.
2207 1.91 mlelstv * This bug has been fixed on devices 9000 and up.
2208 1.91 mlelstv */
2209 1.91 mlelstv #ifdef notyet
2210 1.91 mlelstv scd_bug = !sc->sc_mqrx_supported &&
2211 1.91 mlelstv !((ssn - ring->cur) & 0x3f) &&
2212 1.91 mlelstv (ssn != ring->cur);
2213 1.91 mlelstv #else
2214 1.91 mlelstv scd_bug = !((ssn - ring->cur) & 0x3f) &&
2215 1.91 mlelstv (ssn != ring->cur);
2216 1.91 mlelstv #endif
2217 1.91 mlelstv if (scd_bug)
2218 1.91 mlelstv ssn = (ssn + 1) & 0xfff;
2219 1.45 nonaka
2220 1.91 mlelstv idx = IWM_AGG_SSN_TO_TXQ_IDX(ssn);
2221 1.91 mlelstv IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, qid << 8 | idx);
2222 1.91 mlelstv ring->cur = idx;
2223 1.45 nonaka
2224 1.91 mlelstv memset(&cmd, 0, sizeof(cmd));
2225 1.91 mlelstv cmd.tid = tid;
2226 1.91 mlelstv cmd.scd_queue = qid;
2227 1.91 mlelstv cmd.enable = 1;
2228 1.91 mlelstv cmd.sta_id = sta_id;
2229 1.91 mlelstv cmd.tx_fifo = fifo;
2230 1.91 mlelstv cmd.aggregate = aggregate;
2231 1.91 mlelstv cmd.ssn = htole16(ssn);
2232 1.91 mlelstv cmd.window = IWM_FRAME_LIMIT;
2233 1.1 pooka
2234 1.91 mlelstv err = iwm_send_cmd_pdu(sc, IWM_SCD_QUEUE_CFG, 0,
2235 1.91 mlelstv sizeof(cmd), &cmd);
2236 1.91 mlelstv if (err)
2237 1.91 mlelstv return err;
2238 1.45 nonaka
2239 1.45 nonaka return 0;
2240 1.1 pooka }
2241 1.1 pooka
2242 1.4 nonaka static int
2243 1.1 pooka iwm_post_alive(struct iwm_softc *sc)
2244 1.1 pooka {
2245 1.91 mlelstv int nwords;
2246 1.45 nonaka int err, chnl;
2247 1.45 nonaka uint32_t base;
2248 1.1 pooka
2249 1.1 pooka if (!iwm_nic_lock(sc))
2250 1.1 pooka return EBUSY;
2251 1.1 pooka
2252 1.45 nonaka base = iwm_read_prph(sc, IWM_SCD_SRAM_BASE_ADDR);
2253 1.45 nonaka if (sc->sched_base != base) {
2254 1.45 nonaka DPRINTF(("%s: sched addr mismatch: 0x%08x != 0x%08x\n",
2255 1.45 nonaka DEVNAME(sc), sc->sched_base, base));
2256 1.61 nonaka sc->sched_base = base;
2257 1.1 pooka }
2258 1.1 pooka
2259 1.91 mlelstv iwm_ict_reset(sc);
2260 1.91 mlelstv
2261 1.61 nonaka iwm_nic_unlock(sc);
2262 1.61 nonaka
2263 1.1 pooka /* Clear TX scheduler state in SRAM. */
2264 1.91 mlelstv nwords = (IWM_SCD_TRANS_TBL_MEM_UPPER_BOUND -
2265 1.91 mlelstv IWM_SCD_CONTEXT_MEM_LOWER_BOUND)
2266 1.91 mlelstv / sizeof(uint32_t);
2267 1.45 nonaka err = iwm_write_mem(sc,
2268 1.91 mlelstv sc->sched_base + IWM_SCD_CONTEXT_MEM_LOWER_BOUND,
2269 1.91 mlelstv NULL, nwords);
2270 1.45 nonaka if (err)
2271 1.61 nonaka return err;
2272 1.61 nonaka
2273 1.61 nonaka if (!iwm_nic_lock(sc))
2274 1.61 nonaka return EBUSY;
2275 1.1 pooka
2276 1.1 pooka /* Set physical address of TX scheduler rings (1KB aligned). */
2277 1.1 pooka iwm_write_prph(sc, IWM_SCD_DRAM_BASE_ADDR, sc->sched_dma.paddr >> 10);
2278 1.1 pooka
2279 1.1 pooka iwm_write_prph(sc, IWM_SCD_CHAINEXT_EN, 0);
2280 1.1 pooka
2281 1.1 pooka /* enable command channel */
2282 1.91 mlelstv err = iwm_enable_ac_txq(sc, sc->cmdqid, IWM_TX_FIFO_CMD);
2283 1.91 mlelstv if (err) {
2284 1.91 mlelstv iwm_nic_unlock(sc);
2285 1.45 nonaka return err;
2286 1.91 mlelstv }
2287 1.1 pooka
2288 1.45 nonaka /* Activate TX scheduler. */
2289 1.1 pooka iwm_write_prph(sc, IWM_SCD_TXFACT, 0xff);
2290 1.1 pooka
2291 1.1 pooka /* Enable DMA channels. */
2292 1.1 pooka for (chnl = 0; chnl < IWM_FH_TCSR_CHNL_NUM; chnl++) {
2293 1.1 pooka IWM_WRITE(sc, IWM_FH_TCSR_CHNL_TX_CONFIG_REG(chnl),
2294 1.1 pooka IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
2295 1.1 pooka IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
2296 1.1 pooka }
2297 1.1 pooka
2298 1.1 pooka IWM_SETBITS(sc, IWM_FH_TX_CHICKEN_BITS_REG,
2299 1.1 pooka IWM_FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
2300 1.1 pooka
2301 1.91 mlelstv iwm_nic_unlock(sc);
2302 1.91 mlelstv
2303 1.8 nonaka /* Enable L1-Active */
2304 1.91 mlelstv if (sc->sc_device_family < IWM_DEVICE_FAMILY_8000) {
2305 1.91 mlelstv err = iwm_clear_bits_prph(sc, IWM_APMG_PCIDEV_STT_REG,
2306 1.45 nonaka IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
2307 1.61 nonaka }
2308 1.1 pooka
2309 1.91 mlelstv return err;
2310 1.1 pooka }
2311 1.1 pooka
2312 1.1 pooka static struct iwm_phy_db_entry *
2313 1.45 nonaka iwm_phy_db_get_section(struct iwm_softc *sc, enum iwm_phy_db_section_type type,
2314 1.45 nonaka uint16_t chg_id)
2315 1.1 pooka {
2316 1.1 pooka struct iwm_phy_db *phy_db = &sc->sc_phy_db;
2317 1.1 pooka
2318 1.1 pooka if (type >= IWM_PHY_DB_MAX)
2319 1.1 pooka return NULL;
2320 1.1 pooka
2321 1.1 pooka switch (type) {
2322 1.1 pooka case IWM_PHY_DB_CFG:
2323 1.1 pooka return &phy_db->cfg;
2324 1.1 pooka case IWM_PHY_DB_CALIB_NCH:
2325 1.1 pooka return &phy_db->calib_nch;
2326 1.1 pooka case IWM_PHY_DB_CALIB_CHG_PAPD:
2327 1.1 pooka if (chg_id >= IWM_NUM_PAPD_CH_GROUPS)
2328 1.1 pooka return NULL;
2329 1.1 pooka return &phy_db->calib_ch_group_papd[chg_id];
2330 1.1 pooka case IWM_PHY_DB_CALIB_CHG_TXP:
2331 1.1 pooka if (chg_id >= IWM_NUM_TXP_CH_GROUPS)
2332 1.1 pooka return NULL;
2333 1.1 pooka return &phy_db->calib_ch_group_txp[chg_id];
2334 1.1 pooka default:
2335 1.1 pooka return NULL;
2336 1.1 pooka }
2337 1.1 pooka return NULL;
2338 1.1 pooka }
2339 1.1 pooka
2340 1.1 pooka static int
2341 1.1 pooka iwm_phy_db_set_section(struct iwm_softc *sc,
2342 1.5 nonaka struct iwm_calib_res_notif_phy_db *phy_db_notif, uint16_t size)
2343 1.1 pooka {
2344 1.45 nonaka struct iwm_phy_db_entry *entry;
2345 1.1 pooka enum iwm_phy_db_section_type type = le16toh(phy_db_notif->type);
2346 1.1 pooka uint16_t chg_id = 0;
2347 1.1 pooka
2348 1.1 pooka if (type == IWM_PHY_DB_CALIB_CHG_PAPD ||
2349 1.1 pooka type == IWM_PHY_DB_CALIB_CHG_TXP)
2350 1.1 pooka chg_id = le16toh(*(uint16_t *)phy_db_notif->data);
2351 1.1 pooka
2352 1.1 pooka entry = iwm_phy_db_get_section(sc, type, chg_id);
2353 1.1 pooka if (!entry)
2354 1.1 pooka return EINVAL;
2355 1.1 pooka
2356 1.1 pooka if (entry->data)
2357 1.5 nonaka kmem_intr_free(entry->data, entry->size);
2358 1.5 nonaka entry->data = kmem_intr_alloc(size, KM_NOSLEEP);
2359 1.1 pooka if (!entry->data) {
2360 1.1 pooka entry->size = 0;
2361 1.1 pooka return ENOMEM;
2362 1.1 pooka }
2363 1.1 pooka memcpy(entry->data, phy_db_notif->data, size);
2364 1.1 pooka entry->size = size;
2365 1.1 pooka
2366 1.5 nonaka DPRINTFN(10, ("%s(%d): [PHYDB]SET: Type %d, Size: %d, data: %p\n",
2367 1.1 pooka __func__, __LINE__, type, size, entry->data));
2368 1.1 pooka
2369 1.1 pooka return 0;
2370 1.1 pooka }
2371 1.1 pooka
2372 1.4 nonaka static int
2373 1.1 pooka iwm_is_valid_channel(uint16_t ch_id)
2374 1.1 pooka {
2375 1.1 pooka if (ch_id <= 14 ||
2376 1.1 pooka (36 <= ch_id && ch_id <= 64 && ch_id % 4 == 0) ||
2377 1.1 pooka (100 <= ch_id && ch_id <= 140 && ch_id % 4 == 0) ||
2378 1.1 pooka (145 <= ch_id && ch_id <= 165 && ch_id % 4 == 1))
2379 1.1 pooka return 1;
2380 1.1 pooka return 0;
2381 1.1 pooka }
2382 1.1 pooka
2383 1.4 nonaka static uint8_t
2384 1.1 pooka iwm_ch_id_to_ch_index(uint16_t ch_id)
2385 1.1 pooka {
2386 1.1 pooka if (!iwm_is_valid_channel(ch_id))
2387 1.1 pooka return 0xff;
2388 1.1 pooka
2389 1.1 pooka if (ch_id <= 14)
2390 1.1 pooka return ch_id - 1;
2391 1.1 pooka if (ch_id <= 64)
2392 1.1 pooka return (ch_id + 20) / 4;
2393 1.1 pooka if (ch_id <= 140)
2394 1.1 pooka return (ch_id - 12) / 4;
2395 1.1 pooka return (ch_id - 13) / 4;
2396 1.1 pooka }
2397 1.1 pooka
2398 1.1 pooka
2399 1.4 nonaka static uint16_t
2400 1.1 pooka iwm_channel_id_to_papd(uint16_t ch_id)
2401 1.1 pooka {
2402 1.1 pooka if (!iwm_is_valid_channel(ch_id))
2403 1.1 pooka return 0xff;
2404 1.1 pooka
2405 1.1 pooka if (1 <= ch_id && ch_id <= 14)
2406 1.1 pooka return 0;
2407 1.1 pooka if (36 <= ch_id && ch_id <= 64)
2408 1.1 pooka return 1;
2409 1.1 pooka if (100 <= ch_id && ch_id <= 140)
2410 1.1 pooka return 2;
2411 1.1 pooka return 3;
2412 1.1 pooka }
2413 1.1 pooka
2414 1.4 nonaka static uint16_t
2415 1.1 pooka iwm_channel_id_to_txp(struct iwm_softc *sc, uint16_t ch_id)
2416 1.1 pooka {
2417 1.1 pooka struct iwm_phy_db *phy_db = &sc->sc_phy_db;
2418 1.1 pooka struct iwm_phy_db_chg_txp *txp_chg;
2419 1.1 pooka int i;
2420 1.1 pooka uint8_t ch_index = iwm_ch_id_to_ch_index(ch_id);
2421 1.1 pooka
2422 1.1 pooka if (ch_index == 0xff)
2423 1.1 pooka return 0xff;
2424 1.1 pooka
2425 1.1 pooka for (i = 0; i < IWM_NUM_TXP_CH_GROUPS; i++) {
2426 1.1 pooka txp_chg = (void *)phy_db->calib_ch_group_txp[i].data;
2427 1.1 pooka if (!txp_chg)
2428 1.1 pooka return 0xff;
2429 1.1 pooka /*
2430 1.45 nonaka * Looking for the first channel group the max channel
2431 1.45 nonaka * of which is higher than the requested channel.
2432 1.1 pooka */
2433 1.1 pooka if (le16toh(txp_chg->max_channel_idx) >= ch_index)
2434 1.1 pooka return i;
2435 1.1 pooka }
2436 1.1 pooka return 0xff;
2437 1.1 pooka }
2438 1.1 pooka
2439 1.4 nonaka static int
2440 1.45 nonaka iwm_phy_db_get_section_data(struct iwm_softc *sc, uint32_t type, uint8_t **data,
2441 1.45 nonaka uint16_t *size, uint16_t ch_id)
2442 1.1 pooka {
2443 1.1 pooka struct iwm_phy_db_entry *entry;
2444 1.1 pooka uint16_t ch_group_id = 0;
2445 1.1 pooka
2446 1.1 pooka if (type == IWM_PHY_DB_CALIB_CHG_PAPD)
2447 1.1 pooka ch_group_id = iwm_channel_id_to_papd(ch_id);
2448 1.1 pooka else if (type == IWM_PHY_DB_CALIB_CHG_TXP)
2449 1.1 pooka ch_group_id = iwm_channel_id_to_txp(sc, ch_id);
2450 1.1 pooka
2451 1.1 pooka entry = iwm_phy_db_get_section(sc, type, ch_group_id);
2452 1.1 pooka if (!entry)
2453 1.1 pooka return EINVAL;
2454 1.1 pooka
2455 1.1 pooka *data = entry->data;
2456 1.1 pooka *size = entry->size;
2457 1.1 pooka
2458 1.1 pooka DPRINTFN(10, ("%s(%d): [PHYDB] GET: Type %d , Size: %d\n",
2459 1.1 pooka __func__, __LINE__, type, *size));
2460 1.1 pooka
2461 1.1 pooka return 0;
2462 1.1 pooka }
2463 1.1 pooka
2464 1.4 nonaka static int
2465 1.45 nonaka iwm_send_phy_db_cmd(struct iwm_softc *sc, uint16_t type, uint16_t length,
2466 1.45 nonaka void *data)
2467 1.1 pooka {
2468 1.1 pooka struct iwm_phy_db_cmd phy_db_cmd;
2469 1.1 pooka struct iwm_host_cmd cmd = {
2470 1.1 pooka .id = IWM_PHY_DB_CMD,
2471 1.45 nonaka .flags = IWM_CMD_ASYNC,
2472 1.1 pooka };
2473 1.1 pooka
2474 1.5 nonaka DPRINTFN(10, ("Sending PHY-DB hcmd of type %d, of length %d\n",
2475 1.5 nonaka type, length));
2476 1.1 pooka
2477 1.1 pooka phy_db_cmd.type = le16toh(type);
2478 1.1 pooka phy_db_cmd.length = le16toh(length);
2479 1.1 pooka
2480 1.1 pooka cmd.data[0] = &phy_db_cmd;
2481 1.1 pooka cmd.len[0] = sizeof(struct iwm_phy_db_cmd);
2482 1.1 pooka cmd.data[1] = data;
2483 1.1 pooka cmd.len[1] = length;
2484 1.1 pooka
2485 1.1 pooka return iwm_send_cmd(sc, &cmd);
2486 1.1 pooka }
2487 1.1 pooka
2488 1.1 pooka static int
2489 1.1 pooka iwm_phy_db_send_all_channel_groups(struct iwm_softc *sc,
2490 1.45 nonaka enum iwm_phy_db_section_type type, uint8_t max_ch_groups)
2491 1.1 pooka {
2492 1.1 pooka uint16_t i;
2493 1.1 pooka int err;
2494 1.1 pooka struct iwm_phy_db_entry *entry;
2495 1.1 pooka
2496 1.1 pooka /* Send all the channel-specific groups to operational fw */
2497 1.1 pooka for (i = 0; i < max_ch_groups; i++) {
2498 1.1 pooka entry = iwm_phy_db_get_section(sc, type, i);
2499 1.1 pooka if (!entry)
2500 1.1 pooka return EINVAL;
2501 1.1 pooka
2502 1.1 pooka if (!entry->size)
2503 1.1 pooka continue;
2504 1.1 pooka
2505 1.1 pooka err = iwm_send_phy_db_cmd(sc, type, entry->size, entry->data);
2506 1.1 pooka if (err) {
2507 1.2 nonaka DPRINTF(("%s: Can't SEND phy_db section %d (%d), "
2508 1.2 nonaka "err %d\n", DEVNAME(sc), type, i, err));
2509 1.1 pooka return err;
2510 1.1 pooka }
2511 1.1 pooka
2512 1.45 nonaka DPRINTFN(10, ("%s: Sent PHY_DB HCMD, type = %d num = %d\n",
2513 1.45 nonaka DEVNAME(sc), type, i));
2514 1.45 nonaka
2515 1.45 nonaka DELAY(1000);
2516 1.1 pooka }
2517 1.1 pooka
2518 1.1 pooka return 0;
2519 1.1 pooka }
2520 1.1 pooka
2521 1.4 nonaka static int
2522 1.1 pooka iwm_send_phy_db_data(struct iwm_softc *sc)
2523 1.1 pooka {
2524 1.1 pooka uint8_t *data = NULL;
2525 1.1 pooka uint16_t size = 0;
2526 1.1 pooka int err;
2527 1.1 pooka
2528 1.1 pooka err = iwm_phy_db_get_section_data(sc, IWM_PHY_DB_CFG, &data, &size, 0);
2529 1.45 nonaka if (err)
2530 1.1 pooka return err;
2531 1.1 pooka
2532 1.1 pooka err = iwm_send_phy_db_cmd(sc, IWM_PHY_DB_CFG, size, data);
2533 1.45 nonaka if (err)
2534 1.1 pooka return err;
2535 1.1 pooka
2536 1.1 pooka err = iwm_phy_db_get_section_data(sc, IWM_PHY_DB_CALIB_NCH,
2537 1.1 pooka &data, &size, 0);
2538 1.45 nonaka if (err)
2539 1.1 pooka return err;
2540 1.1 pooka
2541 1.1 pooka err = iwm_send_phy_db_cmd(sc, IWM_PHY_DB_CALIB_NCH, size, data);
2542 1.45 nonaka if (err)
2543 1.1 pooka return err;
2544 1.1 pooka
2545 1.1 pooka err = iwm_phy_db_send_all_channel_groups(sc,
2546 1.1 pooka IWM_PHY_DB_CALIB_CHG_PAPD, IWM_NUM_PAPD_CH_GROUPS);
2547 1.45 nonaka if (err)
2548 1.1 pooka return err;
2549 1.1 pooka
2550 1.1 pooka err = iwm_phy_db_send_all_channel_groups(sc,
2551 1.1 pooka IWM_PHY_DB_CALIB_CHG_TXP, IWM_NUM_TXP_CH_GROUPS);
2552 1.45 nonaka if (err)
2553 1.1 pooka return err;
2554 1.1 pooka
2555 1.1 pooka return 0;
2556 1.1 pooka }
2557 1.1 pooka
2558 1.91 mlelstv static int
2559 1.91 mlelstv iwm_send_time_event_cmd(struct iwm_softc *sc,
2560 1.91 mlelstv const struct iwm_time_event_cmd *cmd)
2561 1.91 mlelstv {
2562 1.91 mlelstv struct iwm_rx_packet *pkt;
2563 1.91 mlelstv struct iwm_time_event_resp *resp;
2564 1.91 mlelstv struct iwm_host_cmd hcmd = {
2565 1.91 mlelstv .id = IWM_TIME_EVENT_CMD,
2566 1.91 mlelstv .flags = IWM_CMD_WANT_RESP,
2567 1.91 mlelstv .resp_pkt_len = sizeof(*pkt) + sizeof(*resp),
2568 1.91 mlelstv };
2569 1.91 mlelstv uint32_t resp_len;
2570 1.91 mlelstv int err;
2571 1.1 pooka
2572 1.91 mlelstv hcmd.data[0] = cmd;
2573 1.91 mlelstv hcmd.len[0] = sizeof(*cmd);
2574 1.91 mlelstv err = iwm_send_cmd(sc, &hcmd);
2575 1.91 mlelstv if (err)
2576 1.91 mlelstv return err;
2577 1.1 pooka
2578 1.91 mlelstv pkt = hcmd.resp_pkt;
2579 1.91 mlelstv if (!pkt || (pkt->hdr.flags & IWM_CMD_FAILED_MSK)) {
2580 1.91 mlelstv err = EIO;
2581 1.91 mlelstv goto out;
2582 1.91 mlelstv }
2583 1.1 pooka
2584 1.91 mlelstv resp_len = iwm_rx_packet_payload_len(pkt);
2585 1.91 mlelstv if (resp_len != sizeof(*resp)) {
2586 1.91 mlelstv err = EIO;
2587 1.91 mlelstv goto out;
2588 1.91 mlelstv }
2589 1.1 pooka
2590 1.91 mlelstv resp = (void *)pkt->data;
2591 1.91 mlelstv if (le32toh(resp->status) == 0)
2592 1.91 mlelstv sc->sc_time_event_uid = le32toh(resp->unique_id);
2593 1.1 pooka else
2594 1.91 mlelstv err = EIO;
2595 1.91 mlelstv out:
2596 1.91 mlelstv iwm_free_resp(sc, &hcmd);
2597 1.91 mlelstv return err;
2598 1.1 pooka }
2599 1.1 pooka
2600 1.4 nonaka static void
2601 1.45 nonaka iwm_protect_session(struct iwm_softc *sc, struct iwm_node *in,
2602 1.45 nonaka uint32_t duration, uint32_t max_delay)
2603 1.1 pooka {
2604 1.91 mlelstv struct iwm_time_event_cmd time_cmd;
2605 1.91 mlelstv
2606 1.91 mlelstv /* Do nothing if a time event is already scheduled. */
2607 1.91 mlelstv if (ISSET(sc->sc_flags, IWM_FLAG_TE_ACTIVE))
2608 1.91 mlelstv return;
2609 1.1 pooka
2610 1.1 pooka memset(&time_cmd, 0, sizeof(time_cmd));
2611 1.1 pooka
2612 1.1 pooka time_cmd.action = htole32(IWM_FW_CTXT_ACTION_ADD);
2613 1.1 pooka time_cmd.id_and_color =
2614 1.1 pooka htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));
2615 1.1 pooka time_cmd.id = htole32(IWM_TE_BSS_STA_AGGRESSIVE_ASSOC);
2616 1.1 pooka
2617 1.45 nonaka time_cmd.apply_time = htole32(0);
2618 1.1 pooka
2619 1.1 pooka time_cmd.max_frags = IWM_TE_V2_FRAG_NONE;
2620 1.1 pooka time_cmd.max_delay = htole32(max_delay);
2621 1.1 pooka /* TODO: why do we need to interval = bi if it is not periodic? */
2622 1.1 pooka time_cmd.interval = htole32(1);
2623 1.1 pooka time_cmd.duration = htole32(duration);
2624 1.1 pooka time_cmd.repeat = 1;
2625 1.1 pooka time_cmd.policy
2626 1.45 nonaka = htole16(IWM_TE_V2_NOTIF_HOST_EVENT_START |
2627 1.45 nonaka IWM_TE_V2_NOTIF_HOST_EVENT_END |
2628 1.91 mlelstv IWM_TE_V2_START_IMMEDIATELY);
2629 1.91 mlelstv
2630 1.91 mlelstv if (iwm_send_time_event_cmd(sc, &time_cmd) == 0)
2631 1.91 mlelstv SET(sc->sc_flags, IWM_FLAG_TE_ACTIVE);
2632 1.91 mlelstv
2633 1.91 mlelstv DELAY(100);
2634 1.91 mlelstv }
2635 1.91 mlelstv
2636 1.91 mlelstv static void
2637 1.91 mlelstv iwm_unprotect_session(struct iwm_softc *sc, struct iwm_node *in)
2638 1.91 mlelstv {
2639 1.91 mlelstv struct iwm_time_event_cmd time_cmd;
2640 1.91 mlelstv
2641 1.91 mlelstv /* Do nothing if the time event has already ended. */
2642 1.91 mlelstv if ((sc->sc_flags & IWM_FLAG_TE_ACTIVE) == 0)
2643 1.91 mlelstv return;
2644 1.91 mlelstv
2645 1.91 mlelstv memset(&time_cmd, 0, sizeof(time_cmd));
2646 1.1 pooka
2647 1.91 mlelstv time_cmd.action = htole32(IWM_FW_CTXT_ACTION_REMOVE);
2648 1.91 mlelstv time_cmd.id_and_color =
2649 1.91 mlelstv htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));
2650 1.91 mlelstv time_cmd.id = htole32(sc->sc_time_event_uid);
2651 1.91 mlelstv
2652 1.91 mlelstv if (iwm_send_time_event_cmd(sc, &time_cmd) == 0)
2653 1.91 mlelstv CLR(sc->sc_flags, IWM_FLAG_TE_ACTIVE);
2654 1.91 mlelstv
2655 1.91 mlelstv DELAY(100);
2656 1.1 pooka }
2657 1.1 pooka
2658 1.1 pooka /*
2659 1.1 pooka * NVM read access and content parsing. We do not support
2660 1.1 pooka * external NVM or writing NVM.
2661 1.1 pooka */
2662 1.1 pooka
2663 1.1 pooka /* list of NVM sections we are allowed/need to read */
2664 1.45 nonaka static const int iwm_nvm_to_read[] = {
2665 1.1 pooka IWM_NVM_SECTION_TYPE_HW,
2666 1.1 pooka IWM_NVM_SECTION_TYPE_SW,
2667 1.45 nonaka IWM_NVM_SECTION_TYPE_REGULATORY,
2668 1.1 pooka IWM_NVM_SECTION_TYPE_CALIBRATION,
2669 1.1 pooka IWM_NVM_SECTION_TYPE_PRODUCTION,
2670 1.91 mlelstv IWM_NVM_SECTION_TYPE_REGULATORY_SDP,
2671 1.45 nonaka IWM_NVM_SECTION_TYPE_HW_8000,
2672 1.45 nonaka IWM_NVM_SECTION_TYPE_MAC_OVERRIDE,
2673 1.45 nonaka IWM_NVM_SECTION_TYPE_PHY_SKU,
2674 1.1 pooka };
2675 1.1 pooka
2676 1.1 pooka /* Default NVM size to read */
2677 1.45 nonaka #define IWM_NVM_DEFAULT_CHUNK_SIZE (2*1024)
2678 1.61 nonaka #define IWM_MAX_NVM_SECTION_SIZE_7000 (16 * 512 * sizeof(uint16_t)) /*16 KB*/
2679 1.61 nonaka #define IWM_MAX_NVM_SECTION_SIZE_8000 (32 * 512 * sizeof(uint16_t)) /*32 KB*/
2680 1.1 pooka
2681 1.1 pooka #define IWM_NVM_WRITE_OPCODE 1
2682 1.1 pooka #define IWM_NVM_READ_OPCODE 0
2683 1.1 pooka
2684 1.4 nonaka static int
2685 1.45 nonaka iwm_nvm_read_chunk(struct iwm_softc *sc, uint16_t section, uint16_t offset,
2686 1.45 nonaka uint16_t length, uint8_t *data, uint16_t *len)
2687 1.1 pooka {
2688 1.1 pooka offset = 0;
2689 1.1 pooka struct iwm_nvm_access_cmd nvm_access_cmd = {
2690 1.1 pooka .offset = htole16(offset),
2691 1.1 pooka .length = htole16(length),
2692 1.1 pooka .type = htole16(section),
2693 1.1 pooka .op_code = IWM_NVM_READ_OPCODE,
2694 1.1 pooka };
2695 1.1 pooka struct iwm_nvm_access_resp *nvm_resp;
2696 1.1 pooka struct iwm_rx_packet *pkt;
2697 1.1 pooka struct iwm_host_cmd cmd = {
2698 1.1 pooka .id = IWM_NVM_ACCESS_CMD,
2699 1.91 mlelstv .flags = (IWM_CMD_WANT_RESP | IWM_CMD_SEND_IN_RFKILL),
2700 1.91 mlelstv .resp_pkt_len = IWM_CMD_RESP_MAX,
2701 1.1 pooka .data = { &nvm_access_cmd, },
2702 1.1 pooka };
2703 1.45 nonaka int err, offset_read;
2704 1.45 nonaka size_t bytes_read;
2705 1.1 pooka uint8_t *resp_data;
2706 1.1 pooka
2707 1.1 pooka cmd.len[0] = sizeof(struct iwm_nvm_access_cmd);
2708 1.1 pooka
2709 1.45 nonaka err = iwm_send_cmd(sc, &cmd);
2710 1.45 nonaka if (err) {
2711 1.45 nonaka DPRINTF(("%s: Could not send NVM_ACCESS command (error=%d)\n",
2712 1.45 nonaka DEVNAME(sc), err));
2713 1.45 nonaka return err;
2714 1.45 nonaka }
2715 1.1 pooka
2716 1.1 pooka pkt = cmd.resp_pkt;
2717 1.1 pooka if (pkt->hdr.flags & IWM_CMD_FAILED_MSK) {
2718 1.45 nonaka err = EIO;
2719 1.1 pooka goto exit;
2720 1.1 pooka }
2721 1.1 pooka
2722 1.1 pooka /* Extract NVM response */
2723 1.1 pooka nvm_resp = (void *)pkt->data;
2724 1.91 mlelstv if (nvm_resp == NULL) {
2725 1.91 mlelstv err = EIO;
2726 1.91 mlelstv goto exit;
2727 1.91 mlelstv }
2728 1.1 pooka
2729 1.45 nonaka err = le16toh(nvm_resp->status);
2730 1.1 pooka bytes_read = le16toh(nvm_resp->length);
2731 1.1 pooka offset_read = le16toh(nvm_resp->offset);
2732 1.1 pooka resp_data = nvm_resp->data;
2733 1.45 nonaka if (err) {
2734 1.45 nonaka err = EINVAL;
2735 1.1 pooka goto exit;
2736 1.1 pooka }
2737 1.1 pooka
2738 1.1 pooka if (offset_read != offset) {
2739 1.45 nonaka err = EINVAL;
2740 1.45 nonaka goto exit;
2741 1.45 nonaka }
2742 1.45 nonaka if (bytes_read > length) {
2743 1.45 nonaka err = EINVAL;
2744 1.1 pooka goto exit;
2745 1.1 pooka }
2746 1.1 pooka
2747 1.1 pooka memcpy(data + offset, resp_data, bytes_read);
2748 1.1 pooka *len = bytes_read;
2749 1.1 pooka
2750 1.1 pooka exit:
2751 1.1 pooka iwm_free_resp(sc, &cmd);
2752 1.45 nonaka return err;
2753 1.1 pooka }
2754 1.1 pooka
2755 1.1 pooka /*
2756 1.1 pooka * Reads an NVM section completely.
2757 1.1 pooka * NICs prior to 7000 family doesn't have a real NVM, but just read
2758 1.1 pooka * section 0 which is the EEPROM. Because the EEPROM reading is unlimited
2759 1.1 pooka * by uCode, we need to manually check in this case that we don't
2760 1.1 pooka * overflow and try to read more than the EEPROM size.
2761 1.1 pooka */
2762 1.4 nonaka static int
2763 1.45 nonaka iwm_nvm_read_section(struct iwm_softc *sc, uint16_t section, uint8_t *data,
2764 1.45 nonaka uint16_t *len, size_t max_len)
2765 1.1 pooka {
2766 1.45 nonaka uint16_t chunklen, seglen;
2767 1.45 nonaka int err;
2768 1.1 pooka
2769 1.45 nonaka chunklen = seglen = IWM_NVM_DEFAULT_CHUNK_SIZE;
2770 1.1 pooka *len = 0;
2771 1.1 pooka
2772 1.45 nonaka /* Read NVM chunks until exhausted (reading less than requested) */
2773 1.45 nonaka while (seglen == chunklen && *len < max_len) {
2774 1.45 nonaka err = iwm_nvm_read_chunk(sc, section, *len, chunklen, data,
2775 1.45 nonaka &seglen);
2776 1.45 nonaka if (err) {
2777 1.61 nonaka DPRINTF(("%s: Cannot read NVM from section %d "
2778 1.45 nonaka "offset %d, length %d\n",
2779 1.45 nonaka DEVNAME(sc), section, *len, chunklen));
2780 1.45 nonaka return err;
2781 1.1 pooka }
2782 1.1 pooka *len += seglen;
2783 1.1 pooka }
2784 1.1 pooka
2785 1.1 pooka DPRINTFN(4, ("NVM section %d read completed\n", section));
2786 1.1 pooka return 0;
2787 1.1 pooka }
2788 1.1 pooka
2789 1.45 nonaka static uint8_t
2790 1.45 nonaka iwm_fw_valid_tx_ant(struct iwm_softc *sc)
2791 1.45 nonaka {
2792 1.45 nonaka uint8_t tx_ant;
2793 1.45 nonaka
2794 1.45 nonaka tx_ant = ((sc->sc_fw_phy_config & IWM_FW_PHY_CFG_TX_CHAIN)
2795 1.45 nonaka >> IWM_FW_PHY_CFG_TX_CHAIN_POS);
2796 1.45 nonaka
2797 1.45 nonaka if (sc->sc_nvm.valid_tx_ant)
2798 1.45 nonaka tx_ant &= sc->sc_nvm.valid_tx_ant;
2799 1.45 nonaka
2800 1.45 nonaka return tx_ant;
2801 1.45 nonaka }
2802 1.1 pooka
2803 1.45 nonaka static uint8_t
2804 1.45 nonaka iwm_fw_valid_rx_ant(struct iwm_softc *sc)
2805 1.45 nonaka {
2806 1.45 nonaka uint8_t rx_ant;
2807 1.1 pooka
2808 1.45 nonaka rx_ant = ((sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RX_CHAIN)
2809 1.45 nonaka >> IWM_FW_PHY_CFG_RX_CHAIN_POS);
2810 1.1 pooka
2811 1.45 nonaka if (sc->sc_nvm.valid_rx_ant)
2812 1.45 nonaka rx_ant &= sc->sc_nvm.valid_rx_ant;
2813 1.1 pooka
2814 1.45 nonaka return rx_ant;
2815 1.45 nonaka }
2816 1.1 pooka
2817 1.4 nonaka static void
2818 1.45 nonaka iwm_init_channel_map(struct iwm_softc *sc, const uint16_t * const nvm_ch_flags,
2819 1.45 nonaka const uint8_t *nvm_channels, size_t nchan)
2820 1.1 pooka {
2821 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
2822 1.1 pooka struct iwm_nvm_data *data = &sc->sc_nvm;
2823 1.1 pooka int ch_idx;
2824 1.1 pooka struct ieee80211_channel *channel;
2825 1.1 pooka uint16_t ch_flags;
2826 1.1 pooka int is_5ghz;
2827 1.1 pooka int flags, hw_value;
2828 1.1 pooka
2829 1.45 nonaka for (ch_idx = 0; ch_idx < nchan; ch_idx++) {
2830 1.1 pooka ch_flags = le16_to_cpup(nvm_ch_flags + ch_idx);
2831 1.64 nonaka aprint_debug_dev(sc->sc_dev,
2832 1.64 nonaka "Ch. %d: %svalid %cibss %s %cradar %cdfs"
2833 1.64 nonaka " %cwide %c40MHz %c80MHz %c160MHz\n",
2834 1.64 nonaka nvm_channels[ch_idx],
2835 1.64 nonaka ch_flags & IWM_NVM_CHANNEL_VALID ? "" : "in",
2836 1.64 nonaka ch_flags & IWM_NVM_CHANNEL_IBSS ? '+' : '-',
2837 1.64 nonaka ch_flags & IWM_NVM_CHANNEL_ACTIVE ? "active" : "passive",
2838 1.64 nonaka ch_flags & IWM_NVM_CHANNEL_RADAR ? '+' : '-',
2839 1.64 nonaka ch_flags & IWM_NVM_CHANNEL_DFS ? '+' : '-',
2840 1.64 nonaka ch_flags & IWM_NVM_CHANNEL_WIDE ? '+' : '-',
2841 1.64 nonaka ch_flags & IWM_NVM_CHANNEL_40MHZ ? '+' : '-',
2842 1.64 nonaka ch_flags & IWM_NVM_CHANNEL_80MHZ ? '+' : '-',
2843 1.64 nonaka ch_flags & IWM_NVM_CHANNEL_160MHZ ? '+' : '-');
2844 1.1 pooka
2845 1.1 pooka if (ch_idx >= IWM_NUM_2GHZ_CHANNELS &&
2846 1.1 pooka !data->sku_cap_band_52GHz_enable)
2847 1.1 pooka ch_flags &= ~IWM_NVM_CHANNEL_VALID;
2848 1.1 pooka
2849 1.1 pooka if (!(ch_flags & IWM_NVM_CHANNEL_VALID)) {
2850 1.1 pooka DPRINTF(("Ch. %d Flags %x [%sGHz] - No traffic\n",
2851 1.64 nonaka nvm_channels[ch_idx], ch_flags,
2852 1.64 nonaka (ch_idx >= IWM_NUM_2GHZ_CHANNELS) ? "5" : "2.4"));
2853 1.1 pooka continue;
2854 1.1 pooka }
2855 1.1 pooka
2856 1.45 nonaka hw_value = nvm_channels[ch_idx];
2857 1.1 pooka channel = &ic->ic_channels[hw_value];
2858 1.1 pooka
2859 1.1 pooka is_5ghz = ch_idx >= IWM_NUM_2GHZ_CHANNELS;
2860 1.1 pooka if (!is_5ghz) {
2861 1.1 pooka flags = IEEE80211_CHAN_2GHZ;
2862 1.1 pooka channel->ic_flags
2863 1.1 pooka = IEEE80211_CHAN_CCK
2864 1.1 pooka | IEEE80211_CHAN_OFDM
2865 1.1 pooka | IEEE80211_CHAN_DYN
2866 1.1 pooka | IEEE80211_CHAN_2GHZ;
2867 1.1 pooka } else {
2868 1.1 pooka flags = IEEE80211_CHAN_5GHZ;
2869 1.1 pooka channel->ic_flags =
2870 1.1 pooka IEEE80211_CHAN_A;
2871 1.1 pooka }
2872 1.1 pooka channel->ic_freq = ieee80211_ieee2mhz(hw_value, flags);
2873 1.1 pooka
2874 1.1 pooka if (!(ch_flags & IWM_NVM_CHANNEL_ACTIVE))
2875 1.1 pooka channel->ic_flags |= IEEE80211_CHAN_PASSIVE;
2876 1.45 nonaka
2877 1.45 nonaka #ifndef IEEE80211_NO_HT
2878 1.45 nonaka if (data->sku_cap_11n_enable)
2879 1.45 nonaka channel->ic_flags |= IEEE80211_CHAN_HT;
2880 1.45 nonaka #endif
2881 1.45 nonaka }
2882 1.45 nonaka }
2883 1.45 nonaka
2884 1.91 mlelstv static int
2885 1.91 mlelstv iwm_mimo_enabled(struct iwm_softc *sc)
2886 1.91 mlelstv {
2887 1.91 mlelstv #ifndef IEEE80211_NO_HT
2888 1.91 mlelstv struct ieee80211com *ic = &sc->sc_ic;
2889 1.91 mlelstv
2890 1.91 mlelstv return !sc->sc_nvm.sku_cap_mimo_disable &&
2891 1.91 mlelstv (ic->ic_userflags & IEEE80211_F_NOMIMO) == 0;
2892 1.91 mlelstv #else
2893 1.91 mlelstv return 0;
2894 1.91 mlelstv #endif
2895 1.91 mlelstv }
2896 1.91 mlelstv
2897 1.45 nonaka #ifndef IEEE80211_NO_HT
2898 1.45 nonaka static void
2899 1.45 nonaka iwm_setup_ht_rates(struct iwm_softc *sc)
2900 1.45 nonaka {
2901 1.45 nonaka struct ieee80211com *ic = &sc->sc_ic;
2902 1.45 nonaka
2903 1.45 nonaka /* TX is supported with the same MCS as RX. */
2904 1.45 nonaka ic->ic_tx_mcs_set = IEEE80211_TX_MCS_SET_DEFINED;
2905 1.45 nonaka
2906 1.45 nonaka ic->ic_sup_mcs[0] = 0xff; /* MCS 0-7 */
2907 1.45 nonaka
2908 1.45 nonaka #ifdef notyet
2909 1.45 nonaka if (sc->sc_nvm.sku_cap_mimo_disable)
2910 1.45 nonaka return;
2911 1.45 nonaka
2912 1.45 nonaka if (iwm_fw_valid_rx_ant(sc) > 1)
2913 1.45 nonaka ic->ic_sup_mcs[1] = 0xff; /* MCS 8-15 */
2914 1.45 nonaka if (iwm_fw_valid_rx_ant(sc) > 2)
2915 1.45 nonaka ic->ic_sup_mcs[2] = 0xff; /* MCS 16-23 */
2916 1.45 nonaka #endif
2917 1.45 nonaka }
2918 1.45 nonaka
2919 1.45 nonaka #define IWM_MAX_RX_BA_SESSIONS 16
2920 1.45 nonaka
2921 1.45 nonaka static void
2922 1.45 nonaka iwm_sta_rx_agg(struct iwm_softc *sc, struct ieee80211_node *ni, uint8_t tid,
2923 1.45 nonaka uint16_t ssn, int start)
2924 1.45 nonaka {
2925 1.45 nonaka struct ieee80211com *ic = &sc->sc_ic;
2926 1.91 mlelstv struct iwm_add_sta_cmd cmd;
2927 1.45 nonaka struct iwm_node *in = (struct iwm_node *)ni;
2928 1.45 nonaka int err, s;
2929 1.45 nonaka uint32_t status;
2930 1.91 mlelstv size_t cmdsize;
2931 1.91 mlelstv
2932 1.91 mlelstv s = splnet();
2933 1.45 nonaka
2934 1.45 nonaka if (start && sc->sc_rx_ba_sessions >= IWM_MAX_RX_BA_SESSIONS) {
2935 1.45 nonaka ieee80211_addba_req_refuse(ic, ni, tid);
2936 1.91 mlelstv splx(s);
2937 1.45 nonaka return;
2938 1.45 nonaka }
2939 1.45 nonaka
2940 1.45 nonaka memset(&cmd, 0, sizeof(cmd));
2941 1.45 nonaka
2942 1.45 nonaka cmd.sta_id = IWM_STATION_ID;
2943 1.45 nonaka cmd.mac_id_n_color
2944 1.45 nonaka = htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));
2945 1.45 nonaka cmd.add_modify = IWM_STA_MODE_MODIFY;
2946 1.45 nonaka
2947 1.45 nonaka if (start) {
2948 1.45 nonaka cmd.add_immediate_ba_tid = (uint8_t)tid;
2949 1.45 nonaka cmd.add_immediate_ba_ssn = ssn;
2950 1.45 nonaka } else {
2951 1.45 nonaka cmd.remove_immediate_ba_tid = (uint8_t)tid;
2952 1.45 nonaka }
2953 1.45 nonaka cmd.modify_mask = start ? IWM_STA_MODIFY_ADD_BA_TID :
2954 1.45 nonaka IWM_STA_MODIFY_REMOVE_BA_TID;
2955 1.45 nonaka
2956 1.45 nonaka status = IWM_ADD_STA_SUCCESS;
2957 1.91 mlelstv if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE))
2958 1.91 mlelstv cmdsize = sizeof(cmd);
2959 1.91 mlelstv else
2960 1.91 mlelstv cmdsize = sizeof(struct iwm_add_sta_cmd_v7);
2961 1.91 mlelstv err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA, cmdsize, &cmd,
2962 1.45 nonaka &status);
2963 1.91 mlelstv if (!err && (status & IWM_ADD_STA_STATUS_MASK) != IWM_ADD_STA_SUCCESS)
2964 1.91 mlelstv err = EIO;
2965 1.91 mlelstv if (err) {
2966 1.91 mlelstv if (start)
2967 1.91 mlelstv ieee80211_addba_req_refuse(ic, ni, tid);
2968 1.91 mlelstv splx(s);
2969 1.91 mlelstv return err;
2970 1.91 mlelstv }
2971 1.45 nonaka
2972 1.91 mlelstv if (start) {
2973 1.91 mlelstv sc->sc_rx_ba_sessions++;
2974 1.91 mlelstv ieee80211_addba_req_accept(ic, ni, tid);
2975 1.91 mlelstv } else if (sc->sc_rx_ba_sessions > 0)
2976 1.91 mlelstv sc->sc_rx_ba_sessions--;
2977 1.45 nonaka splx(s);
2978 1.45 nonaka }
2979 1.45 nonaka
2980 1.45 nonaka static void
2981 1.45 nonaka iwm_htprot_task(void *arg)
2982 1.45 nonaka {
2983 1.45 nonaka struct iwm_softc *sc = arg;
2984 1.45 nonaka struct ieee80211com *ic = &sc->sc_ic;
2985 1.45 nonaka struct iwm_node *in = (struct iwm_node *)ic->ic_bss;
2986 1.45 nonaka int err;
2987 1.45 nonaka
2988 1.45 nonaka /* This call updates HT protection based on in->in_ni.ni_htop1. */
2989 1.45 nonaka err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY, 1);
2990 1.45 nonaka if (err)
2991 1.45 nonaka aprint_error_dev(sc->sc_dev,
2992 1.45 nonaka "could not change HT protection: error %d\n", err);
2993 1.45 nonaka }
2994 1.45 nonaka
2995 1.45 nonaka /*
2996 1.45 nonaka * This function is called by upper layer when HT protection settings in
2997 1.45 nonaka * beacons have changed.
2998 1.45 nonaka */
2999 1.45 nonaka static void
3000 1.45 nonaka iwm_update_htprot(struct ieee80211com *ic, struct ieee80211_node *ni)
3001 1.45 nonaka {
3002 1.45 nonaka struct iwm_softc *sc = ic->ic_softc;
3003 1.45 nonaka
3004 1.45 nonaka /* assumes that ni == ic->ic_bss */
3005 1.45 nonaka task_add(systq, &sc->htprot_task);
3006 1.45 nonaka }
3007 1.45 nonaka
3008 1.45 nonaka static void
3009 1.45 nonaka iwm_ba_task(void *arg)
3010 1.45 nonaka {
3011 1.45 nonaka struct iwm_softc *sc = arg;
3012 1.45 nonaka struct ieee80211com *ic = &sc->sc_ic;
3013 1.45 nonaka struct ieee80211_node *ni = ic->ic_bss;
3014 1.45 nonaka
3015 1.45 nonaka if (sc->ba_start)
3016 1.45 nonaka iwm_sta_rx_agg(sc, ni, sc->ba_tid, sc->ba_ssn, 1);
3017 1.45 nonaka else
3018 1.45 nonaka iwm_sta_rx_agg(sc, ni, sc->ba_tid, 0, 0);
3019 1.45 nonaka }
3020 1.45 nonaka
3021 1.45 nonaka /*
3022 1.45 nonaka * This function is called by upper layer when an ADDBA request is received
3023 1.45 nonaka * from another STA and before the ADDBA response is sent.
3024 1.45 nonaka */
3025 1.45 nonaka static int
3026 1.45 nonaka iwm_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni,
3027 1.45 nonaka uint8_t tid)
3028 1.45 nonaka {
3029 1.45 nonaka struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];
3030 1.45 nonaka struct iwm_softc *sc = IC2IFP(ic)->if_softc;
3031 1.45 nonaka
3032 1.45 nonaka if (sc->sc_rx_ba_sessions >= IWM_MAX_RX_BA_SESSIONS)
3033 1.45 nonaka return ENOSPC;
3034 1.45 nonaka
3035 1.45 nonaka sc->ba_start = 1;
3036 1.45 nonaka sc->ba_tid = tid;
3037 1.45 nonaka sc->ba_ssn = htole16(ba->ba_winstart);
3038 1.45 nonaka task_add(systq, &sc->ba_task);
3039 1.45 nonaka
3040 1.45 nonaka return EBUSY;
3041 1.45 nonaka }
3042 1.45 nonaka
3043 1.45 nonaka /*
3044 1.45 nonaka * This function is called by upper layer on teardown of an HT-immediate
3045 1.45 nonaka * Block Ack agreement (eg. upon receipt of a DELBA frame).
3046 1.45 nonaka */
3047 1.45 nonaka static void
3048 1.45 nonaka iwm_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni,
3049 1.45 nonaka uint8_t tid)
3050 1.45 nonaka {
3051 1.45 nonaka struct iwm_softc *sc = IC2IFP(ic)->if_softc;
3052 1.45 nonaka
3053 1.45 nonaka sc->ba_start = 0;
3054 1.45 nonaka sc->ba_tid = tid;
3055 1.45 nonaka task_add(systq, &sc->ba_task);
3056 1.45 nonaka }
3057 1.45 nonaka #endif
3058 1.45 nonaka
3059 1.45 nonaka static void
3060 1.71 nonaka iwm_free_fw_paging(struct iwm_softc *sc)
3061 1.71 nonaka {
3062 1.71 nonaka int i;
3063 1.71 nonaka
3064 1.71 nonaka if (sc->fw_paging_db[0].fw_paging_block.vaddr == NULL)
3065 1.71 nonaka return;
3066 1.71 nonaka
3067 1.71 nonaka for (i = 0; i < IWM_NUM_OF_FW_PAGING_BLOCKS; i++) {
3068 1.71 nonaka iwm_dma_contig_free(&sc->fw_paging_db[i].fw_paging_block);
3069 1.71 nonaka }
3070 1.71 nonaka
3071 1.71 nonaka memset(sc->fw_paging_db, 0, sizeof(sc->fw_paging_db));
3072 1.71 nonaka }
3073 1.71 nonaka
3074 1.71 nonaka static int
3075 1.71 nonaka iwm_fill_paging_mem(struct iwm_softc *sc, const struct iwm_fw_sects *fws)
3076 1.71 nonaka {
3077 1.71 nonaka int sec_idx, idx;
3078 1.71 nonaka uint32_t offset = 0;
3079 1.71 nonaka
3080 1.71 nonaka /*
3081 1.71 nonaka * find where is the paging image start point:
3082 1.71 nonaka * if CPU2 exist and it's in paging format, then the image looks like:
3083 1.71 nonaka * CPU1 sections (2 or more)
3084 1.71 nonaka * CPU1_CPU2_SEPARATOR_SECTION delimiter - separate between CPU1 to CPU2
3085 1.71 nonaka * CPU2 sections (not paged)
3086 1.71 nonaka * PAGING_SEPARATOR_SECTION delimiter - separate between CPU2
3087 1.71 nonaka * non paged to CPU2 paging sec
3088 1.71 nonaka * CPU2 paging CSS
3089 1.71 nonaka * CPU2 paging image (including instruction and data)
3090 1.71 nonaka */
3091 1.71 nonaka for (sec_idx = 0; sec_idx < IWM_UCODE_SECT_MAX; sec_idx++) {
3092 1.71 nonaka if (fws->fw_sect[sec_idx].fws_devoff ==
3093 1.71 nonaka IWM_PAGING_SEPARATOR_SECTION) {
3094 1.71 nonaka sec_idx++;
3095 1.71 nonaka break;
3096 1.71 nonaka }
3097 1.71 nonaka }
3098 1.71 nonaka
3099 1.71 nonaka /*
3100 1.71 nonaka * If paging is enabled there should be at least 2 more sections left
3101 1.71 nonaka * (one for CSS and one for Paging data)
3102 1.71 nonaka */
3103 1.71 nonaka if (sec_idx >= __arraycount(fws->fw_sect) - 1) {
3104 1.91 mlelstv aprint_error_dev(sc->sc_dev,
3105 1.71 nonaka "Paging: Missing CSS and/or paging sections\n");
3106 1.71 nonaka iwm_free_fw_paging(sc);
3107 1.71 nonaka return EINVAL;
3108 1.71 nonaka }
3109 1.71 nonaka
3110 1.71 nonaka /* copy the CSS block to the dram */
3111 1.71 nonaka DPRINTF(("%s: Paging: load paging CSS to FW, sec = %d\n", DEVNAME(sc),
3112 1.71 nonaka sec_idx));
3113 1.71 nonaka
3114 1.71 nonaka memcpy(sc->fw_paging_db[0].fw_paging_block.vaddr,
3115 1.71 nonaka fws->fw_sect[sec_idx].fws_data, sc->fw_paging_db[0].fw_paging_size);
3116 1.71 nonaka
3117 1.71 nonaka DPRINTF(("%s: Paging: copied %d CSS bytes to first block\n",
3118 1.71 nonaka DEVNAME(sc), sc->fw_paging_db[0].fw_paging_size));
3119 1.71 nonaka
3120 1.71 nonaka sec_idx++;
3121 1.71 nonaka
3122 1.71 nonaka /*
3123 1.71 nonaka * copy the paging blocks to the dram
3124 1.71 nonaka * loop index start from 1 since that CSS block already copied to dram
3125 1.71 nonaka * and CSS index is 0.
3126 1.71 nonaka * loop stop at num_of_paging_blk since that last block is not full.
3127 1.71 nonaka */
3128 1.71 nonaka for (idx = 1; idx < sc->num_of_paging_blk; idx++) {
3129 1.71 nonaka memcpy(sc->fw_paging_db[idx].fw_paging_block.vaddr,
3130 1.71 nonaka (const char *)fws->fw_sect[sec_idx].fws_data + offset,
3131 1.71 nonaka sc->fw_paging_db[idx].fw_paging_size);
3132 1.71 nonaka
3133 1.71 nonaka DPRINTF(("%s: Paging: copied %d paging bytes to block %d\n",
3134 1.71 nonaka DEVNAME(sc), sc->fw_paging_db[idx].fw_paging_size, idx));
3135 1.71 nonaka
3136 1.71 nonaka offset += sc->fw_paging_db[idx].fw_paging_size;
3137 1.71 nonaka }
3138 1.71 nonaka
3139 1.71 nonaka /* copy the last paging block */
3140 1.71 nonaka if (sc->num_of_pages_in_last_blk > 0) {
3141 1.71 nonaka memcpy(sc->fw_paging_db[idx].fw_paging_block.vaddr,
3142 1.71 nonaka (const char *)fws->fw_sect[sec_idx].fws_data + offset,
3143 1.71 nonaka IWM_FW_PAGING_SIZE * sc->num_of_pages_in_last_blk);
3144 1.71 nonaka
3145 1.71 nonaka DPRINTF(("%s: Paging: copied %d pages in the last block %d\n",
3146 1.71 nonaka DEVNAME(sc), sc->num_of_pages_in_last_blk, idx));
3147 1.71 nonaka }
3148 1.71 nonaka
3149 1.71 nonaka return 0;
3150 1.71 nonaka }
3151 1.71 nonaka
3152 1.71 nonaka static int
3153 1.71 nonaka iwm_alloc_fw_paging_mem(struct iwm_softc *sc, const struct iwm_fw_sects *fws)
3154 1.71 nonaka {
3155 1.71 nonaka int blk_idx = 0;
3156 1.71 nonaka int error, num_of_pages;
3157 1.71 nonaka bus_dmamap_t dmap;
3158 1.71 nonaka
3159 1.71 nonaka if (sc->fw_paging_db[0].fw_paging_block.vaddr != NULL) {
3160 1.71 nonaka int i;
3161 1.71 nonaka /* Device got reset, and we setup firmware paging again */
3162 1.91 mlelstv bus_dmamap_sync(sc->sc_dmat,
3163 1.91 mlelstv sc->fw_paging_db[0].fw_paging_block.map,
3164 1.91 mlelstv 0, IWM_FW_PAGING_SIZE,
3165 1.91 mlelstv BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
3166 1.71 nonaka for (i = 0; i < sc->num_of_paging_blk + 1; i++) {
3167 1.71 nonaka dmap = sc->fw_paging_db[i].fw_paging_block.map;
3168 1.71 nonaka bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
3169 1.71 nonaka BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
3170 1.71 nonaka }
3171 1.71 nonaka return 0;
3172 1.71 nonaka }
3173 1.71 nonaka
3174 1.71 nonaka /* ensure IWM_BLOCK_2_EXP_SIZE is power of 2 of IWM_PAGING_BLOCK_SIZE */
3175 1.71 nonaka CTASSERT(__BIT(IWM_BLOCK_2_EXP_SIZE) == IWM_PAGING_BLOCK_SIZE);
3176 1.71 nonaka
3177 1.71 nonaka num_of_pages = fws->paging_mem_size / IWM_FW_PAGING_SIZE;
3178 1.71 nonaka sc->num_of_paging_blk =
3179 1.91 mlelstv ((num_of_pages - 1) / IWM_NUM_OF_PAGE_PER_GROUP) + 1;
3180 1.91 mlelstv
3181 1.91 mlelstv sc->num_of_pages_in_last_blk =
3182 1.91 mlelstv num_of_pages -
3183 1.71 nonaka IWM_NUM_OF_PAGE_PER_GROUP * (sc->num_of_paging_blk - 1);
3184 1.71 nonaka
3185 1.71 nonaka DPRINTF(("%s: Paging: allocating mem for %d paging blocks, "
3186 1.71 nonaka "each block holds 8 pages, last block holds %d pages\n",
3187 1.71 nonaka DEVNAME(sc), sc->num_of_paging_blk, sc->num_of_pages_in_last_blk));
3188 1.71 nonaka
3189 1.71 nonaka /* allocate block of 4Kbytes for paging CSS */
3190 1.71 nonaka error = iwm_dma_contig_alloc(sc->sc_dmat,
3191 1.71 nonaka &sc->fw_paging_db[blk_idx].fw_paging_block, IWM_FW_PAGING_SIZE,
3192 1.71 nonaka 4096);
3193 1.71 nonaka if (error) {
3194 1.71 nonaka /* free all the previous pages since we failed */
3195 1.71 nonaka iwm_free_fw_paging(sc);
3196 1.71 nonaka return ENOMEM;
3197 1.71 nonaka }
3198 1.71 nonaka
3199 1.71 nonaka sc->fw_paging_db[blk_idx].fw_paging_size = IWM_FW_PAGING_SIZE;
3200 1.71 nonaka
3201 1.71 nonaka DPRINTF(("%s: Paging: allocated 4K(CSS) bytes for firmware paging.\n",
3202 1.71 nonaka DEVNAME(sc)));
3203 1.71 nonaka
3204 1.71 nonaka /*
3205 1.71 nonaka * allocate blocks in dram.
3206 1.71 nonaka * since that CSS allocated in fw_paging_db[0] loop start from index 1
3207 1.71 nonaka */
3208 1.71 nonaka for (blk_idx = 1; blk_idx < sc->num_of_paging_blk + 1; blk_idx++) {
3209 1.71 nonaka /* allocate block of IWM_PAGING_BLOCK_SIZE (32K) */
3210 1.71 nonaka /* XXX Use iwm_dma_contig_alloc for allocating */
3211 1.71 nonaka error = iwm_dma_contig_alloc(sc->sc_dmat,
3212 1.71 nonaka &sc->fw_paging_db[blk_idx].fw_paging_block,
3213 1.71 nonaka IWM_PAGING_BLOCK_SIZE, 4096);
3214 1.71 nonaka if (error) {
3215 1.71 nonaka /* free all the previous pages since we failed */
3216 1.71 nonaka iwm_free_fw_paging(sc);
3217 1.71 nonaka return ENOMEM;
3218 1.71 nonaka }
3219 1.71 nonaka
3220 1.71 nonaka sc->fw_paging_db[blk_idx].fw_paging_size =
3221 1.71 nonaka IWM_PAGING_BLOCK_SIZE;
3222 1.71 nonaka
3223 1.71 nonaka DPRINTF(("%s: Paging: allocated 32K bytes for firmware "
3224 1.71 nonaka "paging.\n", DEVNAME(sc)));
3225 1.71 nonaka }
3226 1.71 nonaka
3227 1.71 nonaka return 0;
3228 1.71 nonaka }
3229 1.71 nonaka
3230 1.71 nonaka static int
3231 1.71 nonaka iwm_save_fw_paging(struct iwm_softc *sc, const struct iwm_fw_sects *fws)
3232 1.71 nonaka {
3233 1.71 nonaka int err;
3234 1.71 nonaka
3235 1.71 nonaka err = iwm_alloc_fw_paging_mem(sc, fws);
3236 1.71 nonaka if (err)
3237 1.71 nonaka return err;
3238 1.71 nonaka
3239 1.71 nonaka return iwm_fill_paging_mem(sc, fws);
3240 1.71 nonaka }
3241 1.71 nonaka
3242 1.71 nonaka static bool
3243 1.71 nonaka iwm_has_new_tx_api(struct iwm_softc *sc)
3244 1.71 nonaka {
3245 1.71 nonaka /* XXX */
3246 1.71 nonaka return false;
3247 1.71 nonaka }
3248 1.71 nonaka
3249 1.71 nonaka /* send paging cmd to FW in case CPU2 has paging image */
3250 1.71 nonaka static int
3251 1.71 nonaka iwm_send_paging_cmd(struct iwm_softc *sc, const struct iwm_fw_sects *fws)
3252 1.71 nonaka {
3253 1.71 nonaka struct iwm_fw_paging_cmd fw_paging_cmd = {
3254 1.71 nonaka .flags = htole32(IWM_PAGING_CMD_IS_SECURED |
3255 1.71 nonaka IWM_PAGING_CMD_IS_ENABLED |
3256 1.71 nonaka (sc->num_of_pages_in_last_blk <<
3257 1.71 nonaka IWM_PAGING_CMD_NUM_OF_PAGES_IN_LAST_GRP_POS)),
3258 1.71 nonaka .block_size = htole32(IWM_BLOCK_2_EXP_SIZE),
3259 1.71 nonaka .block_num = htole32(sc->num_of_paging_blk),
3260 1.71 nonaka };
3261 1.71 nonaka size_t size = sizeof(fw_paging_cmd);
3262 1.71 nonaka int blk_idx;
3263 1.71 nonaka bus_dmamap_t dmap;
3264 1.71 nonaka
3265 1.71 nonaka if (!iwm_has_new_tx_api(sc))
3266 1.71 nonaka size -= (sizeof(uint64_t) - sizeof(uint32_t)) *
3267 1.71 nonaka IWM_NUM_OF_FW_PAGING_BLOCKS;
3268 1.71 nonaka
3269 1.88 msaitoh /* loop for all paging blocks + CSS block */
3270 1.71 nonaka for (blk_idx = 0; blk_idx < sc->num_of_paging_blk + 1; blk_idx++) {
3271 1.71 nonaka bus_addr_t dev_phy_addr =
3272 1.71 nonaka sc->fw_paging_db[blk_idx].fw_paging_block.paddr;
3273 1.71 nonaka if (iwm_has_new_tx_api(sc)) {
3274 1.71 nonaka fw_paging_cmd.device_phy_addr.addr64[blk_idx] =
3275 1.71 nonaka htole64(dev_phy_addr);
3276 1.71 nonaka } else {
3277 1.71 nonaka dev_phy_addr = dev_phy_addr >> IWM_PAGE_2_EXP_SIZE;
3278 1.71 nonaka fw_paging_cmd.device_phy_addr.addr32[blk_idx] =
3279 1.71 nonaka htole32(dev_phy_addr);
3280 1.71 nonaka }
3281 1.74 nonaka dmap = sc->fw_paging_db[blk_idx].fw_paging_block.map;
3282 1.91 mlelstv bus_dmamap_sync(sc->sc_dmat, dmap, 0,
3283 1.91 mlelstv blk_idx == 0 ? IWM_FW_PAGING_SIZE : IWM_PAGING_BLOCK_SIZE,
3284 1.71 nonaka BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
3285 1.71 nonaka }
3286 1.71 nonaka
3287 1.71 nonaka return iwm_send_cmd_pdu(sc,
3288 1.91 mlelstv iwm_cmd_id(IWM_FW_PAGING_BLOCK_CMD, IWM_LONG_GROUP, 0),
3289 1.71 nonaka 0, size, &fw_paging_cmd);
3290 1.71 nonaka }
3291 1.71 nonaka
3292 1.71 nonaka static void
3293 1.45 nonaka iwm_set_hw_address_8000(struct iwm_softc *sc, struct iwm_nvm_data *data,
3294 1.45 nonaka const uint16_t *mac_override, const uint16_t *nvm_hw)
3295 1.45 nonaka {
3296 1.45 nonaka static const uint8_t reserved_mac[ETHER_ADDR_LEN] = {
3297 1.45 nonaka 0x02, 0xcc, 0xaa, 0xff, 0xee, 0x00
3298 1.45 nonaka };
3299 1.45 nonaka const uint8_t *hw_addr;
3300 1.45 nonaka
3301 1.45 nonaka if (mac_override) {
3302 1.45 nonaka hw_addr = (const uint8_t *)(mac_override +
3303 1.45 nonaka IWM_MAC_ADDRESS_OVERRIDE_8000);
3304 1.45 nonaka
3305 1.45 nonaka /*
3306 1.45 nonaka * Store the MAC address from MAO section.
3307 1.45 nonaka * No byte swapping is required in MAO section
3308 1.45 nonaka */
3309 1.45 nonaka memcpy(data->hw_addr, hw_addr, ETHER_ADDR_LEN);
3310 1.45 nonaka
3311 1.45 nonaka /*
3312 1.45 nonaka * Force the use of the OTP MAC address in case of reserved MAC
3313 1.45 nonaka * address in the NVM, or if address is given but invalid.
3314 1.45 nonaka */
3315 1.45 nonaka if (memcmp(reserved_mac, hw_addr, ETHER_ADDR_LEN) != 0 &&
3316 1.45 nonaka (memcmp(etherbroadcastaddr, data->hw_addr,
3317 1.45 nonaka sizeof(etherbroadcastaddr)) != 0) &&
3318 1.45 nonaka (memcmp(etheranyaddr, data->hw_addr,
3319 1.45 nonaka sizeof(etheranyaddr)) != 0) &&
3320 1.45 nonaka !ETHER_IS_MULTICAST(data->hw_addr))
3321 1.45 nonaka return;
3322 1.45 nonaka }
3323 1.45 nonaka
3324 1.45 nonaka if (nvm_hw) {
3325 1.45 nonaka /* Read the mac address from WFMP registers. */
3326 1.91 mlelstv uint32_t mac_addr0, mac_addr1;
3327 1.91 mlelstv
3328 1.91 mlelstv if (!iwm_nic_lock(sc))
3329 1.91 mlelstv goto out;
3330 1.91 mlelstv mac_addr0 = htole32(iwm_read_prph(sc, IWM_WFMP_MAC_ADDR_0));
3331 1.91 mlelstv mac_addr1 = htole32(iwm_read_prph(sc, IWM_WFMP_MAC_ADDR_1));
3332 1.91 mlelstv iwm_nic_unlock(sc);
3333 1.45 nonaka
3334 1.45 nonaka hw_addr = (const uint8_t *)&mac_addr0;
3335 1.45 nonaka data->hw_addr[0] = hw_addr[3];
3336 1.45 nonaka data->hw_addr[1] = hw_addr[2];
3337 1.45 nonaka data->hw_addr[2] = hw_addr[1];
3338 1.45 nonaka data->hw_addr[3] = hw_addr[0];
3339 1.45 nonaka
3340 1.45 nonaka hw_addr = (const uint8_t *)&mac_addr1;
3341 1.45 nonaka data->hw_addr[4] = hw_addr[1];
3342 1.45 nonaka data->hw_addr[5] = hw_addr[0];
3343 1.45 nonaka
3344 1.45 nonaka return;
3345 1.1 pooka }
3346 1.91 mlelstv out:
3347 1.45 nonaka aprint_error_dev(sc->sc_dev, "mac address not found\n");
3348 1.45 nonaka memset(data->hw_addr, 0, sizeof(data->hw_addr));
3349 1.1 pooka }
3350 1.1 pooka
3351 1.4 nonaka static int
3352 1.45 nonaka iwm_parse_nvm_data(struct iwm_softc *sc, const uint16_t *nvm_hw,
3353 1.45 nonaka const uint16_t *nvm_sw, const uint16_t *nvm_calib,
3354 1.45 nonaka const uint16_t *mac_override, const uint16_t *phy_sku,
3355 1.91 mlelstv const uint16_t *regulatory, int n_regulatory)
3356 1.1 pooka {
3357 1.1 pooka struct iwm_nvm_data *data = &sc->sc_nvm;
3358 1.1 pooka uint8_t hw_addr[ETHER_ADDR_LEN];
3359 1.45 nonaka uint32_t sku;
3360 1.1 pooka
3361 1.45 nonaka if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
3362 1.45 nonaka uint16_t radio_cfg = le16_to_cpup(nvm_sw + IWM_RADIO_CFG);
3363 1.45 nonaka data->radio_cfg_type = IWM_NVM_RF_CFG_TYPE_MSK(radio_cfg);
3364 1.45 nonaka data->radio_cfg_step = IWM_NVM_RF_CFG_STEP_MSK(radio_cfg);
3365 1.45 nonaka data->radio_cfg_dash = IWM_NVM_RF_CFG_DASH_MSK(radio_cfg);
3366 1.45 nonaka data->radio_cfg_pnum = IWM_NVM_RF_CFG_PNUM_MSK(radio_cfg);
3367 1.45 nonaka
3368 1.61 nonaka data->nvm_version = le16_to_cpup(nvm_sw + IWM_NVM_VERSION);
3369 1.45 nonaka sku = le16_to_cpup(nvm_sw + IWM_SKU);
3370 1.45 nonaka } else {
3371 1.61 nonaka uint32_t radio_cfg = le32_to_cpup(phy_sku + IWM_RADIO_CFG_8000);
3372 1.45 nonaka data->radio_cfg_type = IWM_NVM_RF_CFG_TYPE_MSK_8000(radio_cfg);
3373 1.45 nonaka data->radio_cfg_step = IWM_NVM_RF_CFG_STEP_MSK_8000(radio_cfg);
3374 1.45 nonaka data->radio_cfg_dash = IWM_NVM_RF_CFG_DASH_MSK_8000(radio_cfg);
3375 1.45 nonaka data->radio_cfg_pnum = IWM_NVM_RF_CFG_PNUM_MSK_8000(radio_cfg);
3376 1.45 nonaka data->valid_tx_ant = IWM_NVM_RF_CFG_TX_ANT_MSK_8000(radio_cfg);
3377 1.45 nonaka data->valid_rx_ant = IWM_NVM_RF_CFG_RX_ANT_MSK_8000(radio_cfg);
3378 1.45 nonaka
3379 1.91 mlelstv data->nvm_version = le16_to_cpup(nvm_sw + IWM_NVM_VERSION_8000);
3380 1.61 nonaka sku = le32_to_cpup(phy_sku + IWM_SKU_8000);
3381 1.45 nonaka }
3382 1.1 pooka
3383 1.1 pooka data->sku_cap_band_24GHz_enable = sku & IWM_NVM_SKU_CAP_BAND_24GHZ;
3384 1.1 pooka data->sku_cap_band_52GHz_enable = sku & IWM_NVM_SKU_CAP_BAND_52GHZ;
3385 1.45 nonaka data->sku_cap_11n_enable = sku & IWM_NVM_SKU_CAP_11N_ENABLE;
3386 1.91 mlelstv data->sku_cap_11ac_enable = sku & IWM_NVM_SKU_CAP_11AC_ENABLE;
3387 1.45 nonaka data->sku_cap_mimo_disable = sku & IWM_NVM_SKU_CAP_MIMO_DISABLE;
3388 1.1 pooka
3389 1.91 mlelstv if (sc->sc_device_family >= IWM_DEVICE_FAMILY_8000) {
3390 1.91 mlelstv #if 0
3391 1.91 mlelstv uint16_t lar_offset = data->nvm_version < 0xE39 ?
3392 1.91 mlelstv IWM_NVM_LAR_OFFSET_8000_OLD :
3393 1.91 mlelstv IWM_NVM_LAR_OFFSET_8000;
3394 1.91 mlelstv uint16_t lar_config;
3395 1.91 mlelstv
3396 1.91 mlelstv lar_config = le16_to_cpup(regulatory + lar_offset);
3397 1.91 mlelstv data->lar_enabled = !!(lar_config &
3398 1.91 mlelstv IWM_NVM_LAR_ENABLED_8000);
3399 1.91 mlelstv #else
3400 1.91 mlelstv data->lar_enabled = 0;
3401 1.91 mlelstv #endif
3402 1.91 mlelstv data->n_hw_addrs = le16_to_cpup(nvm_sw + IWM_N_HW_ADDRS_8000);
3403 1.91 mlelstv } else
3404 1.91 mlelstv data->n_hw_addrs = le16_to_cpup(nvm_sw + IWM_N_HW_ADDRS);
3405 1.1 pooka
3406 1.91 mlelstv /* The byte order is little endian 16 bit, meaning 214365 */
3407 1.45 nonaka if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
3408 1.45 nonaka memcpy(hw_addr, nvm_hw + IWM_HW_ADDR, ETHER_ADDR_LEN);
3409 1.45 nonaka data->hw_addr[0] = hw_addr[1];
3410 1.45 nonaka data->hw_addr[1] = hw_addr[0];
3411 1.45 nonaka data->hw_addr[2] = hw_addr[3];
3412 1.45 nonaka data->hw_addr[3] = hw_addr[2];
3413 1.45 nonaka data->hw_addr[4] = hw_addr[5];
3414 1.45 nonaka data->hw_addr[5] = hw_addr[4];
3415 1.45 nonaka } else
3416 1.45 nonaka iwm_set_hw_address_8000(sc, data, mac_override, nvm_hw);
3417 1.1 pooka
3418 1.91 mlelstv if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
3419 1.91 mlelstv if (sc->nvm_type == IWM_NVM_SDP) {
3420 1.91 mlelstv iwm_init_channel_map(sc, regulatory, iwm_nvm_channels,
3421 1.91 mlelstv MIN(n_regulatory, __arraycount(iwm_nvm_channels)));
3422 1.91 mlelstv } else {
3423 1.91 mlelstv iwm_init_channel_map(sc, &nvm_sw[IWM_NVM_CHANNELS],
3424 1.91 mlelstv iwm_nvm_channels, __arraycount(iwm_nvm_channels));
3425 1.91 mlelstv }
3426 1.91 mlelstv } else
3427 1.45 nonaka iwm_init_channel_map(sc, ®ulatory[IWM_NVM_CHANNELS_8000],
3428 1.91 mlelstv iwm_nvm_channels_8000,
3429 1.91 mlelstv MIN(n_regulatory, __arraycount(iwm_nvm_channels_8000)));
3430 1.1 pooka
3431 1.1 pooka data->calib_version = 255; /* TODO:
3432 1.1 pooka this value will prevent some checks from
3433 1.1 pooka failing, we need to check if this
3434 1.1 pooka field is still needed, and if it does,
3435 1.1 pooka where is it in the NVM */
3436 1.1 pooka
3437 1.1 pooka return 0;
3438 1.1 pooka }
3439 1.1 pooka
3440 1.1 pooka static int
3441 1.1 pooka iwm_parse_nvm_sections(struct iwm_softc *sc, struct iwm_nvm_section *sections)
3442 1.1 pooka {
3443 1.45 nonaka const uint16_t *hw, *sw, *calib, *mac_override = NULL, *phy_sku = NULL;
3444 1.45 nonaka const uint16_t *regulatory = NULL;
3445 1.91 mlelstv int n_regulatory = 0;
3446 1.1 pooka
3447 1.1 pooka /* Checking for required sections */
3448 1.45 nonaka if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
3449 1.45 nonaka if (!sections[IWM_NVM_SECTION_TYPE_SW].data ||
3450 1.45 nonaka !sections[IWM_NVM_SECTION_TYPE_HW].data) {
3451 1.45 nonaka return ENOENT;
3452 1.45 nonaka }
3453 1.45 nonaka
3454 1.45 nonaka hw = (const uint16_t *) sections[IWM_NVM_SECTION_TYPE_HW].data;
3455 1.91 mlelstv
3456 1.91 mlelstv if (sc->nvm_type == IWM_NVM_SDP) {
3457 1.91 mlelstv if (!sections[IWM_NVM_SECTION_TYPE_REGULATORY_SDP].data)
3458 1.91 mlelstv return ENOENT;
3459 1.91 mlelstv regulatory = (const uint16_t *)
3460 1.91 mlelstv sections[IWM_NVM_SECTION_TYPE_REGULATORY_SDP].data;
3461 1.91 mlelstv n_regulatory =
3462 1.91 mlelstv sections[IWM_NVM_SECTION_TYPE_REGULATORY_SDP].length
3463 1.91 mlelstv ;
3464 1.91 mlelstv }
3465 1.45 nonaka } else if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000) {
3466 1.45 nonaka /* SW and REGULATORY sections are mandatory */
3467 1.45 nonaka if (!sections[IWM_NVM_SECTION_TYPE_SW].data ||
3468 1.45 nonaka !sections[IWM_NVM_SECTION_TYPE_REGULATORY].data) {
3469 1.45 nonaka return ENOENT;
3470 1.45 nonaka }
3471 1.45 nonaka /* MAC_OVERRIDE or at least HW section must exist */
3472 1.45 nonaka if (!sections[IWM_NVM_SECTION_TYPE_HW_8000].data &&
3473 1.45 nonaka !sections[IWM_NVM_SECTION_TYPE_MAC_OVERRIDE].data) {
3474 1.45 nonaka return ENOENT;
3475 1.45 nonaka }
3476 1.45 nonaka
3477 1.45 nonaka /* PHY_SKU section is mandatory in B0 */
3478 1.45 nonaka if (!sections[IWM_NVM_SECTION_TYPE_PHY_SKU].data) {
3479 1.45 nonaka return ENOENT;
3480 1.45 nonaka }
3481 1.45 nonaka
3482 1.45 nonaka regulatory = (const uint16_t *)
3483 1.45 nonaka sections[IWM_NVM_SECTION_TYPE_REGULATORY].data;
3484 1.91 mlelstv n_regulatory = sections[IWM_NVM_SECTION_TYPE_REGULATORY].length;
3485 1.45 nonaka hw = (const uint16_t *)
3486 1.45 nonaka sections[IWM_NVM_SECTION_TYPE_HW_8000].data;
3487 1.45 nonaka mac_override =
3488 1.45 nonaka (const uint16_t *)
3489 1.45 nonaka sections[IWM_NVM_SECTION_TYPE_MAC_OVERRIDE].data;
3490 1.45 nonaka phy_sku = (const uint16_t *)
3491 1.45 nonaka sections[IWM_NVM_SECTION_TYPE_PHY_SKU].data;
3492 1.45 nonaka } else {
3493 1.45 nonaka panic("unknown device family %d\n", sc->sc_device_family);
3494 1.1 pooka }
3495 1.1 pooka
3496 1.1 pooka sw = (const uint16_t *)sections[IWM_NVM_SECTION_TYPE_SW].data;
3497 1.45 nonaka calib = (const uint16_t *)
3498 1.45 nonaka sections[IWM_NVM_SECTION_TYPE_CALIBRATION].data;
3499 1.45 nonaka
3500 1.45 nonaka return iwm_parse_nvm_data(sc, hw, sw, calib, mac_override,
3501 1.91 mlelstv phy_sku, regulatory, n_regulatory);
3502 1.1 pooka }
3503 1.1 pooka
3504 1.4 nonaka static int
3505 1.1 pooka iwm_nvm_init(struct iwm_softc *sc)
3506 1.1 pooka {
3507 1.1 pooka struct iwm_nvm_section nvm_sections[IWM_NVM_NUM_OF_SECTIONS];
3508 1.45 nonaka int i, section, err;
3509 1.1 pooka uint16_t len;
3510 1.45 nonaka uint8_t *buf;
3511 1.61 nonaka const size_t bufsz = (sc->sc_device_family == IWM_DEVICE_FAMILY_8000) ?
3512 1.61 nonaka IWM_MAX_NVM_SECTION_SIZE_8000 : IWM_MAX_NVM_SECTION_SIZE_7000;
3513 1.1 pooka
3514 1.1 pooka /* Read From FW NVM */
3515 1.1 pooka DPRINTF(("Read NVM\n"));
3516 1.1 pooka
3517 1.45 nonaka memset(nvm_sections, 0, sizeof(nvm_sections));
3518 1.45 nonaka
3519 1.45 nonaka buf = kmem_alloc(bufsz, KM_SLEEP);
3520 1.45 nonaka
3521 1.45 nonaka for (i = 0; i < __arraycount(iwm_nvm_to_read); i++) {
3522 1.45 nonaka section = iwm_nvm_to_read[i];
3523 1.91 mlelstv KASSERT(section < IWM_NVM_NUM_OF_SECTIONS);
3524 1.45 nonaka
3525 1.45 nonaka err = iwm_nvm_read_section(sc, section, buf, &len, bufsz);
3526 1.45 nonaka if (err) {
3527 1.45 nonaka err = 0;
3528 1.45 nonaka continue;
3529 1.45 nonaka }
3530 1.45 nonaka nvm_sections[section].data = kmem_alloc(len, KM_SLEEP);
3531 1.45 nonaka memcpy(nvm_sections[section].data, buf, len);
3532 1.45 nonaka nvm_sections[section].length = len;
3533 1.45 nonaka }
3534 1.45 nonaka kmem_free(buf, bufsz);
3535 1.91 mlelstv err = iwm_parse_nvm_sections(sc, nvm_sections);
3536 1.1 pooka
3537 1.45 nonaka for (i = 0; i < IWM_NVM_NUM_OF_SECTIONS; i++) {
3538 1.45 nonaka if (nvm_sections[i].data != NULL)
3539 1.45 nonaka kmem_free(nvm_sections[i].data, nvm_sections[i].length);
3540 1.1 pooka }
3541 1.1 pooka
3542 1.45 nonaka return err;
3543 1.1 pooka }
3544 1.1 pooka
3545 1.45 nonaka static int
3546 1.45 nonaka iwm_firmware_load_sect(struct iwm_softc *sc, uint32_t dst_addr,
3547 1.45 nonaka const uint8_t *section, uint32_t byte_cnt)
3548 1.45 nonaka {
3549 1.45 nonaka int err = EINVAL;
3550 1.45 nonaka uint32_t chunk_sz, offset;
3551 1.45 nonaka
3552 1.45 nonaka chunk_sz = MIN(IWM_FH_MEM_TB_MAX_LENGTH, byte_cnt);
3553 1.45 nonaka
3554 1.45 nonaka for (offset = 0; offset < byte_cnt; offset += chunk_sz) {
3555 1.45 nonaka uint32_t addr, len;
3556 1.45 nonaka const uint8_t *data;
3557 1.45 nonaka
3558 1.45 nonaka addr = dst_addr + offset;
3559 1.45 nonaka len = MIN(chunk_sz, byte_cnt - offset);
3560 1.45 nonaka data = section + offset;
3561 1.45 nonaka
3562 1.45 nonaka err = iwm_firmware_load_chunk(sc, addr, data, len);
3563 1.45 nonaka if (err)
3564 1.45 nonaka break;
3565 1.45 nonaka }
3566 1.45 nonaka
3567 1.45 nonaka return err;
3568 1.45 nonaka }
3569 1.1 pooka
3570 1.4 nonaka static int
3571 1.1 pooka iwm_firmware_load_chunk(struct iwm_softc *sc, uint32_t dst_addr,
3572 1.45 nonaka const uint8_t *section, uint32_t byte_cnt)
3573 1.1 pooka {
3574 1.1 pooka struct iwm_dma_info *dma = &sc->fw_dma;
3575 1.45 nonaka int err;
3576 1.1 pooka
3577 1.45 nonaka /* Copy firmware chunk into pre-allocated DMA-safe memory. */
3578 1.1 pooka memcpy(dma->vaddr, section, byte_cnt);
3579 1.45 nonaka bus_dmamap_sync(sc->sc_dmat, dma->map, 0, byte_cnt,
3580 1.45 nonaka BUS_DMASYNC_PREWRITE);
3581 1.1 pooka
3582 1.91 mlelstv if (dst_addr >= IWM_FW_MEM_EXTENDED_START &&
3583 1.91 mlelstv dst_addr <= IWM_FW_MEM_EXTENDED_END) {
3584 1.91 mlelstv err = iwm_set_bits_prph(sc, IWM_LMPM_CHICK,
3585 1.91 mlelstv IWM_LMPM_CHICK_EXTENDED_ADDR_SPACE);
3586 1.91 mlelstv if (err)
3587 1.91 mlelstv goto done;
3588 1.91 mlelstv }
3589 1.91 mlelstv
3590 1.1 pooka sc->sc_fw_chunk_done = 0;
3591 1.1 pooka
3592 1.91 mlelstv if (!iwm_nic_lock(sc)) {
3593 1.91 mlelstv err = EBUSY;
3594 1.91 mlelstv goto done;
3595 1.91 mlelstv }
3596 1.45 nonaka
3597 1.1 pooka IWM_WRITE(sc, IWM_FH_TCSR_CHNL_TX_CONFIG_REG(IWM_FH_SRVC_CHNL),
3598 1.1 pooka IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE);
3599 1.1 pooka IWM_WRITE(sc, IWM_FH_SRVC_CHNL_SRAM_ADDR_REG(IWM_FH_SRVC_CHNL),
3600 1.1 pooka dst_addr);
3601 1.1 pooka IWM_WRITE(sc, IWM_FH_TFDIB_CTRL0_REG(IWM_FH_SRVC_CHNL),
3602 1.1 pooka dma->paddr & IWM_FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK);
3603 1.1 pooka IWM_WRITE(sc, IWM_FH_TFDIB_CTRL1_REG(IWM_FH_SRVC_CHNL),
3604 1.8 nonaka (iwm_get_dma_hi_addr(dma->paddr)
3605 1.1 pooka << IWM_FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt);
3606 1.1 pooka IWM_WRITE(sc, IWM_FH_TCSR_CHNL_TX_BUF_STS_REG(IWM_FH_SRVC_CHNL),
3607 1.1 pooka 1 << IWM_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM |
3608 1.1 pooka 1 << IWM_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX |
3609 1.1 pooka IWM_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID);
3610 1.1 pooka IWM_WRITE(sc, IWM_FH_TCSR_CHNL_TX_CONFIG_REG(IWM_FH_SRVC_CHNL),
3611 1.1 pooka IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
3612 1.1 pooka IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE |
3613 1.1 pooka IWM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
3614 1.8 nonaka
3615 1.1 pooka iwm_nic_unlock(sc);
3616 1.1 pooka
3617 1.45 nonaka /* Wait for this segment to load. */
3618 1.45 nonaka err = 0;
3619 1.45 nonaka while (!sc->sc_fw_chunk_done) {
3620 1.91 mlelstv err = tsleep(&sc->sc_fw, 0, "iwmfw", mstohz(1000));
3621 1.45 nonaka if (err)
3622 1.1 pooka break;
3623 1.45 nonaka }
3624 1.45 nonaka if (!sc->sc_fw_chunk_done) {
3625 1.61 nonaka DPRINTF(("%s: fw chunk addr 0x%x len %d failed to load\n",
3626 1.61 nonaka DEVNAME(sc), dst_addr, byte_cnt));
3627 1.45 nonaka }
3628 1.1 pooka
3629 1.91 mlelstv if (dst_addr >= IWM_FW_MEM_EXTENDED_START &&
3630 1.91 mlelstv dst_addr <= IWM_FW_MEM_EXTENDED_END) {
3631 1.91 mlelstv int err2 = iwm_clear_bits_prph(sc, IWM_LMPM_CHICK,
3632 1.91 mlelstv IWM_LMPM_CHICK_EXTENDED_ADDR_SPACE);
3633 1.91 mlelstv if (!err)
3634 1.91 mlelstv err = err2;
3635 1.91 mlelstv }
3636 1.91 mlelstv
3637 1.91 mlelstv done:
3638 1.91 mlelstv bus_dmamap_sync(sc->sc_dmat, dma->map, 0, byte_cnt,
3639 1.91 mlelstv BUS_DMASYNC_POSTWRITE);
3640 1.91 mlelstv
3641 1.45 nonaka return err;
3642 1.1 pooka }
3643 1.1 pooka
3644 1.4 nonaka static int
3645 1.91 mlelstv iwm_load_firmware_7000(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
3646 1.1 pooka {
3647 1.91 mlelstv struct iwm_fw_sects *fws;
3648 1.91 mlelstv int err, i;
3649 1.1 pooka void *data;
3650 1.1 pooka uint32_t dlen;
3651 1.1 pooka uint32_t offset;
3652 1.1 pooka
3653 1.91 mlelstv fws = &sc->sc_fw.fw_sects[ucode_type];
3654 1.91 mlelstv for (i = 0; i < fws->fw_count; i++) {
3655 1.1 pooka data = fws->fw_sect[i].fws_data;
3656 1.1 pooka dlen = fws->fw_sect[i].fws_len;
3657 1.1 pooka offset = fws->fw_sect[i].fws_devoff;
3658 1.45 nonaka if (dlen > sc->sc_fwdmasegsz) {
3659 1.45 nonaka err = EFBIG;
3660 1.45 nonaka } else
3661 1.45 nonaka err = iwm_firmware_load_sect(sc, offset, data, dlen);
3662 1.45 nonaka if (err) {
3663 1.91 mlelstv printf("%s: could not load firmware chunk %u of %u"
3664 1.91 mlelstv " (error %d)\n",DEVNAME(sc), i, fws->fw_count, err);
3665 1.45 nonaka return err;
3666 1.1 pooka }
3667 1.1 pooka }
3668 1.1 pooka
3669 1.91 mlelstv iwm_enable_interrupts(sc);
3670 1.71 nonaka
3671 1.71 nonaka /* release CPU reset */
3672 1.1 pooka IWM_WRITE(sc, IWM_CSR_RESET, 0);
3673 1.1 pooka
3674 1.45 nonaka return 0;
3675 1.1 pooka }
3676 1.1 pooka
3677 1.4 nonaka static int
3678 1.45 nonaka iwm_load_cpu_sections_8000(struct iwm_softc *sc, struct iwm_fw_sects *fws,
3679 1.45 nonaka int cpu, int *first_ucode_section)
3680 1.1 pooka {
3681 1.45 nonaka int shift_param;
3682 1.45 nonaka int i, err = 0, sec_num = 0x1;
3683 1.45 nonaka uint32_t val, last_read_idx = 0;
3684 1.45 nonaka void *data;
3685 1.45 nonaka uint32_t dlen;
3686 1.45 nonaka uint32_t offset;
3687 1.1 pooka
3688 1.45 nonaka if (cpu == 1) {
3689 1.45 nonaka shift_param = 0;
3690 1.45 nonaka *first_ucode_section = 0;
3691 1.45 nonaka } else {
3692 1.45 nonaka shift_param = 16;
3693 1.45 nonaka (*first_ucode_section)++;
3694 1.45 nonaka }
3695 1.1 pooka
3696 1.45 nonaka for (i = *first_ucode_section; i < IWM_UCODE_SECT_MAX; i++) {
3697 1.45 nonaka last_read_idx = i;
3698 1.45 nonaka data = fws->fw_sect[i].fws_data;
3699 1.45 nonaka dlen = fws->fw_sect[i].fws_len;
3700 1.45 nonaka offset = fws->fw_sect[i].fws_devoff;
3701 1.1 pooka
3702 1.45 nonaka /*
3703 1.45 nonaka * CPU1_CPU2_SEPARATOR_SECTION delimiter - separate between
3704 1.45 nonaka * CPU1 to CPU2.
3705 1.45 nonaka * PAGING_SEPARATOR_SECTION delimiter - separate between
3706 1.45 nonaka * CPU2 non paged to CPU2 paging sec.
3707 1.45 nonaka */
3708 1.45 nonaka if (!data || offset == IWM_CPU1_CPU2_SEPARATOR_SECTION ||
3709 1.45 nonaka offset == IWM_PAGING_SEPARATOR_SECTION)
3710 1.45 nonaka break;
3711 1.1 pooka
3712 1.45 nonaka if (dlen > sc->sc_fwdmasegsz) {
3713 1.45 nonaka err = EFBIG;
3714 1.45 nonaka } else
3715 1.45 nonaka err = iwm_firmware_load_sect(sc, offset, data, dlen);
3716 1.45 nonaka if (err) {
3717 1.61 nonaka DPRINTF(("%s: could not load firmware chunk %d "
3718 1.61 nonaka "(error %d)\n", DEVNAME(sc), i, err));
3719 1.45 nonaka return err;
3720 1.45 nonaka }
3721 1.1 pooka
3722 1.45 nonaka /* Notify the ucode of the loaded section number and status */
3723 1.45 nonaka if (iwm_nic_lock(sc)) {
3724 1.45 nonaka val = IWM_READ(sc, IWM_FH_UCODE_LOAD_STATUS);
3725 1.45 nonaka val = val | (sec_num << shift_param);
3726 1.45 nonaka IWM_WRITE(sc, IWM_FH_UCODE_LOAD_STATUS, val);
3727 1.45 nonaka sec_num = (sec_num << 1) | 0x1;
3728 1.45 nonaka iwm_nic_unlock(sc);
3729 1.91 mlelstv } else {
3730 1.91 mlelstv err = EBUSY;
3731 1.91 mlelstv DPRINTF(("%s: could not load firmware chunk %d "
3732 1.91 mlelstv "(error %d)\n", DEVNAME(sc), i, err));
3733 1.91 mlelstv return err;
3734 1.45 nonaka }
3735 1.45 nonaka }
3736 1.45 nonaka
3737 1.45 nonaka *first_ucode_section = last_read_idx;
3738 1.45 nonaka
3739 1.45 nonaka if (iwm_nic_lock(sc)) {
3740 1.45 nonaka if (cpu == 1)
3741 1.45 nonaka IWM_WRITE(sc, IWM_FH_UCODE_LOAD_STATUS, 0xFFFF);
3742 1.45 nonaka else
3743 1.45 nonaka IWM_WRITE(sc, IWM_FH_UCODE_LOAD_STATUS, 0xFFFFFFFF);
3744 1.45 nonaka iwm_nic_unlock(sc);
3745 1.91 mlelstv } else {
3746 1.91 mlelstv err = EBUSY;
3747 1.91 mlelstv DPRINTF(("%s: could not finalize firmware loading (error %d)\n",
3748 1.91 mlelstv DEVNAME(sc), err));
3749 1.91 mlelstv return err;
3750 1.6 nonaka }
3751 1.45 nonaka
3752 1.45 nonaka return 0;
3753 1.45 nonaka }
3754 1.45 nonaka
3755 1.45 nonaka static int
3756 1.45 nonaka iwm_load_firmware_8000(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
3757 1.45 nonaka {
3758 1.45 nonaka struct iwm_fw_sects *fws;
3759 1.45 nonaka int err = 0;
3760 1.45 nonaka int first_ucode_section;
3761 1.45 nonaka
3762 1.45 nonaka fws = &sc->sc_fw.fw_sects[ucode_type];
3763 1.45 nonaka
3764 1.45 nonaka /* configure the ucode to be ready to get the secured image */
3765 1.45 nonaka /* release CPU reset */
3766 1.61 nonaka if (iwm_nic_lock(sc)) {
3767 1.61 nonaka iwm_write_prph(sc, IWM_RELEASE_CPU_RESET,
3768 1.61 nonaka IWM_RELEASE_CPU_RESET_BIT);
3769 1.61 nonaka iwm_nic_unlock(sc);
3770 1.61 nonaka }
3771 1.45 nonaka
3772 1.45 nonaka /* load to FW the binary Secured sections of CPU1 */
3773 1.45 nonaka err = iwm_load_cpu_sections_8000(sc, fws, 1, &first_ucode_section);
3774 1.45 nonaka if (err)
3775 1.45 nonaka return err;
3776 1.45 nonaka
3777 1.45 nonaka /* load to FW the binary sections of CPU2 */
3778 1.91 mlelstv err = iwm_load_cpu_sections_8000(sc, fws, 2, &first_ucode_section);
3779 1.91 mlelstv if (err)
3780 1.91 mlelstv return err;
3781 1.91 mlelstv
3782 1.91 mlelstv iwm_enable_interrupts(sc);
3783 1.91 mlelstv return 0;
3784 1.45 nonaka }
3785 1.45 nonaka
3786 1.45 nonaka static int
3787 1.45 nonaka iwm_load_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
3788 1.45 nonaka {
3789 1.45 nonaka int err, w;
3790 1.45 nonaka
3791 1.45 nonaka sc->sc_uc.uc_intr = 0;
3792 1.45 nonaka
3793 1.45 nonaka if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000)
3794 1.45 nonaka err = iwm_load_firmware_8000(sc, ucode_type);
3795 1.45 nonaka else
3796 1.45 nonaka err = iwm_load_firmware_7000(sc, ucode_type);
3797 1.45 nonaka if (err)
3798 1.45 nonaka return err;
3799 1.45 nonaka
3800 1.45 nonaka /* wait for the firmware to load */
3801 1.45 nonaka for (w = 0; !sc->sc_uc.uc_intr && w < 10; w++)
3802 1.45 nonaka err = tsleep(&sc->sc_uc, 0, "iwmuc", mstohz(100));
3803 1.61 nonaka if (err || !sc->sc_uc.uc_ok) {
3804 1.61 nonaka aprint_error_dev(sc->sc_dev,
3805 1.61 nonaka "could not load firmware (error %d, ok %d)\n",
3806 1.61 nonaka err, sc->sc_uc.uc_ok);
3807 1.61 nonaka if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000) {
3808 1.61 nonaka aprint_error_dev(sc->sc_dev, "cpu1 status: 0x%x\n",
3809 1.61 nonaka iwm_read_prph(sc, IWM_SB_CPU_1_STATUS));
3810 1.61 nonaka aprint_error_dev(sc->sc_dev, "cpu2 status: 0x%x\n",
3811 1.61 nonaka iwm_read_prph(sc, IWM_SB_CPU_2_STATUS));
3812 1.61 nonaka }
3813 1.61 nonaka }
3814 1.45 nonaka
3815 1.45 nonaka return err;
3816 1.1 pooka }
3817 1.1 pooka
3818 1.4 nonaka static int
3819 1.45 nonaka iwm_start_fw(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
3820 1.1 pooka {
3821 1.45 nonaka int err;
3822 1.45 nonaka
3823 1.45 nonaka IWM_WRITE(sc, IWM_CSR_INT, ~0);
3824 1.45 nonaka
3825 1.45 nonaka err = iwm_nic_init(sc);
3826 1.45 nonaka if (err) {
3827 1.45 nonaka aprint_error_dev(sc->sc_dev, "Unable to init nic\n");
3828 1.45 nonaka return err;
3829 1.45 nonaka }
3830 1.45 nonaka
3831 1.45 nonaka /* make sure rfkill handshake bits are cleared */
3832 1.45 nonaka IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR, IWM_CSR_UCODE_SW_BIT_RFKILL);
3833 1.45 nonaka IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR,
3834 1.45 nonaka IWM_CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
3835 1.45 nonaka
3836 1.91 mlelstv /* clear (again), then enable firmware load interrupts */
3837 1.45 nonaka IWM_WRITE(sc, IWM_CSR_INT, ~0);
3838 1.91 mlelstv iwm_enable_fwload_interrupt(sc);
3839 1.45 nonaka
3840 1.45 nonaka /* really make sure rfkill handshake bits are cleared */
3841 1.45 nonaka /* maybe we should write a few times more? just to make sure */
3842 1.45 nonaka IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR, IWM_CSR_UCODE_SW_BIT_RFKILL);
3843 1.45 nonaka IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR, IWM_CSR_UCODE_SW_BIT_RFKILL);
3844 1.45 nonaka
3845 1.45 nonaka return iwm_load_firmware(sc, ucode_type);
3846 1.1 pooka }
3847 1.1 pooka
3848 1.4 nonaka static int
3849 1.1 pooka iwm_send_tx_ant_cfg(struct iwm_softc *sc, uint8_t valid_tx_ant)
3850 1.1 pooka {
3851 1.1 pooka struct iwm_tx_ant_cfg_cmd tx_ant_cmd = {
3852 1.1 pooka .valid = htole32(valid_tx_ant),
3853 1.1 pooka };
3854 1.1 pooka
3855 1.45 nonaka return iwm_send_cmd_pdu(sc, IWM_TX_ANT_CONFIGURATION_CMD, 0,
3856 1.45 nonaka sizeof(tx_ant_cmd), &tx_ant_cmd);
3857 1.1 pooka }
3858 1.1 pooka
3859 1.4 nonaka static int
3860 1.1 pooka iwm_send_phy_cfg_cmd(struct iwm_softc *sc)
3861 1.1 pooka {
3862 1.1 pooka struct iwm_phy_cfg_cmd phy_cfg_cmd;
3863 1.1 pooka enum iwm_ucode_type ucode_type = sc->sc_uc_current;
3864 1.1 pooka
3865 1.1 pooka phy_cfg_cmd.phy_cfg = htole32(sc->sc_fw_phy_config);
3866 1.1 pooka phy_cfg_cmd.calib_control.event_trigger =
3867 1.1 pooka sc->sc_default_calib[ucode_type].event_trigger;
3868 1.1 pooka phy_cfg_cmd.calib_control.flow_trigger =
3869 1.1 pooka sc->sc_default_calib[ucode_type].flow_trigger;
3870 1.1 pooka
3871 1.1 pooka DPRINTFN(10, ("Sending Phy CFG command: 0x%x\n", phy_cfg_cmd.phy_cfg));
3872 1.45 nonaka return iwm_send_cmd_pdu(sc, IWM_PHY_CONFIGURATION_CMD, 0,
3873 1.1 pooka sizeof(phy_cfg_cmd), &phy_cfg_cmd);
3874 1.1 pooka }
3875 1.1 pooka
3876 1.4 nonaka static int
3877 1.91 mlelstv iwm_send_dqa_cmd(struct iwm_softc *sc)
3878 1.91 mlelstv {
3879 1.91 mlelstv struct iwm_dqa_enable_cmd dqa_cmd = {
3880 1.91 mlelstv .cmd_queue = htole32(IWM_DQA_CMD_QUEUE),
3881 1.91 mlelstv };
3882 1.91 mlelstv uint32_t cmd_id;
3883 1.91 mlelstv
3884 1.91 mlelstv cmd_id = iwm_cmd_id(IWM_DQA_ENABLE_CMD, IWM_DATA_PATH_GROUP, 0);
3885 1.91 mlelstv return iwm_send_cmd_pdu(sc, cmd_id, 0, sizeof(dqa_cmd), &dqa_cmd);
3886 1.91 mlelstv }
3887 1.91 mlelstv
3888 1.91 mlelstv static int
3889 1.51 nonaka iwm_load_ucode_wait_alive(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
3890 1.1 pooka {
3891 1.71 nonaka struct iwm_fw_sects *fws;
3892 1.1 pooka enum iwm_ucode_type old_type = sc->sc_uc_current;
3893 1.45 nonaka int err;
3894 1.1 pooka
3895 1.61 nonaka err = iwm_read_firmware(sc, ucode_type);
3896 1.45 nonaka if (err)
3897 1.45 nonaka return err;
3898 1.1 pooka
3899 1.91 mlelstv if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))
3900 1.91 mlelstv sc->cmdqid = IWM_DQA_CMD_QUEUE;
3901 1.91 mlelstv else
3902 1.91 mlelstv sc->cmdqid = IWM_CMD_QUEUE;
3903 1.91 mlelstv
3904 1.1 pooka sc->sc_uc_current = ucode_type;
3905 1.45 nonaka err = iwm_start_fw(sc, ucode_type);
3906 1.45 nonaka if (err) {
3907 1.1 pooka sc->sc_uc_current = old_type;
3908 1.45 nonaka return err;
3909 1.1 pooka }
3910 1.1 pooka
3911 1.71 nonaka err = iwm_post_alive(sc);
3912 1.71 nonaka if (err)
3913 1.71 nonaka return err;
3914 1.71 nonaka
3915 1.71 nonaka fws = &sc->sc_fw.fw_sects[ucode_type];
3916 1.71 nonaka if (fws->paging_mem_size) {
3917 1.71 nonaka err = iwm_save_fw_paging(sc, fws);
3918 1.71 nonaka if (err)
3919 1.71 nonaka return err;
3920 1.71 nonaka
3921 1.71 nonaka err = iwm_send_paging_cmd(sc, fws);
3922 1.71 nonaka if (err) {
3923 1.71 nonaka iwm_free_fw_paging(sc);
3924 1.71 nonaka return err;
3925 1.71 nonaka }
3926 1.71 nonaka }
3927 1.71 nonaka
3928 1.71 nonaka return 0;
3929 1.1 pooka }
3930 1.1 pooka
3931 1.4 nonaka static int
3932 1.1 pooka iwm_run_init_mvm_ucode(struct iwm_softc *sc, int justnvm)
3933 1.1 pooka {
3934 1.91 mlelstv const int wait_flags = (IWM_INIT_COMPLETE | IWM_CALIB_COMPLETE);
3935 1.91 mlelstv int err, s;
3936 1.1 pooka
3937 1.1 pooka if ((sc->sc_flags & IWM_FLAG_RFKILL) && !justnvm) {
3938 1.3 nonaka aprint_error_dev(sc->sc_dev,
3939 1.3 nonaka "radio is disabled by hardware switch\n");
3940 1.1 pooka return EPERM;
3941 1.1 pooka }
3942 1.1 pooka
3943 1.91 mlelstv s = splnet();
3944 1.1 pooka sc->sc_init_complete = 0;
3945 1.45 nonaka err = iwm_load_ucode_wait_alive(sc, IWM_UCODE_TYPE_INIT);
3946 1.45 nonaka if (err) {
3947 1.61 nonaka DPRINTF(("%s: failed to load init firmware\n", DEVNAME(sc)));
3948 1.91 mlelstv splx(s);
3949 1.45 nonaka return err;
3950 1.45 nonaka }
3951 1.1 pooka
3952 1.91 mlelstv if (sc->sc_device_family < IWM_DEVICE_FAMILY_8000) {
3953 1.91 mlelstv err = iwm_send_bt_init_conf(sc);
3954 1.91 mlelstv if (err) {
3955 1.91 mlelstv splx(s);
3956 1.91 mlelstv return err;
3957 1.91 mlelstv }
3958 1.91 mlelstv }
3959 1.91 mlelstv
3960 1.1 pooka if (justnvm) {
3961 1.45 nonaka err = iwm_nvm_init(sc);
3962 1.45 nonaka if (err) {
3963 1.3 nonaka aprint_error_dev(sc->sc_dev, "failed to read nvm\n");
3964 1.91 mlelstv splx(s);
3965 1.45 nonaka return err;
3966 1.1 pooka }
3967 1.1 pooka
3968 1.91 mlelstv if (IEEE80211_ADDR_EQ(etheranyaddr, sc->sc_ic.ic_myaddr))
3969 1.91 mlelstv IEEE80211_ADDR_COPY(&sc->sc_ic.ic_myaddr,
3970 1.91 mlelstv &sc->sc_nvm.hw_addr);
3971 1.91 mlelstv splx(s);
3972 1.1 pooka return 0;
3973 1.1 pooka }
3974 1.1 pooka
3975 1.91 mlelstv err = iwm_sf_config(sc, IWM_SF_INIT_OFF);
3976 1.91 mlelstv if (err) {
3977 1.91 mlelstv splx(s);
3978 1.45 nonaka return err;
3979 1.91 mlelstv }
3980 1.45 nonaka
3981 1.45 nonaka err = iwm_send_tx_ant_cfg(sc, iwm_fw_valid_tx_ant(sc));
3982 1.91 mlelstv if (err) {
3983 1.91 mlelstv splx(s);
3984 1.45 nonaka return err;
3985 1.91 mlelstv }
3986 1.1 pooka
3987 1.1 pooka /*
3988 1.45 nonaka * Send phy configurations command to init uCode
3989 1.45 nonaka * to start the 16.0 uCode init image internal calibrations.
3990 1.45 nonaka */
3991 1.45 nonaka err = iwm_send_phy_cfg_cmd(sc);
3992 1.91 mlelstv if (err) {
3993 1.91 mlelstv splx(s);
3994 1.45 nonaka return err;
3995 1.91 mlelstv }
3996 1.1 pooka
3997 1.1 pooka /*
3998 1.1 pooka * Nothing to do but wait for the init complete notification
3999 1.1 pooka * from the firmware
4000 1.1 pooka */
4001 1.91 mlelstv while ((sc->sc_init_complete & wait_flags) != wait_flags) {
4002 1.45 nonaka err = tsleep(&sc->sc_init_complete, 0, "iwminit", mstohz(2000));
4003 1.45 nonaka if (err)
4004 1.1 pooka break;
4005 1.45 nonaka }
4006 1.1 pooka
4007 1.91 mlelstv splx(s);
4008 1.45 nonaka return err;
4009 1.1 pooka }
4010 1.1 pooka
4011 1.91 mlelstv #ifdef notyet
4012 1.91 mlelstv static int
4013 1.91 mlelstv iwm_config_ltr(struct iwm_softc *sc)
4014 1.91 mlelstv {
4015 1.91 mlelstv struct iwm_ltr_config_cmd cmd = {
4016 1.91 mlelstv .flags = htole32(IWM_LTR_CFG_FLAG_FEATURE_ENABLE),
4017 1.91 mlelstv };
4018 1.91 mlelstv
4019 1.91 mlelstv if (!sc->sc_ltr_enabled)
4020 1.91 mlelstv return 0;
4021 1.91 mlelstv
4022 1.91 mlelstv return iwm_send_cmd_pdu(sc, IWM_LTR_CONFIG, 0, sizeof(cmd), &cmd);
4023 1.91 mlelstv }
4024 1.91 mlelstv #endif
4025 1.91 mlelstv
4026 1.4 nonaka static int
4027 1.1 pooka iwm_rx_addbuf(struct iwm_softc *sc, int size, int idx)
4028 1.1 pooka {
4029 1.1 pooka struct iwm_rx_ring *ring = &sc->rxq;
4030 1.1 pooka struct iwm_rx_data *data = &ring->data[idx];
4031 1.1 pooka struct mbuf *m;
4032 1.45 nonaka int err;
4033 1.1 pooka int fatal = 0;
4034 1.1 pooka
4035 1.1 pooka m = m_gethdr(M_DONTWAIT, MT_DATA);
4036 1.1 pooka if (m == NULL)
4037 1.1 pooka return ENOBUFS;
4038 1.1 pooka
4039 1.1 pooka if (size <= MCLBYTES) {
4040 1.1 pooka MCLGET(m, M_DONTWAIT);
4041 1.1 pooka } else {
4042 1.89 mlelstv MEXTMALLOC(m, size, M_DONTWAIT);
4043 1.1 pooka }
4044 1.1 pooka if ((m->m_flags & M_EXT) == 0) {
4045 1.1 pooka m_freem(m);
4046 1.1 pooka return ENOBUFS;
4047 1.1 pooka }
4048 1.1 pooka
4049 1.1 pooka if (data->m != NULL) {
4050 1.1 pooka bus_dmamap_unload(sc->sc_dmat, data->map);
4051 1.1 pooka fatal = 1;
4052 1.1 pooka }
4053 1.1 pooka
4054 1.89 mlelstv m->m_len = m->m_pkthdr.len = size;
4055 1.45 nonaka err = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m,
4056 1.45 nonaka BUS_DMA_READ|BUS_DMA_NOWAIT);
4057 1.45 nonaka if (err) {
4058 1.1 pooka /* XXX */
4059 1.1 pooka if (fatal)
4060 1.1 pooka panic("iwm: could not load RX mbuf");
4061 1.1 pooka m_freem(m);
4062 1.45 nonaka return err;
4063 1.1 pooka }
4064 1.1 pooka data->m = m;
4065 1.1 pooka bus_dmamap_sync(sc->sc_dmat, data->map, 0, size, BUS_DMASYNC_PREREAD);
4066 1.1 pooka
4067 1.8 nonaka /* Update RX descriptor. */
4068 1.1 pooka ring->desc[idx] = htole32(data->map->dm_segs[0].ds_addr >> 8);
4069 1.1 pooka bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,
4070 1.1 pooka idx * sizeof(uint32_t), sizeof(uint32_t), BUS_DMASYNC_PREWRITE);
4071 1.1 pooka
4072 1.1 pooka return 0;
4073 1.1 pooka }
4074 1.1 pooka
4075 1.1 pooka #define IWM_RSSI_OFFSET 50
4076 1.4 nonaka static int
4077 1.45 nonaka iwm_calc_rssi(struct iwm_softc *sc, struct iwm_rx_phy_info *phy_info)
4078 1.1 pooka {
4079 1.1 pooka int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm;
4080 1.1 pooka uint32_t agc_a, agc_b;
4081 1.1 pooka uint32_t val;
4082 1.1 pooka
4083 1.1 pooka val = le32toh(phy_info->non_cfg_phy[IWM_RX_INFO_AGC_IDX]);
4084 1.1 pooka agc_a = (val & IWM_OFDM_AGC_A_MSK) >> IWM_OFDM_AGC_A_POS;
4085 1.1 pooka agc_b = (val & IWM_OFDM_AGC_B_MSK) >> IWM_OFDM_AGC_B_POS;
4086 1.1 pooka
4087 1.1 pooka val = le32toh(phy_info->non_cfg_phy[IWM_RX_INFO_RSSI_AB_IDX]);
4088 1.1 pooka rssi_a = (val & IWM_OFDM_RSSI_INBAND_A_MSK) >> IWM_OFDM_RSSI_A_POS;
4089 1.1 pooka rssi_b = (val & IWM_OFDM_RSSI_INBAND_B_MSK) >> IWM_OFDM_RSSI_B_POS;
4090 1.1 pooka
4091 1.1 pooka /*
4092 1.1 pooka * dBm = rssi dB - agc dB - constant.
4093 1.1 pooka * Higher AGC (higher radio gain) means lower signal.
4094 1.1 pooka */
4095 1.1 pooka rssi_a_dbm = rssi_a - IWM_RSSI_OFFSET - agc_a;
4096 1.1 pooka rssi_b_dbm = rssi_b - IWM_RSSI_OFFSET - agc_b;
4097 1.1 pooka max_rssi_dbm = MAX(rssi_a_dbm, rssi_b_dbm);
4098 1.1 pooka
4099 1.1 pooka DPRINTF(("Rssi In A %d B %d Max %d AGCA %d AGCB %d\n",
4100 1.1 pooka rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b));
4101 1.1 pooka
4102 1.1 pooka return max_rssi_dbm;
4103 1.1 pooka }
4104 1.1 pooka
4105 1.1 pooka /*
4106 1.45 nonaka * RSSI values are reported by the FW as positive values - need to negate
4107 1.1 pooka * to obtain their dBM. Account for missing antennas by replacing 0
4108 1.1 pooka * values by -256dBm: practically 0 power and a non-feasible 8 bit value.
4109 1.1 pooka */
4110 1.4 nonaka static int
4111 1.51 nonaka iwm_get_signal_strength(struct iwm_softc *sc, struct iwm_rx_phy_info *phy_info)
4112 1.1 pooka {
4113 1.1 pooka int energy_a, energy_b, energy_c, max_energy;
4114 1.1 pooka uint32_t val;
4115 1.1 pooka
4116 1.1 pooka val = le32toh(phy_info->non_cfg_phy[IWM_RX_INFO_ENERGY_ANT_ABC_IDX]);
4117 1.1 pooka energy_a = (val & IWM_RX_INFO_ENERGY_ANT_A_MSK) >>
4118 1.1 pooka IWM_RX_INFO_ENERGY_ANT_A_POS;
4119 1.1 pooka energy_a = energy_a ? -energy_a : -256;
4120 1.1 pooka energy_b = (val & IWM_RX_INFO_ENERGY_ANT_B_MSK) >>
4121 1.1 pooka IWM_RX_INFO_ENERGY_ANT_B_POS;
4122 1.1 pooka energy_b = energy_b ? -energy_b : -256;
4123 1.1 pooka energy_c = (val & IWM_RX_INFO_ENERGY_ANT_C_MSK) >>
4124 1.1 pooka IWM_RX_INFO_ENERGY_ANT_C_POS;
4125 1.1 pooka energy_c = energy_c ? -energy_c : -256;
4126 1.1 pooka max_energy = MAX(energy_a, energy_b);
4127 1.1 pooka max_energy = MAX(max_energy, energy_c);
4128 1.1 pooka
4129 1.5 nonaka DPRINTFN(12, ("energy In A %d B %d C %d, and max %d\n",
4130 1.1 pooka energy_a, energy_b, energy_c, max_energy));
4131 1.1 pooka
4132 1.1 pooka return max_energy;
4133 1.1 pooka }
4134 1.1 pooka
4135 1.4 nonaka static void
4136 1.45 nonaka iwm_rx_rx_phy_cmd(struct iwm_softc *sc, struct iwm_rx_packet *pkt,
4137 1.45 nonaka struct iwm_rx_data *data)
4138 1.1 pooka {
4139 1.1 pooka struct iwm_rx_phy_info *phy_info = (void *)pkt->data;
4140 1.1 pooka
4141 1.1 pooka DPRINTFN(20, ("received PHY stats\n"));
4142 1.1 pooka bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*pkt),
4143 1.1 pooka sizeof(*phy_info), BUS_DMASYNC_POSTREAD);
4144 1.1 pooka
4145 1.1 pooka memcpy(&sc->sc_last_phy_info, phy_info, sizeof(sc->sc_last_phy_info));
4146 1.1 pooka }
4147 1.1 pooka
4148 1.1 pooka /*
4149 1.1 pooka * Retrieve the average noise (in dBm) among receivers.
4150 1.1 pooka */
4151 1.4 nonaka static int
4152 1.45 nonaka iwm_get_noise(const struct iwm_statistics_rx_non_phy *stats)
4153 1.1 pooka {
4154 1.1 pooka int i, total, nbant, noise;
4155 1.1 pooka
4156 1.1 pooka total = nbant = noise = 0;
4157 1.1 pooka for (i = 0; i < 3; i++) {
4158 1.1 pooka noise = le32toh(stats->beacon_silence_rssi[i]) & 0xff;
4159 1.1 pooka if (noise) {
4160 1.1 pooka total += noise;
4161 1.1 pooka nbant++;
4162 1.1 pooka }
4163 1.1 pooka }
4164 1.1 pooka
4165 1.1 pooka /* There should be at least one antenna but check anyway. */
4166 1.1 pooka return (nbant == 0) ? -127 : (total / nbant) - 107;
4167 1.1 pooka }
4168 1.1 pooka
4169 1.4 nonaka static void
4170 1.45 nonaka iwm_rx_rx_mpdu(struct iwm_softc *sc, struct iwm_rx_packet *pkt,
4171 1.45 nonaka struct iwm_rx_data *data)
4172 1.1 pooka {
4173 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
4174 1.1 pooka struct ieee80211_frame *wh;
4175 1.1 pooka struct ieee80211_node *ni;
4176 1.1 pooka struct ieee80211_channel *c = NULL;
4177 1.1 pooka struct mbuf *m;
4178 1.1 pooka struct iwm_rx_phy_info *phy_info;
4179 1.1 pooka struct iwm_rx_mpdu_res_start *rx_res;
4180 1.1 pooka int device_timestamp;
4181 1.1 pooka uint32_t len;
4182 1.1 pooka uint32_t rx_pkt_status;
4183 1.1 pooka int rssi;
4184 1.50 nonaka int s;
4185 1.1 pooka
4186 1.1 pooka bus_dmamap_sync(sc->sc_dmat, data->map, 0, IWM_RBUF_SIZE,
4187 1.1 pooka BUS_DMASYNC_POSTREAD);
4188 1.1 pooka
4189 1.1 pooka phy_info = &sc->sc_last_phy_info;
4190 1.1 pooka rx_res = (struct iwm_rx_mpdu_res_start *)pkt->data;
4191 1.1 pooka wh = (struct ieee80211_frame *)(pkt->data + sizeof(*rx_res));
4192 1.1 pooka len = le16toh(rx_res->byte_count);
4193 1.45 nonaka rx_pkt_status = le32toh(*(uint32_t *)(pkt->data +
4194 1.45 nonaka sizeof(*rx_res) + len));
4195 1.1 pooka
4196 1.1 pooka m = data->m;
4197 1.1 pooka m->m_data = pkt->data + sizeof(*rx_res);
4198 1.1 pooka m->m_pkthdr.len = m->m_len = len;
4199 1.1 pooka
4200 1.1 pooka if (__predict_false(phy_info->cfg_phy_cnt > 20)) {
4201 1.1 pooka DPRINTF(("dsp size out of range [0,20]: %d\n",
4202 1.1 pooka phy_info->cfg_phy_cnt));
4203 1.1 pooka return;
4204 1.1 pooka }
4205 1.1 pooka
4206 1.1 pooka if (!(rx_pkt_status & IWM_RX_MPDU_RES_STATUS_CRC_OK) ||
4207 1.1 pooka !(rx_pkt_status & IWM_RX_MPDU_RES_STATUS_OVERRUN_OK)) {
4208 1.1 pooka DPRINTF(("Bad CRC or FIFO: 0x%08X.\n", rx_pkt_status));
4209 1.1 pooka return; /* drop */
4210 1.1 pooka }
4211 1.1 pooka
4212 1.1 pooka device_timestamp = le32toh(phy_info->system_timestamp);
4213 1.1 pooka
4214 1.1 pooka if (sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_RX_ENERGY_API) {
4215 1.45 nonaka rssi = iwm_get_signal_strength(sc, phy_info);
4216 1.1 pooka } else {
4217 1.45 nonaka rssi = iwm_calc_rssi(sc, phy_info);
4218 1.1 pooka }
4219 1.1 pooka rssi = -rssi;
4220 1.1 pooka
4221 1.1 pooka if (ic->ic_state == IEEE80211_S_SCAN)
4222 1.45 nonaka iwm_fix_channel(sc, m);
4223 1.1 pooka
4224 1.1 pooka if (iwm_rx_addbuf(sc, IWM_RBUF_SIZE, sc->rxq.cur) != 0)
4225 1.1 pooka return;
4226 1.94 mlelstv MCLAIM(sc->rxq.data[sc->rxq.cur].m, &sc->sc_ec.ec_rx_mowner);
4227 1.1 pooka
4228 1.42 ozaki m_set_rcvif(m, IC2IFP(ic));
4229 1.1 pooka
4230 1.45 nonaka if (le32toh(phy_info->channel) < __arraycount(ic->ic_channels))
4231 1.45 nonaka c = &ic->ic_channels[le32toh(phy_info->channel)];
4232 1.1 pooka
4233 1.50 nonaka s = splnet();
4234 1.50 nonaka
4235 1.1 pooka ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
4236 1.1 pooka if (c)
4237 1.1 pooka ni->ni_chan = c;
4238 1.1 pooka
4239 1.48 nonaka if (__predict_false(sc->sc_drvbpf != NULL)) {
4240 1.1 pooka struct iwm_rx_radiotap_header *tap = &sc->sc_rxtap;
4241 1.1 pooka
4242 1.1 pooka tap->wr_flags = 0;
4243 1.1 pooka if (phy_info->phy_flags & htole16(IWM_PHY_INFO_FLAG_SHPREAMBLE))
4244 1.1 pooka tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
4245 1.1 pooka tap->wr_chan_freq =
4246 1.1 pooka htole16(ic->ic_channels[phy_info->channel].ic_freq);
4247 1.1 pooka tap->wr_chan_flags =
4248 1.1 pooka htole16(ic->ic_channels[phy_info->channel].ic_flags);
4249 1.1 pooka tap->wr_dbm_antsignal = (int8_t)rssi;
4250 1.1 pooka tap->wr_dbm_antnoise = (int8_t)sc->sc_noise;
4251 1.1 pooka tap->wr_tsft = phy_info->system_timestamp;
4252 1.45 nonaka if (phy_info->phy_flags &
4253 1.45 nonaka htole16(IWM_RX_RES_PHY_FLAGS_OFDM_HT)) {
4254 1.45 nonaka uint8_t mcs = (phy_info->rate_n_flags &
4255 1.61 nonaka htole32(IWM_RATE_HT_MCS_RATE_CODE_MSK |
4256 1.61 nonaka IWM_RATE_HT_MCS_NSS_MSK));
4257 1.45 nonaka tap->wr_rate = (0x80 | mcs);
4258 1.45 nonaka } else {
4259 1.45 nonaka uint8_t rate = (phy_info->rate_n_flags &
4260 1.45 nonaka htole32(IWM_RATE_LEGACY_RATE_MSK));
4261 1.45 nonaka switch (rate) {
4262 1.45 nonaka /* CCK rates. */
4263 1.45 nonaka case 10: tap->wr_rate = 2; break;
4264 1.45 nonaka case 20: tap->wr_rate = 4; break;
4265 1.45 nonaka case 55: tap->wr_rate = 11; break;
4266 1.45 nonaka case 110: tap->wr_rate = 22; break;
4267 1.45 nonaka /* OFDM rates. */
4268 1.45 nonaka case 0xd: tap->wr_rate = 12; break;
4269 1.45 nonaka case 0xf: tap->wr_rate = 18; break;
4270 1.45 nonaka case 0x5: tap->wr_rate = 24; break;
4271 1.45 nonaka case 0x7: tap->wr_rate = 36; break;
4272 1.45 nonaka case 0x9: tap->wr_rate = 48; break;
4273 1.45 nonaka case 0xb: tap->wr_rate = 72; break;
4274 1.45 nonaka case 0x1: tap->wr_rate = 96; break;
4275 1.45 nonaka case 0x3: tap->wr_rate = 108; break;
4276 1.45 nonaka /* Unknown rate: should not happen. */
4277 1.45 nonaka default: tap->wr_rate = 0;
4278 1.45 nonaka }
4279 1.1 pooka }
4280 1.1 pooka
4281 1.83 msaitoh bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m, BPF_D_IN);
4282 1.1 pooka }
4283 1.1 pooka ieee80211_input(ic, m, ni, rssi, device_timestamp);
4284 1.1 pooka ieee80211_free_node(ni);
4285 1.50 nonaka
4286 1.50 nonaka splx(s);
4287 1.1 pooka }
4288 1.1 pooka
4289 1.4 nonaka static void
4290 1.45 nonaka iwm_rx_tx_cmd_single(struct iwm_softc *sc, struct iwm_rx_packet *pkt,
4291 1.45 nonaka struct iwm_node *in)
4292 1.1 pooka {
4293 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
4294 1.1 pooka struct ifnet *ifp = IC2IFP(ic);
4295 1.45 nonaka struct iwm_tx_resp *tx_resp = (void *)pkt->data;
4296 1.1 pooka int status = le16toh(tx_resp->status.status) & IWM_TX_STATUS_MSK;
4297 1.1 pooka int failack = tx_resp->failure_frame;
4298 1.1 pooka
4299 1.1 pooka KASSERT(tx_resp->frame_count == 1);
4300 1.1 pooka
4301 1.1 pooka /* Update rate control statistics. */
4302 1.1 pooka in->in_amn.amn_txcnt++;
4303 1.1 pooka if (failack > 0) {
4304 1.1 pooka in->in_amn.amn_retrycnt++;
4305 1.1 pooka }
4306 1.1 pooka
4307 1.1 pooka if (status != IWM_TX_STATUS_SUCCESS &&
4308 1.1 pooka status != IWM_TX_STATUS_DIRECT_DONE)
4309 1.84 thorpej if_statinc(ifp, if_oerrors);
4310 1.1 pooka else
4311 1.84 thorpej if_statinc(ifp, if_opackets);
4312 1.1 pooka }
4313 1.1 pooka
4314 1.4 nonaka static void
4315 1.45 nonaka iwm_rx_tx_cmd(struct iwm_softc *sc, struct iwm_rx_packet *pkt,
4316 1.45 nonaka struct iwm_rx_data *data)
4317 1.1 pooka {
4318 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
4319 1.1 pooka struct ifnet *ifp = IC2IFP(ic);
4320 1.1 pooka struct iwm_cmd_header *cmd_hdr = &pkt->hdr;
4321 1.1 pooka int idx = cmd_hdr->idx;
4322 1.1 pooka int qid = cmd_hdr->qid;
4323 1.1 pooka struct iwm_tx_ring *ring = &sc->txq[qid];
4324 1.1 pooka struct iwm_tx_data *txd = &ring->data[idx];
4325 1.1 pooka struct iwm_node *in = txd->in;
4326 1.61 nonaka int s;
4327 1.61 nonaka
4328 1.61 nonaka s = splnet();
4329 1.1 pooka
4330 1.1 pooka if (txd->done) {
4331 1.2 nonaka DPRINTF(("%s: got tx interrupt that's already been handled!\n",
4332 1.2 nonaka DEVNAME(sc)));
4333 1.61 nonaka splx(s);
4334 1.1 pooka return;
4335 1.1 pooka }
4336 1.1 pooka
4337 1.1 pooka bus_dmamap_sync(sc->sc_dmat, data->map, 0, IWM_RBUF_SIZE,
4338 1.1 pooka BUS_DMASYNC_POSTREAD);
4339 1.1 pooka
4340 1.1 pooka sc->sc_tx_timer = 0;
4341 1.1 pooka
4342 1.45 nonaka iwm_rx_tx_cmd_single(sc, pkt, in);
4343 1.1 pooka
4344 1.1 pooka bus_dmamap_sync(sc->sc_dmat, txd->map, 0, txd->map->dm_mapsize,
4345 1.1 pooka BUS_DMASYNC_POSTWRITE);
4346 1.1 pooka bus_dmamap_unload(sc->sc_dmat, txd->map);
4347 1.1 pooka m_freem(txd->m);
4348 1.1 pooka
4349 1.1 pooka DPRINTFN(8, ("free txd %p, in %p\n", txd, txd->in));
4350 1.1 pooka KASSERT(txd->done == 0);
4351 1.1 pooka txd->done = 1;
4352 1.1 pooka KASSERT(txd->in);
4353 1.1 pooka
4354 1.1 pooka txd->m = NULL;
4355 1.1 pooka txd->in = NULL;
4356 1.1 pooka ieee80211_free_node(&in->in_ni);
4357 1.1 pooka
4358 1.1 pooka if (--ring->queued < IWM_TX_RING_LOMARK) {
4359 1.61 nonaka sc->qfullmsk &= ~(1 << qid);
4360 1.1 pooka if (sc->qfullmsk == 0 && (ifp->if_flags & IFF_OACTIVE)) {
4361 1.1 pooka ifp->if_flags &= ~IFF_OACTIVE;
4362 1.65 nonaka KASSERT(KERNEL_LOCKED_P());
4363 1.65 nonaka iwm_start(ifp);
4364 1.1 pooka }
4365 1.1 pooka }
4366 1.61 nonaka
4367 1.61 nonaka splx(s);
4368 1.1 pooka }
4369 1.1 pooka
4370 1.4 nonaka static int
4371 1.45 nonaka iwm_binding_cmd(struct iwm_softc *sc, struct iwm_node *in, uint32_t action)
4372 1.1 pooka {
4373 1.1 pooka struct iwm_binding_cmd cmd;
4374 1.45 nonaka struct iwm_phy_ctxt *phyctxt = in->in_phyctxt;
4375 1.91 mlelstv uint32_t mac_id = IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color);
4376 1.91 mlelstv int i, err, active = (sc->sc_flags & IWM_FLAG_BINDING_ACTIVE);
4377 1.1 pooka uint32_t status;
4378 1.91 mlelstv size_t cmdsize;
4379 1.91 mlelstv
4380 1.91 mlelstv if (action == IWM_FW_CTXT_ACTION_ADD && active) {
4381 1.91 mlelstv device_printf(sc->sc_dev, "binding already added\n");
4382 1.91 mlelstv return EINVAL;
4383 1.91 mlelstv }
4384 1.91 mlelstv
4385 1.91 mlelstv if (action == IWM_FW_CTXT_ACTION_REMOVE && !active) {
4386 1.91 mlelstv device_printf(sc->sc_dev, "binding already removed\n");
4387 1.91 mlelstv return EINVAL;
4388 1.91 mlelstv }
4389 1.91 mlelstv
4390 1.91 mlelstv if (phyctxt == NULL)
4391 1.91 mlelstv return EINVAL;
4392 1.1 pooka
4393 1.1 pooka memset(&cmd, 0, sizeof(cmd));
4394 1.1 pooka
4395 1.1 pooka cmd.id_and_color
4396 1.1 pooka = htole32(IWM_FW_CMD_ID_AND_COLOR(phyctxt->id, phyctxt->color));
4397 1.1 pooka cmd.action = htole32(action);
4398 1.1 pooka cmd.phy = htole32(IWM_FW_CMD_ID_AND_COLOR(phyctxt->id, phyctxt->color));
4399 1.1 pooka
4400 1.91 mlelstv cmd.macs[0] = htole32(mac_id);
4401 1.1 pooka for (i = 1; i < IWM_MAX_MACS_IN_BINDING; i++)
4402 1.1 pooka cmd.macs[i] = htole32(IWM_FW_CTXT_INVALID);
4403 1.1 pooka
4404 1.91 mlelstv if (IEEE80211_IS_CHAN_2GHZ(phyctxt->channel) ||
4405 1.91 mlelstv isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_CDB_SUPPORT))
4406 1.91 mlelstv cmd.lmac_id = htole32(IWM_LMAC_24G_INDEX);
4407 1.91 mlelstv else
4408 1.91 mlelstv cmd.lmac_id = htole32(IWM_LMAC_5G_INDEX);
4409 1.91 mlelstv
4410 1.91 mlelstv if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT))
4411 1.91 mlelstv cmdsize = sizeof(cmd);
4412 1.91 mlelstv else
4413 1.91 mlelstv cmdsize = sizeof(struct iwm_binding_cmd_v1);
4414 1.91 mlelstv
4415 1.1 pooka status = 0;
4416 1.91 mlelstv err = iwm_send_cmd_pdu_status(sc, IWM_BINDING_CONTEXT_CMD, cmdsize, &cmd,
4417 1.91 mlelstv &status);
4418 1.45 nonaka if (err == 0 && status != 0)
4419 1.45 nonaka err = EIO;
4420 1.1 pooka
4421 1.45 nonaka return err;
4422 1.1 pooka }
4423 1.1 pooka
4424 1.4 nonaka static void
4425 1.45 nonaka iwm_phy_ctxt_cmd_hdr(struct iwm_softc *sc, struct iwm_phy_ctxt *ctxt,
4426 1.45 nonaka struct iwm_phy_context_cmd *cmd, uint32_t action, uint32_t apply_time)
4427 1.1 pooka {
4428 1.1 pooka memset(cmd, 0, sizeof(struct iwm_phy_context_cmd));
4429 1.1 pooka
4430 1.1 pooka cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(ctxt->id,
4431 1.1 pooka ctxt->color));
4432 1.1 pooka cmd->action = htole32(action);
4433 1.1 pooka cmd->apply_time = htole32(apply_time);
4434 1.1 pooka }
4435 1.1 pooka
4436 1.4 nonaka static void
4437 1.45 nonaka iwm_phy_ctxt_cmd_data(struct iwm_softc *sc, struct iwm_phy_context_cmd *cmd,
4438 1.45 nonaka struct ieee80211_channel *chan, uint8_t chains_static,
4439 1.45 nonaka uint8_t chains_dynamic)
4440 1.1 pooka {
4441 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
4442 1.1 pooka uint8_t active_cnt, idle_cnt;
4443 1.1 pooka
4444 1.1 pooka cmd->ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?
4445 1.1 pooka IWM_PHY_BAND_24 : IWM_PHY_BAND_5;
4446 1.1 pooka
4447 1.1 pooka cmd->ci.channel = ieee80211_chan2ieee(ic, chan);
4448 1.1 pooka cmd->ci.width = IWM_PHY_VHT_CHANNEL_MODE20;
4449 1.1 pooka cmd->ci.ctrl_pos = IWM_PHY_VHT_CTRL_POS_1_BELOW;
4450 1.1 pooka
4451 1.1 pooka /* Set rx the chains */
4452 1.1 pooka idle_cnt = chains_static;
4453 1.1 pooka active_cnt = chains_dynamic;
4454 1.1 pooka
4455 1.45 nonaka cmd->rxchain_info = htole32(iwm_fw_valid_rx_ant(sc) <<
4456 1.45 nonaka IWM_PHY_RX_CHAIN_VALID_POS);
4457 1.1 pooka cmd->rxchain_info |= htole32(idle_cnt << IWM_PHY_RX_CHAIN_CNT_POS);
4458 1.1 pooka cmd->rxchain_info |= htole32(active_cnt <<
4459 1.1 pooka IWM_PHY_RX_CHAIN_MIMO_CNT_POS);
4460 1.1 pooka
4461 1.45 nonaka cmd->txchain_info = htole32(iwm_fw_valid_tx_ant(sc));
4462 1.1 pooka }
4463 1.1 pooka
4464 1.4 nonaka static int
4465 1.91 mlelstv iwm_phy_ctxt_cmd(struct iwm_softc *sc, struct iwm_phy_ctxt *ctxt, uint8_t chains_static, uint8_t chains_dynamic, uint32_t action,
4466 1.45 nonaka uint32_t apply_time)
4467 1.1 pooka {
4468 1.1 pooka struct iwm_phy_context_cmd cmd;
4469 1.1 pooka
4470 1.45 nonaka iwm_phy_ctxt_cmd_hdr(sc, ctxt, &cmd, action, apply_time);
4471 1.1 pooka
4472 1.45 nonaka iwm_phy_ctxt_cmd_data(sc, &cmd, ctxt->channel,
4473 1.1 pooka chains_static, chains_dynamic);
4474 1.1 pooka
4475 1.45 nonaka return iwm_send_cmd_pdu(sc, IWM_PHY_CONTEXT_CMD, 0,
4476 1.1 pooka sizeof(struct iwm_phy_context_cmd), &cmd);
4477 1.1 pooka }
4478 1.1 pooka
4479 1.4 nonaka static int
4480 1.1 pooka iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
4481 1.1 pooka {
4482 1.91 mlelstv struct iwm_tx_ring *ring = &sc->txq[sc->cmdqid];
4483 1.1 pooka struct iwm_tfd *desc;
4484 1.45 nonaka struct iwm_tx_data *txdata;
4485 1.1 pooka struct iwm_device_cmd *cmd;
4486 1.1 pooka struct mbuf *m;
4487 1.1 pooka bus_addr_t paddr;
4488 1.1 pooka uint32_t addr_lo;
4489 1.45 nonaka int err = 0, i, paylen, off, s;
4490 1.91 mlelstv int idx, code, async, group_id;
4491 1.45 nonaka size_t hdrlen, datasz;
4492 1.45 nonaka uint8_t *data;
4493 1.91 mlelstv int generation = sc->sc_generation;
4494 1.1 pooka
4495 1.1 pooka code = hcmd->id;
4496 1.1 pooka async = hcmd->flags & IWM_CMD_ASYNC;
4497 1.91 mlelstv idx = ring->cur;
4498 1.1 pooka
4499 1.1 pooka for (i = 0, paylen = 0; i < __arraycount(hcmd->len); i++) {
4500 1.1 pooka paylen += hcmd->len[i];
4501 1.1 pooka }
4502 1.1 pooka
4503 1.91 mlelstv /* If this command waits for a response, allocate response buffer. */
4504 1.91 mlelstv hcmd->resp_pkt = NULL;
4505 1.91 mlelstv if (hcmd->flags & IWM_CMD_WANT_RESP) {
4506 1.91 mlelstv uint8_t *resp_buf;
4507 1.91 mlelstv KASSERT(!async);
4508 1.91 mlelstv KASSERT(hcmd->resp_pkt_len >= sizeof(struct iwm_rx_packet));
4509 1.91 mlelstv KASSERT(hcmd->resp_pkt_len <= IWM_CMD_RESP_MAX);
4510 1.91 mlelstv if (sc->sc_cmd_resp_pkt[idx] != NULL)
4511 1.91 mlelstv return ENOSPC;
4512 1.91 mlelstv resp_buf = kmem_zalloc(hcmd->resp_pkt_len, KM_NOSLEEP);
4513 1.91 mlelstv if (resp_buf == NULL)
4514 1.91 mlelstv return ENOMEM;
4515 1.91 mlelstv sc->sc_cmd_resp_pkt[idx] = resp_buf;
4516 1.91 mlelstv sc->sc_cmd_resp_len[idx] = hcmd->resp_pkt_len;
4517 1.91 mlelstv } else {
4518 1.91 mlelstv sc->sc_cmd_resp_pkt[idx] = NULL;
4519 1.91 mlelstv sc->sc_cmd_resp_len[idx] = 0;
4520 1.91 mlelstv }
4521 1.1 pooka
4522 1.1 pooka /*
4523 1.1 pooka * Is the hardware still available? (after e.g. above wait).
4524 1.1 pooka */
4525 1.1 pooka s = splnet();
4526 1.1 pooka
4527 1.91 mlelstv desc = &ring->desc[idx];
4528 1.91 mlelstv txdata = &ring->data[idx];
4529 1.45 nonaka
4530 1.45 nonaka group_id = iwm_cmd_groupid(code);
4531 1.45 nonaka if (group_id != 0) {
4532 1.45 nonaka hdrlen = sizeof(cmd->hdr_wide);
4533 1.45 nonaka datasz = sizeof(cmd->data_wide);
4534 1.45 nonaka } else {
4535 1.45 nonaka hdrlen = sizeof(cmd->hdr);
4536 1.45 nonaka datasz = sizeof(cmd->data);
4537 1.45 nonaka }
4538 1.1 pooka
4539 1.45 nonaka if (paylen > datasz) {
4540 1.45 nonaka /* Command is too large to fit in pre-allocated space. */
4541 1.45 nonaka size_t totlen = hdrlen + paylen;
4542 1.45 nonaka if (paylen > IWM_MAX_CMD_PAYLOAD_SIZE) {
4543 1.91 mlelstv device_printf(sc->sc_dev,
4544 1.45 nonaka "firmware command too long (%zd bytes)\n", totlen);
4545 1.45 nonaka err = EINVAL;
4546 1.1 pooka goto out;
4547 1.1 pooka }
4548 1.1 pooka m = m_gethdr(M_DONTWAIT, MT_DATA);
4549 1.1 pooka if (m == NULL) {
4550 1.91 mlelstv device_printf(sc->sc_dev,
4551 1.91 mlelstv "could not get fw cmd mbuf header\n");
4552 1.45 nonaka err = ENOMEM;
4553 1.1 pooka goto out;
4554 1.1 pooka }
4555 1.94 mlelstv MCLAIM(m, &sc->sc_ec.ec_tx_mowner);
4556 1.1 pooka MEXTMALLOC(m, IWM_RBUF_SIZE, M_DONTWAIT);
4557 1.1 pooka if (!(m->m_flags & M_EXT)) {
4558 1.91 mlelstv device_printf(sc->sc_dev,
4559 1.45 nonaka "could not get fw cmd mbuf (%zd bytes)\n", totlen);
4560 1.1 pooka m_freem(m);
4561 1.45 nonaka err = ENOMEM;
4562 1.1 pooka goto out;
4563 1.1 pooka }
4564 1.1 pooka cmd = mtod(m, struct iwm_device_cmd *);
4565 1.45 nonaka err = bus_dmamap_load(sc->sc_dmat, txdata->map, cmd,
4566 1.45 nonaka totlen, NULL, BUS_DMA_NOWAIT | BUS_DMA_WRITE);
4567 1.45 nonaka if (err) {
4568 1.91 mlelstv device_printf(sc->sc_dev,
4569 1.45 nonaka "could not load fw cmd mbuf (%zd bytes)\n", totlen);
4570 1.1 pooka m_freem(m);
4571 1.1 pooka goto out;
4572 1.1 pooka }
4573 1.45 nonaka txdata->m = m;
4574 1.45 nonaka paddr = txdata->map->dm_segs[0].ds_addr;
4575 1.1 pooka } else {
4576 1.91 mlelstv cmd = &ring->cmd[idx];
4577 1.45 nonaka paddr = txdata->cmd_paddr;
4578 1.1 pooka }
4579 1.1 pooka
4580 1.45 nonaka if (group_id != 0) {
4581 1.45 nonaka cmd->hdr_wide.opcode = iwm_cmd_opcode(code);
4582 1.45 nonaka cmd->hdr_wide.group_id = group_id;
4583 1.45 nonaka cmd->hdr_wide.qid = ring->qid;
4584 1.91 mlelstv cmd->hdr_wide.idx = idx;
4585 1.45 nonaka cmd->hdr_wide.length = htole16(paylen);
4586 1.45 nonaka cmd->hdr_wide.version = iwm_cmd_version(code);
4587 1.45 nonaka data = cmd->data_wide;
4588 1.45 nonaka } else {
4589 1.45 nonaka cmd->hdr.code = code;
4590 1.45 nonaka cmd->hdr.flags = 0;
4591 1.45 nonaka cmd->hdr.qid = ring->qid;
4592 1.91 mlelstv cmd->hdr.idx = idx;
4593 1.45 nonaka data = cmd->data;
4594 1.45 nonaka }
4595 1.1 pooka
4596 1.1 pooka for (i = 0, off = 0; i < __arraycount(hcmd->data); i++) {
4597 1.1 pooka if (hcmd->len[i] == 0)
4598 1.1 pooka continue;
4599 1.45 nonaka memcpy(data + off, hcmd->data[i], hcmd->len[i]);
4600 1.1 pooka off += hcmd->len[i];
4601 1.1 pooka }
4602 1.1 pooka KASSERT(off == paylen);
4603 1.1 pooka
4604 1.1 pooka /* lo field is not aligned */
4605 1.1 pooka addr_lo = htole32((uint32_t)paddr);
4606 1.1 pooka memcpy(&desc->tbs[0].lo, &addr_lo, sizeof(uint32_t));
4607 1.1 pooka desc->tbs[0].hi_n_len = htole16(iwm_get_dma_hi_addr(paddr)
4608 1.45 nonaka | ((hdrlen + paylen) << 4));
4609 1.1 pooka desc->num_tbs = 1;
4610 1.1 pooka
4611 1.9 nonaka DPRINTFN(8, ("iwm_send_cmd 0x%x size=%zu %s\n",
4612 1.52 nonaka code, hdrlen + paylen, async ? " (async)" : ""));
4613 1.1 pooka
4614 1.45 nonaka if (paylen > datasz) {
4615 1.91 mlelstv bus_dmamap_sync(sc->sc_dmat, txdata->map, 0,
4616 1.91 mlelstv hdrlen + paylen, BUS_DMASYNC_PREWRITE);
4617 1.1 pooka } else {
4618 1.1 pooka bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map,
4619 1.91 mlelstv (uint8_t *)cmd - (uint8_t *)ring->cmd_dma.vaddr,
4620 1.91 mlelstv hdrlen + paylen, BUS_DMASYNC_PREWRITE);
4621 1.1 pooka }
4622 1.1 pooka bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,
4623 1.91 mlelstv (uint8_t *)desc - (uint8_t *)ring->desc_dma.vaddr,
4624 1.91 mlelstv sizeof(*desc), BUS_DMASYNC_PREWRITE);
4625 1.1 pooka
4626 1.91 mlelstv /*
4627 1.91 mlelstv * Wake up the NIC to make sure that the firmware will see the host
4628 1.91 mlelstv * command - we will let the NIC sleep once all the host commands
4629 1.91 mlelstv * returned. This needs to be done only on 7000 family NICs.
4630 1.91 mlelstv */
4631 1.91 mlelstv if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
4632 1.91 mlelstv if (ring->queued == 0 && !iwm_nic_lock(sc)) {
4633 1.91 mlelstv err = EBUSY;
4634 1.91 mlelstv goto out;
4635 1.91 mlelstv }
4636 1.91 mlelstv }
4637 1.1 pooka
4638 1.1 pooka iwm_update_sched(sc, ring->qid, ring->cur, 0, 0);
4639 1.91 mlelstv
4640 1.1 pooka DPRINTF(("sending command 0x%x qid %d, idx %d\n",
4641 1.1 pooka code, ring->qid, ring->cur));
4642 1.1 pooka
4643 1.1 pooka /* Kick command ring. */
4644 1.91 mlelstv ring->queued++;
4645 1.1 pooka ring->cur = (ring->cur + 1) % IWM_TX_RING_COUNT;
4646 1.1 pooka IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
4647 1.1 pooka
4648 1.1 pooka if (!async) {
4649 1.67 nonaka err = tsleep(desc, PCATCH, "iwmcmd", mstohz(2000));
4650 1.45 nonaka if (err == 0) {
4651 1.1 pooka /* if hardware is no longer up, return error */
4652 1.1 pooka if (generation != sc->sc_generation) {
4653 1.45 nonaka err = ENXIO;
4654 1.91 mlelstv goto out;
4655 1.91 mlelstv }
4656 1.91 mlelstv
4657 1.91 mlelstv /* Response buffer will be freed in iwm_free_resp(). */
4658 1.91 mlelstv hcmd->resp_pkt = (void *)sc->sc_cmd_resp_pkt[idx];
4659 1.91 mlelstv sc->sc_cmd_resp_pkt[idx] = NULL;
4660 1.91 mlelstv sc->sc_cmd_resp_len[idx] = 0;
4661 1.91 mlelstv } else if (generation == sc->sc_generation) {
4662 1.91 mlelstv if (sc->sc_cmd_resp_pkt[idx] != NULL) {
4663 1.91 mlelstv KASSERT(sc->sc_cmd_resp_len[idx] > 0);
4664 1.91 mlelstv kmem_free(sc->sc_cmd_resp_pkt[idx],
4665 1.91 mlelstv sc->sc_cmd_resp_len[idx]);
4666 1.1 pooka }
4667 1.91 mlelstv sc->sc_cmd_resp_pkt[idx] = NULL;
4668 1.91 mlelstv sc->sc_cmd_resp_len[idx] = 0;
4669 1.1 pooka }
4670 1.1 pooka }
4671 1.1 pooka out:
4672 1.1 pooka splx(s);
4673 1.1 pooka
4674 1.45 nonaka return err;
4675 1.1 pooka }
4676 1.1 pooka
4677 1.4 nonaka static int
4678 1.45 nonaka iwm_send_cmd_pdu(struct iwm_softc *sc, uint32_t id, uint32_t flags,
4679 1.45 nonaka uint16_t len, const void *data)
4680 1.1 pooka {
4681 1.1 pooka struct iwm_host_cmd cmd = {
4682 1.1 pooka .id = id,
4683 1.1 pooka .len = { len, },
4684 1.1 pooka .data = { data, },
4685 1.1 pooka .flags = flags,
4686 1.1 pooka };
4687 1.1 pooka
4688 1.1 pooka return iwm_send_cmd(sc, &cmd);
4689 1.1 pooka }
4690 1.1 pooka
4691 1.4 nonaka static int
4692 1.45 nonaka iwm_send_cmd_status(struct iwm_softc *sc, struct iwm_host_cmd *cmd,
4693 1.45 nonaka uint32_t *status)
4694 1.1 pooka {
4695 1.1 pooka struct iwm_rx_packet *pkt;
4696 1.1 pooka struct iwm_cmd_response *resp;
4697 1.45 nonaka int err, resp_len;
4698 1.1 pooka
4699 1.91 mlelstv KASSERT((cmd->flags & IWM_CMD_WANT_RESP) == 0);
4700 1.91 mlelstv cmd->flags |= IWM_CMD_WANT_RESP;
4701 1.91 mlelstv cmd->resp_pkt_len = sizeof(*pkt) + sizeof(*resp);
4702 1.1 pooka
4703 1.45 nonaka err = iwm_send_cmd(sc, cmd);
4704 1.45 nonaka if (err)
4705 1.45 nonaka return err;
4706 1.91 mlelstv
4707 1.1 pooka pkt = cmd->resp_pkt;
4708 1.91 mlelstv if (pkt == NULL || (pkt->hdr.flags & IWM_CMD_FAILED_MSK))
4709 1.91 mlelstv return EIO;
4710 1.1 pooka
4711 1.1 pooka resp_len = iwm_rx_packet_payload_len(pkt);
4712 1.1 pooka if (resp_len != sizeof(*resp)) {
4713 1.91 mlelstv iwm_free_resp(sc, cmd);
4714 1.91 mlelstv return EIO;
4715 1.1 pooka }
4716 1.1 pooka
4717 1.1 pooka resp = (void *)pkt->data;
4718 1.1 pooka *status = le32toh(resp->status);
4719 1.1 pooka iwm_free_resp(sc, cmd);
4720 1.45 nonaka return err;
4721 1.1 pooka }
4722 1.1 pooka
4723 1.4 nonaka static int
4724 1.45 nonaka iwm_send_cmd_pdu_status(struct iwm_softc *sc, uint32_t id, uint16_t len,
4725 1.45 nonaka const void *data, uint32_t *status)
4726 1.1 pooka {
4727 1.1 pooka struct iwm_host_cmd cmd = {
4728 1.1 pooka .id = id,
4729 1.1 pooka .len = { len, },
4730 1.1 pooka .data = { data, },
4731 1.1 pooka };
4732 1.1 pooka
4733 1.45 nonaka return iwm_send_cmd_status(sc, &cmd, status);
4734 1.1 pooka }
4735 1.1 pooka
4736 1.4 nonaka static void
4737 1.1 pooka iwm_free_resp(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
4738 1.1 pooka {
4739 1.91 mlelstv KASSERT(hcmd != NULL);
4740 1.91 mlelstv KASSERT((hcmd->flags & IWM_CMD_WANT_RESP) == IWM_CMD_WANT_RESP);
4741 1.91 mlelstv if (hcmd->resp_pkt != NULL) {
4742 1.91 mlelstv KASSERT(hcmd->resp_pkt_len > 0);
4743 1.91 mlelstv kmem_free(hcmd->resp_pkt, hcmd->resp_pkt_len);
4744 1.91 mlelstv }
4745 1.91 mlelstv hcmd->resp_pkt = NULL;
4746 1.1 pooka }
4747 1.1 pooka
4748 1.4 nonaka static void
4749 1.45 nonaka iwm_cmd_done(struct iwm_softc *sc, int qid, int idx)
4750 1.1 pooka {
4751 1.91 mlelstv struct iwm_tx_ring *ring = &sc->txq[sc->cmdqid];
4752 1.1 pooka struct iwm_tx_data *data;
4753 1.1 pooka
4754 1.91 mlelstv if (qid != sc->cmdqid) {
4755 1.1 pooka return; /* Not a command ack. */
4756 1.1 pooka }
4757 1.1 pooka
4758 1.45 nonaka data = &ring->data[idx];
4759 1.1 pooka
4760 1.1 pooka if (data->m != NULL) {
4761 1.1 pooka bus_dmamap_sync(sc->sc_dmat, data->map, 0,
4762 1.1 pooka data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
4763 1.1 pooka bus_dmamap_unload(sc->sc_dmat, data->map);
4764 1.1 pooka m_freem(data->m);
4765 1.1 pooka data->m = NULL;
4766 1.1 pooka }
4767 1.45 nonaka wakeup(&ring->desc[idx]);
4768 1.59 nonaka
4769 1.89 mlelstv if (ring->queued == 0) {
4770 1.89 mlelstv device_printf(sc->sc_dev, "cmd_done with empty ring\n");
4771 1.91 mlelstv } else if (--ring->queued == 0) {
4772 1.91 mlelstv /*
4773 1.91 mlelstv * 7000 family NICs are locked while commands are in progress.
4774 1.91 mlelstv * All commands are now done so we may unlock the NIC again.
4775 1.91 mlelstv */
4776 1.91 mlelstv if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
4777 1.91 mlelstv iwm_nic_unlock(sc);
4778 1.91 mlelstv }
4779 1.89 mlelstv }
4780 1.1 pooka }
4781 1.1 pooka
4782 1.1 pooka /*
4783 1.1 pooka * necessary only for block ack mode
4784 1.1 pooka */
4785 1.1 pooka void
4786 1.1 pooka iwm_update_sched(struct iwm_softc *sc, int qid, int idx, uint8_t sta_id,
4787 1.45 nonaka uint16_t len)
4788 1.1 pooka {
4789 1.1 pooka struct iwm_agn_scd_bc_tbl *scd_bc_tbl;
4790 1.91 mlelstv uint16_t val;
4791 1.1 pooka
4792 1.1 pooka scd_bc_tbl = sc->sched_dma.vaddr;
4793 1.1 pooka
4794 1.91 mlelstv len += IWM_TX_CRC_SIZE + IWM_TX_DELIMITER_SIZE;
4795 1.1 pooka if (sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_DW_BC_TABLE)
4796 1.1 pooka len = roundup(len, 4) / 4;
4797 1.1 pooka
4798 1.91 mlelstv val = htole16(sta_id << 12 | len);
4799 1.91 mlelstv
4800 1.91 mlelstv bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map,
4801 1.91 mlelstv 0, sc->sched_dma.size, BUS_DMASYNC_PREWRITE);
4802 1.1 pooka
4803 1.1 pooka /* Update TX scheduler. */
4804 1.91 mlelstv scd_bc_tbl[qid].tfd_offset[idx] = val;
4805 1.91 mlelstv if (idx < IWM_TFD_QUEUE_SIZE_BC_DUP)
4806 1.91 mlelstv scd_bc_tbl[qid].tfd_offset[IWM_TFD_QUEUE_SIZE_MAX + idx] = val;
4807 1.1 pooka bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map,
4808 1.91 mlelstv 0, sc->sched_dma.size, BUS_DMASYNC_POSTWRITE);
4809 1.1 pooka }
4810 1.1 pooka
4811 1.1 pooka /*
4812 1.1 pooka * Fill in various bit for management frames, and leave them
4813 1.1 pooka * unfilled for data frames (firmware takes care of that).
4814 1.1 pooka * Return the selected TX rate.
4815 1.1 pooka */
4816 1.4 nonaka static const struct iwm_rate *
4817 1.1 pooka iwm_tx_fill_cmd(struct iwm_softc *sc, struct iwm_node *in,
4818 1.45 nonaka struct ieee80211_frame *wh, struct iwm_tx_cmd *tx)
4819 1.1 pooka {
4820 1.24 nonaka struct ieee80211com *ic = &sc->sc_ic;
4821 1.28 nonaka struct ieee80211_node *ni = &in->in_ni;
4822 1.1 pooka const struct iwm_rate *rinfo;
4823 1.1 pooka int type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
4824 1.61 nonaka int ridx, rate_flags, i, ind;
4825 1.28 nonaka int nrates = ni->ni_rates.rs_nrates;
4826 1.1 pooka
4827 1.1 pooka tx->rts_retry_limit = IWM_RTS_DFAULT_RETRY_LIMIT;
4828 1.1 pooka tx->data_retry_limit = IWM_DEFAULT_TX_RETRY;
4829 1.1 pooka
4830 1.45 nonaka if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
4831 1.45 nonaka type != IEEE80211_FC0_TYPE_DATA) {
4832 1.28 nonaka /* for non-data, use the lowest supported rate */
4833 1.45 nonaka ridx = (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) ?
4834 1.28 nonaka IWM_RIDX_OFDM : IWM_RIDX_CCK;
4835 1.45 nonaka tx->data_retry_limit = IWM_MGMT_DFAULT_RETRY_LIMIT;
4836 1.45 nonaka #ifndef IEEE80211_NO_HT
4837 1.45 nonaka } else if (ic->ic_fixed_mcs != -1) {
4838 1.45 nonaka ridx = sc->sc_fixed_ridx;
4839 1.45 nonaka #endif
4840 1.28 nonaka } else if (ic->ic_fixed_rate != -1) {
4841 1.28 nonaka ridx = sc->sc_fixed_ridx;
4842 1.28 nonaka } else {
4843 1.28 nonaka /* for data frames, use RS table */
4844 1.45 nonaka tx->initial_rate_index = 0;
4845 1.8 nonaka tx->tx_flags |= htole32(IWM_TX_CMD_FLG_STA_RATE);
4846 1.45 nonaka DPRINTFN(12, ("start with txrate %d\n",
4847 1.45 nonaka tx->initial_rate_index));
4848 1.45 nonaka #ifndef IEEE80211_NO_HT
4849 1.45 nonaka if (ni->ni_flags & IEEE80211_NODE_HT) {
4850 1.45 nonaka ridx = iwm_mcs2ridx[ni->ni_txmcs];
4851 1.45 nonaka return &iwm_rates[ridx];
4852 1.45 nonaka }
4853 1.45 nonaka #endif
4854 1.45 nonaka ridx = (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) ?
4855 1.45 nonaka IWM_RIDX_OFDM : IWM_RIDX_CCK;
4856 1.45 nonaka for (i = 0; i < nrates; i++) {
4857 1.45 nonaka if (iwm_rates[i].rate == (ni->ni_txrate &
4858 1.45 nonaka IEEE80211_RATE_VAL)) {
4859 1.45 nonaka ridx = i;
4860 1.45 nonaka break;
4861 1.45 nonaka }
4862 1.45 nonaka }
4863 1.28 nonaka return &iwm_rates[ridx];
4864 1.1 pooka }
4865 1.1 pooka
4866 1.1 pooka rinfo = &iwm_rates[ridx];
4867 1.61 nonaka for (i = 0, ind = sc->sc_mgmt_last_antenna;
4868 1.61 nonaka i < IWM_RATE_MCS_ANT_NUM; i++) {
4869 1.61 nonaka ind = (ind + 1) % IWM_RATE_MCS_ANT_NUM;
4870 1.61 nonaka if (iwm_fw_valid_tx_ant(sc) & (1 << ind)) {
4871 1.61 nonaka sc->sc_mgmt_last_antenna = ind;
4872 1.61 nonaka break;
4873 1.61 nonaka }
4874 1.61 nonaka }
4875 1.61 nonaka rate_flags = (1 << sc->sc_mgmt_last_antenna) << IWM_RATE_MCS_ANT_POS;
4876 1.1 pooka if (IWM_RIDX_IS_CCK(ridx))
4877 1.1 pooka rate_flags |= IWM_RATE_MCS_CCK_MSK;
4878 1.45 nonaka #ifndef IEEE80211_NO_HT
4879 1.45 nonaka if ((ni->ni_flags & IEEE80211_NODE_HT) &&
4880 1.45 nonaka rinfo->ht_plcp != IWM_RATE_HT_SISO_MCS_INV_PLCP) {
4881 1.45 nonaka rate_flags |= IWM_RATE_MCS_HT_MSK;
4882 1.45 nonaka tx->rate_n_flags = htole32(rate_flags | rinfo->ht_plcp);
4883 1.45 nonaka } else
4884 1.45 nonaka #endif
4885 1.45 nonaka tx->rate_n_flags = htole32(rate_flags | rinfo->plcp);
4886 1.1 pooka
4887 1.1 pooka return rinfo;
4888 1.1 pooka }
4889 1.1 pooka
4890 1.1 pooka #define TB0_SIZE 16
4891 1.4 nonaka static int
4892 1.1 pooka iwm_tx(struct iwm_softc *sc, struct mbuf *m, struct ieee80211_node *ni, int ac)
4893 1.1 pooka {
4894 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
4895 1.45 nonaka struct iwm_node *in = (struct iwm_node *)ni;
4896 1.1 pooka struct iwm_tx_ring *ring;
4897 1.1 pooka struct iwm_tx_data *data;
4898 1.1 pooka struct iwm_tfd *desc;
4899 1.1 pooka struct iwm_device_cmd *cmd;
4900 1.1 pooka struct iwm_tx_cmd *tx;
4901 1.1 pooka struct ieee80211_frame *wh;
4902 1.1 pooka struct ieee80211_key *k = NULL;
4903 1.1 pooka struct mbuf *m1;
4904 1.1 pooka const struct iwm_rate *rinfo;
4905 1.1 pooka uint32_t flags;
4906 1.1 pooka u_int hdrlen;
4907 1.1 pooka bus_dma_segment_t *seg;
4908 1.91 mlelstv uint8_t tid, type, subtype;
4909 1.45 nonaka int i, totlen, err, pad;
4910 1.91 mlelstv int qid;
4911 1.91 mlelstv #ifndef IEEE80211_NO_HT
4912 1.91 mlelstv int hasqos;
4913 1.91 mlelstv #endif
4914 1.1 pooka
4915 1.1 pooka wh = mtod(m, struct ieee80211_frame *);
4916 1.91 mlelstv type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
4917 1.91 mlelstv subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
4918 1.1 pooka hdrlen = ieee80211_anyhdrsize(wh);
4919 1.1 pooka
4920 1.91 mlelstv #ifndef IEEE80211_NO_HT
4921 1.91 mlelstv hasqos = ieee80211_has_qos(wh);
4922 1.91 mlelstv #endif
4923 1.91 mlelstv if (type == IEEE80211_FC0_TYPE_DATA)
4924 1.91 mlelstv tid = IWM_TID_NON_QOS;
4925 1.91 mlelstv else
4926 1.91 mlelstv tid = IWM_MAX_TID_COUNT;
4927 1.91 mlelstv
4928 1.91 mlelstv /*
4929 1.91 mlelstv * Map EDCA categories to Tx data queues.
4930 1.91 mlelstv *
4931 1.91 mlelstv * We use static data queue assignments even in DQA mode. We do not
4932 1.91 mlelstv * need to share Tx queues between stations because we only implement
4933 1.91 mlelstv * client mode; the firmware's station table contains only one entry
4934 1.91 mlelstv * which represents our access point.
4935 1.91 mlelstv */
4936 1.91 mlelstv if (ic->ic_opmode == IEEE80211_M_MONITOR) {
4937 1.91 mlelstv if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))
4938 1.91 mlelstv qid = IWM_DQA_INJECT_MONITOR_QUEUE;
4939 1.91 mlelstv else
4940 1.91 mlelstv qid = IWM_AUX_QUEUE;
4941 1.91 mlelstv } else if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))
4942 1.91 mlelstv qid = IWM_DQA_MIN_MGMT_QUEUE + ac;
4943 1.91 mlelstv else
4944 1.91 mlelstv qid = ac;
4945 1.91 mlelstv
4946 1.91 mlelstv #ifndef IEEE80211_NO_HT
4947 1.91 mlelstv /* If possible, put this frame on an aggregation queue. */
4948 1.91 mlelstv if (hasqos) {
4949 1.91 mlelstv struct ieee80211_tx_ba *ba;
4950 1.91 mlelstv uint16_t qos = ieee80211_get_qos(wh);
4951 1.91 mlelstv int qostid = qos & IEEE80211_QOS_TID;
4952 1.91 mlelstv int agg_qid = IWM_FIRST_AGG_TX_QUEUE + qostid;
4953 1.91 mlelstv
4954 1.91 mlelstv ba = &ni->ni_tx_ba[qostid];
4955 1.91 mlelstv if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
4956 1.91 mlelstv type == IEEE80211_FC0_TYPE_DATA &&
4957 1.91 mlelstv subtype != IEEE80211_FC0_SUBTYPE_NODATA &&
4958 1.91 mlelstv (sc->tx_ba_queue_mask & (1 << agg_qid)) &&
4959 1.91 mlelstv ba->ba_state == IEEE80211_BA_AGREED) {
4960 1.91 mlelstv qid = agg_qid;
4961 1.91 mlelstv tid = qostid;
4962 1.91 mlelstv ac = ieee80211_up_to_ac(ic, qostid);
4963 1.91 mlelstv }
4964 1.91 mlelstv }
4965 1.91 mlelstv #endif
4966 1.1 pooka
4967 1.91 mlelstv ring = &sc->txq[qid];
4968 1.91 mlelstv if (ring == NULL) {
4969 1.91 mlelstv device_printf(sc->sc_dev, "no ring data for queue %d\n", qid);
4970 1.91 mlelstv m_freem(m);
4971 1.91 mlelstv return EFAULT;
4972 1.91 mlelstv }
4973 1.1 pooka desc = &ring->desc[ring->cur];
4974 1.1 pooka memset(desc, 0, sizeof(*desc));
4975 1.1 pooka data = &ring->data[ring->cur];
4976 1.1 pooka
4977 1.1 pooka cmd = &ring->cmd[ring->cur];
4978 1.1 pooka cmd->hdr.code = IWM_TX_CMD;
4979 1.1 pooka cmd->hdr.flags = 0;
4980 1.1 pooka cmd->hdr.qid = ring->qid;
4981 1.1 pooka cmd->hdr.idx = ring->cur;
4982 1.1 pooka
4983 1.1 pooka tx = (void *)cmd->data;
4984 1.1 pooka memset(tx, 0, sizeof(*tx));
4985 1.1 pooka
4986 1.1 pooka rinfo = iwm_tx_fill_cmd(sc, in, wh, tx);
4987 1.1 pooka
4988 1.48 nonaka if (__predict_false(sc->sc_drvbpf != NULL)) {
4989 1.1 pooka struct iwm_tx_radiotap_header *tap = &sc->sc_txtap;
4990 1.1 pooka
4991 1.1 pooka tap->wt_flags = 0;
4992 1.1 pooka tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq);
4993 1.1 pooka tap->wt_chan_flags = htole16(ni->ni_chan->ic_flags);
4994 1.45 nonaka #ifndef IEEE80211_NO_HT
4995 1.45 nonaka if ((ni->ni_flags & IEEE80211_NODE_HT) &&
4996 1.45 nonaka !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
4997 1.45 nonaka type == IEEE80211_FC0_TYPE_DATA &&
4998 1.45 nonaka rinfo->plcp == IWM_RATE_INVM_PLCP) {
4999 1.45 nonaka tap->wt_rate = (0x80 | rinfo->ht_plcp);
5000 1.45 nonaka } else
5001 1.45 nonaka #endif
5002 1.45 nonaka tap->wt_rate = rinfo->rate;
5003 1.1 pooka tap->wt_hwqueue = ac;
5004 1.1 pooka if (wh->i_fc[1] & IEEE80211_FC1_WEP)
5005 1.1 pooka tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
5006 1.1 pooka
5007 1.83 msaitoh bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m, BPF_D_OUT);
5008 1.1 pooka }
5009 1.1 pooka
5010 1.1 pooka /* Encrypt the frame if need be. */
5011 1.1 pooka if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
5012 1.1 pooka k = ieee80211_crypto_encap(ic, ni, m);
5013 1.1 pooka if (k == NULL) {
5014 1.1 pooka m_freem(m);
5015 1.1 pooka return ENOBUFS;
5016 1.1 pooka }
5017 1.1 pooka /* Packet header may have moved, reset our local pointer. */
5018 1.1 pooka wh = mtod(m, struct ieee80211_frame *);
5019 1.1 pooka }
5020 1.1 pooka totlen = m->m_pkthdr.len;
5021 1.1 pooka
5022 1.1 pooka flags = 0;
5023 1.1 pooka if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
5024 1.1 pooka flags |= IWM_TX_CMD_FLG_ACK;
5025 1.1 pooka }
5026 1.1 pooka
5027 1.45 nonaka if (type == IEEE80211_FC0_TYPE_DATA &&
5028 1.45 nonaka !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
5029 1.45 nonaka (totlen + IEEE80211_CRC_LEN > ic->ic_rtsthreshold ||
5030 1.45 nonaka (ic->ic_flags & IEEE80211_F_USEPROT)))
5031 1.1 pooka flags |= IWM_TX_CMD_FLG_PROT_REQUIRE;
5032 1.1 pooka
5033 1.1 pooka if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
5034 1.1 pooka type != IEEE80211_FC0_TYPE_DATA)
5035 1.45 nonaka tx->sta_id = IWM_AUX_STA_ID;
5036 1.1 pooka else
5037 1.1 pooka tx->sta_id = IWM_STATION_ID;
5038 1.1 pooka
5039 1.1 pooka if (type == IEEE80211_FC0_TYPE_MGT) {
5040 1.1 pooka if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ ||
5041 1.1 pooka subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ)
5042 1.54 nonaka tx->pm_frame_timeout = htole16(IWM_PM_FRAME_ASSOC);
5043 1.1 pooka else
5044 1.54 nonaka tx->pm_frame_timeout = htole16(IWM_PM_FRAME_MGMT);
5045 1.1 pooka } else {
5046 1.91 mlelstv #ifndef IEEE80211_NO_HT
5047 1.91 mlelstv if (type == IEEE80211_FC0_TYPE_CTL &&
5048 1.91 mlelstv subtype == IEEE80211_FC0_SUBTYPE_BAR) {
5049 1.91 mlelstv struct ieee80211_frame_min *mwh;
5050 1.91 mlelstv uint8_t *barfrm;
5051 1.91 mlelstv uint16_t ctl;
5052 1.91 mlelstv
5053 1.91 mlelstv mwh = mtod(m, struct ieee80211_frame_min *);
5054 1.91 mlelstv barfrm = (uint8_t *)&mwh[1];
5055 1.91 mlelstv ctl = barfrm[1] << 8 | barfrm[0];
5056 1.91 mlelstv tid = (ctl & IEEE80211_BA_TID_INFO_MASK) >>
5057 1.91 mlelstv IEEE80211_BA_TID_INFO_SHIFT;
5058 1.91 mlelstv flags |= IWM_TX_CMD_FLG_ACK | IWM_TX_CMD_FLG_BAR;
5059 1.91 mlelstv tx->data_retry_limit = IWM_BAR_DEFAULT_RETRY_LIMIT;
5060 1.91 mlelstv }
5061 1.91 mlelstv #endif
5062 1.91 mlelstv
5063 1.54 nonaka tx->pm_frame_timeout = htole16(IWM_PM_FRAME_NONE);
5064 1.1 pooka }
5065 1.1 pooka
5066 1.8 nonaka if (hdrlen & 3) {
5067 1.8 nonaka /* First segment length must be a multiple of 4. */
5068 1.8 nonaka flags |= IWM_TX_CMD_FLG_MH_PAD;
5069 1.8 nonaka pad = 4 - (hdrlen & 3);
5070 1.8 nonaka } else
5071 1.8 nonaka pad = 0;
5072 1.1 pooka
5073 1.1 pooka tx->driver_txop = 0;
5074 1.1 pooka tx->next_frame_len = 0;
5075 1.1 pooka
5076 1.1 pooka tx->len = htole16(totlen);
5077 1.1 pooka tx->tid_tspec = tid;
5078 1.1 pooka tx->life_time = htole32(IWM_TX_CMD_LIFE_TIME_INFINITE);
5079 1.1 pooka
5080 1.1 pooka /* Set physical address of "scratch area". */
5081 1.1 pooka tx->dram_lsb_ptr = htole32(data->scratch_paddr);
5082 1.1 pooka tx->dram_msb_ptr = iwm_get_dma_hi_addr(data->scratch_paddr);
5083 1.1 pooka
5084 1.1 pooka /* Copy 802.11 header in TX command. */
5085 1.61 nonaka memcpy(tx + 1, wh, hdrlen);
5086 1.1 pooka
5087 1.1 pooka flags |= IWM_TX_CMD_FLG_BT_DIS | IWM_TX_CMD_FLG_SEQ_CTL;
5088 1.1 pooka
5089 1.1 pooka tx->sec_ctl = 0;
5090 1.1 pooka tx->tx_flags |= htole32(flags);
5091 1.1 pooka
5092 1.1 pooka /* Trim 802.11 header. */
5093 1.1 pooka m_adj(m, hdrlen);
5094 1.1 pooka
5095 1.45 nonaka err = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m,
5096 1.1 pooka BUS_DMA_NOWAIT | BUS_DMA_WRITE);
5097 1.45 nonaka if (err) {
5098 1.45 nonaka if (err != EFBIG) {
5099 1.3 nonaka aprint_error_dev(sc->sc_dev,
5100 1.45 nonaka "can't map mbuf (error %d)\n", err);
5101 1.1 pooka m_freem(m);
5102 1.45 nonaka return err;
5103 1.1 pooka }
5104 1.1 pooka /* Too many DMA segments, linearize mbuf. */
5105 1.1 pooka MGETHDR(m1, M_DONTWAIT, MT_DATA);
5106 1.1 pooka if (m1 == NULL) {
5107 1.1 pooka m_freem(m);
5108 1.1 pooka return ENOBUFS;
5109 1.1 pooka }
5110 1.90 mlelstv MCLAIM(m1, &sc->sc_ec.ec_rx_mowner);
5111 1.1 pooka if (m->m_pkthdr.len > MHLEN) {
5112 1.1 pooka MCLGET(m1, M_DONTWAIT);
5113 1.1 pooka if (!(m1->m_flags & M_EXT)) {
5114 1.1 pooka m_freem(m);
5115 1.1 pooka m_freem(m1);
5116 1.1 pooka return ENOBUFS;
5117 1.1 pooka }
5118 1.1 pooka }
5119 1.1 pooka m_copydata(m, 0, m->m_pkthdr.len, mtod(m1, void *));
5120 1.1 pooka m1->m_pkthdr.len = m1->m_len = m->m_pkthdr.len;
5121 1.1 pooka m_freem(m);
5122 1.1 pooka m = m1;
5123 1.1 pooka
5124 1.45 nonaka err = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m,
5125 1.1 pooka BUS_DMA_NOWAIT | BUS_DMA_WRITE);
5126 1.45 nonaka if (err) {
5127 1.3 nonaka aprint_error_dev(sc->sc_dev,
5128 1.45 nonaka "can't map mbuf (error %d)\n", err);
5129 1.1 pooka m_freem(m);
5130 1.45 nonaka return err;
5131 1.1 pooka }
5132 1.1 pooka }
5133 1.1 pooka data->m = m;
5134 1.1 pooka data->in = in;
5135 1.1 pooka data->done = 0;
5136 1.91 mlelstv #ifndef IEEE80211_NO_HT
5137 1.91 mlelstv data->txmcs = ni->ni_txmcs;
5138 1.91 mlelstv data->txrate = ni->ni_txrate;
5139 1.91 mlelstv #ifdef notyet
5140 1.91 mlelstv data->ampdu_txmcs = ni->ni_txmcs; /* updated upon Tx interrupt */
5141 1.91 mlelstv data->ampdu_txnss = ni->ni_vht_ss; /* updated upon Tx interrupt */
5142 1.91 mlelstv #endif
5143 1.91 mlelstv #endif
5144 1.1 pooka
5145 1.1 pooka DPRINTFN(8, ("sending txd %p, in %p\n", data, data->in));
5146 1.1 pooka KASSERT(data->in != NULL);
5147 1.1 pooka
5148 1.61 nonaka DPRINTFN(8, ("sending data: qid=%d idx=%d len=%d nsegs=%d type=%d "
5149 1.61 nonaka "subtype=%x tx_flags=%08x init_rateidx=%08x rate_n_flags=%08x\n",
5150 1.61 nonaka ring->qid, ring->cur, totlen, data->map->dm_nsegs, type,
5151 1.61 nonaka (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >> 4,
5152 1.61 nonaka le32toh(tx->tx_flags), le32toh(tx->initial_rate_index),
5153 1.61 nonaka le32toh(tx->rate_n_flags)));
5154 1.1 pooka
5155 1.1 pooka /* Fill TX descriptor. */
5156 1.1 pooka desc->num_tbs = 2 + data->map->dm_nsegs;
5157 1.1 pooka
5158 1.1 pooka desc->tbs[0].lo = htole32(data->cmd_paddr);
5159 1.91 mlelstv desc->tbs[0].hi_n_len = htole16(iwm_get_dma_hi_addr(data->cmd_paddr) |
5160 1.91 mlelstv (TB0_SIZE << 4));
5161 1.1 pooka desc->tbs[1].lo = htole32(data->cmd_paddr + TB0_SIZE);
5162 1.91 mlelstv desc->tbs[1].hi_n_len = htole16(iwm_get_dma_hi_addr(data->cmd_paddr) |
5163 1.1 pooka ((sizeof(struct iwm_cmd_header) + sizeof(*tx)
5164 1.91 mlelstv + hdrlen + pad - TB0_SIZE) << 4));
5165 1.1 pooka
5166 1.1 pooka /* Other DMA segments are for data payload. */
5167 1.1 pooka seg = data->map->dm_segs;
5168 1.1 pooka for (i = 0; i < data->map->dm_nsegs; i++, seg++) {
5169 1.1 pooka desc->tbs[i+2].lo = htole32(seg->ds_addr);
5170 1.47 nonaka desc->tbs[i+2].hi_n_len =
5171 1.91 mlelstv htole16(iwm_get_dma_hi_addr(seg->ds_addr)
5172 1.91 mlelstv | ((seg->ds_len) << 4));
5173 1.1 pooka }
5174 1.1 pooka
5175 1.89 mlelstv bus_dmamap_sync(sc->sc_dmat, data->map, 0, m->m_pkthdr.len,
5176 1.1 pooka BUS_DMASYNC_PREWRITE);
5177 1.1 pooka bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map,
5178 1.61 nonaka (uint8_t *)cmd - (uint8_t *)ring->cmd, sizeof(*cmd),
5179 1.61 nonaka BUS_DMASYNC_PREWRITE);
5180 1.1 pooka bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,
5181 1.61 nonaka (uint8_t *)desc - (uint8_t *)ring->desc, sizeof(*desc),
5182 1.61 nonaka BUS_DMASYNC_PREWRITE);
5183 1.1 pooka
5184 1.91 mlelstv iwm_update_sched(sc, ring->qid, ring->cur, tx->sta_id, totlen);
5185 1.1 pooka
5186 1.1 pooka /* Kick TX ring. */
5187 1.1 pooka ring->cur = (ring->cur + 1) % IWM_TX_RING_COUNT;
5188 1.1 pooka IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
5189 1.1 pooka
5190 1.1 pooka /* Mark TX ring as full if we reach a certain threshold. */
5191 1.1 pooka if (++ring->queued > IWM_TX_RING_HIMARK) {
5192 1.1 pooka sc->qfullmsk |= 1 << ring->qid;
5193 1.1 pooka }
5194 1.1 pooka
5195 1.1 pooka return 0;
5196 1.1 pooka }
5197 1.1 pooka
5198 1.1 pooka #if 0
5199 1.1 pooka /* not necessary? */
5200 1.4 nonaka static int
5201 1.45 nonaka iwm_flush_tx_path(struct iwm_softc *sc, int tfd_msk, int sync)
5202 1.1 pooka {
5203 1.1 pooka struct iwm_tx_path_flush_cmd flush_cmd = {
5204 1.1 pooka .queues_ctl = htole32(tfd_msk),
5205 1.1 pooka .flush_ctl = htole16(IWM_DUMP_TX_FIFO_FLUSH),
5206 1.1 pooka };
5207 1.45 nonaka int err;
5208 1.1 pooka
5209 1.45 nonaka err = iwm_send_cmd_pdu(sc, IWM_TXPATH_FLUSH, sync ? 0 : IWM_CMD_ASYNC,
5210 1.1 pooka sizeof(flush_cmd), &flush_cmd);
5211 1.45 nonaka if (err)
5212 1.3 nonaka aprint_error_dev(sc->sc_dev, "Flushing tx queue failed: %d\n",
5213 1.45 nonaka err);
5214 1.45 nonaka return err;
5215 1.1 pooka }
5216 1.1 pooka #endif
5217 1.1 pooka
5218 1.45 nonaka static void
5219 1.45 nonaka iwm_led_enable(struct iwm_softc *sc)
5220 1.45 nonaka {
5221 1.45 nonaka IWM_WRITE(sc, IWM_CSR_LED_REG, IWM_CSR_LED_REG_TURN_ON);
5222 1.45 nonaka }
5223 1.45 nonaka
5224 1.45 nonaka static void
5225 1.45 nonaka iwm_led_disable(struct iwm_softc *sc)
5226 1.45 nonaka {
5227 1.45 nonaka IWM_WRITE(sc, IWM_CSR_LED_REG, IWM_CSR_LED_REG_TURN_OFF);
5228 1.45 nonaka }
5229 1.45 nonaka
5230 1.45 nonaka static int
5231 1.45 nonaka iwm_led_is_enabled(struct iwm_softc *sc)
5232 1.45 nonaka {
5233 1.45 nonaka return (IWM_READ(sc, IWM_CSR_LED_REG) == IWM_CSR_LED_REG_TURN_ON);
5234 1.45 nonaka }
5235 1.45 nonaka
5236 1.45 nonaka static void
5237 1.45 nonaka iwm_led_blink_timeout(void *arg)
5238 1.45 nonaka {
5239 1.45 nonaka struct iwm_softc *sc = arg;
5240 1.45 nonaka
5241 1.45 nonaka if (iwm_led_is_enabled(sc))
5242 1.45 nonaka iwm_led_disable(sc);
5243 1.45 nonaka else
5244 1.45 nonaka iwm_led_enable(sc);
5245 1.45 nonaka
5246 1.45 nonaka callout_schedule(&sc->sc_led_blink_to, mstohz(200));
5247 1.45 nonaka }
5248 1.45 nonaka
5249 1.45 nonaka static void
5250 1.45 nonaka iwm_led_blink_start(struct iwm_softc *sc)
5251 1.45 nonaka {
5252 1.45 nonaka callout_schedule(&sc->sc_led_blink_to, mstohz(200));
5253 1.45 nonaka }
5254 1.1 pooka
5255 1.45 nonaka static void
5256 1.45 nonaka iwm_led_blink_stop(struct iwm_softc *sc)
5257 1.45 nonaka {
5258 1.45 nonaka callout_stop(&sc->sc_led_blink_to);
5259 1.45 nonaka iwm_led_disable(sc);
5260 1.45 nonaka }
5261 1.1 pooka
5262 1.1 pooka #define IWM_POWER_KEEP_ALIVE_PERIOD_SEC 25
5263 1.1 pooka
5264 1.4 nonaka static int
5265 1.45 nonaka iwm_beacon_filter_send_cmd(struct iwm_softc *sc,
5266 1.51 nonaka struct iwm_beacon_filter_cmd *cmd)
5267 1.1 pooka {
5268 1.45 nonaka return iwm_send_cmd_pdu(sc, IWM_REPLY_BEACON_FILTERING_CMD,
5269 1.45 nonaka 0, sizeof(struct iwm_beacon_filter_cmd), cmd);
5270 1.1 pooka }
5271 1.1 pooka
5272 1.4 nonaka static void
5273 1.45 nonaka iwm_beacon_filter_set_cqm_params(struct iwm_softc *sc, struct iwm_node *in,
5274 1.45 nonaka struct iwm_beacon_filter_cmd *cmd)
5275 1.1 pooka {
5276 1.1 pooka cmd->ba_enable_beacon_abort = htole32(sc->sc_bf.ba_enabled);
5277 1.1 pooka }
5278 1.1 pooka
5279 1.4 nonaka static int
5280 1.45 nonaka iwm_update_beacon_abort(struct iwm_softc *sc, struct iwm_node *in, int enable)
5281 1.1 pooka {
5282 1.1 pooka struct iwm_beacon_filter_cmd cmd = {
5283 1.1 pooka IWM_BF_CMD_CONFIG_DEFAULTS,
5284 1.1 pooka .bf_enable_beacon_filter = htole32(1),
5285 1.1 pooka .ba_enable_beacon_abort = htole32(enable),
5286 1.1 pooka };
5287 1.1 pooka
5288 1.1 pooka if (!sc->sc_bf.bf_enabled)
5289 1.1 pooka return 0;
5290 1.1 pooka
5291 1.1 pooka sc->sc_bf.ba_enabled = enable;
5292 1.45 nonaka iwm_beacon_filter_set_cqm_params(sc, in, &cmd);
5293 1.45 nonaka return iwm_beacon_filter_send_cmd(sc, &cmd);
5294 1.1 pooka }
5295 1.1 pooka
5296 1.4 nonaka static void
5297 1.45 nonaka iwm_power_build_cmd(struct iwm_softc *sc, struct iwm_node *in,
5298 1.45 nonaka struct iwm_mac_power_cmd *cmd)
5299 1.1 pooka {
5300 1.1 pooka struct ieee80211_node *ni = &in->in_ni;
5301 1.45 nonaka int dtim_period, dtim_msec, keep_alive;
5302 1.1 pooka
5303 1.1 pooka cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id,
5304 1.1 pooka in->in_color));
5305 1.45 nonaka if (ni->ni_dtim_period)
5306 1.45 nonaka dtim_period = ni->ni_dtim_period;
5307 1.45 nonaka else
5308 1.45 nonaka dtim_period = 1;
5309 1.1 pooka
5310 1.1 pooka /*
5311 1.1 pooka * Regardless of power management state the driver must set
5312 1.1 pooka * keep alive period. FW will use it for sending keep alive NDPs
5313 1.1 pooka * immediately after association. Check that keep alive period
5314 1.45 nonaka * is at least 3 * DTIM.
5315 1.1 pooka */
5316 1.45 nonaka dtim_msec = dtim_period * ni->ni_intval;
5317 1.45 nonaka keep_alive = MAX(3 * dtim_msec, 1000 * IWM_POWER_KEEP_ALIVE_PERIOD_SEC);
5318 1.1 pooka keep_alive = roundup(keep_alive, 1000) / 1000;
5319 1.1 pooka cmd->keep_alive_seconds = htole16(keep_alive);
5320 1.45 nonaka
5321 1.45 nonaka #ifdef notyet
5322 1.45 nonaka cmd->flags = htole16(IWM_POWER_FLAGS_POWER_SAVE_ENA_MSK);
5323 1.45 nonaka cmd->rx_data_timeout = IWM_DEFAULT_PS_RX_DATA_TIMEOUT;
5324 1.45 nonaka cmd->tx_data_timeout = IWM_DEFAULT_PS_TX_DATA_TIMEOUT;
5325 1.45 nonaka #endif
5326 1.1 pooka }
5327 1.1 pooka
5328 1.4 nonaka static int
5329 1.45 nonaka iwm_power_mac_update_mode(struct iwm_softc *sc, struct iwm_node *in)
5330 1.1 pooka {
5331 1.45 nonaka int err;
5332 1.1 pooka int ba_enable;
5333 1.1 pooka struct iwm_mac_power_cmd cmd;
5334 1.1 pooka
5335 1.1 pooka memset(&cmd, 0, sizeof(cmd));
5336 1.1 pooka
5337 1.45 nonaka iwm_power_build_cmd(sc, in, &cmd);
5338 1.1 pooka
5339 1.45 nonaka err = iwm_send_cmd_pdu(sc, IWM_MAC_PM_POWER_TABLE, 0,
5340 1.45 nonaka sizeof(cmd), &cmd);
5341 1.45 nonaka if (err)
5342 1.45 nonaka return err;
5343 1.1 pooka
5344 1.1 pooka ba_enable = !!(cmd.flags &
5345 1.1 pooka htole16(IWM_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK));
5346 1.45 nonaka return iwm_update_beacon_abort(sc, in, ba_enable);
5347 1.1 pooka }
5348 1.1 pooka
5349 1.4 nonaka static int
5350 1.45 nonaka iwm_power_update_device(struct iwm_softc *sc)
5351 1.1 pooka {
5352 1.91 mlelstv struct iwm_device_power_cmd cmd = { };
5353 1.91 mlelstv struct ieee80211com *ic = &sc->sc_ic;
5354 1.1 pooka
5355 1.1 pooka if (!(sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_DEVICE_PS_CMD))
5356 1.1 pooka return 0;
5357 1.1 pooka
5358 1.91 mlelstv if (ic->ic_opmode != IEEE80211_M_MONITOR)
5359 1.91 mlelstv cmd.flags = htole16(IWM_DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
5360 1.91 mlelstv
5361 1.45 nonaka DPRINTF(("Sending device power command with flags = 0x%X\n",
5362 1.45 nonaka cmd.flags));
5363 1.1 pooka
5364 1.45 nonaka return iwm_send_cmd_pdu(sc, IWM_POWER_TABLE_CMD, 0, sizeof(cmd), &cmd);
5365 1.1 pooka }
5366 1.1 pooka
5367 1.45 nonaka #ifdef notyet
5368 1.4 nonaka static int
5369 1.45 nonaka iwm_enable_beacon_filter(struct iwm_softc *sc, struct iwm_node *in)
5370 1.1 pooka {
5371 1.1 pooka struct iwm_beacon_filter_cmd cmd = {
5372 1.1 pooka IWM_BF_CMD_CONFIG_DEFAULTS,
5373 1.1 pooka .bf_enable_beacon_filter = htole32(1),
5374 1.1 pooka };
5375 1.45 nonaka int err;
5376 1.1 pooka
5377 1.45 nonaka iwm_beacon_filter_set_cqm_params(sc, in, &cmd);
5378 1.45 nonaka err = iwm_beacon_filter_send_cmd(sc, &cmd);
5379 1.1 pooka
5380 1.45 nonaka if (err == 0)
5381 1.1 pooka sc->sc_bf.bf_enabled = 1;
5382 1.1 pooka
5383 1.45 nonaka return err;
5384 1.1 pooka }
5385 1.45 nonaka #endif
5386 1.1 pooka
5387 1.4 nonaka static int
5388 1.45 nonaka iwm_disable_beacon_filter(struct iwm_softc *sc)
5389 1.1 pooka {
5390 1.1 pooka struct iwm_beacon_filter_cmd cmd;
5391 1.45 nonaka int err;
5392 1.1 pooka
5393 1.1 pooka memset(&cmd, 0, sizeof(cmd));
5394 1.1 pooka if ((sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_BF_UPDATED) == 0)
5395 1.1 pooka return 0;
5396 1.1 pooka
5397 1.45 nonaka err = iwm_beacon_filter_send_cmd(sc, &cmd);
5398 1.45 nonaka if (err == 0)
5399 1.1 pooka sc->sc_bf.bf_enabled = 0;
5400 1.1 pooka
5401 1.45 nonaka return err;
5402 1.1 pooka }
5403 1.1 pooka
5404 1.4 nonaka static int
5405 1.45 nonaka iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node *in, int update)
5406 1.1 pooka {
5407 1.91 mlelstv struct iwm_add_sta_cmd add_sta_cmd;
5408 1.45 nonaka int err;
5409 1.45 nonaka uint32_t status;
5410 1.91 mlelstv size_t cmdsize;
5411 1.91 mlelstv struct ieee80211com *ic = &sc->sc_ic;
5412 1.1 pooka
5413 1.45 nonaka memset(&add_sta_cmd, 0, sizeof(add_sta_cmd));
5414 1.1 pooka
5415 1.91 mlelstv if (ic->ic_opmode == IEEE80211_M_MONITOR)
5416 1.91 mlelstv add_sta_cmd.sta_id = IWM_MONITOR_STA_ID;
5417 1.91 mlelstv else
5418 1.91 mlelstv add_sta_cmd.sta_id = IWM_STATION_ID;
5419 1.91 mlelstv if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE)) {
5420 1.91 mlelstv if (ic->ic_opmode == IEEE80211_M_MONITOR)
5421 1.91 mlelstv add_sta_cmd.station_type = IWM_STA_GENERAL_PURPOSE;
5422 1.91 mlelstv else
5423 1.91 mlelstv add_sta_cmd.station_type = IWM_STA_LINK;
5424 1.91 mlelstv }
5425 1.45 nonaka add_sta_cmd.mac_id_n_color
5426 1.45 nonaka = htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));
5427 1.91 mlelstv if (ic->ic_opmode == IEEE80211_M_MONITOR) {
5428 1.91 mlelstv int qid;
5429 1.91 mlelstv IEEE80211_ADDR_COPY(&add_sta_cmd.addr, etheranyaddr);
5430 1.91 mlelstv if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))
5431 1.91 mlelstv qid = IWM_DQA_INJECT_MONITOR_QUEUE;
5432 1.91 mlelstv else
5433 1.91 mlelstv qid = IWM_AUX_QUEUE;
5434 1.91 mlelstv in->tfd_queue_msk |= (1 << qid);
5435 1.91 mlelstv } else {
5436 1.45 nonaka int ac;
5437 1.45 nonaka for (ac = 0; ac < WME_NUM_AC; ac++) {
5438 1.91 mlelstv int qid = ac;
5439 1.91 mlelstv if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))
5440 1.91 mlelstv qid += IWM_DQA_MIN_MGMT_QUEUE;
5441 1.91 mlelstv in->tfd_queue_msk |= (1 << qid);
5442 1.91 mlelstv }
5443 1.91 mlelstv }
5444 1.91 mlelstv if (!update) {
5445 1.91 mlelstv if (ic->ic_opmode == IEEE80211_M_MONITOR) {
5446 1.91 mlelstv IEEE80211_ADDR_COPY(&add_sta_cmd.addr,
5447 1.91 mlelstv etherbroadcastaddr);
5448 1.91 mlelstv } else {
5449 1.91 mlelstv IEEE80211_ADDR_COPY(&add_sta_cmd.addr,
5450 1.91 mlelstv in->in_macaddr);
5451 1.45 nonaka }
5452 1.45 nonaka }
5453 1.1 pooka add_sta_cmd.add_modify = update ? 1 : 0;
5454 1.1 pooka add_sta_cmd.station_flags_msk
5455 1.1 pooka |= htole32(IWM_STA_FLG_FAT_EN_MSK | IWM_STA_FLG_MIMO_EN_MSK);
5456 1.91 mlelstv if (update) {
5457 1.91 mlelstv add_sta_cmd.modify_mask |= (IWM_STA_MODIFY_QUEUES |
5458 1.91 mlelstv IWM_STA_MODIFY_TID_DISABLE_TX);
5459 1.91 mlelstv }
5460 1.45 nonaka add_sta_cmd.tid_disable_tx = htole16(0xffff);
5461 1.91 mlelstv add_sta_cmd.tfd_queue_msk = htole32(in->tfd_queue_msk);
5462 1.45 nonaka
5463 1.45 nonaka #ifndef IEEE80211_NO_HT
5464 1.45 nonaka if (in->in_ni.ni_flags & IEEE80211_NODE_HT) {
5465 1.45 nonaka add_sta_cmd.station_flags_msk
5466 1.45 nonaka |= htole32(IWM_STA_FLG_MAX_AGG_SIZE_MSK |
5467 1.45 nonaka IWM_STA_FLG_AGG_MPDU_DENS_MSK);
5468 1.45 nonaka
5469 1.45 nonaka add_sta_cmd.station_flags
5470 1.45 nonaka |= htole32(IWM_STA_FLG_MAX_AGG_SIZE_64K);
5471 1.45 nonaka switch (ic->ic_ampdu_params & IEEE80211_AMPDU_PARAM_SS) {
5472 1.45 nonaka case IEEE80211_AMPDU_PARAM_SS_2:
5473 1.45 nonaka add_sta_cmd.station_flags
5474 1.45 nonaka |= htole32(IWM_STA_FLG_AGG_MPDU_DENS_2US);
5475 1.45 nonaka break;
5476 1.45 nonaka case IEEE80211_AMPDU_PARAM_SS_4:
5477 1.45 nonaka add_sta_cmd.station_flags
5478 1.45 nonaka |= htole32(IWM_STA_FLG_AGG_MPDU_DENS_4US);
5479 1.45 nonaka break;
5480 1.45 nonaka case IEEE80211_AMPDU_PARAM_SS_8:
5481 1.45 nonaka add_sta_cmd.station_flags
5482 1.45 nonaka |= htole32(IWM_STA_FLG_AGG_MPDU_DENS_8US);
5483 1.45 nonaka break;
5484 1.45 nonaka case IEEE80211_AMPDU_PARAM_SS_16:
5485 1.45 nonaka add_sta_cmd.station_flags
5486 1.45 nonaka |= htole32(IWM_STA_FLG_AGG_MPDU_DENS_16US);
5487 1.45 nonaka break;
5488 1.45 nonaka default:
5489 1.45 nonaka break;
5490 1.45 nonaka }
5491 1.45 nonaka }
5492 1.45 nonaka #endif
5493 1.1 pooka
5494 1.1 pooka status = IWM_ADD_STA_SUCCESS;
5495 1.91 mlelstv if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE))
5496 1.91 mlelstv cmdsize = sizeof(add_sta_cmd);
5497 1.91 mlelstv else
5498 1.91 mlelstv cmdsize = sizeof(struct iwm_add_sta_cmd_v7);
5499 1.91 mlelstv err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA, cmdsize,
5500 1.45 nonaka &add_sta_cmd, &status);
5501 1.91 mlelstv if (err == 0 && (status & IWM_ADD_STA_STATUS_MASK) != IWM_ADD_STA_SUCCESS)
5502 1.45 nonaka err = EIO;
5503 1.1 pooka
5504 1.45 nonaka return err;
5505 1.1 pooka }
5506 1.1 pooka
5507 1.4 nonaka static int
5508 1.45 nonaka iwm_add_aux_sta(struct iwm_softc *sc)
5509 1.1 pooka {
5510 1.91 mlelstv struct iwm_add_sta_cmd cmd;
5511 1.91 mlelstv int err, qid;
5512 1.45 nonaka uint32_t status;
5513 1.91 mlelstv size_t cmdsize;
5514 1.1 pooka
5515 1.91 mlelstv if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT)) {
5516 1.91 mlelstv qid = IWM_DQA_AUX_QUEUE;
5517 1.91 mlelstv err = iwm_enable_txq(sc, IWM_AUX_STA_ID, qid,
5518 1.91 mlelstv IWM_TX_FIFO_MCAST, 0, IWM_MAX_TID_COUNT, 0);
5519 1.91 mlelstv } else {
5520 1.91 mlelstv qid = IWM_AUX_QUEUE;
5521 1.91 mlelstv err = iwm_enable_ac_txq(sc, qid, IWM_TX_FIFO_MCAST);
5522 1.91 mlelstv }
5523 1.45 nonaka if (err)
5524 1.45 nonaka return err;
5525 1.1 pooka
5526 1.1 pooka memset(&cmd, 0, sizeof(cmd));
5527 1.45 nonaka cmd.sta_id = IWM_AUX_STA_ID;
5528 1.91 mlelstv if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE))
5529 1.91 mlelstv cmd.station_type = IWM_STA_AUX_ACTIVITY;
5530 1.45 nonaka cmd.mac_id_n_color =
5531 1.45 nonaka htole32(IWM_FW_CMD_ID_AND_COLOR(IWM_MAC_INDEX_AUX, 0));
5532 1.91 mlelstv cmd.tfd_queue_msk = htole32(1 << qid);
5533 1.45 nonaka cmd.tid_disable_tx = htole16(0xffff);
5534 1.1 pooka
5535 1.45 nonaka status = IWM_ADD_STA_SUCCESS;
5536 1.91 mlelstv if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE))
5537 1.91 mlelstv cmdsize = sizeof(cmd);
5538 1.91 mlelstv else
5539 1.91 mlelstv cmdsize = sizeof(struct iwm_add_sta_cmd_v7);
5540 1.91 mlelstv err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA, cmdsize, &cmd,
5541 1.45 nonaka &status);
5542 1.91 mlelstv if (err == 0 &&
5543 1.91 mlelstv (status & IWM_ADD_STA_STATUS_MASK) != IWM_ADD_STA_SUCCESS)
5544 1.45 nonaka err = EIO;
5545 1.1 pooka
5546 1.45 nonaka return err;
5547 1.1 pooka }
5548 1.1 pooka
5549 1.1 pooka #define IWM_PLCP_QUIET_THRESH 1
5550 1.1 pooka #define IWM_ACTIVE_QUIET_TIME 10
5551 1.1 pooka #define LONG_OUT_TIME_PERIOD 600
5552 1.1 pooka #define SHORT_OUT_TIME_PERIOD 200
5553 1.1 pooka #define SUSPEND_TIME_PERIOD 100
5554 1.1 pooka
5555 1.4 nonaka static uint16_t
5556 1.45 nonaka iwm_scan_rx_chain(struct iwm_softc *sc)
5557 1.1 pooka {
5558 1.1 pooka uint16_t rx_chain;
5559 1.1 pooka uint8_t rx_ant;
5560 1.1 pooka
5561 1.45 nonaka rx_ant = iwm_fw_valid_rx_ant(sc);
5562 1.1 pooka rx_chain = rx_ant << IWM_PHY_RX_CHAIN_VALID_POS;
5563 1.1 pooka rx_chain |= rx_ant << IWM_PHY_RX_CHAIN_FORCE_MIMO_SEL_POS;
5564 1.1 pooka rx_chain |= rx_ant << IWM_PHY_RX_CHAIN_FORCE_SEL_POS;
5565 1.1 pooka rx_chain |= 0x1 << IWM_PHY_RX_CHAIN_DRIVER_FORCE_POS;
5566 1.1 pooka return htole16(rx_chain);
5567 1.1 pooka }
5568 1.1 pooka
5569 1.4 nonaka static uint32_t
5570 1.45 nonaka iwm_scan_rate_n_flags(struct iwm_softc *sc, int flags, int no_cck)
5571 1.1 pooka {
5572 1.1 pooka uint32_t tx_ant;
5573 1.1 pooka int i, ind;
5574 1.1 pooka
5575 1.1 pooka for (i = 0, ind = sc->sc_scan_last_antenna;
5576 1.1 pooka i < IWM_RATE_MCS_ANT_NUM; i++) {
5577 1.1 pooka ind = (ind + 1) % IWM_RATE_MCS_ANT_NUM;
5578 1.45 nonaka if (iwm_fw_valid_tx_ant(sc) & (1 << ind)) {
5579 1.1 pooka sc->sc_scan_last_antenna = ind;
5580 1.1 pooka break;
5581 1.1 pooka }
5582 1.1 pooka }
5583 1.1 pooka tx_ant = (1 << sc->sc_scan_last_antenna) << IWM_RATE_MCS_ANT_POS;
5584 1.1 pooka
5585 1.1 pooka if ((flags & IEEE80211_CHAN_2GHZ) && !no_cck)
5586 1.1 pooka return htole32(IWM_RATE_1M_PLCP | IWM_RATE_MCS_CCK_MSK |
5587 1.1 pooka tx_ant);
5588 1.1 pooka else
5589 1.1 pooka return htole32(IWM_RATE_6M_PLCP | tx_ant);
5590 1.1 pooka }
5591 1.1 pooka
5592 1.45 nonaka static uint8_t
5593 1.45 nonaka iwm_lmac_scan_fill_channels(struct iwm_softc *sc,
5594 1.45 nonaka struct iwm_scan_channel_cfg_lmac *chan, int n_ssids)
5595 1.1 pooka {
5596 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
5597 1.1 pooka struct ieee80211_channel *c;
5598 1.45 nonaka uint8_t nchan;
5599 1.1 pooka
5600 1.45 nonaka for (nchan = 0, c = &ic->ic_channels[1];
5601 1.45 nonaka c <= &ic->ic_channels[IEEE80211_CHAN_MAX] &&
5602 1.45 nonaka nchan < sc->sc_capa_n_scan_channels;
5603 1.45 nonaka c++) {
5604 1.45 nonaka if (c->ic_flags == 0)
5605 1.45 nonaka continue;
5606 1.45 nonaka
5607 1.45 nonaka chan->channel_num = htole16(ieee80211_mhz2ieee(c->ic_freq, 0));
5608 1.45 nonaka chan->iter_count = htole16(1);
5609 1.61 nonaka chan->iter_interval = htole32(0);
5610 1.45 nonaka chan->flags = htole32(IWM_UNIFIED_SCAN_CHANNEL_PARTIAL);
5611 1.61 nonaka chan->flags |= htole32(IWM_SCAN_CHANNEL_NSSIDS(n_ssids));
5612 1.61 nonaka if (!IEEE80211_IS_CHAN_PASSIVE(c) && n_ssids != 0)
5613 1.61 nonaka chan->flags |= htole32(IWM_SCAN_CHANNEL_TYPE_ACTIVE);
5614 1.45 nonaka chan++;
5615 1.45 nonaka nchan++;
5616 1.45 nonaka }
5617 1.45 nonaka
5618 1.45 nonaka return nchan;
5619 1.45 nonaka }
5620 1.45 nonaka
5621 1.45 nonaka static uint8_t
5622 1.45 nonaka iwm_umac_scan_fill_channels(struct iwm_softc *sc,
5623 1.45 nonaka struct iwm_scan_channel_cfg_umac *chan, int n_ssids)
5624 1.45 nonaka {
5625 1.45 nonaka struct ieee80211com *ic = &sc->sc_ic;
5626 1.45 nonaka struct ieee80211_channel *c;
5627 1.45 nonaka uint8_t nchan;
5628 1.1 pooka
5629 1.1 pooka for (nchan = 0, c = &ic->ic_channels[1];
5630 1.45 nonaka c <= &ic->ic_channels[IEEE80211_CHAN_MAX] &&
5631 1.45 nonaka nchan < sc->sc_capa_n_scan_channels;
5632 1.1 pooka c++) {
5633 1.45 nonaka if (c->ic_flags == 0)
5634 1.1 pooka continue;
5635 1.61 nonaka
5636 1.45 nonaka chan->channel_num = ieee80211_mhz2ieee(c->ic_freq, 0);
5637 1.45 nonaka chan->iter_count = 1;
5638 1.45 nonaka chan->iter_interval = htole16(0);
5639 1.61 nonaka chan->flags = htole32(IWM_SCAN_CHANNEL_UMAC_NSSIDS(n_ssids));
5640 1.1 pooka chan++;
5641 1.1 pooka nchan++;
5642 1.1 pooka }
5643 1.45 nonaka
5644 1.1 pooka return nchan;
5645 1.1 pooka }
5646 1.1 pooka
5647 1.45 nonaka static int
5648 1.91 mlelstv iwm_fill_probe_req_v1(struct iwm_softc *sc, struct iwm_scan_probe_req_v1 *preq1)
5649 1.91 mlelstv {
5650 1.91 mlelstv struct iwm_scan_probe_req preq2;
5651 1.91 mlelstv int err, i;
5652 1.91 mlelstv
5653 1.91 mlelstv err = iwm_fill_probe_req(sc, &preq2);
5654 1.91 mlelstv if (err)
5655 1.91 mlelstv return err;
5656 1.91 mlelstv
5657 1.91 mlelstv preq1->mac_header = preq2.mac_header;
5658 1.91 mlelstv for (i=0; i<__arraycount(preq1->band_data); i++)
5659 1.91 mlelstv preq1->band_data[i] = preq2.band_data[i];
5660 1.91 mlelstv preq1->common_data = preq2.common_data;
5661 1.91 mlelstv memcpy(preq1->buf, preq2.buf, sizeof(preq1->buf));
5662 1.91 mlelstv return 0;
5663 1.91 mlelstv }
5664 1.91 mlelstv
5665 1.91 mlelstv static int
5666 1.45 nonaka iwm_fill_probe_req(struct iwm_softc *sc, struct iwm_scan_probe_req *preq)
5667 1.45 nonaka {
5668 1.45 nonaka struct ieee80211com *ic = &sc->sc_ic;
5669 1.45 nonaka struct ieee80211_frame *wh = (struct ieee80211_frame *)preq->buf;
5670 1.45 nonaka struct ieee80211_rateset *rs;
5671 1.45 nonaka size_t remain = sizeof(preq->buf);
5672 1.45 nonaka uint8_t *frm, *pos;
5673 1.45 nonaka
5674 1.45 nonaka memset(preq, 0, sizeof(*preq));
5675 1.45 nonaka
5676 1.78 christos KASSERT(ic->ic_des_esslen < sizeof(ic->ic_des_essid));
5677 1.45 nonaka if (remain < sizeof(*wh) + 2 + ic->ic_des_esslen)
5678 1.45 nonaka return ENOBUFS;
5679 1.1 pooka
5680 1.45 nonaka /*
5681 1.45 nonaka * Build a probe request frame. Most of the following code is a
5682 1.45 nonaka * copy & paste of what is done in net80211.
5683 1.45 nonaka */
5684 1.45 nonaka wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
5685 1.1 pooka IEEE80211_FC0_SUBTYPE_PROBE_REQ;
5686 1.45 nonaka wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
5687 1.45 nonaka IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr);
5688 1.45 nonaka IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
5689 1.45 nonaka IEEE80211_ADDR_COPY(wh->i_addr3, etherbroadcastaddr);
5690 1.45 nonaka *(uint16_t *)&wh->i_dur[0] = 0; /* filled by HW */
5691 1.45 nonaka *(uint16_t *)&wh->i_seq[0] = 0; /* filled by HW */
5692 1.45 nonaka
5693 1.45 nonaka frm = (uint8_t *)(wh + 1);
5694 1.45 nonaka frm = ieee80211_add_ssid(frm, ic->ic_des_essid, ic->ic_des_esslen);
5695 1.45 nonaka
5696 1.45 nonaka /* Tell the firmware where the MAC header is. */
5697 1.45 nonaka preq->mac_header.offset = 0;
5698 1.45 nonaka preq->mac_header.len = htole16(frm - (uint8_t *)wh);
5699 1.45 nonaka remain -= frm - (uint8_t *)wh;
5700 1.45 nonaka
5701 1.45 nonaka /* Fill in 2GHz IEs and tell firmware where they are. */
5702 1.45 nonaka rs = &ic->ic_sup_rates[IEEE80211_MODE_11G];
5703 1.45 nonaka if (rs->rs_nrates > IEEE80211_RATE_SIZE) {
5704 1.45 nonaka if (remain < 4 + rs->rs_nrates)
5705 1.45 nonaka return ENOBUFS;
5706 1.45 nonaka } else if (remain < 2 + rs->rs_nrates)
5707 1.45 nonaka return ENOBUFS;
5708 1.45 nonaka preq->band_data[0].offset = htole16(frm - (uint8_t *)wh);
5709 1.45 nonaka pos = frm;
5710 1.45 nonaka frm = ieee80211_add_rates(frm, rs);
5711 1.45 nonaka if (rs->rs_nrates > IEEE80211_RATE_SIZE)
5712 1.45 nonaka frm = ieee80211_add_xrates(frm, rs);
5713 1.45 nonaka preq->band_data[0].len = htole16(frm - pos);
5714 1.45 nonaka remain -= frm - pos;
5715 1.45 nonaka
5716 1.45 nonaka if (isset(sc->sc_enabled_capa,
5717 1.45 nonaka IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT)) {
5718 1.45 nonaka if (remain < 3)
5719 1.45 nonaka return ENOBUFS;
5720 1.45 nonaka *frm++ = IEEE80211_ELEMID_DSPARMS;
5721 1.45 nonaka *frm++ = 1;
5722 1.45 nonaka *frm++ = 0;
5723 1.45 nonaka remain -= 3;
5724 1.45 nonaka }
5725 1.45 nonaka
5726 1.45 nonaka if (sc->sc_nvm.sku_cap_band_52GHz_enable) {
5727 1.45 nonaka /* Fill in 5GHz IEs. */
5728 1.45 nonaka rs = &ic->ic_sup_rates[IEEE80211_MODE_11A];
5729 1.45 nonaka if (rs->rs_nrates > IEEE80211_RATE_SIZE) {
5730 1.45 nonaka if (remain < 4 + rs->rs_nrates)
5731 1.45 nonaka return ENOBUFS;
5732 1.45 nonaka } else if (remain < 2 + rs->rs_nrates)
5733 1.45 nonaka return ENOBUFS;
5734 1.45 nonaka preq->band_data[1].offset = htole16(frm - (uint8_t *)wh);
5735 1.45 nonaka pos = frm;
5736 1.45 nonaka frm = ieee80211_add_rates(frm, rs);
5737 1.45 nonaka if (rs->rs_nrates > IEEE80211_RATE_SIZE)
5738 1.45 nonaka frm = ieee80211_add_xrates(frm, rs);
5739 1.45 nonaka preq->band_data[1].len = htole16(frm - pos);
5740 1.45 nonaka remain -= frm - pos;
5741 1.45 nonaka }
5742 1.45 nonaka
5743 1.45 nonaka #ifndef IEEE80211_NO_HT
5744 1.45 nonaka /* Send 11n IEs on both 2GHz and 5GHz bands. */
5745 1.45 nonaka preq->common_data.offset = htole16(frm - (uint8_t *)wh);
5746 1.45 nonaka pos = frm;
5747 1.45 nonaka if (ic->ic_flags & IEEE80211_F_HTON) {
5748 1.45 nonaka if (remain < 28)
5749 1.45 nonaka return ENOBUFS;
5750 1.45 nonaka frm = ieee80211_add_htcaps(frm, ic);
5751 1.45 nonaka /* XXX add WME info? */
5752 1.45 nonaka }
5753 1.45 nonaka #endif
5754 1.45 nonaka
5755 1.45 nonaka preq->common_data.len = htole16(frm - pos);
5756 1.45 nonaka
5757 1.45 nonaka return 0;
5758 1.45 nonaka }
5759 1.45 nonaka
5760 1.45 nonaka static int
5761 1.45 nonaka iwm_lmac_scan(struct iwm_softc *sc)
5762 1.45 nonaka {
5763 1.45 nonaka struct ieee80211com *ic = &sc->sc_ic;
5764 1.45 nonaka struct iwm_host_cmd hcmd = {
5765 1.45 nonaka .id = IWM_SCAN_OFFLOAD_REQUEST_CMD,
5766 1.45 nonaka .len = { 0, },
5767 1.45 nonaka .data = { NULL, },
5768 1.45 nonaka .flags = 0,
5769 1.45 nonaka };
5770 1.45 nonaka struct iwm_scan_req_lmac *req;
5771 1.45 nonaka size_t req_len;
5772 1.45 nonaka int err;
5773 1.45 nonaka
5774 1.45 nonaka DPRINTF(("%s: %s\n", DEVNAME(sc), __func__));
5775 1.45 nonaka
5776 1.45 nonaka req_len = sizeof(struct iwm_scan_req_lmac) +
5777 1.45 nonaka (sizeof(struct iwm_scan_channel_cfg_lmac) *
5778 1.91 mlelstv sc->sc_capa_n_scan_channels) + sizeof(struct iwm_scan_probe_req_v1);
5779 1.45 nonaka if (req_len > IWM_MAX_CMD_PAYLOAD_SIZE)
5780 1.45 nonaka return ENOMEM;
5781 1.45 nonaka req = kmem_zalloc(req_len, KM_SLEEP);
5782 1.45 nonaka hcmd.len[0] = (uint16_t)req_len;
5783 1.45 nonaka hcmd.data[0] = (void *)req;
5784 1.45 nonaka
5785 1.45 nonaka /* These timings correspond to iwlwifi's UNASSOC scan. */
5786 1.45 nonaka req->active_dwell = 10;
5787 1.45 nonaka req->passive_dwell = 110;
5788 1.45 nonaka req->fragmented_dwell = 44;
5789 1.45 nonaka req->extended_dwell = 90;
5790 1.45 nonaka req->max_out_time = 0;
5791 1.45 nonaka req->suspend_time = 0;
5792 1.45 nonaka
5793 1.45 nonaka req->scan_prio = htole32(IWM_SCAN_PRIORITY_HIGH);
5794 1.45 nonaka req->rx_chain_select = iwm_scan_rx_chain(sc);
5795 1.45 nonaka req->iter_num = htole32(1);
5796 1.45 nonaka req->delay = 0;
5797 1.45 nonaka
5798 1.45 nonaka req->scan_flags = htole32(IWM_LMAC_SCAN_FLAG_PASS_ALL |
5799 1.45 nonaka IWM_LMAC_SCAN_FLAG_ITER_COMPLETE |
5800 1.45 nonaka IWM_LMAC_SCAN_FLAG_EXTENDED_DWELL);
5801 1.45 nonaka if (ic->ic_des_esslen == 0)
5802 1.45 nonaka req->scan_flags |= htole32(IWM_LMAC_SCAN_FLAG_PASSIVE);
5803 1.45 nonaka else
5804 1.45 nonaka req->scan_flags |= htole32(IWM_LMAC_SCAN_FLAG_PRE_CONNECTION);
5805 1.45 nonaka if (isset(sc->sc_enabled_capa,
5806 1.45 nonaka IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT))
5807 1.45 nonaka req->scan_flags |= htole32(IWM_LMAC_SCAN_FLAGS_RRM_ENABLED);
5808 1.45 nonaka
5809 1.45 nonaka req->flags = htole32(IWM_PHY_BAND_24);
5810 1.45 nonaka if (sc->sc_nvm.sku_cap_band_52GHz_enable)
5811 1.45 nonaka req->flags |= htole32(IWM_PHY_BAND_5);
5812 1.45 nonaka req->filter_flags =
5813 1.45 nonaka htole32(IWM_MAC_FILTER_ACCEPT_GRP | IWM_MAC_FILTER_IN_BEACON);
5814 1.45 nonaka
5815 1.45 nonaka /* Tx flags 2 GHz. */
5816 1.45 nonaka req->tx_cmd[0].tx_flags = htole32(IWM_TX_CMD_FLG_SEQ_CTL |
5817 1.45 nonaka IWM_TX_CMD_FLG_BT_DIS);
5818 1.45 nonaka req->tx_cmd[0].rate_n_flags =
5819 1.45 nonaka iwm_scan_rate_n_flags(sc, IEEE80211_CHAN_2GHZ, 1/*XXX*/);
5820 1.45 nonaka req->tx_cmd[0].sta_id = IWM_AUX_STA_ID;
5821 1.45 nonaka
5822 1.45 nonaka /* Tx flags 5 GHz. */
5823 1.45 nonaka req->tx_cmd[1].tx_flags = htole32(IWM_TX_CMD_FLG_SEQ_CTL |
5824 1.45 nonaka IWM_TX_CMD_FLG_BT_DIS);
5825 1.45 nonaka req->tx_cmd[1].rate_n_flags =
5826 1.45 nonaka iwm_scan_rate_n_flags(sc, IEEE80211_CHAN_5GHZ, 1/*XXX*/);
5827 1.45 nonaka req->tx_cmd[1].sta_id = IWM_AUX_STA_ID;
5828 1.45 nonaka
5829 1.45 nonaka /* Check if we're doing an active directed scan. */
5830 1.45 nonaka if (ic->ic_des_esslen != 0) {
5831 1.45 nonaka req->direct_scan[0].id = IEEE80211_ELEMID_SSID;
5832 1.45 nonaka req->direct_scan[0].len = ic->ic_des_esslen;
5833 1.45 nonaka memcpy(req->direct_scan[0].ssid, ic->ic_des_essid,
5834 1.45 nonaka ic->ic_des_esslen);
5835 1.45 nonaka }
5836 1.45 nonaka
5837 1.45 nonaka req->n_channels = iwm_lmac_scan_fill_channels(sc,
5838 1.45 nonaka (struct iwm_scan_channel_cfg_lmac *)req->data,
5839 1.45 nonaka ic->ic_des_esslen != 0);
5840 1.45 nonaka
5841 1.91 mlelstv err = iwm_fill_probe_req_v1(sc,
5842 1.91 mlelstv (struct iwm_scan_probe_req_v1 *)(req->data +
5843 1.45 nonaka (sizeof(struct iwm_scan_channel_cfg_lmac) *
5844 1.45 nonaka sc->sc_capa_n_scan_channels)));
5845 1.45 nonaka if (err) {
5846 1.45 nonaka kmem_free(req, req_len);
5847 1.45 nonaka return err;
5848 1.1 pooka }
5849 1.1 pooka
5850 1.45 nonaka /* Specify the scan plan: We'll do one iteration. */
5851 1.45 nonaka req->schedule[0].iterations = 1;
5852 1.45 nonaka req->schedule[0].full_scan_mul = 1;
5853 1.1 pooka
5854 1.45 nonaka /* Disable EBS. */
5855 1.45 nonaka req->channel_opt[0].non_ebs_ratio = 1;
5856 1.45 nonaka req->channel_opt[1].non_ebs_ratio = 1;
5857 1.1 pooka
5858 1.45 nonaka err = iwm_send_cmd(sc, &hcmd);
5859 1.45 nonaka kmem_free(req, req_len);
5860 1.45 nonaka return err;
5861 1.45 nonaka }
5862 1.45 nonaka
5863 1.45 nonaka static int
5864 1.45 nonaka iwm_config_umac_scan(struct iwm_softc *sc)
5865 1.45 nonaka {
5866 1.45 nonaka struct ieee80211com *ic = &sc->sc_ic;
5867 1.45 nonaka struct iwm_scan_config *scan_config;
5868 1.45 nonaka int err, nchan;
5869 1.45 nonaka size_t cmd_size;
5870 1.45 nonaka struct ieee80211_channel *c;
5871 1.45 nonaka struct iwm_host_cmd hcmd = {
5872 1.91 mlelstv .id = iwm_cmd_id(IWM_SCAN_CFG_CMD, IWM_LONG_GROUP, 0),
5873 1.45 nonaka .flags = 0,
5874 1.45 nonaka };
5875 1.45 nonaka static const uint32_t rates = (IWM_SCAN_CONFIG_RATE_1M |
5876 1.45 nonaka IWM_SCAN_CONFIG_RATE_2M | IWM_SCAN_CONFIG_RATE_5M |
5877 1.45 nonaka IWM_SCAN_CONFIG_RATE_11M | IWM_SCAN_CONFIG_RATE_6M |
5878 1.45 nonaka IWM_SCAN_CONFIG_RATE_9M | IWM_SCAN_CONFIG_RATE_12M |
5879 1.45 nonaka IWM_SCAN_CONFIG_RATE_18M | IWM_SCAN_CONFIG_RATE_24M |
5880 1.45 nonaka IWM_SCAN_CONFIG_RATE_36M | IWM_SCAN_CONFIG_RATE_48M |
5881 1.45 nonaka IWM_SCAN_CONFIG_RATE_54M);
5882 1.45 nonaka
5883 1.45 nonaka cmd_size = sizeof(*scan_config) + sc->sc_capa_n_scan_channels;
5884 1.45 nonaka
5885 1.45 nonaka scan_config = kmem_zalloc(cmd_size, KM_SLEEP);
5886 1.45 nonaka scan_config->tx_chains = htole32(iwm_fw_valid_tx_ant(sc));
5887 1.45 nonaka scan_config->rx_chains = htole32(iwm_fw_valid_rx_ant(sc));
5888 1.45 nonaka scan_config->legacy_rates = htole32(rates |
5889 1.45 nonaka IWM_SCAN_CONFIG_SUPPORTED_RATE(rates));
5890 1.45 nonaka
5891 1.45 nonaka /* These timings correspond to iwlwifi's UNASSOC scan. */
5892 1.45 nonaka scan_config->dwell_active = 10;
5893 1.45 nonaka scan_config->dwell_passive = 110;
5894 1.45 nonaka scan_config->dwell_fragmented = 44;
5895 1.45 nonaka scan_config->dwell_extended = 90;
5896 1.45 nonaka scan_config->out_of_channel_time = htole32(0);
5897 1.45 nonaka scan_config->suspend_time = htole32(0);
5898 1.45 nonaka
5899 1.45 nonaka IEEE80211_ADDR_COPY(scan_config->mac_addr, sc->sc_ic.ic_myaddr);
5900 1.45 nonaka
5901 1.45 nonaka scan_config->bcast_sta_id = IWM_AUX_STA_ID;
5902 1.91 mlelstv #if 1
5903 1.45 nonaka scan_config->channel_flags = IWM_CHANNEL_FLAG_EBS |
5904 1.45 nonaka IWM_CHANNEL_FLAG_ACCURATE_EBS | IWM_CHANNEL_FLAG_EBS_ADD |
5905 1.45 nonaka IWM_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE;
5906 1.91 mlelstv #else
5907 1.91 mlelstv scan_config->channel_flags = 0;
5908 1.91 mlelstv #endif
5909 1.45 nonaka
5910 1.45 nonaka for (c = &ic->ic_channels[1], nchan = 0;
5911 1.45 nonaka c <= &ic->ic_channels[IEEE80211_CHAN_MAX] &&
5912 1.45 nonaka nchan < sc->sc_capa_n_scan_channels; c++) {
5913 1.45 nonaka if (c->ic_flags == 0)
5914 1.45 nonaka continue;
5915 1.45 nonaka scan_config->channel_array[nchan++] =
5916 1.45 nonaka ieee80211_mhz2ieee(c->ic_freq, 0);
5917 1.1 pooka }
5918 1.1 pooka
5919 1.45 nonaka scan_config->flags = htole32(IWM_SCAN_CONFIG_FLAG_ACTIVATE |
5920 1.45 nonaka IWM_SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS |
5921 1.45 nonaka IWM_SCAN_CONFIG_FLAG_SET_TX_CHAINS |
5922 1.45 nonaka IWM_SCAN_CONFIG_FLAG_SET_RX_CHAINS |
5923 1.45 nonaka IWM_SCAN_CONFIG_FLAG_SET_AUX_STA_ID |
5924 1.45 nonaka IWM_SCAN_CONFIG_FLAG_SET_ALL_TIMES |
5925 1.45 nonaka IWM_SCAN_CONFIG_FLAG_SET_LEGACY_RATES |
5926 1.45 nonaka IWM_SCAN_CONFIG_FLAG_SET_MAC_ADDR |
5927 1.45 nonaka IWM_SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS|
5928 1.45 nonaka IWM_SCAN_CONFIG_N_CHANNELS(nchan) |
5929 1.45 nonaka IWM_SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED);
5930 1.45 nonaka
5931 1.45 nonaka hcmd.data[0] = scan_config;
5932 1.45 nonaka hcmd.len[0] = cmd_size;
5933 1.45 nonaka
5934 1.45 nonaka err = iwm_send_cmd(sc, &hcmd);
5935 1.45 nonaka kmem_free(scan_config, cmd_size);
5936 1.45 nonaka return err;
5937 1.1 pooka }
5938 1.1 pooka
5939 1.4 nonaka static int
5940 1.91 mlelstv iwm_umac_scan_size(struct iwm_softc *sc)
5941 1.91 mlelstv {
5942 1.91 mlelstv int base_size = IWM_SCAN_REQ_UMAC_SIZE_V1;
5943 1.91 mlelstv int tail_size;
5944 1.91 mlelstv
5945 1.91 mlelstv if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2))
5946 1.91 mlelstv base_size = IWM_SCAN_REQ_UMAC_SIZE_V8;
5947 1.91 mlelstv else if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL))
5948 1.91 mlelstv base_size = IWM_SCAN_REQ_UMAC_SIZE_V7;
5949 1.91 mlelstv if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_SCAN_EXT_CHAN_VER))
5950 1.91 mlelstv tail_size = sizeof(struct iwm_scan_req_umac_tail_v2);
5951 1.91 mlelstv else
5952 1.91 mlelstv tail_size = sizeof(struct iwm_scan_req_umac_tail_v1);
5953 1.91 mlelstv
5954 1.91 mlelstv return base_size + sizeof(struct iwm_scan_channel_cfg_umac) *
5955 1.91 mlelstv sc->sc_capa_n_scan_channels + tail_size;
5956 1.91 mlelstv }
5957 1.91 mlelstv
5958 1.91 mlelstv static struct iwm_scan_umac_chan_param *
5959 1.91 mlelstv iwm_get_scan_req_umac_chan_param(struct iwm_softc *sc,
5960 1.91 mlelstv struct iwm_scan_req_umac *req)
5961 1.91 mlelstv {
5962 1.91 mlelstv if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2))
5963 1.91 mlelstv return &req->v8.channel;
5964 1.91 mlelstv
5965 1.91 mlelstv if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL))
5966 1.91 mlelstv return &req->v7.channel;
5967 1.91 mlelstv
5968 1.91 mlelstv return &req->v1.channel;
5969 1.91 mlelstv }
5970 1.91 mlelstv
5971 1.91 mlelstv static void *
5972 1.91 mlelstv iwm_get_scan_req_umac_data(struct iwm_softc *sc, struct iwm_scan_req_umac *req)
5973 1.91 mlelstv {
5974 1.91 mlelstv if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2))
5975 1.91 mlelstv return (void *)&req->v8.data;
5976 1.91 mlelstv
5977 1.91 mlelstv if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL))
5978 1.91 mlelstv return (void *)&req->v7.data;
5979 1.91 mlelstv
5980 1.91 mlelstv return (void *)&req->v1.data;
5981 1.91 mlelstv
5982 1.91 mlelstv }
5983 1.91 mlelstv
5984 1.91 mlelstv /* adaptive dwell max budget time [TU] for full scan */
5985 1.91 mlelstv #define IWM_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 300
5986 1.91 mlelstv /* adaptive dwell max budget time [TU] for directed scan */
5987 1.91 mlelstv #define IWM_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN 100
5988 1.91 mlelstv /* adaptive dwell default high band APs number */
5989 1.91 mlelstv #define IWM_SCAN_ADWELL_DEFAULT_HB_N_APS 8
5990 1.91 mlelstv /* adaptive dwell default low band APs number */
5991 1.91 mlelstv #define IWM_SCAN_ADWELL_DEFAULT_LB_N_APS 2
5992 1.91 mlelstv /* adaptive dwell default APs number in social channels (1, 6, 11) */
5993 1.91 mlelstv #define IWM_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL 10
5994 1.91 mlelstv
5995 1.91 mlelstv static int
5996 1.45 nonaka iwm_umac_scan(struct iwm_softc *sc)
5997 1.1 pooka {
5998 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
5999 1.1 pooka struct iwm_host_cmd hcmd = {
6000 1.91 mlelstv .id = iwm_cmd_id(IWM_SCAN_REQ_UMAC, IWM_LONG_GROUP, 0),
6001 1.1 pooka .len = { 0, },
6002 1.45 nonaka .data = { NULL, },
6003 1.45 nonaka .flags = 0,
6004 1.1 pooka };
6005 1.45 nonaka struct iwm_scan_req_umac *req;
6006 1.91 mlelstv void *cmd_data, *tail_data;
6007 1.91 mlelstv struct iwm_scan_req_umac_tail_v2 *tail;
6008 1.91 mlelstv struct iwm_scan_req_umac_tail_v1 *tailv1;
6009 1.91 mlelstv struct iwm_scan_umac_chan_param *chanparam;
6010 1.45 nonaka size_t req_len;
6011 1.45 nonaka int err;
6012 1.1 pooka
6013 1.45 nonaka DPRINTF(("%s: %s\n", DEVNAME(sc), __func__));
6014 1.1 pooka
6015 1.91 mlelstv req_len = iwm_umac_scan_size(sc);
6016 1.91 mlelstv if (req_len < IWM_SCAN_REQ_UMAC_SIZE_V1 + sizeof(*tailv1) ||
6017 1.91 mlelstv req_len > IWM_MAX_CMD_PAYLOAD_SIZE)
6018 1.91 mlelstv return ERANGE;
6019 1.45 nonaka req = kmem_zalloc(req_len, KM_SLEEP);
6020 1.1 pooka
6021 1.45 nonaka hcmd.len[0] = (uint16_t)req_len;
6022 1.45 nonaka hcmd.data[0] = (void *)req;
6023 1.1 pooka
6024 1.91 mlelstv if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL)) {
6025 1.91 mlelstv req->v7.adwell_default_n_aps_social =
6026 1.91 mlelstv IWM_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL;
6027 1.91 mlelstv req->v7.adwell_default_n_aps =
6028 1.91 mlelstv IWM_SCAN_ADWELL_DEFAULT_LB_N_APS;
6029 1.91 mlelstv
6030 1.91 mlelstv if (ic->ic_des_esslen != 0)
6031 1.91 mlelstv req->v7.adwell_max_budget =
6032 1.91 mlelstv htole16(IWM_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN);
6033 1.91 mlelstv else
6034 1.91 mlelstv req->v7.adwell_max_budget =
6035 1.91 mlelstv htole16(IWM_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN);
6036 1.91 mlelstv
6037 1.91 mlelstv req->v7.scan_priority = htole32(IWM_SCAN_PRIORITY_HIGH);
6038 1.91 mlelstv req->v7.max_out_time[IWM_SCAN_LB_LMAC_IDX] = 0;
6039 1.91 mlelstv req->v7.suspend_time[IWM_SCAN_LB_LMAC_IDX] = 0;
6040 1.91 mlelstv
6041 1.91 mlelstv if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2)) {
6042 1.91 mlelstv req->v8.active_dwell[IWM_SCAN_LB_LMAC_IDX] = 10;
6043 1.91 mlelstv req->v8.passive_dwell[IWM_SCAN_LB_LMAC_IDX] = 110;
6044 1.91 mlelstv } else {
6045 1.91 mlelstv req->v7.active_dwell = 10;
6046 1.91 mlelstv req->v7.passive_dwell = 110;
6047 1.91 mlelstv req->v7.fragmented_dwell = 44;
6048 1.91 mlelstv }
6049 1.91 mlelstv } else {
6050 1.91 mlelstv /* These timings correspond to iwlwifi's UNASSOC scan. */
6051 1.91 mlelstv req->v1.active_dwell = 10;
6052 1.91 mlelstv req->v1.passive_dwell = 110;
6053 1.91 mlelstv req->v1.fragmented_dwell = 44;
6054 1.91 mlelstv req->v1.extended_dwell = 90;
6055 1.91 mlelstv
6056 1.91 mlelstv req->v1.scan_priority = htole32(IWM_SCAN_PRIORITY_HIGH);
6057 1.91 mlelstv }
6058 1.45 nonaka
6059 1.45 nonaka req->ooc_priority = htole32(IWM_SCAN_PRIORITY_HIGH);
6060 1.45 nonaka
6061 1.91 mlelstv cmd_data = iwm_get_scan_req_umac_data(sc, req);
6062 1.91 mlelstv chanparam = iwm_get_scan_req_umac_chan_param(sc, req);
6063 1.91 mlelstv chanparam->count = iwm_umac_scan_fill_channels(sc,
6064 1.91 mlelstv (struct iwm_scan_channel_cfg_umac *)cmd_data,
6065 1.45 nonaka ic->ic_des_esslen != 0);
6066 1.91 mlelstv chanparam->flags = 0;
6067 1.91 mlelstv
6068 1.91 mlelstv tail_data = (char *)cmd_data
6069 1.91 mlelstv + sizeof(struct iwm_scan_channel_cfg_umac) * sc->sc_capa_n_scan_channels;
6070 1.91 mlelstv
6071 1.91 mlelstv tail = (struct iwm_scan_req_umac_tail_v2 *)tail_data;
6072 1.91 mlelstv tailv1 = (struct iwm_scan_req_umac_tail_v1 *)tail_data;
6073 1.45 nonaka
6074 1.45 nonaka req->general_flags = htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASS_ALL |
6075 1.45 nonaka IWM_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE |
6076 1.45 nonaka IWM_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL);
6077 1.45 nonaka
6078 1.45 nonaka /* Check if we're doing an active directed scan. */
6079 1.45 nonaka if (ic->ic_des_esslen != 0) {
6080 1.91 mlelstv tailv1->direct_scan[0].id = IEEE80211_ELEMID_SSID;
6081 1.91 mlelstv tailv1->direct_scan[0].len = ic->ic_des_esslen;
6082 1.91 mlelstv memcpy(tailv1->direct_scan[0].ssid, ic->ic_des_essid,
6083 1.45 nonaka ic->ic_des_esslen);
6084 1.45 nonaka req->general_flags |=
6085 1.45 nonaka htole32(IWM_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT);
6086 1.45 nonaka } else
6087 1.45 nonaka req->general_flags |= htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASSIVE);
6088 1.1 pooka
6089 1.45 nonaka if (isset(sc->sc_enabled_capa,
6090 1.45 nonaka IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT))
6091 1.45 nonaka req->general_flags |=
6092 1.45 nonaka htole32(IWM_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED);
6093 1.1 pooka
6094 1.91 mlelstv if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_SCAN_EXT_CHAN_VER))
6095 1.91 mlelstv err = iwm_fill_probe_req(sc, &tail->preq);
6096 1.91 mlelstv else
6097 1.91 mlelstv err = iwm_fill_probe_req_v1(sc, &tailv1->preq);
6098 1.45 nonaka if (err) {
6099 1.45 nonaka kmem_free(req, req_len);
6100 1.45 nonaka return err;
6101 1.1 pooka }
6102 1.1 pooka
6103 1.45 nonaka /* Specify the scan plan: We'll do one iteration. */
6104 1.91 mlelstv tailv1->schedule[0].interval = 0;
6105 1.91 mlelstv tailv1->schedule[0].iter_count = 1;
6106 1.45 nonaka
6107 1.45 nonaka err = iwm_send_cmd(sc, &hcmd);
6108 1.45 nonaka kmem_free(req, req_len);
6109 1.45 nonaka return err;
6110 1.1 pooka }
6111 1.1 pooka
6112 1.91 mlelstv void
6113 1.91 mlelstv iwm_mcc_update(struct iwm_softc *sc, struct iwm_mcc_chub_notif *notif)
6114 1.91 mlelstv {
6115 1.91 mlelstv struct ieee80211com *ic = &sc->sc_ic;
6116 1.91 mlelstv struct ifnet *ifp = IC2IFP(ic);
6117 1.91 mlelstv char alpha2[3];
6118 1.91 mlelstv
6119 1.91 mlelstv snprintf(alpha2, sizeof(alpha2), "%c%c",
6120 1.91 mlelstv (le16toh(notif->mcc) & 0xff00) >> 8, le16toh(notif->mcc) & 0xff);
6121 1.91 mlelstv
6122 1.91 mlelstv if (ifp->if_flags & IFF_DEBUG) {
6123 1.91 mlelstv printf("%s: firmware has detected regulatory domain '%s' "
6124 1.91 mlelstv "(0x%x)\n", DEVNAME(sc), alpha2, le16toh(notif->mcc));
6125 1.91 mlelstv }
6126 1.91 mlelstv
6127 1.91 mlelstv /* TODO: Schedule a task to send MCC_UPDATE_CMD? */
6128 1.91 mlelstv }
6129 1.91 mlelstv
6130 1.45 nonaka static uint8_t
6131 1.45 nonaka iwm_ridx2rate(struct ieee80211_rateset *rs, int ridx)
6132 1.45 nonaka {
6133 1.45 nonaka int i;
6134 1.45 nonaka uint8_t rval;
6135 1.1 pooka
6136 1.45 nonaka for (i = 0; i < rs->rs_nrates; i++) {
6137 1.45 nonaka rval = (rs->rs_rates[i] & IEEE80211_RATE_VAL);
6138 1.45 nonaka if (rval == iwm_rates[ridx].rate)
6139 1.45 nonaka return rs->rs_rates[i];
6140 1.45 nonaka }
6141 1.45 nonaka return 0;
6142 1.45 nonaka }
6143 1.1 pooka
6144 1.4 nonaka static void
6145 1.45 nonaka iwm_ack_rates(struct iwm_softc *sc, struct iwm_node *in, int *cck_rates,
6146 1.45 nonaka int *ofdm_rates)
6147 1.1 pooka {
6148 1.24 nonaka struct ieee80211_node *ni = &in->in_ni;
6149 1.45 nonaka struct ieee80211_rateset *rs = &ni->ni_rates;
6150 1.56 nonaka int lowest_present_ofdm = -1;
6151 1.56 nonaka int lowest_present_cck = -1;
6152 1.1 pooka uint8_t cck = 0;
6153 1.1 pooka uint8_t ofdm = 0;
6154 1.1 pooka int i;
6155 1.1 pooka
6156 1.45 nonaka if (ni->ni_chan == IEEE80211_CHAN_ANYC ||
6157 1.45 nonaka IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) {
6158 1.45 nonaka for (i = IWM_FIRST_CCK_RATE; i < IWM_FIRST_OFDM_RATE; i++) {
6159 1.45 nonaka if ((iwm_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0)
6160 1.45 nonaka continue;
6161 1.24 nonaka cck |= (1 << i);
6162 1.56 nonaka if (lowest_present_cck == -1 || lowest_present_cck > i)
6163 1.24 nonaka lowest_present_cck = i;
6164 1.24 nonaka }
6165 1.1 pooka }
6166 1.1 pooka for (i = IWM_FIRST_OFDM_RATE; i <= IWM_LAST_NON_HT_RATE; i++) {
6167 1.45 nonaka if ((iwm_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0)
6168 1.45 nonaka continue;
6169 1.45 nonaka ofdm |= (1 << (i - IWM_FIRST_OFDM_RATE));
6170 1.56 nonaka if (lowest_present_ofdm == -1 || lowest_present_ofdm > i)
6171 1.20 nonaka lowest_present_ofdm = i;
6172 1.1 pooka }
6173 1.1 pooka
6174 1.1 pooka /*
6175 1.1 pooka * Now we've got the basic rates as bitmaps in the ofdm and cck
6176 1.1 pooka * variables. This isn't sufficient though, as there might not
6177 1.1 pooka * be all the right rates in the bitmap. E.g. if the only basic
6178 1.1 pooka * rates are 5.5 Mbps and 11 Mbps, we still need to add 1 Mbps
6179 1.1 pooka * and 6 Mbps because the 802.11-2007 standard says in 9.6:
6180 1.1 pooka *
6181 1.1 pooka * [...] a STA responding to a received frame shall transmit
6182 1.1 pooka * its Control Response frame [...] at the highest rate in the
6183 1.1 pooka * BSSBasicRateSet parameter that is less than or equal to the
6184 1.1 pooka * rate of the immediately previous frame in the frame exchange
6185 1.1 pooka * sequence ([...]) and that is of the same modulation class
6186 1.1 pooka * ([...]) as the received frame. If no rate contained in the
6187 1.1 pooka * BSSBasicRateSet parameter meets these conditions, then the
6188 1.1 pooka * control frame sent in response to a received frame shall be
6189 1.1 pooka * transmitted at the highest mandatory rate of the PHY that is
6190 1.1 pooka * less than or equal to the rate of the received frame, and
6191 1.1 pooka * that is of the same modulation class as the received frame.
6192 1.1 pooka *
6193 1.1 pooka * As a consequence, we need to add all mandatory rates that are
6194 1.1 pooka * lower than all of the basic rates to these bitmaps.
6195 1.1 pooka */
6196 1.1 pooka
6197 1.1 pooka if (IWM_RATE_24M_INDEX < lowest_present_ofdm)
6198 1.1 pooka ofdm |= IWM_RATE_BIT_MSK(24) >> IWM_FIRST_OFDM_RATE;
6199 1.1 pooka if (IWM_RATE_12M_INDEX < lowest_present_ofdm)
6200 1.1 pooka ofdm |= IWM_RATE_BIT_MSK(12) >> IWM_FIRST_OFDM_RATE;
6201 1.1 pooka /* 6M already there or needed so always add */
6202 1.1 pooka ofdm |= IWM_RATE_BIT_MSK(6) >> IWM_FIRST_OFDM_RATE;
6203 1.1 pooka
6204 1.1 pooka /*
6205 1.1 pooka * CCK is a bit more complex with DSSS vs. HR/DSSS vs. ERP.
6206 1.1 pooka * Note, however:
6207 1.1 pooka * - if no CCK rates are basic, it must be ERP since there must
6208 1.1 pooka * be some basic rates at all, so they're OFDM => ERP PHY
6209 1.1 pooka * (or we're in 5 GHz, and the cck bitmap will never be used)
6210 1.1 pooka * - if 11M is a basic rate, it must be ERP as well, so add 5.5M
6211 1.1 pooka * - if 5.5M is basic, 1M and 2M are mandatory
6212 1.1 pooka * - if 2M is basic, 1M is mandatory
6213 1.1 pooka * - if 1M is basic, that's the only valid ACK rate.
6214 1.1 pooka * As a consequence, it's not as complicated as it sounds, just add
6215 1.1 pooka * any lower rates to the ACK rate bitmap.
6216 1.1 pooka */
6217 1.1 pooka if (IWM_RATE_11M_INDEX < lowest_present_cck)
6218 1.1 pooka cck |= IWM_RATE_BIT_MSK(11) >> IWM_FIRST_CCK_RATE;
6219 1.1 pooka if (IWM_RATE_5M_INDEX < lowest_present_cck)
6220 1.1 pooka cck |= IWM_RATE_BIT_MSK(5) >> IWM_FIRST_CCK_RATE;
6221 1.1 pooka if (IWM_RATE_2M_INDEX < lowest_present_cck)
6222 1.1 pooka cck |= IWM_RATE_BIT_MSK(2) >> IWM_FIRST_CCK_RATE;
6223 1.1 pooka /* 1M already there or needed so always add */
6224 1.1 pooka cck |= IWM_RATE_BIT_MSK(1) >> IWM_FIRST_CCK_RATE;
6225 1.1 pooka
6226 1.1 pooka *cck_rates = cck;
6227 1.1 pooka *ofdm_rates = ofdm;
6228 1.1 pooka }
6229 1.1 pooka
6230 1.4 nonaka static void
6231 1.45 nonaka iwm_mac_ctxt_cmd_common(struct iwm_softc *sc, struct iwm_node *in,
6232 1.45 nonaka struct iwm_mac_ctx_cmd *cmd, uint32_t action, int assoc)
6233 1.1 pooka {
6234 1.45 nonaka #define IWM_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */
6235 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
6236 1.1 pooka struct ieee80211_node *ni = ic->ic_bss;
6237 1.1 pooka int cck_ack_rates, ofdm_ack_rates;
6238 1.1 pooka int i;
6239 1.1 pooka
6240 1.1 pooka cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id,
6241 1.1 pooka in->in_color));
6242 1.1 pooka cmd->action = htole32(action);
6243 1.1 pooka
6244 1.91 mlelstv if (ic->ic_opmode == IEEE80211_M_MONITOR)
6245 1.91 mlelstv cmd->mac_type = htole32(IWM_FW_MAC_TYPE_LISTENER);
6246 1.91 mlelstv else if (ic->ic_opmode == IEEE80211_M_STA)
6247 1.91 mlelstv cmd->mac_type = htole32(IWM_FW_MAC_TYPE_BSS_STA);
6248 1.91 mlelstv else
6249 1.91 mlelstv panic("unsupported operating mode %d", ic->ic_opmode);
6250 1.45 nonaka cmd->tsf_id = htole32(IWM_TSF_ID_A);
6251 1.1 pooka
6252 1.1 pooka IEEE80211_ADDR_COPY(cmd->node_addr, ic->ic_myaddr);
6253 1.91 mlelstv if (ic->ic_opmode == IEEE80211_M_MONITOR) {
6254 1.91 mlelstv IEEE80211_ADDR_COPY(cmd->bssid_addr, etherbroadcastaddr);
6255 1.91 mlelstv return;
6256 1.91 mlelstv }
6257 1.45 nonaka
6258 1.91 mlelstv IEEE80211_ADDR_COPY(cmd->bssid_addr, in->in_macaddr);
6259 1.45 nonaka iwm_ack_rates(sc, in, &cck_ack_rates, &ofdm_ack_rates);
6260 1.1 pooka cmd->cck_rates = htole32(cck_ack_rates);
6261 1.1 pooka cmd->ofdm_rates = htole32(ofdm_ack_rates);
6262 1.1 pooka
6263 1.1 pooka cmd->cck_short_preamble
6264 1.1 pooka = htole32((ic->ic_flags & IEEE80211_F_SHPREAMBLE)
6265 1.1 pooka ? IWM_MAC_FLG_SHORT_PREAMBLE : 0);
6266 1.1 pooka cmd->short_slot
6267 1.1 pooka = htole32((ic->ic_flags & IEEE80211_F_SHSLOT)
6268 1.1 pooka ? IWM_MAC_FLG_SHORT_SLOT : 0);
6269 1.1 pooka
6270 1.45 nonaka for (i = 0; i < WME_NUM_AC; i++) {
6271 1.45 nonaka struct wmeParams *wmep = &ic->ic_wme.wme_params[i];
6272 1.45 nonaka int txf = iwm_ac_to_tx_fifo[i];
6273 1.45 nonaka
6274 1.45 nonaka cmd->ac[txf].cw_min = htole16(IWM_EXP2(wmep->wmep_logcwmin));
6275 1.45 nonaka cmd->ac[txf].cw_max = htole16(IWM_EXP2(wmep->wmep_logcwmax));
6276 1.45 nonaka cmd->ac[txf].aifsn = wmep->wmep_aifsn;
6277 1.1 pooka cmd->ac[txf].fifos_mask = (1 << txf);
6278 1.45 nonaka cmd->ac[txf].edca_txop = htole16(wmep->wmep_txopLimit * 32);
6279 1.1 pooka }
6280 1.45 nonaka if (ni->ni_flags & IEEE80211_NODE_QOS)
6281 1.45 nonaka cmd->qos_flags |= htole32(IWM_MAC_QOS_FLG_UPDATE_EDCA);
6282 1.1 pooka
6283 1.45 nonaka #ifndef IEEE80211_NO_HT
6284 1.45 nonaka if (ni->ni_flags & IEEE80211_NODE_HT) {
6285 1.45 nonaka enum ieee80211_htprot htprot =
6286 1.45 nonaka (ni->ni_htop1 & IEEE80211_HTOP1_PROT_MASK);
6287 1.45 nonaka switch (htprot) {
6288 1.45 nonaka case IEEE80211_HTPROT_NONE:
6289 1.45 nonaka break;
6290 1.45 nonaka case IEEE80211_HTPROT_NONMEMBER:
6291 1.45 nonaka case IEEE80211_HTPROT_NONHT_MIXED:
6292 1.45 nonaka cmd->protection_flags |=
6293 1.45 nonaka htole32(IWM_MAC_PROT_FLG_HT_PROT);
6294 1.45 nonaka case IEEE80211_HTPROT_20MHZ:
6295 1.45 nonaka cmd->protection_flags |=
6296 1.45 nonaka htole32(IWM_MAC_PROT_FLG_HT_PROT |
6297 1.45 nonaka IWM_MAC_PROT_FLG_FAT_PROT);
6298 1.45 nonaka break;
6299 1.45 nonaka default:
6300 1.45 nonaka break;
6301 1.45 nonaka }
6302 1.1 pooka
6303 1.45 nonaka cmd->qos_flags |= htole32(IWM_MAC_QOS_FLG_TGN);
6304 1.1 pooka }
6305 1.45 nonaka #endif
6306 1.1 pooka
6307 1.45 nonaka if (ic->ic_flags & IEEE80211_F_USEPROT)
6308 1.45 nonaka cmd->protection_flags |= htole32(IWM_MAC_PROT_FLG_TGG_PROTECT);
6309 1.1 pooka
6310 1.45 nonaka cmd->filter_flags = htole32(IWM_MAC_FILTER_ACCEPT_GRP);
6311 1.45 nonaka #undef IWM_EXP2
6312 1.1 pooka }
6313 1.1 pooka
6314 1.45 nonaka static void
6315 1.45 nonaka iwm_mac_ctxt_cmd_fill_sta(struct iwm_softc *sc, struct iwm_node *in,
6316 1.45 nonaka struct iwm_mac_data_sta *sta, int assoc)
6317 1.1 pooka {
6318 1.45 nonaka struct ieee80211_node *ni = &in->in_ni;
6319 1.45 nonaka uint32_t dtim_off;
6320 1.45 nonaka uint64_t tsf;
6321 1.1 pooka
6322 1.45 nonaka dtim_off = ni->ni_dtim_count * ni->ni_intval * IEEE80211_DUR_TU;
6323 1.45 nonaka tsf = le64toh(ni->ni_tstamp.tsf);
6324 1.1 pooka
6325 1.45 nonaka sta->is_assoc = htole32(assoc);
6326 1.45 nonaka sta->dtim_time = htole32(ni->ni_rstamp + dtim_off);
6327 1.45 nonaka sta->dtim_tsf = htole64(tsf + dtim_off);
6328 1.45 nonaka sta->bi = htole32(ni->ni_intval);
6329 1.45 nonaka sta->bi_reciprocal = htole32(iwm_reciprocal(ni->ni_intval));
6330 1.45 nonaka sta->dtim_interval = htole32(ni->ni_intval * ni->ni_dtim_period);
6331 1.45 nonaka sta->dtim_reciprocal = htole32(iwm_reciprocal(sta->dtim_interval));
6332 1.45 nonaka sta->listen_interval = htole32(10);
6333 1.45 nonaka sta->assoc_id = htole32(ni->ni_associd);
6334 1.45 nonaka sta->assoc_beacon_arrive_time = htole32(ni->ni_rstamp);
6335 1.1 pooka }
6336 1.1 pooka
6337 1.4 nonaka static int
6338 1.45 nonaka iwm_mac_ctxt_cmd(struct iwm_softc *sc, struct iwm_node *in, uint32_t action,
6339 1.45 nonaka int assoc)
6340 1.1 pooka {
6341 1.45 nonaka struct ieee80211_node *ni = &in->in_ni;
6342 1.1 pooka struct iwm_mac_ctx_cmd cmd;
6343 1.1 pooka
6344 1.1 pooka memset(&cmd, 0, sizeof(cmd));
6345 1.1 pooka
6346 1.45 nonaka iwm_mac_ctxt_cmd_common(sc, in, &cmd, action, assoc);
6347 1.1 pooka
6348 1.45 nonaka /* Allow beacons to pass through as long as we are not associated or we
6349 1.45 nonaka * do not have dtim period information */
6350 1.45 nonaka if (!assoc || !ni->ni_associd || !ni->ni_dtim_period)
6351 1.45 nonaka cmd.filter_flags |= htole32(IWM_MAC_FILTER_IN_BEACON);
6352 1.45 nonaka else
6353 1.45 nonaka iwm_mac_ctxt_cmd_fill_sta(sc, in, &cmd.sta, assoc);
6354 1.1 pooka
6355 1.45 nonaka return iwm_send_cmd_pdu(sc, IWM_MAC_CONTEXT_CMD, 0, sizeof(cmd), &cmd);
6356 1.1 pooka }
6357 1.1 pooka
6358 1.45 nonaka #define IWM_MISSED_BEACONS_THRESHOLD 8
6359 1.1 pooka
6360 1.1 pooka static void
6361 1.45 nonaka iwm_rx_missed_beacons_notif(struct iwm_softc *sc,
6362 1.91 mlelstv struct iwm_missed_beacons_notif *mb)
6363 1.1 pooka {
6364 1.68 nonaka int s;
6365 1.1 pooka
6366 1.1 pooka DPRINTF(("missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n",
6367 1.1 pooka le32toh(mb->mac_id),
6368 1.1 pooka le32toh(mb->consec_missed_beacons),
6369 1.1 pooka le32toh(mb->consec_missed_beacons_since_last_rx),
6370 1.1 pooka le32toh(mb->num_recvd_beacons),
6371 1.1 pooka le32toh(mb->num_expected_beacons)));
6372 1.1 pooka
6373 1.1 pooka /*
6374 1.1 pooka * TODO: the threshold should be adjusted based on latency conditions,
6375 1.1 pooka * and/or in case of a CS flow on one of the other AP vifs.
6376 1.1 pooka */
6377 1.1 pooka if (le32toh(mb->consec_missed_beacons_since_last_rx) >
6378 1.68 nonaka IWM_MISSED_BEACONS_THRESHOLD) {
6379 1.68 nonaka s = splnet();
6380 1.1 pooka ieee80211_beacon_miss(&sc->sc_ic);
6381 1.68 nonaka splx(s);
6382 1.68 nonaka }
6383 1.1 pooka }
6384 1.1 pooka
6385 1.4 nonaka static int
6386 1.45 nonaka iwm_update_quotas(struct iwm_softc *sc, struct iwm_node *in)
6387 1.1 pooka {
6388 1.1 pooka struct iwm_time_quota_cmd cmd;
6389 1.45 nonaka int i, idx, num_active_macs, quota, quota_rem;
6390 1.1 pooka int colors[IWM_MAX_BINDINGS] = { -1, -1, -1, -1, };
6391 1.1 pooka int n_ifs[IWM_MAX_BINDINGS] = {0, };
6392 1.1 pooka uint16_t id;
6393 1.1 pooka
6394 1.1 pooka memset(&cmd, 0, sizeof(cmd));
6395 1.1 pooka
6396 1.1 pooka /* currently, PHY ID == binding ID */
6397 1.1 pooka if (in) {
6398 1.1 pooka id = in->in_phyctxt->id;
6399 1.1 pooka KASSERT(id < IWM_MAX_BINDINGS);
6400 1.1 pooka colors[id] = in->in_phyctxt->color;
6401 1.1 pooka
6402 1.1 pooka if (1)
6403 1.1 pooka n_ifs[id] = 1;
6404 1.1 pooka }
6405 1.1 pooka
6406 1.1 pooka /*
6407 1.1 pooka * The FW's scheduling session consists of
6408 1.45 nonaka * IWM_MAX_QUOTA fragments. Divide these fragments
6409 1.1 pooka * equally between all the bindings that require quota
6410 1.1 pooka */
6411 1.1 pooka num_active_macs = 0;
6412 1.1 pooka for (i = 0; i < IWM_MAX_BINDINGS; i++) {
6413 1.1 pooka cmd.quotas[i].id_and_color = htole32(IWM_FW_CTXT_INVALID);
6414 1.1 pooka num_active_macs += n_ifs[i];
6415 1.1 pooka }
6416 1.1 pooka
6417 1.1 pooka quota = 0;
6418 1.1 pooka quota_rem = 0;
6419 1.1 pooka if (num_active_macs) {
6420 1.45 nonaka quota = IWM_MAX_QUOTA / num_active_macs;
6421 1.45 nonaka quota_rem = IWM_MAX_QUOTA % num_active_macs;
6422 1.1 pooka }
6423 1.1 pooka
6424 1.1 pooka for (idx = 0, i = 0; i < IWM_MAX_BINDINGS; i++) {
6425 1.1 pooka if (colors[i] < 0)
6426 1.1 pooka continue;
6427 1.1 pooka
6428 1.1 pooka cmd.quotas[idx].id_and_color =
6429 1.1 pooka htole32(IWM_FW_CMD_ID_AND_COLOR(i, colors[i]));
6430 1.1 pooka
6431 1.1 pooka if (n_ifs[i] <= 0) {
6432 1.1 pooka cmd.quotas[idx].quota = htole32(0);
6433 1.1 pooka cmd.quotas[idx].max_duration = htole32(0);
6434 1.1 pooka } else {
6435 1.1 pooka cmd.quotas[idx].quota = htole32(quota * n_ifs[i]);
6436 1.1 pooka cmd.quotas[idx].max_duration = htole32(0);
6437 1.1 pooka }
6438 1.1 pooka idx++;
6439 1.1 pooka }
6440 1.1 pooka
6441 1.1 pooka /* Give the remainder of the session to the first binding */
6442 1.1 pooka cmd.quotas[0].quota = htole32(le32toh(cmd.quotas[0].quota) + quota_rem);
6443 1.1 pooka
6444 1.45 nonaka return iwm_send_cmd_pdu(sc, IWM_TIME_QUOTA_CMD, 0, sizeof(cmd), &cmd);
6445 1.1 pooka }
6446 1.1 pooka
6447 1.4 nonaka static int
6448 1.91 mlelstv iwm_scan(struct iwm_softc *sc)
6449 1.1 pooka {
6450 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
6451 1.45 nonaka int err;
6452 1.1 pooka
6453 1.91 mlelstv #ifdef notyet
6454 1.91 mlelstv if (sc->sc_flags & IWM_FLAG_BGSCAN) {
6455 1.91 mlelstv err = iwm_scan_abort(sc);
6456 1.91 mlelstv if (err) {
6457 1.91 mlelstv device_printf(sc->sc_dev,
6458 1.91 mlelstv "could not abort background scan\n");
6459 1.91 mlelstv return err;
6460 1.91 mlelstv }
6461 1.91 mlelstv }
6462 1.91 mlelstv #endif
6463 1.11 nonaka
6464 1.91 mlelstv if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN))
6465 1.91 mlelstv err = iwm_umac_scan(sc);
6466 1.91 mlelstv else
6467 1.91 mlelstv err = iwm_lmac_scan(sc);
6468 1.45 nonaka if (err) {
6469 1.91 mlelstv device_printf(sc->sc_dev, "could not initiate scan (error = %d)\n", err);
6470 1.45 nonaka return err;
6471 1.1 pooka }
6472 1.1 pooka
6473 1.91 mlelstv /*
6474 1.91 mlelstv * The current mode might have been fixed during association.
6475 1.91 mlelstv * Ensure all channels get scanned.
6476 1.91 mlelstv */
6477 1.91 mlelstv if (IFM_SUBTYPE(ic->ic_media.ifm_cur->ifm_media) == IFM_AUTO)
6478 1.91 mlelstv ieee80211_setmode(ic, IEEE80211_MODE_AUTO);
6479 1.91 mlelstv
6480 1.91 mlelstv return 0;
6481 1.91 mlelstv }
6482 1.1 pooka
6483 1.91 mlelstv static int
6484 1.91 mlelstv iwm_phy_ctxt_update(struct iwm_softc *sc, struct iwm_phy_ctxt *phyctxt,
6485 1.91 mlelstv struct ieee80211_channel *chan, uint8_t chains_static,
6486 1.91 mlelstv uint8_t chains_dynamic, uint32_t apply_time)
6487 1.91 mlelstv {
6488 1.91 mlelstv uint16_t band_flags = (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ);
6489 1.91 mlelstv int err;
6490 1.91 mlelstv
6491 1.91 mlelstv if (isset(sc->sc_enabled_capa,
6492 1.91 mlelstv IWM_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT) &&
6493 1.91 mlelstv (phyctxt->channel->ic_flags & band_flags) !=
6494 1.91 mlelstv (chan->ic_flags & band_flags)) {
6495 1.91 mlelstv err = iwm_phy_ctxt_cmd(sc, phyctxt, chains_static,
6496 1.91 mlelstv chains_dynamic, IWM_FW_CTXT_ACTION_REMOVE, apply_time);
6497 1.91 mlelstv if (err) {
6498 1.91 mlelstv device_printf(sc->sc_dev,
6499 1.91 mlelstv "could not remove PHY context (error %d)\n", err);
6500 1.91 mlelstv return err;
6501 1.91 mlelstv }
6502 1.91 mlelstv phyctxt->channel = chan;
6503 1.91 mlelstv err = iwm_phy_ctxt_cmd(sc, phyctxt, chains_static,
6504 1.91 mlelstv chains_dynamic, IWM_FW_CTXT_ACTION_ADD, apply_time);
6505 1.91 mlelstv if (err) {
6506 1.91 mlelstv device_printf(sc->sc_dev,
6507 1.91 mlelstv "could not add PHY context (error %d)\n", err);
6508 1.91 mlelstv return err;
6509 1.91 mlelstv }
6510 1.91 mlelstv } else {
6511 1.91 mlelstv phyctxt->channel = chan;
6512 1.91 mlelstv err = iwm_phy_ctxt_cmd(sc, phyctxt, chains_static,
6513 1.91 mlelstv chains_dynamic, IWM_FW_CTXT_ACTION_MODIFY, apply_time);
6514 1.91 mlelstv if (err) {
6515 1.91 mlelstv device_printf(sc->sc_dev,
6516 1.91 mlelstv "could not update PHY context (error %d)\n", err);
6517 1.91 mlelstv return err;
6518 1.91 mlelstv }
6519 1.91 mlelstv }
6520 1.91 mlelstv
6521 1.91 mlelstv return 0;
6522 1.91 mlelstv }
6523 1.91 mlelstv
6524 1.91 mlelstv static int
6525 1.91 mlelstv iwm_auth(struct iwm_softc *sc)
6526 1.91 mlelstv {
6527 1.91 mlelstv struct ieee80211com *ic = &sc->sc_ic;
6528 1.91 mlelstv struct iwm_node *in = (struct iwm_node *)ic->ic_bss;
6529 1.91 mlelstv uint32_t duration;
6530 1.91 mlelstv int generation = sc->sc_generation, err;
6531 1.91 mlelstv
6532 1.91 mlelstv if (ic->ic_opmode == IEEE80211_M_MONITOR) {
6533 1.91 mlelstv err = iwm_phy_ctxt_update(sc, &sc->sc_phyctxt[0],
6534 1.91 mlelstv ic->ic_ibss_chan, 1, 1, 0);
6535 1.91 mlelstv if (err)
6536 1.91 mlelstv return err;
6537 1.91 mlelstv } else {
6538 1.91 mlelstv err = iwm_phy_ctxt_update(sc, &sc->sc_phyctxt[0],
6539 1.91 mlelstv in->in_ni.ni_chan, 1, 1, 0);
6540 1.91 mlelstv if (err)
6541 1.91 mlelstv return err;
6542 1.91 mlelstv }
6543 1.91 mlelstv
6544 1.91 mlelstv in->in_phyctxt = &sc->sc_phyctxt[0];
6545 1.91 mlelstv IEEE80211_ADDR_COPY(in->in_macaddr, in->in_ni.ni_macaddr);
6546 1.91 mlelstv iwm_setrates(in);
6547 1.91 mlelstv
6548 1.91 mlelstv err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_ADD, 0);
6549 1.91 mlelstv if (err) {
6550 1.91 mlelstv aprint_error_dev(sc->sc_dev,
6551 1.91 mlelstv "could not add MAC context (error %d)\n", err);
6552 1.91 mlelstv return err;
6553 1.91 mlelstv }
6554 1.91 mlelstv sc->sc_flags |= IWM_FLAG_MAC_ACTIVE;
6555 1.91 mlelstv
6556 1.91 mlelstv err = iwm_binding_cmd(sc, in, IWM_FW_CTXT_ACTION_ADD);
6557 1.91 mlelstv if (err) {
6558 1.91 mlelstv aprint_error_dev(sc->sc_dev,
6559 1.91 mlelstv "could not add binding (error %d)\n", err);
6560 1.91 mlelstv goto rm_mac_ctxt;
6561 1.91 mlelstv }
6562 1.91 mlelstv sc->sc_flags |= IWM_FLAG_BINDING_ACTIVE;
6563 1.91 mlelstv
6564 1.91 mlelstv in->tid_disable_ampdu = 0xffff;
6565 1.45 nonaka err = iwm_add_sta_cmd(sc, in, 0);
6566 1.91 mlelstv if (err) {
6567 1.91 mlelstv aprint_error_dev(sc->sc_dev,
6568 1.91 mlelstv "could not add sta (error %d)\n", err);
6569 1.91 mlelstv goto rm_binding;
6570 1.91 mlelstv }
6571 1.91 mlelstv sc->sc_flags |= IWM_FLAG_STA_ACTIVE;
6572 1.91 mlelstv
6573 1.91 mlelstv if (ic->ic_opmode == IEEE80211_M_MONITOR)
6574 1.91 mlelstv return 0;
6575 1.91 mlelstv
6576 1.91 mlelstv /*
6577 1.91 mlelstv * Prevent the FW from wandering off channel during association
6578 1.91 mlelstv * by "protecting" the session with a time event.
6579 1.91 mlelstv */
6580 1.93 mlelstv if (in->in_ni.ni_intval)
6581 1.93 mlelstv duration = in->in_ni.ni_intval * 5;
6582 1.93 mlelstv else
6583 1.93 mlelstv duration = IEEE80211_DUR_TU;
6584 1.93 mlelstv iwm_protect_session(sc, in, duration, in->in_ni.ni_intval / 2);
6585 1.91 mlelstv
6586 1.91 mlelstv return 0;
6587 1.91 mlelstv
6588 1.91 mlelstv rm_binding:
6589 1.91 mlelstv if (generation == sc->sc_generation) {
6590 1.91 mlelstv iwm_binding_cmd(sc, in, IWM_FW_CTXT_ACTION_REMOVE);
6591 1.91 mlelstv sc->sc_flags &= ~IWM_FLAG_BINDING_ACTIVE;
6592 1.91 mlelstv }
6593 1.91 mlelstv rm_mac_ctxt:
6594 1.91 mlelstv if (generation == sc->sc_generation) {
6595 1.91 mlelstv iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_REMOVE, 0);
6596 1.91 mlelstv sc->sc_flags &= ~IWM_FLAG_MAC_ACTIVE;
6597 1.91 mlelstv }
6598 1.91 mlelstv return err;
6599 1.91 mlelstv }
6600 1.91 mlelstv
6601 1.91 mlelstv #ifdef notyet
6602 1.91 mlelstv static int
6603 1.91 mlelstv iwm_deauth(struct iwm_softc *sc)
6604 1.91 mlelstv {
6605 1.91 mlelstv struct ieee80211com *ic = &sc->sc_ic;
6606 1.91 mlelstv struct iwm_node *in = (void *)ic->ic_bss;
6607 1.91 mlelstv int err;
6608 1.91 mlelstv
6609 1.91 mlelstv splassert(IPL_NET);
6610 1.91 mlelstv
6611 1.91 mlelstv iwm_unprotect_session(sc, in);
6612 1.91 mlelstv
6613 1.91 mlelstv if (sc->sc_flags & IWM_FLAG_STA_ACTIVE) {
6614 1.91 mlelstv err = iwm_flush_sta(sc, in);
6615 1.91 mlelstv if (err)
6616 1.91 mlelstv return err;
6617 1.91 mlelstv err = iwm_rm_sta_cmd(sc, in);
6618 1.91 mlelstv if (err) {
6619 1.91 mlelstv printf("%s: could not remove STA (error %d)\n",
6620 1.91 mlelstv DEVNAME(sc), err);
6621 1.91 mlelstv return err;
6622 1.91 mlelstv }
6623 1.91 mlelstv in->tid_disable_ampdu = 0xffff;
6624 1.91 mlelstv sc->sc_flags &= ~IWM_FLAG_STA_ACTIVE;
6625 1.91 mlelstv sc->sc_rx_ba_sessions = 0;
6626 1.91 mlelstv sc->ba_rx.start_tidmask = 0;
6627 1.91 mlelstv sc->ba_rx.stop_tidmask = 0;
6628 1.91 mlelstv sc->tx_ba_queue_mask = 0;
6629 1.91 mlelstv sc->ba_tx.start_tidmask = 0;
6630 1.91 mlelstv sc->ba_tx.stop_tidmask = 0;
6631 1.91 mlelstv }
6632 1.91 mlelstv
6633 1.91 mlelstv if (sc->sc_flags & IWM_FLAG_BINDING_ACTIVE) {
6634 1.91 mlelstv err = iwm_binding_cmd(sc, in, IWM_FW_CTXT_ACTION_REMOVE);
6635 1.91 mlelstv if (err) {
6636 1.91 mlelstv printf("%s: could not remove binding (error %d)\n",
6637 1.91 mlelstv DEVNAME(sc), err);
6638 1.91 mlelstv return err;
6639 1.91 mlelstv }
6640 1.91 mlelstv sc->sc_flags &= ~IWM_FLAG_BINDING_ACTIVE;
6641 1.91 mlelstv }
6642 1.91 mlelstv
6643 1.91 mlelstv if (sc->sc_flags & IWM_FLAG_MAC_ACTIVE) {
6644 1.91 mlelstv err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_REMOVE, 0);
6645 1.91 mlelstv if (err) {
6646 1.91 mlelstv printf("%s: could not remove MAC context (error %d)\n",
6647 1.91 mlelstv DEVNAME(sc), err);
6648 1.91 mlelstv return err;
6649 1.91 mlelstv }
6650 1.91 mlelstv sc->sc_flags &= ~IWM_FLAG_MAC_ACTIVE;
6651 1.91 mlelstv }
6652 1.91 mlelstv
6653 1.91 mlelstv /* Move unused PHY context to a default channel. */
6654 1.91 mlelstv err = iwm_phy_ctxt_update(sc, &sc->sc_phyctxt[0],
6655 1.91 mlelstv &ic->ic_channels[1], 1, 1, 0);
6656 1.45 nonaka if (err)
6657 1.45 nonaka return err;
6658 1.8 nonaka
6659 1.91 mlelstv return 0;
6660 1.91 mlelstv }
6661 1.91 mlelstv #endif
6662 1.91 mlelstv
6663 1.91 mlelstv static int
6664 1.91 mlelstv iwm_run(struct iwm_softc *sc)
6665 1.91 mlelstv {
6666 1.91 mlelstv struct ieee80211com *ic = &sc->sc_ic;
6667 1.91 mlelstv struct iwm_node *in = (void *)ic->ic_bss;
6668 1.91 mlelstv #ifndef IEEE80211_NO_HT
6669 1.91 mlelstv struct ieee80211_node *ni = &in->in_ni;
6670 1.91 mlelstv #endif
6671 1.91 mlelstv int err;
6672 1.91 mlelstv
6673 1.91 mlelstv if (ic->ic_opmode == IEEE80211_M_MONITOR) {
6674 1.91 mlelstv /* Add a MAC context and a sniffing STA. */
6675 1.91 mlelstv err = iwm_auth(sc);
6676 1.91 mlelstv if (err)
6677 1.91 mlelstv return err;
6678 1.91 mlelstv }
6679 1.91 mlelstv
6680 1.91 mlelstv /* Configure Rx chains for MIMO and configure 40 MHz channel. */
6681 1.91 mlelstv if (ic->ic_opmode == IEEE80211_M_MONITOR) {
6682 1.91 mlelstv uint8_t chains = iwm_mimo_enabled(sc) ? 2 : 1;
6683 1.91 mlelstv err = iwm_phy_ctxt_update(sc, in->in_phyctxt,
6684 1.91 mlelstv in->in_phyctxt->channel, chains, chains, 0);
6685 1.91 mlelstv if (err) {
6686 1.91 mlelstv printf("%s: failed to update PHY\n", DEVNAME(sc));
6687 1.91 mlelstv return err;
6688 1.91 mlelstv }
6689 1.91 mlelstv }
6690 1.91 mlelstv #ifndef IEEE80211_NO_HT
6691 1.91 mlelstv else if (ni->ni_flags & IEEE80211_NODE_HT) {
6692 1.91 mlelstv uint8_t chains = iwm_mimo_enabled(sc) ? 2 : 1;
6693 1.91 mlelstv uint8_t sco, vht_chan_width;
6694 1.91 mlelstv if (IEEE80211_CHAN_40MHZ_ALLOWED(in->in_ni.ni_chan) &&
6695 1.91 mlelstv ieee80211_node_supports_ht_chan40(ni))
6696 1.91 mlelstv sco = (ni->ni_htop0 & IEEE80211_HTOP0_SCO_MASK);
6697 1.91 mlelstv else
6698 1.91 mlelstv sco = IEEE80211_HTOP0_SCO_SCN;
6699 1.91 mlelstv if ((ni->ni_flags & IEEE80211_NODE_VHT) &&
6700 1.91 mlelstv IEEE80211_CHAN_80MHZ_ALLOWED(in->in_ni.ni_chan) &&
6701 1.91 mlelstv ieee80211_node_supports_vht_chan80(ni))
6702 1.91 mlelstv vht_chan_width = IEEE80211_VHTOP0_CHAN_WIDTH_80;
6703 1.91 mlelstv else
6704 1.91 mlelstv vht_chan_width = IEEE80211_VHTOP0_CHAN_WIDTH_HT;
6705 1.91 mlelstv err = iwm_phy_ctxt_update(sc, in->in_phyctxt,
6706 1.91 mlelstv in->in_phyctxt->channel, chains, chains, 0);
6707 1.91 mlelstv if (err) {
6708 1.91 mlelstv printf("%s: failed to update PHY\n", DEVNAME(sc));
6709 1.91 mlelstv return err;
6710 1.91 mlelstv }
6711 1.91 mlelstv }
6712 1.91 mlelstv #endif
6713 1.91 mlelstv
6714 1.91 mlelstv /* Update STA again to apply HT and VHT settings. */
6715 1.91 mlelstv err = iwm_add_sta_cmd(sc, in, 1);
6716 1.91 mlelstv if (err) {
6717 1.91 mlelstv printf("%s: could not update STA (error %d)\n",
6718 1.91 mlelstv DEVNAME(sc), err);
6719 1.91 mlelstv return err;
6720 1.91 mlelstv }
6721 1.91 mlelstv
6722 1.91 mlelstv /* We have now been assigned an associd by the AP. */
6723 1.91 mlelstv err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY, 1);
6724 1.91 mlelstv if (err) {
6725 1.91 mlelstv printf("%s: failed to update MAC\n", DEVNAME(sc));
6726 1.91 mlelstv return err;
6727 1.91 mlelstv }
6728 1.91 mlelstv
6729 1.91 mlelstv /* XXX */
6730 1.91 mlelstv iwm_unprotect_session(sc, in);
6731 1.91 mlelstv
6732 1.91 mlelstv err = iwm_sf_config(sc, IWM_SF_FULL_ON);
6733 1.91 mlelstv if (err) {
6734 1.91 mlelstv printf("%s: could not set sf full on (error %d)\n",
6735 1.91 mlelstv DEVNAME(sc), err);
6736 1.91 mlelstv return err;
6737 1.91 mlelstv }
6738 1.91 mlelstv
6739 1.91 mlelstv err = iwm_allow_mcast(sc);
6740 1.45 nonaka if (err) {
6741 1.91 mlelstv printf("%s: could not allow mcast (error %d)\n",
6742 1.91 mlelstv DEVNAME(sc), err);
6743 1.45 nonaka return err;
6744 1.45 nonaka }
6745 1.1 pooka
6746 1.91 mlelstv err = iwm_power_update_device(sc);
6747 1.91 mlelstv if (err) {
6748 1.91 mlelstv printf("%s: could not send power command (error %d)\n",
6749 1.91 mlelstv DEVNAME(sc), err);
6750 1.91 mlelstv return err;
6751 1.91 mlelstv }
6752 1.91 mlelstv #ifdef notyet
6753 1.45 nonaka /*
6754 1.91 mlelstv * Disabled for now. Default beacon filter settings
6755 1.91 mlelstv * prevent net80211 from getting ERP and HT protection
6756 1.91 mlelstv * updates from beacons.
6757 1.91 mlelstv */
6758 1.91 mlelstv err = iwm_enable_beacon_filter(sc, in);
6759 1.91 mlelstv if (err) {
6760 1.91 mlelstv printf("%s: could not enable beacon filter\n",
6761 1.91 mlelstv DEVNAME(sc));
6762 1.91 mlelstv return err;
6763 1.91 mlelstv }
6764 1.91 mlelstv #endif
6765 1.91 mlelstv err = iwm_power_mac_update_mode(sc, in);
6766 1.91 mlelstv if (err) {
6767 1.91 mlelstv printf("%s: could not update MAC power (error %d)\n",
6768 1.91 mlelstv DEVNAME(sc), err);
6769 1.91 mlelstv return err;
6770 1.91 mlelstv }
6771 1.91 mlelstv
6772 1.91 mlelstv if (!isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DYNAMIC_QUOTA)) {
6773 1.91 mlelstv err = iwm_update_quotas(sc, in);
6774 1.91 mlelstv if (err) {
6775 1.91 mlelstv printf("%s: could not update quotas (error %d)\n",
6776 1.91 mlelstv DEVNAME(sc), err);
6777 1.91 mlelstv return err;
6778 1.91 mlelstv }
6779 1.91 mlelstv }
6780 1.91 mlelstv
6781 1.91 mlelstv ieee80211_amrr_node_init(&sc->sc_amrr, &in->in_amn);
6782 1.91 mlelstv #ifndef IEEE80211_NO_HT
6783 1.91 mlelstv ieee80211_ra_node_init(&in->in_rn);
6784 1.91 mlelstv ieee80211_ra_vht_node_init(&in->in_rn_vht);
6785 1.91 mlelstv #endif
6786 1.91 mlelstv
6787 1.91 mlelstv if (ic->ic_opmode == IEEE80211_M_MONITOR) {
6788 1.91 mlelstv iwm_led_blink_start(sc);
6789 1.91 mlelstv return 0;
6790 1.91 mlelstv }
6791 1.91 mlelstv
6792 1.91 mlelstv /* Start at lowest available bit-rate, AMRR will raise. */
6793 1.91 mlelstv in->in_ni.ni_txrate = 0;
6794 1.91 mlelstv #ifndef IEEE80211_NO_HT
6795 1.91 mlelstv in->in_ni.ni_txmcs = 0;
6796 1.91 mlelstv in->in_ni.ni_vht_ss = 1;
6797 1.91 mlelstv #endif
6798 1.91 mlelstv iwm_setrates(in);
6799 1.91 mlelstv
6800 1.91 mlelstv callout_schedule(&sc->sc_calib_to, mstohz(500));
6801 1.91 mlelstv iwm_led_enable(sc);
6802 1.91 mlelstv
6803 1.91 mlelstv return 0;
6804 1.91 mlelstv }
6805 1.91 mlelstv
6806 1.91 mlelstv #ifdef notyet
6807 1.91 mlelstv static int
6808 1.91 mlelstv iwm_run_stop(struct iwm_softc *sc)
6809 1.91 mlelstv {
6810 1.91 mlelstv struct ieee80211com *ic = &sc->sc_ic;
6811 1.91 mlelstv struct iwm_node *in = (void *)ic->ic_bss;
6812 1.91 mlelstv #ifndef IEEE80211_NO_HT
6813 1.91 mlelstv struct ieee80211_node *ni = &in->in_ni;
6814 1.91 mlelstv int i, tid;
6815 1.91 mlelstv #endif
6816 1.91 mlelstv int err;
6817 1.91 mlelstv
6818 1.91 mlelstv /*
6819 1.91 mlelstv * Stop Tx/Rx BA sessions now. We cannot rely on the BA task
6820 1.91 mlelstv * for this when moving out of RUN state since it runs in a
6821 1.91 mlelstv * separate thread.
6822 1.91 mlelstv * Note that in->in_ni (struct ieee80211_node) already represents
6823 1.91 mlelstv * our new access point in case we are roaming between APs.
6824 1.91 mlelstv * This means we cannot rely on struct ieee802111_node to tell
6825 1.91 mlelstv * us which BA sessions exist.
6826 1.45 nonaka */
6827 1.91 mlelstv #ifndef IEEE80211_NO_HT
6828 1.91 mlelstv for (i = 0; i < __arraycount(sc->sc_rxba_data); i++) {
6829 1.91 mlelstv struct iwm_rxba_data *rxba = &sc->sc_rxba_data[i];
6830 1.91 mlelstv if (rxba->baid == IWM_RX_REORDER_DATA_INVALID_BAID)
6831 1.91 mlelstv continue;
6832 1.91 mlelstv err = iwm_sta_rx_agg(sc, ni, rxba->tid, 0, 0, 0, 0);
6833 1.91 mlelstv if (err)
6834 1.91 mlelstv return err;
6835 1.91 mlelstv iwm_clear_reorder_buffer(sc, rxba);
6836 1.91 mlelstv if (sc->sc_rx_ba_sessions > 0)
6837 1.91 mlelstv sc->sc_rx_ba_sessions--;
6838 1.91 mlelstv }
6839 1.91 mlelstv for (tid = 0; tid < IWM_MAX_TID_COUNT; tid++) {
6840 1.91 mlelstv int qid = IWM_FIRST_AGG_TX_QUEUE + tid;
6841 1.91 mlelstv if ((sc->tx_ba_queue_mask & (1 << qid)) == 0)
6842 1.91 mlelstv continue;
6843 1.91 mlelstv err = iwm_sta_tx_agg(sc, ni, tid, 0, 0, 0);
6844 1.91 mlelstv if (err)
6845 1.91 mlelstv return err;
6846 1.91 mlelstv err = iwm_disable_txq(sc, IWM_STATION_ID, qid, tid);
6847 1.91 mlelstv if (err)
6848 1.91 mlelstv return err;
6849 1.91 mlelstv in->tfd_queue_msk &= ~(1 << qid);
6850 1.91 mlelstv }
6851 1.91 mlelstv ieee80211_ba_del(ni);
6852 1.91 mlelstv #endif
6853 1.91 mlelstv
6854 1.91 mlelstv if (ic->ic_opmode == IEEE80211_M_MONITOR)
6855 1.91 mlelstv iwm_led_blink_stop(sc);
6856 1.91 mlelstv
6857 1.91 mlelstv err = iwm_sf_config(sc, IWM_SF_INIT_OFF);
6858 1.91 mlelstv if (err)
6859 1.91 mlelstv return err;
6860 1.91 mlelstv
6861 1.91 mlelstv iwm_disable_beacon_filter(sc);
6862 1.91 mlelstv
6863 1.91 mlelstv if (!isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DYNAMIC_QUOTA)) {
6864 1.91 mlelstv err = iwm_update_quotas(sc, in);
6865 1.91 mlelstv if (err) {
6866 1.91 mlelstv printf("%s: could not update quotas (error %d)\n",
6867 1.91 mlelstv DEVNAME(sc), err);
6868 1.91 mlelstv return err;
6869 1.91 mlelstv }
6870 1.91 mlelstv }
6871 1.91 mlelstv
6872 1.91 mlelstv /* Mark station as disassociated. */
6873 1.91 mlelstv err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY, 0);
6874 1.91 mlelstv if (err) {
6875 1.91 mlelstv printf("%s: failed to update MAC\n", DEVNAME(sc));
6876 1.91 mlelstv return err;
6877 1.91 mlelstv }
6878 1.91 mlelstv
6879 1.91 mlelstv #ifndef IEEE80211_NO_HT
6880 1.91 mlelstv /* Reset Tx chains in case MIMO or 40 MHz channels were enabled. */
6881 1.91 mlelstv if (in->in_ni.ni_flags & IEEE80211_NODE_HT) {
6882 1.91 mlelstv err = iwm_phy_ctxt_update(sc, in->in_phyctxt,
6883 1.91 mlelstv in->in_phyctxt->channel, 1, 1, 0);
6884 1.91 mlelstv if (err) {
6885 1.91 mlelstv printf("%s: failed to update PHY\n", DEVNAME(sc));
6886 1.91 mlelstv return err;
6887 1.91 mlelstv }
6888 1.91 mlelstv }
6889 1.91 mlelstv #endif
6890 1.1 pooka
6891 1.1 pooka return 0;
6892 1.1 pooka }
6893 1.91 mlelstv #endif
6894 1.1 pooka
6895 1.4 nonaka static int
6896 1.1 pooka iwm_assoc(struct iwm_softc *sc)
6897 1.1 pooka {
6898 1.91 mlelstv #if 0
6899 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
6900 1.45 nonaka struct iwm_node *in = (struct iwm_node *)ic->ic_bss;
6901 1.45 nonaka int err;
6902 1.1 pooka
6903 1.45 nonaka err = iwm_add_sta_cmd(sc, in, 1);
6904 1.45 nonaka if (err)
6905 1.45 nonaka return err;
6906 1.91 mlelstv #endif
6907 1.1 pooka
6908 1.1 pooka return 0;
6909 1.1 pooka }
6910 1.1 pooka
6911 1.1 pooka static struct ieee80211_node *
6912 1.1 pooka iwm_node_alloc(struct ieee80211_node_table *nt)
6913 1.1 pooka {
6914 1.5 nonaka return malloc(sizeof(struct iwm_node), M_80211_NODE, M_NOWAIT | M_ZERO);
6915 1.1 pooka }
6916 1.1 pooka
6917 1.4 nonaka static void
6918 1.1 pooka iwm_calib_timeout(void *arg)
6919 1.1 pooka {
6920 1.1 pooka struct iwm_softc *sc = arg;
6921 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
6922 1.45 nonaka struct iwm_node *in = (struct iwm_node *)ic->ic_bss;
6923 1.45 nonaka struct ieee80211_node *ni = &in->in_ni;
6924 1.45 nonaka int otxrate;
6925 1.1 pooka int s;
6926 1.1 pooka
6927 1.1 pooka s = splnet();
6928 1.45 nonaka if ((ic->ic_fixed_rate == -1
6929 1.45 nonaka #ifndef IEEE80211_NO_HT
6930 1.45 nonaka || ic->ic_fixed_mcs == -1
6931 1.45 nonaka #endif
6932 1.45 nonaka ) &&
6933 1.45 nonaka ic->ic_opmode == IEEE80211_M_STA && ic->ic_bss) {
6934 1.45 nonaka #ifndef IEEE80211_NO_HT
6935 1.45 nonaka if (ni->ni_flags & IEEE80211_NODE_HT)
6936 1.45 nonaka otxrate = ni->ni_txmcs;
6937 1.45 nonaka else
6938 1.91 mlelstv #endif
6939 1.45 nonaka otxrate = ni->ni_txrate;
6940 1.1 pooka ieee80211_amrr_choose(&sc->sc_amrr, &in->in_ni, &in->in_amn);
6941 1.45 nonaka
6942 1.45 nonaka #ifndef IEEE80211_NO_HT
6943 1.45 nonaka /*
6944 1.45 nonaka * If AMRR has chosen a new TX rate we must update
6945 1.45 nonaka * the firwmare's LQ rate table from process context.
6946 1.45 nonaka */
6947 1.45 nonaka if ((ni->ni_flags & IEEE80211_NODE_HT) &&
6948 1.45 nonaka otxrate != ni->ni_txmcs)
6949 1.91 mlelstv iwm_setrates_task(sc);
6950 1.91 mlelstv else
6951 1.45 nonaka #endif
6952 1.91 mlelstv if (otxrate != ni->ni_txrate)
6953 1.91 mlelstv iwm_setrates_task(sc);
6954 1.1 pooka }
6955 1.1 pooka splx(s);
6956 1.1 pooka
6957 1.45 nonaka callout_schedule(&sc->sc_calib_to, mstohz(500));
6958 1.1 pooka }
6959 1.1 pooka
6960 1.91 mlelstv static int
6961 1.91 mlelstv iwm_setrates_task(struct iwm_softc *sc)
6962 1.91 mlelstv {
6963 1.91 mlelstv struct work *wk;
6964 1.91 mlelstv
6965 1.91 mlelstv wk = kmem_intr_alloc(sizeof(*wk), KM_NOSLEEP);
6966 1.91 mlelstv if (!wk) {
6967 1.91 mlelstv DPRINTF(("%s: allocating setrates cb mem failed\n", DEVNAME(sc)));
6968 1.91 mlelstv return ENOMEM;
6969 1.91 mlelstv }
6970 1.91 mlelstv
6971 1.91 mlelstv workqueue_enqueue(sc->sc_setratewq, wk, NULL);
6972 1.91 mlelstv
6973 1.91 mlelstv return 0;
6974 1.91 mlelstv }
6975 1.91 mlelstv
6976 1.4 nonaka static void
6977 1.91 mlelstv iwm_setrates_cb(struct work *wk, void *arg)
6978 1.45 nonaka {
6979 1.45 nonaka struct iwm_softc *sc = arg;
6980 1.45 nonaka struct ieee80211com *ic = &sc->sc_ic;
6981 1.45 nonaka struct iwm_node *in = (struct iwm_node *)ic->ic_bss;
6982 1.91 mlelstv int s;
6983 1.91 mlelstv
6984 1.91 mlelstv kmem_intr_free(wk, sizeof(*wk));
6985 1.91 mlelstv
6986 1.91 mlelstv s = splnet();
6987 1.45 nonaka
6988 1.45 nonaka /* Update rates table based on new TX rate determined by AMRR. */
6989 1.45 nonaka iwm_setrates(in);
6990 1.91 mlelstv
6991 1.91 mlelstv splx(s);
6992 1.45 nonaka }
6993 1.45 nonaka
6994 1.45 nonaka static int
6995 1.1 pooka iwm_setrates(struct iwm_node *in)
6996 1.1 pooka {
6997 1.1 pooka struct ieee80211_node *ni = &in->in_ni;
6998 1.1 pooka struct ieee80211com *ic = ni->ni_ic;
6999 1.1 pooka struct iwm_softc *sc = IC2IFP(ic)->if_softc;
7000 1.1 pooka struct iwm_lq_cmd *lq = &in->in_lq;
7001 1.45 nonaka struct ieee80211_rateset *rs = &ni->ni_rates;
7002 1.45 nonaka int i, j, ridx, ridx_min, tab = 0;
7003 1.45 nonaka #ifndef IEEE80211_NO_HT
7004 1.45 nonaka int sgi_ok;
7005 1.45 nonaka #endif
7006 1.45 nonaka struct iwm_host_cmd cmd = {
7007 1.45 nonaka .id = IWM_LQ_CMD,
7008 1.45 nonaka .len = { sizeof(in->in_lq), },
7009 1.45 nonaka };
7010 1.1 pooka
7011 1.45 nonaka memset(lq, 0, sizeof(*lq));
7012 1.45 nonaka lq->sta_id = IWM_STATION_ID;
7013 1.1 pooka
7014 1.45 nonaka if (ic->ic_flags & IEEE80211_F_USEPROT)
7015 1.45 nonaka lq->flags |= IWM_LQ_FLAG_USE_RTS_MSK;
7016 1.8 nonaka
7017 1.45 nonaka #ifndef IEEE80211_NO_HT
7018 1.45 nonaka sgi_ok = ((ni->ni_flags & IEEE80211_NODE_HT) &&
7019 1.45 nonaka (ni->ni_htcaps & IEEE80211_HTCAP_SGI20));
7020 1.45 nonaka #endif
7021 1.1 pooka
7022 1.1 pooka
7023 1.1 pooka /*
7024 1.45 nonaka * Fill the LQ rate selection table with legacy and/or HT rates
7025 1.45 nonaka * in descending order, i.e. with the node's current TX rate first.
7026 1.45 nonaka * In cases where throughput of an HT rate corresponds to a legacy
7027 1.45 nonaka * rate it makes no sense to add both. We rely on the fact that
7028 1.45 nonaka * iwm_rates is laid out such that equivalent HT/legacy rates share
7029 1.45 nonaka * the same IWM_RATE_*_INDEX value. Also, rates not applicable to
7030 1.45 nonaka * legacy/HT are assumed to be marked with an 'invalid' PLCP value.
7031 1.1 pooka */
7032 1.45 nonaka j = 0;
7033 1.45 nonaka ridx_min = (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) ?
7034 1.45 nonaka IWM_RIDX_OFDM : IWM_RIDX_CCK;
7035 1.45 nonaka for (ridx = IWM_RIDX_MAX; ridx >= ridx_min; ridx--) {
7036 1.45 nonaka if (j >= __arraycount(lq->rs_table))
7037 1.45 nonaka break;
7038 1.45 nonaka tab = 0;
7039 1.45 nonaka #ifndef IEEE80211_NO_HT
7040 1.45 nonaka if ((ni->ni_flags & IEEE80211_NODE_HT) &&
7041 1.45 nonaka iwm_rates[ridx].ht_plcp != IWM_RATE_HT_SISO_MCS_INV_PLCP) {
7042 1.45 nonaka for (i = ni->ni_txmcs; i >= 0; i--) {
7043 1.45 nonaka if (isclr(ni->ni_rxmcs, i))
7044 1.45 nonaka continue;
7045 1.45 nonaka if (ridx == iwm_mcs2ridx[i]) {
7046 1.45 nonaka tab = iwm_rates[ridx].ht_plcp;
7047 1.45 nonaka tab |= IWM_RATE_MCS_HT_MSK;
7048 1.45 nonaka if (sgi_ok)
7049 1.45 nonaka tab |= IWM_RATE_MCS_SGI_MSK;
7050 1.45 nonaka break;
7051 1.45 nonaka }
7052 1.45 nonaka }
7053 1.45 nonaka }
7054 1.45 nonaka #endif
7055 1.45 nonaka if (tab == 0 && iwm_rates[ridx].plcp != IWM_RATE_INVM_PLCP) {
7056 1.45 nonaka for (i = ni->ni_txrate; i >= 0; i--) {
7057 1.45 nonaka if (iwm_rates[ridx].rate == (rs->rs_rates[i] &
7058 1.45 nonaka IEEE80211_RATE_VAL)) {
7059 1.45 nonaka tab = iwm_rates[ridx].plcp;
7060 1.45 nonaka break;
7061 1.45 nonaka }
7062 1.45 nonaka }
7063 1.45 nonaka }
7064 1.1 pooka
7065 1.45 nonaka if (tab == 0)
7066 1.45 nonaka continue;
7067 1.1 pooka
7068 1.45 nonaka tab |= 1 << IWM_RATE_MCS_ANT_POS;
7069 1.1 pooka if (IWM_RIDX_IS_CCK(ridx))
7070 1.1 pooka tab |= IWM_RATE_MCS_CCK_MSK;
7071 1.1 pooka DPRINTFN(2, ("station rate %d %x\n", i, tab));
7072 1.45 nonaka lq->rs_table[j++] = htole32(tab);
7073 1.1 pooka }
7074 1.1 pooka
7075 1.45 nonaka /* Fill the rest with the lowest possible rate */
7076 1.45 nonaka i = j > 0 ? j - 1 : 0;
7077 1.45 nonaka while (j < __arraycount(lq->rs_table))
7078 1.45 nonaka lq->rs_table[j++] = lq->rs_table[i];
7079 1.45 nonaka
7080 1.45 nonaka lq->single_stream_ant_msk = IWM_ANT_A;
7081 1.45 nonaka lq->dual_stream_ant_msk = IWM_ANT_AB;
7082 1.45 nonaka
7083 1.45 nonaka lq->agg_time_limit = htole16(4000); /* 4ms */
7084 1.45 nonaka lq->agg_disable_start_th = 3;
7085 1.45 nonaka #ifdef notyet
7086 1.45 nonaka lq->agg_frame_cnt_limit = 0x3f;
7087 1.45 nonaka #else
7088 1.45 nonaka lq->agg_frame_cnt_limit = 1; /* tx agg disabled */
7089 1.45 nonaka #endif
7090 1.45 nonaka
7091 1.45 nonaka cmd.data[0] = &in->in_lq;
7092 1.45 nonaka return iwm_send_cmd(sc, &cmd);
7093 1.1 pooka }
7094 1.1 pooka
7095 1.4 nonaka static int
7096 1.1 pooka iwm_media_change(struct ifnet *ifp)
7097 1.1 pooka {
7098 1.1 pooka struct iwm_softc *sc = ifp->if_softc;
7099 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
7100 1.1 pooka uint8_t rate, ridx;
7101 1.45 nonaka int err;
7102 1.1 pooka
7103 1.45 nonaka err = ieee80211_media_change(ifp);
7104 1.45 nonaka if (err != ENETRESET)
7105 1.45 nonaka return err;
7106 1.1 pooka
7107 1.45 nonaka #ifndef IEEE80211_NO_HT
7108 1.45 nonaka if (ic->ic_fixed_mcs != -1)
7109 1.45 nonaka sc->sc_fixed_ridx = iwm_mcs2ridx[ic->ic_fixed_mcs];
7110 1.45 nonaka else
7111 1.45 nonaka #endif
7112 1.1 pooka if (ic->ic_fixed_rate != -1) {
7113 1.1 pooka rate = ic->ic_sup_rates[ic->ic_curmode].
7114 1.1 pooka rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
7115 1.1 pooka /* Map 802.11 rate to HW rate index. */
7116 1.1 pooka for (ridx = 0; ridx <= IWM_RIDX_MAX; ridx++)
7117 1.1 pooka if (iwm_rates[ridx].rate == rate)
7118 1.1 pooka break;
7119 1.1 pooka sc->sc_fixed_ridx = ridx;
7120 1.1 pooka }
7121 1.1 pooka
7122 1.1 pooka if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
7123 1.1 pooka (IFF_UP | IFF_RUNNING)) {
7124 1.1 pooka iwm_stop(ifp, 0);
7125 1.45 nonaka err = iwm_init(ifp);
7126 1.1 pooka }
7127 1.45 nonaka return err;
7128 1.1 pooka }
7129 1.1 pooka
7130 1.65 nonaka static int
7131 1.65 nonaka iwm_do_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
7132 1.1 pooka {
7133 1.65 nonaka struct ifnet *ifp = IC2IFP(ic);
7134 1.65 nonaka struct iwm_softc *sc = ifp->if_softc;
7135 1.45 nonaka enum ieee80211_state ostate = ic->ic_state;
7136 1.45 nonaka int err;
7137 1.1 pooka
7138 1.45 nonaka DPRINTF(("switching state %s->%s\n", ieee80211_state_name[ostate],
7139 1.45 nonaka ieee80211_state_name[nstate]));
7140 1.1 pooka
7141 1.45 nonaka if (ostate == IEEE80211_S_SCAN && nstate != ostate)
7142 1.45 nonaka iwm_led_blink_stop(sc);
7143 1.45 nonaka
7144 1.45 nonaka if (ostate == IEEE80211_S_RUN && nstate != ostate)
7145 1.45 nonaka iwm_disable_beacon_filter(sc);
7146 1.45 nonaka
7147 1.45 nonaka /* Reset the device if moving out of AUTH, ASSOC, or RUN. */
7148 1.45 nonaka /* XXX Is there a way to switch states without a full reset? */
7149 1.45 nonaka if (ostate > IEEE80211_S_SCAN && nstate < ostate) {
7150 1.1 pooka /*
7151 1.45 nonaka * Upon receiving a deauth frame from AP the net80211 stack
7152 1.45 nonaka * puts the driver into AUTH state. This will fail with this
7153 1.45 nonaka * driver so bring the FSM from RUN to SCAN in this case.
7154 1.1 pooka */
7155 1.69 nonaka if (nstate != IEEE80211_S_INIT) {
7156 1.1 pooka DPRINTF(("Force transition to INIT; MGT=%d\n", arg));
7157 1.45 nonaka /* Always pass arg as -1 since we can't Tx right now. */
7158 1.45 nonaka sc->sc_newstate(ic, IEEE80211_S_INIT, -1);
7159 1.91 mlelstv iwm_stop(ifp, 1);
7160 1.69 nonaka iwm_init(ifp);
7161 1.69 nonaka return 0;
7162 1.1 pooka }
7163 1.1 pooka }
7164 1.1 pooka
7165 1.1 pooka switch (nstate) {
7166 1.1 pooka case IEEE80211_S_INIT:
7167 1.1 pooka break;
7168 1.1 pooka
7169 1.1 pooka case IEEE80211_S_SCAN:
7170 1.91 mlelstv if (!ISSET(sc->sc_flags, IWM_FLAG_SCANNING)) {
7171 1.91 mlelstv err = iwm_scan(sc);
7172 1.91 mlelstv if (err)
7173 1.91 mlelstv return err;
7174 1.91 mlelstv SET(sc->sc_flags, IWM_FLAG_SCANNING);
7175 1.1 pooka }
7176 1.91 mlelstv iwm_led_blink_start(sc);
7177 1.1 pooka ic->ic_state = nstate;
7178 1.65 nonaka return 0;
7179 1.1 pooka
7180 1.1 pooka case IEEE80211_S_AUTH:
7181 1.45 nonaka err = iwm_auth(sc);
7182 1.45 nonaka if (err) {
7183 1.2 nonaka DPRINTF(("%s: could not move to auth state: %d\n",
7184 1.45 nonaka DEVNAME(sc), err));
7185 1.65 nonaka return err;
7186 1.1 pooka }
7187 1.1 pooka break;
7188 1.1 pooka
7189 1.1 pooka case IEEE80211_S_ASSOC:
7190 1.45 nonaka err = iwm_assoc(sc);
7191 1.45 nonaka if (err) {
7192 1.2 nonaka DPRINTF(("%s: failed to associate: %d\n", DEVNAME(sc),
7193 1.45 nonaka err));
7194 1.65 nonaka return err;
7195 1.1 pooka }
7196 1.1 pooka break;
7197 1.1 pooka
7198 1.45 nonaka case IEEE80211_S_RUN:
7199 1.91 mlelstv err = iwm_run(sc);
7200 1.45 nonaka if (err) {
7201 1.91 mlelstv DPRINTF(("%s: failed to run: %d\n", DEVNAME(sc),
7202 1.91 mlelstv err));
7203 1.65 nonaka return err;
7204 1.45 nonaka }
7205 1.45 nonaka break;
7206 1.1 pooka
7207 1.1 pooka default:
7208 1.2 nonaka break;
7209 1.1 pooka }
7210 1.1 pooka
7211 1.65 nonaka return sc->sc_newstate(ic, nstate, arg);
7212 1.65 nonaka }
7213 1.65 nonaka
7214 1.65 nonaka static void
7215 1.65 nonaka iwm_newstate_cb(struct work *wk, void *v)
7216 1.65 nonaka {
7217 1.65 nonaka struct iwm_softc *sc = v;
7218 1.65 nonaka struct ieee80211com *ic = &sc->sc_ic;
7219 1.65 nonaka struct iwm_newstate_state *iwmns = (struct iwm_newstate_state *)wk;
7220 1.65 nonaka enum ieee80211_state nstate = iwmns->ns_nstate;
7221 1.65 nonaka int generation = iwmns->ns_generation;
7222 1.65 nonaka int arg = iwmns->ns_arg;
7223 1.65 nonaka
7224 1.75 para kmem_intr_free(iwmns, sizeof(*iwmns));
7225 1.65 nonaka
7226 1.91 mlelstv if (ISSET(sc->sc_flags, IWM_FLAG_STOPPED))
7227 1.91 mlelstv return;
7228 1.65 nonaka
7229 1.65 nonaka DPRINTF(("Prepare to switch state %d->%d\n", ic->ic_state, nstate));
7230 1.65 nonaka if (sc->sc_generation != generation) {
7231 1.65 nonaka DPRINTF(("newstate_cb: someone pulled the plug meanwhile\n"));
7232 1.65 nonaka if (nstate == IEEE80211_S_INIT) {
7233 1.65 nonaka DPRINTF(("newstate_cb: nstate == IEEE80211_S_INIT: "
7234 1.65 nonaka "calling sc_newstate()\n"));
7235 1.65 nonaka (void) sc->sc_newstate(ic, nstate, arg);
7236 1.65 nonaka }
7237 1.65 nonaka } else
7238 1.65 nonaka (void) iwm_do_newstate(ic, nstate, arg);
7239 1.1 pooka }
7240 1.1 pooka
7241 1.4 nonaka static int
7242 1.1 pooka iwm_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
7243 1.1 pooka {
7244 1.1 pooka struct iwm_newstate_state *iwmns;
7245 1.1 pooka struct ifnet *ifp = IC2IFP(ic);
7246 1.1 pooka struct iwm_softc *sc = ifp->if_softc;
7247 1.1 pooka
7248 1.1 pooka callout_stop(&sc->sc_calib_to);
7249 1.1 pooka
7250 1.5 nonaka iwmns = kmem_intr_alloc(sizeof(*iwmns), KM_NOSLEEP);
7251 1.1 pooka if (!iwmns) {
7252 1.2 nonaka DPRINTF(("%s: allocating state cb mem failed\n", DEVNAME(sc)));
7253 1.1 pooka return ENOMEM;
7254 1.1 pooka }
7255 1.1 pooka
7256 1.1 pooka iwmns->ns_nstate = nstate;
7257 1.1 pooka iwmns->ns_arg = arg;
7258 1.1 pooka iwmns->ns_generation = sc->sc_generation;
7259 1.1 pooka
7260 1.1 pooka workqueue_enqueue(sc->sc_nswq, &iwmns->ns_wk, NULL);
7261 1.1 pooka
7262 1.1 pooka return 0;
7263 1.1 pooka }
7264 1.1 pooka
7265 1.4 nonaka static void
7266 1.50 nonaka iwm_endscan(struct iwm_softc *sc)
7267 1.1 pooka {
7268 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
7269 1.61 nonaka int s;
7270 1.1 pooka
7271 1.61 nonaka DPRINTF(("%s: scan ended\n", DEVNAME(sc)));
7272 1.1 pooka
7273 1.61 nonaka s = splnet();
7274 1.61 nonaka if (ic->ic_state == IEEE80211_S_SCAN)
7275 1.61 nonaka ieee80211_end_scan(ic);
7276 1.91 mlelstv CLR(sc->sc_flags, IWM_FLAG_SCANNING);
7277 1.61 nonaka splx(s);
7278 1.45 nonaka }
7279 1.45 nonaka
7280 1.45 nonaka /*
7281 1.45 nonaka * Aging and idle timeouts for the different possible scenarios
7282 1.45 nonaka * in default configuration
7283 1.45 nonaka */
7284 1.45 nonaka static const uint32_t
7285 1.45 nonaka iwm_sf_full_timeout_def[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES] = {
7286 1.45 nonaka {
7287 1.45 nonaka htole32(IWM_SF_SINGLE_UNICAST_AGING_TIMER_DEF),
7288 1.45 nonaka htole32(IWM_SF_SINGLE_UNICAST_IDLE_TIMER_DEF)
7289 1.45 nonaka },
7290 1.45 nonaka {
7291 1.45 nonaka htole32(IWM_SF_AGG_UNICAST_AGING_TIMER_DEF),
7292 1.45 nonaka htole32(IWM_SF_AGG_UNICAST_IDLE_TIMER_DEF)
7293 1.45 nonaka },
7294 1.45 nonaka {
7295 1.45 nonaka htole32(IWM_SF_MCAST_AGING_TIMER_DEF),
7296 1.45 nonaka htole32(IWM_SF_MCAST_IDLE_TIMER_DEF)
7297 1.45 nonaka },
7298 1.45 nonaka {
7299 1.45 nonaka htole32(IWM_SF_BA_AGING_TIMER_DEF),
7300 1.45 nonaka htole32(IWM_SF_BA_IDLE_TIMER_DEF)
7301 1.45 nonaka },
7302 1.45 nonaka {
7303 1.45 nonaka htole32(IWM_SF_TX_RE_AGING_TIMER_DEF),
7304 1.45 nonaka htole32(IWM_SF_TX_RE_IDLE_TIMER_DEF)
7305 1.45 nonaka },
7306 1.45 nonaka };
7307 1.45 nonaka
7308 1.45 nonaka /*
7309 1.45 nonaka * Aging and idle timeouts for the different possible scenarios
7310 1.45 nonaka * in single BSS MAC configuration.
7311 1.45 nonaka */
7312 1.45 nonaka static const uint32_t
7313 1.45 nonaka iwm_sf_full_timeout[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES] = {
7314 1.45 nonaka {
7315 1.45 nonaka htole32(IWM_SF_SINGLE_UNICAST_AGING_TIMER),
7316 1.45 nonaka htole32(IWM_SF_SINGLE_UNICAST_IDLE_TIMER)
7317 1.45 nonaka },
7318 1.45 nonaka {
7319 1.45 nonaka htole32(IWM_SF_AGG_UNICAST_AGING_TIMER),
7320 1.45 nonaka htole32(IWM_SF_AGG_UNICAST_IDLE_TIMER)
7321 1.45 nonaka },
7322 1.45 nonaka {
7323 1.45 nonaka htole32(IWM_SF_MCAST_AGING_TIMER),
7324 1.45 nonaka htole32(IWM_SF_MCAST_IDLE_TIMER)
7325 1.45 nonaka },
7326 1.45 nonaka {
7327 1.45 nonaka htole32(IWM_SF_BA_AGING_TIMER),
7328 1.45 nonaka htole32(IWM_SF_BA_IDLE_TIMER)
7329 1.45 nonaka },
7330 1.45 nonaka {
7331 1.45 nonaka htole32(IWM_SF_TX_RE_AGING_TIMER),
7332 1.45 nonaka htole32(IWM_SF_TX_RE_IDLE_TIMER)
7333 1.45 nonaka },
7334 1.45 nonaka };
7335 1.45 nonaka
7336 1.45 nonaka static void
7337 1.45 nonaka iwm_fill_sf_command(struct iwm_softc *sc, struct iwm_sf_cfg_cmd *sf_cmd,
7338 1.45 nonaka struct ieee80211_node *ni)
7339 1.45 nonaka {
7340 1.45 nonaka int i, j, watermark;
7341 1.45 nonaka
7342 1.45 nonaka sf_cmd->watermark[IWM_SF_LONG_DELAY_ON] = htole32(IWM_SF_W_MARK_SCAN);
7343 1.45 nonaka
7344 1.45 nonaka /*
7345 1.45 nonaka * If we are in association flow - check antenna configuration
7346 1.45 nonaka * capabilities of the AP station, and choose the watermark accordingly.
7347 1.45 nonaka */
7348 1.45 nonaka if (ni) {
7349 1.45 nonaka #ifndef IEEE80211_NO_HT
7350 1.45 nonaka if (ni->ni_flags & IEEE80211_NODE_HT) {
7351 1.45 nonaka #ifdef notyet
7352 1.45 nonaka if (ni->ni_rxmcs[2] != 0)
7353 1.45 nonaka watermark = IWM_SF_W_MARK_MIMO3;
7354 1.45 nonaka else if (ni->ni_rxmcs[1] != 0)
7355 1.45 nonaka watermark = IWM_SF_W_MARK_MIMO2;
7356 1.45 nonaka else
7357 1.45 nonaka #endif
7358 1.45 nonaka watermark = IWM_SF_W_MARK_SISO;
7359 1.45 nonaka } else
7360 1.45 nonaka #endif
7361 1.45 nonaka watermark = IWM_SF_W_MARK_LEGACY;
7362 1.45 nonaka /* default watermark value for unassociated mode. */
7363 1.45 nonaka } else {
7364 1.45 nonaka watermark = IWM_SF_W_MARK_MIMO2;
7365 1.45 nonaka }
7366 1.45 nonaka sf_cmd->watermark[IWM_SF_FULL_ON] = htole32(watermark);
7367 1.45 nonaka
7368 1.45 nonaka for (i = 0; i < IWM_SF_NUM_SCENARIO; i++) {
7369 1.45 nonaka for (j = 0; j < IWM_SF_NUM_TIMEOUT_TYPES; j++) {
7370 1.45 nonaka sf_cmd->long_delay_timeouts[i][j] =
7371 1.45 nonaka htole32(IWM_SF_LONG_DELAY_AGING_TIMER);
7372 1.1 pooka }
7373 1.45 nonaka }
7374 1.45 nonaka
7375 1.45 nonaka if (ni) {
7376 1.45 nonaka memcpy(sf_cmd->full_on_timeouts, iwm_sf_full_timeout,
7377 1.45 nonaka sizeof(iwm_sf_full_timeout));
7378 1.1 pooka } else {
7379 1.45 nonaka memcpy(sf_cmd->full_on_timeouts, iwm_sf_full_timeout_def,
7380 1.45 nonaka sizeof(iwm_sf_full_timeout_def));
7381 1.45 nonaka }
7382 1.45 nonaka }
7383 1.45 nonaka
7384 1.45 nonaka static int
7385 1.45 nonaka iwm_sf_config(struct iwm_softc *sc, int new_state)
7386 1.45 nonaka {
7387 1.45 nonaka struct ieee80211com *ic = &sc->sc_ic;
7388 1.45 nonaka struct iwm_sf_cfg_cmd sf_cmd = {
7389 1.45 nonaka .state = htole32(IWM_SF_FULL_ON),
7390 1.45 nonaka };
7391 1.45 nonaka
7392 1.91 mlelstv #if 0
7393 1.91 mlelstv /* only used for models with sdio interface, in iwlwifi */
7394 1.45 nonaka if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000)
7395 1.45 nonaka sf_cmd.state |= htole32(IWM_SF_CFG_DUMMY_NOTIF_OFF);
7396 1.91 mlelstv #endif
7397 1.45 nonaka
7398 1.45 nonaka switch (new_state) {
7399 1.45 nonaka case IWM_SF_UNINIT:
7400 1.45 nonaka case IWM_SF_INIT_OFF:
7401 1.45 nonaka iwm_fill_sf_command(sc, &sf_cmd, NULL);
7402 1.45 nonaka break;
7403 1.45 nonaka case IWM_SF_FULL_ON:
7404 1.45 nonaka iwm_fill_sf_command(sc, &sf_cmd, ic->ic_bss);
7405 1.45 nonaka break;
7406 1.45 nonaka default:
7407 1.45 nonaka return EINVAL;
7408 1.1 pooka }
7409 1.1 pooka
7410 1.45 nonaka return iwm_send_cmd_pdu(sc, IWM_REPLY_SF_CFG_CMD, IWM_CMD_ASYNC,
7411 1.45 nonaka sizeof(sf_cmd), &sf_cmd);
7412 1.45 nonaka }
7413 1.45 nonaka
7414 1.45 nonaka static int
7415 1.45 nonaka iwm_send_bt_init_conf(struct iwm_softc *sc)
7416 1.45 nonaka {
7417 1.45 nonaka struct iwm_bt_coex_cmd bt_cmd;
7418 1.45 nonaka
7419 1.45 nonaka bt_cmd.mode = htole32(IWM_BT_COEX_WIFI);
7420 1.45 nonaka bt_cmd.enabled_modules = htole32(IWM_BT_COEX_HIGH_BAND_RET);
7421 1.45 nonaka
7422 1.91 mlelstv return iwm_send_cmd_pdu(sc, IWM_BT_CONFIG, 0, sizeof(bt_cmd),
7423 1.91 mlelstv &bt_cmd);
7424 1.45 nonaka }
7425 1.45 nonaka
7426 1.60 nonaka static bool
7427 1.60 nonaka iwm_is_lar_supported(struct iwm_softc *sc)
7428 1.60 nonaka {
7429 1.60 nonaka bool nvm_lar = sc->sc_nvm.lar_enabled;
7430 1.60 nonaka bool tlv_lar = isset(sc->sc_enabled_capa,
7431 1.60 nonaka IWM_UCODE_TLV_CAPA_LAR_SUPPORT);
7432 1.60 nonaka
7433 1.60 nonaka if (iwm_lar_disable)
7434 1.60 nonaka return false;
7435 1.60 nonaka
7436 1.60 nonaka /*
7437 1.60 nonaka * Enable LAR only if it is supported by the FW (TLV) &&
7438 1.60 nonaka * enabled in the NVM
7439 1.60 nonaka */
7440 1.60 nonaka if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000)
7441 1.60 nonaka return nvm_lar && tlv_lar;
7442 1.60 nonaka else
7443 1.60 nonaka return tlv_lar;
7444 1.60 nonaka }
7445 1.60 nonaka
7446 1.45 nonaka static int
7447 1.91 mlelstv iwm_send_soc_conf(struct iwm_softc *sc)
7448 1.91 mlelstv {
7449 1.91 mlelstv struct iwm_soc_configuration_cmd cmd;
7450 1.91 mlelstv int err;
7451 1.91 mlelstv uint32_t cmd_id, flags = 0;
7452 1.91 mlelstv
7453 1.91 mlelstv memset(&cmd, 0, sizeof(cmd));
7454 1.91 mlelstv
7455 1.91 mlelstv /*
7456 1.91 mlelstv * In VER_1 of this command, the discrete value is considered
7457 1.91 mlelstv * an integer; In VER_2, it's a bitmask. Since we have only 2
7458 1.91 mlelstv * values in VER_1, this is backwards-compatible with VER_2,
7459 1.91 mlelstv * as long as we don't set any other flag bits.
7460 1.91 mlelstv */
7461 1.91 mlelstv #ifdef notyet
7462 1.91 mlelstv if (!sc->sc_integrated) { /* VER_1 */
7463 1.91 mlelstv flags = IWM_SOC_CONFIG_CMD_FLAGS_DISCRETE;
7464 1.91 mlelstv } else { /* VER_2 */
7465 1.91 mlelstv uint8_t scan_cmd_ver;
7466 1.91 mlelstv if (sc->sc_ltr_delay != IWM_SOC_FLAGS_LTR_APPLY_DELAY_NONE)
7467 1.91 mlelstv flags |= (sc->sc_ltr_delay &
7468 1.91 mlelstv IWM_SOC_FLAGS_LTR_APPLY_DELAY_MASK);
7469 1.91 mlelstv scan_cmd_ver = iwm_lookup_cmd_ver(sc, IWM_LONG_GROUP,
7470 1.91 mlelstv IWM_SCAN_REQ_UMAC);
7471 1.91 mlelstv if (scan_cmd_ver != IWM_FW_CMD_VER_UNKNOWN &&
7472 1.91 mlelstv scan_cmd_ver >= 2 && sc->sc_low_latency_xtal)
7473 1.91 mlelstv flags |= IWM_SOC_CONFIG_CMD_FLAGS_LOW_LATENCY;
7474 1.91 mlelstv }
7475 1.91 mlelstv cmd.latency = htole32(sc->sc_xtal_latency);
7476 1.91 mlelstv #else
7477 1.91 mlelstv flags = IWM_SOC_CONFIG_CMD_FLAGS_DISCRETE;
7478 1.91 mlelstv #endif
7479 1.91 mlelstv cmd.flags = htole32(flags);
7480 1.91 mlelstv
7481 1.91 mlelstv cmd_id = iwm_cmd_id(IWM_SOC_CONFIGURATION_CMD, IWM_SYSTEM_GROUP, 0);
7482 1.91 mlelstv err = iwm_send_cmd_pdu(sc, cmd_id, 0, sizeof(cmd), &cmd);
7483 1.91 mlelstv if (err)
7484 1.91 mlelstv printf("%s: failed to set soc latency: %d\n", DEVNAME(sc), err);
7485 1.91 mlelstv return err;
7486 1.91 mlelstv }
7487 1.91 mlelstv
7488 1.91 mlelstv static int
7489 1.45 nonaka iwm_send_update_mcc_cmd(struct iwm_softc *sc, const char *alpha2)
7490 1.45 nonaka {
7491 1.45 nonaka struct iwm_mcc_update_cmd mcc_cmd;
7492 1.45 nonaka struct iwm_host_cmd hcmd = {
7493 1.45 nonaka .id = IWM_MCC_UPDATE_CMD,
7494 1.91 mlelstv .flags = IWM_CMD_WANT_RESP,
7495 1.91 mlelstv .resp_pkt_len = IWM_CMD_RESP_MAX,
7496 1.45 nonaka .data = { &mcc_cmd },
7497 1.45 nonaka };
7498 1.91 mlelstv struct iwm_rx_packet *pkt;
7499 1.91 mlelstv size_t resp_len;
7500 1.60 nonaka int err;
7501 1.91 mlelstv int resp_v3 = isset(sc->sc_enabled_capa,
7502 1.91 mlelstv IWM_UCODE_TLV_CAPA_LAR_SUPPORT_V3);
7503 1.60 nonaka
7504 1.60 nonaka if (!iwm_is_lar_supported(sc)) {
7505 1.60 nonaka DPRINTF(("%s: no LAR support\n", __func__));
7506 1.60 nonaka return 0;
7507 1.60 nonaka }
7508 1.45 nonaka
7509 1.45 nonaka memset(&mcc_cmd, 0, sizeof(mcc_cmd));
7510 1.45 nonaka mcc_cmd.mcc = htole16(alpha2[0] << 8 | alpha2[1]);
7511 1.71 nonaka if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_WIFI_MCC_UPDATE) ||
7512 1.45 nonaka isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_LAR_MULTI_MCC))
7513 1.45 nonaka mcc_cmd.source_id = IWM_MCC_SOURCE_GET_CURRENT;
7514 1.45 nonaka else
7515 1.45 nonaka mcc_cmd.source_id = IWM_MCC_SOURCE_OLD_FW;
7516 1.45 nonaka
7517 1.91 mlelstv if (resp_v3)
7518 1.45 nonaka hcmd.len[0] = sizeof(struct iwm_mcc_update_cmd);
7519 1.45 nonaka else
7520 1.45 nonaka hcmd.len[0] = sizeof(struct iwm_mcc_update_cmd_v1);
7521 1.45 nonaka
7522 1.45 nonaka err = iwm_send_cmd(sc, &hcmd);
7523 1.45 nonaka if (err)
7524 1.45 nonaka return err;
7525 1.45 nonaka
7526 1.91 mlelstv pkt = hcmd.resp_pkt;
7527 1.91 mlelstv if (!pkt || (pkt->hdr.flags & IWM_CMD_FAILED_MSK)) {
7528 1.91 mlelstv err = EIO;
7529 1.91 mlelstv goto out;
7530 1.91 mlelstv }
7531 1.91 mlelstv
7532 1.91 mlelstv if (resp_v3) {
7533 1.91 mlelstv struct iwm_mcc_update_resp_v3 *resp;
7534 1.91 mlelstv resp_len = iwm_rx_packet_payload_len(pkt);
7535 1.91 mlelstv if (resp_len < sizeof(*resp)) {
7536 1.91 mlelstv err = EIO;
7537 1.91 mlelstv goto out;
7538 1.91 mlelstv }
7539 1.91 mlelstv
7540 1.91 mlelstv resp = (void *)pkt->data;
7541 1.91 mlelstv if (resp_len != sizeof(*resp) +
7542 1.91 mlelstv resp->n_channels * sizeof(resp->channels[0])) {
7543 1.91 mlelstv err = EIO;
7544 1.91 mlelstv goto out;
7545 1.91 mlelstv }
7546 1.91 mlelstv } else {
7547 1.91 mlelstv struct iwm_mcc_update_resp_v1 *resp_v1;
7548 1.91 mlelstv resp_len = iwm_rx_packet_payload_len(pkt);
7549 1.91 mlelstv if (resp_len < sizeof(*resp_v1)) {
7550 1.91 mlelstv err = EIO;
7551 1.91 mlelstv goto out;
7552 1.91 mlelstv }
7553 1.91 mlelstv
7554 1.91 mlelstv resp_v1 = (void *)pkt->data;
7555 1.91 mlelstv if (resp_len != sizeof(*resp_v1) +
7556 1.91 mlelstv resp_v1->n_channels * sizeof(resp_v1->channels[0])) {
7557 1.91 mlelstv err = EIO;
7558 1.91 mlelstv goto out;
7559 1.91 mlelstv }
7560 1.91 mlelstv }
7561 1.91 mlelstv out:
7562 1.45 nonaka iwm_free_resp(sc, &hcmd);
7563 1.91 mlelstv return err;
7564 1.91 mlelstv }
7565 1.91 mlelstv
7566 1.91 mlelstv static int
7567 1.91 mlelstv iwm_send_temp_report_ths_cmd(struct iwm_softc *sc)
7568 1.91 mlelstv {
7569 1.91 mlelstv struct iwm_temp_report_ths_cmd cmd;
7570 1.91 mlelstv int err;
7571 1.91 mlelstv
7572 1.91 mlelstv /*
7573 1.91 mlelstv * In order to give responsibility for critical-temperature-kill
7574 1.91 mlelstv * and TX backoff to FW we need to send an empty temperature
7575 1.91 mlelstv * reporting command at init time.
7576 1.91 mlelstv */
7577 1.91 mlelstv memset(&cmd, 0, sizeof(cmd));
7578 1.45 nonaka
7579 1.91 mlelstv err = iwm_send_cmd_pdu(sc,
7580 1.91 mlelstv IWM_WIDE_ID(IWM_PHY_OPS_GROUP, IWM_TEMP_REPORTING_THRESHOLDS_CMD),
7581 1.91 mlelstv 0, sizeof(cmd), &cmd);
7582 1.91 mlelstv if (err)
7583 1.91 mlelstv printf("%s: TEMP_REPORT_THS_CMD command failed (error %d)\n",
7584 1.91 mlelstv DEVNAME(sc), err);
7585 1.91 mlelstv
7586 1.91 mlelstv return err;
7587 1.45 nonaka }
7588 1.45 nonaka
7589 1.45 nonaka static void
7590 1.45 nonaka iwm_tt_tx_backoff(struct iwm_softc *sc, uint32_t backoff)
7591 1.45 nonaka {
7592 1.45 nonaka struct iwm_host_cmd cmd = {
7593 1.45 nonaka .id = IWM_REPLY_THERMAL_MNG_BACKOFF,
7594 1.45 nonaka .len = { sizeof(uint32_t), },
7595 1.45 nonaka .data = { &backoff, },
7596 1.45 nonaka };
7597 1.45 nonaka
7598 1.45 nonaka iwm_send_cmd(sc, &cmd);
7599 1.1 pooka }
7600 1.1 pooka
7601 1.4 nonaka static int
7602 1.1 pooka iwm_init_hw(struct iwm_softc *sc)
7603 1.1 pooka {
7604 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
7605 1.91 mlelstv int err, i, ac, qid, s;
7606 1.1 pooka
7607 1.45 nonaka err = iwm_run_init_mvm_ucode(sc, 0);
7608 1.45 nonaka if (err)
7609 1.45 nonaka return err;
7610 1.1 pooka
7611 1.45 nonaka /* Should stop and start HW since INIT image just loaded. */
7612 1.1 pooka iwm_stop_device(sc);
7613 1.45 nonaka err = iwm_start_hw(sc);
7614 1.45 nonaka if (err) {
7615 1.3 nonaka aprint_error_dev(sc->sc_dev, "could not initialize hardware\n");
7616 1.45 nonaka return err;
7617 1.2 nonaka }
7618 1.1 pooka
7619 1.45 nonaka /* Restart, this time with the regular firmware */
7620 1.91 mlelstv s = splnet();
7621 1.45 nonaka err = iwm_load_ucode_wait_alive(sc, IWM_UCODE_TYPE_REGULAR);
7622 1.45 nonaka if (err) {
7623 1.61 nonaka aprint_error_dev(sc->sc_dev,
7624 1.61 nonaka "could not load firmware (error %d)\n", err);
7625 1.91 mlelstv splx(s);
7626 1.91 mlelstv return err;
7627 1.45 nonaka }
7628 1.45 nonaka
7629 1.91 mlelstv if (!iwm_nic_lock(sc)) {
7630 1.91 mlelstv splx(s);
7631 1.91 mlelstv return EBUSY;
7632 1.1 pooka }
7633 1.1 pooka
7634 1.45 nonaka err = iwm_send_tx_ant_cfg(sc, iwm_fw_valid_tx_ant(sc));
7635 1.45 nonaka if (err) {
7636 1.45 nonaka aprint_error_dev(sc->sc_dev,
7637 1.45 nonaka "could not init tx ant config (error %d)\n", err);
7638 1.45 nonaka goto err;
7639 1.45 nonaka }
7640 1.1 pooka
7641 1.8 nonaka /* Send phy db control command and then phy db calibration*/
7642 1.45 nonaka err = iwm_send_phy_db_data(sc);
7643 1.45 nonaka if (err) {
7644 1.45 nonaka aprint_error_dev(sc->sc_dev,
7645 1.45 nonaka "could not init phy db (error %d)\n", err);
7646 1.45 nonaka goto err;
7647 1.45 nonaka }
7648 1.1 pooka
7649 1.45 nonaka err = iwm_send_phy_cfg_cmd(sc);
7650 1.45 nonaka if (err) {
7651 1.45 nonaka aprint_error_dev(sc->sc_dev,
7652 1.45 nonaka "could not send phy config (error %d)\n", err);
7653 1.45 nonaka goto err;
7654 1.45 nonaka }
7655 1.1 pooka
7656 1.91 mlelstv err = iwm_send_bt_init_conf(sc);
7657 1.91 mlelstv if (err) {
7658 1.91 mlelstv aprint_error_dev(sc->sc_dev,
7659 1.91 mlelstv "could not init bt coex (error %d)\n", err);
7660 1.91 mlelstv goto err;
7661 1.91 mlelstv }
7662 1.91 mlelstv
7663 1.91 mlelstv if (isset(sc->sc_enabled_capa,
7664 1.91 mlelstv IWM_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT)) {
7665 1.91 mlelstv err = iwm_send_soc_conf(sc);
7666 1.91 mlelstv if (err)
7667 1.91 mlelstv goto err;
7668 1.91 mlelstv }
7669 1.91 mlelstv
7670 1.91 mlelstv if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT)) {
7671 1.91 mlelstv err = iwm_send_dqa_cmd(sc);
7672 1.91 mlelstv if (err)
7673 1.91 mlelstv goto err;
7674 1.91 mlelstv }
7675 1.91 mlelstv
7676 1.1 pooka /* Add auxiliary station for scanning */
7677 1.45 nonaka err = iwm_add_aux_sta(sc);
7678 1.45 nonaka if (err) {
7679 1.45 nonaka aprint_error_dev(sc->sc_dev,
7680 1.45 nonaka "could not add aux station (error %d)\n", err);
7681 1.45 nonaka goto err;
7682 1.45 nonaka }
7683 1.1 pooka
7684 1.1 pooka for (i = 0; i < IWM_NUM_PHY_CTX; i++) {
7685 1.1 pooka /*
7686 1.1 pooka * The channel used here isn't relevant as it's
7687 1.1 pooka * going to be overwritten in the other flows.
7688 1.1 pooka * For now use the first channel we have.
7689 1.1 pooka */
7690 1.45 nonaka sc->sc_phyctxt[i].channel = &ic->ic_channels[1];
7691 1.45 nonaka err = iwm_phy_ctxt_cmd(sc, &sc->sc_phyctxt[i], 1, 1,
7692 1.45 nonaka IWM_FW_CTXT_ACTION_ADD, 0);
7693 1.45 nonaka if (err) {
7694 1.45 nonaka aprint_error_dev(sc->sc_dev,
7695 1.91 mlelstv "could not add phy context %d (error %d)\n",
7696 1.91 mlelstv i, err);
7697 1.91 mlelstv goto err;
7698 1.91 mlelstv }
7699 1.91 mlelstv }
7700 1.91 mlelstv
7701 1.91 mlelstv /* Initialize tx backoffs to the minimum. */
7702 1.91 mlelstv if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000)
7703 1.91 mlelstv iwm_tt_tx_backoff(sc, 0);
7704 1.91 mlelstv
7705 1.91 mlelstv #ifdef notyet
7706 1.91 mlelstv err = iwm_config_ltr(sc);
7707 1.91 mlelstv if (err) {
7708 1.91 mlelstv aprint_error_dev(sc->sc_dev,
7709 1.91 mlelstv "PCIe LTR confguration failed (error %d)\n", err);
7710 1.91 mlelstv }
7711 1.91 mlelstv #endif
7712 1.91 mlelstv
7713 1.91 mlelstv if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_CT_KILL_BY_FW)) {
7714 1.91 mlelstv err = iwm_send_temp_report_ths_cmd(sc);
7715 1.91 mlelstv if (err)
7716 1.45 nonaka goto err;
7717 1.45 nonaka }
7718 1.45 nonaka
7719 1.45 nonaka err = iwm_power_update_device(sc);
7720 1.45 nonaka if (err) {
7721 1.45 nonaka aprint_error_dev(sc->sc_dev,
7722 1.45 nonaka "could send power command (error %d)\n", err);
7723 1.45 nonaka goto err;
7724 1.45 nonaka }
7725 1.45 nonaka
7726 1.91 mlelstv if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_LAR_SUPPORT)) {
7727 1.91 mlelstv err = iwm_send_update_mcc_cmd(sc, iwm_default_mcc);
7728 1.91 mlelstv if (err) {
7729 1.91 mlelstv aprint_error_dev(sc->sc_dev,
7730 1.91 mlelstv "could not init LAR (error %d)\n", err);
7731 1.91 mlelstv goto err;
7732 1.91 mlelstv }
7733 1.45 nonaka }
7734 1.45 nonaka
7735 1.45 nonaka if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) {
7736 1.45 nonaka err = iwm_config_umac_scan(sc);
7737 1.45 nonaka if (err) {
7738 1.45 nonaka aprint_error_dev(sc->sc_dev,
7739 1.45 nonaka "could not configure scan (error %d)\n", err);
7740 1.45 nonaka goto err;
7741 1.45 nonaka }
7742 1.45 nonaka }
7743 1.45 nonaka
7744 1.91 mlelstv if (ic->ic_opmode == IEEE80211_M_MONITOR) {
7745 1.91 mlelstv if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))
7746 1.91 mlelstv qid = IWM_DQA_INJECT_MONITOR_QUEUE;
7747 1.91 mlelstv else
7748 1.91 mlelstv qid = IWM_AUX_QUEUE;
7749 1.91 mlelstv err = iwm_enable_txq(sc, IWM_MONITOR_STA_ID, qid,
7750 1.91 mlelstv iwm_ac_to_tx_fifo[WME_AC_BE], 0, IWM_MAX_TID_COUNT, 0);
7751 1.45 nonaka if (err) {
7752 1.45 nonaka aprint_error_dev(sc->sc_dev,
7753 1.91 mlelstv "could not enable monitor inject Tx queue "
7754 1.91 mlelstv "(error %d)\n", err);
7755 1.45 nonaka goto err;
7756 1.45 nonaka }
7757 1.91 mlelstv } else {
7758 1.91 mlelstv for (ac = 0; ac < WME_NUM_AC; ac++) {
7759 1.91 mlelstv if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))
7760 1.91 mlelstv qid = ac + IWM_DQA_MIN_MGMT_QUEUE;
7761 1.91 mlelstv else
7762 1.91 mlelstv qid = ac;
7763 1.91 mlelstv err = iwm_enable_txq(sc, IWM_STATION_ID, qid,
7764 1.91 mlelstv iwm_ac_to_tx_fifo[ac], 0, IWM_TID_NON_QOS, 0);
7765 1.91 mlelstv if (err) {
7766 1.91 mlelstv aprint_error_dev(sc->sc_dev,
7767 1.91 mlelstv "could not enable Tx queue %d (error %d)\n",
7768 1.91 mlelstv ac, err);
7769 1.91 mlelstv goto err;
7770 1.91 mlelstv }
7771 1.91 mlelstv }
7772 1.1 pooka }
7773 1.1 pooka
7774 1.45 nonaka err = iwm_disable_beacon_filter(sc);
7775 1.45 nonaka if (err) {
7776 1.45 nonaka aprint_error_dev(sc->sc_dev,
7777 1.45 nonaka "could not disable beacon filter (error %d)\n", err);
7778 1.45 nonaka goto err;
7779 1.1 pooka }
7780 1.1 pooka
7781 1.45 nonaka err:
7782 1.91 mlelstv iwm_nic_unlock(sc);
7783 1.91 mlelstv splx(s);
7784 1.45 nonaka return err;
7785 1.1 pooka }
7786 1.1 pooka
7787 1.11 nonaka /* Allow multicast from our BSSID. */
7788 1.11 nonaka static int
7789 1.11 nonaka iwm_allow_mcast(struct iwm_softc *sc)
7790 1.11 nonaka {
7791 1.11 nonaka struct ieee80211com *ic = &sc->sc_ic;
7792 1.91 mlelstv struct iwm_node *in = (struct iwm_node *)ic->ic_bss;
7793 1.11 nonaka struct iwm_mcast_filter_cmd *cmd;
7794 1.11 nonaka size_t size;
7795 1.45 nonaka int err;
7796 1.11 nonaka
7797 1.11 nonaka size = roundup(sizeof(*cmd), 4);
7798 1.11 nonaka cmd = kmem_intr_zalloc(size, KM_NOSLEEP);
7799 1.11 nonaka if (cmd == NULL)
7800 1.11 nonaka return ENOMEM;
7801 1.11 nonaka cmd->filter_own = 1;
7802 1.11 nonaka cmd->port_id = 0;
7803 1.11 nonaka cmd->count = 0;
7804 1.11 nonaka cmd->pass_all = 1;
7805 1.91 mlelstv IEEE80211_ADDR_COPY(cmd->bssid, in->in_macaddr);
7806 1.11 nonaka
7807 1.91 mlelstv err = iwm_send_cmd_pdu(sc, IWM_MCAST_FILTER_CMD,
7808 1.91 mlelstv 0, size, cmd);
7809 1.11 nonaka kmem_intr_free(cmd, size);
7810 1.45 nonaka return err;
7811 1.11 nonaka }
7812 1.11 nonaka
7813 1.4 nonaka static int
7814 1.1 pooka iwm_init(struct ifnet *ifp)
7815 1.1 pooka {
7816 1.1 pooka struct iwm_softc *sc = ifp->if_softc;
7817 1.91 mlelstv struct ieee80211com *ic = &sc->sc_ic;
7818 1.91 mlelstv int err, generation;
7819 1.91 mlelstv
7820 1.91 mlelstv generation = ++sc->sc_generation;
7821 1.91 mlelstv
7822 1.91 mlelstv err = iwm_preinit(sc, false);
7823 1.91 mlelstv if (err)
7824 1.91 mlelstv return err;
7825 1.1 pooka
7826 1.91 mlelstv err = iwm_start_hw(sc);
7827 1.91 mlelstv if (err) {
7828 1.91 mlelstv device_printf(sc->sc_dev, "could not initialize hardware\n");
7829 1.91 mlelstv return err;
7830 1.91 mlelstv }
7831 1.45 nonaka
7832 1.91 mlelstv CLR(sc->sc_flags, IWM_FLAG_STOPPED);
7833 1.1 pooka
7834 1.45 nonaka err = iwm_init_hw(sc);
7835 1.45 nonaka if (err) {
7836 1.91 mlelstv if (generation == sc->sc_generation)
7837 1.91 mlelstv iwm_stop_device(sc);
7838 1.45 nonaka return err;
7839 1.1 pooka }
7840 1.1 pooka
7841 1.1 pooka ifp->if_flags &= ~IFF_OACTIVE;
7842 1.1 pooka ifp->if_flags |= IFF_RUNNING;
7843 1.1 pooka
7844 1.91 mlelstv if (ic->ic_opmode == IEEE80211_M_MONITOR) {
7845 1.91 mlelstv ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
7846 1.91 mlelstv return 0;
7847 1.91 mlelstv }
7848 1.91 mlelstv
7849 1.1 pooka ieee80211_begin_scan(&sc->sc_ic, 0);
7850 1.1 pooka
7851 1.1 pooka return 0;
7852 1.1 pooka }
7853 1.1 pooka
7854 1.4 nonaka static void
7855 1.1 pooka iwm_start(struct ifnet *ifp)
7856 1.1 pooka {
7857 1.1 pooka struct iwm_softc *sc = ifp->if_softc;
7858 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
7859 1.1 pooka struct ieee80211_node *ni;
7860 1.8 nonaka struct ether_header *eh;
7861 1.1 pooka struct mbuf *m;
7862 1.1 pooka int ac;
7863 1.1 pooka
7864 1.1 pooka if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
7865 1.1 pooka return;
7866 1.1 pooka
7867 1.1 pooka for (;;) {
7868 1.1 pooka /* why isn't this done per-queue? */
7869 1.1 pooka if (sc->qfullmsk != 0) {
7870 1.1 pooka ifp->if_flags |= IFF_OACTIVE;
7871 1.1 pooka break;
7872 1.1 pooka }
7873 1.1 pooka
7874 1.1 pooka /* need to send management frames even if we're not RUNning */
7875 1.1 pooka IF_DEQUEUE(&ic->ic_mgtq, m);
7876 1.1 pooka if (m) {
7877 1.41 ozaki ni = M_GETCTX(m, struct ieee80211_node *);
7878 1.50 nonaka M_CLEARCTX(m);
7879 1.45 nonaka ac = WME_AC_BE;
7880 1.1 pooka goto sendit;
7881 1.1 pooka }
7882 1.1 pooka if (ic->ic_state != IEEE80211_S_RUN) {
7883 1.1 pooka break;
7884 1.1 pooka }
7885 1.1 pooka
7886 1.1 pooka IFQ_DEQUEUE(&ifp->if_snd, m);
7887 1.50 nonaka if (m == NULL)
7888 1.1 pooka break;
7889 1.50 nonaka
7890 1.8 nonaka if (m->m_len < sizeof (*eh) &&
7891 1.8 nonaka (m = m_pullup(m, sizeof (*eh))) == NULL) {
7892 1.84 thorpej if_statinc(ifp, if_oerrors);
7893 1.8 nonaka continue;
7894 1.8 nonaka }
7895 1.1 pooka
7896 1.1 pooka eh = mtod(m, struct ether_header *);
7897 1.1 pooka ni = ieee80211_find_txnode(ic, eh->ether_dhost);
7898 1.1 pooka if (ni == NULL) {
7899 1.1 pooka m_freem(m);
7900 1.84 thorpej if_statinc(ifp, if_oerrors);
7901 1.1 pooka continue;
7902 1.1 pooka }
7903 1.50 nonaka
7904 1.1 pooka /* classify mbuf so we can find which tx ring to use */
7905 1.1 pooka if (ieee80211_classify(ic, m, ni) != 0) {
7906 1.1 pooka m_freem(m);
7907 1.1 pooka ieee80211_free_node(ni);
7908 1.84 thorpej if_statinc(ifp, if_oerrors);
7909 1.1 pooka continue;
7910 1.1 pooka }
7911 1.1 pooka
7912 1.1 pooka /* No QoS encapsulation for EAPOL frames. */
7913 1.1 pooka ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ?
7914 1.1 pooka M_WME_GETAC(m) : WME_AC_BE;
7915 1.1 pooka
7916 1.83 msaitoh bpf_mtap(ifp, m, BPF_D_OUT);
7917 1.48 nonaka
7918 1.1 pooka if ((m = ieee80211_encap(ic, m, ni)) == NULL) {
7919 1.1 pooka ieee80211_free_node(ni);
7920 1.84 thorpej if_statinc(ifp, if_oerrors);
7921 1.1 pooka continue;
7922 1.1 pooka }
7923 1.1 pooka
7924 1.1 pooka sendit:
7925 1.83 msaitoh bpf_mtap3(ic->ic_rawbpf, m, BPF_D_OUT);
7926 1.48 nonaka
7927 1.1 pooka if (iwm_tx(sc, m, ni, ac) != 0) {
7928 1.1 pooka ieee80211_free_node(ni);
7929 1.84 thorpej if_statinc(ifp, if_oerrors);
7930 1.1 pooka continue;
7931 1.1 pooka }
7932 1.1 pooka
7933 1.1 pooka if (ifp->if_flags & IFF_UP) {
7934 1.1 pooka sc->sc_tx_timer = 15;
7935 1.1 pooka ifp->if_timer = 1;
7936 1.1 pooka }
7937 1.1 pooka }
7938 1.1 pooka }
7939 1.1 pooka
7940 1.4 nonaka static void
7941 1.1 pooka iwm_stop(struct ifnet *ifp, int disable)
7942 1.1 pooka {
7943 1.1 pooka struct iwm_softc *sc = ifp->if_softc;
7944 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
7945 1.45 nonaka struct iwm_node *in = (struct iwm_node *)ic->ic_bss;
7946 1.91 mlelstv int i, s;
7947 1.91 mlelstv
7948 1.91 mlelstv s = splnet();
7949 1.1 pooka
7950 1.1 pooka sc->sc_flags &= ~IWM_FLAG_HW_INITED;
7951 1.1 pooka sc->sc_flags |= IWM_FLAG_STOPPED;
7952 1.91 mlelstv
7953 1.91 mlelstv iwm_stop_device(sc);
7954 1.91 mlelstv
7955 1.1 pooka sc->sc_generation++;
7956 1.91 mlelstv for (i = 0; i < __arraycount(sc->sc_cmd_resp_pkt); i++) {
7957 1.91 mlelstv if (sc->sc_cmd_resp_pkt[i] != NULL) {
7958 1.91 mlelstv KASSERT(sc->sc_cmd_resp_len[i] > 0);
7959 1.91 mlelstv kmem_free(sc->sc_cmd_resp_pkt[i],
7960 1.91 mlelstv sc->sc_cmd_resp_len[i]);
7961 1.91 mlelstv }
7962 1.91 mlelstv sc->sc_cmd_resp_pkt[i] = NULL;
7963 1.91 mlelstv sc->sc_cmd_resp_len[i] = 0;
7964 1.91 mlelstv }
7965 1.91 mlelstv
7966 1.1 pooka ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
7967 1.1 pooka
7968 1.91 mlelstv if (in) {
7969 1.45 nonaka in->in_phyctxt = NULL;
7970 1.91 mlelstv in->tid_disable_ampdu = 0xffff;
7971 1.91 mlelstv in->tfd_queue_msk = 0;
7972 1.91 mlelstv IEEE80211_ADDR_COPY(in->in_macaddr, etheranyaddr);
7973 1.91 mlelstv }
7974 1.91 mlelstv
7975 1.91 mlelstv sc->sc_flags &= ~(IWM_FLAG_SCANNING | IWM_FLAG_BGSCAN);
7976 1.91 mlelstv sc->sc_flags &= ~IWM_FLAG_MAC_ACTIVE;
7977 1.91 mlelstv sc->sc_flags &= ~IWM_FLAG_BINDING_ACTIVE;
7978 1.91 mlelstv sc->sc_flags &= ~IWM_FLAG_STA_ACTIVE;
7979 1.91 mlelstv sc->sc_flags &= ~IWM_FLAG_TE_ACTIVE;
7980 1.91 mlelstv #ifdef notyet
7981 1.91 mlelstv sc->sc_flags &= ~IWM_FLAG_HW_ERR;
7982 1.91 mlelstv sc->sc_flags &= ~IWM_FLAG_SHUTDOWN;
7983 1.91 mlelstv #endif
7984 1.91 mlelstv sc->sc_flags &= ~IWM_FLAG_TXFLUSH;
7985 1.45 nonaka
7986 1.1 pooka if (ic->ic_state != IEEE80211_S_INIT)
7987 1.1 pooka ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
7988 1.1 pooka
7989 1.45 nonaka iwm_led_blink_stop(sc);
7990 1.1 pooka ifp->if_timer = sc->sc_tx_timer = 0;
7991 1.91 mlelstv splx(s);
7992 1.1 pooka }
7993 1.1 pooka
7994 1.4 nonaka static void
7995 1.1 pooka iwm_watchdog(struct ifnet *ifp)
7996 1.1 pooka {
7997 1.1 pooka struct iwm_softc *sc = ifp->if_softc;
7998 1.1 pooka
7999 1.1 pooka ifp->if_timer = 0;
8000 1.1 pooka if (sc->sc_tx_timer > 0) {
8001 1.1 pooka if (--sc->sc_tx_timer == 0) {
8002 1.5 nonaka aprint_error_dev(sc->sc_dev, "device timeout\n");
8003 1.2 nonaka #ifdef IWM_DEBUG
8004 1.1 pooka iwm_nic_error(sc);
8005 1.91 mlelstv iwm_dump_driver_status(sc);
8006 1.2 nonaka #endif
8007 1.1 pooka ifp->if_flags &= ~IFF_UP;
8008 1.1 pooka iwm_stop(ifp, 1);
8009 1.84 thorpej if_statinc(ifp, if_oerrors);
8010 1.1 pooka return;
8011 1.1 pooka }
8012 1.1 pooka ifp->if_timer = 1;
8013 1.1 pooka }
8014 1.1 pooka
8015 1.1 pooka ieee80211_watchdog(&sc->sc_ic);
8016 1.1 pooka }
8017 1.1 pooka
8018 1.4 nonaka static int
8019 1.1 pooka iwm_ioctl(struct ifnet *ifp, u_long cmd, void *data)
8020 1.1 pooka {
8021 1.1 pooka struct iwm_softc *sc = ifp->if_softc;
8022 1.1 pooka struct ieee80211com *ic = &sc->sc_ic;
8023 1.1 pooka const struct sockaddr *sa;
8024 1.45 nonaka int s, err = 0;
8025 1.1 pooka
8026 1.1 pooka s = splnet();
8027 1.1 pooka
8028 1.1 pooka switch (cmd) {
8029 1.1 pooka case SIOCSIFADDR:
8030 1.1 pooka ifp->if_flags |= IFF_UP;
8031 1.1 pooka /* FALLTHROUGH */
8032 1.1 pooka case SIOCSIFFLAGS:
8033 1.45 nonaka err = ifioctl_common(ifp, cmd, data);
8034 1.45 nonaka if (err)
8035 1.1 pooka break;
8036 1.1 pooka if (ifp->if_flags & IFF_UP) {
8037 1.1 pooka if (!(ifp->if_flags & IFF_RUNNING)) {
8038 1.91 mlelstv /* Force reload of firmware image from disk. */
8039 1.91 mlelstv sc->sc_fw.fw_status = IWM_FW_STATUS_NONE;
8040 1.45 nonaka err = iwm_init(ifp);
8041 1.1 pooka }
8042 1.1 pooka } else {
8043 1.91 mlelstv if (ifp->if_flags & IFF_RUNNING) {
8044 1.1 pooka iwm_stop(ifp, 1);
8045 1.91 mlelstv }
8046 1.1 pooka }
8047 1.1 pooka break;
8048 1.1 pooka
8049 1.1 pooka case SIOCADDMULTI:
8050 1.1 pooka case SIOCDELMULTI:
8051 1.1 pooka sa = ifreq_getaddr(SIOCADDMULTI, (struct ifreq *)data);
8052 1.45 nonaka err = (cmd == SIOCADDMULTI) ?
8053 1.1 pooka ether_addmulti(sa, &sc->sc_ec) :
8054 1.1 pooka ether_delmulti(sa, &sc->sc_ec);
8055 1.45 nonaka if (err == ENETRESET)
8056 1.45 nonaka err = 0;
8057 1.1 pooka break;
8058 1.1 pooka
8059 1.1 pooka default:
8060 1.45 nonaka err = ieee80211_ioctl(ic, cmd, data);
8061 1.36 nonaka break;
8062 1.1 pooka }
8063 1.1 pooka
8064 1.45 nonaka if (err == ENETRESET) {
8065 1.45 nonaka err = 0;
8066 1.1 pooka if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
8067 1.1 pooka (IFF_UP | IFF_RUNNING)) {
8068 1.1 pooka iwm_stop(ifp, 0);
8069 1.45 nonaka err = iwm_init(ifp);
8070 1.1 pooka }
8071 1.1 pooka }
8072 1.1 pooka
8073 1.1 pooka splx(s);
8074 1.45 nonaka return err;
8075 1.1 pooka }
8076 1.1 pooka
8077 1.1 pooka /*
8078 1.1 pooka * Note: This structure is read from the device with IO accesses,
8079 1.1 pooka * and the reading already does the endian conversion. As it is
8080 1.1 pooka * read with uint32_t-sized accesses, any members with a different size
8081 1.1 pooka * need to be ordered correctly though!
8082 1.1 pooka */
8083 1.1 pooka struct iwm_error_event_table {
8084 1.1 pooka uint32_t valid; /* (nonzero) valid, (0) log is empty */
8085 1.1 pooka uint32_t error_id; /* type of error */
8086 1.45 nonaka uint32_t trm_hw_status0; /* TRM HW status */
8087 1.45 nonaka uint32_t trm_hw_status1; /* TRM HW status */
8088 1.1 pooka uint32_t blink2; /* branch link */
8089 1.1 pooka uint32_t ilink1; /* interrupt link */
8090 1.1 pooka uint32_t ilink2; /* interrupt link */
8091 1.1 pooka uint32_t data1; /* error-specific data */
8092 1.1 pooka uint32_t data2; /* error-specific data */
8093 1.1 pooka uint32_t data3; /* error-specific data */
8094 1.1 pooka uint32_t bcon_time; /* beacon timer */
8095 1.1 pooka uint32_t tsf_low; /* network timestamp function timer */
8096 1.1 pooka uint32_t tsf_hi; /* network timestamp function timer */
8097 1.1 pooka uint32_t gp1; /* GP1 timer register */
8098 1.1 pooka uint32_t gp2; /* GP2 timer register */
8099 1.45 nonaka uint32_t fw_rev_type; /* firmware revision type */
8100 1.45 nonaka uint32_t major; /* uCode version major */
8101 1.45 nonaka uint32_t minor; /* uCode version minor */
8102 1.1 pooka uint32_t hw_ver; /* HW Silicon version */
8103 1.1 pooka uint32_t brd_ver; /* HW board version */
8104 1.1 pooka uint32_t log_pc; /* log program counter */
8105 1.1 pooka uint32_t frame_ptr; /* frame pointer */
8106 1.1 pooka uint32_t stack_ptr; /* stack pointer */
8107 1.1 pooka uint32_t hcmd; /* last host command header */
8108 1.1 pooka uint32_t isr0; /* isr status register LMPM_NIC_ISR0:
8109 1.1 pooka * rxtx_flag */
8110 1.1 pooka uint32_t isr1; /* isr status register LMPM_NIC_ISR1:
8111 1.1 pooka * host_flag */
8112 1.1 pooka uint32_t isr2; /* isr status register LMPM_NIC_ISR2:
8113 1.1 pooka * enc_flag */
8114 1.1 pooka uint32_t isr3; /* isr status register LMPM_NIC_ISR3:
8115 1.1 pooka * time_flag */
8116 1.1 pooka uint32_t isr4; /* isr status register LMPM_NIC_ISR4:
8117 1.1 pooka * wico interrupt */
8118 1.45 nonaka uint32_t last_cmd_id; /* last HCMD id handled by the firmware */
8119 1.1 pooka uint32_t wait_event; /* wait event() caller address */
8120 1.1 pooka uint32_t l2p_control; /* L2pControlField */
8121 1.1 pooka uint32_t l2p_duration; /* L2pDurationField */
8122 1.1 pooka uint32_t l2p_mhvalid; /* L2pMhValidBits */
8123 1.1 pooka uint32_t l2p_addr_match; /* L2pAddrMatchStat */
8124 1.1 pooka uint32_t lmpm_pmg_sel; /* indicate which clocks are turned on
8125 1.1 pooka * (LMPM_PMG_SEL) */
8126 1.1 pooka uint32_t u_timestamp; /* indicate when the date and time of the
8127 1.1 pooka * compilation */
8128 1.1 pooka uint32_t flow_handler; /* FH read/write pointers, RX credit */
8129 1.45 nonaka } __packed /* LOG_ERROR_TABLE_API_S_VER_3 */;
8130 1.45 nonaka
8131 1.45 nonaka /*
8132 1.45 nonaka * UMAC error struct - relevant starting from family 8000 chip.
8133 1.45 nonaka * Note: This structure is read from the device with IO accesses,
8134 1.45 nonaka * and the reading already does the endian conversion. As it is
8135 1.45 nonaka * read with u32-sized accesses, any members with a different size
8136 1.45 nonaka * need to be ordered correctly though!
8137 1.45 nonaka */
8138 1.45 nonaka struct iwm_umac_error_event_table {
8139 1.45 nonaka uint32_t valid; /* (nonzero) valid, (0) log is empty */
8140 1.45 nonaka uint32_t error_id; /* type of error */
8141 1.45 nonaka uint32_t blink1; /* branch link */
8142 1.45 nonaka uint32_t blink2; /* branch link */
8143 1.45 nonaka uint32_t ilink1; /* interrupt link */
8144 1.45 nonaka uint32_t ilink2; /* interrupt link */
8145 1.45 nonaka uint32_t data1; /* error-specific data */
8146 1.45 nonaka uint32_t data2; /* error-specific data */
8147 1.45 nonaka uint32_t data3; /* error-specific data */
8148 1.45 nonaka uint32_t umac_major;
8149 1.45 nonaka uint32_t umac_minor;
8150 1.45 nonaka uint32_t frame_pointer; /* core register 27 */
8151 1.45 nonaka uint32_t stack_pointer; /* core register 28 */
8152 1.45 nonaka uint32_t cmd_header; /* latest host cmd sent to UMAC */
8153 1.45 nonaka uint32_t nic_isr_pref; /* ISR status register */
8154 1.1 pooka } __packed;
8155 1.1 pooka
8156 1.1 pooka #define ERROR_START_OFFSET (1 * sizeof(uint32_t))
8157 1.1 pooka #define ERROR_ELEM_SIZE (7 * sizeof(uint32_t))
8158 1.1 pooka
8159 1.91 mlelstv #define IWM_FW_SYSASSERT_CPU_MASK 0xf0000000
8160 1.4 nonaka static const struct {
8161 1.1 pooka const char *name;
8162 1.1 pooka uint8_t num;
8163 1.1 pooka } advanced_lookup[] = {
8164 1.1 pooka { "NMI_INTERRUPT_WDG", 0x34 },
8165 1.1 pooka { "SYSASSERT", 0x35 },
8166 1.1 pooka { "UCODE_VERSION_MISMATCH", 0x37 },
8167 1.1 pooka { "BAD_COMMAND", 0x38 },
8168 1.91 mlelstv { "BAD_COMMAND", 0x39 },
8169 1.1 pooka { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
8170 1.1 pooka { "FATAL_ERROR", 0x3D },
8171 1.1 pooka { "NMI_TRM_HW_ERR", 0x46 },
8172 1.1 pooka { "NMI_INTERRUPT_TRM", 0x4C },
8173 1.1 pooka { "NMI_INTERRUPT_BREAK_POINT", 0x54 },
8174 1.1 pooka { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C },
8175 1.1 pooka { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 },
8176 1.1 pooka { "NMI_INTERRUPT_HOST", 0x66 },
8177 1.91 mlelstv { "NMI_INTERRUPT_LMAC_FATAL", 0x70 },
8178 1.91 mlelstv { "NMI_INTERRUPT_UMAC_FATAL", 0x71 },
8179 1.91 mlelstv { "NMI_INTERRUPT_OTHER_LMAC_FATAL", 0x73 },
8180 1.1 pooka { "NMI_INTERRUPT_ACTION_PT", 0x7C },
8181 1.1 pooka { "NMI_INTERRUPT_UNKNOWN", 0x84 },
8182 1.1 pooka { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 },
8183 1.1 pooka { "ADVANCED_SYSASSERT", 0 },
8184 1.1 pooka };
8185 1.1 pooka
8186 1.4 nonaka static const char *
8187 1.1 pooka iwm_desc_lookup(uint32_t num)
8188 1.1 pooka {
8189 1.1 pooka int i;
8190 1.1 pooka
8191 1.1 pooka for (i = 0; i < __arraycount(advanced_lookup) - 1; i++)
8192 1.91 mlelstv if (advanced_lookup[i].num ==
8193 1.91 mlelstv (num & ~IWM_FW_SYSASSERT_CPU_MASK))
8194 1.1 pooka return advanced_lookup[i].name;
8195 1.1 pooka
8196 1.1 pooka /* No entry matches 'num', so it is the last: ADVANCED_SYSASSERT */
8197 1.1 pooka return advanced_lookup[i].name;
8198 1.1 pooka }
8199 1.1 pooka
8200 1.1 pooka /*
8201 1.1 pooka * Support for dumping the error log seemed like a good idea ...
8202 1.1 pooka * but it's mostly hex junk and the only sensible thing is the
8203 1.1 pooka * hw/ucode revision (which we know anyway). Since it's here,
8204 1.1 pooka * I'll just leave it in, just in case e.g. the Intel guys want to
8205 1.1 pooka * help us decipher some "ADVANCED_SYSASSERT" later.
8206 1.1 pooka */
8207 1.4 nonaka static void
8208 1.1 pooka iwm_nic_error(struct iwm_softc *sc)
8209 1.1 pooka {
8210 1.45 nonaka struct iwm_error_event_table t;
8211 1.1 pooka uint32_t base;
8212 1.1 pooka
8213 1.91 mlelstv device_printf(sc->sc_dev, "dumping device error log\n");
8214 1.1 pooka base = sc->sc_uc.uc_error_event_table;
8215 1.45 nonaka if (base < 0x800000) {
8216 1.91 mlelstv device_printf(sc->sc_dev,
8217 1.45 nonaka "Invalid error log pointer 0x%08x\n", base);
8218 1.1 pooka return;
8219 1.1 pooka }
8220 1.1 pooka
8221 1.45 nonaka if (iwm_read_mem(sc, base, &t, sizeof(t)/sizeof(uint32_t))) {
8222 1.91 mlelstv device_printf(sc->sc_dev, "reading errlog failed\n");
8223 1.1 pooka return;
8224 1.1 pooka }
8225 1.1 pooka
8226 1.45 nonaka if (!t.valid) {
8227 1.91 mlelstv device_printf(sc->sc_dev, "errlog not found, skipping\n");
8228 1.1 pooka return;
8229 1.1 pooka }
8230 1.1 pooka
8231 1.45 nonaka if (ERROR_START_OFFSET <= t.valid * ERROR_ELEM_SIZE) {
8232 1.91 mlelstv device_printf(sc->sc_dev, "Start Error Log Dump:\n");
8233 1.91 mlelstv device_printf(sc->sc_dev, "Status: 0x%x, count: %d\n",
8234 1.45 nonaka sc->sc_flags, t.valid);
8235 1.1 pooka }
8236 1.1 pooka
8237 1.91 mlelstv device_printf(sc->sc_dev, "%08X | %-28s\n", t.error_id,
8238 1.45 nonaka iwm_desc_lookup(t.error_id));
8239 1.91 mlelstv device_printf(sc->sc_dev, "%08X | trm_hw_status0\n",
8240 1.45 nonaka t.trm_hw_status0);
8241 1.91 mlelstv device_printf(sc->sc_dev, "%08X | trm_hw_status1\n",
8242 1.45 nonaka t.trm_hw_status1);
8243 1.91 mlelstv device_printf(sc->sc_dev, "%08X | branchlink2\n", t.blink2);
8244 1.91 mlelstv device_printf(sc->sc_dev, "%08X | interruptlink1\n", t.ilink1);
8245 1.91 mlelstv device_printf(sc->sc_dev, "%08X | interruptlink2\n", t.ilink2);
8246 1.91 mlelstv device_printf(sc->sc_dev, "%08X | data1\n", t.data1);
8247 1.91 mlelstv device_printf(sc->sc_dev, "%08X | data2\n", t.data2);
8248 1.91 mlelstv device_printf(sc->sc_dev, "%08X | data3\n", t.data3);
8249 1.91 mlelstv device_printf(sc->sc_dev, "%08X | beacon time\n", t.bcon_time);
8250 1.91 mlelstv device_printf(sc->sc_dev, "%08X | tsf low\n", t.tsf_low);
8251 1.91 mlelstv device_printf(sc->sc_dev, "%08X | tsf hi\n", t.tsf_hi);
8252 1.91 mlelstv device_printf(sc->sc_dev, "%08X | time gp1\n", t.gp1);
8253 1.91 mlelstv device_printf(sc->sc_dev, "%08X | time gp2\n", t.gp2);
8254 1.91 mlelstv device_printf(sc->sc_dev, "%08X | uCode revision type\n",
8255 1.45 nonaka t.fw_rev_type);
8256 1.91 mlelstv device_printf(sc->sc_dev, "%08X | uCode version major\n",
8257 1.45 nonaka t.major);
8258 1.91 mlelstv device_printf(sc->sc_dev, "%08X | uCode version minor\n",
8259 1.45 nonaka t.minor);
8260 1.91 mlelstv device_printf(sc->sc_dev, "%08X | hw version\n", t.hw_ver);
8261 1.91 mlelstv device_printf(sc->sc_dev, "%08X | board version\n", t.brd_ver);
8262 1.91 mlelstv device_printf(sc->sc_dev, "%08X | hcmd\n", t.hcmd);
8263 1.91 mlelstv device_printf(sc->sc_dev, "%08X | isr0\n", t.isr0);
8264 1.91 mlelstv device_printf(sc->sc_dev, "%08X | isr1\n", t.isr1);
8265 1.91 mlelstv device_printf(sc->sc_dev, "%08X | isr2\n", t.isr2);
8266 1.91 mlelstv device_printf(sc->sc_dev, "%08X | isr3\n", t.isr3);
8267 1.91 mlelstv device_printf(sc->sc_dev, "%08X | isr4\n", t.isr4);
8268 1.91 mlelstv device_printf(sc->sc_dev, "%08X | last cmd Id\n", t.last_cmd_id);
8269 1.91 mlelstv device_printf(sc->sc_dev, "%08X | wait_event\n", t.wait_event);
8270 1.91 mlelstv device_printf(sc->sc_dev, "%08X | l2p_control\n", t.l2p_control);
8271 1.91 mlelstv device_printf(sc->sc_dev, "%08X | l2p_duration\n", t.l2p_duration);
8272 1.91 mlelstv device_printf(sc->sc_dev, "%08X | l2p_mhvalid\n", t.l2p_mhvalid);
8273 1.91 mlelstv device_printf(sc->sc_dev, "%08X | l2p_addr_match\n",
8274 1.45 nonaka t.l2p_addr_match);
8275 1.91 mlelstv device_printf(sc->sc_dev, "%08X | lmpm_pmg_sel\n", t.lmpm_pmg_sel);
8276 1.91 mlelstv device_printf(sc->sc_dev, "%08X | timestamp\n", t.u_timestamp);
8277 1.91 mlelstv device_printf(sc->sc_dev, "%08X | flow_handler\n", t.flow_handler);
8278 1.45 nonaka
8279 1.45 nonaka if (sc->sc_uc.uc_umac_error_event_table)
8280 1.45 nonaka iwm_nic_umac_error(sc);
8281 1.45 nonaka }
8282 1.45 nonaka
8283 1.45 nonaka static void
8284 1.45 nonaka iwm_nic_umac_error(struct iwm_softc *sc)
8285 1.45 nonaka {
8286 1.45 nonaka struct iwm_umac_error_event_table t;
8287 1.45 nonaka uint32_t base;
8288 1.45 nonaka
8289 1.45 nonaka base = sc->sc_uc.uc_umac_error_event_table;
8290 1.45 nonaka
8291 1.45 nonaka if (base < 0x800000) {
8292 1.91 mlelstv device_printf(sc->sc_dev,
8293 1.45 nonaka "Invalid error log pointer 0x%08x\n", base);
8294 1.45 nonaka return;
8295 1.45 nonaka }
8296 1.45 nonaka
8297 1.45 nonaka if (iwm_read_mem(sc, base, &t, sizeof(t)/sizeof(uint32_t))) {
8298 1.91 mlelstv device_printf(sc->sc_dev, "reading errlog failed\n");
8299 1.45 nonaka return;
8300 1.45 nonaka }
8301 1.45 nonaka
8302 1.45 nonaka if (ERROR_START_OFFSET <= t.valid * ERROR_ELEM_SIZE) {
8303 1.91 mlelstv device_printf(sc->sc_dev, "Start UMAC Error Log Dump:\n");
8304 1.91 mlelstv device_printf(sc->sc_dev, "Status: 0x%x, count: %d\n",
8305 1.45 nonaka sc->sc_flags, t.valid);
8306 1.45 nonaka }
8307 1.45 nonaka
8308 1.91 mlelstv device_printf(sc->sc_dev, "0x%08X | %s\n", t.error_id,
8309 1.45 nonaka iwm_desc_lookup(t.error_id));
8310 1.91 mlelstv device_printf(sc->sc_dev, "0x%08X | umac branchlink1\n", t.blink1);
8311 1.91 mlelstv device_printf(sc->sc_dev, "0x%08X | umac branchlink2\n", t.blink2);
8312 1.91 mlelstv device_printf(sc->sc_dev, "0x%08X | umac interruptlink1\n",
8313 1.45 nonaka t.ilink1);
8314 1.91 mlelstv device_printf(sc->sc_dev, "0x%08X | umac interruptlink2\n",
8315 1.45 nonaka t.ilink2);
8316 1.91 mlelstv device_printf(sc->sc_dev, "0x%08X | umac data1\n", t.data1);
8317 1.91 mlelstv device_printf(sc->sc_dev, "0x%08X | umac data2\n", t.data2);
8318 1.91 mlelstv device_printf(sc->sc_dev, "0x%08X | umac data3\n", t.data3);
8319 1.91 mlelstv device_printf(sc->sc_dev, "0x%08X | umac major\n", t.umac_major);
8320 1.91 mlelstv device_printf(sc->sc_dev, "0x%08X | umac minor\n", t.umac_minor);
8321 1.91 mlelstv device_printf(sc->sc_dev, "0x%08X | frame pointer\n",
8322 1.45 nonaka t.frame_pointer);
8323 1.91 mlelstv device_printf(sc->sc_dev, "0x%08X | stack pointer\n",
8324 1.45 nonaka t.stack_pointer);
8325 1.91 mlelstv device_printf(sc->sc_dev, "0x%08X | last host cmd\n", t.cmd_header);
8326 1.91 mlelstv device_printf(sc->sc_dev, "0x%08X | isr status reg\n",
8327 1.45 nonaka t.nic_isr_pref);
8328 1.1 pooka }
8329 1.91 mlelstv
8330 1.91 mlelstv static void
8331 1.91 mlelstv iwm_dump_driver_status(struct iwm_softc *sc)
8332 1.91 mlelstv {
8333 1.91 mlelstv int i;
8334 1.91 mlelstv
8335 1.91 mlelstv printf("driver status:\n");
8336 1.91 mlelstv for (i = 0; i < IWM_MAX_QUEUES; i++) {
8337 1.91 mlelstv struct iwm_tx_ring *ring = &sc->txq[i];
8338 1.91 mlelstv printf(" tx ring %2d: qid=%-2d cur=%-3d "
8339 1.91 mlelstv "queued=%-3d\n",
8340 1.91 mlelstv i, ring->qid, ring->cur, ring->queued);
8341 1.91 mlelstv }
8342 1.91 mlelstv printf(" rx ring: cur=%d\n", sc->rxq.cur);
8343 1.91 mlelstv printf(" 802.11 state %s\n",
8344 1.91 mlelstv ieee80211_state_name[sc->sc_ic.ic_state]);
8345 1.91 mlelstv }
8346 1.1 pooka
8347 1.1 pooka #define SYNC_RESP_STRUCT(_var_, _pkt_) \
8348 1.1 pooka do { \
8349 1.1 pooka bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*(_pkt_)), \
8350 1.1 pooka sizeof(*(_var_)), BUS_DMASYNC_POSTREAD); \
8351 1.1 pooka _var_ = (void *)((_pkt_)+1); \
8352 1.1 pooka } while (/*CONSTCOND*/0)
8353 1.1 pooka
8354 1.91 mlelstv #define SYNC_RESP(_len_, _pkt_) \
8355 1.1 pooka do { \
8356 1.1 pooka bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*(_pkt_)), \
8357 1.91 mlelstv (_len_), BUS_DMASYNC_POSTREAD); \
8358 1.1 pooka } while (/*CONSTCOND*/0)
8359 1.1 pooka
8360 1.1 pooka
8361 1.4 nonaka static void
8362 1.91 mlelstv iwm_rx_pkt(struct iwm_softc *sc, struct iwm_rx_data *data)
8363 1.1 pooka {
8364 1.91 mlelstv struct iwm_rx_packet *pkt;
8365 1.91 mlelstv int qid, idx, code;
8366 1.91 mlelstv int handled = 1;
8367 1.1 pooka
8368 1.91 mlelstv bus_dmamap_sync(sc->sc_dmat, data->map, 0, IWM_RBUF_SIZE,
8369 1.91 mlelstv BUS_DMASYNC_POSTREAD);
8370 1.91 mlelstv pkt = mtod(data->m, struct iwm_rx_packet *);
8371 1.1 pooka
8372 1.91 mlelstv qid = pkt->hdr.qid;
8373 1.91 mlelstv idx = pkt->hdr.idx;
8374 1.91 mlelstv code = IWM_WIDE_ID(pkt->hdr.flags, pkt->hdr.code);
8375 1.1 pooka
8376 1.91 mlelstv if (((qid & ~0x80) == 0 && idx == 0 && code == 0) ||
8377 1.91 mlelstv pkt->len_n_flags == htole32(IWM_FH_RSCSR_FRAME_INVALID))
8378 1.91 mlelstv return;
8379 1.1 pooka
8380 1.91 mlelstv switch (code) {
8381 1.91 mlelstv case IWM_REPLY_RX_PHY_CMD:
8382 1.91 mlelstv iwm_rx_rx_phy_cmd(sc, pkt, data);
8383 1.91 mlelstv break;
8384 1.1 pooka
8385 1.91 mlelstv case IWM_REPLY_RX_MPDU_CMD:
8386 1.91 mlelstv iwm_rx_rx_mpdu(sc, pkt, data);
8387 1.91 mlelstv break;
8388 1.1 pooka
8389 1.91 mlelstv case IWM_TX_CMD:
8390 1.91 mlelstv iwm_rx_tx_cmd(sc, pkt, data);
8391 1.91 mlelstv break;
8392 1.1 pooka
8393 1.91 mlelstv #ifdef notyet
8394 1.91 mlelstv case IWM_BA_NOTIF:
8395 1.91 mlelstv iwm_rx_compressed_ba(sc, pkt);
8396 1.91 mlelstv break;
8397 1.91 mlelstv #endif
8398 1.1 pooka
8399 1.92 kre case IWM_MISSED_BEACONS_NOTIFICATION: {
8400 1.91 mlelstv struct iwm_missed_beacons_notif *mb;
8401 1.92 kre
8402 1.91 mlelstv SYNC_RESP_STRUCT(mb, pkt);
8403 1.91 mlelstv iwm_rx_missed_beacons_notif(sc, mb);
8404 1.91 mlelstv break;
8405 1.92 kre }
8406 1.1 pooka
8407 1.91 mlelstv case IWM_MFUART_LOAD_NOTIFICATION:
8408 1.91 mlelstv break;
8409 1.1 pooka
8410 1.91 mlelstv case IWM_ALIVE: {
8411 1.91 mlelstv struct iwm_alive_resp_v1 *resp1;
8412 1.91 mlelstv struct iwm_alive_resp_v2 *resp2;
8413 1.91 mlelstv struct iwm_alive_resp_v3 *resp3;
8414 1.91 mlelstv
8415 1.91 mlelstv if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp1)) {
8416 1.91 mlelstv SYNC_RESP_STRUCT(resp1, pkt);
8417 1.91 mlelstv sc->sc_uc.uc_error_event_table
8418 1.91 mlelstv = le32toh(resp1->error_event_table_ptr);
8419 1.91 mlelstv sc->sc_uc.uc_log_event_table
8420 1.91 mlelstv = le32toh(resp1->log_event_table_ptr);
8421 1.91 mlelstv sc->sched_base = le32toh(resp1->scd_base_ptr);
8422 1.91 mlelstv if (resp1->status == IWM_ALIVE_STATUS_OK)
8423 1.91 mlelstv sc->sc_uc.uc_ok = 1;
8424 1.91 mlelstv else
8425 1.91 mlelstv sc->sc_uc.uc_ok = 0;
8426 1.91 mlelstv }
8427 1.45 nonaka
8428 1.1 pooka
8429 1.91 mlelstv if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp2)) {
8430 1.91 mlelstv SYNC_RESP_STRUCT(resp2, pkt);
8431 1.91 mlelstv sc->sc_uc.uc_error_event_table
8432 1.91 mlelstv = le32toh(resp2->error_event_table_ptr);
8433 1.91 mlelstv sc->sc_uc.uc_log_event_table
8434 1.91 mlelstv = le32toh(resp2->log_event_table_ptr);
8435 1.91 mlelstv sc->sched_base = le32toh(resp2->scd_base_ptr);
8436 1.91 mlelstv sc->sc_uc.uc_umac_error_event_table
8437 1.91 mlelstv = le32toh(resp2->error_info_addr);
8438 1.91 mlelstv if (resp2->status == IWM_ALIVE_STATUS_OK)
8439 1.91 mlelstv sc->sc_uc.uc_ok = 1;
8440 1.91 mlelstv else
8441 1.91 mlelstv sc->sc_uc.uc_ok = 0;
8442 1.45 nonaka }
8443 1.1 pooka
8444 1.91 mlelstv if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp3)) {
8445 1.91 mlelstv SYNC_RESP_STRUCT(resp3, pkt);
8446 1.91 mlelstv sc->sc_uc.uc_error_event_table
8447 1.91 mlelstv = le32toh(resp3->error_event_table_ptr);
8448 1.91 mlelstv sc->sc_uc.uc_log_event_table
8449 1.91 mlelstv = le32toh(resp3->log_event_table_ptr);
8450 1.91 mlelstv sc->sched_base = le32toh(resp3->scd_base_ptr);
8451 1.91 mlelstv sc->sc_uc.uc_umac_error_event_table
8452 1.91 mlelstv = le32toh(resp3->error_info_addr);
8453 1.91 mlelstv if (resp3->status == IWM_ALIVE_STATUS_OK)
8454 1.91 mlelstv sc->sc_uc.uc_ok = 1;
8455 1.91 mlelstv else
8456 1.91 mlelstv sc->sc_uc.uc_ok = 0;
8457 1.45 nonaka }
8458 1.1 pooka
8459 1.91 mlelstv sc->sc_uc.uc_intr = 1;
8460 1.91 mlelstv wakeup(&sc->sc_uc);
8461 1.91 mlelstv break;
8462 1.91 mlelstv }
8463 1.91 mlelstv
8464 1.91 mlelstv case IWM_CALIB_RES_NOTIF_PHY_DB: {
8465 1.91 mlelstv struct iwm_calib_res_notif_phy_db *phy_db_notif;
8466 1.91 mlelstv SYNC_RESP_STRUCT(phy_db_notif, pkt);
8467 1.91 mlelstv uint16_t size = le16toh(phy_db_notif->length);
8468 1.91 mlelstv bus_dmamap_sync(sc->sc_dmat, data->map,
8469 1.91 mlelstv sizeof(*pkt) + sizeof(*phy_db_notif),
8470 1.91 mlelstv size, BUS_DMASYNC_POSTREAD);
8471 1.91 mlelstv iwm_phy_db_set_section(sc, phy_db_notif, size);
8472 1.91 mlelstv sc->sc_init_complete |= IWM_CALIB_COMPLETE;
8473 1.91 mlelstv wakeup(&sc->sc_init_complete);
8474 1.91 mlelstv break;
8475 1.91 mlelstv }
8476 1.91 mlelstv
8477 1.91 mlelstv case IWM_STATISTICS_NOTIFICATION: {
8478 1.91 mlelstv struct iwm_notif_statistics *stats;
8479 1.91 mlelstv SYNC_RESP_STRUCT(stats, pkt);
8480 1.91 mlelstv memcpy(&sc->sc_stats, stats, sizeof(sc->sc_stats));
8481 1.91 mlelstv sc->sc_noise = iwm_get_noise(&stats->rx.general);
8482 1.91 mlelstv break;
8483 1.91 mlelstv }
8484 1.91 mlelstv
8485 1.91 mlelstv case IWM_MCC_CHUB_UPDATE_CMD: {
8486 1.91 mlelstv struct iwm_mcc_chub_notif *notif;
8487 1.91 mlelstv SYNC_RESP_STRUCT(notif, pkt);
8488 1.91 mlelstv iwm_mcc_update(sc, notif);
8489 1.91 mlelstv break;
8490 1.91 mlelstv }
8491 1.91 mlelstv
8492 1.91 mlelstv case IWM_DTS_MEASUREMENT_NOTIFICATION:
8493 1.91 mlelstv case IWM_WIDE_ID(IWM_PHY_OPS_GROUP,
8494 1.91 mlelstv IWM_DTS_MEASUREMENT_NOTIF_WIDE):
8495 1.91 mlelstv case IWM_WIDE_ID(IWM_PHY_OPS_GROUP,
8496 1.91 mlelstv IWM_TEMP_REPORTING_THRESHOLDS_CMD):
8497 1.91 mlelstv break;
8498 1.1 pooka
8499 1.91 mlelstv #if notyet
8500 1.91 mlelstv case IWM_WIDE_ID(IWM_PHY_OPS_GROUP,
8501 1.91 mlelstv IWM_CT_KILL_NOTIFICATION): {
8502 1.91 mlelstv struct iwm_ct_kill_notif *notif;
8503 1.91 mlelstv SYNC_RESP_STRUCT(notif, pkt);
8504 1.91 mlelstv printf("%s: device at critical temperature (%u degC), "
8505 1.91 mlelstv "stopping device\n",
8506 1.91 mlelstv DEVNAME(sc), le16toh(notif->temperature));
8507 1.91 mlelstv sc->sc_flags |= IWM_FLAG_HW_ERR;
8508 1.91 mlelstv task_add(systq, &sc->init_task);
8509 1.91 mlelstv break;
8510 1.91 mlelstv }
8511 1.91 mlelstv #endif
8512 1.1 pooka
8513 1.91 mlelstv case IWM_ADD_STA_KEY:
8514 1.91 mlelstv case IWM_PHY_CONFIGURATION_CMD:
8515 1.91 mlelstv case IWM_TX_ANT_CONFIGURATION_CMD:
8516 1.91 mlelstv case IWM_ADD_STA:
8517 1.91 mlelstv case IWM_MAC_CONTEXT_CMD:
8518 1.91 mlelstv case IWM_REPLY_SF_CFG_CMD:
8519 1.91 mlelstv case IWM_POWER_TABLE_CMD:
8520 1.91 mlelstv case IWM_LTR_CONFIG:
8521 1.91 mlelstv case IWM_PHY_CONTEXT_CMD:
8522 1.91 mlelstv case IWM_BINDING_CONTEXT_CMD:
8523 1.91 mlelstv case IWM_WIDE_ID(IWM_LONG_GROUP, IWM_SCAN_CFG_CMD):
8524 1.91 mlelstv case IWM_WIDE_ID(IWM_LONG_GROUP, IWM_SCAN_REQ_UMAC):
8525 1.91 mlelstv case IWM_WIDE_ID(IWM_LONG_GROUP, IWM_SCAN_ABORT_UMAC):
8526 1.91 mlelstv case IWM_SCAN_OFFLOAD_REQUEST_CMD:
8527 1.91 mlelstv case IWM_SCAN_OFFLOAD_ABORT_CMD:
8528 1.91 mlelstv case IWM_REPLY_BEACON_FILTERING_CMD:
8529 1.91 mlelstv case IWM_MAC_PM_POWER_TABLE:
8530 1.91 mlelstv case IWM_TIME_QUOTA_CMD:
8531 1.91 mlelstv case IWM_REMOVE_STA:
8532 1.91 mlelstv case IWM_TXPATH_FLUSH:
8533 1.91 mlelstv case IWM_LQ_CMD:
8534 1.91 mlelstv case IWM_WIDE_ID(IWM_LONG_GROUP,
8535 1.91 mlelstv IWM_FW_PAGING_BLOCK_CMD):
8536 1.91 mlelstv case IWM_BT_CONFIG:
8537 1.91 mlelstv case IWM_REPLY_THERMAL_MNG_BACKOFF:
8538 1.91 mlelstv case IWM_NVM_ACCESS_CMD:
8539 1.91 mlelstv case IWM_MCC_UPDATE_CMD:
8540 1.91 mlelstv case IWM_TIME_EVENT_CMD: {
8541 1.91 mlelstv size_t pkt_len;
8542 1.91 mlelstv
8543 1.91 mlelstv if (sc->sc_cmd_resp_pkt[idx] == NULL)
8544 1.91 mlelstv break;
8545 1.91 mlelstv
8546 1.91 mlelstv pkt_len = sizeof(pkt->len_n_flags) +
8547 1.91 mlelstv iwm_rx_packet_len(pkt);
8548 1.91 mlelstv
8549 1.91 mlelstv if ((pkt->hdr.flags & IWM_CMD_FAILED_MSK) ||
8550 1.91 mlelstv pkt_len < sizeof(*pkt) ||
8551 1.91 mlelstv pkt_len > sc->sc_cmd_resp_len[idx]) {
8552 1.91 mlelstv kmem_free(sc->sc_cmd_resp_pkt[idx],
8553 1.91 mlelstv sc->sc_cmd_resp_len[idx]);
8554 1.91 mlelstv sc->sc_cmd_resp_pkt[idx] = NULL;
8555 1.91 mlelstv sc->sc_cmd_resp_len[idx] = 0;
8556 1.45 nonaka break;
8557 1.45 nonaka }
8558 1.45 nonaka
8559 1.91 mlelstv SYNC_RESP(pkt_len - sizeof(*pkt), pkt);
8560 1.91 mlelstv memcpy(sc->sc_cmd_resp_pkt[idx], pkt, pkt_len);
8561 1.91 mlelstv break;
8562 1.91 mlelstv }
8563 1.91 mlelstv
8564 1.91 mlelstv /* ignore */
8565 1.91 mlelstv case IWM_PHY_DB_CMD:
8566 1.91 mlelstv break;
8567 1.45 nonaka
8568 1.91 mlelstv case IWM_INIT_COMPLETE_NOTIF:
8569 1.91 mlelstv sc->sc_init_complete |= IWM_INIT_COMPLETE;
8570 1.91 mlelstv wakeup(&sc->sc_init_complete);
8571 1.91 mlelstv break;
8572 1.1 pooka
8573 1.91 mlelstv case IWM_SCAN_OFFLOAD_COMPLETE: {
8574 1.91 mlelstv struct iwm_periodic_scan_complete *notif;
8575 1.91 mlelstv SYNC_RESP_STRUCT(notif, pkt);
8576 1.91 mlelstv break;
8577 1.91 mlelstv }
8578 1.1 pooka
8579 1.91 mlelstv case IWM_SCAN_ITERATION_COMPLETE: {
8580 1.91 mlelstv struct iwm_lmac_scan_complete_notif *notif;
8581 1.91 mlelstv SYNC_RESP_STRUCT(notif, pkt);
8582 1.91 mlelstv if (ISSET(sc->sc_flags, IWM_FLAG_SCANNING))
8583 1.91 mlelstv iwm_endscan(sc);
8584 1.91 mlelstv break;
8585 1.91 mlelstv }
8586 1.1 pooka
8587 1.91 mlelstv case IWM_SCAN_COMPLETE_UMAC: {
8588 1.91 mlelstv struct iwm_umac_scan_complete *notif;
8589 1.91 mlelstv SYNC_RESP_STRUCT(notif, pkt);
8590 1.91 mlelstv if (ISSET(sc->sc_flags, IWM_FLAG_SCANNING))
8591 1.91 mlelstv iwm_endscan(sc);
8592 1.91 mlelstv break;
8593 1.91 mlelstv }
8594 1.45 nonaka
8595 1.91 mlelstv case IWM_SCAN_ITERATION_COMPLETE_UMAC: {
8596 1.91 mlelstv struct iwm_umac_scan_iter_complete_notif *notif;
8597 1.91 mlelstv SYNC_RESP_STRUCT(notif, pkt);
8598 1.91 mlelstv if (ISSET(sc->sc_flags, IWM_FLAG_SCANNING))
8599 1.91 mlelstv iwm_endscan(sc);
8600 1.91 mlelstv break;
8601 1.91 mlelstv }
8602 1.45 nonaka
8603 1.91 mlelstv case IWM_REPLY_ERROR: {
8604 1.91 mlelstv struct iwm_error_resp *resp;
8605 1.91 mlelstv SYNC_RESP_STRUCT(resp, pkt);
8606 1.91 mlelstv device_printf(sc->sc_dev, "firmware error 0x%x, cmd 0x%x\n",
8607 1.91 mlelstv le32toh(resp->error_type), resp->cmd_id);
8608 1.91 mlelstv break;
8609 1.91 mlelstv }
8610 1.1 pooka
8611 1.91 mlelstv case IWM_TIME_EVENT_NOTIFICATION: {
8612 1.91 mlelstv struct iwm_time_event_notif *notif;
8613 1.91 mlelstv uint32_t action;
8614 1.91 mlelstv SYNC_RESP_STRUCT(notif, pkt);
8615 1.91 mlelstv
8616 1.91 mlelstv if (sc->sc_time_event_uid != le32toh(notif->unique_id))
8617 1.91 mlelstv break;
8618 1.91 mlelstv action = le32toh(notif->action);
8619 1.91 mlelstv if (action & IWM_TE_V2_NOTIF_HOST_EVENT_END)
8620 1.91 mlelstv CLR(sc->sc_flags, IWM_FLAG_TE_ACTIVE);
8621 1.91 mlelstv break;
8622 1.91 mlelstv }
8623 1.1 pooka
8624 1.91 mlelstv case IWM_WIDE_ID(IWM_SYSTEM_GROUP,
8625 1.91 mlelstv IWM_FSEQ_VER_MISMATCH_NOTIFICATION):
8626 1.91 mlelstv break;
8627 1.1 pooka
8628 1.91 mlelstv /*
8629 1.91 mlelstv * Firmware versions 21 and 22 generate some DEBUG_LOG_MSG
8630 1.91 mlelstv * messages. Just ignore them for now.
8631 1.91 mlelstv */
8632 1.91 mlelstv case IWM_DEBUG_LOG_MSG:
8633 1.91 mlelstv break;
8634 1.8 nonaka
8635 1.91 mlelstv case IWM_MCAST_FILTER_CMD:
8636 1.91 mlelstv break;
8637 1.71 nonaka
8638 1.91 mlelstv case IWM_SCD_QUEUE_CFG: {
8639 1.91 mlelstv struct iwm_scd_txq_cfg_rsp *rsp;
8640 1.91 mlelstv SYNC_RESP_STRUCT(rsp, pkt);
8641 1.1 pooka
8642 1.91 mlelstv break;
8643 1.91 mlelstv }
8644 1.11 nonaka
8645 1.91 mlelstv case IWM_WIDE_ID(IWM_DATA_PATH_GROUP, IWM_DQA_ENABLE_CMD):
8646 1.91 mlelstv break;
8647 1.1 pooka
8648 1.91 mlelstv case IWM_WIDE_ID(IWM_SYSTEM_GROUP, IWM_SOC_CONFIGURATION_CMD):
8649 1.91 mlelstv break;
8650 1.1 pooka
8651 1.91 mlelstv default:
8652 1.91 mlelstv handled = 0;
8653 1.91 mlelstv device_printf(sc->sc_dev,
8654 1.91 mlelstv "unhandled firmware response 0x%x/0x%x rx ring %d[%d]\n",
8655 1.91 mlelstv code, pkt->len_n_flags, (qid & ~0x80), idx);
8656 1.91 mlelstv break;
8657 1.1 pooka }
8658 1.1 pooka
8659 1.1 pooka /*
8660 1.91 mlelstv * uCode sets bit 0x80 when it originates the notification,
8661 1.91 mlelstv * i.e. when the notification is not a direct response to a
8662 1.91 mlelstv * command sent by the driver.
8663 1.91 mlelstv * For example, uCode issues IWM_REPLY_RX when it sends a
8664 1.91 mlelstv * received frame to the driver.
8665 1.1 pooka */
8666 1.91 mlelstv if (handled && !(qid & (1 << 7))) {
8667 1.91 mlelstv iwm_cmd_done(sc, qid, idx);
8668 1.91 mlelstv }
8669 1.91 mlelstv }
8670 1.91 mlelstv
8671 1.91 mlelstv static void
8672 1.91 mlelstv iwm_notif_intr(struct iwm_softc *sc)
8673 1.91 mlelstv {
8674 1.91 mlelstv uint32_t wreg;
8675 1.91 mlelstv uint16_t hw;
8676 1.91 mlelstv int count;
8677 1.91 mlelstv
8678 1.91 mlelstv bus_dmamap_sync(sc->sc_dmat, sc->rxq.stat_dma.map,
8679 1.91 mlelstv 0, sc->rxq.stat_dma.size, BUS_DMASYNC_POSTREAD);
8680 1.91 mlelstv
8681 1.91 mlelstv #if notyet
8682 1.91 mlelstv if (sc->sc_mqrx_supported) {
8683 1.91 mlelstv count = IWM_RX_MQ_RING_COUNT;
8684 1.91 mlelstv wreg = IWM_RFH_Q0_FRBDCB_WIDX_TRG;
8685 1.91 mlelstv } else
8686 1.91 mlelstv #endif
8687 1.91 mlelstv {
8688 1.91 mlelstv count = IWM_RX_RING_COUNT;
8689 1.91 mlelstv wreg = IWM_FH_RSCSR_CHNL0_WPTR;
8690 1.91 mlelstv }
8691 1.91 mlelstv
8692 1.91 mlelstv hw = le16toh(sc->rxq.stat->closed_rb_num) & 0xfff;
8693 1.91 mlelstv hw &= (count - 1);
8694 1.91 mlelstv while (sc->rxq.cur != hw) {
8695 1.91 mlelstv struct iwm_rx_data *data = &sc->rxq.data[sc->rxq.cur];
8696 1.91 mlelstv iwm_rx_pkt(sc, data);
8697 1.91 mlelstv sc->rxq.cur = (sc->rxq.cur + 1) % count;
8698 1.91 mlelstv }
8699 1.91 mlelstv
8700 1.91 mlelstv /*
8701 1.91 mlelstv * Tell the firmware what we have processed.
8702 1.91 mlelstv * Seems like the hardware gets upset unless we align the write by 8??
8703 1.91 mlelstv */
8704 1.91 mlelstv hw = (hw == 0) ? count - 1 : hw - 1;
8705 1.91 mlelstv IWM_WRITE(sc, wreg, hw & ~7);
8706 1.1 pooka }
8707 1.1 pooka
8708 1.61 nonaka static int
8709 1.61 nonaka iwm_intr(void *arg)
8710 1.61 nonaka {
8711 1.61 nonaka struct iwm_softc *sc = arg;
8712 1.61 nonaka
8713 1.70 nonaka /* Disable interrupts */
8714 1.61 nonaka IWM_WRITE(sc, IWM_CSR_INT_MASK, 0);
8715 1.61 nonaka
8716 1.70 nonaka softint_schedule(sc->sc_soft_ih);
8717 1.70 nonaka return 1;
8718 1.70 nonaka }
8719 1.70 nonaka
8720 1.70 nonaka static void
8721 1.70 nonaka iwm_softintr(void *arg)
8722 1.70 nonaka {
8723 1.70 nonaka struct iwm_softc *sc = arg;
8724 1.70 nonaka struct ifnet *ifp = IC2IFP(&sc->sc_ic);
8725 1.70 nonaka uint32_t r1, r2;
8726 1.91 mlelstv int s;
8727 1.70 nonaka
8728 1.63 nonaka if (__predict_true(sc->sc_flags & IWM_FLAG_USE_ICT)) {
8729 1.61 nonaka uint32_t *ict = sc->ict_dma.vaddr;
8730 1.61 nonaka int tmp;
8731 1.61 nonaka
8732 1.61 nonaka bus_dmamap_sync(sc->sc_dmat, sc->ict_dma.map,
8733 1.61 nonaka 0, sc->ict_dma.size, BUS_DMASYNC_POSTREAD);
8734 1.61 nonaka tmp = htole32(ict[sc->ict_cur]);
8735 1.70 nonaka if (tmp == 0)
8736 1.70 nonaka goto out_ena; /* Interrupt not for us. */
8737 1.61 nonaka
8738 1.61 nonaka /*
8739 1.61 nonaka * ok, there was something. keep plowing until we have all.
8740 1.61 nonaka */
8741 1.61 nonaka r1 = r2 = 0;
8742 1.61 nonaka while (tmp) {
8743 1.61 nonaka r1 |= tmp;
8744 1.61 nonaka ict[sc->ict_cur] = 0; /* Acknowledge. */
8745 1.61 nonaka sc->ict_cur = (sc->ict_cur + 1) % IWM_ICT_COUNT;
8746 1.61 nonaka tmp = htole32(ict[sc->ict_cur]);
8747 1.61 nonaka }
8748 1.61 nonaka
8749 1.62 nonaka bus_dmamap_sync(sc->sc_dmat, sc->ict_dma.map,
8750 1.62 nonaka 0, sc->ict_dma.size, BUS_DMASYNC_PREWRITE);
8751 1.62 nonaka
8752 1.61 nonaka /* this is where the fun begins. don't ask */
8753 1.61 nonaka if (r1 == 0xffffffff)
8754 1.61 nonaka r1 = 0;
8755 1.61 nonaka
8756 1.91 mlelstv /*
8757 1.91 mlelstv * Workaround for hardware bug where bits are falsely cleared
8758 1.91 mlelstv * when using interrupt coalescing. Bit 15 should be set if
8759 1.91 mlelstv * bits 18 and 19 are set.
8760 1.91 mlelstv */
8761 1.61 nonaka if (r1 & 0xc0000)
8762 1.61 nonaka r1 |= 0x8000;
8763 1.61 nonaka r1 = (0xff & r1) | ((0xff00 & r1) << 16);
8764 1.61 nonaka } else {
8765 1.61 nonaka r1 = IWM_READ(sc, IWM_CSR_INT);
8766 1.61 nonaka r2 = IWM_READ(sc, IWM_CSR_FH_INT_STATUS);
8767 1.61 nonaka }
8768 1.61 nonaka if (r1 == 0 && r2 == 0) {
8769 1.70 nonaka goto out_ena; /* Interrupt not for us. */
8770 1.61 nonaka }
8771 1.91 mlelstv if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0)
8772 1.91 mlelstv return; /* Hardware gone! */
8773 1.61 nonaka
8774 1.63 nonaka /* Acknowledge interrupts. */
8775 1.61 nonaka IWM_WRITE(sc, IWM_CSR_INT, r1 | ~sc->sc_intmask);
8776 1.91 mlelstv
8777 1.91 mlelstv if (r1 & IWM_CSR_INT_BIT_RF_KILL) {
8778 1.91 mlelstv if (iwm_check_rfkill(sc) && ifp != NULL &&
8779 1.91 mlelstv (ifp->if_flags & IFF_UP))
8780 1.91 mlelstv goto fatal;
8781 1.91 mlelstv }
8782 1.61 nonaka
8783 1.1 pooka if (r1 & IWM_CSR_INT_BIT_SW_ERR) {
8784 1.1 pooka
8785 1.1 pooka iwm_nic_error(sc);
8786 1.91 mlelstv iwm_dump_driver_status(sc);
8787 1.1 pooka
8788 1.3 nonaka aprint_error_dev(sc->sc_dev, "fatal firmware error\n");
8789 1.50 nonaka fatal:
8790 1.91 mlelstv if (ifp != NULL) {
8791 1.91 mlelstv s = splnet();
8792 1.91 mlelstv ifp->if_flags &= ~IFF_UP;
8793 1.91 mlelstv iwm_stop(ifp, 1);
8794 1.91 mlelstv splx(s);
8795 1.91 mlelstv }
8796 1.50 nonaka /* Don't restore interrupt mask */
8797 1.50 nonaka return;
8798 1.1 pooka
8799 1.1 pooka }
8800 1.1 pooka
8801 1.1 pooka if (r1 & IWM_CSR_INT_BIT_HW_ERR) {
8802 1.3 nonaka aprint_error_dev(sc->sc_dev,
8803 1.3 nonaka "hardware error, stopping device\n");
8804 1.50 nonaka goto fatal;
8805 1.1 pooka }
8806 1.1 pooka
8807 1.1 pooka /* firmware chunk loaded */
8808 1.1 pooka if (r1 & IWM_CSR_INT_BIT_FH_TX) {
8809 1.1 pooka IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, IWM_CSR_FH_INT_TX_MASK);
8810 1.1 pooka sc->sc_fw_chunk_done = 1;
8811 1.1 pooka wakeup(&sc->sc_fw);
8812 1.1 pooka }
8813 1.1 pooka
8814 1.91 mlelstv if (r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX |
8815 1.91 mlelstv IWM_CSR_INT_BIT_RX_PERIODIC)) {
8816 1.91 mlelstv if (r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX)) {
8817 1.91 mlelstv IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, IWM_CSR_FH_INT_RX_MASK);
8818 1.91 mlelstv }
8819 1.91 mlelstv
8820 1.91 mlelstv if (r1 & IWM_CSR_INT_BIT_RX_PERIODIC) {
8821 1.91 mlelstv IWM_WRITE(sc, IWM_CSR_INT, IWM_CSR_INT_BIT_RX_PERIODIC);
8822 1.91 mlelstv }
8823 1.91 mlelstv
8824 1.91 mlelstv /* Disable periodic interrupt; we use it as just a one-shot. */
8825 1.91 mlelstv IWM_WRITE_1(sc, IWM_CSR_INT_PERIODIC_REG, IWM_CSR_INT_PERIODIC_DIS);
8826 1.91 mlelstv
8827 1.91 mlelstv /*
8828 1.91 mlelstv * Enable periodic interrupt in 8 msec only if we received
8829 1.91 mlelstv * real RX interrupt (instead of just periodic int), to catch
8830 1.91 mlelstv * any dangling Rx interrupt. If it was just the periodic
8831 1.91 mlelstv * interrupt, there was no dangling Rx activity, and no need
8832 1.91 mlelstv * to extend the periodic interrupt; one-shot is enough.
8833 1.91 mlelstv */
8834 1.91 mlelstv if (r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX))
8835 1.91 mlelstv IWM_WRITE_1(sc, IWM_CSR_INT_PERIODIC_REG,
8836 1.91 mlelstv IWM_CSR_INT_PERIODIC_ENA);
8837 1.1 pooka
8838 1.1 pooka iwm_notif_intr(sc);
8839 1.1 pooka }
8840 1.1 pooka
8841 1.70 nonaka out_ena:
8842 1.1 pooka iwm_restore_interrupts(sc);
8843 1.1 pooka }
8844 1.1 pooka
8845 1.1 pooka /*
8846 1.1 pooka * Autoconf glue-sniffing
8847 1.1 pooka */
8848 1.1 pooka
8849 1.1 pooka static const pci_product_id_t iwm_devices[] = {
8850 1.5 nonaka PCI_PRODUCT_INTEL_WIFI_LINK_7260_1,
8851 1.5 nonaka PCI_PRODUCT_INTEL_WIFI_LINK_7260_2,
8852 1.5 nonaka PCI_PRODUCT_INTEL_WIFI_LINK_3160_1,
8853 1.5 nonaka PCI_PRODUCT_INTEL_WIFI_LINK_3160_2,
8854 1.5 nonaka PCI_PRODUCT_INTEL_WIFI_LINK_7265_1,
8855 1.5 nonaka PCI_PRODUCT_INTEL_WIFI_LINK_7265_2,
8856 1.45 nonaka PCI_PRODUCT_INTEL_WIFI_LINK_3165_1,
8857 1.45 nonaka PCI_PRODUCT_INTEL_WIFI_LINK_3165_2,
8858 1.77 mlelstv PCI_PRODUCT_INTEL_WIFI_LINK_3168,
8859 1.45 nonaka PCI_PRODUCT_INTEL_WIFI_LINK_8260_1,
8860 1.45 nonaka PCI_PRODUCT_INTEL_WIFI_LINK_8260_2,
8861 1.58 nonaka PCI_PRODUCT_INTEL_WIFI_LINK_4165_1,
8862 1.58 nonaka PCI_PRODUCT_INTEL_WIFI_LINK_4165_2,
8863 1.72 nonaka PCI_PRODUCT_INTEL_WIFI_LINK_8265,
8864 1.1 pooka };
8865 1.1 pooka
8866 1.1 pooka static int
8867 1.4 nonaka iwm_match(device_t parent, cfdata_t match __unused, void *aux)
8868 1.1 pooka {
8869 1.1 pooka struct pci_attach_args *pa = aux;
8870 1.1 pooka
8871 1.1 pooka if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL)
8872 1.1 pooka return 0;
8873 1.1 pooka
8874 1.5 nonaka for (size_t i = 0; i < __arraycount(iwm_devices); i++)
8875 1.1 pooka if (PCI_PRODUCT(pa->pa_id) == iwm_devices[i])
8876 1.1 pooka return 1;
8877 1.1 pooka
8878 1.1 pooka return 0;
8879 1.1 pooka }
8880 1.1 pooka
8881 1.4 nonaka static int
8882 1.91 mlelstv iwm_preinit(struct iwm_softc *sc, bool printme)
8883 1.1 pooka {
8884 1.45 nonaka int err;
8885 1.1 pooka
8886 1.91 mlelstv err = iwm_prepare_card_hw(sc);
8887 1.91 mlelstv if (err) {
8888 1.91 mlelstv aprint_error_dev(sc->sc_dev, "could not prepare hardware\n");
8889 1.91 mlelstv return err;
8890 1.91 mlelstv }
8891 1.91 mlelstv
8892 1.91 mlelstv if (sc->attached) {
8893 1.91 mlelstv return 0;
8894 1.91 mlelstv }
8895 1.91 mlelstv
8896 1.45 nonaka err = iwm_start_hw(sc);
8897 1.45 nonaka if (err) {
8898 1.3 nonaka aprint_error_dev(sc->sc_dev, "could not initialize hardware\n");
8899 1.45 nonaka return err;
8900 1.1 pooka }
8901 1.1 pooka
8902 1.45 nonaka err = iwm_run_init_mvm_ucode(sc, 1);
8903 1.1 pooka iwm_stop_device(sc);
8904 1.45 nonaka if (err)
8905 1.45 nonaka return err;
8906 1.1 pooka
8907 1.91 mlelstv sc->attached = 1;
8908 1.91 mlelstv
8909 1.91 mlelstv if (printme)
8910 1.91 mlelstv aprint_normal_dev(sc->sc_dev,
8911 1.91 mlelstv "hw rev 0x%x, fw ver %s, address %s\n",
8912 1.91 mlelstv sc->sc_hw_rev & IWM_CSR_HW_REV_TYPE_MSK, sc->sc_fwver,
8913 1.91 mlelstv ether_sprintf(sc->sc_nvm.hw_addr));
8914 1.8 nonaka
8915 1.36 nonaka return 0;
8916 1.36 nonaka }
8917 1.36 nonaka
8918 1.36 nonaka static void
8919 1.36 nonaka iwm_attach_hook(device_t dev)
8920 1.36 nonaka {
8921 1.36 nonaka struct iwm_softc *sc = device_private(dev);
8922 1.30 nonaka
8923 1.87 riastrad iwm_config_complete(sc);
8924 1.1 pooka }
8925 1.1 pooka
8926 1.94 mlelstv static void
8927 1.94 mlelstv iwm_claim_rx_ring(struct iwm_softc *sc)
8928 1.94 mlelstv {
8929 1.94 mlelstv struct iwm_rx_ring *ring = &sc->rxq;
8930 1.94 mlelstv struct mbuf *m;
8931 1.94 mlelstv int i;
8932 1.94 mlelstv
8933 1.94 mlelstv /* Claim mbufs from RX ring */
8934 1.94 mlelstv for (i = 0; i < IWM_RX_RING_COUNT; i++) {
8935 1.94 mlelstv m = ring->data[i].m;
8936 1.94 mlelstv if (m != NULL) {
8937 1.94 mlelstv MCLAIM(m, &sc->sc_ec.ec_rx_mowner);
8938 1.94 mlelstv }
8939 1.94 mlelstv }
8940 1.94 mlelstv }
8941 1.94 mlelstv
8942 1.4 nonaka static void
8943 1.4 nonaka iwm_attach(device_t parent, device_t self, void *aux)
8944 1.1 pooka {
8945 1.1 pooka struct iwm_softc *sc = device_private(self);
8946 1.1 pooka struct pci_attach_args *pa = aux;
8947 1.1 pooka pcireg_t reg, memtype;
8948 1.37 nonaka char intrbuf[PCI_INTRSTR_LEN];
8949 1.1 pooka const char *intrstr;
8950 1.45 nonaka int err;
8951 1.2 nonaka int txq_i;
8952 1.36 nonaka const struct sysctlnode *node;
8953 1.1 pooka
8954 1.3 nonaka sc->sc_dev = self;
8955 1.1 pooka sc->sc_pct = pa->pa_pc;
8956 1.1 pooka sc->sc_pcitag = pa->pa_tag;
8957 1.1 pooka sc->sc_dmat = pa->pa_dmat;
8958 1.5 nonaka sc->sc_pciid = pa->pa_id;
8959 1.1 pooka
8960 1.1 pooka pci_aprint_devinfo(pa, NULL);
8961 1.1 pooka
8962 1.91 mlelstv mutex_init(&sc->sc_nic_mtx, MUTEX_DEFAULT, IPL_NET);
8963 1.91 mlelstv
8964 1.45 nonaka if (workqueue_create(&sc->sc_nswq, "iwmns",
8965 1.45 nonaka iwm_newstate_cb, sc, PRI_NONE, IPL_NET, 0))
8966 1.45 nonaka panic("%s: could not create workqueue: newstate",
8967 1.45 nonaka device_xname(self));
8968 1.50 nonaka sc->sc_soft_ih = softint_establish(SOFTINT_NET, iwm_softintr, sc);
8969 1.50 nonaka if (sc->sc_soft_ih == NULL)
8970 1.50 nonaka panic("%s: could not establish softint", device_xname(self));
8971 1.45 nonaka
8972 1.1 pooka /*
8973 1.1 pooka * Get the offset of the PCI Express Capability Structure in PCI
8974 1.1 pooka * Configuration Space.
8975 1.1 pooka */
8976 1.45 nonaka err = pci_get_capability(sc->sc_pct, sc->sc_pcitag,
8977 1.1 pooka PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, NULL);
8978 1.45 nonaka if (err == 0) {
8979 1.3 nonaka aprint_error_dev(self,
8980 1.3 nonaka "PCIe capability structure not found!\n");
8981 1.1 pooka return;
8982 1.1 pooka }
8983 1.1 pooka
8984 1.1 pooka /* Clear device-specific "PCI retry timeout" register (41h). */
8985 1.1 pooka reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
8986 1.1 pooka pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);
8987 1.1 pooka
8988 1.45 nonaka /* Enable bus-mastering */
8989 1.1 pooka reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);
8990 1.1 pooka reg |= PCI_COMMAND_MASTER_ENABLE;
8991 1.1 pooka pci_conf_write(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, reg);
8992 1.1 pooka
8993 1.1 pooka memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START);
8994 1.45 nonaka err = pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0,
8995 1.1 pooka &sc->sc_st, &sc->sc_sh, NULL, &sc->sc_sz);
8996 1.45 nonaka if (err) {
8997 1.3 nonaka aprint_error_dev(self, "can't map mem space\n");
8998 1.1 pooka return;
8999 1.1 pooka }
9000 1.1 pooka
9001 1.1 pooka /* Install interrupt handler. */
9002 1.45 nonaka err = pci_intr_alloc(pa, &sc->sc_pihp, NULL, 0);
9003 1.45 nonaka if (err) {
9004 1.37 nonaka aprint_error_dev(self, "can't allocate interrupt\n");
9005 1.1 pooka return;
9006 1.1 pooka }
9007 1.61 nonaka reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);
9008 1.61 nonaka if (pci_intr_type(sc->sc_pct, sc->sc_pihp[0]) == PCI_INTR_TYPE_INTX)
9009 1.61 nonaka CLR(reg, PCI_COMMAND_INTERRUPT_DISABLE);
9010 1.61 nonaka else
9011 1.61 nonaka SET(reg, PCI_COMMAND_INTERRUPT_DISABLE);
9012 1.61 nonaka pci_conf_write(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, reg);
9013 1.31 nonaka intrstr = pci_intr_string(sc->sc_pct, sc->sc_pihp[0], intrbuf,
9014 1.31 nonaka sizeof(intrbuf));
9015 1.49 nonaka sc->sc_ih = pci_intr_establish_xname(sc->sc_pct, sc->sc_pihp[0],
9016 1.49 nonaka IPL_NET, iwm_intr, sc, device_xname(self));
9017 1.1 pooka if (sc->sc_ih == NULL) {
9018 1.3 nonaka aprint_error_dev(self, "can't establish interrupt");
9019 1.1 pooka if (intrstr != NULL)
9020 1.3 nonaka aprint_error(" at %s", intrstr);
9021 1.3 nonaka aprint_error("\n");
9022 1.1 pooka return;
9023 1.1 pooka }
9024 1.3 nonaka aprint_normal_dev(self, "interrupting at %s\n", intrstr);
9025 1.1 pooka
9026 1.45 nonaka sc->sc_hw_rev = IWM_READ(sc, IWM_CSR_HW_REV);
9027 1.5 nonaka switch (PCI_PRODUCT(sc->sc_pciid)) {
9028 1.45 nonaka case PCI_PRODUCT_INTEL_WIFI_LINK_3160_1:
9029 1.45 nonaka case PCI_PRODUCT_INTEL_WIFI_LINK_3160_2:
9030 1.71 nonaka sc->sc_fwname = "iwlwifi-3160-17.ucode";
9031 1.45 nonaka sc->host_interrupt_operation_mode = 1;
9032 1.59 nonaka sc->apmg_wake_up_wa = 1;
9033 1.45 nonaka sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
9034 1.45 nonaka sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
9035 1.91 mlelstv sc->nvm_type = IWM_NVM;
9036 1.45 nonaka break;
9037 1.45 nonaka case PCI_PRODUCT_INTEL_WIFI_LINK_3165_1:
9038 1.45 nonaka case PCI_PRODUCT_INTEL_WIFI_LINK_3165_2:
9039 1.91 mlelstv #if 0
9040 1.91 mlelstv /* 7265D-29 */
9041 1.91 mlelstv sc->sc_fwname = "iwlwifi-7265D-29.ucode";
9042 1.91 mlelstv #else
9043 1.91 mlelstv /* 7265D-22 */
9044 1.71 nonaka sc->sc_fwname = "iwlwifi-7265D-22.ucode";
9045 1.91 mlelstv #endif
9046 1.71 nonaka sc->host_interrupt_operation_mode = 0;
9047 1.71 nonaka sc->apmg_wake_up_wa = 1;
9048 1.71 nonaka sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
9049 1.71 nonaka sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
9050 1.91 mlelstv sc->nvm_type = IWM_NVM;
9051 1.71 nonaka break;
9052 1.71 nonaka case PCI_PRODUCT_INTEL_WIFI_LINK_3168:
9053 1.91 mlelstv sc->sc_fwname = "iwlwifi-3168-29.ucode";
9054 1.45 nonaka sc->host_interrupt_operation_mode = 0;
9055 1.59 nonaka sc->apmg_wake_up_wa = 1;
9056 1.45 nonaka sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
9057 1.45 nonaka sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
9058 1.91 mlelstv sc->nvm_type = IWM_NVM_SDP;
9059 1.45 nonaka break;
9060 1.5 nonaka case PCI_PRODUCT_INTEL_WIFI_LINK_7260_1:
9061 1.5 nonaka case PCI_PRODUCT_INTEL_WIFI_LINK_7260_2:
9062 1.71 nonaka sc->sc_fwname = "iwlwifi-7260-17.ucode";
9063 1.17 nonaka sc->host_interrupt_operation_mode = 1;
9064 1.59 nonaka sc->apmg_wake_up_wa = 1;
9065 1.45 nonaka sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
9066 1.45 nonaka sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
9067 1.91 mlelstv sc->nvm_type = IWM_NVM;
9068 1.5 nonaka break;
9069 1.5 nonaka case PCI_PRODUCT_INTEL_WIFI_LINK_7265_1:
9070 1.5 nonaka case PCI_PRODUCT_INTEL_WIFI_LINK_7265_2:
9071 1.45 nonaka sc->sc_fwname = (sc->sc_hw_rev & IWM_CSR_HW_REV_TYPE_MSK) ==
9072 1.45 nonaka IWM_CSR_HW_REV_TYPE_7265D ?
9073 1.91 mlelstv #if 0
9074 1.91 mlelstv /* 7265D-29 */
9075 1.91 mlelstv "iwlwifi-7265D-29.ucode": "iwlwifi-7265-17.ucode";
9076 1.91 mlelstv #else
9077 1.91 mlelstv /* 7265D-22 */
9078 1.71 nonaka "iwlwifi-7265D-22.ucode": "iwlwifi-7265-17.ucode";
9079 1.91 mlelstv #endif
9080 1.45 nonaka sc->host_interrupt_operation_mode = 0;
9081 1.59 nonaka sc->apmg_wake_up_wa = 1;
9082 1.45 nonaka sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
9083 1.45 nonaka sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
9084 1.91 mlelstv sc->nvm_type = IWM_NVM;
9085 1.45 nonaka break;
9086 1.45 nonaka case PCI_PRODUCT_INTEL_WIFI_LINK_8260_1:
9087 1.45 nonaka case PCI_PRODUCT_INTEL_WIFI_LINK_8260_2:
9088 1.58 nonaka case PCI_PRODUCT_INTEL_WIFI_LINK_4165_1:
9089 1.58 nonaka case PCI_PRODUCT_INTEL_WIFI_LINK_4165_2:
9090 1.91 mlelstv #if 0
9091 1.91 mlelstv /* 8000C-36 */
9092 1.91 mlelstv sc->sc_fwname = "iwlwifi-8000C-36.ucode";
9093 1.91 mlelstv #else
9094 1.91 mlelstv /* 8000C-22 */
9095 1.71 nonaka sc->sc_fwname = "iwlwifi-8000C-22.ucode";
9096 1.91 mlelstv #endif
9097 1.71 nonaka sc->host_interrupt_operation_mode = 0;
9098 1.71 nonaka sc->apmg_wake_up_wa = 0;
9099 1.71 nonaka sc->sc_device_family = IWM_DEVICE_FAMILY_8000;
9100 1.71 nonaka sc->sc_fwdmasegsz = IWM_FWDMASEGSZ_8000;
9101 1.91 mlelstv sc->nvm_type = IWM_NVM_EXT;
9102 1.71 nonaka break;
9103 1.71 nonaka case PCI_PRODUCT_INTEL_WIFI_LINK_8265:
9104 1.91 mlelstv #if 0
9105 1.91 mlelstv /* 8265-36 */
9106 1.91 mlelstv sc->sc_fwname = "iwlwifi-8265-36.ucode";
9107 1.91 mlelstv #else
9108 1.91 mlelstv /* 8265-22 */
9109 1.71 nonaka sc->sc_fwname = "iwlwifi-8265-22.ucode";
9110 1.91 mlelstv #endif
9111 1.17 nonaka sc->host_interrupt_operation_mode = 0;
9112 1.59 nonaka sc->apmg_wake_up_wa = 0;
9113 1.45 nonaka sc->sc_device_family = IWM_DEVICE_FAMILY_8000;
9114 1.45 nonaka sc->sc_fwdmasegsz = IWM_FWDMASEGSZ_8000;
9115 1.91 mlelstv sc->nvm_type = IWM_NVM_EXT;
9116 1.5 nonaka break;
9117 1.91 mlelstv /* INTEL_WL_9560 -> 9000-46 */
9118 1.5 nonaka default:
9119 1.5 nonaka aprint_error_dev(self, "unknown product %#x",
9120 1.5 nonaka PCI_PRODUCT(sc->sc_pciid));
9121 1.5 nonaka return;
9122 1.5 nonaka }
9123 1.5 nonaka DPRINTF(("%s: firmware=%s\n", DEVNAME(sc), sc->sc_fwname));
9124 1.2 nonaka
9125 1.2 nonaka /*
9126 1.45 nonaka * In the 8000 HW family the format of the 4 bytes of CSR_HW_REV have
9127 1.45 nonaka * changed, and now the revision step also includes bit 0-1 (no more
9128 1.45 nonaka * "dash" value). To keep hw_rev backwards compatible - we'll store it
9129 1.45 nonaka * in the old format.
9130 1.2 nonaka */
9131 1.2 nonaka
9132 1.45 nonaka if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000)
9133 1.45 nonaka sc->sc_hw_rev = (sc->sc_hw_rev & 0xfff0) |
9134 1.45 nonaka (IWM_CSR_HW_REV_STEP(sc->sc_hw_rev << 2) << 2);
9135 1.45 nonaka
9136 1.2 nonaka if (iwm_prepare_card_hw(sc) != 0) {
9137 1.3 nonaka aprint_error_dev(sc->sc_dev, "could not initialize hardware\n");
9138 1.2 nonaka return;
9139 1.2 nonaka }
9140 1.2 nonaka
9141 1.45 nonaka if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000) {
9142 1.45 nonaka uint32_t hw_step;
9143 1.45 nonaka
9144 1.45 nonaka /*
9145 1.45 nonaka * In order to recognize C step the driver should read the
9146 1.45 nonaka * chip version id located at the AUX bus MISC address.
9147 1.45 nonaka */
9148 1.45 nonaka IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
9149 1.45 nonaka IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
9150 1.45 nonaka DELAY(2);
9151 1.45 nonaka
9152 1.45 nonaka err = iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
9153 1.45 nonaka IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
9154 1.45 nonaka IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
9155 1.45 nonaka 25000);
9156 1.45 nonaka if (!err) {
9157 1.45 nonaka aprint_error_dev(sc->sc_dev,
9158 1.45 nonaka "failed to wake up the nic\n");
9159 1.45 nonaka return;
9160 1.45 nonaka }
9161 1.45 nonaka
9162 1.45 nonaka if (iwm_nic_lock(sc)) {
9163 1.45 nonaka hw_step = iwm_read_prph(sc, IWM_WFPM_CTRL_REG);
9164 1.45 nonaka hw_step |= IWM_ENABLE_WFPM;
9165 1.45 nonaka iwm_write_prph(sc, IWM_WFPM_CTRL_REG, hw_step);
9166 1.45 nonaka hw_step = iwm_read_prph(sc, IWM_AUX_MISC_REG);
9167 1.45 nonaka hw_step = (hw_step >> IWM_HW_STEP_LOCATION_BITS) & 0xF;
9168 1.45 nonaka if (hw_step == 0x3)
9169 1.45 nonaka sc->sc_hw_rev = (sc->sc_hw_rev & 0xFFFFFFF3) |
9170 1.45 nonaka (IWM_SILICON_C_STEP << 2);
9171 1.45 nonaka iwm_nic_unlock(sc);
9172 1.45 nonaka } else {
9173 1.45 nonaka aprint_error_dev(sc->sc_dev,
9174 1.45 nonaka "failed to lock the nic\n");
9175 1.45 nonaka return;
9176 1.45 nonaka }
9177 1.45 nonaka }
9178 1.45 nonaka
9179 1.45 nonaka /*
9180 1.45 nonaka * Allocate DMA memory for firmware transfers.
9181 1.45 nonaka * Must be aligned on a 16-byte boundary.
9182 1.45 nonaka */
9183 1.45 nonaka err = iwm_dma_contig_alloc(sc->sc_dmat, &sc->fw_dma, sc->sc_fwdmasegsz,
9184 1.45 nonaka 16);
9185 1.45 nonaka if (err) {
9186 1.3 nonaka aprint_error_dev(sc->sc_dev,
9187 1.3 nonaka "could not allocate memory for firmware\n");
9188 1.2 nonaka return;
9189 1.2 nonaka }
9190 1.2 nonaka
9191 1.45 nonaka /* Allocate "Keep Warm" page, used internally by the card. */
9192 1.45 nonaka err = iwm_dma_contig_alloc(sc->sc_dmat, &sc->kw_dma, 4096, 4096);
9193 1.45 nonaka if (err) {
9194 1.3 nonaka aprint_error_dev(sc->sc_dev,
9195 1.3 nonaka "could not allocate keep warm page\n");
9196 1.2 nonaka goto fail1;
9197 1.2 nonaka }
9198 1.2 nonaka
9199 1.45 nonaka /* Allocate interrupt cause table (ICT).*/
9200 1.45 nonaka err = iwm_dma_contig_alloc(sc->sc_dmat, &sc->ict_dma, IWM_ICT_SIZE,
9201 1.45 nonaka 1 << IWM_ICT_PADDR_SHIFT);
9202 1.45 nonaka if (err) {
9203 1.3 nonaka aprint_error_dev(sc->sc_dev, "could not allocate ICT table\n");
9204 1.2 nonaka goto fail2;
9205 1.2 nonaka }
9206 1.2 nonaka
9207 1.45 nonaka /* TX scheduler rings must be aligned on a 1KB boundary. */
9208 1.45 nonaka err = iwm_dma_contig_alloc(sc->sc_dmat, &sc->sched_dma,
9209 1.45 nonaka __arraycount(sc->txq) * sizeof(struct iwm_agn_scd_bc_tbl), 1024);
9210 1.45 nonaka if (err) {
9211 1.3 nonaka aprint_error_dev(sc->sc_dev,
9212 1.3 nonaka "could not allocate TX scheduler rings\n");
9213 1.2 nonaka goto fail3;
9214 1.2 nonaka }
9215 1.2 nonaka
9216 1.2 nonaka for (txq_i = 0; txq_i < __arraycount(sc->txq); txq_i++) {
9217 1.45 nonaka err = iwm_alloc_tx_ring(sc, &sc->txq[txq_i], txq_i);
9218 1.45 nonaka if (err) {
9219 1.3 nonaka aprint_error_dev(sc->sc_dev,
9220 1.3 nonaka "could not allocate TX ring %d\n", txq_i);
9221 1.2 nonaka goto fail4;
9222 1.2 nonaka }
9223 1.2 nonaka }
9224 1.2 nonaka
9225 1.45 nonaka err = iwm_alloc_rx_ring(sc, &sc->rxq);
9226 1.45 nonaka if (err) {
9227 1.3 nonaka aprint_error_dev(sc->sc_dev, "could not allocate RX ring\n");
9228 1.76 msaitoh goto fail5;
9229 1.2 nonaka }
9230 1.2 nonaka
9231 1.2 nonaka /* Clear pending interrupts. */
9232 1.2 nonaka IWM_WRITE(sc, IWM_CSR_INT, 0xffffffff);
9233 1.2 nonaka
9234 1.45 nonaka if ((err = sysctl_createv(&sc->sc_clog, 0, NULL, &node,
9235 1.36 nonaka 0, CTLTYPE_NODE, device_xname(sc->sc_dev),
9236 1.36 nonaka SYSCTL_DESCR("iwm per-controller controls"),
9237 1.36 nonaka NULL, 0, NULL, 0,
9238 1.36 nonaka CTL_HW, iwm_sysctl_root_num, CTL_CREATE,
9239 1.36 nonaka CTL_EOL)) != 0) {
9240 1.36 nonaka aprint_normal_dev(sc->sc_dev,
9241 1.36 nonaka "couldn't create iwm per-controller sysctl node\n");
9242 1.36 nonaka }
9243 1.45 nonaka if (err == 0) {
9244 1.36 nonaka int iwm_nodenum = node->sysctl_num;
9245 1.36 nonaka
9246 1.36 nonaka /* Reload firmware sysctl node */
9247 1.45 nonaka if ((err = sysctl_createv(&sc->sc_clog, 0, NULL, &node,
9248 1.36 nonaka CTLFLAG_READWRITE, CTLTYPE_INT, "fw_loaded",
9249 1.36 nonaka SYSCTL_DESCR("Reload firmware"),
9250 1.36 nonaka iwm_sysctl_fw_loaded_handler, 0, (void *)sc, 0,
9251 1.36 nonaka CTL_HW, iwm_sysctl_root_num, iwm_nodenum, CTL_CREATE,
9252 1.36 nonaka CTL_EOL)) != 0) {
9253 1.36 nonaka aprint_normal_dev(sc->sc_dev,
9254 1.36 nonaka "couldn't create load_fw sysctl node\n");
9255 1.36 nonaka }
9256 1.36 nonaka }
9257 1.36 nonaka
9258 1.87 riastrad callout_init(&sc->sc_calib_to, 0);
9259 1.87 riastrad callout_setfunc(&sc->sc_calib_to, iwm_calib_timeout, sc);
9260 1.87 riastrad callout_init(&sc->sc_led_blink_to, 0);
9261 1.87 riastrad callout_setfunc(&sc->sc_led_blink_to, iwm_led_blink_timeout, sc);
9262 1.91 mlelstv
9263 1.87 riastrad if (workqueue_create(&sc->sc_setratewq, "iwmsr",
9264 1.91 mlelstv iwm_setrates_cb, sc, PRI_NONE, IPL_NET, 0))
9265 1.87 riastrad panic("%s: could not create workqueue: setrates",
9266 1.87 riastrad device_xname(self));
9267 1.91 mlelstv
9268 1.91 mlelstv #ifndef IEEE80211_NO_HT
9269 1.87 riastrad if (workqueue_create(&sc->sc_bawq, "iwmba",
9270 1.91 mlelstv iwm_ba_cb, sc, PRI_NONE, IPL_NET, 0))
9271 1.87 riastrad panic("%s: could not create workqueue: blockack",
9272 1.87 riastrad device_xname(self));
9273 1.87 riastrad if (workqueue_create(&sc->sc_htprowq, "iwmhtpro",
9274 1.91 mlelstv iwm_htprot_cb, sc, PRI_NONE, IPL_NET, 0))
9275 1.87 riastrad panic("%s: could not create workqueue: htprot",
9276 1.87 riastrad device_xname(self));
9277 1.87 riastrad #endif
9278 1.87 riastrad
9279 1.87 riastrad /*
9280 1.87 riastrad * We can't do normal attach before the file system is mounted
9281 1.87 riastrad * because we cannot read the MAC address without loading the
9282 1.87 riastrad * firmware from disk. So we postpone until mountroot is done.
9283 1.87 riastrad * Notably, this will require a full driver unload/load cycle
9284 1.87 riastrad * (or reboot) in case the firmware is not present when the
9285 1.87 riastrad * hook runs.
9286 1.87 riastrad */
9287 1.87 riastrad config_mountroot(self, iwm_attach_hook);
9288 1.87 riastrad
9289 1.87 riastrad return;
9290 1.87 riastrad
9291 1.87 riastrad fail5: while (--txq_i >= 0)
9292 1.87 riastrad iwm_free_tx_ring(sc, &sc->txq[txq_i]);
9293 1.87 riastrad fail4: iwm_dma_contig_free(&sc->sched_dma);
9294 1.87 riastrad fail3: if (sc->ict_dma.vaddr != NULL)
9295 1.87 riastrad iwm_dma_contig_free(&sc->ict_dma);
9296 1.87 riastrad fail2: iwm_dma_contig_free(&sc->kw_dma);
9297 1.87 riastrad fail1: iwm_dma_contig_free(&sc->fw_dma);
9298 1.87 riastrad }
9299 1.87 riastrad
9300 1.87 riastrad static int
9301 1.87 riastrad iwm_config_complete(struct iwm_softc *sc)
9302 1.87 riastrad {
9303 1.87 riastrad device_t self = sc->sc_dev;
9304 1.87 riastrad struct ieee80211com *ic = &sc->sc_ic;
9305 1.87 riastrad struct ifnet *ifp = &sc->sc_ec.ec_if;
9306 1.87 riastrad int err;
9307 1.87 riastrad
9308 1.87 riastrad KASSERT(!ISSET(sc->sc_flags, IWM_FLAG_ATTACHED));
9309 1.87 riastrad
9310 1.91 mlelstv err = iwm_preinit(sc, true);
9311 1.87 riastrad if (err)
9312 1.87 riastrad return err;
9313 1.87 riastrad
9314 1.36 nonaka /*
9315 1.36 nonaka * Attach interface
9316 1.36 nonaka */
9317 1.36 nonaka ic->ic_ifp = ifp;
9318 1.36 nonaka ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
9319 1.36 nonaka ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
9320 1.36 nonaka ic->ic_state = IEEE80211_S_INIT;
9321 1.36 nonaka
9322 1.36 nonaka /* Set device capabilities. */
9323 1.36 nonaka ic->ic_caps =
9324 1.36 nonaka IEEE80211_C_WEP | /* WEP */
9325 1.36 nonaka IEEE80211_C_WPA | /* 802.11i */
9326 1.45 nonaka #ifdef notyet
9327 1.45 nonaka IEEE80211_C_SCANALL | /* device scans all channels at once */
9328 1.45 nonaka IEEE80211_C_SCANALLBAND | /* device scans all bands at once */
9329 1.45 nonaka #endif
9330 1.36 nonaka IEEE80211_C_SHSLOT | /* short slot time supported */
9331 1.36 nonaka IEEE80211_C_SHPREAMBLE; /* short preamble supported */
9332 1.36 nonaka
9333 1.45 nonaka #ifndef IEEE80211_NO_HT
9334 1.45 nonaka ic->ic_htcaps = IEEE80211_HTCAP_SGI20;
9335 1.45 nonaka ic->ic_htxcaps = 0;
9336 1.45 nonaka ic->ic_txbfcaps = 0;
9337 1.45 nonaka ic->ic_aselcaps = 0;
9338 1.45 nonaka ic->ic_ampdu_params = (IEEE80211_AMPDU_PARAM_SS_4 | 0x3 /* 64k */);
9339 1.45 nonaka #endif
9340 1.45 nonaka
9341 1.36 nonaka /* all hardware can do 2.4GHz band */
9342 1.36 nonaka ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
9343 1.36 nonaka ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
9344 1.36 nonaka
9345 1.87 riastrad /* not all hardware can do 5GHz band */
9346 1.87 riastrad if (sc->sc_nvm.sku_cap_band_52GHz_enable)
9347 1.87 riastrad ic->ic_sup_rates[IEEE80211_MODE_11A] = ieee80211_std_rateset_11a;
9348 1.87 riastrad
9349 1.87 riastrad #ifndef IEEE80211_NO_HT
9350 1.87 riastrad if (sc->sc_nvm.sku_cap_11n_enable)
9351 1.87 riastrad iwm_setup_ht_rates(sc);
9352 1.87 riastrad #endif
9353 1.87 riastrad
9354 1.36 nonaka for (int i = 0; i < __arraycount(sc->sc_phyctxt); i++) {
9355 1.36 nonaka sc->sc_phyctxt[i].id = i;
9356 1.36 nonaka }
9357 1.36 nonaka
9358 1.36 nonaka sc->sc_amrr.amrr_min_success_threshold = 1;
9359 1.36 nonaka sc->sc_amrr.amrr_max_success_threshold = 15;
9360 1.36 nonaka
9361 1.36 nonaka /* IBSS channel undefined for now. */
9362 1.36 nonaka ic->ic_ibss_chan = &ic->ic_channels[1];
9363 1.36 nonaka
9364 1.36 nonaka #if 0
9365 1.36 nonaka ic->ic_max_rssi = IWM_MAX_DBM - IWM_MIN_DBM;
9366 1.36 nonaka #endif
9367 1.36 nonaka
9368 1.36 nonaka ifp->if_softc = sc;
9369 1.36 nonaka ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
9370 1.36 nonaka ifp->if_init = iwm_init;
9371 1.36 nonaka ifp->if_stop = iwm_stop;
9372 1.36 nonaka ifp->if_ioctl = iwm_ioctl;
9373 1.36 nonaka ifp->if_start = iwm_start;
9374 1.36 nonaka ifp->if_watchdog = iwm_watchdog;
9375 1.36 nonaka IFQ_SET_READY(&ifp->if_snd);
9376 1.36 nonaka memcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
9377 1.36 nonaka
9378 1.86 riastrad if_initialize(ifp);
9379 1.36 nonaka ieee80211_ifattach(ic);
9380 1.40 ozaki /* Use common softint-based if_input */
9381 1.40 ozaki ifp->if_percpuq = if_percpuq_create(ifp);
9382 1.44 ozaki if_register(ifp);
9383 1.36 nonaka
9384 1.94 mlelstv iwm_claim_rx_ring(sc);
9385 1.94 mlelstv
9386 1.87 riastrad ic->ic_node_alloc = iwm_node_alloc;
9387 1.87 riastrad
9388 1.87 riastrad /* Override 802.11 state transition machine. */
9389 1.87 riastrad sc->sc_newstate = ic->ic_newstate;
9390 1.87 riastrad ic->ic_newstate = iwm_newstate;
9391 1.87 riastrad
9392 1.87 riastrad /* XXX media locking needs revisiting */
9393 1.87 riastrad mutex_init(&sc->sc_media_mtx, MUTEX_DEFAULT, IPL_SOFTNET);
9394 1.87 riastrad ieee80211_media_init_with_lock(ic,
9395 1.87 riastrad iwm_media_change, ieee80211_media_status, &sc->sc_media_mtx);
9396 1.87 riastrad
9397 1.87 riastrad ieee80211_announce(ic);
9398 1.87 riastrad
9399 1.87 riastrad iwm_radiotap_attach(sc);
9400 1.36 nonaka
9401 1.36 nonaka if (pmf_device_register(self, NULL, NULL))
9402 1.36 nonaka pmf_class_network_register(self, ifp);
9403 1.36 nonaka else
9404 1.36 nonaka aprint_error_dev(self, "couldn't establish power handler\n");
9405 1.36 nonaka
9406 1.87 riastrad sc->sc_flags |= IWM_FLAG_ATTACHED;
9407 1.2 nonaka
9408 1.87 riastrad return 0;
9409 1.1 pooka }
9410 1.1 pooka
9411 1.1 pooka void
9412 1.1 pooka iwm_radiotap_attach(struct iwm_softc *sc)
9413 1.1 pooka {
9414 1.47 nonaka struct ifnet *ifp = IC2IFP(&sc->sc_ic);
9415 1.1 pooka
9416 1.1 pooka bpf_attach2(ifp, DLT_IEEE802_11_RADIO,
9417 1.1 pooka sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN,
9418 1.1 pooka &sc->sc_drvbpf);
9419 1.1 pooka
9420 1.1 pooka sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
9421 1.1 pooka sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
9422 1.1 pooka sc->sc_rxtap.wr_ihdr.it_present = htole32(IWM_RX_RADIOTAP_PRESENT);
9423 1.1 pooka
9424 1.1 pooka sc->sc_txtap_len = sizeof sc->sc_txtapu;
9425 1.1 pooka sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
9426 1.1 pooka sc->sc_txtap.wt_ihdr.it_present = htole32(IWM_TX_RADIOTAP_PRESENT);
9427 1.1 pooka }
9428 1.1 pooka
9429 1.1 pooka #if 0
9430 1.4 nonaka static void
9431 1.47 nonaka iwm_init_task(void *arg)
9432 1.1 pooka {
9433 1.47 nonaka struct iwm_softc *sc = arg;
9434 1.47 nonaka struct ifnet *ifp = IC2IFP(&sc->sc_ic);
9435 1.1 pooka int s;
9436 1.8 nonaka
9437 1.45 nonaka rw_enter_write(&sc->ioctl_rwl);
9438 1.1 pooka s = splnet();
9439 1.8 nonaka
9440 1.1 pooka iwm_stop(ifp, 0);
9441 1.1 pooka if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP)
9442 1.1 pooka iwm_init(ifp);
9443 1.1 pooka
9444 1.1 pooka splx(s);
9445 1.45 nonaka rw_exit(&sc->ioctl_rwl);
9446 1.1 pooka }
9447 1.1 pooka
9448 1.4 nonaka static void
9449 1.1 pooka iwm_wakeup(struct iwm_softc *sc)
9450 1.1 pooka {
9451 1.1 pooka pcireg_t reg;
9452 1.1 pooka
9453 1.1 pooka /* Clear device-specific "PCI retry timeout" register (41h). */
9454 1.1 pooka reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
9455 1.1 pooka pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);
9456 1.1 pooka
9457 1.1 pooka iwm_init_task(sc);
9458 1.1 pooka }
9459 1.1 pooka
9460 1.4 nonaka static int
9461 1.4 nonaka iwm_activate(device_t self, enum devact act)
9462 1.1 pooka {
9463 1.4 nonaka struct iwm_softc *sc = device_private(self);
9464 1.4 nonaka struct ifnet *ifp = IC2IFP(&sc->sc_ic);
9465 1.1 pooka
9466 1.1 pooka switch (act) {
9467 1.4 nonaka case DVACT_DEACTIVATE:
9468 1.1 pooka if (ifp->if_flags & IFF_RUNNING)
9469 1.91 mlelstv iwm_stop(ifp, 1);
9470 1.4 nonaka return 0;
9471 1.4 nonaka default:
9472 1.4 nonaka return EOPNOTSUPP;
9473 1.1 pooka }
9474 1.1 pooka }
9475 1.1 pooka #endif
9476 1.1 pooka
9477 1.1 pooka CFATTACH_DECL_NEW(iwm, sizeof(struct iwm_softc), iwm_match, iwm_attach,
9478 1.1 pooka NULL, NULL);
9479 1.32 nonaka
9480 1.36 nonaka static int
9481 1.36 nonaka iwm_sysctl_fw_loaded_handler(SYSCTLFN_ARGS)
9482 1.36 nonaka {
9483 1.36 nonaka struct sysctlnode node;
9484 1.36 nonaka struct iwm_softc *sc;
9485 1.45 nonaka int err, t;
9486 1.36 nonaka
9487 1.36 nonaka node = *rnode;
9488 1.36 nonaka sc = node.sysctl_data;
9489 1.36 nonaka t = ISSET(sc->sc_flags, IWM_FLAG_FW_LOADED) ? 1 : 0;
9490 1.36 nonaka node.sysctl_data = &t;
9491 1.45 nonaka err = sysctl_lookup(SYSCTLFN_CALL(&node));
9492 1.45 nonaka if (err || newp == NULL)
9493 1.45 nonaka return err;
9494 1.36 nonaka
9495 1.36 nonaka if (t == 0)
9496 1.36 nonaka CLR(sc->sc_flags, IWM_FLAG_FW_LOADED);
9497 1.36 nonaka return 0;
9498 1.36 nonaka }
9499 1.36 nonaka
9500 1.32 nonaka SYSCTL_SETUP(sysctl_iwm, "sysctl iwm(4) subtree setup")
9501 1.32 nonaka {
9502 1.36 nonaka const struct sysctlnode *rnode;
9503 1.36 nonaka #ifdef IWM_DEBUG
9504 1.36 nonaka const struct sysctlnode *cnode;
9505 1.36 nonaka #endif /* IWM_DEBUG */
9506 1.32 nonaka int rc;
9507 1.32 nonaka
9508 1.32 nonaka if ((rc = sysctl_createv(clog, 0, NULL, &rnode,
9509 1.32 nonaka CTLFLAG_PERMANENT, CTLTYPE_NODE, "iwm",
9510 1.32 nonaka SYSCTL_DESCR("iwm global controls"),
9511 1.32 nonaka NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0)
9512 1.32 nonaka goto err;
9513 1.32 nonaka
9514 1.36 nonaka iwm_sysctl_root_num = rnode->sysctl_num;
9515 1.36 nonaka
9516 1.36 nonaka #ifdef IWM_DEBUG
9517 1.32 nonaka /* control debugging printfs */
9518 1.32 nonaka if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
9519 1.32 nonaka CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
9520 1.32 nonaka "debug", SYSCTL_DESCR("Enable debugging output"),
9521 1.32 nonaka NULL, 0, &iwm_debug, 0, CTL_CREATE, CTL_EOL)) != 0)
9522 1.32 nonaka goto err;
9523 1.36 nonaka #endif /* IWM_DEBUG */
9524 1.32 nonaka
9525 1.32 nonaka return;
9526 1.32 nonaka
9527 1.32 nonaka err:
9528 1.32 nonaka aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
9529 1.32 nonaka }
9530