Tue Jun 5 12:17:18 2018 UTC ()
Fix panic on boot with iwm(4). Advised by nonaka@n.o, thanks.

XXX pullup-8


(knakahara)
diff -r1.78 -r1.79 src/sys/dev/pci/if_iwm.c

cvs diff -r1.78 -r1.79 src/sys/dev/pci/if_iwm.c (switch to unified diff)

--- src/sys/dev/pci/if_iwm.c 2018/01/21 18:12:37 1.78
+++ src/sys/dev/pci/if_iwm.c 2018/06/05 12:17:18 1.79
@@ -1,1108 +1,1108 @@ @@ -1,1108 +1,1108 @@
1/* $NetBSD: if_iwm.c,v 1.78 2018/01/21 18:12:37 christos Exp $ */ 1/* $NetBSD: if_iwm.c,v 1.79 2018/06/05 12:17:18 knakahara Exp $ */
2/* OpenBSD: if_iwm.c,v 1.148 2016/11/19 21:07:08 stsp Exp */ 2/* OpenBSD: if_iwm.c,v 1.148 2016/11/19 21:07:08 stsp Exp */
3#define IEEE80211_NO_HT 3#define IEEE80211_NO_HT
4/* 4/*
5 * Copyright (c) 2014, 2016 genua gmbh <info@genua.de> 5 * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
6 * Author: Stefan Sperling <stsp@openbsd.org> 6 * Author: Stefan Sperling <stsp@openbsd.org>
7 * Copyright (c) 2014 Fixup Software Ltd. 7 * Copyright (c) 2014 Fixup Software Ltd.
8 * 8 *
9 * Permission to use, copy, modify, and distribute this software for any 9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above 10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies. 11 * copyright notice and this permission notice appear in all copies.
12 * 12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */ 20 */
21 21
22/*- 22/*-
23 * Based on BSD-licensed source modules in the Linux iwlwifi driver, 23 * Based on BSD-licensed source modules in the Linux iwlwifi driver,
24 * which were used as the reference documentation for this implementation. 24 * which were used as the reference documentation for this implementation.
25 * 25 *
26 *********************************************************************** 26 ***********************************************************************
27 * 27 *
28 * This file is provided under a dual BSD/GPLv2 license. When using or 28 * This file is provided under a dual BSD/GPLv2 license. When using or
29 * redistributing this file, you may do so under either license. 29 * redistributing this file, you may do so under either license.
30 * 30 *
31 * GPL LICENSE SUMMARY 31 * GPL LICENSE SUMMARY
32 * 32 *
33 * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. 33 * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
34 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH 34 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
35 * Copyright(c) 2016 Intel Deutschland GmbH 35 * Copyright(c) 2016 Intel Deutschland GmbH
36 * 36 *
37 * This program is free software; you can redistribute it and/or modify 37 * This program is free software; you can redistribute it and/or modify
38 * it under the terms of version 2 of the GNU General Public License as 38 * it under the terms of version 2 of the GNU General Public License as
39 * published by the Free Software Foundation. 39 * published by the Free Software Foundation.
40 * 40 *
41 * This program is distributed in the hope that it will be useful, but 41 * This program is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of 42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details. 44 * General Public License for more details.
45 * 45 *
46 * You should have received a copy of the GNU General Public License 46 * You should have received a copy of the GNU General Public License
47 * along with this program; if not, write to the Free Software 47 * along with this program; if not, write to the Free Software
48 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, 48 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
49 * USA 49 * USA
50 * 50 *
51 * The full GNU General Public License is included in this distribution 51 * The full GNU General Public License is included in this distribution
52 * in the file called COPYING. 52 * in the file called COPYING.
53 * 53 *
54 * Contact Information: 54 * Contact Information:
55 * Intel Linux Wireless <linuxwifi@intel.com> 55 * Intel Linux Wireless <linuxwifi@intel.com>
56 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 56 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
57 * 57 *
58 * BSD LICENSE 58 * BSD LICENSE
59 * 59 *
60 * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. 60 * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
61 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH 61 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
62 * Copyright(c) 2016 Intel Deutschland GmbH 62 * Copyright(c) 2016 Intel Deutschland GmbH
63 * All rights reserved. 63 * All rights reserved.
64 * 64 *
65 * Redistribution and use in source and binary forms, with or without 65 * Redistribution and use in source and binary forms, with or without
66 * modification, are permitted provided that the following conditions 66 * modification, are permitted provided that the following conditions
67 * are met: 67 * are met:
68 * 68 *
69 * * Redistributions of source code must retain the above copyright 69 * * Redistributions of source code must retain the above copyright
70 * notice, this list of conditions and the following disclaimer. 70 * notice, this list of conditions and the following disclaimer.
71 * * Redistributions in binary form must reproduce the above copyright 71 * * Redistributions in binary form must reproduce the above copyright
72 * notice, this list of conditions and the following disclaimer in 72 * notice, this list of conditions and the following disclaimer in
73 * the documentation and/or other materials provided with the 73 * the documentation and/or other materials provided with the
74 * distribution. 74 * distribution.
75 * * Neither the name Intel Corporation nor the names of its 75 * * Neither the name Intel Corporation nor the names of its
76 * contributors may be used to endorse or promote products derived 76 * contributors may be used to endorse or promote products derived
77 * from this software without specific prior written permission. 77 * from this software without specific prior written permission.
78 * 78 *
79 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 79 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
80 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 80 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
81 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 81 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
82 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 82 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
83 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 83 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
84 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 84 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
85 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 85 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
86 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 86 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
87 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 87 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
88 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 88 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
89 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 89 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
90 */ 90 */
91 91
92/*- 92/*-
93 * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr> 93 * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
94 * 94 *
95 * Permission to use, copy, modify, and distribute this software for any 95 * Permission to use, copy, modify, and distribute this software for any
96 * purpose with or without fee is hereby granted, provided that the above 96 * purpose with or without fee is hereby granted, provided that the above
97 * copyright notice and this permission notice appear in all copies. 97 * copyright notice and this permission notice appear in all copies.
98 * 98 *
99 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 99 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
100 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 100 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
101 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 101 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
102 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 102 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
103 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 103 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
104 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 104 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
105 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 105 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
106 */ 106 */
107 107
108#include <sys/cdefs.h> 108#include <sys/cdefs.h>
109__KERNEL_RCSID(0, "$NetBSD: if_iwm.c,v 1.78 2018/01/21 18:12:37 christos Exp $"); 109__KERNEL_RCSID(0, "$NetBSD: if_iwm.c,v 1.79 2018/06/05 12:17:18 knakahara Exp $");
110 110
111#include <sys/param.h> 111#include <sys/param.h>
112#include <sys/conf.h> 112#include <sys/conf.h>
113#include <sys/kernel.h> 113#include <sys/kernel.h>
114#include <sys/kmem.h> 114#include <sys/kmem.h>
115#include <sys/mbuf.h> 115#include <sys/mbuf.h>
116#include <sys/mutex.h> 116#include <sys/mutex.h>
117#include <sys/proc.h> 117#include <sys/proc.h>
118#include <sys/socket.h> 118#include <sys/socket.h>
119#include <sys/sockio.h> 119#include <sys/sockio.h>
120#include <sys/sysctl.h> 120#include <sys/sysctl.h>
121#include <sys/systm.h> 121#include <sys/systm.h>
122 122
123#include <sys/cpu.h> 123#include <sys/cpu.h>
124#include <sys/bus.h> 124#include <sys/bus.h>
125#include <sys/workqueue.h> 125#include <sys/workqueue.h>
126#include <machine/endian.h> 126#include <machine/endian.h>
127#include <sys/intr.h> 127#include <sys/intr.h>
128 128
129#include <dev/pci/pcireg.h> 129#include <dev/pci/pcireg.h>
130#include <dev/pci/pcivar.h> 130#include <dev/pci/pcivar.h>
131#include <dev/pci/pcidevs.h> 131#include <dev/pci/pcidevs.h>
132#include <dev/firmload.h> 132#include <dev/firmload.h>
133 133
134#include <net/bpf.h> 134#include <net/bpf.h>
135#include <net/if.h> 135#include <net/if.h>
136#include <net/if_dl.h> 136#include <net/if_dl.h>
137#include <net/if_media.h> 137#include <net/if_media.h>
138#include <net/if_ether.h> 138#include <net/if_ether.h>
139 139
140#include <netinet/in.h> 140#include <netinet/in.h>
141#include <netinet/ip.h> 141#include <netinet/ip.h>
142 142
143#include <net80211/ieee80211_var.h> 143#include <net80211/ieee80211_var.h>
144#include <net80211/ieee80211_amrr.h> 144#include <net80211/ieee80211_amrr.h>
145#include <net80211/ieee80211_radiotap.h> 145#include <net80211/ieee80211_radiotap.h>
146 146
147#define DEVNAME(_s) device_xname((_s)->sc_dev) 147#define DEVNAME(_s) device_xname((_s)->sc_dev)
148#define IC2IFP(_ic_) ((_ic_)->ic_ifp) 148#define IC2IFP(_ic_) ((_ic_)->ic_ifp)
149 149
150#define le16_to_cpup(_a_) (le16toh(*(const uint16_t *)(_a_))) 150#define le16_to_cpup(_a_) (le16toh(*(const uint16_t *)(_a_)))
151#define le32_to_cpup(_a_) (le32toh(*(const uint32_t *)(_a_))) 151#define le32_to_cpup(_a_) (le32toh(*(const uint32_t *)(_a_)))
152 152
153#ifdef IWM_DEBUG 153#ifdef IWM_DEBUG
154#define DPRINTF(x) do { if (iwm_debug > 0) printf x; } while (0) 154#define DPRINTF(x) do { if (iwm_debug > 0) printf x; } while (0)
155#define DPRINTFN(n, x) do { if (iwm_debug >= (n)) printf x; } while (0) 155#define DPRINTFN(n, x) do { if (iwm_debug >= (n)) printf x; } while (0)
156int iwm_debug = 0; 156int iwm_debug = 0;
157#else 157#else
158#define DPRINTF(x) do { ; } while (0) 158#define DPRINTF(x) do { ; } while (0)
159#define DPRINTFN(n, x) do { ; } while (0) 159#define DPRINTFN(n, x) do { ; } while (0)
160#endif 160#endif
161 161
162#include <dev/pci/if_iwmreg.h> 162#include <dev/pci/if_iwmreg.h>
163#include <dev/pci/if_iwmvar.h> 163#include <dev/pci/if_iwmvar.h>
164 164
165static const uint8_t iwm_nvm_channels[] = { 165static const uint8_t iwm_nvm_channels[] = {
166 /* 2.4 GHz */ 166 /* 2.4 GHz */
167 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 167 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
168 /* 5 GHz */ 168 /* 5 GHz */
169 36, 40, 44, 48, 52, 56, 60, 64, 169 36, 40, 44, 48, 52, 56, 60, 64,
170 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 170 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
171 149, 153, 157, 161, 165 171 149, 153, 157, 161, 165
172}; 172};
173 173
174static const uint8_t iwm_nvm_channels_8000[] = { 174static const uint8_t iwm_nvm_channels_8000[] = {
175 /* 2.4 GHz */ 175 /* 2.4 GHz */
176 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 176 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
177 /* 5 GHz */ 177 /* 5 GHz */
178 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 178 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92,
179 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 179 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
180 149, 153, 157, 161, 165, 169, 173, 177, 181 180 149, 153, 157, 161, 165, 169, 173, 177, 181
181}; 181};
182 182
183#define IWM_NUM_2GHZ_CHANNELS 14 183#define IWM_NUM_2GHZ_CHANNELS 14
184 184
185static const struct iwm_rate { 185static const struct iwm_rate {
186 uint8_t rate; 186 uint8_t rate;
187 uint8_t plcp; 187 uint8_t plcp;
188 uint8_t ht_plcp; 188 uint8_t ht_plcp;
189} iwm_rates[] = { 189} iwm_rates[] = {
190 /* Legacy */ /* HT */ 190 /* Legacy */ /* HT */
191 { 2, IWM_RATE_1M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP }, 191 { 2, IWM_RATE_1M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP },
192 { 4, IWM_RATE_2M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP }, 192 { 4, IWM_RATE_2M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP },
193 { 11, IWM_RATE_5M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP }, 193 { 11, IWM_RATE_5M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP },
194 { 22, IWM_RATE_11M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP }, 194 { 22, IWM_RATE_11M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP },
195 { 12, IWM_RATE_6M_PLCP, IWM_RATE_HT_SISO_MCS_0_PLCP }, 195 { 12, IWM_RATE_6M_PLCP, IWM_RATE_HT_SISO_MCS_0_PLCP },
196 { 18, IWM_RATE_9M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP }, 196 { 18, IWM_RATE_9M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP },
197 { 24, IWM_RATE_12M_PLCP, IWM_RATE_HT_SISO_MCS_1_PLCP }, 197 { 24, IWM_RATE_12M_PLCP, IWM_RATE_HT_SISO_MCS_1_PLCP },
198 { 36, IWM_RATE_18M_PLCP, IWM_RATE_HT_SISO_MCS_2_PLCP }, 198 { 36, IWM_RATE_18M_PLCP, IWM_RATE_HT_SISO_MCS_2_PLCP },
199 { 48, IWM_RATE_24M_PLCP, IWM_RATE_HT_SISO_MCS_3_PLCP }, 199 { 48, IWM_RATE_24M_PLCP, IWM_RATE_HT_SISO_MCS_3_PLCP },
200 { 72, IWM_RATE_36M_PLCP, IWM_RATE_HT_SISO_MCS_4_PLCP }, 200 { 72, IWM_RATE_36M_PLCP, IWM_RATE_HT_SISO_MCS_4_PLCP },
201 { 96, IWM_RATE_48M_PLCP, IWM_RATE_HT_SISO_MCS_5_PLCP }, 201 { 96, IWM_RATE_48M_PLCP, IWM_RATE_HT_SISO_MCS_5_PLCP },
202 { 108, IWM_RATE_54M_PLCP, IWM_RATE_HT_SISO_MCS_6_PLCP }, 202 { 108, IWM_RATE_54M_PLCP, IWM_RATE_HT_SISO_MCS_6_PLCP },
203 { 128, IWM_RATE_INVM_PLCP, IWM_RATE_HT_SISO_MCS_7_PLCP }, 203 { 128, IWM_RATE_INVM_PLCP, IWM_RATE_HT_SISO_MCS_7_PLCP },
204}; 204};
205#define IWM_RIDX_CCK 0 205#define IWM_RIDX_CCK 0
206#define IWM_RIDX_OFDM 4 206#define IWM_RIDX_OFDM 4
207#define IWM_RIDX_MAX (__arraycount(iwm_rates)-1) 207#define IWM_RIDX_MAX (__arraycount(iwm_rates)-1)
208#define IWM_RIDX_IS_CCK(_i_) ((_i_) < IWM_RIDX_OFDM) 208#define IWM_RIDX_IS_CCK(_i_) ((_i_) < IWM_RIDX_OFDM)
209#define IWM_RIDX_IS_OFDM(_i_) ((_i_) >= IWM_RIDX_OFDM) 209#define IWM_RIDX_IS_OFDM(_i_) ((_i_) >= IWM_RIDX_OFDM)
210 210
211#ifndef IEEE80211_NO_HT 211#ifndef IEEE80211_NO_HT
212/* Convert an MCS index into an iwm_rates[] index. */ 212/* Convert an MCS index into an iwm_rates[] index. */
213static const int iwm_mcs2ridx[] = { 213static const int iwm_mcs2ridx[] = {
214 IWM_RATE_MCS_0_INDEX, 214 IWM_RATE_MCS_0_INDEX,
215 IWM_RATE_MCS_1_INDEX, 215 IWM_RATE_MCS_1_INDEX,
216 IWM_RATE_MCS_2_INDEX, 216 IWM_RATE_MCS_2_INDEX,
217 IWM_RATE_MCS_3_INDEX, 217 IWM_RATE_MCS_3_INDEX,
218 IWM_RATE_MCS_4_INDEX, 218 IWM_RATE_MCS_4_INDEX,
219 IWM_RATE_MCS_5_INDEX, 219 IWM_RATE_MCS_5_INDEX,
220 IWM_RATE_MCS_6_INDEX, 220 IWM_RATE_MCS_6_INDEX,
221 IWM_RATE_MCS_7_INDEX, 221 IWM_RATE_MCS_7_INDEX,
222}; 222};
223#endif 223#endif
224 224
225struct iwm_nvm_section { 225struct iwm_nvm_section {
226 uint16_t length; 226 uint16_t length;
227 uint8_t *data; 227 uint8_t *data;
228}; 228};
229 229
230struct iwm_newstate_state { 230struct iwm_newstate_state {
231 struct work ns_wk; 231 struct work ns_wk;
232 enum ieee80211_state ns_nstate; 232 enum ieee80211_state ns_nstate;
233 int ns_arg; 233 int ns_arg;
234 int ns_generation; 234 int ns_generation;
235}; 235};
236 236
237static int iwm_store_cscheme(struct iwm_softc *, uint8_t *, size_t); 237static int iwm_store_cscheme(struct iwm_softc *, uint8_t *, size_t);
238static int iwm_firmware_store_section(struct iwm_softc *, 238static int iwm_firmware_store_section(struct iwm_softc *,
239 enum iwm_ucode_type, uint8_t *, size_t); 239 enum iwm_ucode_type, uint8_t *, size_t);
240static int iwm_set_default_calib(struct iwm_softc *, const void *); 240static int iwm_set_default_calib(struct iwm_softc *, const void *);
241static int iwm_read_firmware(struct iwm_softc *, enum iwm_ucode_type); 241static int iwm_read_firmware(struct iwm_softc *, enum iwm_ucode_type);
242static uint32_t iwm_read_prph(struct iwm_softc *, uint32_t); 242static uint32_t iwm_read_prph(struct iwm_softc *, uint32_t);
243static void iwm_write_prph(struct iwm_softc *, uint32_t, uint32_t); 243static void iwm_write_prph(struct iwm_softc *, uint32_t, uint32_t);
244#ifdef IWM_DEBUG 244#ifdef IWM_DEBUG
245static int iwm_read_mem(struct iwm_softc *, uint32_t, void *, int); 245static int iwm_read_mem(struct iwm_softc *, uint32_t, void *, int);
246#endif 246#endif
247static int iwm_write_mem(struct iwm_softc *, uint32_t, const void *, int); 247static int iwm_write_mem(struct iwm_softc *, uint32_t, const void *, int);
248static int iwm_write_mem32(struct iwm_softc *, uint32_t, uint32_t); 248static int iwm_write_mem32(struct iwm_softc *, uint32_t, uint32_t);
249static int iwm_poll_bit(struct iwm_softc *, int, uint32_t, uint32_t, int); 249static int iwm_poll_bit(struct iwm_softc *, int, uint32_t, uint32_t, int);
250static int iwm_nic_lock(struct iwm_softc *); 250static int iwm_nic_lock(struct iwm_softc *);
251static void iwm_nic_unlock(struct iwm_softc *); 251static void iwm_nic_unlock(struct iwm_softc *);
252static void iwm_set_bits_mask_prph(struct iwm_softc *, uint32_t, uint32_t, 252static void iwm_set_bits_mask_prph(struct iwm_softc *, uint32_t, uint32_t,
253 uint32_t); 253 uint32_t);
254static void iwm_set_bits_prph(struct iwm_softc *, uint32_t, uint32_t); 254static void iwm_set_bits_prph(struct iwm_softc *, uint32_t, uint32_t);
255static void iwm_clear_bits_prph(struct iwm_softc *, uint32_t, uint32_t); 255static void iwm_clear_bits_prph(struct iwm_softc *, uint32_t, uint32_t);
256static int iwm_dma_contig_alloc(bus_dma_tag_t, struct iwm_dma_info *, 256static int iwm_dma_contig_alloc(bus_dma_tag_t, struct iwm_dma_info *,
257 bus_size_t, bus_size_t); 257 bus_size_t, bus_size_t);
258static void iwm_dma_contig_free(struct iwm_dma_info *); 258static void iwm_dma_contig_free(struct iwm_dma_info *);
259static int iwm_alloc_rx_ring(struct iwm_softc *, struct iwm_rx_ring *); 259static int iwm_alloc_rx_ring(struct iwm_softc *, struct iwm_rx_ring *);
260static void iwm_disable_rx_dma(struct iwm_softc *); 260static void iwm_disable_rx_dma(struct iwm_softc *);
261static void iwm_reset_rx_ring(struct iwm_softc *, struct iwm_rx_ring *); 261static void iwm_reset_rx_ring(struct iwm_softc *, struct iwm_rx_ring *);
262static void iwm_free_rx_ring(struct iwm_softc *, struct iwm_rx_ring *); 262static void iwm_free_rx_ring(struct iwm_softc *, struct iwm_rx_ring *);
263static int iwm_alloc_tx_ring(struct iwm_softc *, struct iwm_tx_ring *, 263static int iwm_alloc_tx_ring(struct iwm_softc *, struct iwm_tx_ring *,
264 int); 264 int);
265static void iwm_reset_tx_ring(struct iwm_softc *, struct iwm_tx_ring *); 265static void iwm_reset_tx_ring(struct iwm_softc *, struct iwm_tx_ring *);
266static void iwm_free_tx_ring(struct iwm_softc *, struct iwm_tx_ring *); 266static void iwm_free_tx_ring(struct iwm_softc *, struct iwm_tx_ring *);
267static void iwm_enable_rfkill_int(struct iwm_softc *); 267static void iwm_enable_rfkill_int(struct iwm_softc *);
268static int iwm_check_rfkill(struct iwm_softc *); 268static int iwm_check_rfkill(struct iwm_softc *);
269static void iwm_enable_interrupts(struct iwm_softc *); 269static void iwm_enable_interrupts(struct iwm_softc *);
270static void iwm_restore_interrupts(struct iwm_softc *); 270static void iwm_restore_interrupts(struct iwm_softc *);
271static void iwm_disable_interrupts(struct iwm_softc *); 271static void iwm_disable_interrupts(struct iwm_softc *);
272static void iwm_ict_reset(struct iwm_softc *); 272static void iwm_ict_reset(struct iwm_softc *);
273static int iwm_set_hw_ready(struct iwm_softc *); 273static int iwm_set_hw_ready(struct iwm_softc *);
274static int iwm_prepare_card_hw(struct iwm_softc *); 274static int iwm_prepare_card_hw(struct iwm_softc *);
275static void iwm_apm_config(struct iwm_softc *); 275static void iwm_apm_config(struct iwm_softc *);
276static int iwm_apm_init(struct iwm_softc *); 276static int iwm_apm_init(struct iwm_softc *);
277static void iwm_apm_stop(struct iwm_softc *); 277static void iwm_apm_stop(struct iwm_softc *);
278static int iwm_allow_mcast(struct iwm_softc *); 278static int iwm_allow_mcast(struct iwm_softc *);
279static int iwm_start_hw(struct iwm_softc *); 279static int iwm_start_hw(struct iwm_softc *);
280static void iwm_stop_device(struct iwm_softc *); 280static void iwm_stop_device(struct iwm_softc *);
281static void iwm_nic_config(struct iwm_softc *); 281static void iwm_nic_config(struct iwm_softc *);
282static int iwm_nic_rx_init(struct iwm_softc *); 282static int iwm_nic_rx_init(struct iwm_softc *);
283static int iwm_nic_tx_init(struct iwm_softc *); 283static int iwm_nic_tx_init(struct iwm_softc *);
284static int iwm_nic_init(struct iwm_softc *); 284static int iwm_nic_init(struct iwm_softc *);
285static int iwm_enable_txq(struct iwm_softc *, int, int, int); 285static int iwm_enable_txq(struct iwm_softc *, int, int, int);
286static int iwm_post_alive(struct iwm_softc *); 286static int iwm_post_alive(struct iwm_softc *);
287static struct iwm_phy_db_entry * 287static struct iwm_phy_db_entry *
288 iwm_phy_db_get_section(struct iwm_softc *, 288 iwm_phy_db_get_section(struct iwm_softc *,
289 enum iwm_phy_db_section_type, uint16_t); 289 enum iwm_phy_db_section_type, uint16_t);
290static int iwm_phy_db_set_section(struct iwm_softc *, 290static int iwm_phy_db_set_section(struct iwm_softc *,
291 struct iwm_calib_res_notif_phy_db *, uint16_t); 291 struct iwm_calib_res_notif_phy_db *, uint16_t);
292static int iwm_is_valid_channel(uint16_t); 292static int iwm_is_valid_channel(uint16_t);
293static uint8_t iwm_ch_id_to_ch_index(uint16_t); 293static uint8_t iwm_ch_id_to_ch_index(uint16_t);
294static uint16_t iwm_channel_id_to_papd(uint16_t); 294static uint16_t iwm_channel_id_to_papd(uint16_t);
295static uint16_t iwm_channel_id_to_txp(struct iwm_softc *, uint16_t); 295static uint16_t iwm_channel_id_to_txp(struct iwm_softc *, uint16_t);
296static int iwm_phy_db_get_section_data(struct iwm_softc *, uint32_t, 296static int iwm_phy_db_get_section_data(struct iwm_softc *, uint32_t,
297 uint8_t **, uint16_t *, uint16_t); 297 uint8_t **, uint16_t *, uint16_t);
298static int iwm_send_phy_db_cmd(struct iwm_softc *, uint16_t, uint16_t, 298static int iwm_send_phy_db_cmd(struct iwm_softc *, uint16_t, uint16_t,
299 void *); 299 void *);
300static int iwm_phy_db_send_all_channel_groups(struct iwm_softc *, 300static int iwm_phy_db_send_all_channel_groups(struct iwm_softc *,
301 enum iwm_phy_db_section_type, uint8_t); 301 enum iwm_phy_db_section_type, uint8_t);
302static int iwm_send_phy_db_data(struct iwm_softc *); 302static int iwm_send_phy_db_data(struct iwm_softc *);
303static void iwm_te_v2_to_v1(const struct iwm_time_event_cmd_v2 *, 303static void iwm_te_v2_to_v1(const struct iwm_time_event_cmd_v2 *,
304 struct iwm_time_event_cmd_v1 *); 304 struct iwm_time_event_cmd_v1 *);
305static int iwm_send_time_event_cmd(struct iwm_softc *, 305static int iwm_send_time_event_cmd(struct iwm_softc *,
306 const struct iwm_time_event_cmd_v2 *); 306 const struct iwm_time_event_cmd_v2 *);
307static void iwm_protect_session(struct iwm_softc *, struct iwm_node *, 307static void iwm_protect_session(struct iwm_softc *, struct iwm_node *,
308 uint32_t, uint32_t); 308 uint32_t, uint32_t);
309static int iwm_nvm_read_chunk(struct iwm_softc *, uint16_t, uint16_t, 309static int iwm_nvm_read_chunk(struct iwm_softc *, uint16_t, uint16_t,
310 uint16_t, uint8_t *, uint16_t *); 310 uint16_t, uint8_t *, uint16_t *);
311static int iwm_nvm_read_section(struct iwm_softc *, uint16_t, uint8_t *, 311static int iwm_nvm_read_section(struct iwm_softc *, uint16_t, uint8_t *,
312 uint16_t *, size_t); 312 uint16_t *, size_t);
313static void iwm_init_channel_map(struct iwm_softc *, const uint16_t * const, 313static void iwm_init_channel_map(struct iwm_softc *, const uint16_t * const,
314 const uint8_t *, size_t); 314 const uint8_t *, size_t);
315#ifndef IEEE80211_NO_HT 315#ifndef IEEE80211_NO_HT
316static void iwm_setup_ht_rates(struct iwm_softc *); 316static void iwm_setup_ht_rates(struct iwm_softc *);
317static void iwm_htprot_task(void *); 317static void iwm_htprot_task(void *);
318static void iwm_update_htprot(struct ieee80211com *, 318static void iwm_update_htprot(struct ieee80211com *,
319 struct ieee80211_node *); 319 struct ieee80211_node *);
320static int iwm_ampdu_rx_start(struct ieee80211com *, 320static int iwm_ampdu_rx_start(struct ieee80211com *,
321 struct ieee80211_node *, uint8_t); 321 struct ieee80211_node *, uint8_t);
322static void iwm_ampdu_rx_stop(struct ieee80211com *, 322static void iwm_ampdu_rx_stop(struct ieee80211com *,
323 struct ieee80211_node *, uint8_t); 323 struct ieee80211_node *, uint8_t);
324static void iwm_sta_rx_agg(struct iwm_softc *, struct ieee80211_node *, 324static void iwm_sta_rx_agg(struct iwm_softc *, struct ieee80211_node *,
325 uint8_t, uint16_t, int); 325 uint8_t, uint16_t, int);
326#ifdef notyet 326#ifdef notyet
327static int iwm_ampdu_tx_start(struct ieee80211com *, 327static int iwm_ampdu_tx_start(struct ieee80211com *,
328 struct ieee80211_node *, uint8_t); 328 struct ieee80211_node *, uint8_t);
329static void iwm_ampdu_tx_stop(struct ieee80211com *, 329static void iwm_ampdu_tx_stop(struct ieee80211com *,
330 struct ieee80211_node *, uint8_t); 330 struct ieee80211_node *, uint8_t);
331#endif 331#endif
332static void iwm_ba_task(void *); 332static void iwm_ba_task(void *);
333#endif 333#endif
334 334
335static int iwm_parse_nvm_data(struct iwm_softc *, const uint16_t *, 335static int iwm_parse_nvm_data(struct iwm_softc *, const uint16_t *,
336 const uint16_t *, const uint16_t *, const uint16_t *, 336 const uint16_t *, const uint16_t *, const uint16_t *,
337 const uint16_t *, const uint16_t *); 337 const uint16_t *, const uint16_t *);
338static void iwm_set_hw_address_8000(struct iwm_softc *, 338static void iwm_set_hw_address_8000(struct iwm_softc *,
339 struct iwm_nvm_data *, const uint16_t *, const uint16_t *); 339 struct iwm_nvm_data *, const uint16_t *, const uint16_t *);
340static int iwm_parse_nvm_sections(struct iwm_softc *, 340static int iwm_parse_nvm_sections(struct iwm_softc *,
341 struct iwm_nvm_section *); 341 struct iwm_nvm_section *);
342static int iwm_nvm_init(struct iwm_softc *); 342static int iwm_nvm_init(struct iwm_softc *);
343static int iwm_firmware_load_sect(struct iwm_softc *, uint32_t, 343static int iwm_firmware_load_sect(struct iwm_softc *, uint32_t,
344 const uint8_t *, uint32_t); 344 const uint8_t *, uint32_t);
345static int iwm_firmware_load_chunk(struct iwm_softc *, uint32_t, 345static int iwm_firmware_load_chunk(struct iwm_softc *, uint32_t,
346 const uint8_t *, uint32_t); 346 const uint8_t *, uint32_t);
347static int iwm_load_cpu_sections_7000(struct iwm_softc *, 347static int iwm_load_cpu_sections_7000(struct iwm_softc *,
348 struct iwm_fw_sects *, int , int *); 348 struct iwm_fw_sects *, int , int *);
349static int iwm_load_firmware_7000(struct iwm_softc *, enum iwm_ucode_type); 349static int iwm_load_firmware_7000(struct iwm_softc *, enum iwm_ucode_type);
350static int iwm_load_cpu_sections_8000(struct iwm_softc *, 350static int iwm_load_cpu_sections_8000(struct iwm_softc *,
351 struct iwm_fw_sects *, int , int *); 351 struct iwm_fw_sects *, int , int *);
352static int iwm_load_firmware_8000(struct iwm_softc *, enum iwm_ucode_type); 352static int iwm_load_firmware_8000(struct iwm_softc *, enum iwm_ucode_type);
353static int iwm_load_firmware(struct iwm_softc *, enum iwm_ucode_type); 353static int iwm_load_firmware(struct iwm_softc *, enum iwm_ucode_type);
354static int iwm_start_fw(struct iwm_softc *, enum iwm_ucode_type); 354static int iwm_start_fw(struct iwm_softc *, enum iwm_ucode_type);
355static int iwm_send_tx_ant_cfg(struct iwm_softc *, uint8_t); 355static int iwm_send_tx_ant_cfg(struct iwm_softc *, uint8_t);
356static int iwm_send_phy_cfg_cmd(struct iwm_softc *); 356static int iwm_send_phy_cfg_cmd(struct iwm_softc *);
357static int iwm_load_ucode_wait_alive(struct iwm_softc *, 357static int iwm_load_ucode_wait_alive(struct iwm_softc *,
358 enum iwm_ucode_type); 358 enum iwm_ucode_type);
359static int iwm_run_init_mvm_ucode(struct iwm_softc *, int); 359static int iwm_run_init_mvm_ucode(struct iwm_softc *, int);
360static int iwm_rx_addbuf(struct iwm_softc *, int, int); 360static int iwm_rx_addbuf(struct iwm_softc *, int, int);
361static int iwm_calc_rssi(struct iwm_softc *, struct iwm_rx_phy_info *); 361static int iwm_calc_rssi(struct iwm_softc *, struct iwm_rx_phy_info *);
362static int iwm_get_signal_strength(struct iwm_softc *, 362static int iwm_get_signal_strength(struct iwm_softc *,
363 struct iwm_rx_phy_info *); 363 struct iwm_rx_phy_info *);
364static void iwm_rx_rx_phy_cmd(struct iwm_softc *, 364static void iwm_rx_rx_phy_cmd(struct iwm_softc *,
365 struct iwm_rx_packet *, struct iwm_rx_data *); 365 struct iwm_rx_packet *, struct iwm_rx_data *);
366static int iwm_get_noise(const struct iwm_statistics_rx_non_phy *); 366static int iwm_get_noise(const struct iwm_statistics_rx_non_phy *);
367static void iwm_rx_rx_mpdu(struct iwm_softc *, struct iwm_rx_packet *, 367static void iwm_rx_rx_mpdu(struct iwm_softc *, struct iwm_rx_packet *,
368 struct iwm_rx_data *); 368 struct iwm_rx_data *);
369static void iwm_rx_tx_cmd_single(struct iwm_softc *, struct iwm_rx_packet *, struct iwm_node *); 369static void iwm_rx_tx_cmd_single(struct iwm_softc *, struct iwm_rx_packet *, struct iwm_node *);
370static void iwm_rx_tx_cmd(struct iwm_softc *, struct iwm_rx_packet *, 370static void iwm_rx_tx_cmd(struct iwm_softc *, struct iwm_rx_packet *,
371 struct iwm_rx_data *); 371 struct iwm_rx_data *);
372static int iwm_binding_cmd(struct iwm_softc *, struct iwm_node *, 372static int iwm_binding_cmd(struct iwm_softc *, struct iwm_node *,
373 uint32_t); 373 uint32_t);
374#if 0 374#if 0
375static int iwm_binding_update(struct iwm_softc *, struct iwm_node *, int); 375static int iwm_binding_update(struct iwm_softc *, struct iwm_node *, int);
376static int iwm_binding_add_vif(struct iwm_softc *, struct iwm_node *); 376static int iwm_binding_add_vif(struct iwm_softc *, struct iwm_node *);
377#endif 377#endif
378static void iwm_phy_ctxt_cmd_hdr(struct iwm_softc *, struct iwm_phy_ctxt *, 378static void iwm_phy_ctxt_cmd_hdr(struct iwm_softc *, struct iwm_phy_ctxt *,
379 struct iwm_phy_context_cmd *, uint32_t, uint32_t); 379 struct iwm_phy_context_cmd *, uint32_t, uint32_t);
380static void iwm_phy_ctxt_cmd_data(struct iwm_softc *, 380static void iwm_phy_ctxt_cmd_data(struct iwm_softc *,
381 struct iwm_phy_context_cmd *, struct ieee80211_channel *, 381 struct iwm_phy_context_cmd *, struct ieee80211_channel *,
382 uint8_t, uint8_t); 382 uint8_t, uint8_t);
383static int iwm_phy_ctxt_cmd(struct iwm_softc *, struct iwm_phy_ctxt *, 383static int iwm_phy_ctxt_cmd(struct iwm_softc *, struct iwm_phy_ctxt *,
384 uint8_t, uint8_t, uint32_t, uint32_t); 384 uint8_t, uint8_t, uint32_t, uint32_t);
385static int iwm_send_cmd(struct iwm_softc *, struct iwm_host_cmd *); 385static int iwm_send_cmd(struct iwm_softc *, struct iwm_host_cmd *);
386static int iwm_send_cmd_pdu(struct iwm_softc *, uint32_t, uint32_t, 386static int iwm_send_cmd_pdu(struct iwm_softc *, uint32_t, uint32_t,
387 uint16_t, const void *); 387 uint16_t, const void *);
388static int iwm_send_cmd_status(struct iwm_softc *, struct iwm_host_cmd *, 388static int iwm_send_cmd_status(struct iwm_softc *, struct iwm_host_cmd *,
389 uint32_t *); 389 uint32_t *);
390static int iwm_send_cmd_pdu_status(struct iwm_softc *, uint32_t, uint16_t, 390static int iwm_send_cmd_pdu_status(struct iwm_softc *, uint32_t, uint16_t,
391 const void *, uint32_t *); 391 const void *, uint32_t *);
392static void iwm_free_resp(struct iwm_softc *, struct iwm_host_cmd *); 392static void iwm_free_resp(struct iwm_softc *, struct iwm_host_cmd *);
393static void iwm_cmd_done(struct iwm_softc *, int qid, int idx); 393static void iwm_cmd_done(struct iwm_softc *, int qid, int idx);
394#if 0 394#if 0
395static void iwm_update_sched(struct iwm_softc *, int, int, uint8_t, 395static void iwm_update_sched(struct iwm_softc *, int, int, uint8_t,
396 uint16_t); 396 uint16_t);
397#endif 397#endif
398static const struct iwm_rate * 398static const struct iwm_rate *
399 iwm_tx_fill_cmd(struct iwm_softc *, struct iwm_node *, 399 iwm_tx_fill_cmd(struct iwm_softc *, struct iwm_node *,
400 struct ieee80211_frame *, struct iwm_tx_cmd *); 400 struct ieee80211_frame *, struct iwm_tx_cmd *);
401static int iwm_tx(struct iwm_softc *, struct mbuf *, 401static int iwm_tx(struct iwm_softc *, struct mbuf *,
402 struct ieee80211_node *, int); 402 struct ieee80211_node *, int);
403static void iwm_led_enable(struct iwm_softc *); 403static void iwm_led_enable(struct iwm_softc *);
404static void iwm_led_disable(struct iwm_softc *); 404static void iwm_led_disable(struct iwm_softc *);
405static int iwm_led_is_enabled(struct iwm_softc *); 405static int iwm_led_is_enabled(struct iwm_softc *);
406static void iwm_led_blink_timeout(void *); 406static void iwm_led_blink_timeout(void *);
407static void iwm_led_blink_start(struct iwm_softc *); 407static void iwm_led_blink_start(struct iwm_softc *);
408static void iwm_led_blink_stop(struct iwm_softc *); 408static void iwm_led_blink_stop(struct iwm_softc *);
409static int iwm_beacon_filter_send_cmd(struct iwm_softc *, 409static int iwm_beacon_filter_send_cmd(struct iwm_softc *,
410 struct iwm_beacon_filter_cmd *); 410 struct iwm_beacon_filter_cmd *);
411static void iwm_beacon_filter_set_cqm_params(struct iwm_softc *, 411static void iwm_beacon_filter_set_cqm_params(struct iwm_softc *,
412 struct iwm_node *, struct iwm_beacon_filter_cmd *); 412 struct iwm_node *, struct iwm_beacon_filter_cmd *);
413static int iwm_update_beacon_abort(struct iwm_softc *, struct iwm_node *, 413static int iwm_update_beacon_abort(struct iwm_softc *, struct iwm_node *,
414 int); 414 int);
415static void iwm_power_build_cmd(struct iwm_softc *, struct iwm_node *, 415static void iwm_power_build_cmd(struct iwm_softc *, struct iwm_node *,
416 struct iwm_mac_power_cmd *); 416 struct iwm_mac_power_cmd *);
417static int iwm_power_mac_update_mode(struct iwm_softc *, 417static int iwm_power_mac_update_mode(struct iwm_softc *,
418 struct iwm_node *); 418 struct iwm_node *);
419static int iwm_power_update_device(struct iwm_softc *); 419static int iwm_power_update_device(struct iwm_softc *);
420#ifdef notyet 420#ifdef notyet
421static int iwm_enable_beacon_filter(struct iwm_softc *, struct iwm_node *); 421static int iwm_enable_beacon_filter(struct iwm_softc *, struct iwm_node *);
422#endif 422#endif
423static int iwm_disable_beacon_filter(struct iwm_softc *); 423static int iwm_disable_beacon_filter(struct iwm_softc *);
424static int iwm_add_sta_cmd(struct iwm_softc *, struct iwm_node *, int); 424static int iwm_add_sta_cmd(struct iwm_softc *, struct iwm_node *, int);
425static int iwm_add_aux_sta(struct iwm_softc *); 425static int iwm_add_aux_sta(struct iwm_softc *);
426static uint16_t iwm_scan_rx_chain(struct iwm_softc *); 426static uint16_t iwm_scan_rx_chain(struct iwm_softc *);
427static uint32_t iwm_scan_rate_n_flags(struct iwm_softc *, int, int); 427static uint32_t iwm_scan_rate_n_flags(struct iwm_softc *, int, int);
428#ifdef notyet 428#ifdef notyet
429static uint16_t iwm_get_active_dwell(struct iwm_softc *, int, int); 429static uint16_t iwm_get_active_dwell(struct iwm_softc *, int, int);
430static uint16_t iwm_get_passive_dwell(struct iwm_softc *, int); 430static uint16_t iwm_get_passive_dwell(struct iwm_softc *, int);
431#endif 431#endif
432static uint8_t iwm_lmac_scan_fill_channels(struct iwm_softc *, 432static uint8_t iwm_lmac_scan_fill_channels(struct iwm_softc *,
433 struct iwm_scan_channel_cfg_lmac *, int); 433 struct iwm_scan_channel_cfg_lmac *, int);
434static int iwm_fill_probe_req(struct iwm_softc *, 434static int iwm_fill_probe_req(struct iwm_softc *,
435 struct iwm_scan_probe_req *); 435 struct iwm_scan_probe_req *);
436static int iwm_lmac_scan(struct iwm_softc *); 436static int iwm_lmac_scan(struct iwm_softc *);
437static int iwm_config_umac_scan(struct iwm_softc *); 437static int iwm_config_umac_scan(struct iwm_softc *);
438static int iwm_umac_scan(struct iwm_softc *); 438static int iwm_umac_scan(struct iwm_softc *);
439static uint8_t iwm_ridx2rate(struct ieee80211_rateset *, int); 439static uint8_t iwm_ridx2rate(struct ieee80211_rateset *, int);
440static void iwm_ack_rates(struct iwm_softc *, struct iwm_node *, int *, 440static void iwm_ack_rates(struct iwm_softc *, struct iwm_node *, int *,
441 int *); 441 int *);
442static void iwm_mac_ctxt_cmd_common(struct iwm_softc *, struct iwm_node *, 442static void iwm_mac_ctxt_cmd_common(struct iwm_softc *, struct iwm_node *,
443 struct iwm_mac_ctx_cmd *, uint32_t, int); 443 struct iwm_mac_ctx_cmd *, uint32_t, int);
444static void iwm_mac_ctxt_cmd_fill_sta(struct iwm_softc *, struct iwm_node *, 444static void iwm_mac_ctxt_cmd_fill_sta(struct iwm_softc *, struct iwm_node *,
445 struct iwm_mac_data_sta *, int); 445 struct iwm_mac_data_sta *, int);
446static int iwm_mac_ctxt_cmd(struct iwm_softc *, struct iwm_node *, 446static int iwm_mac_ctxt_cmd(struct iwm_softc *, struct iwm_node *,
447 uint32_t, int); 447 uint32_t, int);
448static int iwm_update_quotas(struct iwm_softc *, struct iwm_node *); 448static int iwm_update_quotas(struct iwm_softc *, struct iwm_node *);
449static int iwm_auth(struct iwm_softc *); 449static int iwm_auth(struct iwm_softc *);
450static int iwm_assoc(struct iwm_softc *); 450static int iwm_assoc(struct iwm_softc *);
451static void iwm_calib_timeout(void *); 451static void iwm_calib_timeout(void *);
452#ifndef IEEE80211_NO_HT 452#ifndef IEEE80211_NO_HT
453static void iwm_setrates_task(void *); 453static void iwm_setrates_task(void *);
454static int iwm_setrates(struct iwm_node *); 454static int iwm_setrates(struct iwm_node *);
455#endif 455#endif
456static int iwm_media_change(struct ifnet *); 456static int iwm_media_change(struct ifnet *);
457static int iwm_do_newstate(struct ieee80211com *, enum ieee80211_state, 457static int iwm_do_newstate(struct ieee80211com *, enum ieee80211_state,
458 int); 458 int);
459static void iwm_newstate_cb(struct work *, void *); 459static void iwm_newstate_cb(struct work *, void *);
460static int iwm_newstate(struct ieee80211com *, enum ieee80211_state, int); 460static int iwm_newstate(struct ieee80211com *, enum ieee80211_state, int);
461static void iwm_endscan(struct iwm_softc *); 461static void iwm_endscan(struct iwm_softc *);
462static void iwm_fill_sf_command(struct iwm_softc *, struct iwm_sf_cfg_cmd *, 462static void iwm_fill_sf_command(struct iwm_softc *, struct iwm_sf_cfg_cmd *,
463 struct ieee80211_node *); 463 struct ieee80211_node *);
464static int iwm_sf_config(struct iwm_softc *, int); 464static int iwm_sf_config(struct iwm_softc *, int);
465static int iwm_send_bt_init_conf(struct iwm_softc *); 465static int iwm_send_bt_init_conf(struct iwm_softc *);
466static int iwm_send_update_mcc_cmd(struct iwm_softc *, const char *); 466static int iwm_send_update_mcc_cmd(struct iwm_softc *, const char *);
467static void iwm_tt_tx_backoff(struct iwm_softc *, uint32_t); 467static void iwm_tt_tx_backoff(struct iwm_softc *, uint32_t);
468static int iwm_init_hw(struct iwm_softc *); 468static int iwm_init_hw(struct iwm_softc *);
469static int iwm_init(struct ifnet *); 469static int iwm_init(struct ifnet *);
470static void iwm_start(struct ifnet *); 470static void iwm_start(struct ifnet *);
471static void iwm_stop(struct ifnet *, int); 471static void iwm_stop(struct ifnet *, int);
472static void iwm_watchdog(struct ifnet *); 472static void iwm_watchdog(struct ifnet *);
473static int iwm_ioctl(struct ifnet *, u_long, void *); 473static int iwm_ioctl(struct ifnet *, u_long, void *);
474#ifdef IWM_DEBUG 474#ifdef IWM_DEBUG
475static const char *iwm_desc_lookup(uint32_t); 475static const char *iwm_desc_lookup(uint32_t);
476static void iwm_nic_error(struct iwm_softc *); 476static void iwm_nic_error(struct iwm_softc *);
477static void iwm_nic_umac_error(struct iwm_softc *); 477static void iwm_nic_umac_error(struct iwm_softc *);
478#endif 478#endif
479static void iwm_notif_intr(struct iwm_softc *); 479static void iwm_notif_intr(struct iwm_softc *);
480static int iwm_intr(void *); 480static int iwm_intr(void *);
481static void iwm_softintr(void *); 481static void iwm_softintr(void *);
482static int iwm_preinit(struct iwm_softc *); 482static int iwm_preinit(struct iwm_softc *);
483static void iwm_attach_hook(device_t); 483static void iwm_attach_hook(device_t);
484static void iwm_attach(device_t, device_t, void *); 484static void iwm_attach(device_t, device_t, void *);
485#if 0 485#if 0
486static void iwm_init_task(void *); 486static void iwm_init_task(void *);
487static int iwm_activate(device_t, enum devact); 487static int iwm_activate(device_t, enum devact);
488static void iwm_wakeup(struct iwm_softc *); 488static void iwm_wakeup(struct iwm_softc *);
489#endif 489#endif
490static void iwm_radiotap_attach(struct iwm_softc *); 490static void iwm_radiotap_attach(struct iwm_softc *);
491static int iwm_sysctl_fw_loaded_handler(SYSCTLFN_PROTO); 491static int iwm_sysctl_fw_loaded_handler(SYSCTLFN_PROTO);
492 492
493static int iwm_sysctl_root_num; 493static int iwm_sysctl_root_num;
494static int iwm_lar_disable; 494static int iwm_lar_disable;
495 495
496#ifndef IWM_DEFAULT_MCC 496#ifndef IWM_DEFAULT_MCC
497#define IWM_DEFAULT_MCC "ZZ" 497#define IWM_DEFAULT_MCC "ZZ"
498#endif 498#endif
499static char iwm_default_mcc[3] = IWM_DEFAULT_MCC; 499static char iwm_default_mcc[3] = IWM_DEFAULT_MCC;
500 500
501static int 501static int
502iwm_firmload(struct iwm_softc *sc) 502iwm_firmload(struct iwm_softc *sc)
503{ 503{
504 struct iwm_fw_info *fw = &sc->sc_fw; 504 struct iwm_fw_info *fw = &sc->sc_fw;
505 firmware_handle_t fwh; 505 firmware_handle_t fwh;
506 int err; 506 int err;
507 507
508 if (ISSET(sc->sc_flags, IWM_FLAG_FW_LOADED)) 508 if (ISSET(sc->sc_flags, IWM_FLAG_FW_LOADED))
509 return 0; 509 return 0;
510 510
511 /* Open firmware image. */ 511 /* Open firmware image. */
512 err = firmware_open("if_iwm", sc->sc_fwname, &fwh); 512 err = firmware_open("if_iwm", sc->sc_fwname, &fwh);
513 if (err) { 513 if (err) {
514 aprint_error_dev(sc->sc_dev, 514 aprint_error_dev(sc->sc_dev,
515 "could not get firmware handle %s\n", sc->sc_fwname); 515 "could not get firmware handle %s\n", sc->sc_fwname);
516 return err; 516 return err;
517 } 517 }
518 518
519 if (fw->fw_rawdata != NULL && fw->fw_rawsize > 0) { 519 if (fw->fw_rawdata != NULL && fw->fw_rawsize > 0) {
520 kmem_free(fw->fw_rawdata, fw->fw_rawsize); 520 kmem_free(fw->fw_rawdata, fw->fw_rawsize);
521 fw->fw_rawdata = NULL; 521 fw->fw_rawdata = NULL;
522 } 522 }
523 523
524 fw->fw_rawsize = firmware_get_size(fwh); 524 fw->fw_rawsize = firmware_get_size(fwh);
525 /* 525 /*
526 * Well, this is how the Linux driver checks it .... 526 * Well, this is how the Linux driver checks it ....
527 */ 527 */
528 if (fw->fw_rawsize < sizeof(uint32_t)) { 528 if (fw->fw_rawsize < sizeof(uint32_t)) {
529 aprint_error_dev(sc->sc_dev, 529 aprint_error_dev(sc->sc_dev,
530 "firmware too short: %zd bytes\n", fw->fw_rawsize); 530 "firmware too short: %zd bytes\n", fw->fw_rawsize);
531 err = EINVAL; 531 err = EINVAL;
532 goto out; 532 goto out;
533 } 533 }
534 534
535 /* Read the firmware. */ 535 /* Read the firmware. */
536 fw->fw_rawdata = kmem_alloc(fw->fw_rawsize, KM_SLEEP); 536 fw->fw_rawdata = kmem_alloc(fw->fw_rawsize, KM_SLEEP);
537 err = firmware_read(fwh, 0, fw->fw_rawdata, fw->fw_rawsize); 537 err = firmware_read(fwh, 0, fw->fw_rawdata, fw->fw_rawsize);
538 if (err) { 538 if (err) {
539 aprint_error_dev(sc->sc_dev, 539 aprint_error_dev(sc->sc_dev,
540 "could not read firmware %s\n", sc->sc_fwname); 540 "could not read firmware %s\n", sc->sc_fwname);
541 goto out; 541 goto out;
542 } 542 }
543 543
544 SET(sc->sc_flags, IWM_FLAG_FW_LOADED); 544 SET(sc->sc_flags, IWM_FLAG_FW_LOADED);
545 out: 545 out:
546 /* caller will release memory, if necessary */ 546 /* caller will release memory, if necessary */
547 547
548 firmware_close(fwh); 548 firmware_close(fwh);
549 return err; 549 return err;
550} 550}
551 551
552/* 552/*
553 * just maintaining status quo. 553 * just maintaining status quo.
554 */ 554 */
555static void 555static void
556iwm_fix_channel(struct iwm_softc *sc, struct mbuf *m) 556iwm_fix_channel(struct iwm_softc *sc, struct mbuf *m)
557{ 557{
558 struct ieee80211com *ic = &sc->sc_ic; 558 struct ieee80211com *ic = &sc->sc_ic;
559 struct ieee80211_frame *wh; 559 struct ieee80211_frame *wh;
560 uint8_t subtype; 560 uint8_t subtype;
561 561
562 wh = mtod(m, struct ieee80211_frame *); 562 wh = mtod(m, struct ieee80211_frame *);
563 563
564 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT) 564 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT)
565 return; 565 return;
566 566
567 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 567 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
568 568
569 if (subtype != IEEE80211_FC0_SUBTYPE_BEACON && 569 if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
570 subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP) 570 subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
571 return; 571 return;
572 572
573 int chan = le32toh(sc->sc_last_phy_info.channel); 573 int chan = le32toh(sc->sc_last_phy_info.channel);
574 if (chan < __arraycount(ic->ic_channels)) 574 if (chan < __arraycount(ic->ic_channels))
575 ic->ic_curchan = &ic->ic_channels[chan]; 575 ic->ic_curchan = &ic->ic_channels[chan];
576} 576}
577 577
578static int 578static int
579iwm_store_cscheme(struct iwm_softc *sc, uint8_t *data, size_t dlen) 579iwm_store_cscheme(struct iwm_softc *sc, uint8_t *data, size_t dlen)
580{ 580{
581 struct iwm_fw_cscheme_list *l = (struct iwm_fw_cscheme_list *)data; 581 struct iwm_fw_cscheme_list *l = (struct iwm_fw_cscheme_list *)data;
582 582
583 if (dlen < sizeof(*l) || 583 if (dlen < sizeof(*l) ||
584 dlen < sizeof(l->size) + l->size * sizeof(*l->cs)) 584 dlen < sizeof(l->size) + l->size * sizeof(*l->cs))
585 return EINVAL; 585 return EINVAL;
586 586
587 /* we don't actually store anything for now, always use s/w crypto */ 587 /* we don't actually store anything for now, always use s/w crypto */
588 588
589 return 0; 589 return 0;
590} 590}
591 591
592static int 592static int
593iwm_firmware_store_section(struct iwm_softc *sc, enum iwm_ucode_type type, 593iwm_firmware_store_section(struct iwm_softc *sc, enum iwm_ucode_type type,
594 uint8_t *data, size_t dlen) 594 uint8_t *data, size_t dlen)
595{ 595{
596 struct iwm_fw_sects *fws; 596 struct iwm_fw_sects *fws;
597 struct iwm_fw_onesect *fwone; 597 struct iwm_fw_onesect *fwone;
598 598
599 if (type >= IWM_UCODE_TYPE_MAX) 599 if (type >= IWM_UCODE_TYPE_MAX)
600 return EINVAL; 600 return EINVAL;
601 if (dlen < sizeof(uint32_t)) 601 if (dlen < sizeof(uint32_t))
602 return EINVAL; 602 return EINVAL;
603 603
604 fws = &sc->sc_fw.fw_sects[type]; 604 fws = &sc->sc_fw.fw_sects[type];
605 if (fws->fw_count >= IWM_UCODE_SECT_MAX) 605 if (fws->fw_count >= IWM_UCODE_SECT_MAX)
606 return EINVAL; 606 return EINVAL;
607 607
608 fwone = &fws->fw_sect[fws->fw_count]; 608 fwone = &fws->fw_sect[fws->fw_count];
609 609
610 /* first 32bit are device load offset */ 610 /* first 32bit are device load offset */
611 memcpy(&fwone->fws_devoff, data, sizeof(uint32_t)); 611 memcpy(&fwone->fws_devoff, data, sizeof(uint32_t));
612 612
613 /* rest is data */ 613 /* rest is data */
614 fwone->fws_data = data + sizeof(uint32_t); 614 fwone->fws_data = data + sizeof(uint32_t);
615 fwone->fws_len = dlen - sizeof(uint32_t); 615 fwone->fws_len = dlen - sizeof(uint32_t);
616 616
617 /* for freeing the buffer during driver unload */ 617 /* for freeing the buffer during driver unload */
618 fwone->fws_alloc = data; 618 fwone->fws_alloc = data;
619 fwone->fws_allocsize = dlen; 619 fwone->fws_allocsize = dlen;
620 620
621 fws->fw_count++; 621 fws->fw_count++;
622 fws->fw_totlen += fwone->fws_len; 622 fws->fw_totlen += fwone->fws_len;
623 623
624 return 0; 624 return 0;
625} 625}
626 626
627struct iwm_tlv_calib_data { 627struct iwm_tlv_calib_data {
628 uint32_t ucode_type; 628 uint32_t ucode_type;
629 struct iwm_tlv_calib_ctrl calib; 629 struct iwm_tlv_calib_ctrl calib;
630} __packed; 630} __packed;
631 631
632static int 632static int
633iwm_set_default_calib(struct iwm_softc *sc, const void *data) 633iwm_set_default_calib(struct iwm_softc *sc, const void *data)
634{ 634{
635 const struct iwm_tlv_calib_data *def_calib = data; 635 const struct iwm_tlv_calib_data *def_calib = data;
636 uint32_t ucode_type = le32toh(def_calib->ucode_type); 636 uint32_t ucode_type = le32toh(def_calib->ucode_type);
637 637
638 if (ucode_type >= IWM_UCODE_TYPE_MAX) { 638 if (ucode_type >= IWM_UCODE_TYPE_MAX) {
639 DPRINTF(("%s: Wrong ucode_type %u for default calibration.\n", 639 DPRINTF(("%s: Wrong ucode_type %u for default calibration.\n",
640 DEVNAME(sc), ucode_type)); 640 DEVNAME(sc), ucode_type));
641 return EINVAL; 641 return EINVAL;
642 } 642 }
643 643
644 sc->sc_default_calib[ucode_type].flow_trigger = 644 sc->sc_default_calib[ucode_type].flow_trigger =
645 def_calib->calib.flow_trigger; 645 def_calib->calib.flow_trigger;
646 sc->sc_default_calib[ucode_type].event_trigger = 646 sc->sc_default_calib[ucode_type].event_trigger =
647 def_calib->calib.event_trigger; 647 def_calib->calib.event_trigger;
648 648
649 return 0; 649 return 0;
650} 650}
651 651
652static int 652static int
653iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type) 653iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
654{ 654{
655 struct iwm_fw_info *fw = &sc->sc_fw; 655 struct iwm_fw_info *fw = &sc->sc_fw;
656 struct iwm_tlv_ucode_header *uhdr; 656 struct iwm_tlv_ucode_header *uhdr;
657 struct iwm_ucode_tlv tlv; 657 struct iwm_ucode_tlv tlv;
658 enum iwm_ucode_tlv_type tlv_type; 658 enum iwm_ucode_tlv_type tlv_type;
659 uint8_t *data; 659 uint8_t *data;
660 int err, status; 660 int err, status;
661 size_t len; 661 size_t len;
662 662
663 if (ucode_type != IWM_UCODE_TYPE_INIT && 663 if (ucode_type != IWM_UCODE_TYPE_INIT &&
664 fw->fw_status == IWM_FW_STATUS_DONE) 664 fw->fw_status == IWM_FW_STATUS_DONE)
665 return 0; 665 return 0;
666 666
667 if (fw->fw_status == IWM_FW_STATUS_NONE) { 667 if (fw->fw_status == IWM_FW_STATUS_NONE) {
668 fw->fw_status = IWM_FW_STATUS_INPROGRESS; 668 fw->fw_status = IWM_FW_STATUS_INPROGRESS;
669 } else { 669 } else {
670 while (fw->fw_status == IWM_FW_STATUS_INPROGRESS) 670 while (fw->fw_status == IWM_FW_STATUS_INPROGRESS)
671 tsleep(&sc->sc_fw, 0, "iwmfwp", 0); 671 tsleep(&sc->sc_fw, 0, "iwmfwp", 0);
672 } 672 }
673 status = fw->fw_status; 673 status = fw->fw_status;
674 674
675 if (status == IWM_FW_STATUS_DONE) 675 if (status == IWM_FW_STATUS_DONE)
676 return 0; 676 return 0;
677 677
678 err = iwm_firmload(sc); 678 err = iwm_firmload(sc);
679 if (err) { 679 if (err) {
680 aprint_error_dev(sc->sc_dev, 680 aprint_error_dev(sc->sc_dev,
681 "could not read firmware %s (error %d)\n", 681 "could not read firmware %s (error %d)\n",
682 sc->sc_fwname, err); 682 sc->sc_fwname, err);
683 goto out; 683 goto out;
684 } 684 }
685 685
686 sc->sc_capaflags = 0; 686 sc->sc_capaflags = 0;
687 sc->sc_capa_n_scan_channels = IWM_MAX_NUM_SCAN_CHANNELS; 687 sc->sc_capa_n_scan_channels = IWM_MAX_NUM_SCAN_CHANNELS;
688 memset(sc->sc_enabled_capa, 0, sizeof(sc->sc_enabled_capa)); 688 memset(sc->sc_enabled_capa, 0, sizeof(sc->sc_enabled_capa));
689 memset(sc->sc_fw_mcc, 0, sizeof(sc->sc_fw_mcc)); 689 memset(sc->sc_fw_mcc, 0, sizeof(sc->sc_fw_mcc));
690 690
691 uhdr = (void *)fw->fw_rawdata; 691 uhdr = (void *)fw->fw_rawdata;
692 if (*(uint32_t *)fw->fw_rawdata != 0 692 if (*(uint32_t *)fw->fw_rawdata != 0
693 || le32toh(uhdr->magic) != IWM_TLV_UCODE_MAGIC) { 693 || le32toh(uhdr->magic) != IWM_TLV_UCODE_MAGIC) {
694 aprint_error_dev(sc->sc_dev, "invalid firmware %s\n", 694 aprint_error_dev(sc->sc_dev, "invalid firmware %s\n",
695 sc->sc_fwname); 695 sc->sc_fwname);
696 err = EINVAL; 696 err = EINVAL;
697 goto out; 697 goto out;
698 } 698 }
699 699
700 snprintf(sc->sc_fwver, sizeof(sc->sc_fwver), "%d.%d (API ver %d)", 700 snprintf(sc->sc_fwver, sizeof(sc->sc_fwver), "%d.%d (API ver %d)",
701 IWM_UCODE_MAJOR(le32toh(uhdr->ver)), 701 IWM_UCODE_MAJOR(le32toh(uhdr->ver)),
702 IWM_UCODE_MINOR(le32toh(uhdr->ver)), 702 IWM_UCODE_MINOR(le32toh(uhdr->ver)),
703 IWM_UCODE_API(le32toh(uhdr->ver))); 703 IWM_UCODE_API(le32toh(uhdr->ver)));
704 data = uhdr->data; 704 data = uhdr->data;
705 len = fw->fw_rawsize - sizeof(*uhdr); 705 len = fw->fw_rawsize - sizeof(*uhdr);
706 706
707 while (len >= sizeof(tlv)) { 707 while (len >= sizeof(tlv)) {
708 size_t tlv_len; 708 size_t tlv_len;
709 void *tlv_data; 709 void *tlv_data;
710 710
711 memcpy(&tlv, data, sizeof(tlv)); 711 memcpy(&tlv, data, sizeof(tlv));
712 tlv_len = le32toh(tlv.length); 712 tlv_len = le32toh(tlv.length);
713 tlv_type = le32toh(tlv.type); 713 tlv_type = le32toh(tlv.type);
714 714
715 len -= sizeof(tlv); 715 len -= sizeof(tlv);
716 data += sizeof(tlv); 716 data += sizeof(tlv);
717 tlv_data = data; 717 tlv_data = data;
718 718
719 if (len < tlv_len) { 719 if (len < tlv_len) {
720 aprint_error_dev(sc->sc_dev, 720 aprint_error_dev(sc->sc_dev,
721 "firmware too short: %zu bytes\n", len); 721 "firmware too short: %zu bytes\n", len);
722 err = EINVAL; 722 err = EINVAL;
723 goto parse_out; 723 goto parse_out;
724 } 724 }
725 725
726 switch (tlv_type) { 726 switch (tlv_type) {
727 case IWM_UCODE_TLV_PROBE_MAX_LEN: 727 case IWM_UCODE_TLV_PROBE_MAX_LEN:
728 if (tlv_len < sizeof(uint32_t)) { 728 if (tlv_len < sizeof(uint32_t)) {
729 err = EINVAL; 729 err = EINVAL;
730 goto parse_out; 730 goto parse_out;
731 } 731 }
732 sc->sc_capa_max_probe_len 732 sc->sc_capa_max_probe_len
733 = le32toh(*(uint32_t *)tlv_data); 733 = le32toh(*(uint32_t *)tlv_data);
734 /* limit it to something sensible */ 734 /* limit it to something sensible */
735 if (sc->sc_capa_max_probe_len > 735 if (sc->sc_capa_max_probe_len >
736 IWM_SCAN_OFFLOAD_PROBE_REQ_SIZE) { 736 IWM_SCAN_OFFLOAD_PROBE_REQ_SIZE) {
737 err = EINVAL; 737 err = EINVAL;
738 goto parse_out; 738 goto parse_out;
739 } 739 }
740 break; 740 break;
741 case IWM_UCODE_TLV_PAN: 741 case IWM_UCODE_TLV_PAN:
742 if (tlv_len) { 742 if (tlv_len) {
743 err = EINVAL; 743 err = EINVAL;
744 goto parse_out; 744 goto parse_out;
745 } 745 }
746 sc->sc_capaflags |= IWM_UCODE_TLV_FLAGS_PAN; 746 sc->sc_capaflags |= IWM_UCODE_TLV_FLAGS_PAN;
747 break; 747 break;
748 case IWM_UCODE_TLV_FLAGS: 748 case IWM_UCODE_TLV_FLAGS:
749 if (tlv_len < sizeof(uint32_t)) { 749 if (tlv_len < sizeof(uint32_t)) {
750 err = EINVAL; 750 err = EINVAL;
751 goto parse_out; 751 goto parse_out;
752 } 752 }
753 if (tlv_len % sizeof(uint32_t)) { 753 if (tlv_len % sizeof(uint32_t)) {
754 err = EINVAL; 754 err = EINVAL;
755 goto parse_out; 755 goto parse_out;
756 } 756 }
757 /* 757 /*
758 * Apparently there can be many flags, but Linux driver 758 * Apparently there can be many flags, but Linux driver
759 * parses only the first one, and so do we. 759 * parses only the first one, and so do we.
760 * 760 *
761 * XXX: why does this override IWM_UCODE_TLV_PAN? 761 * XXX: why does this override IWM_UCODE_TLV_PAN?
762 * Intentional or a bug? Observations from 762 * Intentional or a bug? Observations from
763 * current firmware file: 763 * current firmware file:
764 * 1) TLV_PAN is parsed first 764 * 1) TLV_PAN is parsed first
765 * 2) TLV_FLAGS contains TLV_FLAGS_PAN 765 * 2) TLV_FLAGS contains TLV_FLAGS_PAN
766 * ==> this resets TLV_PAN to itself... hnnnk 766 * ==> this resets TLV_PAN to itself... hnnnk
767 */ 767 */
768 sc->sc_capaflags = le32toh(*(uint32_t *)tlv_data); 768 sc->sc_capaflags = le32toh(*(uint32_t *)tlv_data);
769 break; 769 break;
770 case IWM_UCODE_TLV_CSCHEME: 770 case IWM_UCODE_TLV_CSCHEME:
771 err = iwm_store_cscheme(sc, tlv_data, tlv_len); 771 err = iwm_store_cscheme(sc, tlv_data, tlv_len);
772 if (err) 772 if (err)
773 goto parse_out; 773 goto parse_out;
774 break; 774 break;
775 case IWM_UCODE_TLV_NUM_OF_CPU: { 775 case IWM_UCODE_TLV_NUM_OF_CPU: {
776 uint32_t num_cpu; 776 uint32_t num_cpu;
777 if (tlv_len != sizeof(uint32_t)) { 777 if (tlv_len != sizeof(uint32_t)) {
778 err = EINVAL; 778 err = EINVAL;
779 goto parse_out; 779 goto parse_out;
780 } 780 }
781 num_cpu = le32toh(*(uint32_t *)tlv_data); 781 num_cpu = le32toh(*(uint32_t *)tlv_data);
782 if (num_cpu == 2) { 782 if (num_cpu == 2) {
783 fw->fw_sects[IWM_UCODE_TYPE_REGULAR].is_dual_cpus = 783 fw->fw_sects[IWM_UCODE_TYPE_REGULAR].is_dual_cpus =
784 true; 784 true;
785 fw->fw_sects[IWM_UCODE_TYPE_INIT].is_dual_cpus = 785 fw->fw_sects[IWM_UCODE_TYPE_INIT].is_dual_cpus =
786 true; 786 true;
787 fw->fw_sects[IWM_UCODE_TYPE_WOW].is_dual_cpus = 787 fw->fw_sects[IWM_UCODE_TYPE_WOW].is_dual_cpus =
788 true; 788 true;
789 } else if (num_cpu < 1 || num_cpu > 2) { 789 } else if (num_cpu < 1 || num_cpu > 2) {
790 err = EINVAL; 790 err = EINVAL;
791 goto parse_out; 791 goto parse_out;
792 } 792 }
793 break; 793 break;
794 } 794 }
795 case IWM_UCODE_TLV_SEC_RT: 795 case IWM_UCODE_TLV_SEC_RT:
796 err = iwm_firmware_store_section(sc, 796 err = iwm_firmware_store_section(sc,
797 IWM_UCODE_TYPE_REGULAR, tlv_data, tlv_len); 797 IWM_UCODE_TYPE_REGULAR, tlv_data, tlv_len);
798 if (err) 798 if (err)
799 goto parse_out; 799 goto parse_out;
800 break; 800 break;
801 case IWM_UCODE_TLV_SEC_INIT: 801 case IWM_UCODE_TLV_SEC_INIT:
802 err = iwm_firmware_store_section(sc, 802 err = iwm_firmware_store_section(sc,
803 IWM_UCODE_TYPE_INIT, tlv_data, tlv_len); 803 IWM_UCODE_TYPE_INIT, tlv_data, tlv_len);
804 if (err) 804 if (err)
805 goto parse_out; 805 goto parse_out;
806 break; 806 break;
807 case IWM_UCODE_TLV_SEC_WOWLAN: 807 case IWM_UCODE_TLV_SEC_WOWLAN:
808 err = iwm_firmware_store_section(sc, 808 err = iwm_firmware_store_section(sc,
809 IWM_UCODE_TYPE_WOW, tlv_data, tlv_len); 809 IWM_UCODE_TYPE_WOW, tlv_data, tlv_len);
810 if (err) 810 if (err)
811 goto parse_out; 811 goto parse_out;
812 break; 812 break;
813 case IWM_UCODE_TLV_DEF_CALIB: 813 case IWM_UCODE_TLV_DEF_CALIB:
814 if (tlv_len != sizeof(struct iwm_tlv_calib_data)) { 814 if (tlv_len != sizeof(struct iwm_tlv_calib_data)) {
815 err = EINVAL; 815 err = EINVAL;
816 goto parse_out; 816 goto parse_out;
817 } 817 }
818 err = iwm_set_default_calib(sc, tlv_data); 818 err = iwm_set_default_calib(sc, tlv_data);
819 if (err) 819 if (err)
820 goto parse_out; 820 goto parse_out;
821 break; 821 break;
822 case IWM_UCODE_TLV_PHY_SKU: 822 case IWM_UCODE_TLV_PHY_SKU:
823 if (tlv_len != sizeof(uint32_t)) { 823 if (tlv_len != sizeof(uint32_t)) {
824 err = EINVAL; 824 err = EINVAL;
825 goto parse_out; 825 goto parse_out;
826 } 826 }
827 sc->sc_fw_phy_config = le32toh(*(uint32_t *)tlv_data); 827 sc->sc_fw_phy_config = le32toh(*(uint32_t *)tlv_data);
828 break; 828 break;
829 829
830 case IWM_UCODE_TLV_API_CHANGES_SET: { 830 case IWM_UCODE_TLV_API_CHANGES_SET: {
831 struct iwm_ucode_api *api; 831 struct iwm_ucode_api *api;
832 uint32_t idx, bits; 832 uint32_t idx, bits;
833 int i; 833 int i;
834 if (tlv_len != sizeof(*api)) { 834 if (tlv_len != sizeof(*api)) {
835 err = EINVAL; 835 err = EINVAL;
836 goto parse_out; 836 goto parse_out;
837 } 837 }
838 api = (struct iwm_ucode_api *)tlv_data; 838 api = (struct iwm_ucode_api *)tlv_data;
839 idx = le32toh(api->api_index); 839 idx = le32toh(api->api_index);
840 bits = le32toh(api->api_flags); 840 bits = le32toh(api->api_flags);
841 if (idx >= howmany(IWM_NUM_UCODE_TLV_API, 32)) { 841 if (idx >= howmany(IWM_NUM_UCODE_TLV_API, 32)) {
842 err = EINVAL; 842 err = EINVAL;
843 goto parse_out; 843 goto parse_out;
844 } 844 }
845 for (i = 0; i < 32; i++) { 845 for (i = 0; i < 32; i++) {
846 if (!ISSET(bits, __BIT(i))) 846 if (!ISSET(bits, __BIT(i)))
847 continue; 847 continue;
848 setbit(sc->sc_ucode_api, i + (32 * idx)); 848 setbit(sc->sc_ucode_api, i + (32 * idx));
849 } 849 }
850 break; 850 break;
851 } 851 }
852 852
853 case IWM_UCODE_TLV_ENABLED_CAPABILITIES: { 853 case IWM_UCODE_TLV_ENABLED_CAPABILITIES: {
854 struct iwm_ucode_capa *capa; 854 struct iwm_ucode_capa *capa;
855 uint32_t idx, bits; 855 uint32_t idx, bits;
856 int i; 856 int i;
857 if (tlv_len != sizeof(*capa)) { 857 if (tlv_len != sizeof(*capa)) {
858 err = EINVAL; 858 err = EINVAL;
859 goto parse_out; 859 goto parse_out;
860 } 860 }
861 capa = (struct iwm_ucode_capa *)tlv_data; 861 capa = (struct iwm_ucode_capa *)tlv_data;
862 idx = le32toh(capa->api_index); 862 idx = le32toh(capa->api_index);
863 bits = le32toh(capa->api_capa); 863 bits = le32toh(capa->api_capa);
864 if (idx >= howmany(IWM_NUM_UCODE_TLV_CAPA, 32)) { 864 if (idx >= howmany(IWM_NUM_UCODE_TLV_CAPA, 32)) {
865 err = EINVAL; 865 err = EINVAL;
866 goto parse_out; 866 goto parse_out;
867 } 867 }
868 for (i = 0; i < 32; i++) { 868 for (i = 0; i < 32; i++) {
869 if (!ISSET(bits, __BIT(i))) 869 if (!ISSET(bits, __BIT(i)))
870 continue; 870 continue;
871 setbit(sc->sc_enabled_capa, i + (32 * idx)); 871 setbit(sc->sc_enabled_capa, i + (32 * idx));
872 } 872 }
873 break; 873 break;
874 } 874 }
875 875
876 case IWM_UCODE_TLV_FW_UNDOCUMENTED1: 876 case IWM_UCODE_TLV_FW_UNDOCUMENTED1:
877 case IWM_UCODE_TLV_SDIO_ADMA_ADDR: 877 case IWM_UCODE_TLV_SDIO_ADMA_ADDR:
878 case IWM_UCODE_TLV_FW_GSCAN_CAPA: 878 case IWM_UCODE_TLV_FW_GSCAN_CAPA:
879 case IWM_UCODE_TLV_FW_MEM_SEG: 879 case IWM_UCODE_TLV_FW_MEM_SEG:
880 /* ignore, not used by current driver */ 880 /* ignore, not used by current driver */
881 break; 881 break;
882 882
883 case IWM_UCODE_TLV_SEC_RT_USNIFFER: 883 case IWM_UCODE_TLV_SEC_RT_USNIFFER:
884 err = iwm_firmware_store_section(sc, 884 err = iwm_firmware_store_section(sc,
885 IWM_UCODE_TYPE_REGULAR_USNIFFER, tlv_data, 885 IWM_UCODE_TYPE_REGULAR_USNIFFER, tlv_data,
886 tlv_len); 886 tlv_len);
887 if (err) 887 if (err)
888 goto parse_out; 888 goto parse_out;
889 break; 889 break;
890 890
891 case IWM_UCODE_TLV_PAGING: { 891 case IWM_UCODE_TLV_PAGING: {
892 uint32_t paging_mem_size; 892 uint32_t paging_mem_size;
893 if (tlv_len != sizeof(paging_mem_size)) { 893 if (tlv_len != sizeof(paging_mem_size)) {
894 err = EINVAL; 894 err = EINVAL;
895 goto parse_out; 895 goto parse_out;
896 } 896 }
897 paging_mem_size = le32toh(*(uint32_t *)tlv_data); 897 paging_mem_size = le32toh(*(uint32_t *)tlv_data);
898 if (paging_mem_size > IWM_MAX_PAGING_IMAGE_SIZE) { 898 if (paging_mem_size > IWM_MAX_PAGING_IMAGE_SIZE) {
899 err = EINVAL; 899 err = EINVAL;
900 goto parse_out; 900 goto parse_out;
901 } 901 }
902 if (paging_mem_size & (IWM_FW_PAGING_SIZE - 1)) { 902 if (paging_mem_size & (IWM_FW_PAGING_SIZE - 1)) {
903 err = EINVAL; 903 err = EINVAL;
904 goto parse_out; 904 goto parse_out;
905 } 905 }
906 fw->fw_sects[IWM_UCODE_TYPE_REGULAR].paging_mem_size = 906 fw->fw_sects[IWM_UCODE_TYPE_REGULAR].paging_mem_size =
907 paging_mem_size; 907 paging_mem_size;
908 fw->fw_sects[IWM_UCODE_TYPE_REGULAR_USNIFFER].paging_mem_size = 908 fw->fw_sects[IWM_UCODE_TYPE_REGULAR_USNIFFER].paging_mem_size =
909 paging_mem_size; 909 paging_mem_size;
910 break; 910 break;
911 } 911 }
912 912
913 case IWM_UCODE_TLV_N_SCAN_CHANNELS: 913 case IWM_UCODE_TLV_N_SCAN_CHANNELS:
914 if (tlv_len != sizeof(uint32_t)) { 914 if (tlv_len != sizeof(uint32_t)) {
915 err = EINVAL; 915 err = EINVAL;
916 goto parse_out; 916 goto parse_out;
917 } 917 }
918 sc->sc_capa_n_scan_channels = 918 sc->sc_capa_n_scan_channels =
919 le32toh(*(uint32_t *)tlv_data); 919 le32toh(*(uint32_t *)tlv_data);
920 break; 920 break;
921 921
922 case IWM_UCODE_TLV_FW_VERSION: 922 case IWM_UCODE_TLV_FW_VERSION:
923 if (tlv_len != sizeof(uint32_t) * 3) { 923 if (tlv_len != sizeof(uint32_t) * 3) {
924 err = EINVAL; 924 err = EINVAL;
925 goto parse_out; 925 goto parse_out;
926 } 926 }
927 snprintf(sc->sc_fwver, sizeof(sc->sc_fwver), 927 snprintf(sc->sc_fwver, sizeof(sc->sc_fwver),
928 "%d.%d.%d", 928 "%d.%d.%d",
929 le32toh(((uint32_t *)tlv_data)[0]), 929 le32toh(((uint32_t *)tlv_data)[0]),
930 le32toh(((uint32_t *)tlv_data)[1]), 930 le32toh(((uint32_t *)tlv_data)[1]),
931 le32toh(((uint32_t *)tlv_data)[2])); 931 le32toh(((uint32_t *)tlv_data)[2]));
932 break; 932 break;
933 933
934 default: 934 default:
935 DPRINTF(("%s: unknown firmware section %d, abort\n", 935 DPRINTF(("%s: unknown firmware section %d, abort\n",
936 DEVNAME(sc), tlv_type)); 936 DEVNAME(sc), tlv_type));
937 err = EINVAL; 937 err = EINVAL;
938 goto parse_out; 938 goto parse_out;
939 } 939 }
940 940
941 len -= roundup(tlv_len, 4); 941 len -= roundup(tlv_len, 4);
942 data += roundup(tlv_len, 4); 942 data += roundup(tlv_len, 4);
943 } 943 }
944 944
945 KASSERT(err == 0); 945 KASSERT(err == 0);
946 946
947 parse_out: 947 parse_out:
948 if (err) { 948 if (err) {
949 aprint_error_dev(sc->sc_dev, 949 aprint_error_dev(sc->sc_dev,
950 "firmware parse error, section type %d\n", tlv_type); 950 "firmware parse error, section type %d\n", tlv_type);
951 } 951 }
952 952
953 if (!(sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)) { 953 if (!(sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)) {
954 aprint_error_dev(sc->sc_dev, 954 aprint_error_dev(sc->sc_dev,
955 "device uses unsupported power ops\n"); 955 "device uses unsupported power ops\n");
956 err = ENOTSUP; 956 err = ENOTSUP;
957 } 957 }
958 958
959 out: 959 out:
960 if (err) 960 if (err)
961 fw->fw_status = IWM_FW_STATUS_NONE; 961 fw->fw_status = IWM_FW_STATUS_NONE;
962 else 962 else
963 fw->fw_status = IWM_FW_STATUS_DONE; 963 fw->fw_status = IWM_FW_STATUS_DONE;
964 wakeup(&sc->sc_fw); 964 wakeup(&sc->sc_fw);
965 965
966 if (err && fw->fw_rawdata != NULL) { 966 if (err && fw->fw_rawdata != NULL) {
967 kmem_free(fw->fw_rawdata, fw->fw_rawsize); 967 kmem_free(fw->fw_rawdata, fw->fw_rawsize);
968 fw->fw_rawdata = NULL; 968 fw->fw_rawdata = NULL;
969 CLR(sc->sc_flags, IWM_FLAG_FW_LOADED); 969 CLR(sc->sc_flags, IWM_FLAG_FW_LOADED);
970 /* don't touch fw->fw_status */ 970 /* don't touch fw->fw_status */
971 memset(fw->fw_sects, 0, sizeof(fw->fw_sects)); 971 memset(fw->fw_sects, 0, sizeof(fw->fw_sects));
972 } 972 }
973 return err; 973 return err;
974} 974}
975 975
976static uint32_t 976static uint32_t
977iwm_read_prph(struct iwm_softc *sc, uint32_t addr) 977iwm_read_prph(struct iwm_softc *sc, uint32_t addr)
978{ 978{
979 IWM_WRITE(sc, 979 IWM_WRITE(sc,
980 IWM_HBUS_TARG_PRPH_RADDR, ((addr & 0x000fffff) | (3 << 24))); 980 IWM_HBUS_TARG_PRPH_RADDR, ((addr & 0x000fffff) | (3 << 24)));
981 IWM_BARRIER_READ_WRITE(sc); 981 IWM_BARRIER_READ_WRITE(sc);
982 return IWM_READ(sc, IWM_HBUS_TARG_PRPH_RDAT); 982 return IWM_READ(sc, IWM_HBUS_TARG_PRPH_RDAT);
983} 983}
984 984
985static void 985static void
986iwm_write_prph(struct iwm_softc *sc, uint32_t addr, uint32_t val) 986iwm_write_prph(struct iwm_softc *sc, uint32_t addr, uint32_t val)
987{ 987{
988 IWM_WRITE(sc, 988 IWM_WRITE(sc,
989 IWM_HBUS_TARG_PRPH_WADDR, ((addr & 0x000fffff) | (3 << 24))); 989 IWM_HBUS_TARG_PRPH_WADDR, ((addr & 0x000fffff) | (3 << 24)));
990 IWM_BARRIER_WRITE(sc); 990 IWM_BARRIER_WRITE(sc);
991 IWM_WRITE(sc, IWM_HBUS_TARG_PRPH_WDAT, val); 991 IWM_WRITE(sc, IWM_HBUS_TARG_PRPH_WDAT, val);
992} 992}
993 993
994#ifdef IWM_DEBUG 994#ifdef IWM_DEBUG
995static int 995static int
996iwm_read_mem(struct iwm_softc *sc, uint32_t addr, void *buf, int dwords) 996iwm_read_mem(struct iwm_softc *sc, uint32_t addr, void *buf, int dwords)
997{ 997{
998 int offs; 998 int offs;
999 uint32_t *vals = buf; 999 uint32_t *vals = buf;
1000 1000
1001 if (iwm_nic_lock(sc)) { 1001 if (iwm_nic_lock(sc)) {
1002 IWM_WRITE(sc, IWM_HBUS_TARG_MEM_RADDR, addr); 1002 IWM_WRITE(sc, IWM_HBUS_TARG_MEM_RADDR, addr);
1003 for (offs = 0; offs < dwords; offs++) 1003 for (offs = 0; offs < dwords; offs++)
1004 vals[offs] = IWM_READ(sc, IWM_HBUS_TARG_MEM_RDAT); 1004 vals[offs] = IWM_READ(sc, IWM_HBUS_TARG_MEM_RDAT);
1005 iwm_nic_unlock(sc); 1005 iwm_nic_unlock(sc);
1006 return 0; 1006 return 0;
1007 } 1007 }
1008 return EBUSY; 1008 return EBUSY;
1009} 1009}
1010#endif 1010#endif
1011 1011
1012static int 1012static int
1013iwm_write_mem(struct iwm_softc *sc, uint32_t addr, const void *buf, int dwords) 1013iwm_write_mem(struct iwm_softc *sc, uint32_t addr, const void *buf, int dwords)
1014{ 1014{
1015 int offs; 1015 int offs;
1016 const uint32_t *vals = buf; 1016 const uint32_t *vals = buf;
1017 1017
1018 if (iwm_nic_lock(sc)) { 1018 if (iwm_nic_lock(sc)) {
1019 IWM_WRITE(sc, IWM_HBUS_TARG_MEM_WADDR, addr); 1019 IWM_WRITE(sc, IWM_HBUS_TARG_MEM_WADDR, addr);
1020 /* WADDR auto-increments */ 1020 /* WADDR auto-increments */
1021 for (offs = 0; offs < dwords; offs++) { 1021 for (offs = 0; offs < dwords; offs++) {
1022 uint32_t val = vals ? vals[offs] : 0; 1022 uint32_t val = vals ? vals[offs] : 0;
1023 IWM_WRITE(sc, IWM_HBUS_TARG_MEM_WDAT, val); 1023 IWM_WRITE(sc, IWM_HBUS_TARG_MEM_WDAT, val);
1024 } 1024 }
1025 iwm_nic_unlock(sc); 1025 iwm_nic_unlock(sc);
1026 return 0; 1026 return 0;
1027 } 1027 }
1028 return EBUSY; 1028 return EBUSY;
1029} 1029}
1030 1030
1031static int 1031static int
1032iwm_write_mem32(struct iwm_softc *sc, uint32_t addr, uint32_t val) 1032iwm_write_mem32(struct iwm_softc *sc, uint32_t addr, uint32_t val)
1033{ 1033{
1034 return iwm_write_mem(sc, addr, &val, 1); 1034 return iwm_write_mem(sc, addr, &val, 1);
1035} 1035}
1036 1036
1037static int 1037static int
1038iwm_poll_bit(struct iwm_softc *sc, int reg, uint32_t bits, uint32_t mask, 1038iwm_poll_bit(struct iwm_softc *sc, int reg, uint32_t bits, uint32_t mask,
1039 int timo) 1039 int timo)
1040{ 1040{
1041 for (;;) { 1041 for (;;) {
1042 if ((IWM_READ(sc, reg) & mask) == (bits & mask)) { 1042 if ((IWM_READ(sc, reg) & mask) == (bits & mask)) {
1043 return 1; 1043 return 1;
1044 } 1044 }
1045 if (timo < 10) { 1045 if (timo < 10) {
1046 return 0; 1046 return 0;
1047 } 1047 }
1048 timo -= 10; 1048 timo -= 10;
1049 DELAY(10); 1049 DELAY(10);
1050 } 1050 }
1051} 1051}
1052 1052
1053static int 1053static int
1054iwm_nic_lock(struct iwm_softc *sc) 1054iwm_nic_lock(struct iwm_softc *sc)
1055{ 1055{
1056 int rv = 0; 1056 int rv = 0;
1057 1057
1058 if (sc->sc_cmd_hold_nic_awake) 1058 if (sc->sc_cmd_hold_nic_awake)
1059 return 1; 1059 return 1;
1060 1060
1061 IWM_SETBITS(sc, IWM_CSR_GP_CNTRL, 1061 IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
1062 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 1062 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1063 1063
1064 if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000) 1064 if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000)
1065 DELAY(2); 1065 DELAY(2);
1066 1066
1067 if (iwm_poll_bit(sc, IWM_CSR_GP_CNTRL, 1067 if (iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
1068 IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, 1068 IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
1069 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY 1069 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
1070 | IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP, 15000)) { 1070 | IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP, 15000)) {
1071 rv = 1; 1071 rv = 1;
1072 } else { 1072 } else {
1073 DPRINTF(("%s: resetting device via NMI\n", DEVNAME(sc))); 1073 DPRINTF(("%s: resetting device via NMI\n", DEVNAME(sc)));
1074 IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_FORCE_NMI); 1074 IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_FORCE_NMI);
1075 } 1075 }
1076 1076
1077 return rv; 1077 return rv;
1078} 1078}
1079 1079
1080static void 1080static void
1081iwm_nic_unlock(struct iwm_softc *sc) 1081iwm_nic_unlock(struct iwm_softc *sc)
1082{ 1082{
1083 1083
1084 if (sc->sc_cmd_hold_nic_awake) 1084 if (sc->sc_cmd_hold_nic_awake)
1085 return; 1085 return;
1086 1086
1087 IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL, 1087 IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
1088 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 1088 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1089} 1089}
1090 1090
1091static void 1091static void
1092iwm_set_bits_mask_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits, 1092iwm_set_bits_mask_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits,
1093 uint32_t mask) 1093 uint32_t mask)
1094{ 1094{
1095 uint32_t val; 1095 uint32_t val;
1096 1096
1097 /* XXX: no error path? */ 1097 /* XXX: no error path? */
1098 if (iwm_nic_lock(sc)) { 1098 if (iwm_nic_lock(sc)) {
1099 val = iwm_read_prph(sc, reg) & mask; 1099 val = iwm_read_prph(sc, reg) & mask;
1100 val |= bits; 1100 val |= bits;
1101 iwm_write_prph(sc, reg, val); 1101 iwm_write_prph(sc, reg, val);
1102 iwm_nic_unlock(sc); 1102 iwm_nic_unlock(sc);
1103 } 1103 }
1104} 1104}
1105 1105
1106static void 1106static void
1107iwm_set_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits) 1107iwm_set_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits)
1108{ 1108{
@@ -6733,1574 +6733,1576 @@ iwm_init_hw(struct iwm_softc *sc) @@ -6733,1574 +6733,1576 @@ iwm_init_hw(struct iwm_softc *sc)
6733 iwm_stop_device(sc); 6733 iwm_stop_device(sc);
6734 return err; 6734 return err;
6735} 6735}
6736 6736
6737/* Allow multicast from our BSSID. */ 6737/* Allow multicast from our BSSID. */
6738static int 6738static int
6739iwm_allow_mcast(struct iwm_softc *sc) 6739iwm_allow_mcast(struct iwm_softc *sc)
6740{ 6740{
6741 struct ieee80211com *ic = &sc->sc_ic; 6741 struct ieee80211com *ic = &sc->sc_ic;
6742 struct ieee80211_node *ni = ic->ic_bss; 6742 struct ieee80211_node *ni = ic->ic_bss;
6743 struct iwm_mcast_filter_cmd *cmd; 6743 struct iwm_mcast_filter_cmd *cmd;
6744 size_t size; 6744 size_t size;
6745 int err; 6745 int err;
6746 6746
6747 size = roundup(sizeof(*cmd), 4); 6747 size = roundup(sizeof(*cmd), 4);
6748 cmd = kmem_intr_zalloc(size, KM_NOSLEEP); 6748 cmd = kmem_intr_zalloc(size, KM_NOSLEEP);
6749 if (cmd == NULL) 6749 if (cmd == NULL)
6750 return ENOMEM; 6750 return ENOMEM;
6751 cmd->filter_own = 1; 6751 cmd->filter_own = 1;
6752 cmd->port_id = 0; 6752 cmd->port_id = 0;
6753 cmd->count = 0; 6753 cmd->count = 0;
6754 cmd->pass_all = 1; 6754 cmd->pass_all = 1;
6755 IEEE80211_ADDR_COPY(cmd->bssid, ni->ni_bssid); 6755 IEEE80211_ADDR_COPY(cmd->bssid, ni->ni_bssid);
6756 6756
6757 err = iwm_send_cmd_pdu(sc, IWM_MCAST_FILTER_CMD, 0, size, cmd); 6757 err = iwm_send_cmd_pdu(sc, IWM_MCAST_FILTER_CMD, 0, size, cmd);
6758 kmem_intr_free(cmd, size); 6758 kmem_intr_free(cmd, size);
6759 return err; 6759 return err;
6760} 6760}
6761 6761
6762static int 6762static int
6763iwm_init(struct ifnet *ifp) 6763iwm_init(struct ifnet *ifp)
6764{ 6764{
6765 struct iwm_softc *sc = ifp->if_softc; 6765 struct iwm_softc *sc = ifp->if_softc;
6766 int err; 6766 int err;
6767 6767
6768 if (ISSET(sc->sc_flags, IWM_FLAG_HW_INITED)) 6768 if (ISSET(sc->sc_flags, IWM_FLAG_HW_INITED))
6769 return 0; 6769 return 0;
6770 6770
6771 sc->sc_generation++; 6771 sc->sc_generation++;
6772 sc->sc_flags &= ~IWM_FLAG_STOPPED; 6772 sc->sc_flags &= ~IWM_FLAG_STOPPED;
6773 6773
6774 err = iwm_init_hw(sc); 6774 err = iwm_init_hw(sc);
6775 if (err) { 6775 if (err) {
6776 iwm_stop(ifp, 1); 6776 iwm_stop(ifp, 1);
6777 return err; 6777 return err;
6778 } 6778 }
6779 6779
6780 ifp->if_flags &= ~IFF_OACTIVE; 6780 ifp->if_flags &= ~IFF_OACTIVE;
6781 ifp->if_flags |= IFF_RUNNING; 6781 ifp->if_flags |= IFF_RUNNING;
6782 6782
6783 ieee80211_begin_scan(&sc->sc_ic, 0); 6783 ieee80211_begin_scan(&sc->sc_ic, 0);
6784 SET(sc->sc_flags, IWM_FLAG_HW_INITED); 6784 SET(sc->sc_flags, IWM_FLAG_HW_INITED);
6785 6785
6786 return 0; 6786 return 0;
6787} 6787}
6788 6788
6789static void 6789static void
6790iwm_start(struct ifnet *ifp) 6790iwm_start(struct ifnet *ifp)
6791{ 6791{
6792 struct iwm_softc *sc = ifp->if_softc; 6792 struct iwm_softc *sc = ifp->if_softc;
6793 struct ieee80211com *ic = &sc->sc_ic; 6793 struct ieee80211com *ic = &sc->sc_ic;
6794 struct ieee80211_node *ni; 6794 struct ieee80211_node *ni;
6795 struct ether_header *eh; 6795 struct ether_header *eh;
6796 struct mbuf *m; 6796 struct mbuf *m;
6797 int ac; 6797 int ac;
6798 6798
6799 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 6799 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
6800 return; 6800 return;
6801 6801
6802 for (;;) { 6802 for (;;) {
6803 /* why isn't this done per-queue? */ 6803 /* why isn't this done per-queue? */
6804 if (sc->qfullmsk != 0) { 6804 if (sc->qfullmsk != 0) {
6805 ifp->if_flags |= IFF_OACTIVE; 6805 ifp->if_flags |= IFF_OACTIVE;
6806 break; 6806 break;
6807 } 6807 }
6808 6808
6809 /* need to send management frames even if we're not RUNning */ 6809 /* need to send management frames even if we're not RUNning */
6810 IF_DEQUEUE(&ic->ic_mgtq, m); 6810 IF_DEQUEUE(&ic->ic_mgtq, m);
6811 if (m) { 6811 if (m) {
6812 ni = M_GETCTX(m, struct ieee80211_node *); 6812 ni = M_GETCTX(m, struct ieee80211_node *);
6813 M_CLEARCTX(m); 6813 M_CLEARCTX(m);
6814 ac = WME_AC_BE; 6814 ac = WME_AC_BE;
6815 goto sendit; 6815 goto sendit;
6816 } 6816 }
6817 if (ic->ic_state != IEEE80211_S_RUN) { 6817 if (ic->ic_state != IEEE80211_S_RUN) {
6818 break; 6818 break;
6819 } 6819 }
6820 6820
6821 IFQ_DEQUEUE(&ifp->if_snd, m); 6821 IFQ_DEQUEUE(&ifp->if_snd, m);
6822 if (m == NULL) 6822 if (m == NULL)
6823 break; 6823 break;
6824 6824
6825 if (m->m_len < sizeof (*eh) && 6825 if (m->m_len < sizeof (*eh) &&
6826 (m = m_pullup(m, sizeof (*eh))) == NULL) { 6826 (m = m_pullup(m, sizeof (*eh))) == NULL) {
6827 ifp->if_oerrors++; 6827 ifp->if_oerrors++;
6828 continue; 6828 continue;
6829 } 6829 }
6830 6830
6831 eh = mtod(m, struct ether_header *); 6831 eh = mtod(m, struct ether_header *);
6832 ni = ieee80211_find_txnode(ic, eh->ether_dhost); 6832 ni = ieee80211_find_txnode(ic, eh->ether_dhost);
6833 if (ni == NULL) { 6833 if (ni == NULL) {
6834 m_freem(m); 6834 m_freem(m);
6835 ifp->if_oerrors++; 6835 ifp->if_oerrors++;
6836 continue; 6836 continue;
6837 } 6837 }
6838 6838
6839 /* classify mbuf so we can find which tx ring to use */ 6839 /* classify mbuf so we can find which tx ring to use */
6840 if (ieee80211_classify(ic, m, ni) != 0) { 6840 if (ieee80211_classify(ic, m, ni) != 0) {
6841 m_freem(m); 6841 m_freem(m);
6842 ieee80211_free_node(ni); 6842 ieee80211_free_node(ni);
6843 ifp->if_oerrors++; 6843 ifp->if_oerrors++;
6844 continue; 6844 continue;
6845 } 6845 }
6846 6846
6847 /* No QoS encapsulation for EAPOL frames. */ 6847 /* No QoS encapsulation for EAPOL frames. */
6848 ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ? 6848 ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ?
6849 M_WME_GETAC(m) : WME_AC_BE; 6849 M_WME_GETAC(m) : WME_AC_BE;
6850 6850
6851 bpf_mtap(ifp, m); 6851 bpf_mtap(ifp, m);
6852 6852
6853 if ((m = ieee80211_encap(ic, m, ni)) == NULL) { 6853 if ((m = ieee80211_encap(ic, m, ni)) == NULL) {
6854 ieee80211_free_node(ni); 6854 ieee80211_free_node(ni);
6855 ifp->if_oerrors++; 6855 ifp->if_oerrors++;
6856 continue; 6856 continue;
6857 } 6857 }
6858 6858
6859 sendit: 6859 sendit:
6860 bpf_mtap3(ic->ic_rawbpf, m); 6860 bpf_mtap3(ic->ic_rawbpf, m);
6861 6861
6862 if (iwm_tx(sc, m, ni, ac) != 0) { 6862 if (iwm_tx(sc, m, ni, ac) != 0) {
6863 ieee80211_free_node(ni); 6863 ieee80211_free_node(ni);
6864 ifp->if_oerrors++; 6864 ifp->if_oerrors++;
6865 continue; 6865 continue;
6866 } 6866 }
6867 6867
6868 if (ifp->if_flags & IFF_UP) { 6868 if (ifp->if_flags & IFF_UP) {
6869 sc->sc_tx_timer = 15; 6869 sc->sc_tx_timer = 15;
6870 ifp->if_timer = 1; 6870 ifp->if_timer = 1;
6871 } 6871 }
6872 } 6872 }
6873} 6873}
6874 6874
6875static void 6875static void
6876iwm_stop(struct ifnet *ifp, int disable) 6876iwm_stop(struct ifnet *ifp, int disable)
6877{ 6877{
6878 struct iwm_softc *sc = ifp->if_softc; 6878 struct iwm_softc *sc = ifp->if_softc;
6879 struct ieee80211com *ic = &sc->sc_ic; 6879 struct ieee80211com *ic = &sc->sc_ic;
6880 struct iwm_node *in = (struct iwm_node *)ic->ic_bss; 6880 struct iwm_node *in = (struct iwm_node *)ic->ic_bss;
6881 6881
6882 sc->sc_flags &= ~IWM_FLAG_HW_INITED; 6882 sc->sc_flags &= ~IWM_FLAG_HW_INITED;
6883 sc->sc_flags |= IWM_FLAG_STOPPED; 6883 sc->sc_flags |= IWM_FLAG_STOPPED;
6884 sc->sc_generation++; 6884 sc->sc_generation++;
6885 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 6885 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
6886 6886
6887 if (in) 6887 if (in)
6888 in->in_phyctxt = NULL; 6888 in->in_phyctxt = NULL;
6889 6889
6890 if (ic->ic_state != IEEE80211_S_INIT) 6890 if (ic->ic_state != IEEE80211_S_INIT)
6891 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 6891 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
6892 6892
6893 callout_stop(&sc->sc_calib_to); 6893 callout_stop(&sc->sc_calib_to);
6894 iwm_led_blink_stop(sc); 6894 iwm_led_blink_stop(sc);
6895 ifp->if_timer = sc->sc_tx_timer = 0; 6895 ifp->if_timer = sc->sc_tx_timer = 0;
6896 iwm_stop_device(sc); 6896 iwm_stop_device(sc);
6897} 6897}
6898 6898
6899static void 6899static void
6900iwm_watchdog(struct ifnet *ifp) 6900iwm_watchdog(struct ifnet *ifp)
6901{ 6901{
6902 struct iwm_softc *sc = ifp->if_softc; 6902 struct iwm_softc *sc = ifp->if_softc;
6903 6903
6904 ifp->if_timer = 0; 6904 ifp->if_timer = 0;
6905 if (sc->sc_tx_timer > 0) { 6905 if (sc->sc_tx_timer > 0) {
6906 if (--sc->sc_tx_timer == 0) { 6906 if (--sc->sc_tx_timer == 0) {
6907 aprint_error_dev(sc->sc_dev, "device timeout\n"); 6907 aprint_error_dev(sc->sc_dev, "device timeout\n");
6908#ifdef IWM_DEBUG 6908#ifdef IWM_DEBUG
6909 iwm_nic_error(sc); 6909 iwm_nic_error(sc);
6910#endif 6910#endif
6911 ifp->if_flags &= ~IFF_UP; 6911 ifp->if_flags &= ~IFF_UP;
6912 iwm_stop(ifp, 1); 6912 iwm_stop(ifp, 1);
6913 ifp->if_oerrors++; 6913 ifp->if_oerrors++;
6914 return; 6914 return;
6915 } 6915 }
6916 ifp->if_timer = 1; 6916 ifp->if_timer = 1;
6917 } 6917 }
6918 6918
6919 ieee80211_watchdog(&sc->sc_ic); 6919 ieee80211_watchdog(&sc->sc_ic);
6920} 6920}
6921 6921
6922static int 6922static int
6923iwm_ioctl(struct ifnet *ifp, u_long cmd, void *data) 6923iwm_ioctl(struct ifnet *ifp, u_long cmd, void *data)
6924{ 6924{
6925 struct iwm_softc *sc = ifp->if_softc; 6925 struct iwm_softc *sc = ifp->if_softc;
6926 struct ieee80211com *ic = &sc->sc_ic; 6926 struct ieee80211com *ic = &sc->sc_ic;
6927 const struct sockaddr *sa; 6927 const struct sockaddr *sa;
6928 int s, err = 0; 6928 int s, err = 0;
6929 6929
6930 s = splnet(); 6930 s = splnet();
6931 6931
6932 switch (cmd) { 6932 switch (cmd) {
6933 case SIOCSIFADDR: 6933 case SIOCSIFADDR:
6934 ifp->if_flags |= IFF_UP; 6934 ifp->if_flags |= IFF_UP;
6935 /* FALLTHROUGH */ 6935 /* FALLTHROUGH */
6936 case SIOCSIFFLAGS: 6936 case SIOCSIFFLAGS:
6937 err = ifioctl_common(ifp, cmd, data); 6937 err = ifioctl_common(ifp, cmd, data);
6938 if (err) 6938 if (err)
6939 break; 6939 break;
6940 if (ifp->if_flags & IFF_UP) { 6940 if (ifp->if_flags & IFF_UP) {
6941 if (!(ifp->if_flags & IFF_RUNNING)) { 6941 if (!(ifp->if_flags & IFF_RUNNING)) {
6942 err = iwm_init(ifp); 6942 err = iwm_init(ifp);
6943 if (err) 6943 if (err)
6944 ifp->if_flags &= ~IFF_UP; 6944 ifp->if_flags &= ~IFF_UP;
6945 } 6945 }
6946 } else { 6946 } else {
6947 if (ifp->if_flags & IFF_RUNNING) 6947 if (ifp->if_flags & IFF_RUNNING)
6948 iwm_stop(ifp, 1); 6948 iwm_stop(ifp, 1);
6949 } 6949 }
6950 break; 6950 break;
6951 6951
6952 case SIOCADDMULTI: 6952 case SIOCADDMULTI:
6953 case SIOCDELMULTI: 6953 case SIOCDELMULTI:
6954 if (!ISSET(sc->sc_flags, IWM_FLAG_ATTACHED)) { 6954 if (!ISSET(sc->sc_flags, IWM_FLAG_ATTACHED)) {
6955 err = ENXIO; 6955 err = ENXIO;
6956 break; 6956 break;
6957 } 6957 }
6958 sa = ifreq_getaddr(SIOCADDMULTI, (struct ifreq *)data); 6958 sa = ifreq_getaddr(SIOCADDMULTI, (struct ifreq *)data);
6959 err = (cmd == SIOCADDMULTI) ? 6959 err = (cmd == SIOCADDMULTI) ?
6960 ether_addmulti(sa, &sc->sc_ec) : 6960 ether_addmulti(sa, &sc->sc_ec) :
6961 ether_delmulti(sa, &sc->sc_ec); 6961 ether_delmulti(sa, &sc->sc_ec);
6962 if (err == ENETRESET) 6962 if (err == ENETRESET)
6963 err = 0; 6963 err = 0;
6964 break; 6964 break;
6965 6965
6966 default: 6966 default:
6967 if (!ISSET(sc->sc_flags, IWM_FLAG_ATTACHED)) { 6967 if (!ISSET(sc->sc_flags, IWM_FLAG_ATTACHED)) {
6968 err = ether_ioctl(ifp, cmd, data); 6968 err = ether_ioctl(ifp, cmd, data);
6969 break; 6969 break;
6970 } 6970 }
6971 err = ieee80211_ioctl(ic, cmd, data); 6971 err = ieee80211_ioctl(ic, cmd, data);
6972 break; 6972 break;
6973 } 6973 }
6974 6974
6975 if (err == ENETRESET) { 6975 if (err == ENETRESET) {
6976 err = 0; 6976 err = 0;
6977 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == 6977 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
6978 (IFF_UP | IFF_RUNNING)) { 6978 (IFF_UP | IFF_RUNNING)) {
6979 iwm_stop(ifp, 0); 6979 iwm_stop(ifp, 0);
6980 err = iwm_init(ifp); 6980 err = iwm_init(ifp);
6981 } 6981 }
6982 } 6982 }
6983 6983
6984 splx(s); 6984 splx(s);
6985 return err; 6985 return err;
6986} 6986}
6987 6987
6988/* 6988/*
6989 * Note: This structure is read from the device with IO accesses, 6989 * Note: This structure is read from the device with IO accesses,
6990 * and the reading already does the endian conversion. As it is 6990 * and the reading already does the endian conversion. As it is
6991 * read with uint32_t-sized accesses, any members with a different size 6991 * read with uint32_t-sized accesses, any members with a different size
6992 * need to be ordered correctly though! 6992 * need to be ordered correctly though!
6993 */ 6993 */
6994struct iwm_error_event_table { 6994struct iwm_error_event_table {
6995 uint32_t valid; /* (nonzero) valid, (0) log is empty */ 6995 uint32_t valid; /* (nonzero) valid, (0) log is empty */
6996 uint32_t error_id; /* type of error */ 6996 uint32_t error_id; /* type of error */
6997 uint32_t trm_hw_status0; /* TRM HW status */ 6997 uint32_t trm_hw_status0; /* TRM HW status */
6998 uint32_t trm_hw_status1; /* TRM HW status */ 6998 uint32_t trm_hw_status1; /* TRM HW status */
6999 uint32_t blink2; /* branch link */ 6999 uint32_t blink2; /* branch link */
7000 uint32_t ilink1; /* interrupt link */ 7000 uint32_t ilink1; /* interrupt link */
7001 uint32_t ilink2; /* interrupt link */ 7001 uint32_t ilink2; /* interrupt link */
7002 uint32_t data1; /* error-specific data */ 7002 uint32_t data1; /* error-specific data */
7003 uint32_t data2; /* error-specific data */ 7003 uint32_t data2; /* error-specific data */
7004 uint32_t data3; /* error-specific data */ 7004 uint32_t data3; /* error-specific data */
7005 uint32_t bcon_time; /* beacon timer */ 7005 uint32_t bcon_time; /* beacon timer */
7006 uint32_t tsf_low; /* network timestamp function timer */ 7006 uint32_t tsf_low; /* network timestamp function timer */
7007 uint32_t tsf_hi; /* network timestamp function timer */ 7007 uint32_t tsf_hi; /* network timestamp function timer */
7008 uint32_t gp1; /* GP1 timer register */ 7008 uint32_t gp1; /* GP1 timer register */
7009 uint32_t gp2; /* GP2 timer register */ 7009 uint32_t gp2; /* GP2 timer register */
7010 uint32_t fw_rev_type; /* firmware revision type */ 7010 uint32_t fw_rev_type; /* firmware revision type */
7011 uint32_t major; /* uCode version major */ 7011 uint32_t major; /* uCode version major */
7012 uint32_t minor; /* uCode version minor */ 7012 uint32_t minor; /* uCode version minor */
7013 uint32_t hw_ver; /* HW Silicon version */ 7013 uint32_t hw_ver; /* HW Silicon version */
7014 uint32_t brd_ver; /* HW board version */ 7014 uint32_t brd_ver; /* HW board version */
7015 uint32_t log_pc; /* log program counter */ 7015 uint32_t log_pc; /* log program counter */
7016 uint32_t frame_ptr; /* frame pointer */ 7016 uint32_t frame_ptr; /* frame pointer */
7017 uint32_t stack_ptr; /* stack pointer */ 7017 uint32_t stack_ptr; /* stack pointer */
7018 uint32_t hcmd; /* last host command header */ 7018 uint32_t hcmd; /* last host command header */
7019 uint32_t isr0; /* isr status register LMPM_NIC_ISR0: 7019 uint32_t isr0; /* isr status register LMPM_NIC_ISR0:
7020 * rxtx_flag */ 7020 * rxtx_flag */
7021 uint32_t isr1; /* isr status register LMPM_NIC_ISR1: 7021 uint32_t isr1; /* isr status register LMPM_NIC_ISR1:
7022 * host_flag */ 7022 * host_flag */
7023 uint32_t isr2; /* isr status register LMPM_NIC_ISR2: 7023 uint32_t isr2; /* isr status register LMPM_NIC_ISR2:
7024 * enc_flag */ 7024 * enc_flag */
7025 uint32_t isr3; /* isr status register LMPM_NIC_ISR3: 7025 uint32_t isr3; /* isr status register LMPM_NIC_ISR3:
7026 * time_flag */ 7026 * time_flag */
7027 uint32_t isr4; /* isr status register LMPM_NIC_ISR4: 7027 uint32_t isr4; /* isr status register LMPM_NIC_ISR4:
7028 * wico interrupt */ 7028 * wico interrupt */
7029 uint32_t last_cmd_id; /* last HCMD id handled by the firmware */ 7029 uint32_t last_cmd_id; /* last HCMD id handled by the firmware */
7030 uint32_t wait_event; /* wait event() caller address */ 7030 uint32_t wait_event; /* wait event() caller address */
7031 uint32_t l2p_control; /* L2pControlField */ 7031 uint32_t l2p_control; /* L2pControlField */
7032 uint32_t l2p_duration; /* L2pDurationField */ 7032 uint32_t l2p_duration; /* L2pDurationField */
7033 uint32_t l2p_mhvalid; /* L2pMhValidBits */ 7033 uint32_t l2p_mhvalid; /* L2pMhValidBits */
7034 uint32_t l2p_addr_match; /* L2pAddrMatchStat */ 7034 uint32_t l2p_addr_match; /* L2pAddrMatchStat */
7035 uint32_t lmpm_pmg_sel; /* indicate which clocks are turned on 7035 uint32_t lmpm_pmg_sel; /* indicate which clocks are turned on
7036 * (LMPM_PMG_SEL) */ 7036 * (LMPM_PMG_SEL) */
7037 uint32_t u_timestamp; /* indicate when the date and time of the 7037 uint32_t u_timestamp; /* indicate when the date and time of the
7038 * compilation */ 7038 * compilation */
7039 uint32_t flow_handler; /* FH read/write pointers, RX credit */ 7039 uint32_t flow_handler; /* FH read/write pointers, RX credit */
7040} __packed /* LOG_ERROR_TABLE_API_S_VER_3 */; 7040} __packed /* LOG_ERROR_TABLE_API_S_VER_3 */;
7041 7041
7042/* 7042/*
7043 * UMAC error struct - relevant starting from family 8000 chip. 7043 * UMAC error struct - relevant starting from family 8000 chip.
7044 * Note: This structure is read from the device with IO accesses, 7044 * Note: This structure is read from the device with IO accesses,
7045 * and the reading already does the endian conversion. As it is 7045 * and the reading already does the endian conversion. As it is
7046 * read with u32-sized accesses, any members with a different size 7046 * read with u32-sized accesses, any members with a different size
7047 * need to be ordered correctly though! 7047 * need to be ordered correctly though!
7048 */ 7048 */
7049struct iwm_umac_error_event_table { 7049struct iwm_umac_error_event_table {
7050 uint32_t valid; /* (nonzero) valid, (0) log is empty */ 7050 uint32_t valid; /* (nonzero) valid, (0) log is empty */
7051 uint32_t error_id; /* type of error */ 7051 uint32_t error_id; /* type of error */
7052 uint32_t blink1; /* branch link */ 7052 uint32_t blink1; /* branch link */
7053 uint32_t blink2; /* branch link */ 7053 uint32_t blink2; /* branch link */
7054 uint32_t ilink1; /* interrupt link */ 7054 uint32_t ilink1; /* interrupt link */
7055 uint32_t ilink2; /* interrupt link */ 7055 uint32_t ilink2; /* interrupt link */
7056 uint32_t data1; /* error-specific data */ 7056 uint32_t data1; /* error-specific data */
7057 uint32_t data2; /* error-specific data */ 7057 uint32_t data2; /* error-specific data */
7058 uint32_t data3; /* error-specific data */ 7058 uint32_t data3; /* error-specific data */
7059 uint32_t umac_major; 7059 uint32_t umac_major;
7060 uint32_t umac_minor; 7060 uint32_t umac_minor;
7061 uint32_t frame_pointer; /* core register 27 */ 7061 uint32_t frame_pointer; /* core register 27 */
7062 uint32_t stack_pointer; /* core register 28 */ 7062 uint32_t stack_pointer; /* core register 28 */
7063 uint32_t cmd_header; /* latest host cmd sent to UMAC */ 7063 uint32_t cmd_header; /* latest host cmd sent to UMAC */
7064 uint32_t nic_isr_pref; /* ISR status register */ 7064 uint32_t nic_isr_pref; /* ISR status register */
7065} __packed; 7065} __packed;
7066 7066
7067#define ERROR_START_OFFSET (1 * sizeof(uint32_t)) 7067#define ERROR_START_OFFSET (1 * sizeof(uint32_t))
7068#define ERROR_ELEM_SIZE (7 * sizeof(uint32_t)) 7068#define ERROR_ELEM_SIZE (7 * sizeof(uint32_t))
7069 7069
7070#ifdef IWM_DEBUG 7070#ifdef IWM_DEBUG
7071static const struct { 7071static const struct {
7072 const char *name; 7072 const char *name;
7073 uint8_t num; 7073 uint8_t num;
7074} advanced_lookup[] = { 7074} advanced_lookup[] = {
7075 { "NMI_INTERRUPT_WDG", 0x34 }, 7075 { "NMI_INTERRUPT_WDG", 0x34 },
7076 { "SYSASSERT", 0x35 }, 7076 { "SYSASSERT", 0x35 },
7077 { "UCODE_VERSION_MISMATCH", 0x37 }, 7077 { "UCODE_VERSION_MISMATCH", 0x37 },
7078 { "BAD_COMMAND", 0x38 }, 7078 { "BAD_COMMAND", 0x38 },
7079 { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C }, 7079 { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
7080 { "FATAL_ERROR", 0x3D }, 7080 { "FATAL_ERROR", 0x3D },
7081 { "NMI_TRM_HW_ERR", 0x46 }, 7081 { "NMI_TRM_HW_ERR", 0x46 },
7082 { "NMI_INTERRUPT_TRM", 0x4C }, 7082 { "NMI_INTERRUPT_TRM", 0x4C },
7083 { "NMI_INTERRUPT_BREAK_POINT", 0x54 }, 7083 { "NMI_INTERRUPT_BREAK_POINT", 0x54 },
7084 { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C }, 7084 { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C },
7085 { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 }, 7085 { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 },
7086 { "NMI_INTERRUPT_HOST", 0x66 }, 7086 { "NMI_INTERRUPT_HOST", 0x66 },
7087 { "NMI_INTERRUPT_ACTION_PT", 0x7C }, 7087 { "NMI_INTERRUPT_ACTION_PT", 0x7C },
7088 { "NMI_INTERRUPT_UNKNOWN", 0x84 }, 7088 { "NMI_INTERRUPT_UNKNOWN", 0x84 },
7089 { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 }, 7089 { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 },
7090 { "ADVANCED_SYSASSERT", 0 }, 7090 { "ADVANCED_SYSASSERT", 0 },
7091}; 7091};
7092 7092
7093static const char * 7093static const char *
7094iwm_desc_lookup(uint32_t num) 7094iwm_desc_lookup(uint32_t num)
7095{ 7095{
7096 int i; 7096 int i;
7097 7097
7098 for (i = 0; i < __arraycount(advanced_lookup) - 1; i++) 7098 for (i = 0; i < __arraycount(advanced_lookup) - 1; i++)
7099 if (advanced_lookup[i].num == num) 7099 if (advanced_lookup[i].num == num)
7100 return advanced_lookup[i].name; 7100 return advanced_lookup[i].name;
7101 7101
7102 /* No entry matches 'num', so it is the last: ADVANCED_SYSASSERT */ 7102 /* No entry matches 'num', so it is the last: ADVANCED_SYSASSERT */
7103 return advanced_lookup[i].name; 7103 return advanced_lookup[i].name;
7104} 7104}
7105 7105
7106/* 7106/*
7107 * Support for dumping the error log seemed like a good idea ... 7107 * Support for dumping the error log seemed like a good idea ...
7108 * but it's mostly hex junk and the only sensible thing is the 7108 * but it's mostly hex junk and the only sensible thing is the
7109 * hw/ucode revision (which we know anyway). Since it's here, 7109 * hw/ucode revision (which we know anyway). Since it's here,
7110 * I'll just leave it in, just in case e.g. the Intel guys want to 7110 * I'll just leave it in, just in case e.g. the Intel guys want to
7111 * help us decipher some "ADVANCED_SYSASSERT" later. 7111 * help us decipher some "ADVANCED_SYSASSERT" later.
7112 */ 7112 */
7113static void 7113static void
7114iwm_nic_error(struct iwm_softc *sc) 7114iwm_nic_error(struct iwm_softc *sc)
7115{ 7115{
7116 struct iwm_error_event_table t; 7116 struct iwm_error_event_table t;
7117 uint32_t base; 7117 uint32_t base;
7118 7118
7119 aprint_error_dev(sc->sc_dev, "dumping device error log\n"); 7119 aprint_error_dev(sc->sc_dev, "dumping device error log\n");
7120 base = sc->sc_uc.uc_error_event_table; 7120 base = sc->sc_uc.uc_error_event_table;
7121 if (base < 0x800000) { 7121 if (base < 0x800000) {
7122 aprint_error_dev(sc->sc_dev, 7122 aprint_error_dev(sc->sc_dev,
7123 "Invalid error log pointer 0x%08x\n", base); 7123 "Invalid error log pointer 0x%08x\n", base);
7124 return; 7124 return;
7125 } 7125 }
7126 7126
7127 if (iwm_read_mem(sc, base, &t, sizeof(t)/sizeof(uint32_t))) { 7127 if (iwm_read_mem(sc, base, &t, sizeof(t)/sizeof(uint32_t))) {
7128 aprint_error_dev(sc->sc_dev, "reading errlog failed\n"); 7128 aprint_error_dev(sc->sc_dev, "reading errlog failed\n");
7129 return; 7129 return;
7130 } 7130 }
7131 7131
7132 if (!t.valid) { 7132 if (!t.valid) {
7133 aprint_error_dev(sc->sc_dev, "errlog not found, skipping\n"); 7133 aprint_error_dev(sc->sc_dev, "errlog not found, skipping\n");
7134 return; 7134 return;
7135 } 7135 }
7136 7136
7137 if (ERROR_START_OFFSET <= t.valid * ERROR_ELEM_SIZE) { 7137 if (ERROR_START_OFFSET <= t.valid * ERROR_ELEM_SIZE) {
7138 aprint_error_dev(sc->sc_dev, "Start Error Log Dump:\n"); 7138 aprint_error_dev(sc->sc_dev, "Start Error Log Dump:\n");
7139 aprint_error_dev(sc->sc_dev, "Status: 0x%x, count: %d\n", 7139 aprint_error_dev(sc->sc_dev, "Status: 0x%x, count: %d\n",
7140 sc->sc_flags, t.valid); 7140 sc->sc_flags, t.valid);
7141 } 7141 }
7142 7142
7143 aprint_error_dev(sc->sc_dev, "%08X | %-28s\n", t.error_id, 7143 aprint_error_dev(sc->sc_dev, "%08X | %-28s\n", t.error_id,
7144 iwm_desc_lookup(t.error_id)); 7144 iwm_desc_lookup(t.error_id));
7145 aprint_error_dev(sc->sc_dev, "%08X | trm_hw_status0\n", 7145 aprint_error_dev(sc->sc_dev, "%08X | trm_hw_status0\n",
7146 t.trm_hw_status0); 7146 t.trm_hw_status0);
7147 aprint_error_dev(sc->sc_dev, "%08X | trm_hw_status1\n", 7147 aprint_error_dev(sc->sc_dev, "%08X | trm_hw_status1\n",
7148 t.trm_hw_status1); 7148 t.trm_hw_status1);
7149 aprint_error_dev(sc->sc_dev, "%08X | branchlink2\n", t.blink2); 7149 aprint_error_dev(sc->sc_dev, "%08X | branchlink2\n", t.blink2);
7150 aprint_error_dev(sc->sc_dev, "%08X | interruptlink1\n", t.ilink1); 7150 aprint_error_dev(sc->sc_dev, "%08X | interruptlink1\n", t.ilink1);
7151 aprint_error_dev(sc->sc_dev, "%08X | interruptlink2\n", t.ilink2); 7151 aprint_error_dev(sc->sc_dev, "%08X | interruptlink2\n", t.ilink2);
7152 aprint_error_dev(sc->sc_dev, "%08X | data1\n", t.data1); 7152 aprint_error_dev(sc->sc_dev, "%08X | data1\n", t.data1);
7153 aprint_error_dev(sc->sc_dev, "%08X | data2\n", t.data2); 7153 aprint_error_dev(sc->sc_dev, "%08X | data2\n", t.data2);
7154 aprint_error_dev(sc->sc_dev, "%08X | data3\n", t.data3); 7154 aprint_error_dev(sc->sc_dev, "%08X | data3\n", t.data3);
7155 aprint_error_dev(sc->sc_dev, "%08X | beacon time\n", t.bcon_time); 7155 aprint_error_dev(sc->sc_dev, "%08X | beacon time\n", t.bcon_time);
7156 aprint_error_dev(sc->sc_dev, "%08X | tsf low\n", t.tsf_low); 7156 aprint_error_dev(sc->sc_dev, "%08X | tsf low\n", t.tsf_low);
7157 aprint_error_dev(sc->sc_dev, "%08X | tsf hi\n", t.tsf_hi); 7157 aprint_error_dev(sc->sc_dev, "%08X | tsf hi\n", t.tsf_hi);
7158 aprint_error_dev(sc->sc_dev, "%08X | time gp1\n", t.gp1); 7158 aprint_error_dev(sc->sc_dev, "%08X | time gp1\n", t.gp1);
7159 aprint_error_dev(sc->sc_dev, "%08X | time gp2\n", t.gp2); 7159 aprint_error_dev(sc->sc_dev, "%08X | time gp2\n", t.gp2);
7160 aprint_error_dev(sc->sc_dev, "%08X | uCode revision type\n", 7160 aprint_error_dev(sc->sc_dev, "%08X | uCode revision type\n",
7161 t.fw_rev_type); 7161 t.fw_rev_type);
7162 aprint_error_dev(sc->sc_dev, "%08X | uCode version major\n", 7162 aprint_error_dev(sc->sc_dev, "%08X | uCode version major\n",
7163 t.major); 7163 t.major);
7164 aprint_error_dev(sc->sc_dev, "%08X | uCode version minor\n", 7164 aprint_error_dev(sc->sc_dev, "%08X | uCode version minor\n",
7165 t.minor); 7165 t.minor);
7166 aprint_error_dev(sc->sc_dev, "%08X | hw version\n", t.hw_ver); 7166 aprint_error_dev(sc->sc_dev, "%08X | hw version\n", t.hw_ver);
7167 aprint_error_dev(sc->sc_dev, "%08X | board version\n", t.brd_ver); 7167 aprint_error_dev(sc->sc_dev, "%08X | board version\n", t.brd_ver);
7168 aprint_error_dev(sc->sc_dev, "%08X | hcmd\n", t.hcmd); 7168 aprint_error_dev(sc->sc_dev, "%08X | hcmd\n", t.hcmd);
7169 aprint_error_dev(sc->sc_dev, "%08X | isr0\n", t.isr0); 7169 aprint_error_dev(sc->sc_dev, "%08X | isr0\n", t.isr0);
7170 aprint_error_dev(sc->sc_dev, "%08X | isr1\n", t.isr1); 7170 aprint_error_dev(sc->sc_dev, "%08X | isr1\n", t.isr1);
7171 aprint_error_dev(sc->sc_dev, "%08X | isr2\n", t.isr2); 7171 aprint_error_dev(sc->sc_dev, "%08X | isr2\n", t.isr2);
7172 aprint_error_dev(sc->sc_dev, "%08X | isr3\n", t.isr3); 7172 aprint_error_dev(sc->sc_dev, "%08X | isr3\n", t.isr3);
7173 aprint_error_dev(sc->sc_dev, "%08X | isr4\n", t.isr4); 7173 aprint_error_dev(sc->sc_dev, "%08X | isr4\n", t.isr4);
7174 aprint_error_dev(sc->sc_dev, "%08X | last cmd Id\n", t.last_cmd_id); 7174 aprint_error_dev(sc->sc_dev, "%08X | last cmd Id\n", t.last_cmd_id);
7175 aprint_error_dev(sc->sc_dev, "%08X | wait_event\n", t.wait_event); 7175 aprint_error_dev(sc->sc_dev, "%08X | wait_event\n", t.wait_event);
7176 aprint_error_dev(sc->sc_dev, "%08X | l2p_control\n", t.l2p_control); 7176 aprint_error_dev(sc->sc_dev, "%08X | l2p_control\n", t.l2p_control);
7177 aprint_error_dev(sc->sc_dev, "%08X | l2p_duration\n", t.l2p_duration); 7177 aprint_error_dev(sc->sc_dev, "%08X | l2p_duration\n", t.l2p_duration);
7178 aprint_error_dev(sc->sc_dev, "%08X | l2p_mhvalid\n", t.l2p_mhvalid); 7178 aprint_error_dev(sc->sc_dev, "%08X | l2p_mhvalid\n", t.l2p_mhvalid);
7179 aprint_error_dev(sc->sc_dev, "%08X | l2p_addr_match\n", 7179 aprint_error_dev(sc->sc_dev, "%08X | l2p_addr_match\n",
7180 t.l2p_addr_match); 7180 t.l2p_addr_match);
7181 aprint_error_dev(sc->sc_dev, "%08X | lmpm_pmg_sel\n", t.lmpm_pmg_sel); 7181 aprint_error_dev(sc->sc_dev, "%08X | lmpm_pmg_sel\n", t.lmpm_pmg_sel);
7182 aprint_error_dev(sc->sc_dev, "%08X | timestamp\n", t.u_timestamp); 7182 aprint_error_dev(sc->sc_dev, "%08X | timestamp\n", t.u_timestamp);
7183 aprint_error_dev(sc->sc_dev, "%08X | flow_handler\n", t.flow_handler); 7183 aprint_error_dev(sc->sc_dev, "%08X | flow_handler\n", t.flow_handler);
7184 7184
7185 if (sc->sc_uc.uc_umac_error_event_table) 7185 if (sc->sc_uc.uc_umac_error_event_table)
7186 iwm_nic_umac_error(sc); 7186 iwm_nic_umac_error(sc);
7187} 7187}
7188 7188
7189static void 7189static void
7190iwm_nic_umac_error(struct iwm_softc *sc) 7190iwm_nic_umac_error(struct iwm_softc *sc)
7191{ 7191{
7192 struct iwm_umac_error_event_table t; 7192 struct iwm_umac_error_event_table t;
7193 uint32_t base; 7193 uint32_t base;
7194 7194
7195 base = sc->sc_uc.uc_umac_error_event_table; 7195 base = sc->sc_uc.uc_umac_error_event_table;
7196 7196
7197 if (base < 0x800000) { 7197 if (base < 0x800000) {
7198 aprint_error_dev(sc->sc_dev, 7198 aprint_error_dev(sc->sc_dev,
7199 "Invalid error log pointer 0x%08x\n", base); 7199 "Invalid error log pointer 0x%08x\n", base);
7200 return; 7200 return;
7201 } 7201 }
7202 7202
7203 if (iwm_read_mem(sc, base, &t, sizeof(t)/sizeof(uint32_t))) { 7203 if (iwm_read_mem(sc, base, &t, sizeof(t)/sizeof(uint32_t))) {
7204 aprint_error_dev(sc->sc_dev, "reading errlog failed\n"); 7204 aprint_error_dev(sc->sc_dev, "reading errlog failed\n");
7205 return; 7205 return;
7206 } 7206 }
7207 7207
7208 if (ERROR_START_OFFSET <= t.valid * ERROR_ELEM_SIZE) { 7208 if (ERROR_START_OFFSET <= t.valid * ERROR_ELEM_SIZE) {
7209 aprint_error_dev(sc->sc_dev, "Start UMAC Error Log Dump:\n"); 7209 aprint_error_dev(sc->sc_dev, "Start UMAC Error Log Dump:\n");
7210 aprint_error_dev(sc->sc_dev, "Status: 0x%x, count: %d\n", 7210 aprint_error_dev(sc->sc_dev, "Status: 0x%x, count: %d\n",
7211 sc->sc_flags, t.valid); 7211 sc->sc_flags, t.valid);
7212 } 7212 }
7213 7213
7214 aprint_error_dev(sc->sc_dev, "0x%08X | %s\n", t.error_id, 7214 aprint_error_dev(sc->sc_dev, "0x%08X | %s\n", t.error_id,
7215 iwm_desc_lookup(t.error_id)); 7215 iwm_desc_lookup(t.error_id));
7216 aprint_error_dev(sc->sc_dev, "0x%08X | umac branchlink1\n", t.blink1); 7216 aprint_error_dev(sc->sc_dev, "0x%08X | umac branchlink1\n", t.blink1);
7217 aprint_error_dev(sc->sc_dev, "0x%08X | umac branchlink2\n", t.blink2); 7217 aprint_error_dev(sc->sc_dev, "0x%08X | umac branchlink2\n", t.blink2);
7218 aprint_error_dev(sc->sc_dev, "0x%08X | umac interruptlink1\n", 7218 aprint_error_dev(sc->sc_dev, "0x%08X | umac interruptlink1\n",
7219 t.ilink1); 7219 t.ilink1);
7220 aprint_error_dev(sc->sc_dev, "0x%08X | umac interruptlink2\n", 7220 aprint_error_dev(sc->sc_dev, "0x%08X | umac interruptlink2\n",
7221 t.ilink2); 7221 t.ilink2);
7222 aprint_error_dev(sc->sc_dev, "0x%08X | umac data1\n", t.data1); 7222 aprint_error_dev(sc->sc_dev, "0x%08X | umac data1\n", t.data1);
7223 aprint_error_dev(sc->sc_dev, "0x%08X | umac data2\n", t.data2); 7223 aprint_error_dev(sc->sc_dev, "0x%08X | umac data2\n", t.data2);
7224 aprint_error_dev(sc->sc_dev, "0x%08X | umac data3\n", t.data3); 7224 aprint_error_dev(sc->sc_dev, "0x%08X | umac data3\n", t.data3);
7225 aprint_error_dev(sc->sc_dev, "0x%08X | umac major\n", t.umac_major); 7225 aprint_error_dev(sc->sc_dev, "0x%08X | umac major\n", t.umac_major);
7226 aprint_error_dev(sc->sc_dev, "0x%08X | umac minor\n", t.umac_minor); 7226 aprint_error_dev(sc->sc_dev, "0x%08X | umac minor\n", t.umac_minor);
7227 aprint_error_dev(sc->sc_dev, "0x%08X | frame pointer\n", 7227 aprint_error_dev(sc->sc_dev, "0x%08X | frame pointer\n",
7228 t.frame_pointer); 7228 t.frame_pointer);
7229 aprint_error_dev(sc->sc_dev, "0x%08X | stack pointer\n", 7229 aprint_error_dev(sc->sc_dev, "0x%08X | stack pointer\n",
7230 t.stack_pointer); 7230 t.stack_pointer);
7231 aprint_error_dev(sc->sc_dev, "0x%08X | last host cmd\n", t.cmd_header); 7231 aprint_error_dev(sc->sc_dev, "0x%08X | last host cmd\n", t.cmd_header);
7232 aprint_error_dev(sc->sc_dev, "0x%08X | isr status reg\n", 7232 aprint_error_dev(sc->sc_dev, "0x%08X | isr status reg\n",
7233 t.nic_isr_pref); 7233 t.nic_isr_pref);
7234} 7234}
7235#endif 7235#endif
7236 7236
7237#define SYNC_RESP_STRUCT(_var_, _pkt_) \ 7237#define SYNC_RESP_STRUCT(_var_, _pkt_) \
7238do { \ 7238do { \
7239 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*(_pkt_)), \ 7239 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*(_pkt_)), \
7240 sizeof(*(_var_)), BUS_DMASYNC_POSTREAD); \ 7240 sizeof(*(_var_)), BUS_DMASYNC_POSTREAD); \
7241 _var_ = (void *)((_pkt_)+1); \ 7241 _var_ = (void *)((_pkt_)+1); \
7242} while (/*CONSTCOND*/0) 7242} while (/*CONSTCOND*/0)
7243 7243
7244#define SYNC_RESP_PTR(_ptr_, _len_, _pkt_) \ 7244#define SYNC_RESP_PTR(_ptr_, _len_, _pkt_) \
7245do { \ 7245do { \
7246 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*(_pkt_)), \ 7246 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*(_pkt_)), \
7247 sizeof(len), BUS_DMASYNC_POSTREAD); \ 7247 sizeof(len), BUS_DMASYNC_POSTREAD); \
7248 _ptr_ = (void *)((_pkt_)+1); \ 7248 _ptr_ = (void *)((_pkt_)+1); \
7249} while (/*CONSTCOND*/0) 7249} while (/*CONSTCOND*/0)
7250 7250
7251#define ADVANCE_RXQ(sc) (sc->rxq.cur = (sc->rxq.cur + 1) % IWM_RX_RING_COUNT); 7251#define ADVANCE_RXQ(sc) (sc->rxq.cur = (sc->rxq.cur + 1) % IWM_RX_RING_COUNT);
7252 7252
7253static void 7253static void
7254iwm_notif_intr(struct iwm_softc *sc) 7254iwm_notif_intr(struct iwm_softc *sc)
7255{ 7255{
7256 uint16_t hw; 7256 uint16_t hw;
7257 7257
7258 bus_dmamap_sync(sc->sc_dmat, sc->rxq.stat_dma.map, 7258 bus_dmamap_sync(sc->sc_dmat, sc->rxq.stat_dma.map,
7259 0, sc->rxq.stat_dma.size, BUS_DMASYNC_POSTREAD); 7259 0, sc->rxq.stat_dma.size, BUS_DMASYNC_POSTREAD);
7260 7260
7261 hw = le16toh(sc->rxq.stat->closed_rb_num) & 0xfff; 7261 hw = le16toh(sc->rxq.stat->closed_rb_num) & 0xfff;
7262 while (sc->rxq.cur != hw) { 7262 while (sc->rxq.cur != hw) {
7263 struct iwm_rx_data *data = &sc->rxq.data[sc->rxq.cur]; 7263 struct iwm_rx_data *data = &sc->rxq.data[sc->rxq.cur];
7264 struct iwm_rx_packet *pkt; 7264 struct iwm_rx_packet *pkt;
7265 struct iwm_cmd_response *cresp; 7265 struct iwm_cmd_response *cresp;
7266 int orig_qid, qid, idx, code; 7266 int orig_qid, qid, idx, code;
7267 7267
7268 bus_dmamap_sync(sc->sc_dmat, data->map, 0, sizeof(*pkt), 7268 bus_dmamap_sync(sc->sc_dmat, data->map, 0, sizeof(*pkt),
7269 BUS_DMASYNC_POSTREAD); 7269 BUS_DMASYNC_POSTREAD);
7270 pkt = mtod(data->m, struct iwm_rx_packet *); 7270 pkt = mtod(data->m, struct iwm_rx_packet *);
7271 7271
7272 orig_qid = pkt->hdr.qid; 7272 orig_qid = pkt->hdr.qid;
7273 qid = orig_qid & ~0x80; 7273 qid = orig_qid & ~0x80;
7274 idx = pkt->hdr.idx; 7274 idx = pkt->hdr.idx;
7275 7275
7276 code = IWM_WIDE_ID(pkt->hdr.flags, pkt->hdr.code); 7276 code = IWM_WIDE_ID(pkt->hdr.flags, pkt->hdr.code);
7277 7277
7278 /* 7278 /*
7279 * randomly get these from the firmware, no idea why. 7279 * randomly get these from the firmware, no idea why.
7280 * they at least seem harmless, so just ignore them for now 7280 * they at least seem harmless, so just ignore them for now
7281 */ 7281 */
7282 if (__predict_false((pkt->hdr.code == 0 && qid == 0 && idx == 0) 7282 if (__predict_false((pkt->hdr.code == 0 && qid == 0 && idx == 0)
7283 || pkt->len_n_flags == htole32(0x55550000))) { 7283 || pkt->len_n_flags == htole32(0x55550000))) {
7284 ADVANCE_RXQ(sc); 7284 ADVANCE_RXQ(sc);
7285 continue; 7285 continue;
7286 } 7286 }
7287 7287
7288 switch (code) { 7288 switch (code) {
7289 case IWM_REPLY_RX_PHY_CMD: 7289 case IWM_REPLY_RX_PHY_CMD:
7290 iwm_rx_rx_phy_cmd(sc, pkt, data); 7290 iwm_rx_rx_phy_cmd(sc, pkt, data);
7291 break; 7291 break;
7292 7292
7293 case IWM_REPLY_RX_MPDU_CMD: 7293 case IWM_REPLY_RX_MPDU_CMD:
7294 iwm_rx_rx_mpdu(sc, pkt, data); 7294 iwm_rx_rx_mpdu(sc, pkt, data);
7295 break; 7295 break;
7296 7296
7297 case IWM_TX_CMD: 7297 case IWM_TX_CMD:
7298 iwm_rx_tx_cmd(sc, pkt, data); 7298 iwm_rx_tx_cmd(sc, pkt, data);
7299 break; 7299 break;
7300 7300
7301 case IWM_MISSED_BEACONS_NOTIFICATION: 7301 case IWM_MISSED_BEACONS_NOTIFICATION:
7302 iwm_rx_missed_beacons_notif(sc, pkt, data); 7302 iwm_rx_missed_beacons_notif(sc, pkt, data);
7303 break; 7303 break;
7304 7304
7305 case IWM_MFUART_LOAD_NOTIFICATION: 7305 case IWM_MFUART_LOAD_NOTIFICATION:
7306 break; 7306 break;
7307 7307
7308 case IWM_ALIVE: { 7308 case IWM_ALIVE: {
7309 struct iwm_alive_resp_v1 *resp1; 7309 struct iwm_alive_resp_v1 *resp1;
7310 struct iwm_alive_resp_v2 *resp2; 7310 struct iwm_alive_resp_v2 *resp2;
7311 struct iwm_alive_resp_v3 *resp3; 7311 struct iwm_alive_resp_v3 *resp3;
7312 7312
7313 if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp1)) { 7313 if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp1)) {
7314 SYNC_RESP_STRUCT(resp1, pkt); 7314 SYNC_RESP_STRUCT(resp1, pkt);
7315 sc->sc_uc.uc_error_event_table 7315 sc->sc_uc.uc_error_event_table
7316 = le32toh(resp1->error_event_table_ptr); 7316 = le32toh(resp1->error_event_table_ptr);
7317 sc->sc_uc.uc_log_event_table 7317 sc->sc_uc.uc_log_event_table
7318 = le32toh(resp1->log_event_table_ptr); 7318 = le32toh(resp1->log_event_table_ptr);
7319 sc->sched_base = le32toh(resp1->scd_base_ptr); 7319 sc->sched_base = le32toh(resp1->scd_base_ptr);
7320 if (resp1->status == IWM_ALIVE_STATUS_OK) 7320 if (resp1->status == IWM_ALIVE_STATUS_OK)
7321 sc->sc_uc.uc_ok = 1; 7321 sc->sc_uc.uc_ok = 1;
7322 else 7322 else
7323 sc->sc_uc.uc_ok = 0; 7323 sc->sc_uc.uc_ok = 0;
7324 } 7324 }
7325 if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp2)) { 7325 if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp2)) {
7326 SYNC_RESP_STRUCT(resp2, pkt); 7326 SYNC_RESP_STRUCT(resp2, pkt);
7327 sc->sc_uc.uc_error_event_table 7327 sc->sc_uc.uc_error_event_table
7328 = le32toh(resp2->error_event_table_ptr); 7328 = le32toh(resp2->error_event_table_ptr);
7329 sc->sc_uc.uc_log_event_table 7329 sc->sc_uc.uc_log_event_table
7330 = le32toh(resp2->log_event_table_ptr); 7330 = le32toh(resp2->log_event_table_ptr);
7331 sc->sched_base = le32toh(resp2->scd_base_ptr); 7331 sc->sched_base = le32toh(resp2->scd_base_ptr);
7332 sc->sc_uc.uc_umac_error_event_table 7332 sc->sc_uc.uc_umac_error_event_table
7333 = le32toh(resp2->error_info_addr); 7333 = le32toh(resp2->error_info_addr);
7334 if (resp2->status == IWM_ALIVE_STATUS_OK) 7334 if (resp2->status == IWM_ALIVE_STATUS_OK)
7335 sc->sc_uc.uc_ok = 1; 7335 sc->sc_uc.uc_ok = 1;
7336 else 7336 else
7337 sc->sc_uc.uc_ok = 0; 7337 sc->sc_uc.uc_ok = 0;
7338 } 7338 }
7339 if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp3)) { 7339 if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp3)) {
7340 SYNC_RESP_STRUCT(resp3, pkt); 7340 SYNC_RESP_STRUCT(resp3, pkt);
7341 sc->sc_uc.uc_error_event_table 7341 sc->sc_uc.uc_error_event_table
7342 = le32toh(resp3->error_event_table_ptr); 7342 = le32toh(resp3->error_event_table_ptr);
7343 sc->sc_uc.uc_log_event_table 7343 sc->sc_uc.uc_log_event_table
7344 = le32toh(resp3->log_event_table_ptr); 7344 = le32toh(resp3->log_event_table_ptr);
7345 sc->sched_base = le32toh(resp3->scd_base_ptr); 7345 sc->sched_base = le32toh(resp3->scd_base_ptr);
7346 sc->sc_uc.uc_umac_error_event_table 7346 sc->sc_uc.uc_umac_error_event_table
7347 = le32toh(resp3->error_info_addr); 7347 = le32toh(resp3->error_info_addr);
7348 if (resp3->status == IWM_ALIVE_STATUS_OK) 7348 if (resp3->status == IWM_ALIVE_STATUS_OK)
7349 sc->sc_uc.uc_ok = 1; 7349 sc->sc_uc.uc_ok = 1;
7350 else 7350 else
7351 sc->sc_uc.uc_ok = 0; 7351 sc->sc_uc.uc_ok = 0;
7352 } 7352 }
7353 7353
7354 sc->sc_uc.uc_intr = 1; 7354 sc->sc_uc.uc_intr = 1;
7355 wakeup(&sc->sc_uc); 7355 wakeup(&sc->sc_uc);
7356 break; 7356 break;
7357 } 7357 }
7358 7358
7359 case IWM_CALIB_RES_NOTIF_PHY_DB: { 7359 case IWM_CALIB_RES_NOTIF_PHY_DB: {
7360 struct iwm_calib_res_notif_phy_db *phy_db_notif; 7360 struct iwm_calib_res_notif_phy_db *phy_db_notif;
7361 SYNC_RESP_STRUCT(phy_db_notif, pkt); 7361 SYNC_RESP_STRUCT(phy_db_notif, pkt);
7362 uint16_t size = le16toh(phy_db_notif->length); 7362 uint16_t size = le16toh(phy_db_notif->length);
7363 bus_dmamap_sync(sc->sc_dmat, data->map, 7363 bus_dmamap_sync(sc->sc_dmat, data->map,
7364 sizeof(*pkt) + sizeof(*phy_db_notif), 7364 sizeof(*pkt) + sizeof(*phy_db_notif),
7365 size, BUS_DMASYNC_POSTREAD); 7365 size, BUS_DMASYNC_POSTREAD);
7366 iwm_phy_db_set_section(sc, phy_db_notif, size); 7366 iwm_phy_db_set_section(sc, phy_db_notif, size);
7367 break; 7367 break;
7368 } 7368 }
7369 7369
7370 case IWM_STATISTICS_NOTIFICATION: { 7370 case IWM_STATISTICS_NOTIFICATION: {
7371 struct iwm_notif_statistics *stats; 7371 struct iwm_notif_statistics *stats;
7372 SYNC_RESP_STRUCT(stats, pkt); 7372 SYNC_RESP_STRUCT(stats, pkt);
7373 memcpy(&sc->sc_stats, stats, sizeof(sc->sc_stats)); 7373 memcpy(&sc->sc_stats, stats, sizeof(sc->sc_stats));
7374 sc->sc_noise = iwm_get_noise(&stats->rx.general); 7374 sc->sc_noise = iwm_get_noise(&stats->rx.general);
7375 break; 7375 break;
7376 } 7376 }
7377 7377
7378 case IWM_NVM_ACCESS_CMD: 7378 case IWM_NVM_ACCESS_CMD:
7379 case IWM_MCC_UPDATE_CMD: 7379 case IWM_MCC_UPDATE_CMD:
7380 if (sc->sc_wantresp == ((qid << 16) | idx)) { 7380 if (sc->sc_wantresp == ((qid << 16) | idx)) {
7381 bus_dmamap_sync(sc->sc_dmat, data->map, 0, 7381 bus_dmamap_sync(sc->sc_dmat, data->map, 0,
7382 sizeof(sc->sc_cmd_resp), 7382 sizeof(sc->sc_cmd_resp),
7383 BUS_DMASYNC_POSTREAD); 7383 BUS_DMASYNC_POSTREAD);
7384 memcpy(sc->sc_cmd_resp, 7384 memcpy(sc->sc_cmd_resp,
7385 pkt, sizeof(sc->sc_cmd_resp)); 7385 pkt, sizeof(sc->sc_cmd_resp));
7386 } 7386 }
7387 break; 7387 break;
7388 7388
7389 case IWM_MCC_CHUB_UPDATE_CMD: { 7389 case IWM_MCC_CHUB_UPDATE_CMD: {
7390 struct iwm_mcc_chub_notif *notif; 7390 struct iwm_mcc_chub_notif *notif;
7391 SYNC_RESP_STRUCT(notif, pkt); 7391 SYNC_RESP_STRUCT(notif, pkt);
7392 7392
7393 sc->sc_fw_mcc[0] = (notif->mcc & 0xff00) >> 8; 7393 sc->sc_fw_mcc[0] = (notif->mcc & 0xff00) >> 8;
7394 sc->sc_fw_mcc[1] = notif->mcc & 0xff; 7394 sc->sc_fw_mcc[1] = notif->mcc & 0xff;
7395 sc->sc_fw_mcc[2] = '\0'; 7395 sc->sc_fw_mcc[2] = '\0';
7396 break; 7396 break;
7397 } 7397 }
7398 7398
7399 case IWM_DTS_MEASUREMENT_NOTIFICATION: 7399 case IWM_DTS_MEASUREMENT_NOTIFICATION:
7400 case IWM_WIDE_ID(IWM_PHY_OPS_GROUP, 7400 case IWM_WIDE_ID(IWM_PHY_OPS_GROUP,
7401 IWM_DTS_MEASUREMENT_NOTIF_WIDE): { 7401 IWM_DTS_MEASUREMENT_NOTIF_WIDE): {
7402 struct iwm_dts_measurement_notif_v1 *notif1; 7402 struct iwm_dts_measurement_notif_v1 *notif1;
7403 struct iwm_dts_measurement_notif_v2 *notif2; 7403 struct iwm_dts_measurement_notif_v2 *notif2;
7404 7404
7405 if (iwm_rx_packet_payload_len(pkt) == sizeof(*notif1)) { 7405 if (iwm_rx_packet_payload_len(pkt) == sizeof(*notif1)) {
7406 SYNC_RESP_STRUCT(notif1, pkt); 7406 SYNC_RESP_STRUCT(notif1, pkt);
7407 DPRINTF(("%s: DTS temp=%d \n", 7407 DPRINTF(("%s: DTS temp=%d \n",
7408 DEVNAME(sc), notif1->temp)); 7408 DEVNAME(sc), notif1->temp));
7409 break; 7409 break;
7410 } 7410 }
7411 if (iwm_rx_packet_payload_len(pkt) == sizeof(*notif2)) { 7411 if (iwm_rx_packet_payload_len(pkt) == sizeof(*notif2)) {
7412 SYNC_RESP_STRUCT(notif2, pkt); 7412 SYNC_RESP_STRUCT(notif2, pkt);
7413 DPRINTF(("%s: DTS temp=%d \n", 7413 DPRINTF(("%s: DTS temp=%d \n",
7414 DEVNAME(sc), notif2->temp)); 7414 DEVNAME(sc), notif2->temp));
7415 break; 7415 break;
7416 } 7416 }
7417 break; 7417 break;
7418 } 7418 }
7419 7419
7420 case IWM_PHY_CONFIGURATION_CMD: 7420 case IWM_PHY_CONFIGURATION_CMD:
7421 case IWM_TX_ANT_CONFIGURATION_CMD: 7421 case IWM_TX_ANT_CONFIGURATION_CMD:
7422 case IWM_ADD_STA: 7422 case IWM_ADD_STA:
7423 case IWM_MAC_CONTEXT_CMD: 7423 case IWM_MAC_CONTEXT_CMD:
7424 case IWM_REPLY_SF_CFG_CMD: 7424 case IWM_REPLY_SF_CFG_CMD:
7425 case IWM_POWER_TABLE_CMD: 7425 case IWM_POWER_TABLE_CMD:
7426 case IWM_PHY_CONTEXT_CMD: 7426 case IWM_PHY_CONTEXT_CMD:
7427 case IWM_BINDING_CONTEXT_CMD: 7427 case IWM_BINDING_CONTEXT_CMD:
7428 case IWM_TIME_EVENT_CMD: 7428 case IWM_TIME_EVENT_CMD:
7429 case IWM_SCAN_REQUEST_CMD: 7429 case IWM_SCAN_REQUEST_CMD:
7430 case IWM_WIDE_ID(IWM_ALWAYS_LONG_GROUP, IWM_SCAN_CFG_CMD): 7430 case IWM_WIDE_ID(IWM_ALWAYS_LONG_GROUP, IWM_SCAN_CFG_CMD):
7431 case IWM_WIDE_ID(IWM_ALWAYS_LONG_GROUP, IWM_SCAN_REQ_UMAC): 7431 case IWM_WIDE_ID(IWM_ALWAYS_LONG_GROUP, IWM_SCAN_REQ_UMAC):
7432 case IWM_WIDE_ID(IWM_ALWAYS_LONG_GROUP, IWM_SCAN_ABORT_UMAC): 7432 case IWM_WIDE_ID(IWM_ALWAYS_LONG_GROUP, IWM_SCAN_ABORT_UMAC):
7433 case IWM_SCAN_OFFLOAD_REQUEST_CMD: 7433 case IWM_SCAN_OFFLOAD_REQUEST_CMD:
7434 case IWM_SCAN_OFFLOAD_ABORT_CMD: 7434 case IWM_SCAN_OFFLOAD_ABORT_CMD:
7435 case IWM_REPLY_BEACON_FILTERING_CMD: 7435 case IWM_REPLY_BEACON_FILTERING_CMD:
7436 case IWM_MAC_PM_POWER_TABLE: 7436 case IWM_MAC_PM_POWER_TABLE:
7437 case IWM_TIME_QUOTA_CMD: 7437 case IWM_TIME_QUOTA_CMD:
7438 case IWM_REMOVE_STA: 7438 case IWM_REMOVE_STA:
7439 case IWM_TXPATH_FLUSH: 7439 case IWM_TXPATH_FLUSH:
7440 case IWM_LQ_CMD: 7440 case IWM_LQ_CMD:
7441 case IWM_WIDE_ID(IWM_ALWAYS_LONG_GROUP, IWM_FW_PAGING_BLOCK_CMD): 7441 case IWM_WIDE_ID(IWM_ALWAYS_LONG_GROUP, IWM_FW_PAGING_BLOCK_CMD):
7442 case IWM_BT_CONFIG: 7442 case IWM_BT_CONFIG:
7443 case IWM_REPLY_THERMAL_MNG_BACKOFF: 7443 case IWM_REPLY_THERMAL_MNG_BACKOFF:
7444 SYNC_RESP_STRUCT(cresp, pkt); 7444 SYNC_RESP_STRUCT(cresp, pkt);
7445 if (sc->sc_wantresp == ((qid << 16) | idx)) { 7445 if (sc->sc_wantresp == ((qid << 16) | idx)) {
7446 memcpy(sc->sc_cmd_resp, 7446 memcpy(sc->sc_cmd_resp,
7447 pkt, sizeof(*pkt) + sizeof(*cresp)); 7447 pkt, sizeof(*pkt) + sizeof(*cresp));
7448 } 7448 }
7449 break; 7449 break;
7450 7450
7451 /* ignore */ 7451 /* ignore */
7452 case IWM_PHY_DB_CMD: 7452 case IWM_PHY_DB_CMD:
7453 break; 7453 break;
7454 7454
7455 case IWM_INIT_COMPLETE_NOTIF: 7455 case IWM_INIT_COMPLETE_NOTIF:
7456 sc->sc_init_complete = 1; 7456 sc->sc_init_complete = 1;
7457 wakeup(&sc->sc_init_complete); 7457 wakeup(&sc->sc_init_complete);
7458 break; 7458 break;
7459 7459
7460 case IWM_SCAN_OFFLOAD_COMPLETE: { 7460 case IWM_SCAN_OFFLOAD_COMPLETE: {
7461 struct iwm_periodic_scan_complete *notif; 7461 struct iwm_periodic_scan_complete *notif;
7462 SYNC_RESP_STRUCT(notif, pkt); 7462 SYNC_RESP_STRUCT(notif, pkt);
7463 break; 7463 break;
7464 } 7464 }
7465 7465
7466 case IWM_SCAN_ITERATION_COMPLETE: { 7466 case IWM_SCAN_ITERATION_COMPLETE: {
7467 struct iwm_lmac_scan_complete_notif *notif; 7467 struct iwm_lmac_scan_complete_notif *notif;
7468 SYNC_RESP_STRUCT(notif, pkt); 7468 SYNC_RESP_STRUCT(notif, pkt);
7469 if (ISSET(sc->sc_flags, IWM_FLAG_SCANNING)) { 7469 if (ISSET(sc->sc_flags, IWM_FLAG_SCANNING)) {
7470 CLR(sc->sc_flags, IWM_FLAG_SCANNING); 7470 CLR(sc->sc_flags, IWM_FLAG_SCANNING);
7471 iwm_endscan(sc); 7471 iwm_endscan(sc);
7472 } 7472 }
7473 break; 7473 break;
7474 } 7474 }
7475 7475
7476 case IWM_SCAN_COMPLETE_UMAC: { 7476 case IWM_SCAN_COMPLETE_UMAC: {
7477 struct iwm_umac_scan_complete *notif; 7477 struct iwm_umac_scan_complete *notif;
7478 SYNC_RESP_STRUCT(notif, pkt); 7478 SYNC_RESP_STRUCT(notif, pkt);
7479 if (ISSET(sc->sc_flags, IWM_FLAG_SCANNING)) { 7479 if (ISSET(sc->sc_flags, IWM_FLAG_SCANNING)) {
7480 CLR(sc->sc_flags, IWM_FLAG_SCANNING); 7480 CLR(sc->sc_flags, IWM_FLAG_SCANNING);
7481 iwm_endscan(sc); 7481 iwm_endscan(sc);
7482 } 7482 }
7483 break; 7483 break;
7484 } 7484 }
7485 7485
7486 case IWM_SCAN_ITERATION_COMPLETE_UMAC: { 7486 case IWM_SCAN_ITERATION_COMPLETE_UMAC: {
7487 struct iwm_umac_scan_iter_complete_notif *notif; 7487 struct iwm_umac_scan_iter_complete_notif *notif;
7488 SYNC_RESP_STRUCT(notif, pkt); 7488 SYNC_RESP_STRUCT(notif, pkt);
7489 if (ISSET(sc->sc_flags, IWM_FLAG_SCANNING)) { 7489 if (ISSET(sc->sc_flags, IWM_FLAG_SCANNING)) {
7490 CLR(sc->sc_flags, IWM_FLAG_SCANNING); 7490 CLR(sc->sc_flags, IWM_FLAG_SCANNING);
7491 iwm_endscan(sc); 7491 iwm_endscan(sc);
7492 } 7492 }
7493 break; 7493 break;
7494 } 7494 }
7495 7495
7496 case IWM_REPLY_ERROR: { 7496 case IWM_REPLY_ERROR: {
7497 struct iwm_error_resp *resp; 7497 struct iwm_error_resp *resp;
7498 SYNC_RESP_STRUCT(resp, pkt); 7498 SYNC_RESP_STRUCT(resp, pkt);
7499 aprint_error_dev(sc->sc_dev, 7499 aprint_error_dev(sc->sc_dev,
7500 "firmware error 0x%x, cmd 0x%x\n", 7500 "firmware error 0x%x, cmd 0x%x\n",
7501 le32toh(resp->error_type), resp->cmd_id); 7501 le32toh(resp->error_type), resp->cmd_id);
7502 break; 7502 break;
7503 } 7503 }
7504 7504
7505 case IWM_TIME_EVENT_NOTIFICATION: { 7505 case IWM_TIME_EVENT_NOTIFICATION: {
7506 struct iwm_time_event_notif *notif; 7506 struct iwm_time_event_notif *notif;
7507 SYNC_RESP_STRUCT(notif, pkt); 7507 SYNC_RESP_STRUCT(notif, pkt);
7508 break; 7508 break;
7509 } 7509 }
7510 7510
7511 case IWM_DEBUG_LOG_MSG: 7511 case IWM_DEBUG_LOG_MSG:
7512 break; 7512 break;
7513 7513
7514 case IWM_MCAST_FILTER_CMD: 7514 case IWM_MCAST_FILTER_CMD:
7515 break; 7515 break;
7516 7516
7517 case IWM_SCD_QUEUE_CFG: { 7517 case IWM_SCD_QUEUE_CFG: {
7518 struct iwm_scd_txq_cfg_rsp *rsp; 7518 struct iwm_scd_txq_cfg_rsp *rsp;
7519 SYNC_RESP_STRUCT(rsp, pkt); 7519 SYNC_RESP_STRUCT(rsp, pkt);
7520 break; 7520 break;
7521 } 7521 }
7522 7522
7523 default: 7523 default:
7524 aprint_error_dev(sc->sc_dev, 7524 aprint_error_dev(sc->sc_dev,
7525 "unhandled firmware response 0x%x 0x%x/0x%x " 7525 "unhandled firmware response 0x%x 0x%x/0x%x "
7526 "rx ring %d[%d]\n", 7526 "rx ring %d[%d]\n",
7527 code, pkt->hdr.code, pkt->len_n_flags, qid, idx); 7527 code, pkt->hdr.code, pkt->len_n_flags, qid, idx);
7528 break; 7528 break;
7529 } 7529 }
7530 7530
7531 /* 7531 /*
7532 * uCode sets bit 0x80 when it originates the notification, 7532 * uCode sets bit 0x80 when it originates the notification,
7533 * i.e. when the notification is not a direct response to a 7533 * i.e. when the notification is not a direct response to a
7534 * command sent by the driver. 7534 * command sent by the driver.
7535 * For example, uCode issues IWM_REPLY_RX when it sends a 7535 * For example, uCode issues IWM_REPLY_RX when it sends a
7536 * received frame to the driver. 7536 * received frame to the driver.
7537 */ 7537 */
7538 if (!(orig_qid & (1 << 7))) { 7538 if (!(orig_qid & (1 << 7))) {
7539 iwm_cmd_done(sc, qid, idx); 7539 iwm_cmd_done(sc, qid, idx);
7540 } 7540 }
7541 7541
7542 ADVANCE_RXQ(sc); 7542 ADVANCE_RXQ(sc);
7543 } 7543 }
7544 7544
7545 /* 7545 /*
7546 * Seems like the hardware gets upset unless we align the write by 8?? 7546 * Seems like the hardware gets upset unless we align the write by 8??
7547 */ 7547 */
7548 hw = (hw == 0) ? IWM_RX_RING_COUNT - 1 : hw - 1; 7548 hw = (hw == 0) ? IWM_RX_RING_COUNT - 1 : hw - 1;
7549 IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_WPTR, hw & ~7); 7549 IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_WPTR, hw & ~7);
7550} 7550}
7551 7551
7552static int 7552static int
7553iwm_intr(void *arg) 7553iwm_intr(void *arg)
7554{ 7554{
7555 struct iwm_softc *sc = arg; 7555 struct iwm_softc *sc = arg;
7556 7556
7557 /* Disable interrupts */ 7557 /* Disable interrupts */
7558 IWM_WRITE(sc, IWM_CSR_INT_MASK, 0); 7558 IWM_WRITE(sc, IWM_CSR_INT_MASK, 0);
7559 7559
7560 softint_schedule(sc->sc_soft_ih); 7560 softint_schedule(sc->sc_soft_ih);
7561 return 1; 7561 return 1;
7562} 7562}
7563 7563
7564static void 7564static void
7565iwm_softintr(void *arg) 7565iwm_softintr(void *arg)
7566{ 7566{
7567 struct iwm_softc *sc = arg; 7567 struct iwm_softc *sc = arg;
7568 struct ifnet *ifp = IC2IFP(&sc->sc_ic); 7568 struct ifnet *ifp = IC2IFP(&sc->sc_ic);
7569 uint32_t r1, r2; 7569 uint32_t r1, r2;
7570 int isperiodic = 0, s; 7570 int isperiodic = 0, s;
7571 7571
7572 if (__predict_true(sc->sc_flags & IWM_FLAG_USE_ICT)) { 7572 if (__predict_true(sc->sc_flags & IWM_FLAG_USE_ICT)) {
7573 uint32_t *ict = sc->ict_dma.vaddr; 7573 uint32_t *ict = sc->ict_dma.vaddr;
7574 int tmp; 7574 int tmp;
7575 7575
7576 bus_dmamap_sync(sc->sc_dmat, sc->ict_dma.map, 7576 bus_dmamap_sync(sc->sc_dmat, sc->ict_dma.map,
7577 0, sc->ict_dma.size, BUS_DMASYNC_POSTREAD); 7577 0, sc->ict_dma.size, BUS_DMASYNC_POSTREAD);
7578 tmp = htole32(ict[sc->ict_cur]); 7578 tmp = htole32(ict[sc->ict_cur]);
7579 if (tmp == 0) 7579 if (tmp == 0)
7580 goto out_ena; /* Interrupt not for us. */ 7580 goto out_ena; /* Interrupt not for us. */
7581 7581
7582 /* 7582 /*
7583 * ok, there was something. keep plowing until we have all. 7583 * ok, there was something. keep plowing until we have all.
7584 */ 7584 */
7585 r1 = r2 = 0; 7585 r1 = r2 = 0;
7586 while (tmp) { 7586 while (tmp) {
7587 r1 |= tmp; 7587 r1 |= tmp;
7588 ict[sc->ict_cur] = 0; /* Acknowledge. */ 7588 ict[sc->ict_cur] = 0; /* Acknowledge. */
7589 sc->ict_cur = (sc->ict_cur + 1) % IWM_ICT_COUNT; 7589 sc->ict_cur = (sc->ict_cur + 1) % IWM_ICT_COUNT;
7590 tmp = htole32(ict[sc->ict_cur]); 7590 tmp = htole32(ict[sc->ict_cur]);
7591 } 7591 }
7592 7592
7593 bus_dmamap_sync(sc->sc_dmat, sc->ict_dma.map, 7593 bus_dmamap_sync(sc->sc_dmat, sc->ict_dma.map,
7594 0, sc->ict_dma.size, BUS_DMASYNC_PREWRITE); 7594 0, sc->ict_dma.size, BUS_DMASYNC_PREWRITE);
7595 7595
7596 /* this is where the fun begins. don't ask */ 7596 /* this is where the fun begins. don't ask */
7597 if (r1 == 0xffffffff) 7597 if (r1 == 0xffffffff)
7598 r1 = 0; 7598 r1 = 0;
7599 7599
7600 /* i am not expected to understand this */ 7600 /* i am not expected to understand this */
7601 if (r1 & 0xc0000) 7601 if (r1 & 0xc0000)
7602 r1 |= 0x8000; 7602 r1 |= 0x8000;
7603 r1 = (0xff & r1) | ((0xff00 & r1) << 16); 7603 r1 = (0xff & r1) | ((0xff00 & r1) << 16);
7604 } else { 7604 } else {
7605 r1 = IWM_READ(sc, IWM_CSR_INT); 7605 r1 = IWM_READ(sc, IWM_CSR_INT);
7606 if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0) 7606 if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0)
7607 return; /* Hardware gone! */ 7607 return; /* Hardware gone! */
7608 r2 = IWM_READ(sc, IWM_CSR_FH_INT_STATUS); 7608 r2 = IWM_READ(sc, IWM_CSR_FH_INT_STATUS);
7609 } 7609 }
7610 if (r1 == 0 && r2 == 0) { 7610 if (r1 == 0 && r2 == 0) {
7611 goto out_ena; /* Interrupt not for us. */ 7611 goto out_ena; /* Interrupt not for us. */
7612 } 7612 }
7613 7613
7614 /* Acknowledge interrupts. */ 7614 /* Acknowledge interrupts. */
7615 IWM_WRITE(sc, IWM_CSR_INT, r1 | ~sc->sc_intmask); 7615 IWM_WRITE(sc, IWM_CSR_INT, r1 | ~sc->sc_intmask);
7616 if (__predict_false(!(sc->sc_flags & IWM_FLAG_USE_ICT))) 7616 if (__predict_false(!(sc->sc_flags & IWM_FLAG_USE_ICT)))
7617 IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, r2); 7617 IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, r2);
7618 7618
7619 if (r1 & IWM_CSR_INT_BIT_SW_ERR) { 7619 if (r1 & IWM_CSR_INT_BIT_SW_ERR) {
7620#ifdef IWM_DEBUG 7620#ifdef IWM_DEBUG
7621 int i; 7621 int i;
7622 7622
7623 iwm_nic_error(sc); 7623 iwm_nic_error(sc);
7624 7624
7625 /* Dump driver status (TX and RX rings) while we're here. */ 7625 /* Dump driver status (TX and RX rings) while we're here. */
7626 DPRINTF(("driver status:\n")); 7626 DPRINTF(("driver status:\n"));
7627 for (i = 0; i < IWM_MAX_QUEUES; i++) { 7627 for (i = 0; i < IWM_MAX_QUEUES; i++) {
7628 struct iwm_tx_ring *ring = &sc->txq[i]; 7628 struct iwm_tx_ring *ring = &sc->txq[i];
7629 DPRINTF((" tx ring %2d: qid=%-2d cur=%-3d " 7629 DPRINTF((" tx ring %2d: qid=%-2d cur=%-3d "
7630 "queued=%-3d\n", 7630 "queued=%-3d\n",
7631 i, ring->qid, ring->cur, ring->queued)); 7631 i, ring->qid, ring->cur, ring->queued));
7632 } 7632 }
7633 DPRINTF((" rx ring: cur=%d\n", sc->rxq.cur)); 7633 DPRINTF((" rx ring: cur=%d\n", sc->rxq.cur));
7634 DPRINTF((" 802.11 state %s\n", 7634 DPRINTF((" 802.11 state %s\n",
7635 ieee80211_state_name[sc->sc_ic.ic_state])); 7635 ieee80211_state_name[sc->sc_ic.ic_state]));
7636#endif 7636#endif
7637 7637
7638 aprint_error_dev(sc->sc_dev, "fatal firmware error\n"); 7638 aprint_error_dev(sc->sc_dev, "fatal firmware error\n");
7639 fatal: 7639 fatal:
7640 s = splnet(); 7640 s = splnet();
7641 ifp->if_flags &= ~IFF_UP; 7641 ifp->if_flags &= ~IFF_UP;
7642 iwm_stop(ifp, 1); 7642 iwm_stop(ifp, 1);
7643 splx(s); 7643 splx(s);
7644 /* Don't restore interrupt mask */ 7644 /* Don't restore interrupt mask */
7645 return; 7645 return;
7646 7646
7647 } 7647 }
7648 7648
7649 if (r1 & IWM_CSR_INT_BIT_HW_ERR) { 7649 if (r1 & IWM_CSR_INT_BIT_HW_ERR) {
7650 aprint_error_dev(sc->sc_dev, 7650 aprint_error_dev(sc->sc_dev,
7651 "hardware error, stopping device\n"); 7651 "hardware error, stopping device\n");
7652 goto fatal; 7652 goto fatal;
7653 } 7653 }
7654 7654
7655 /* firmware chunk loaded */ 7655 /* firmware chunk loaded */
7656 if (r1 & IWM_CSR_INT_BIT_FH_TX) { 7656 if (r1 & IWM_CSR_INT_BIT_FH_TX) {
7657 IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, IWM_CSR_FH_INT_TX_MASK); 7657 IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, IWM_CSR_FH_INT_TX_MASK);
7658 sc->sc_fw_chunk_done = 1; 7658 sc->sc_fw_chunk_done = 1;
7659 wakeup(&sc->sc_fw); 7659 wakeup(&sc->sc_fw);
7660 } 7660 }
7661 7661
7662 if (r1 & IWM_CSR_INT_BIT_RF_KILL) { 7662 if (r1 & IWM_CSR_INT_BIT_RF_KILL) {
7663 if (iwm_check_rfkill(sc) && (ifp->if_flags & IFF_UP)) 7663 if (iwm_check_rfkill(sc) && (ifp->if_flags & IFF_UP))
7664 goto fatal; 7664 goto fatal;
7665 } 7665 }
7666 7666
7667 if (r1 & IWM_CSR_INT_BIT_RX_PERIODIC) { 7667 if (r1 & IWM_CSR_INT_BIT_RX_PERIODIC) {
7668 IWM_WRITE(sc, IWM_CSR_INT, IWM_CSR_INT_BIT_RX_PERIODIC); 7668 IWM_WRITE(sc, IWM_CSR_INT, IWM_CSR_INT_BIT_RX_PERIODIC);
7669 if ((r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX)) == 0) 7669 if ((r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX)) == 0)
7670 IWM_WRITE_1(sc, 7670 IWM_WRITE_1(sc,
7671 IWM_CSR_INT_PERIODIC_REG, IWM_CSR_INT_PERIODIC_DIS); 7671 IWM_CSR_INT_PERIODIC_REG, IWM_CSR_INT_PERIODIC_DIS);
7672 isperiodic = 1; 7672 isperiodic = 1;
7673 } 7673 }
7674 7674
7675 if ((r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX)) || 7675 if ((r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX)) ||
7676 isperiodic) { 7676 isperiodic) {
7677 IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, IWM_CSR_FH_INT_RX_MASK); 7677 IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, IWM_CSR_FH_INT_RX_MASK);
7678 7678
7679 iwm_notif_intr(sc); 7679 iwm_notif_intr(sc);
7680 7680
7681 /* enable periodic interrupt, see above */ 7681 /* enable periodic interrupt, see above */
7682 if (r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX) && 7682 if (r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX) &&
7683 !isperiodic) 7683 !isperiodic)
7684 IWM_WRITE_1(sc, IWM_CSR_INT_PERIODIC_REG, 7684 IWM_WRITE_1(sc, IWM_CSR_INT_PERIODIC_REG,
7685 IWM_CSR_INT_PERIODIC_ENA); 7685 IWM_CSR_INT_PERIODIC_ENA);
7686 } 7686 }
7687 7687
7688out_ena: 7688out_ena:
7689 iwm_restore_interrupts(sc); 7689 iwm_restore_interrupts(sc);
7690} 7690}
7691 7691
7692/* 7692/*
7693 * Autoconf glue-sniffing 7693 * Autoconf glue-sniffing
7694 */ 7694 */
7695 7695
7696static const pci_product_id_t iwm_devices[] = { 7696static const pci_product_id_t iwm_devices[] = {
7697 PCI_PRODUCT_INTEL_WIFI_LINK_7260_1, 7697 PCI_PRODUCT_INTEL_WIFI_LINK_7260_1,
7698 PCI_PRODUCT_INTEL_WIFI_LINK_7260_2, 7698 PCI_PRODUCT_INTEL_WIFI_LINK_7260_2,
7699 PCI_PRODUCT_INTEL_WIFI_LINK_3160_1, 7699 PCI_PRODUCT_INTEL_WIFI_LINK_3160_1,
7700 PCI_PRODUCT_INTEL_WIFI_LINK_3160_2, 7700 PCI_PRODUCT_INTEL_WIFI_LINK_3160_2,
7701 PCI_PRODUCT_INTEL_WIFI_LINK_7265_1, 7701 PCI_PRODUCT_INTEL_WIFI_LINK_7265_1,
7702 PCI_PRODUCT_INTEL_WIFI_LINK_7265_2, 7702 PCI_PRODUCT_INTEL_WIFI_LINK_7265_2,
7703 PCI_PRODUCT_INTEL_WIFI_LINK_3165_1, 7703 PCI_PRODUCT_INTEL_WIFI_LINK_3165_1,
7704 PCI_PRODUCT_INTEL_WIFI_LINK_3165_2, 7704 PCI_PRODUCT_INTEL_WIFI_LINK_3165_2,
7705 PCI_PRODUCT_INTEL_WIFI_LINK_3168, 7705 PCI_PRODUCT_INTEL_WIFI_LINK_3168,
7706 PCI_PRODUCT_INTEL_WIFI_LINK_8260_1, 7706 PCI_PRODUCT_INTEL_WIFI_LINK_8260_1,
7707 PCI_PRODUCT_INTEL_WIFI_LINK_8260_2, 7707 PCI_PRODUCT_INTEL_WIFI_LINK_8260_2,
7708 PCI_PRODUCT_INTEL_WIFI_LINK_4165_1, 7708 PCI_PRODUCT_INTEL_WIFI_LINK_4165_1,
7709 PCI_PRODUCT_INTEL_WIFI_LINK_4165_2, 7709 PCI_PRODUCT_INTEL_WIFI_LINK_4165_2,
7710 PCI_PRODUCT_INTEL_WIFI_LINK_8265, 7710 PCI_PRODUCT_INTEL_WIFI_LINK_8265,
7711}; 7711};
7712 7712
7713static int 7713static int
7714iwm_match(device_t parent, cfdata_t match __unused, void *aux) 7714iwm_match(device_t parent, cfdata_t match __unused, void *aux)
7715{ 7715{
7716 struct pci_attach_args *pa = aux; 7716 struct pci_attach_args *pa = aux;
7717 7717
7718 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL) 7718 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL)
7719 return 0; 7719 return 0;
7720 7720
7721 for (size_t i = 0; i < __arraycount(iwm_devices); i++) 7721 for (size_t i = 0; i < __arraycount(iwm_devices); i++)
7722 if (PCI_PRODUCT(pa->pa_id) == iwm_devices[i]) 7722 if (PCI_PRODUCT(pa->pa_id) == iwm_devices[i])
7723 return 1; 7723 return 1;
7724 7724
7725 return 0; 7725 return 0;
7726} 7726}
7727 7727
7728static int 7728static int
7729iwm_preinit(struct iwm_softc *sc) 7729iwm_preinit(struct iwm_softc *sc)
7730{ 7730{
7731 struct ieee80211com *ic = &sc->sc_ic; 7731 struct ieee80211com *ic = &sc->sc_ic;
 7732 struct ifnet *ifp = IC2IFP(&sc->sc_ic);;
7732 int err; 7733 int err;
7733 7734
7734 if (ISSET(sc->sc_flags, IWM_FLAG_ATTACHED)) 7735 if (ISSET(sc->sc_flags, IWM_FLAG_ATTACHED))
7735 return 0; 7736 return 0;
7736 7737
7737 err = iwm_start_hw(sc); 7738 err = iwm_start_hw(sc);
7738 if (err) { 7739 if (err) {
7739 aprint_error_dev(sc->sc_dev, "could not initialize hardware\n"); 7740 aprint_error_dev(sc->sc_dev, "could not initialize hardware\n");
7740 return err; 7741 return err;
7741 } 7742 }
7742 7743
7743 err = iwm_run_init_mvm_ucode(sc, 1); 7744 err = iwm_run_init_mvm_ucode(sc, 1);
7744 iwm_stop_device(sc); 7745 iwm_stop_device(sc);
7745 if (err) 7746 if (err)
7746 return err; 7747 return err;
7747 7748
7748 sc->sc_flags |= IWM_FLAG_ATTACHED; 7749 sc->sc_flags |= IWM_FLAG_ATTACHED;
7749 7750
7750 aprint_normal_dev(sc->sc_dev, "hw rev 0x%x, fw ver %s, address %s\n", 7751 aprint_normal_dev(sc->sc_dev, "hw rev 0x%x, fw ver %s, address %s\n",
7751 sc->sc_hw_rev & IWM_CSR_HW_REV_TYPE_MSK, sc->sc_fwver, 7752 sc->sc_hw_rev & IWM_CSR_HW_REV_TYPE_MSK, sc->sc_fwver,
7752 ether_sprintf(sc->sc_nvm.hw_addr)); 7753 ether_sprintf(sc->sc_nvm.hw_addr));
7753 7754
7754#ifndef IEEE80211_NO_HT 7755#ifndef IEEE80211_NO_HT
7755 if (sc->sc_nvm.sku_cap_11n_enable) 7756 if (sc->sc_nvm.sku_cap_11n_enable)
7756 iwm_setup_ht_rates(sc); 7757 iwm_setup_ht_rates(sc);
7757#endif 7758#endif
7758 7759
7759 /* not all hardware can do 5GHz band */ 7760 /* not all hardware can do 5GHz band */
7760 if (sc->sc_nvm.sku_cap_band_52GHz_enable) 7761 if (sc->sc_nvm.sku_cap_band_52GHz_enable)
7761 ic->ic_sup_rates[IEEE80211_MODE_11A] = ieee80211_std_rateset_11a; 7762 ic->ic_sup_rates[IEEE80211_MODE_11A] = ieee80211_std_rateset_11a;
7762 7763
 7764 ether_ifdetach(ifp);
7763 ieee80211_ifattach(ic); 7765 ieee80211_ifattach(ic);
7764 7766
7765 ic->ic_node_alloc = iwm_node_alloc; 7767 ic->ic_node_alloc = iwm_node_alloc;
7766 7768
7767 /* Override 802.11 state transition machine. */ 7769 /* Override 802.11 state transition machine. */
7768 sc->sc_newstate = ic->ic_newstate; 7770 sc->sc_newstate = ic->ic_newstate;
7769 ic->ic_newstate = iwm_newstate; 7771 ic->ic_newstate = iwm_newstate;
7770 ieee80211_media_init(ic, iwm_media_change, ieee80211_media_status); 7772 ieee80211_media_init(ic, iwm_media_change, ieee80211_media_status);
7771 ieee80211_announce(ic); 7773 ieee80211_announce(ic);
7772 7774
7773 iwm_radiotap_attach(sc); 7775 iwm_radiotap_attach(sc);
7774 7776
7775 return 0; 7777 return 0;
7776} 7778}
7777 7779
7778static void 7780static void
7779iwm_attach_hook(device_t dev) 7781iwm_attach_hook(device_t dev)
7780{ 7782{
7781 struct iwm_softc *sc = device_private(dev); 7783 struct iwm_softc *sc = device_private(dev);
7782 7784
7783 iwm_preinit(sc); 7785 iwm_preinit(sc);
7784} 7786}
7785 7787
7786static void 7788static void
7787iwm_attach(device_t parent, device_t self, void *aux) 7789iwm_attach(device_t parent, device_t self, void *aux)
7788{ 7790{
7789 struct iwm_softc *sc = device_private(self); 7791 struct iwm_softc *sc = device_private(self);
7790 struct pci_attach_args *pa = aux; 7792 struct pci_attach_args *pa = aux;
7791 struct ieee80211com *ic = &sc->sc_ic; 7793 struct ieee80211com *ic = &sc->sc_ic;
7792 struct ifnet *ifp = &sc->sc_ec.ec_if; 7794 struct ifnet *ifp = &sc->sc_ec.ec_if;
7793 pcireg_t reg, memtype; 7795 pcireg_t reg, memtype;
7794 char intrbuf[PCI_INTRSTR_LEN]; 7796 char intrbuf[PCI_INTRSTR_LEN];
7795 const char *intrstr; 7797 const char *intrstr;
7796 int err; 7798 int err;
7797 int txq_i; 7799 int txq_i;
7798 const struct sysctlnode *node; 7800 const struct sysctlnode *node;
7799 7801
7800 sc->sc_dev = self; 7802 sc->sc_dev = self;
7801 sc->sc_pct = pa->pa_pc; 7803 sc->sc_pct = pa->pa_pc;
7802 sc->sc_pcitag = pa->pa_tag; 7804 sc->sc_pcitag = pa->pa_tag;
7803 sc->sc_dmat = pa->pa_dmat; 7805 sc->sc_dmat = pa->pa_dmat;
7804 sc->sc_pciid = pa->pa_id; 7806 sc->sc_pciid = pa->pa_id;
7805 7807
7806 pci_aprint_devinfo(pa, NULL); 7808 pci_aprint_devinfo(pa, NULL);
7807 7809
7808 if (workqueue_create(&sc->sc_nswq, "iwmns", 7810 if (workqueue_create(&sc->sc_nswq, "iwmns",
7809 iwm_newstate_cb, sc, PRI_NONE, IPL_NET, 0)) 7811 iwm_newstate_cb, sc, PRI_NONE, IPL_NET, 0))
7810 panic("%s: could not create workqueue: newstate", 7812 panic("%s: could not create workqueue: newstate",
7811 device_xname(self)); 7813 device_xname(self));
7812 sc->sc_soft_ih = softint_establish(SOFTINT_NET, iwm_softintr, sc); 7814 sc->sc_soft_ih = softint_establish(SOFTINT_NET, iwm_softintr, sc);
7813 if (sc->sc_soft_ih == NULL) 7815 if (sc->sc_soft_ih == NULL)
7814 panic("%s: could not establish softint", device_xname(self)); 7816 panic("%s: could not establish softint", device_xname(self));
7815 7817
7816 /* 7818 /*
7817 * Get the offset of the PCI Express Capability Structure in PCI 7819 * Get the offset of the PCI Express Capability Structure in PCI
7818 * Configuration Space. 7820 * Configuration Space.
7819 */ 7821 */
7820 err = pci_get_capability(sc->sc_pct, sc->sc_pcitag, 7822 err = pci_get_capability(sc->sc_pct, sc->sc_pcitag,
7821 PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, NULL); 7823 PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, NULL);
7822 if (err == 0) { 7824 if (err == 0) {
7823 aprint_error_dev(self, 7825 aprint_error_dev(self,
7824 "PCIe capability structure not found!\n"); 7826 "PCIe capability structure not found!\n");
7825 return; 7827 return;
7826 } 7828 }
7827 7829
7828 /* Clear device-specific "PCI retry timeout" register (41h). */ 7830 /* Clear device-specific "PCI retry timeout" register (41h). */
7829 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40); 7831 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
7830 pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00); 7832 pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);
7831 7833
7832 /* Enable bus-mastering */ 7834 /* Enable bus-mastering */
7833 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG); 7835 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);
7834 reg |= PCI_COMMAND_MASTER_ENABLE; 7836 reg |= PCI_COMMAND_MASTER_ENABLE;
7835 pci_conf_write(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, reg); 7837 pci_conf_write(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, reg);
7836 7838
7837 memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START); 7839 memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START);
7838 err = pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0, 7840 err = pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0,
7839 &sc->sc_st, &sc->sc_sh, NULL, &sc->sc_sz); 7841 &sc->sc_st, &sc->sc_sh, NULL, &sc->sc_sz);
7840 if (err) { 7842 if (err) {
7841 aprint_error_dev(self, "can't map mem space\n"); 7843 aprint_error_dev(self, "can't map mem space\n");
7842 return; 7844 return;
7843 } 7845 }
7844 7846
7845 /* Install interrupt handler. */ 7847 /* Install interrupt handler. */
7846 err = pci_intr_alloc(pa, &sc->sc_pihp, NULL, 0); 7848 err = pci_intr_alloc(pa, &sc->sc_pihp, NULL, 0);
7847 if (err) { 7849 if (err) {
7848 aprint_error_dev(self, "can't allocate interrupt\n"); 7850 aprint_error_dev(self, "can't allocate interrupt\n");
7849 return; 7851 return;
7850 } 7852 }
7851 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG); 7853 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);
7852 if (pci_intr_type(sc->sc_pct, sc->sc_pihp[0]) == PCI_INTR_TYPE_INTX) 7854 if (pci_intr_type(sc->sc_pct, sc->sc_pihp[0]) == PCI_INTR_TYPE_INTX)
7853 CLR(reg, PCI_COMMAND_INTERRUPT_DISABLE); 7855 CLR(reg, PCI_COMMAND_INTERRUPT_DISABLE);
7854 else 7856 else
7855 SET(reg, PCI_COMMAND_INTERRUPT_DISABLE); 7857 SET(reg, PCI_COMMAND_INTERRUPT_DISABLE);
7856 pci_conf_write(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, reg); 7858 pci_conf_write(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, reg);
7857 intrstr = pci_intr_string(sc->sc_pct, sc->sc_pihp[0], intrbuf, 7859 intrstr = pci_intr_string(sc->sc_pct, sc->sc_pihp[0], intrbuf,
7858 sizeof(intrbuf)); 7860 sizeof(intrbuf));
7859 sc->sc_ih = pci_intr_establish_xname(sc->sc_pct, sc->sc_pihp[0], 7861 sc->sc_ih = pci_intr_establish_xname(sc->sc_pct, sc->sc_pihp[0],
7860 IPL_NET, iwm_intr, sc, device_xname(self)); 7862 IPL_NET, iwm_intr, sc, device_xname(self));
7861 if (sc->sc_ih == NULL) { 7863 if (sc->sc_ih == NULL) {
7862 aprint_error_dev(self, "can't establish interrupt"); 7864 aprint_error_dev(self, "can't establish interrupt");
7863 if (intrstr != NULL) 7865 if (intrstr != NULL)
7864 aprint_error(" at %s", intrstr); 7866 aprint_error(" at %s", intrstr);
7865 aprint_error("\n"); 7867 aprint_error("\n");
7866 return; 7868 return;
7867 } 7869 }
7868 aprint_normal_dev(self, "interrupting at %s\n", intrstr); 7870 aprint_normal_dev(self, "interrupting at %s\n", intrstr);
7869 7871
7870 sc->sc_wantresp = IWM_CMD_RESP_IDLE; 7872 sc->sc_wantresp = IWM_CMD_RESP_IDLE;
7871 7873
7872 sc->sc_hw_rev = IWM_READ(sc, IWM_CSR_HW_REV); 7874 sc->sc_hw_rev = IWM_READ(sc, IWM_CSR_HW_REV);
7873 switch (PCI_PRODUCT(sc->sc_pciid)) { 7875 switch (PCI_PRODUCT(sc->sc_pciid)) {
7874 case PCI_PRODUCT_INTEL_WIFI_LINK_3160_1: 7876 case PCI_PRODUCT_INTEL_WIFI_LINK_3160_1:
7875 case PCI_PRODUCT_INTEL_WIFI_LINK_3160_2: 7877 case PCI_PRODUCT_INTEL_WIFI_LINK_3160_2:
7876 sc->sc_fwname = "iwlwifi-3160-17.ucode"; 7878 sc->sc_fwname = "iwlwifi-3160-17.ucode";
7877 sc->host_interrupt_operation_mode = 1; 7879 sc->host_interrupt_operation_mode = 1;
7878 sc->apmg_wake_up_wa = 1; 7880 sc->apmg_wake_up_wa = 1;
7879 sc->sc_device_family = IWM_DEVICE_FAMILY_7000; 7881 sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
7880 sc->sc_fwdmasegsz = IWM_FWDMASEGSZ; 7882 sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
7881 break; 7883 break;
7882 case PCI_PRODUCT_INTEL_WIFI_LINK_3165_1: 7884 case PCI_PRODUCT_INTEL_WIFI_LINK_3165_1:
7883 case PCI_PRODUCT_INTEL_WIFI_LINK_3165_2: 7885 case PCI_PRODUCT_INTEL_WIFI_LINK_3165_2:
7884 sc->sc_fwname = "iwlwifi-7265D-22.ucode"; 7886 sc->sc_fwname = "iwlwifi-7265D-22.ucode";
7885 sc->host_interrupt_operation_mode = 0; 7887 sc->host_interrupt_operation_mode = 0;
7886 sc->apmg_wake_up_wa = 1; 7888 sc->apmg_wake_up_wa = 1;
7887 sc->sc_device_family = IWM_DEVICE_FAMILY_7000; 7889 sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
7888 sc->sc_fwdmasegsz = IWM_FWDMASEGSZ; 7890 sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
7889 break; 7891 break;
7890 case PCI_PRODUCT_INTEL_WIFI_LINK_3168: 7892 case PCI_PRODUCT_INTEL_WIFI_LINK_3168:
7891 sc->sc_fwname = "iwlwifi-3168-22.ucode"; 7893 sc->sc_fwname = "iwlwifi-3168-22.ucode";
7892 sc->host_interrupt_operation_mode = 0; 7894 sc->host_interrupt_operation_mode = 0;
7893 sc->apmg_wake_up_wa = 1; 7895 sc->apmg_wake_up_wa = 1;
7894 sc->sc_device_family = IWM_DEVICE_FAMILY_7000; 7896 sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
7895 sc->sc_fwdmasegsz = IWM_FWDMASEGSZ; 7897 sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
7896 break; 7898 break;
7897 case PCI_PRODUCT_INTEL_WIFI_LINK_7260_1: 7899 case PCI_PRODUCT_INTEL_WIFI_LINK_7260_1:
7898 case PCI_PRODUCT_INTEL_WIFI_LINK_7260_2: 7900 case PCI_PRODUCT_INTEL_WIFI_LINK_7260_2:
7899 sc->sc_fwname = "iwlwifi-7260-17.ucode"; 7901 sc->sc_fwname = "iwlwifi-7260-17.ucode";
7900 sc->host_interrupt_operation_mode = 1; 7902 sc->host_interrupt_operation_mode = 1;
7901 sc->apmg_wake_up_wa = 1; 7903 sc->apmg_wake_up_wa = 1;
7902 sc->sc_device_family = IWM_DEVICE_FAMILY_7000; 7904 sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
7903 sc->sc_fwdmasegsz = IWM_FWDMASEGSZ; 7905 sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
7904 break; 7906 break;
7905 case PCI_PRODUCT_INTEL_WIFI_LINK_7265_1: 7907 case PCI_PRODUCT_INTEL_WIFI_LINK_7265_1:
7906 case PCI_PRODUCT_INTEL_WIFI_LINK_7265_2: 7908 case PCI_PRODUCT_INTEL_WIFI_LINK_7265_2:
7907 sc->sc_fwname = (sc->sc_hw_rev & IWM_CSR_HW_REV_TYPE_MSK) == 7909 sc->sc_fwname = (sc->sc_hw_rev & IWM_CSR_HW_REV_TYPE_MSK) ==
7908 IWM_CSR_HW_REV_TYPE_7265D ? 7910 IWM_CSR_HW_REV_TYPE_7265D ?
7909 "iwlwifi-7265D-22.ucode": "iwlwifi-7265-17.ucode"; 7911 "iwlwifi-7265D-22.ucode": "iwlwifi-7265-17.ucode";
7910 sc->host_interrupt_operation_mode = 0; 7912 sc->host_interrupt_operation_mode = 0;
7911 sc->apmg_wake_up_wa = 1; 7913 sc->apmg_wake_up_wa = 1;
7912 sc->sc_device_family = IWM_DEVICE_FAMILY_7000; 7914 sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
7913 sc->sc_fwdmasegsz = IWM_FWDMASEGSZ; 7915 sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
7914 break; 7916 break;
7915 case PCI_PRODUCT_INTEL_WIFI_LINK_8260_1: 7917 case PCI_PRODUCT_INTEL_WIFI_LINK_8260_1:
7916 case PCI_PRODUCT_INTEL_WIFI_LINK_8260_2: 7918 case PCI_PRODUCT_INTEL_WIFI_LINK_8260_2:
7917 case PCI_PRODUCT_INTEL_WIFI_LINK_4165_1: 7919 case PCI_PRODUCT_INTEL_WIFI_LINK_4165_1:
7918 case PCI_PRODUCT_INTEL_WIFI_LINK_4165_2: 7920 case PCI_PRODUCT_INTEL_WIFI_LINK_4165_2:
7919 sc->sc_fwname = "iwlwifi-8000C-22.ucode"; 7921 sc->sc_fwname = "iwlwifi-8000C-22.ucode";
7920 sc->host_interrupt_operation_mode = 0; 7922 sc->host_interrupt_operation_mode = 0;
7921 sc->apmg_wake_up_wa = 0; 7923 sc->apmg_wake_up_wa = 0;
7922 sc->sc_device_family = IWM_DEVICE_FAMILY_8000; 7924 sc->sc_device_family = IWM_DEVICE_FAMILY_8000;
7923 sc->sc_fwdmasegsz = IWM_FWDMASEGSZ_8000; 7925 sc->sc_fwdmasegsz = IWM_FWDMASEGSZ_8000;
7924 break; 7926 break;
7925 case PCI_PRODUCT_INTEL_WIFI_LINK_8265: 7927 case PCI_PRODUCT_INTEL_WIFI_LINK_8265:
7926 sc->sc_fwname = "iwlwifi-8265-22.ucode"; 7928 sc->sc_fwname = "iwlwifi-8265-22.ucode";
7927 sc->host_interrupt_operation_mode = 0; 7929 sc->host_interrupt_operation_mode = 0;
7928 sc->apmg_wake_up_wa = 0; 7930 sc->apmg_wake_up_wa = 0;
7929 sc->sc_device_family = IWM_DEVICE_FAMILY_8000; 7931 sc->sc_device_family = IWM_DEVICE_FAMILY_8000;
7930 sc->sc_fwdmasegsz = IWM_FWDMASEGSZ_8000; 7932 sc->sc_fwdmasegsz = IWM_FWDMASEGSZ_8000;
7931 break; 7933 break;
7932 default: 7934 default:
7933 aprint_error_dev(self, "unknown product %#x", 7935 aprint_error_dev(self, "unknown product %#x",
7934 PCI_PRODUCT(sc->sc_pciid)); 7936 PCI_PRODUCT(sc->sc_pciid));
7935 return; 7937 return;
7936 } 7938 }
7937 DPRINTF(("%s: firmware=%s\n", DEVNAME(sc), sc->sc_fwname)); 7939 DPRINTF(("%s: firmware=%s\n", DEVNAME(sc), sc->sc_fwname));
7938 7940
7939 /* 7941 /*
7940 * In the 8000 HW family the format of the 4 bytes of CSR_HW_REV have 7942 * In the 8000 HW family the format of the 4 bytes of CSR_HW_REV have
7941 * changed, and now the revision step also includes bit 0-1 (no more 7943 * changed, and now the revision step also includes bit 0-1 (no more
7942 * "dash" value). To keep hw_rev backwards compatible - we'll store it 7944 * "dash" value). To keep hw_rev backwards compatible - we'll store it
7943 * in the old format. 7945 * in the old format.
7944 */ 7946 */
7945 7947
7946 if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000) 7948 if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000)
7947 sc->sc_hw_rev = (sc->sc_hw_rev & 0xfff0) | 7949 sc->sc_hw_rev = (sc->sc_hw_rev & 0xfff0) |
7948 (IWM_CSR_HW_REV_STEP(sc->sc_hw_rev << 2) << 2); 7950 (IWM_CSR_HW_REV_STEP(sc->sc_hw_rev << 2) << 2);
7949 7951
7950 if (iwm_prepare_card_hw(sc) != 0) { 7952 if (iwm_prepare_card_hw(sc) != 0) {
7951 aprint_error_dev(sc->sc_dev, "could not initialize hardware\n"); 7953 aprint_error_dev(sc->sc_dev, "could not initialize hardware\n");
7952 return; 7954 return;
7953 } 7955 }
7954 7956
7955 if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000) { 7957 if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000) {
7956 uint32_t hw_step; 7958 uint32_t hw_step;
7957 7959
7958 /* 7960 /*
7959 * In order to recognize C step the driver should read the 7961 * In order to recognize C step the driver should read the
7960 * chip version id located at the AUX bus MISC address. 7962 * chip version id located at the AUX bus MISC address.
7961 */ 7963 */
7962 IWM_SETBITS(sc, IWM_CSR_GP_CNTRL, 7964 IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
7963 IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE); 7965 IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
7964 DELAY(2); 7966 DELAY(2);
7965 7967
7966 err = iwm_poll_bit(sc, IWM_CSR_GP_CNTRL, 7968 err = iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
7967 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 7969 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
7968 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 7970 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
7969 25000); 7971 25000);
7970 if (!err) { 7972 if (!err) {
7971 aprint_error_dev(sc->sc_dev, 7973 aprint_error_dev(sc->sc_dev,
7972 "failed to wake up the nic\n"); 7974 "failed to wake up the nic\n");
7973 return; 7975 return;
7974 } 7976 }
7975 7977
7976 if (iwm_nic_lock(sc)) { 7978 if (iwm_nic_lock(sc)) {
7977 hw_step = iwm_read_prph(sc, IWM_WFPM_CTRL_REG); 7979 hw_step = iwm_read_prph(sc, IWM_WFPM_CTRL_REG);
7978 hw_step |= IWM_ENABLE_WFPM; 7980 hw_step |= IWM_ENABLE_WFPM;
7979 iwm_write_prph(sc, IWM_WFPM_CTRL_REG, hw_step); 7981 iwm_write_prph(sc, IWM_WFPM_CTRL_REG, hw_step);
7980 hw_step = iwm_read_prph(sc, IWM_AUX_MISC_REG); 7982 hw_step = iwm_read_prph(sc, IWM_AUX_MISC_REG);
7981 hw_step = (hw_step >> IWM_HW_STEP_LOCATION_BITS) & 0xF; 7983 hw_step = (hw_step >> IWM_HW_STEP_LOCATION_BITS) & 0xF;
7982 if (hw_step == 0x3) 7984 if (hw_step == 0x3)
7983 sc->sc_hw_rev = (sc->sc_hw_rev & 0xFFFFFFF3) | 7985 sc->sc_hw_rev = (sc->sc_hw_rev & 0xFFFFFFF3) |
7984 (IWM_SILICON_C_STEP << 2); 7986 (IWM_SILICON_C_STEP << 2);
7985 iwm_nic_unlock(sc); 7987 iwm_nic_unlock(sc);
7986 } else { 7988 } else {
7987 aprint_error_dev(sc->sc_dev, 7989 aprint_error_dev(sc->sc_dev,
7988 "failed to lock the nic\n"); 7990 "failed to lock the nic\n");
7989 return; 7991 return;
7990 } 7992 }
7991 } 7993 }
7992 7994
7993 /* 7995 /*
7994 * Allocate DMA memory for firmware transfers. 7996 * Allocate DMA memory for firmware transfers.
7995 * Must be aligned on a 16-byte boundary. 7997 * Must be aligned on a 16-byte boundary.
7996 */ 7998 */
7997 err = iwm_dma_contig_alloc(sc->sc_dmat, &sc->fw_dma, sc->sc_fwdmasegsz, 7999 err = iwm_dma_contig_alloc(sc->sc_dmat, &sc->fw_dma, sc->sc_fwdmasegsz,
7998 16); 8000 16);
7999 if (err) { 8001 if (err) {
8000 aprint_error_dev(sc->sc_dev, 8002 aprint_error_dev(sc->sc_dev,
8001 "could not allocate memory for firmware\n"); 8003 "could not allocate memory for firmware\n");
8002 return; 8004 return;
8003 } 8005 }
8004 8006
8005 /* Allocate "Keep Warm" page, used internally by the card. */ 8007 /* Allocate "Keep Warm" page, used internally by the card. */
8006 err = iwm_dma_contig_alloc(sc->sc_dmat, &sc->kw_dma, 4096, 4096); 8008 err = iwm_dma_contig_alloc(sc->sc_dmat, &sc->kw_dma, 4096, 4096);
8007 if (err) { 8009 if (err) {
8008 aprint_error_dev(sc->sc_dev, 8010 aprint_error_dev(sc->sc_dev,
8009 "could not allocate keep warm page\n"); 8011 "could not allocate keep warm page\n");
8010 goto fail1; 8012 goto fail1;
8011 } 8013 }
8012 8014
8013 /* Allocate interrupt cause table (ICT).*/ 8015 /* Allocate interrupt cause table (ICT).*/
8014 err = iwm_dma_contig_alloc(sc->sc_dmat, &sc->ict_dma, IWM_ICT_SIZE, 8016 err = iwm_dma_contig_alloc(sc->sc_dmat, &sc->ict_dma, IWM_ICT_SIZE,
8015 1 << IWM_ICT_PADDR_SHIFT); 8017 1 << IWM_ICT_PADDR_SHIFT);
8016 if (err) { 8018 if (err) {
8017 aprint_error_dev(sc->sc_dev, "could not allocate ICT table\n"); 8019 aprint_error_dev(sc->sc_dev, "could not allocate ICT table\n");
8018 goto fail2; 8020 goto fail2;
8019 } 8021 }
8020 8022
8021 /* TX scheduler rings must be aligned on a 1KB boundary. */ 8023 /* TX scheduler rings must be aligned on a 1KB boundary. */
8022 err = iwm_dma_contig_alloc(sc->sc_dmat, &sc->sched_dma, 8024 err = iwm_dma_contig_alloc(sc->sc_dmat, &sc->sched_dma,
8023 __arraycount(sc->txq) * sizeof(struct iwm_agn_scd_bc_tbl), 1024); 8025 __arraycount(sc->txq) * sizeof(struct iwm_agn_scd_bc_tbl), 1024);
8024 if (err) { 8026 if (err) {
8025 aprint_error_dev(sc->sc_dev, 8027 aprint_error_dev(sc->sc_dev,
8026 "could not allocate TX scheduler rings\n"); 8028 "could not allocate TX scheduler rings\n");
8027 goto fail3; 8029 goto fail3;
8028 } 8030 }
8029 8031
8030 for (txq_i = 0; txq_i < __arraycount(sc->txq); txq_i++) { 8032 for (txq_i = 0; txq_i < __arraycount(sc->txq); txq_i++) {
8031 err = iwm_alloc_tx_ring(sc, &sc->txq[txq_i], txq_i); 8033 err = iwm_alloc_tx_ring(sc, &sc->txq[txq_i], txq_i);
8032 if (err) { 8034 if (err) {
8033 aprint_error_dev(sc->sc_dev, 8035 aprint_error_dev(sc->sc_dev,
8034 "could not allocate TX ring %d\n", txq_i); 8036 "could not allocate TX ring %d\n", txq_i);
8035 goto fail4; 8037 goto fail4;
8036 } 8038 }
8037 } 8039 }
8038 8040
8039 err = iwm_alloc_rx_ring(sc, &sc->rxq); 8041 err = iwm_alloc_rx_ring(sc, &sc->rxq);
8040 if (err) { 8042 if (err) {
8041 aprint_error_dev(sc->sc_dev, "could not allocate RX ring\n"); 8043 aprint_error_dev(sc->sc_dev, "could not allocate RX ring\n");
8042 goto fail5; 8044 goto fail5;
8043 } 8045 }
8044 8046
8045 /* Clear pending interrupts. */ 8047 /* Clear pending interrupts. */
8046 IWM_WRITE(sc, IWM_CSR_INT, 0xffffffff); 8048 IWM_WRITE(sc, IWM_CSR_INT, 0xffffffff);
8047 8049
8048 if ((err = sysctl_createv(&sc->sc_clog, 0, NULL, &node, 8050 if ((err = sysctl_createv(&sc->sc_clog, 0, NULL, &node,
8049 0, CTLTYPE_NODE, device_xname(sc->sc_dev), 8051 0, CTLTYPE_NODE, device_xname(sc->sc_dev),
8050 SYSCTL_DESCR("iwm per-controller controls"), 8052 SYSCTL_DESCR("iwm per-controller controls"),
8051 NULL, 0, NULL, 0, 8053 NULL, 0, NULL, 0,
8052 CTL_HW, iwm_sysctl_root_num, CTL_CREATE, 8054 CTL_HW, iwm_sysctl_root_num, CTL_CREATE,
8053 CTL_EOL)) != 0) { 8055 CTL_EOL)) != 0) {
8054 aprint_normal_dev(sc->sc_dev, 8056 aprint_normal_dev(sc->sc_dev,
8055 "couldn't create iwm per-controller sysctl node\n"); 8057 "couldn't create iwm per-controller sysctl node\n");
8056 } 8058 }
8057 if (err == 0) { 8059 if (err == 0) {
8058 int iwm_nodenum = node->sysctl_num; 8060 int iwm_nodenum = node->sysctl_num;
8059 8061
8060 /* Reload firmware sysctl node */ 8062 /* Reload firmware sysctl node */
8061 if ((err = sysctl_createv(&sc->sc_clog, 0, NULL, &node, 8063 if ((err = sysctl_createv(&sc->sc_clog, 0, NULL, &node,
8062 CTLFLAG_READWRITE, CTLTYPE_INT, "fw_loaded", 8064 CTLFLAG_READWRITE, CTLTYPE_INT, "fw_loaded",
8063 SYSCTL_DESCR("Reload firmware"), 8065 SYSCTL_DESCR("Reload firmware"),
8064 iwm_sysctl_fw_loaded_handler, 0, (void *)sc, 0, 8066 iwm_sysctl_fw_loaded_handler, 0, (void *)sc, 0,
8065 CTL_HW, iwm_sysctl_root_num, iwm_nodenum, CTL_CREATE, 8067 CTL_HW, iwm_sysctl_root_num, iwm_nodenum, CTL_CREATE,
8066 CTL_EOL)) != 0) { 8068 CTL_EOL)) != 0) {
8067 aprint_normal_dev(sc->sc_dev, 8069 aprint_normal_dev(sc->sc_dev,
8068 "couldn't create load_fw sysctl node\n"); 8070 "couldn't create load_fw sysctl node\n");
8069 } 8071 }
8070 } 8072 }
8071 8073
8072 /* 8074 /*
8073 * Attach interface 8075 * Attach interface
8074 */ 8076 */
8075 ic->ic_ifp = ifp; 8077 ic->ic_ifp = ifp;
8076 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 8078 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
8077 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ 8079 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
8078 ic->ic_state = IEEE80211_S_INIT; 8080 ic->ic_state = IEEE80211_S_INIT;
8079 8081
8080 /* Set device capabilities. */ 8082 /* Set device capabilities. */
8081 ic->ic_caps = 8083 ic->ic_caps =
8082 IEEE80211_C_WEP | /* WEP */ 8084 IEEE80211_C_WEP | /* WEP */
8083 IEEE80211_C_WPA | /* 802.11i */ 8085 IEEE80211_C_WPA | /* 802.11i */
8084#ifdef notyet 8086#ifdef notyet
8085 IEEE80211_C_SCANALL | /* device scans all channels at once */ 8087 IEEE80211_C_SCANALL | /* device scans all channels at once */
8086 IEEE80211_C_SCANALLBAND | /* device scans all bands at once */ 8088 IEEE80211_C_SCANALLBAND | /* device scans all bands at once */
8087#endif 8089#endif
8088 IEEE80211_C_SHSLOT | /* short slot time supported */ 8090 IEEE80211_C_SHSLOT | /* short slot time supported */
8089 IEEE80211_C_SHPREAMBLE; /* short preamble supported */ 8091 IEEE80211_C_SHPREAMBLE; /* short preamble supported */
8090 8092
8091#ifndef IEEE80211_NO_HT 8093#ifndef IEEE80211_NO_HT
8092 ic->ic_htcaps = IEEE80211_HTCAP_SGI20; 8094 ic->ic_htcaps = IEEE80211_HTCAP_SGI20;
8093 ic->ic_htxcaps = 0; 8095 ic->ic_htxcaps = 0;
8094 ic->ic_txbfcaps = 0; 8096 ic->ic_txbfcaps = 0;
8095 ic->ic_aselcaps = 0; 8097 ic->ic_aselcaps = 0;
8096 ic->ic_ampdu_params = (IEEE80211_AMPDU_PARAM_SS_4 | 0x3 /* 64k */); 8098 ic->ic_ampdu_params = (IEEE80211_AMPDU_PARAM_SS_4 | 0x3 /* 64k */);
8097#endif 8099#endif
8098 8100
8099 /* all hardware can do 2.4GHz band */ 8101 /* all hardware can do 2.4GHz band */
8100 ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b; 8102 ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
8101 ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g; 8103 ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
8102 8104
8103 for (int i = 0; i < __arraycount(sc->sc_phyctxt); i++) { 8105 for (int i = 0; i < __arraycount(sc->sc_phyctxt); i++) {
8104 sc->sc_phyctxt[i].id = i; 8106 sc->sc_phyctxt[i].id = i;
8105 } 8107 }
8106 8108
8107 sc->sc_amrr.amrr_min_success_threshold = 1; 8109 sc->sc_amrr.amrr_min_success_threshold = 1;
8108 sc->sc_amrr.amrr_max_success_threshold = 15; 8110 sc->sc_amrr.amrr_max_success_threshold = 15;
8109 8111
8110 /* IBSS channel undefined for now. */ 8112 /* IBSS channel undefined for now. */
8111 ic->ic_ibss_chan = &ic->ic_channels[1]; 8113 ic->ic_ibss_chan = &ic->ic_channels[1];
8112 8114
8113#if 0 8115#if 0
8114 ic->ic_max_rssi = IWM_MAX_DBM - IWM_MIN_DBM; 8116 ic->ic_max_rssi = IWM_MAX_DBM - IWM_MIN_DBM;
8115#endif 8117#endif
8116 8118
8117 ifp->if_softc = sc; 8119 ifp->if_softc = sc;
8118 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 8120 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
8119 ifp->if_init = iwm_init; 8121 ifp->if_init = iwm_init;
8120 ifp->if_stop = iwm_stop; 8122 ifp->if_stop = iwm_stop;
8121 ifp->if_ioctl = iwm_ioctl; 8123 ifp->if_ioctl = iwm_ioctl;
8122 ifp->if_start = iwm_start; 8124 ifp->if_start = iwm_start;
8123 ifp->if_watchdog = iwm_watchdog; 8125 ifp->if_watchdog = iwm_watchdog;
8124 IFQ_SET_READY(&ifp->if_snd); 8126 IFQ_SET_READY(&ifp->if_snd);
8125 memcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ); 8127 memcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
8126 8128
8127 err = if_initialize(ifp); 8129 err = if_initialize(ifp);
8128 if (err != 0) { 8130 if (err != 0) {
8129 aprint_error_dev(sc->sc_dev, "if_initialize failed(%d)\n", 8131 aprint_error_dev(sc->sc_dev, "if_initialize failed(%d)\n",
8130 err); 8132 err);
8131 goto fail6; 8133 goto fail6;
8132 } 8134 }
8133#if 0 8135#if 0
8134 ieee80211_ifattach(ic); 8136 ieee80211_ifattach(ic);
8135#else 8137#else
8136 ether_ifattach(ifp, ic->ic_myaddr); /* XXX */ 8138 ether_ifattach(ifp, NULL); /* XXX */
8137#endif 8139#endif
8138 /* Use common softint-based if_input */ 8140 /* Use common softint-based if_input */
8139 ifp->if_percpuq = if_percpuq_create(ifp); 8141 ifp->if_percpuq = if_percpuq_create(ifp);
8140 if_register(ifp); 8142 if_register(ifp);
8141 8143
8142 callout_init(&sc->sc_calib_to, 0); 8144 callout_init(&sc->sc_calib_to, 0);
8143 callout_setfunc(&sc->sc_calib_to, iwm_calib_timeout, sc); 8145 callout_setfunc(&sc->sc_calib_to, iwm_calib_timeout, sc);
8144 callout_init(&sc->sc_led_blink_to, 0); 8146 callout_init(&sc->sc_led_blink_to, 0);
8145 callout_setfunc(&sc->sc_led_blink_to, iwm_led_blink_timeout, sc); 8147 callout_setfunc(&sc->sc_led_blink_to, iwm_led_blink_timeout, sc);
8146#ifndef IEEE80211_NO_HT 8148#ifndef IEEE80211_NO_HT
8147 if (workqueue_create(&sc->sc_setratewq, "iwmsr", 8149 if (workqueue_create(&sc->sc_setratewq, "iwmsr",
8148 iwm_setrates_task, sc, PRI_NONE, IPL_NET, 0)) 8150 iwm_setrates_task, sc, PRI_NONE, IPL_NET, 0))
8149 panic("%s: could not create workqueue: setrates", 8151 panic("%s: could not create workqueue: setrates",
8150 device_xname(self)); 8152 device_xname(self));
8151 if (workqueue_create(&sc->sc_bawq, "iwmba", 8153 if (workqueue_create(&sc->sc_bawq, "iwmba",
8152 iwm_ba_task, sc, PRI_NONE, IPL_NET, 0)) 8154 iwm_ba_task, sc, PRI_NONE, IPL_NET, 0))
8153 panic("%s: could not create workqueue: blockack", 8155 panic("%s: could not create workqueue: blockack",
8154 device_xname(self)); 8156 device_xname(self));
8155 if (workqueue_create(&sc->sc_htprowq, "iwmhtpro", 8157 if (workqueue_create(&sc->sc_htprowq, "iwmhtpro",
8156 iwm_htprot_task, sc, PRI_NONE, IPL_NET, 0)) 8158 iwm_htprot_task, sc, PRI_NONE, IPL_NET, 0))
8157 panic("%s: could not create workqueue: htprot", 8159 panic("%s: could not create workqueue: htprot",
8158 device_xname(self)); 8160 device_xname(self));
8159#endif 8161#endif
8160 8162
8161 if (pmf_device_register(self, NULL, NULL)) 8163 if (pmf_device_register(self, NULL, NULL))
8162 pmf_class_network_register(self, ifp); 8164 pmf_class_network_register(self, ifp);
8163 else 8165 else
8164 aprint_error_dev(self, "couldn't establish power handler\n"); 8166 aprint_error_dev(self, "couldn't establish power handler\n");
8165 8167
8166 /* 8168 /*
8167 * We can't do normal attach before the file system is mounted 8169 * We can't do normal attach before the file system is mounted
8168 * because we cannot read the MAC address without loading the 8170 * because we cannot read the MAC address without loading the
8169 * firmware from disk. So we postpone until mountroot is done. 8171 * firmware from disk. So we postpone until mountroot is done.
8170 * Notably, this will require a full driver unload/load cycle 8172 * Notably, this will require a full driver unload/load cycle
8171 * (or reboot) in case the firmware is not present when the 8173 * (or reboot) in case the firmware is not present when the
8172 * hook runs. 8174 * hook runs.
8173 */ 8175 */
8174 config_mountroot(self, iwm_attach_hook); 8176 config_mountroot(self, iwm_attach_hook);
8175 8177
8176 return; 8178 return;
8177 8179
8178fail6: iwm_free_rx_ring(sc, &sc->rxq); 8180fail6: iwm_free_rx_ring(sc, &sc->rxq);
8179fail5: while (--txq_i >= 0) 8181fail5: while (--txq_i >= 0)
8180 iwm_free_tx_ring(sc, &sc->txq[txq_i]); 8182 iwm_free_tx_ring(sc, &sc->txq[txq_i]);
8181fail4: iwm_dma_contig_free(&sc->sched_dma); 8183fail4: iwm_dma_contig_free(&sc->sched_dma);
8182fail3: if (sc->ict_dma.vaddr != NULL) 8184fail3: if (sc->ict_dma.vaddr != NULL)
8183 iwm_dma_contig_free(&sc->ict_dma); 8185 iwm_dma_contig_free(&sc->ict_dma);
8184fail2: iwm_dma_contig_free(&sc->kw_dma); 8186fail2: iwm_dma_contig_free(&sc->kw_dma);
8185fail1: iwm_dma_contig_free(&sc->fw_dma); 8187fail1: iwm_dma_contig_free(&sc->fw_dma);
8186} 8188}
8187 8189
8188void 8190void
8189iwm_radiotap_attach(struct iwm_softc *sc) 8191iwm_radiotap_attach(struct iwm_softc *sc)
8190{ 8192{
8191 struct ifnet *ifp = IC2IFP(&sc->sc_ic); 8193 struct ifnet *ifp = IC2IFP(&sc->sc_ic);
8192 8194
8193 bpf_attach2(ifp, DLT_IEEE802_11_RADIO, 8195 bpf_attach2(ifp, DLT_IEEE802_11_RADIO,
8194 sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN, 8196 sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN,
8195 &sc->sc_drvbpf); 8197 &sc->sc_drvbpf);
8196 8198
8197 sc->sc_rxtap_len = sizeof sc->sc_rxtapu; 8199 sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
8198 sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); 8200 sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
8199 sc->sc_rxtap.wr_ihdr.it_present = htole32(IWM_RX_RADIOTAP_PRESENT); 8201 sc->sc_rxtap.wr_ihdr.it_present = htole32(IWM_RX_RADIOTAP_PRESENT);
8200 8202
8201 sc->sc_txtap_len = sizeof sc->sc_txtapu; 8203 sc->sc_txtap_len = sizeof sc->sc_txtapu;
8202 sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); 8204 sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
8203 sc->sc_txtap.wt_ihdr.it_present = htole32(IWM_TX_RADIOTAP_PRESENT); 8205 sc->sc_txtap.wt_ihdr.it_present = htole32(IWM_TX_RADIOTAP_PRESENT);
8204} 8206}
8205 8207
8206#if 0 8208#if 0
8207static void 8209static void
8208iwm_init_task(void *arg) 8210iwm_init_task(void *arg)
8209{ 8211{
8210 struct iwm_softc *sc = arg; 8212 struct iwm_softc *sc = arg;
8211 struct ifnet *ifp = IC2IFP(&sc->sc_ic); 8213 struct ifnet *ifp = IC2IFP(&sc->sc_ic);
8212 int s; 8214 int s;
8213 8215
8214 rw_enter_write(&sc->ioctl_rwl); 8216 rw_enter_write(&sc->ioctl_rwl);
8215 s = splnet(); 8217 s = splnet();
8216 8218
8217 iwm_stop(ifp, 0); 8219 iwm_stop(ifp, 0);
8218 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP) 8220 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP)
8219 iwm_init(ifp); 8221 iwm_init(ifp);
8220 8222
8221 splx(s); 8223 splx(s);
8222 rw_exit(&sc->ioctl_rwl); 8224 rw_exit(&sc->ioctl_rwl);
8223} 8225}
8224 8226
8225static void 8227static void
8226iwm_wakeup(struct iwm_softc *sc) 8228iwm_wakeup(struct iwm_softc *sc)
8227{ 8229{
8228 pcireg_t reg; 8230 pcireg_t reg;
8229 8231
8230 /* Clear device-specific "PCI retry timeout" register (41h). */ 8232 /* Clear device-specific "PCI retry timeout" register (41h). */
8231 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40); 8233 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
8232 pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00); 8234 pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);
8233 8235
8234 iwm_init_task(sc); 8236 iwm_init_task(sc);
8235} 8237}
8236 8238
8237static int 8239static int
8238iwm_activate(device_t self, enum devact act) 8240iwm_activate(device_t self, enum devact act)
8239{ 8241{
8240 struct iwm_softc *sc = device_private(self); 8242 struct iwm_softc *sc = device_private(self);
8241 struct ifnet *ifp = IC2IFP(&sc->sc_ic); 8243 struct ifnet *ifp = IC2IFP(&sc->sc_ic);
8242 8244
8243 switch (act) { 8245 switch (act) {
8244 case DVACT_DEACTIVATE: 8246 case DVACT_DEACTIVATE:
8245 if (ifp->if_flags & IFF_RUNNING) 8247 if (ifp->if_flags & IFF_RUNNING)
8246 iwm_stop(ifp, 0); 8248 iwm_stop(ifp, 0);
8247 return 0; 8249 return 0;
8248 default: 8250 default:
8249 return EOPNOTSUPP; 8251 return EOPNOTSUPP;
8250 } 8252 }
8251} 8253}
8252#endif 8254#endif
8253 8255
8254CFATTACH_DECL_NEW(iwm, sizeof(struct iwm_softc), iwm_match, iwm_attach, 8256CFATTACH_DECL_NEW(iwm, sizeof(struct iwm_softc), iwm_match, iwm_attach,
8255 NULL, NULL); 8257 NULL, NULL);
8256 8258
8257static int 8259static int
8258iwm_sysctl_fw_loaded_handler(SYSCTLFN_ARGS) 8260iwm_sysctl_fw_loaded_handler(SYSCTLFN_ARGS)
8259{ 8261{
8260 struct sysctlnode node; 8262 struct sysctlnode node;
8261 struct iwm_softc *sc; 8263 struct iwm_softc *sc;
8262 int err, t; 8264 int err, t;
8263 8265
8264 node = *rnode; 8266 node = *rnode;
8265 sc = node.sysctl_data; 8267 sc = node.sysctl_data;
8266 t = ISSET(sc->sc_flags, IWM_FLAG_FW_LOADED) ? 1 : 0; 8268 t = ISSET(sc->sc_flags, IWM_FLAG_FW_LOADED) ? 1 : 0;
8267 node.sysctl_data = &t; 8269 node.sysctl_data = &t;
8268 err = sysctl_lookup(SYSCTLFN_CALL(&node)); 8270 err = sysctl_lookup(SYSCTLFN_CALL(&node));
8269 if (err || newp == NULL) 8271 if (err || newp == NULL)
8270 return err; 8272 return err;
8271 8273
8272 if (t == 0) 8274 if (t == 0)
8273 CLR(sc->sc_flags, IWM_FLAG_FW_LOADED); 8275 CLR(sc->sc_flags, IWM_FLAG_FW_LOADED);
8274 return 0; 8276 return 0;
8275} 8277}
8276 8278
8277SYSCTL_SETUP(sysctl_iwm, "sysctl iwm(4) subtree setup") 8279SYSCTL_SETUP(sysctl_iwm, "sysctl iwm(4) subtree setup")
8278{ 8280{
8279 const struct sysctlnode *rnode; 8281 const struct sysctlnode *rnode;
8280#ifdef IWM_DEBUG 8282#ifdef IWM_DEBUG
8281 const struct sysctlnode *cnode; 8283 const struct sysctlnode *cnode;
8282#endif /* IWM_DEBUG */ 8284#endif /* IWM_DEBUG */
8283 int rc; 8285 int rc;
8284 8286
8285 if ((rc = sysctl_createv(clog, 0, NULL, &rnode, 8287 if ((rc = sysctl_createv(clog, 0, NULL, &rnode,
8286 CTLFLAG_PERMANENT, CTLTYPE_NODE, "iwm", 8288 CTLFLAG_PERMANENT, CTLTYPE_NODE, "iwm",
8287 SYSCTL_DESCR("iwm global controls"), 8289 SYSCTL_DESCR("iwm global controls"),
8288 NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) 8290 NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0)
8289 goto err; 8291 goto err;
8290 8292
8291 iwm_sysctl_root_num = rnode->sysctl_num; 8293 iwm_sysctl_root_num = rnode->sysctl_num;
8292 8294
8293#ifdef IWM_DEBUG 8295#ifdef IWM_DEBUG
8294 /* control debugging printfs */ 8296 /* control debugging printfs */
8295 if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, 8297 if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
8296 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, 8298 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
8297 "debug", SYSCTL_DESCR("Enable debugging output"), 8299 "debug", SYSCTL_DESCR("Enable debugging output"),
8298 NULL, 0, &iwm_debug, 0, CTL_CREATE, CTL_EOL)) != 0) 8300 NULL, 0, &iwm_debug, 0, CTL_CREATE, CTL_EOL)) != 0)
8299 goto err; 8301 goto err;
8300#endif /* IWM_DEBUG */ 8302#endif /* IWM_DEBUG */
8301 8303
8302 return; 8304 return;
8303 8305
8304 err: 8306 err:
8305 aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); 8307 aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
8306} 8308}