Tue Mar 3 09:10:45 2015 UTC ()
workaround for interrupt coalescing bug not needed on 7265.
From OpenBSD if_iwm.c rev.1.25, if_iwmvar.h rev.1.7.


(nonaka)
diff -r1.16 -r1.17 src/sys/dev/pci/if_iwm.c
diff -r1.4 -r1.5 src/sys/dev/pci/if_iwmvar.h

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

--- src/sys/dev/pci/if_iwm.c 2015/03/02 12:07:27 1.16
+++ src/sys/dev/pci/if_iwm.c 2015/03/03 09:10:45 1.17
@@ -1,2734 +1,2739 @@ @@ -1,2734 +1,2739 @@
1/* $NetBSD: if_iwm.c,v 1.16 2015/03/02 12:07:27 nonaka Exp $ */ 1/* $NetBSD: if_iwm.c,v 1.17 2015/03/03 09:10:45 nonaka Exp $ */
2/* OpenBSD: if_iwm.c,v 1.18 2015/02/11 01:12:42 brad Exp */ 2/* OpenBSD: if_iwm.c,v 1.18 2015/02/11 01:12:42 brad Exp */
3 3
4/* 4/*
5 * Copyright (c) 2014 genua mbh <info@genua.de> 5 * Copyright (c) 2014 genua mbh <info@genua.de>
6 * Copyright (c) 2014 Fixup Software Ltd. 6 * Copyright (c) 2014 Fixup Software Ltd.
7 * 7 *
8 * Permission to use, copy, modify, and distribute this software for any 8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above 9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies. 10 * copyright notice and this permission notice appear in all copies.
11 * 11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */ 19 */
20 20
21/*- 21/*-
22 * Based on BSD-licensed source modules in the Linux iwlwifi driver, 22 * Based on BSD-licensed source modules in the Linux iwlwifi driver,
23 * which were used as the reference documentation for this implementation. 23 * which were used as the reference documentation for this implementation.
24 * 24 *
25 * Driver version we are currently based off of is 25 * Driver version we are currently based off of is
26 * Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd) 26 * Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
27 * 27 *
28 *********************************************************************** 28 ***********************************************************************
29 * 29 *
30 * This file is provided under a dual BSD/GPLv2 license. When using or 30 * This file is provided under a dual BSD/GPLv2 license. When using or
31 * redistributing this file, you may do so under either license. 31 * redistributing this file, you may do so under either license.
32 * 32 *
33 * GPL LICENSE SUMMARY 33 * GPL LICENSE SUMMARY
34 * 34 *
35 * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. 35 * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
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 <ilw@linux.intel.com> 55 * Intel Linux Wireless <ilw@linux.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 * 58 *
59 * BSD LICENSE 59 * BSD LICENSE
60 * 60 *
61 * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. 61 * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
62 * All rights reserved. 62 * All rights reserved.
63 * 63 *
64 * Redistribution and use in source and binary forms, with or without 64 * Redistribution and use in source and binary forms, with or without
65 * modification, are permitted provided that the following conditions 65 * modification, are permitted provided that the following conditions
66 * are met: 66 * are met:
67 * 67 *
68 * * Redistributions of source code must retain the above copyright 68 * * Redistributions of source code must retain the above copyright
69 * notice, this list of conditions and the following disclaimer. 69 * notice, this list of conditions and the following disclaimer.
70 * * Redistributions in binary form must reproduce the above copyright 70 * * Redistributions in binary form must reproduce the above copyright
71 * notice, this list of conditions and the following disclaimer in 71 * notice, this list of conditions and the following disclaimer in
72 * the documentation and/or other materials provided with the 72 * the documentation and/or other materials provided with the
73 * distribution. 73 * distribution.
74 * * Neither the name Intel Corporation nor the names of its 74 * * Neither the name Intel Corporation nor the names of its
75 * contributors may be used to endorse or promote products derived 75 * contributors may be used to endorse or promote products derived
76 * from this software without specific prior written permission. 76 * from this software without specific prior written permission.
77 * 77 *
78 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 78 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
79 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 79 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
80 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 80 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
81 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 81 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
82 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 82 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
83 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 83 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
84 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 84 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
85 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 85 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
86 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 86 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
87 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 87 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
88 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 88 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
89 */ 89 */
90 90
91/*- 91/*-
92 * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr> 92 * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
93 * 93 *
94 * Permission to use, copy, modify, and distribute this software for any 94 * Permission to use, copy, modify, and distribute this software for any
95 * purpose with or without fee is hereby granted, provided that the above 95 * purpose with or without fee is hereby granted, provided that the above
96 * copyright notice and this permission notice appear in all copies. 96 * copyright notice and this permission notice appear in all copies.
97 * 97 *
98 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 98 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
99 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 99 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
100 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 100 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
101 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 101 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
102 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 102 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
103 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 103 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
104 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 104 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
105 */ 105 */
106 106
107#include <sys/cdefs.h> 107#include <sys/cdefs.h>
108__KERNEL_RCSID(0, "$NetBSD: if_iwm.c,v 1.16 2015/03/02 12:07:27 nonaka Exp $"); 108__KERNEL_RCSID(0, "$NetBSD: if_iwm.c,v 1.17 2015/03/03 09:10:45 nonaka Exp $");
109 109
110#include <sys/param.h> 110#include <sys/param.h>
111#include <sys/conf.h> 111#include <sys/conf.h>
112#include <sys/kernel.h> 112#include <sys/kernel.h>
113#include <sys/kmem.h> 113#include <sys/kmem.h>
114#include <sys/mbuf.h> 114#include <sys/mbuf.h>
115#include <sys/mutex.h> 115#include <sys/mutex.h>
116#include <sys/proc.h> 116#include <sys/proc.h>
117#include <sys/socket.h> 117#include <sys/socket.h>
118#include <sys/sockio.h> 118#include <sys/sockio.h>
119#include <sys/systm.h> 119#include <sys/systm.h>
120 120
121#include <sys/cpu.h> 121#include <sys/cpu.h>
122#include <sys/bus.h> 122#include <sys/bus.h>
123#include <sys/workqueue.h> 123#include <sys/workqueue.h>
124#include <machine/endian.h> 124#include <machine/endian.h>
125#include <machine/intr.h> 125#include <machine/intr.h>
126 126
127#include <dev/pci/pcireg.h> 127#include <dev/pci/pcireg.h>
128#include <dev/pci/pcivar.h> 128#include <dev/pci/pcivar.h>
129#include <dev/pci/pcidevs.h> 129#include <dev/pci/pcidevs.h>
130#include <dev/firmload.h> 130#include <dev/firmload.h>
131 131
132#include <net/bpf.h> 132#include <net/bpf.h>
133#include <net/if.h> 133#include <net/if.h>
134#include <net/if_arp.h> 134#include <net/if_arp.h>
135#include <net/if_dl.h> 135#include <net/if_dl.h>
136#include <net/if_media.h> 136#include <net/if_media.h>
137#include <net/if_types.h> 137#include <net/if_types.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/in_systm.h> 141#include <netinet/in_systm.h>
142#include <netinet/ip.h> 142#include <netinet/ip.h>
143 143
144#include <net80211/ieee80211_var.h> 144#include <net80211/ieee80211_var.h>
145#include <net80211/ieee80211_amrr.h> 145#include <net80211/ieee80211_amrr.h>
146#include <net80211/ieee80211_radiotap.h> 146#include <net80211/ieee80211_radiotap.h>
147 147
148#define DEVNAME(_s) device_xname((_s)->sc_dev) 148#define DEVNAME(_s) device_xname((_s)->sc_dev)
149#define IC2IFP(_ic_) ((_ic_)->ic_ifp) 149#define IC2IFP(_ic_) ((_ic_)->ic_ifp)
150 150
151#define le16_to_cpup(_a_) (le16toh(*(const uint16_t *)(_a_))) 151#define le16_to_cpup(_a_) (le16toh(*(const uint16_t *)(_a_)))
152#define le32_to_cpup(_a_) (le32toh(*(const uint32_t *)(_a_))) 152#define le32_to_cpup(_a_) (le32toh(*(const uint32_t *)(_a_)))
153 153
154#ifdef IWM_DEBUG 154#ifdef IWM_DEBUG
155#define DPRINTF(x) do { if (iwm_debug > 0) printf x; } while (0) 155#define DPRINTF(x) do { if (iwm_debug > 0) printf x; } while (0)
156#define DPRINTFN(n, x) do { if (iwm_debug >= (n)) printf x; } while (0) 156#define DPRINTFN(n, x) do { if (iwm_debug >= (n)) printf x; } while (0)
157int iwm_debug = 1; 157int iwm_debug = 1;
158#else 158#else
159#define DPRINTF(x) do { ; } while (0) 159#define DPRINTF(x) do { ; } while (0)
160#define DPRINTFN(n, x) do { ; } while (0) 160#define DPRINTFN(n, x) do { ; } while (0)
161#endif 161#endif
162 162
163#include <dev/pci/if_iwmreg.h> 163#include <dev/pci/if_iwmreg.h>
164#include <dev/pci/if_iwmvar.h> 164#include <dev/pci/if_iwmvar.h>
165 165
166static const uint8_t iwm_nvm_channels[] = { 166static const uint8_t iwm_nvm_channels[] = {
167 /* 2.4 GHz */ 167 /* 2.4 GHz */
168 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 168 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
169 /* 5 GHz */ 169 /* 5 GHz */
170 36, 40, 44 , 48, 52, 56, 60, 64, 170 36, 40, 44 , 48, 52, 56, 60, 64,
171 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 171 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
172 149, 153, 157, 161, 165 172 149, 153, 157, 161, 165
173}; 173};
174#define IWM_NUM_2GHZ_CHANNELS 14 174#define IWM_NUM_2GHZ_CHANNELS 14
175 175
176/* It looks like 11a TX is broken, unfortunately. */ 176/* It looks like 11a TX is broken, unfortunately. */
177#define IWM_NO_5GHZ 1 177#define IWM_NO_5GHZ 1
178 178
179static const struct iwm_rate { 179static const struct iwm_rate {
180 uint8_t rate; 180 uint8_t rate;
181 uint8_t plcp; 181 uint8_t plcp;
182} iwm_rates[] = { 182} iwm_rates[] = {
183 { 2, IWM_RATE_1M_PLCP }, 183 { 2, IWM_RATE_1M_PLCP },
184 { 4, IWM_RATE_2M_PLCP }, 184 { 4, IWM_RATE_2M_PLCP },
185 { 11, IWM_RATE_5M_PLCP }, 185 { 11, IWM_RATE_5M_PLCP },
186 { 22, IWM_RATE_11M_PLCP }, 186 { 22, IWM_RATE_11M_PLCP },
187 { 12, IWM_RATE_6M_PLCP }, 187 { 12, IWM_RATE_6M_PLCP },
188 { 18, IWM_RATE_9M_PLCP }, 188 { 18, IWM_RATE_9M_PLCP },
189 { 24, IWM_RATE_12M_PLCP }, 189 { 24, IWM_RATE_12M_PLCP },
190 { 36, IWM_RATE_18M_PLCP }, 190 { 36, IWM_RATE_18M_PLCP },
191 { 48, IWM_RATE_24M_PLCP }, 191 { 48, IWM_RATE_24M_PLCP },
192 { 72, IWM_RATE_36M_PLCP }, 192 { 72, IWM_RATE_36M_PLCP },
193 { 96, IWM_RATE_48M_PLCP }, 193 { 96, IWM_RATE_48M_PLCP },
194 { 108, IWM_RATE_54M_PLCP }, 194 { 108, IWM_RATE_54M_PLCP },
195}; 195};
196#define IWM_RIDX_CCK 0 196#define IWM_RIDX_CCK 0
197#define IWM_RIDX_OFDM 4 197#define IWM_RIDX_OFDM 4
198#define IWM_RIDX_MAX (__arraycount(iwm_rates)-1) 198#define IWM_RIDX_MAX (__arraycount(iwm_rates)-1)
199#define IWM_RIDX_IS_CCK(_i_) ((_i_) < IWM_RIDX_OFDM) 199#define IWM_RIDX_IS_CCK(_i_) ((_i_) < IWM_RIDX_OFDM)
200#define IWM_RIDX_IS_OFDM(_i_) ((_i_) >= IWM_RIDX_OFDM) 200#define IWM_RIDX_IS_OFDM(_i_) ((_i_) >= IWM_RIDX_OFDM)
201 201
202struct iwm_newstate_state { 202struct iwm_newstate_state {
203 struct work ns_wk; 203 struct work ns_wk;
204 enum ieee80211_state ns_nstate; 204 enum ieee80211_state ns_nstate;
205 int ns_arg; 205 int ns_arg;
206 int ns_generation; 206 int ns_generation;
207}; 207};
208 208
209static int iwm_store_cscheme(struct iwm_softc *, uint8_t *, size_t); 209static int iwm_store_cscheme(struct iwm_softc *, uint8_t *, size_t);
210static int iwm_firmware_store_section(struct iwm_softc *, 210static int iwm_firmware_store_section(struct iwm_softc *,
211 enum iwm_ucode_type, uint8_t *, size_t); 211 enum iwm_ucode_type, uint8_t *, size_t);
212static int iwm_set_default_calib(struct iwm_softc *, const void *); 212static int iwm_set_default_calib(struct iwm_softc *, const void *);
213static int iwm_read_firmware(struct iwm_softc *); 213static int iwm_read_firmware(struct iwm_softc *);
214static uint32_t iwm_read_prph(struct iwm_softc *, uint32_t); 214static uint32_t iwm_read_prph(struct iwm_softc *, uint32_t);
215static void iwm_write_prph(struct iwm_softc *, uint32_t, uint32_t); 215static void iwm_write_prph(struct iwm_softc *, uint32_t, uint32_t);
216#ifdef IWM_DEBUG 216#ifdef IWM_DEBUG
217static int iwm_read_mem(struct iwm_softc *, uint32_t, void *, int); 217static int iwm_read_mem(struct iwm_softc *, uint32_t, void *, int);
218#endif 218#endif
219static int iwm_write_mem(struct iwm_softc *, uint32_t, const void *, int); 219static int iwm_write_mem(struct iwm_softc *, uint32_t, const void *, int);
220static int iwm_write_mem32(struct iwm_softc *, uint32_t, uint32_t); 220static int iwm_write_mem32(struct iwm_softc *, uint32_t, uint32_t);
221static int iwm_poll_bit(struct iwm_softc *, int, uint32_t, uint32_t, int); 221static int iwm_poll_bit(struct iwm_softc *, int, uint32_t, uint32_t, int);
222static int iwm_nic_lock(struct iwm_softc *); 222static int iwm_nic_lock(struct iwm_softc *);
223static void iwm_nic_unlock(struct iwm_softc *); 223static void iwm_nic_unlock(struct iwm_softc *);
224static void iwm_set_bits_mask_prph(struct iwm_softc *, uint32_t, uint32_t, 224static void iwm_set_bits_mask_prph(struct iwm_softc *, uint32_t, uint32_t,
225 uint32_t); 225 uint32_t);
226static void iwm_set_bits_prph(struct iwm_softc *, uint32_t, uint32_t); 226static void iwm_set_bits_prph(struct iwm_softc *, uint32_t, uint32_t);
227static void iwm_clear_bits_prph(struct iwm_softc *, uint32_t, uint32_t); 227static void iwm_clear_bits_prph(struct iwm_softc *, uint32_t, uint32_t);
228static int iwm_dma_contig_alloc(bus_dma_tag_t, struct iwm_dma_info *, 228static int iwm_dma_contig_alloc(bus_dma_tag_t, struct iwm_dma_info *,
229 bus_size_t, bus_size_t); 229 bus_size_t, bus_size_t);
230static void iwm_dma_contig_free(struct iwm_dma_info *); 230static void iwm_dma_contig_free(struct iwm_dma_info *);
231static int iwm_alloc_fwmem(struct iwm_softc *); 231static int iwm_alloc_fwmem(struct iwm_softc *);
232static void iwm_free_fwmem(struct iwm_softc *); 232static void iwm_free_fwmem(struct iwm_softc *);
233static int iwm_alloc_sched(struct iwm_softc *); 233static int iwm_alloc_sched(struct iwm_softc *);
234static void iwm_free_sched(struct iwm_softc *); 234static void iwm_free_sched(struct iwm_softc *);
235static int iwm_alloc_kw(struct iwm_softc *); 235static int iwm_alloc_kw(struct iwm_softc *);
236static void iwm_free_kw(struct iwm_softc *); 236static void iwm_free_kw(struct iwm_softc *);
237static int iwm_alloc_ict(struct iwm_softc *); 237static int iwm_alloc_ict(struct iwm_softc *);
238static void iwm_free_ict(struct iwm_softc *); 238static void iwm_free_ict(struct iwm_softc *);
239static int iwm_alloc_rx_ring(struct iwm_softc *, struct iwm_rx_ring *); 239static int iwm_alloc_rx_ring(struct iwm_softc *, struct iwm_rx_ring *);
240static void iwm_reset_rx_ring(struct iwm_softc *, struct iwm_rx_ring *); 240static void iwm_reset_rx_ring(struct iwm_softc *, struct iwm_rx_ring *);
241static void iwm_free_rx_ring(struct iwm_softc *, struct iwm_rx_ring *); 241static void iwm_free_rx_ring(struct iwm_softc *, struct iwm_rx_ring *);
242static int iwm_alloc_tx_ring(struct iwm_softc *, struct iwm_tx_ring *, 242static int iwm_alloc_tx_ring(struct iwm_softc *, struct iwm_tx_ring *,
243 int); 243 int);
244static void iwm_reset_tx_ring(struct iwm_softc *, struct iwm_tx_ring *); 244static void iwm_reset_tx_ring(struct iwm_softc *, struct iwm_tx_ring *);
245static void iwm_free_tx_ring(struct iwm_softc *, struct iwm_tx_ring *); 245static void iwm_free_tx_ring(struct iwm_softc *, struct iwm_tx_ring *);
246static void iwm_enable_rfkill_int(struct iwm_softc *); 246static void iwm_enable_rfkill_int(struct iwm_softc *);
247static int iwm_check_rfkill(struct iwm_softc *); 247static int iwm_check_rfkill(struct iwm_softc *);
248static void iwm_enable_interrupts(struct iwm_softc *); 248static void iwm_enable_interrupts(struct iwm_softc *);
249static void iwm_restore_interrupts(struct iwm_softc *); 249static void iwm_restore_interrupts(struct iwm_softc *);
250static void iwm_disable_interrupts(struct iwm_softc *); 250static void iwm_disable_interrupts(struct iwm_softc *);
251static void iwm_ict_reset(struct iwm_softc *); 251static void iwm_ict_reset(struct iwm_softc *);
252static int iwm_set_hw_ready(struct iwm_softc *); 252static int iwm_set_hw_ready(struct iwm_softc *);
253static int iwm_prepare_card_hw(struct iwm_softc *); 253static int iwm_prepare_card_hw(struct iwm_softc *);
254static void iwm_apm_config(struct iwm_softc *); 254static void iwm_apm_config(struct iwm_softc *);
255static int iwm_apm_init(struct iwm_softc *); 255static int iwm_apm_init(struct iwm_softc *);
256static void iwm_apm_stop(struct iwm_softc *); 256static void iwm_apm_stop(struct iwm_softc *);
257static int iwm_allow_mcast(struct iwm_softc *); 257static int iwm_allow_mcast(struct iwm_softc *);
258static int iwm_start_hw(struct iwm_softc *); 258static int iwm_start_hw(struct iwm_softc *);
259static void iwm_stop_device(struct iwm_softc *); 259static void iwm_stop_device(struct iwm_softc *);
260static void iwm_set_pwr(struct iwm_softc *); 260static void iwm_set_pwr(struct iwm_softc *);
261static void iwm_mvm_nic_config(struct iwm_softc *); 261static void iwm_mvm_nic_config(struct iwm_softc *);
262static int iwm_nic_rx_init(struct iwm_softc *); 262static int iwm_nic_rx_init(struct iwm_softc *);
263static int iwm_nic_tx_init(struct iwm_softc *); 263static int iwm_nic_tx_init(struct iwm_softc *);
264static int iwm_nic_init(struct iwm_softc *); 264static int iwm_nic_init(struct iwm_softc *);
265static void iwm_enable_txq(struct iwm_softc *, int, int); 265static void iwm_enable_txq(struct iwm_softc *, int, int);
266static int iwm_post_alive(struct iwm_softc *); 266static int iwm_post_alive(struct iwm_softc *);
267static int iwm_is_valid_channel(uint16_t); 267static int iwm_is_valid_channel(uint16_t);
268static uint8_t iwm_ch_id_to_ch_index(uint16_t); 268static uint8_t iwm_ch_id_to_ch_index(uint16_t);
269static uint16_t iwm_channel_id_to_papd(uint16_t); 269static uint16_t iwm_channel_id_to_papd(uint16_t);
270static uint16_t iwm_channel_id_to_txp(struct iwm_softc *, uint16_t); 270static uint16_t iwm_channel_id_to_txp(struct iwm_softc *, uint16_t);
271static int iwm_phy_db_get_section_data(struct iwm_softc *, uint32_t, 271static int iwm_phy_db_get_section_data(struct iwm_softc *, uint32_t,
272 uint8_t **, uint16_t *, uint16_t); 272 uint8_t **, uint16_t *, uint16_t);
273static int iwm_send_phy_db_cmd(struct iwm_softc *, uint16_t, uint16_t, 273static int iwm_send_phy_db_cmd(struct iwm_softc *, uint16_t, uint16_t,
274 void *); 274 void *);
275static int iwm_send_phy_db_data(struct iwm_softc *); 275static int iwm_send_phy_db_data(struct iwm_softc *);
276static int iwm_send_phy_db_data(struct iwm_softc *); 276static int iwm_send_phy_db_data(struct iwm_softc *);
277static void iwm_mvm_te_v2_to_v1(const struct iwm_time_event_cmd_v2 *, 277static void iwm_mvm_te_v2_to_v1(const struct iwm_time_event_cmd_v2 *,
278 struct iwm_time_event_cmd_v1 *); 278 struct iwm_time_event_cmd_v1 *);
279static int iwm_mvm_send_time_event_cmd(struct iwm_softc *, 279static int iwm_mvm_send_time_event_cmd(struct iwm_softc *,
280 const struct iwm_time_event_cmd_v2 *); 280 const struct iwm_time_event_cmd_v2 *);
281static int iwm_mvm_time_event_send_add(struct iwm_softc *, 281static int iwm_mvm_time_event_send_add(struct iwm_softc *,
282 struct iwm_node *, void *, struct iwm_time_event_cmd_v2 *); 282 struct iwm_node *, void *, struct iwm_time_event_cmd_v2 *);
283static void iwm_mvm_protect_session(struct iwm_softc *, struct iwm_node *, 283static void iwm_mvm_protect_session(struct iwm_softc *, struct iwm_node *,
284 uint32_t, uint32_t, uint32_t); 284 uint32_t, uint32_t, uint32_t);
285static int iwm_nvm_read_chunk(struct iwm_softc *, uint16_t, uint16_t, 285static int iwm_nvm_read_chunk(struct iwm_softc *, uint16_t, uint16_t,
286 uint16_t, uint8_t *, uint16_t *); 286 uint16_t, uint8_t *, uint16_t *);
287static int iwm_nvm_read_section(struct iwm_softc *, uint16_t, uint8_t *, 287static int iwm_nvm_read_section(struct iwm_softc *, uint16_t, uint8_t *,
288 uint16_t *); 288 uint16_t *);
289static void iwm_init_channel_map(struct iwm_softc *, 289static void iwm_init_channel_map(struct iwm_softc *,
290 const uint16_t * const); 290 const uint16_t * const);
291static int iwm_parse_nvm_data(struct iwm_softc *, const uint16_t *, 291static int iwm_parse_nvm_data(struct iwm_softc *, const uint16_t *,
292 const uint16_t *, const uint16_t *, uint8_t, uint8_t); 292 const uint16_t *, const uint16_t *, uint8_t, uint8_t);
293static int iwm_nvm_init(struct iwm_softc *); 293static int iwm_nvm_init(struct iwm_softc *);
294static int iwm_firmware_load_chunk(struct iwm_softc *, uint32_t, 294static int iwm_firmware_load_chunk(struct iwm_softc *, uint32_t,
295 const uint8_t *, uint32_t); 295 const uint8_t *, uint32_t);
296static int iwm_load_firmware(struct iwm_softc *, enum iwm_ucode_type); 296static int iwm_load_firmware(struct iwm_softc *, enum iwm_ucode_type);
297static int iwm_start_fw(struct iwm_softc *, enum iwm_ucode_type); 297static int iwm_start_fw(struct iwm_softc *, enum iwm_ucode_type);
298static int iwm_fw_alive(struct iwm_softc *, uint32_t); 298static int iwm_fw_alive(struct iwm_softc *, uint32_t);
299static int iwm_send_tx_ant_cfg(struct iwm_softc *, uint8_t); 299static int iwm_send_tx_ant_cfg(struct iwm_softc *, uint8_t);
300static int iwm_send_phy_cfg_cmd(struct iwm_softc *); 300static int iwm_send_phy_cfg_cmd(struct iwm_softc *);
301static int iwm_mvm_load_ucode_wait_alive(struct iwm_softc *, 301static int iwm_mvm_load_ucode_wait_alive(struct iwm_softc *,
302 enum iwm_ucode_type); 302 enum iwm_ucode_type);
303static int iwm_run_init_mvm_ucode(struct iwm_softc *, int); 303static int iwm_run_init_mvm_ucode(struct iwm_softc *, int);
304static int iwm_rx_addbuf(struct iwm_softc *, int, int); 304static int iwm_rx_addbuf(struct iwm_softc *, int, int);
305static int iwm_mvm_calc_rssi(struct iwm_softc *, struct iwm_rx_phy_info *); 305static int iwm_mvm_calc_rssi(struct iwm_softc *, struct iwm_rx_phy_info *);
306static int iwm_mvm_get_signal_strength(struct iwm_softc *, 306static int iwm_mvm_get_signal_strength(struct iwm_softc *,
307 struct iwm_rx_phy_info *); 307 struct iwm_rx_phy_info *);
308static void iwm_mvm_rx_rx_phy_cmd(struct iwm_softc *, 308static void iwm_mvm_rx_rx_phy_cmd(struct iwm_softc *,
309 struct iwm_rx_packet *, struct iwm_rx_data *); 309 struct iwm_rx_packet *, struct iwm_rx_data *);
310static int iwm_get_noise(const struct iwm_mvm_statistics_rx_non_phy *); 310static int iwm_get_noise(const struct iwm_mvm_statistics_rx_non_phy *);
311static void iwm_mvm_rx_rx_mpdu(struct iwm_softc *, struct iwm_rx_packet *, 311static void iwm_mvm_rx_rx_mpdu(struct iwm_softc *, struct iwm_rx_packet *,
312 struct iwm_rx_data *); 312 struct iwm_rx_data *);
313static void iwm_mvm_rx_tx_cmd_single(struct iwm_softc *, 313static void iwm_mvm_rx_tx_cmd_single(struct iwm_softc *,
314 struct iwm_rx_packet *, struct iwm_node *); 314 struct iwm_rx_packet *, struct iwm_node *);
315static void iwm_mvm_rx_tx_cmd(struct iwm_softc *, struct iwm_rx_packet *, 315static void iwm_mvm_rx_tx_cmd(struct iwm_softc *, struct iwm_rx_packet *,
316 struct iwm_rx_data *); 316 struct iwm_rx_data *);
317static int iwm_mvm_binding_cmd(struct iwm_softc *, struct iwm_node *, 317static int iwm_mvm_binding_cmd(struct iwm_softc *, struct iwm_node *,
318 uint32_t); 318 uint32_t);
319static int iwm_mvm_binding_update(struct iwm_softc *, struct iwm_node *, 319static int iwm_mvm_binding_update(struct iwm_softc *, struct iwm_node *,
320 int); 320 int);
321static int iwm_mvm_binding_add_vif(struct iwm_softc *, struct iwm_node *); 321static int iwm_mvm_binding_add_vif(struct iwm_softc *, struct iwm_node *);
322static void iwm_mvm_phy_ctxt_cmd_hdr(struct iwm_softc *, 322static void iwm_mvm_phy_ctxt_cmd_hdr(struct iwm_softc *,
323 struct iwm_mvm_phy_ctxt *, struct iwm_phy_context_cmd *, 323 struct iwm_mvm_phy_ctxt *, struct iwm_phy_context_cmd *,
324 uint32_t, uint32_t); 324 uint32_t, uint32_t);
325static void iwm_mvm_phy_ctxt_cmd_data(struct iwm_softc *, 325static void iwm_mvm_phy_ctxt_cmd_data(struct iwm_softc *,
326 struct iwm_phy_context_cmd *, struct ieee80211_channel *, 326 struct iwm_phy_context_cmd *, struct ieee80211_channel *,
327 uint8_t, uint8_t); 327 uint8_t, uint8_t);
328static int iwm_mvm_phy_ctxt_apply(struct iwm_softc *, 328static int iwm_mvm_phy_ctxt_apply(struct iwm_softc *,
329 struct iwm_mvm_phy_ctxt *, uint8_t, uint8_t, uint32_t, 329 struct iwm_mvm_phy_ctxt *, uint8_t, uint8_t, uint32_t,
330 uint32_t); 330 uint32_t);
331static int iwm_mvm_phy_ctxt_add(struct iwm_softc *, 331static int iwm_mvm_phy_ctxt_add(struct iwm_softc *,
332 struct iwm_mvm_phy_ctxt *, struct ieee80211_channel *, 332 struct iwm_mvm_phy_ctxt *, struct ieee80211_channel *,
333 uint8_t, uint8_t); 333 uint8_t, uint8_t);
334static int iwm_mvm_phy_ctxt_changed(struct iwm_softc *, 334static int iwm_mvm_phy_ctxt_changed(struct iwm_softc *,
335 struct iwm_mvm_phy_ctxt *, struct ieee80211_channel *, 335 struct iwm_mvm_phy_ctxt *, struct ieee80211_channel *,
336 uint8_t, uint8_t); 336 uint8_t, uint8_t);
337static int iwm_send_cmd(struct iwm_softc *, struct iwm_host_cmd *); 337static int iwm_send_cmd(struct iwm_softc *, struct iwm_host_cmd *);
338static int iwm_mvm_send_cmd_pdu(struct iwm_softc *, uint8_t, uint32_t, 338static int iwm_mvm_send_cmd_pdu(struct iwm_softc *, uint8_t, uint32_t,
339 uint16_t, const void *); 339 uint16_t, const void *);
340static int iwm_mvm_send_cmd_status(struct iwm_softc *, 340static int iwm_mvm_send_cmd_status(struct iwm_softc *,
341 struct iwm_host_cmd *, uint32_t *); 341 struct iwm_host_cmd *, uint32_t *);
342static int iwm_mvm_send_cmd_pdu_status(struct iwm_softc *, uint8_t, 342static int iwm_mvm_send_cmd_pdu_status(struct iwm_softc *, uint8_t,
343 uint16_t, const void *, uint32_t *); 343 uint16_t, const void *, uint32_t *);
344static void iwm_free_resp(struct iwm_softc *, struct iwm_host_cmd *); 344static void iwm_free_resp(struct iwm_softc *, struct iwm_host_cmd *);
345static void iwm_cmd_done(struct iwm_softc *, struct iwm_rx_packet *); 345static void iwm_cmd_done(struct iwm_softc *, struct iwm_rx_packet *);
346#if 0 346#if 0
347static void iwm_update_sched(struct iwm_softc *, int, int, uint8_t, 347static void iwm_update_sched(struct iwm_softc *, int, int, uint8_t,
348 uint16_t); 348 uint16_t);
349#endif 349#endif
350static const struct iwm_rate *iwm_tx_fill_cmd(struct iwm_softc *, 350static const struct iwm_rate *iwm_tx_fill_cmd(struct iwm_softc *,
351 struct iwm_node *, struct ieee80211_frame *, 351 struct iwm_node *, struct ieee80211_frame *,
352 struct iwm_tx_cmd *); 352 struct iwm_tx_cmd *);
353static int iwm_tx(struct iwm_softc *, struct mbuf *, 353static int iwm_tx(struct iwm_softc *, struct mbuf *,
354 struct ieee80211_node *, int); 354 struct ieee80211_node *, int);
355static int iwm_mvm_beacon_filter_send_cmd(struct iwm_softc *, 355static int iwm_mvm_beacon_filter_send_cmd(struct iwm_softc *,
356 struct iwm_beacon_filter_cmd *); 356 struct iwm_beacon_filter_cmd *);
357static void iwm_mvm_beacon_filter_set_cqm_params(struct iwm_softc *, 357static void iwm_mvm_beacon_filter_set_cqm_params(struct iwm_softc *,
358 struct iwm_node *, struct iwm_beacon_filter_cmd *); 358 struct iwm_node *, struct iwm_beacon_filter_cmd *);
359static int iwm_mvm_update_beacon_abort(struct iwm_softc *, 359static int iwm_mvm_update_beacon_abort(struct iwm_softc *,
360 struct iwm_node *, int); 360 struct iwm_node *, int);
361static void iwm_mvm_power_log(struct iwm_softc *, 361static void iwm_mvm_power_log(struct iwm_softc *,
362 struct iwm_mac_power_cmd *); 362 struct iwm_mac_power_cmd *);
363static void iwm_mvm_power_build_cmd(struct iwm_softc *, struct iwm_node *, 363static void iwm_mvm_power_build_cmd(struct iwm_softc *, struct iwm_node *,
364 struct iwm_mac_power_cmd *); 364 struct iwm_mac_power_cmd *);
365static int iwm_mvm_power_mac_update_mode(struct iwm_softc *, 365static int iwm_mvm_power_mac_update_mode(struct iwm_softc *,
366 struct iwm_node *); 366 struct iwm_node *);
367static int iwm_mvm_power_update_device(struct iwm_softc *); 367static int iwm_mvm_power_update_device(struct iwm_softc *);
368static int iwm_mvm_enable_beacon_filter(struct iwm_softc *, 368static int iwm_mvm_enable_beacon_filter(struct iwm_softc *,
369 struct iwm_node *); 369 struct iwm_node *);
370static int iwm_mvm_disable_beacon_filter(struct iwm_softc *, 370static int iwm_mvm_disable_beacon_filter(struct iwm_softc *,
371 struct iwm_node *); 371 struct iwm_node *);
372static void iwm_mvm_add_sta_cmd_v6_to_v5(struct iwm_mvm_add_sta_cmd_v6 *, 372static void iwm_mvm_add_sta_cmd_v6_to_v5(struct iwm_mvm_add_sta_cmd_v6 *,
373 struct iwm_mvm_add_sta_cmd_v5 *); 373 struct iwm_mvm_add_sta_cmd_v5 *);
374static int iwm_mvm_send_add_sta_cmd_status(struct iwm_softc *, 374static int iwm_mvm_send_add_sta_cmd_status(struct iwm_softc *,
375 struct iwm_mvm_add_sta_cmd_v6 *, int *); 375 struct iwm_mvm_add_sta_cmd_v6 *, int *);
376static int iwm_mvm_sta_send_to_fw(struct iwm_softc *, struct iwm_node *, 376static int iwm_mvm_sta_send_to_fw(struct iwm_softc *, struct iwm_node *,
377 int); 377 int);
378static int iwm_mvm_add_sta(struct iwm_softc *, struct iwm_node *); 378static int iwm_mvm_add_sta(struct iwm_softc *, struct iwm_node *);
379static int iwm_mvm_update_sta(struct iwm_softc *, struct iwm_node *); 379static int iwm_mvm_update_sta(struct iwm_softc *, struct iwm_node *);
380static int iwm_mvm_add_int_sta_common(struct iwm_softc *, 380static int iwm_mvm_add_int_sta_common(struct iwm_softc *,
381 struct iwm_int_sta *, const uint8_t *, uint16_t, uint16_t); 381 struct iwm_int_sta *, const uint8_t *, uint16_t, uint16_t);
382static int iwm_mvm_add_aux_sta(struct iwm_softc *); 382static int iwm_mvm_add_aux_sta(struct iwm_softc *);
383static uint16_t iwm_mvm_scan_rx_chain(struct iwm_softc *); 383static uint16_t iwm_mvm_scan_rx_chain(struct iwm_softc *);
384static uint32_t iwm_mvm_scan_max_out_time(struct iwm_softc *, uint32_t, int); 384static uint32_t iwm_mvm_scan_max_out_time(struct iwm_softc *, uint32_t, int);
385static uint32_t iwm_mvm_scan_suspend_time(struct iwm_softc *, int); 385static uint32_t iwm_mvm_scan_suspend_time(struct iwm_softc *, int);
386static uint32_t iwm_mvm_scan_rxon_flags(struct iwm_softc *, int); 386static uint32_t iwm_mvm_scan_rxon_flags(struct iwm_softc *, int);
387static uint32_t iwm_mvm_scan_rate_n_flags(struct iwm_softc *, int, int); 387static uint32_t iwm_mvm_scan_rate_n_flags(struct iwm_softc *, int, int);
388static uint16_t iwm_mvm_get_active_dwell(struct iwm_softc *, int, int); 388static uint16_t iwm_mvm_get_active_dwell(struct iwm_softc *, int, int);
389static uint16_t iwm_mvm_get_passive_dwell(struct iwm_softc *, int); 389static uint16_t iwm_mvm_get_passive_dwell(struct iwm_softc *, int);
390static int iwm_mvm_scan_fill_channels(struct iwm_softc *, 390static int iwm_mvm_scan_fill_channels(struct iwm_softc *,
391 struct iwm_scan_cmd *, int, int, int); 391 struct iwm_scan_cmd *, int, int, int);
392static uint16_t iwm_mvm_fill_probe_req(struct iwm_softc *, 392static uint16_t iwm_mvm_fill_probe_req(struct iwm_softc *,
393 struct ieee80211_frame *, const uint8_t *, int, 393 struct ieee80211_frame *, const uint8_t *, int,
394 const uint8_t *, int, const uint8_t *, int, int); 394 const uint8_t *, int, const uint8_t *, int, int);
395static int iwm_mvm_scan_request(struct iwm_softc *, int, int, uint8_t *, 395static int iwm_mvm_scan_request(struct iwm_softc *, int, int, uint8_t *,
396 int); 396 int);
397static void iwm_mvm_ack_rates(struct iwm_softc *, struct iwm_node *, int *, 397static void iwm_mvm_ack_rates(struct iwm_softc *, struct iwm_node *, int *,
398 int *); 398 int *);
399static void iwm_mvm_mac_ctxt_cmd_common(struct iwm_softc *, 399static void iwm_mvm_mac_ctxt_cmd_common(struct iwm_softc *,
400 struct iwm_node *, struct iwm_mac_ctx_cmd *, uint32_t); 400 struct iwm_node *, struct iwm_mac_ctx_cmd *, uint32_t);
401static int iwm_mvm_mac_ctxt_send_cmd(struct iwm_softc *, 401static int iwm_mvm_mac_ctxt_send_cmd(struct iwm_softc *,
402 struct iwm_mac_ctx_cmd *); 402 struct iwm_mac_ctx_cmd *);
403static void iwm_mvm_mac_ctxt_cmd_fill_sta(struct iwm_softc *, 403static void iwm_mvm_mac_ctxt_cmd_fill_sta(struct iwm_softc *,
404 struct iwm_node *, struct iwm_mac_data_sta *, int); 404 struct iwm_node *, struct iwm_mac_data_sta *, int);
405static int iwm_mvm_mac_ctxt_cmd_station(struct iwm_softc *, 405static int iwm_mvm_mac_ctxt_cmd_station(struct iwm_softc *,
406 struct iwm_node *, uint32_t); 406 struct iwm_node *, uint32_t);
407static int iwm_mvm_mac_ctx_send(struct iwm_softc *, struct iwm_node *, 407static int iwm_mvm_mac_ctx_send(struct iwm_softc *, struct iwm_node *,
408 uint32_t); 408 uint32_t);
409static int iwm_mvm_mac_ctxt_add(struct iwm_softc *, struct iwm_node *); 409static int iwm_mvm_mac_ctxt_add(struct iwm_softc *, struct iwm_node *);
410static int iwm_mvm_mac_ctxt_changed(struct iwm_softc *, struct iwm_node *); 410static int iwm_mvm_mac_ctxt_changed(struct iwm_softc *, struct iwm_node *);
411static int iwm_mvm_update_quotas(struct iwm_softc *, struct iwm_node *); 411static int iwm_mvm_update_quotas(struct iwm_softc *, struct iwm_node *);
412static int iwm_auth(struct iwm_softc *); 412static int iwm_auth(struct iwm_softc *);
413static int iwm_assoc(struct iwm_softc *); 413static int iwm_assoc(struct iwm_softc *);
414static int iwm_release(struct iwm_softc *, struct iwm_node *); 414static int iwm_release(struct iwm_softc *, struct iwm_node *);
415static void iwm_calib_timeout(void *); 415static void iwm_calib_timeout(void *);
416static void iwm_setrates(struct iwm_node *); 416static void iwm_setrates(struct iwm_node *);
417static int iwm_media_change(struct ifnet *); 417static int iwm_media_change(struct ifnet *);
418static void iwm_newstate_cb(struct work *, void *); 418static void iwm_newstate_cb(struct work *, void *);
419static int iwm_newstate(struct ieee80211com *, enum ieee80211_state, int); 419static int iwm_newstate(struct ieee80211com *, enum ieee80211_state, int);
420static void iwm_endscan_cb(struct work *, void *); 420static void iwm_endscan_cb(struct work *, void *);
421static int iwm_init_hw(struct iwm_softc *); 421static int iwm_init_hw(struct iwm_softc *);
422static int iwm_init(struct ifnet *); 422static int iwm_init(struct ifnet *);
423static void iwm_start(struct ifnet *); 423static void iwm_start(struct ifnet *);
424static void iwm_stop(struct ifnet *, int); 424static void iwm_stop(struct ifnet *, int);
425static void iwm_watchdog(struct ifnet *); 425static void iwm_watchdog(struct ifnet *);
426static int iwm_ioctl(struct ifnet *, u_long, void *); 426static int iwm_ioctl(struct ifnet *, u_long, void *);
427#ifdef IWM_DEBUG 427#ifdef IWM_DEBUG
428static const char *iwm_desc_lookup(uint32_t); 428static const char *iwm_desc_lookup(uint32_t);
429static void iwm_nic_error(struct iwm_softc *); 429static void iwm_nic_error(struct iwm_softc *);
430#endif 430#endif
431static void iwm_notif_intr(struct iwm_softc *); 431static void iwm_notif_intr(struct iwm_softc *);
432static int iwm_intr(void *); 432static int iwm_intr(void *);
433static int iwm_preinit(struct iwm_softc *); 433static int iwm_preinit(struct iwm_softc *);
434static void iwm_attach_hook(device_t); 434static void iwm_attach_hook(device_t);
435static void iwm_attach(device_t, device_t, void *); 435static void iwm_attach(device_t, device_t, void *);
436#if 0 436#if 0
437static void iwm_init_task(void *); 437static void iwm_init_task(void *);
438static int iwm_activate(device_t, enum devact); 438static int iwm_activate(device_t, enum devact);
439static void iwm_wakeup(struct iwm_softc *); 439static void iwm_wakeup(struct iwm_softc *);
440#endif 440#endif
441static void iwm_radiotap_attach(struct iwm_softc *); 441static void iwm_radiotap_attach(struct iwm_softc *);
442 442
443static int 443static int
444iwm_firmload(struct iwm_softc *sc) 444iwm_firmload(struct iwm_softc *sc)
445{ 445{
446 struct iwm_fw_info *fw = &sc->sc_fw; 446 struct iwm_fw_info *fw = &sc->sc_fw;
447 firmware_handle_t fwh; 447 firmware_handle_t fwh;
448 int error; 448 int error;
449 449
450 /* Open firmware image. */ 450 /* Open firmware image. */
451 if ((error = firmware_open("if_iwm", sc->sc_fwname, &fwh)) != 0) { 451 if ((error = firmware_open("if_iwm", sc->sc_fwname, &fwh)) != 0) {
452 aprint_error_dev(sc->sc_dev, 452 aprint_error_dev(sc->sc_dev,
453 "could not get firmware handle %s\n", sc->sc_fwname); 453 "could not get firmware handle %s\n", sc->sc_fwname);
454 return error; 454 return error;
455 } 455 }
456 456
457 fw->fw_rawsize = firmware_get_size(fwh); 457 fw->fw_rawsize = firmware_get_size(fwh);
458 /* 458 /*
459 * Well, this is how the Linux driver checks it .... 459 * Well, this is how the Linux driver checks it ....
460 */ 460 */
461 if (fw->fw_rawsize < sizeof(uint32_t)) { 461 if (fw->fw_rawsize < sizeof(uint32_t)) {
462 aprint_error_dev(sc->sc_dev, 462 aprint_error_dev(sc->sc_dev,
463 "firmware too short: %zd bytes\n", fw->fw_rawsize); 463 "firmware too short: %zd bytes\n", fw->fw_rawsize);
464 error = EINVAL; 464 error = EINVAL;
465 goto out; 465 goto out;
466 } 466 }
467 467
468 /* some sanity */ 468 /* some sanity */
469 if (fw->fw_rawsize > IWM_FWMAXSIZE) { 469 if (fw->fw_rawsize > IWM_FWMAXSIZE) {
470 aprint_error_dev(sc->sc_dev, 470 aprint_error_dev(sc->sc_dev,
471 "firmware size is ridiculous: %zd bytes\n", 471 "firmware size is ridiculous: %zd bytes\n",
472 fw->fw_rawsize); 472 fw->fw_rawsize);
473 error = EINVAL; 473 error = EINVAL;
474 goto out; 474 goto out;
475 } 475 }
476 476
477 /* Read the firmware. */ 477 /* Read the firmware. */
478 fw->fw_rawdata = kmem_alloc(fw->fw_rawsize, KM_SLEEP); 478 fw->fw_rawdata = kmem_alloc(fw->fw_rawsize, KM_SLEEP);
479 if (fw->fw_rawdata == NULL) { 479 if (fw->fw_rawdata == NULL) {
480 aprint_error_dev(sc->sc_dev, 480 aprint_error_dev(sc->sc_dev,
481 "not enough memory to stock firmware %s\n", sc->sc_fwname); 481 "not enough memory to stock firmware %s\n", sc->sc_fwname);
482 error = ENOMEM; 482 error = ENOMEM;
483 goto out; 483 goto out;
484 } 484 }
485 error = firmware_read(fwh, 0, fw->fw_rawdata, fw->fw_rawsize); 485 error = firmware_read(fwh, 0, fw->fw_rawdata, fw->fw_rawsize);
486 if (error) { 486 if (error) {
487 aprint_error_dev(sc->sc_dev, 487 aprint_error_dev(sc->sc_dev,
488 "could not read firmware %s\n", sc->sc_fwname); 488 "could not read firmware %s\n", sc->sc_fwname);
489 goto out; 489 goto out;
490 } 490 }
491 491
492 out: 492 out:
493 /* caller will release memory, if necessary */ 493 /* caller will release memory, if necessary */
494 494
495 firmware_close(fwh); 495 firmware_close(fwh);
496 return error; 496 return error;
497} 497}
498 498
499/* 499/*
500 * just maintaining status quo. 500 * just maintaining status quo.
501 */ 501 */
502static void 502static void
503iwm_fix_channel(struct ieee80211com *ic, struct mbuf *m) 503iwm_fix_channel(struct ieee80211com *ic, struct mbuf *m)
504{ 504{
505 struct ieee80211_frame *wh; 505 struct ieee80211_frame *wh;
506 uint8_t subtype; 506 uint8_t subtype;
507 uint8_t *frm, *efrm; 507 uint8_t *frm, *efrm;
508 508
509 wh = mtod(m, struct ieee80211_frame *); 509 wh = mtod(m, struct ieee80211_frame *);
510 510
511 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT) 511 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT)
512 return; 512 return;
513 513
514 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 514 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
515 515
516 if (subtype != IEEE80211_FC0_SUBTYPE_BEACON && 516 if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
517 subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP) 517 subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
518 return; 518 return;
519 519
520 frm = (uint8_t *)(wh + 1); 520 frm = (uint8_t *)(wh + 1);
521 efrm = mtod(m, uint8_t *) + m->m_len; 521 efrm = mtod(m, uint8_t *) + m->m_len;
522 522
523 frm += 12; /* skip tstamp, bintval and capinfo fields */ 523 frm += 12; /* skip tstamp, bintval and capinfo fields */
524 while (frm < efrm) { 524 while (frm < efrm) {
525 if (*frm == IEEE80211_ELEMID_DSPARMS) { 525 if (*frm == IEEE80211_ELEMID_DSPARMS) {
526#if IEEE80211_CHAN_MAX < 255 526#if IEEE80211_CHAN_MAX < 255
527 if (frm[2] <= IEEE80211_CHAN_MAX) 527 if (frm[2] <= IEEE80211_CHAN_MAX)
528#endif 528#endif
529 ic->ic_curchan = &ic->ic_channels[frm[2]]; 529 ic->ic_curchan = &ic->ic_channels[frm[2]];
530 } 530 }
531 frm += frm[1] + 2; 531 frm += frm[1] + 2;
532 } 532 }
533} 533}
534 534
535/* 535/*
536 * Firmware parser. 536 * Firmware parser.
537 */ 537 */
538 538
539static int 539static int
540iwm_store_cscheme(struct iwm_softc *sc, uint8_t *data, size_t dlen) 540iwm_store_cscheme(struct iwm_softc *sc, uint8_t *data, size_t dlen)
541{ 541{
542 struct iwm_fw_cscheme_list *l = (void *)data; 542 struct iwm_fw_cscheme_list *l = (void *)data;
543 543
544 if (dlen < sizeof(*l) || 544 if (dlen < sizeof(*l) ||
545 dlen < sizeof(l->size) + l->size * sizeof(*l->cs)) 545 dlen < sizeof(l->size) + l->size * sizeof(*l->cs))
546 return EINVAL; 546 return EINVAL;
547 547
548 /* we don't actually store anything for now, always use s/w crypto */ 548 /* we don't actually store anything for now, always use s/w crypto */
549 549
550 return 0; 550 return 0;
551} 551}
552 552
553static int 553static int
554iwm_firmware_store_section(struct iwm_softc *sc, 554iwm_firmware_store_section(struct iwm_softc *sc,
555 enum iwm_ucode_type type, uint8_t *data, size_t dlen) 555 enum iwm_ucode_type type, uint8_t *data, size_t dlen)
556{ 556{
557 struct iwm_fw_sects *fws; 557 struct iwm_fw_sects *fws;
558 struct iwm_fw_onesect *fwone; 558 struct iwm_fw_onesect *fwone;
559 559
560 if (type >= IWM_UCODE_TYPE_MAX) 560 if (type >= IWM_UCODE_TYPE_MAX)
561 return EINVAL; 561 return EINVAL;
562 if (dlen < sizeof(uint32_t)) 562 if (dlen < sizeof(uint32_t))
563 return EINVAL; 563 return EINVAL;
564 564
565 fws = &sc->sc_fw.fw_sects[type]; 565 fws = &sc->sc_fw.fw_sects[type];
566 if (fws->fw_count >= IWM_UCODE_SECT_MAX) 566 if (fws->fw_count >= IWM_UCODE_SECT_MAX)
567 return EINVAL; 567 return EINVAL;
568 568
569 fwone = &fws->fw_sect[fws->fw_count]; 569 fwone = &fws->fw_sect[fws->fw_count];
570 570
571 /* first 32bit are device load offset */ 571 /* first 32bit are device load offset */
572 memcpy(&fwone->fws_devoff, data, sizeof(uint32_t)); 572 memcpy(&fwone->fws_devoff, data, sizeof(uint32_t));
573 573
574 /* rest is data */ 574 /* rest is data */
575 fwone->fws_data = data + sizeof(uint32_t); 575 fwone->fws_data = data + sizeof(uint32_t);
576 fwone->fws_len = dlen - sizeof(uint32_t); 576 fwone->fws_len = dlen - sizeof(uint32_t);
577 577
578 /* for freeing the buffer during driver unload */ 578 /* for freeing the buffer during driver unload */
579 fwone->fws_alloc = data; 579 fwone->fws_alloc = data;
580 fwone->fws_allocsize = dlen; 580 fwone->fws_allocsize = dlen;
581 581
582 fws->fw_count++; 582 fws->fw_count++;
583 fws->fw_totlen += fwone->fws_len; 583 fws->fw_totlen += fwone->fws_len;
584 584
585 return 0; 585 return 0;
586} 586}
587 587
588/* iwlwifi: iwl-drv.c */ 588/* iwlwifi: iwl-drv.c */
589struct iwm_tlv_calib_data { 589struct iwm_tlv_calib_data {
590 uint32_t ucode_type; 590 uint32_t ucode_type;
591 struct iwm_tlv_calib_ctrl calib; 591 struct iwm_tlv_calib_ctrl calib;
592} __packed; 592} __packed;
593 593
594static int 594static int
595iwm_set_default_calib(struct iwm_softc *sc, const void *data) 595iwm_set_default_calib(struct iwm_softc *sc, const void *data)
596{ 596{
597 const struct iwm_tlv_calib_data *def_calib = data; 597 const struct iwm_tlv_calib_data *def_calib = data;
598 uint32_t ucode_type = le32toh(def_calib->ucode_type); 598 uint32_t ucode_type = le32toh(def_calib->ucode_type);
599 599
600 if (ucode_type >= IWM_UCODE_TYPE_MAX) { 600 if (ucode_type >= IWM_UCODE_TYPE_MAX) {
601 DPRINTF(("%s: Wrong ucode_type %u for default " 601 DPRINTF(("%s: Wrong ucode_type %u for default "
602 "calibration.\n", DEVNAME(sc), ucode_type)); 602 "calibration.\n", DEVNAME(sc), ucode_type));
603 return EINVAL; 603 return EINVAL;
604 } 604 }
605 605
606 sc->sc_default_calib[ucode_type].flow_trigger = 606 sc->sc_default_calib[ucode_type].flow_trigger =
607 def_calib->calib.flow_trigger; 607 def_calib->calib.flow_trigger;
608 sc->sc_default_calib[ucode_type].event_trigger = 608 sc->sc_default_calib[ucode_type].event_trigger =
609 def_calib->calib.event_trigger; 609 def_calib->calib.event_trigger;
610 610
611 return 0; 611 return 0;
612} 612}
613 613
614static int 614static int
615iwm_read_firmware(struct iwm_softc *sc) 615iwm_read_firmware(struct iwm_softc *sc)
616{ 616{
617 struct iwm_fw_info *fw = &sc->sc_fw; 617 struct iwm_fw_info *fw = &sc->sc_fw;
618 struct iwm_tlv_ucode_header *uhdr; 618 struct iwm_tlv_ucode_header *uhdr;
619 struct iwm_ucode_tlv tlv; 619 struct iwm_ucode_tlv tlv;
620 enum iwm_ucode_tlv_type tlv_type; 620 enum iwm_ucode_tlv_type tlv_type;
621 uint8_t *data; 621 uint8_t *data;
622 int error, status; 622 int error, status;
623 size_t len; 623 size_t len;
624 624
625 if (fw->fw_status == IWM_FW_STATUS_NONE) { 625 if (fw->fw_status == IWM_FW_STATUS_NONE) {
626 fw->fw_status = IWM_FW_STATUS_INPROGRESS; 626 fw->fw_status = IWM_FW_STATUS_INPROGRESS;
627 } else { 627 } else {
628 while (fw->fw_status == IWM_FW_STATUS_INPROGRESS) 628 while (fw->fw_status == IWM_FW_STATUS_INPROGRESS)
629 tsleep(&sc->sc_fw, 0, "iwmfwp", 0); 629 tsleep(&sc->sc_fw, 0, "iwmfwp", 0);
630 } 630 }
631 status = fw->fw_status; 631 status = fw->fw_status;
632 632
633 if (status == IWM_FW_STATUS_DONE) 633 if (status == IWM_FW_STATUS_DONE)
634 return 0; 634 return 0;
635 635
636 /* 636 /*
637 * Load firmware into driver memory. 637 * Load firmware into driver memory.
638 * fw_rawdata and fw_rawsize will be set. 638 * fw_rawdata and fw_rawsize will be set.
639 */ 639 */
640 error = iwm_firmload(sc); 640 error = iwm_firmload(sc);
641 if (error != 0) { 641 if (error != 0) {
642 aprint_error_dev(sc->sc_dev, 642 aprint_error_dev(sc->sc_dev,
643 "could not read firmware %s (error %d)\n", 643 "could not read firmware %s (error %d)\n",
644 sc->sc_fwname, error); 644 sc->sc_fwname, error);
645 goto out; 645 goto out;
646 } 646 }
647 647
648 /* 648 /*
649 * Parse firmware contents 649 * Parse firmware contents
650 */ 650 */
651 651
652 uhdr = (void *)fw->fw_rawdata; 652 uhdr = (void *)fw->fw_rawdata;
653 if (*(uint32_t *)fw->fw_rawdata != 0 653 if (*(uint32_t *)fw->fw_rawdata != 0
654 || le32toh(uhdr->magic) != IWM_TLV_UCODE_MAGIC) { 654 || le32toh(uhdr->magic) != IWM_TLV_UCODE_MAGIC) {
655 aprint_error_dev(sc->sc_dev, "invalid firmware %s\n", 655 aprint_error_dev(sc->sc_dev, "invalid firmware %s\n",
656 sc->sc_fwname); 656 sc->sc_fwname);
657 error = EINVAL; 657 error = EINVAL;
658 goto out; 658 goto out;
659 } 659 }
660 660
661 sc->sc_fwver = le32toh(uhdr->ver); 661 sc->sc_fwver = le32toh(uhdr->ver);
662 data = uhdr->data; 662 data = uhdr->data;
663 len = fw->fw_rawsize - sizeof(*uhdr); 663 len = fw->fw_rawsize - sizeof(*uhdr);
664 664
665 while (len >= sizeof(tlv)) { 665 while (len >= sizeof(tlv)) {
666 size_t tlv_len; 666 size_t tlv_len;
667 void *tlv_data; 667 void *tlv_data;
668 668
669 memcpy(&tlv, data, sizeof(tlv)); 669 memcpy(&tlv, data, sizeof(tlv));
670 tlv_len = le32toh(tlv.length); 670 tlv_len = le32toh(tlv.length);
671 tlv_type = le32toh(tlv.type); 671 tlv_type = le32toh(tlv.type);
672 672
673 len -= sizeof(tlv); 673 len -= sizeof(tlv);
674 data += sizeof(tlv); 674 data += sizeof(tlv);
675 tlv_data = data; 675 tlv_data = data;
676 676
677 if (len < tlv_len) { 677 if (len < tlv_len) {
678 aprint_error_dev(sc->sc_dev, 678 aprint_error_dev(sc->sc_dev,
679 "firmware too short: %zu bytes\n", len); 679 "firmware too short: %zu bytes\n", len);
680 error = EINVAL; 680 error = EINVAL;
681 goto parse_out; 681 goto parse_out;
682 } 682 }
683 683
684 switch ((int)tlv_type) { 684 switch ((int)tlv_type) {
685 case IWM_UCODE_TLV_PROBE_MAX_LEN: 685 case IWM_UCODE_TLV_PROBE_MAX_LEN:
686 if (tlv_len < sizeof(uint32_t)) { 686 if (tlv_len < sizeof(uint32_t)) {
687 error = EINVAL; 687 error = EINVAL;
688 goto parse_out; 688 goto parse_out;
689 } 689 }
690 sc->sc_capa_max_probe_len 690 sc->sc_capa_max_probe_len
691 = le32toh(*(uint32_t *)tlv_data); 691 = le32toh(*(uint32_t *)tlv_data);
692 /* limit it to something sensible */ 692 /* limit it to something sensible */
693 if (sc->sc_capa_max_probe_len > (1<<16)) { 693 if (sc->sc_capa_max_probe_len > (1<<16)) {
694 DPRINTF(("%s: IWM_UCODE_TLV_PROBE_MAX_LEN " 694 DPRINTF(("%s: IWM_UCODE_TLV_PROBE_MAX_LEN "
695 "ridiculous\n", DEVNAME(sc))); 695 "ridiculous\n", DEVNAME(sc)));
696 error = EINVAL; 696 error = EINVAL;
697 goto parse_out; 697 goto parse_out;
698 } 698 }
699 break; 699 break;
700 case IWM_UCODE_TLV_PAN: 700 case IWM_UCODE_TLV_PAN:
701 if (tlv_len) { 701 if (tlv_len) {
702 error = EINVAL; 702 error = EINVAL;
703 goto parse_out; 703 goto parse_out;
704 } 704 }
705 sc->sc_capaflags |= IWM_UCODE_TLV_FLAGS_PAN; 705 sc->sc_capaflags |= IWM_UCODE_TLV_FLAGS_PAN;
706 break; 706 break;
707 case IWM_UCODE_TLV_FLAGS: 707 case IWM_UCODE_TLV_FLAGS:
708 if (tlv_len < sizeof(uint32_t)) { 708 if (tlv_len < sizeof(uint32_t)) {
709 error = EINVAL; 709 error = EINVAL;
710 goto parse_out; 710 goto parse_out;
711 } 711 }
712 /* 712 /*
713 * Apparently there can be many flags, but Linux driver 713 * Apparently there can be many flags, but Linux driver
714 * parses only the first one, and so do we. 714 * parses only the first one, and so do we.
715 * 715 *
716 * XXX: why does this override IWM_UCODE_TLV_PAN? 716 * XXX: why does this override IWM_UCODE_TLV_PAN?
717 * Intentional or a bug? Observations from 717 * Intentional or a bug? Observations from
718 * current firmware file: 718 * current firmware file:
719 * 1) TLV_PAN is parsed first 719 * 1) TLV_PAN is parsed first
720 * 2) TLV_FLAGS contains TLV_FLAGS_PAN 720 * 2) TLV_FLAGS contains TLV_FLAGS_PAN
721 * ==> this resets TLV_PAN to itself... hnnnk 721 * ==> this resets TLV_PAN to itself... hnnnk
722 */ 722 */
723 sc->sc_capaflags = le32toh(*(uint32_t *)tlv_data); 723 sc->sc_capaflags = le32toh(*(uint32_t *)tlv_data);
724 break; 724 break;
725 case IWM_UCODE_TLV_CSCHEME: 725 case IWM_UCODE_TLV_CSCHEME:
726 if ((error = iwm_store_cscheme(sc, 726 if ((error = iwm_store_cscheme(sc,
727 tlv_data, tlv_len)) != 0) 727 tlv_data, tlv_len)) != 0)
728 goto parse_out; 728 goto parse_out;
729 break; 729 break;
730 case IWM_UCODE_TLV_NUM_OF_CPU: 730 case IWM_UCODE_TLV_NUM_OF_CPU:
731 if (tlv_len != sizeof(uint32_t)) { 731 if (tlv_len != sizeof(uint32_t)) {
732 error = EINVAL; 732 error = EINVAL;
733 goto parse_out; 733 goto parse_out;
734 } 734 }
735 if (le32toh(*(uint32_t*)tlv_data) != 1) { 735 if (le32toh(*(uint32_t*)tlv_data) != 1) {
736 DPRINTF(("%s: driver supports " 736 DPRINTF(("%s: driver supports "
737 "only TLV_NUM_OF_CPU == 1", DEVNAME(sc))); 737 "only TLV_NUM_OF_CPU == 1", DEVNAME(sc)));
738 error = EINVAL; 738 error = EINVAL;
739 goto parse_out; 739 goto parse_out;
740 } 740 }
741 break; 741 break;
742 case IWM_UCODE_TLV_SEC_RT: 742 case IWM_UCODE_TLV_SEC_RT:
743 if ((error = iwm_firmware_store_section(sc, 743 if ((error = iwm_firmware_store_section(sc,
744 IWM_UCODE_TYPE_REGULAR, tlv_data, tlv_len)) != 0) 744 IWM_UCODE_TYPE_REGULAR, tlv_data, tlv_len)) != 0)
745 goto parse_out; 745 goto parse_out;
746 break; 746 break;
747 case IWM_UCODE_TLV_SEC_INIT: 747 case IWM_UCODE_TLV_SEC_INIT:
748 if ((error = iwm_firmware_store_section(sc, 748 if ((error = iwm_firmware_store_section(sc,
749 IWM_UCODE_TYPE_INIT, tlv_data, tlv_len)) != 0) 749 IWM_UCODE_TYPE_INIT, tlv_data, tlv_len)) != 0)
750 goto parse_out; 750 goto parse_out;
751 break; 751 break;
752 case IWM_UCODE_TLV_SEC_WOWLAN: 752 case IWM_UCODE_TLV_SEC_WOWLAN:
753 if ((error = iwm_firmware_store_section(sc, 753 if ((error = iwm_firmware_store_section(sc,
754 IWM_UCODE_TYPE_WOW, tlv_data, tlv_len)) != 0) 754 IWM_UCODE_TYPE_WOW, tlv_data, tlv_len)) != 0)
755 goto parse_out; 755 goto parse_out;
756 break; 756 break;
757 case IWM_UCODE_TLV_DEF_CALIB: 757 case IWM_UCODE_TLV_DEF_CALIB:
758 if (tlv_len != sizeof(struct iwm_tlv_calib_data)) { 758 if (tlv_len != sizeof(struct iwm_tlv_calib_data)) {
759 error = EINVAL; 759 error = EINVAL;
760 goto parse_out; 760 goto parse_out;
761 } 761 }
762 if ((error = iwm_set_default_calib(sc, tlv_data)) != 0) 762 if ((error = iwm_set_default_calib(sc, tlv_data)) != 0)
763 goto parse_out; 763 goto parse_out;
764 break; 764 break;
765 case IWM_UCODE_TLV_PHY_SKU: 765 case IWM_UCODE_TLV_PHY_SKU:
766 if (tlv_len != sizeof(uint32_t)) { 766 if (tlv_len != sizeof(uint32_t)) {
767 error = EINVAL; 767 error = EINVAL;
768 goto parse_out; 768 goto parse_out;
769 } 769 }
770 sc->sc_fw_phy_config = le32toh(*(uint32_t *)tlv_data); 770 sc->sc_fw_phy_config = le32toh(*(uint32_t *)tlv_data);
771 break; 771 break;
772 772
773 case IWM_UCODE_TLV_API_CHANGES_SET: 773 case IWM_UCODE_TLV_API_CHANGES_SET:
774 case IWM_UCODE_TLV_ENABLED_CAPABILITIES: 774 case IWM_UCODE_TLV_ENABLED_CAPABILITIES:
775 /* ignore, not used by current driver */ 775 /* ignore, not used by current driver */
776 break; 776 break;
777 777
778 default: 778 default:
779 DPRINTF(("%s: unknown firmware section %d, abort\n", 779 DPRINTF(("%s: unknown firmware section %d, abort\n",
780 DEVNAME(sc), tlv_type)); 780 DEVNAME(sc), tlv_type));
781 error = EINVAL; 781 error = EINVAL;
782 goto parse_out; 782 goto parse_out;
783 } 783 }
784 784
785 len -= roundup(tlv_len, 4); 785 len -= roundup(tlv_len, 4);
786 data += roundup(tlv_len, 4); 786 data += roundup(tlv_len, 4);
787 } 787 }
788 788
789 KASSERT(error == 0); 789 KASSERT(error == 0);
790 790
791 parse_out: 791 parse_out:
792 if (error) { 792 if (error) {
793 aprint_error_dev(sc->sc_dev, 793 aprint_error_dev(sc->sc_dev,
794 "firmware parse error, section type %d\n", tlv_type); 794 "firmware parse error, section type %d\n", tlv_type);
795 } 795 }
796 796
797 if (!(sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)) { 797 if (!(sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)) {
798 aprint_error_dev(sc->sc_dev, 798 aprint_error_dev(sc->sc_dev,
799 "device uses unsupported power ops\n"); 799 "device uses unsupported power ops\n");
800 error = ENOTSUP; 800 error = ENOTSUP;
801 } 801 }
802 802
803 out: 803 out:
804 if (error) 804 if (error)
805 fw->fw_status = IWM_FW_STATUS_NONE; 805 fw->fw_status = IWM_FW_STATUS_NONE;
806 else 806 else
807 fw->fw_status = IWM_FW_STATUS_DONE; 807 fw->fw_status = IWM_FW_STATUS_DONE;
808 wakeup(&sc->sc_fw); 808 wakeup(&sc->sc_fw);
809 809
810 if (error) { 810 if (error) {
811 kmem_free(fw->fw_rawdata, fw->fw_rawsize); 811 kmem_free(fw->fw_rawdata, fw->fw_rawsize);
812 fw->fw_rawdata = NULL; 812 fw->fw_rawdata = NULL;
813 } 813 }
814 return error; 814 return error;
815} 815}
816 816
817/* 817/*
818 * basic device access 818 * basic device access
819 */ 819 */
820 820
821static uint32_t 821static uint32_t
822iwm_read_prph(struct iwm_softc *sc, uint32_t addr) 822iwm_read_prph(struct iwm_softc *sc, uint32_t addr)
823{ 823{
824 IWM_WRITE(sc, 824 IWM_WRITE(sc,
825 IWM_HBUS_TARG_PRPH_RADDR, ((addr & 0x000fffff) | (3 << 24))); 825 IWM_HBUS_TARG_PRPH_RADDR, ((addr & 0x000fffff) | (3 << 24)));
826 IWM_BARRIER_READ_WRITE(sc); 826 IWM_BARRIER_READ_WRITE(sc);
827 return IWM_READ(sc, IWM_HBUS_TARG_PRPH_RDAT); 827 return IWM_READ(sc, IWM_HBUS_TARG_PRPH_RDAT);
828} 828}
829 829
830static void 830static void
831iwm_write_prph(struct iwm_softc *sc, uint32_t addr, uint32_t val) 831iwm_write_prph(struct iwm_softc *sc, uint32_t addr, uint32_t val)
832{ 832{
833 IWM_WRITE(sc, 833 IWM_WRITE(sc,
834 IWM_HBUS_TARG_PRPH_WADDR, ((addr & 0x000fffff) | (3 << 24))); 834 IWM_HBUS_TARG_PRPH_WADDR, ((addr & 0x000fffff) | (3 << 24)));
835 IWM_BARRIER_WRITE(sc); 835 IWM_BARRIER_WRITE(sc);
836 IWM_WRITE(sc, IWM_HBUS_TARG_PRPH_WDAT, val); 836 IWM_WRITE(sc, IWM_HBUS_TARG_PRPH_WDAT, val);
837} 837}
838 838
839#ifdef IWM_DEBUG 839#ifdef IWM_DEBUG
840/* iwlwifi: pcie/trans.c */ 840/* iwlwifi: pcie/trans.c */
841static int 841static int
842iwm_read_mem(struct iwm_softc *sc, uint32_t addr, void *buf, int dwords) 842iwm_read_mem(struct iwm_softc *sc, uint32_t addr, void *buf, int dwords)
843{ 843{
844 int offs, ret = 0; 844 int offs, ret = 0;
845 uint32_t *vals = buf; 845 uint32_t *vals = buf;
846 846
847 if (iwm_nic_lock(sc)) { 847 if (iwm_nic_lock(sc)) {
848 IWM_WRITE(sc, IWM_HBUS_TARG_MEM_RADDR, addr); 848 IWM_WRITE(sc, IWM_HBUS_TARG_MEM_RADDR, addr);
849 for (offs = 0; offs < dwords; offs++) 849 for (offs = 0; offs < dwords; offs++)
850 vals[offs] = IWM_READ(sc, IWM_HBUS_TARG_MEM_RDAT); 850 vals[offs] = IWM_READ(sc, IWM_HBUS_TARG_MEM_RDAT);
851 iwm_nic_unlock(sc); 851 iwm_nic_unlock(sc);
852 } else { 852 } else {
853 ret = EBUSY; 853 ret = EBUSY;
854 } 854 }
855 return ret; 855 return ret;
856} 856}
857#endif 857#endif
858 858
859/* iwlwifi: pcie/trans.c */ 859/* iwlwifi: pcie/trans.c */
860static int 860static int
861iwm_write_mem(struct iwm_softc *sc, uint32_t addr, const void *buf, int dwords) 861iwm_write_mem(struct iwm_softc *sc, uint32_t addr, const void *buf, int dwords)
862{ 862{
863 int offs; 863 int offs;
864 const uint32_t *vals = buf; 864 const uint32_t *vals = buf;
865 865
866 if (iwm_nic_lock(sc)) { 866 if (iwm_nic_lock(sc)) {
867 IWM_WRITE(sc, IWM_HBUS_TARG_MEM_WADDR, addr); 867 IWM_WRITE(sc, IWM_HBUS_TARG_MEM_WADDR, addr);
868 /* WADDR auto-increments */ 868 /* WADDR auto-increments */
869 for (offs = 0; offs < dwords; offs++) { 869 for (offs = 0; offs < dwords; offs++) {
870 uint32_t val = vals ? vals[offs] : 0; 870 uint32_t val = vals ? vals[offs] : 0;
871 IWM_WRITE(sc, IWM_HBUS_TARG_MEM_WDAT, val); 871 IWM_WRITE(sc, IWM_HBUS_TARG_MEM_WDAT, val);
872 } 872 }
873 iwm_nic_unlock(sc); 873 iwm_nic_unlock(sc);
874 } else { 874 } else {
875 DPRINTF(("%s: write_mem failed\n", DEVNAME(sc))); 875 DPRINTF(("%s: write_mem failed\n", DEVNAME(sc)));
876 return EBUSY; 876 return EBUSY;
877 } 877 }
878 return 0; 878 return 0;
879} 879}
880 880
881static int 881static int
882iwm_write_mem32(struct iwm_softc *sc, uint32_t addr, uint32_t val) 882iwm_write_mem32(struct iwm_softc *sc, uint32_t addr, uint32_t val)
883{ 883{
884 return iwm_write_mem(sc, addr, &val, 1); 884 return iwm_write_mem(sc, addr, &val, 1);
885} 885}
886 886
887static int 887static int
888iwm_poll_bit(struct iwm_softc *sc, int reg, 888iwm_poll_bit(struct iwm_softc *sc, int reg,
889 uint32_t bits, uint32_t mask, int timo) 889 uint32_t bits, uint32_t mask, int timo)
890{ 890{
891 for (;;) { 891 for (;;) {
892 if ((IWM_READ(sc, reg) & mask) == (bits & mask)) { 892 if ((IWM_READ(sc, reg) & mask) == (bits & mask)) {
893 return 1; 893 return 1;
894 } 894 }
895 if (timo < 10) { 895 if (timo < 10) {
896 return 0; 896 return 0;
897 } 897 }
898 timo -= 10; 898 timo -= 10;
899 DELAY(10); 899 DELAY(10);
900 } 900 }
901} 901}
902 902
903static int 903static int
904iwm_nic_lock(struct iwm_softc *sc) 904iwm_nic_lock(struct iwm_softc *sc)
905{ 905{
906 int rv = 0; 906 int rv = 0;
907 907
908 IWM_SETBITS(sc, IWM_CSR_GP_CNTRL, 908 IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
909 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 909 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
910 910
911 if (iwm_poll_bit(sc, IWM_CSR_GP_CNTRL, 911 if (iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
912 IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, 912 IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
913 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY 913 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
914 | IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP, 15000)) { 914 | IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP, 15000)) {
915 rv = 1; 915 rv = 1;
916 } else { 916 } else {
917 /* jolt */ 917 /* jolt */
918 IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_FORCE_NMI); 918 IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_FORCE_NMI);
919 } 919 }
920 920
921 return rv; 921 return rv;
922} 922}
923 923
924static void 924static void
925iwm_nic_unlock(struct iwm_softc *sc) 925iwm_nic_unlock(struct iwm_softc *sc)
926{ 926{
927 IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL, 927 IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
928 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 928 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
929} 929}
930 930
931static void 931static void
932iwm_set_bits_mask_prph(struct iwm_softc *sc, 932iwm_set_bits_mask_prph(struct iwm_softc *sc,
933 uint32_t reg, uint32_t bits, uint32_t mask) 933 uint32_t reg, uint32_t bits, uint32_t mask)
934{ 934{
935 uint32_t val; 935 uint32_t val;
936 936
937 /* XXX: no error path? */ 937 /* XXX: no error path? */
938 if (iwm_nic_lock(sc)) { 938 if (iwm_nic_lock(sc)) {
939 val = iwm_read_prph(sc, reg) & mask; 939 val = iwm_read_prph(sc, reg) & mask;
940 val |= bits; 940 val |= bits;
941 iwm_write_prph(sc, reg, val); 941 iwm_write_prph(sc, reg, val);
942 iwm_nic_unlock(sc); 942 iwm_nic_unlock(sc);
943 } 943 }
944} 944}
945 945
946static void 946static void
947iwm_set_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits) 947iwm_set_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits)
948{ 948{
949 iwm_set_bits_mask_prph(sc, reg, bits, ~0); 949 iwm_set_bits_mask_prph(sc, reg, bits, ~0);
950} 950}
951 951
952static void 952static void
953iwm_clear_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits) 953iwm_clear_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits)
954{ 954{
955 iwm_set_bits_mask_prph(sc, reg, 0, ~bits); 955 iwm_set_bits_mask_prph(sc, reg, 0, ~bits);
956} 956}
957 957
958/* 958/*
959 * DMA resource routines 959 * DMA resource routines
960 */ 960 */
961 961
962static int 962static int
963iwm_dma_contig_alloc(bus_dma_tag_t tag, struct iwm_dma_info *dma, 963iwm_dma_contig_alloc(bus_dma_tag_t tag, struct iwm_dma_info *dma,
964 bus_size_t size, bus_size_t alignment) 964 bus_size_t size, bus_size_t alignment)
965{ 965{
966 int nsegs, error; 966 int nsegs, error;
967 void *va; 967 void *va;
968 968
969 dma->tag = tag; 969 dma->tag = tag;
970 dma->size = size; 970 dma->size = size;
971 971
972 error = bus_dmamap_create(tag, size, 1, size, 0, BUS_DMA_NOWAIT, 972 error = bus_dmamap_create(tag, size, 1, size, 0, BUS_DMA_NOWAIT,
973 &dma->map); 973 &dma->map);
974 if (error != 0) 974 if (error != 0)
975 goto fail; 975 goto fail;
976 976
977 error = bus_dmamem_alloc(tag, size, alignment, 0, &dma->seg, 1, &nsegs, 977 error = bus_dmamem_alloc(tag, size, alignment, 0, &dma->seg, 1, &nsegs,
978 BUS_DMA_NOWAIT); 978 BUS_DMA_NOWAIT);
979 if (error != 0) 979 if (error != 0)
980 goto fail; 980 goto fail;
981 981
982 error = bus_dmamem_map(tag, &dma->seg, 1, size, &va, 982 error = bus_dmamem_map(tag, &dma->seg, 1, size, &va,
983 BUS_DMA_NOWAIT); 983 BUS_DMA_NOWAIT);
984 if (error != 0) 984 if (error != 0)
985 goto fail; 985 goto fail;
986 dma->vaddr = va; 986 dma->vaddr = va;
987 987
988 error = bus_dmamap_load(tag, dma->map, dma->vaddr, size, NULL, 988 error = bus_dmamap_load(tag, dma->map, dma->vaddr, size, NULL,
989 BUS_DMA_NOWAIT); 989 BUS_DMA_NOWAIT);
990 if (error != 0) 990 if (error != 0)
991 goto fail; 991 goto fail;
992 992
993 memset(dma->vaddr, 0, size); 993 memset(dma->vaddr, 0, size);
994 bus_dmamap_sync(tag, dma->map, 0, size, BUS_DMASYNC_PREWRITE); 994 bus_dmamap_sync(tag, dma->map, 0, size, BUS_DMASYNC_PREWRITE);
995 dma->paddr = dma->map->dm_segs[0].ds_addr; 995 dma->paddr = dma->map->dm_segs[0].ds_addr;
996 996
997 return 0; 997 return 0;
998 998
999fail: iwm_dma_contig_free(dma); 999fail: iwm_dma_contig_free(dma);
1000 return error; 1000 return error;
1001} 1001}
1002 1002
1003static void 1003static void
1004iwm_dma_contig_free(struct iwm_dma_info *dma) 1004iwm_dma_contig_free(struct iwm_dma_info *dma)
1005{ 1005{
1006 if (dma->map != NULL) { 1006 if (dma->map != NULL) {
1007 if (dma->vaddr != NULL) { 1007 if (dma->vaddr != NULL) {
1008 bus_dmamap_sync(dma->tag, dma->map, 0, dma->size, 1008 bus_dmamap_sync(dma->tag, dma->map, 0, dma->size,
1009 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1009 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1010 bus_dmamap_unload(dma->tag, dma->map); 1010 bus_dmamap_unload(dma->tag, dma->map);
1011 bus_dmamem_unmap(dma->tag, dma->vaddr, dma->size); 1011 bus_dmamem_unmap(dma->tag, dma->vaddr, dma->size);
1012 bus_dmamem_free(dma->tag, &dma->seg, 1); 1012 bus_dmamem_free(dma->tag, &dma->seg, 1);
1013 dma->vaddr = NULL; 1013 dma->vaddr = NULL;
1014 } 1014 }
1015 bus_dmamap_destroy(dma->tag, dma->map); 1015 bus_dmamap_destroy(dma->tag, dma->map);
1016 dma->map = NULL; 1016 dma->map = NULL;
1017 } 1017 }
1018} 1018}
1019 1019
1020/* fwmem is used to load firmware onto the card */ 1020/* fwmem is used to load firmware onto the card */
1021static int 1021static int
1022iwm_alloc_fwmem(struct iwm_softc *sc) 1022iwm_alloc_fwmem(struct iwm_softc *sc)
1023{ 1023{
1024 /* Must be aligned on a 16-byte boundary. */ 1024 /* Must be aligned on a 16-byte boundary. */
1025 return iwm_dma_contig_alloc(sc->sc_dmat, &sc->fw_dma, 1025 return iwm_dma_contig_alloc(sc->sc_dmat, &sc->fw_dma,
1026 sc->sc_fwdmasegsz, 16); 1026 sc->sc_fwdmasegsz, 16);
1027} 1027}
1028 1028
1029static void 1029static void
1030iwm_free_fwmem(struct iwm_softc *sc) 1030iwm_free_fwmem(struct iwm_softc *sc)
1031{ 1031{
1032 iwm_dma_contig_free(&sc->fw_dma); 1032 iwm_dma_contig_free(&sc->fw_dma);
1033} 1033}
1034 1034
1035/* tx scheduler rings. not used? */ 1035/* tx scheduler rings. not used? */
1036static int 1036static int
1037iwm_alloc_sched(struct iwm_softc *sc) 1037iwm_alloc_sched(struct iwm_softc *sc)
1038{ 1038{
1039 int rv; 1039 int rv;
1040 1040
1041 /* TX scheduler rings must be aligned on a 1KB boundary. */ 1041 /* TX scheduler rings must be aligned on a 1KB boundary. */
1042 rv = iwm_dma_contig_alloc(sc->sc_dmat, &sc->sched_dma, 1042 rv = iwm_dma_contig_alloc(sc->sc_dmat, &sc->sched_dma,
1043 __arraycount(sc->txq) * sizeof(struct iwm_agn_scd_bc_tbl), 1024); 1043 __arraycount(sc->txq) * sizeof(struct iwm_agn_scd_bc_tbl), 1024);
1044 return rv; 1044 return rv;
1045} 1045}
1046 1046
1047static void 1047static void
1048iwm_free_sched(struct iwm_softc *sc) 1048iwm_free_sched(struct iwm_softc *sc)
1049{ 1049{
1050 iwm_dma_contig_free(&sc->sched_dma); 1050 iwm_dma_contig_free(&sc->sched_dma);
1051} 1051}
1052 1052
1053/* keep-warm page is used internally by the card. see iwl-fh.h for more info */ 1053/* keep-warm page is used internally by the card. see iwl-fh.h for more info */
1054static int 1054static int
1055iwm_alloc_kw(struct iwm_softc *sc) 1055iwm_alloc_kw(struct iwm_softc *sc)
1056{ 1056{
1057 return iwm_dma_contig_alloc(sc->sc_dmat, &sc->kw_dma, 4096, 4096); 1057 return iwm_dma_contig_alloc(sc->sc_dmat, &sc->kw_dma, 4096, 4096);
1058} 1058}
1059 1059
1060static void 1060static void
1061iwm_free_kw(struct iwm_softc *sc) 1061iwm_free_kw(struct iwm_softc *sc)
1062{ 1062{
1063 iwm_dma_contig_free(&sc->kw_dma); 1063 iwm_dma_contig_free(&sc->kw_dma);
1064} 1064}
1065 1065
1066/* interrupt cause table */ 1066/* interrupt cause table */
1067static int 1067static int
1068iwm_alloc_ict(struct iwm_softc *sc) 1068iwm_alloc_ict(struct iwm_softc *sc)
1069{ 1069{
1070 return iwm_dma_contig_alloc(sc->sc_dmat, &sc->ict_dma, 1070 return iwm_dma_contig_alloc(sc->sc_dmat, &sc->ict_dma,
1071 IWM_ICT_SIZE, 1<<IWM_ICT_PADDR_SHIFT); 1071 IWM_ICT_SIZE, 1<<IWM_ICT_PADDR_SHIFT);
1072} 1072}
1073 1073
1074static void 1074static void
1075iwm_free_ict(struct iwm_softc *sc) 1075iwm_free_ict(struct iwm_softc *sc)
1076{ 1076{
1077 iwm_dma_contig_free(&sc->ict_dma); 1077 iwm_dma_contig_free(&sc->ict_dma);
1078} 1078}
1079 1079
1080static int 1080static int
1081iwm_alloc_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring) 1081iwm_alloc_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring)
1082{ 1082{
1083 bus_size_t size; 1083 bus_size_t size;
1084 int i, error; 1084 int i, error;
1085 1085
1086 ring->cur = 0; 1086 ring->cur = 0;
1087 1087
1088 /* Allocate RX descriptors (256-byte aligned). */ 1088 /* Allocate RX descriptors (256-byte aligned). */
1089 size = IWM_RX_RING_COUNT * sizeof(uint32_t); 1089 size = IWM_RX_RING_COUNT * sizeof(uint32_t);
1090 error = iwm_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma, size, 256); 1090 error = iwm_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma, size, 256);
1091 if (error != 0) { 1091 if (error != 0) {
1092 aprint_error_dev(sc->sc_dev, 1092 aprint_error_dev(sc->sc_dev,
1093 "could not allocate RX ring DMA memory\n"); 1093 "could not allocate RX ring DMA memory\n");
1094 goto fail; 1094 goto fail;
1095 } 1095 }
1096 ring->desc = ring->desc_dma.vaddr; 1096 ring->desc = ring->desc_dma.vaddr;
1097 1097
1098 /* Allocate RX status area (16-byte aligned). */ 1098 /* Allocate RX status area (16-byte aligned). */
1099 error = iwm_dma_contig_alloc(sc->sc_dmat, &ring->stat_dma, 1099 error = iwm_dma_contig_alloc(sc->sc_dmat, &ring->stat_dma,
1100 sizeof(*ring->stat), 16); 1100 sizeof(*ring->stat), 16);
1101 if (error != 0) { 1101 if (error != 0) {
1102 aprint_error_dev(sc->sc_dev, 1102 aprint_error_dev(sc->sc_dev,
1103 "could not allocate RX status DMA memory\n"); 1103 "could not allocate RX status DMA memory\n");
1104 goto fail; 1104 goto fail;
1105 } 1105 }
1106 ring->stat = ring->stat_dma.vaddr; 1106 ring->stat = ring->stat_dma.vaddr;
1107 1107
1108 /* 1108 /*
1109 * Allocate and map RX buffers. 1109 * Allocate and map RX buffers.
1110 */ 1110 */
1111 for (i = 0; i < IWM_RX_RING_COUNT; i++) { 1111 for (i = 0; i < IWM_RX_RING_COUNT; i++) {
1112 struct iwm_rx_data *data = &ring->data[i]; 1112 struct iwm_rx_data *data = &ring->data[i];
1113 1113
1114 memset(data, 0, sizeof(*data)); 1114 memset(data, 0, sizeof(*data));
1115 error = bus_dmamap_create(sc->sc_dmat, IWM_RBUF_SIZE, 1, 1115 error = bus_dmamap_create(sc->sc_dmat, IWM_RBUF_SIZE, 1,
1116 IWM_RBUF_SIZE, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, 1116 IWM_RBUF_SIZE, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
1117 &data->map); 1117 &data->map);
1118 if (error != 0) { 1118 if (error != 0) {
1119 aprint_error_dev(sc->sc_dev, 1119 aprint_error_dev(sc->sc_dev,
1120 "could not create RX buf DMA map\n"); 1120 "could not create RX buf DMA map\n");
1121 goto fail; 1121 goto fail;
1122 } 1122 }
1123 1123
1124 if ((error = iwm_rx_addbuf(sc, IWM_RBUF_SIZE, i)) != 0) { 1124 if ((error = iwm_rx_addbuf(sc, IWM_RBUF_SIZE, i)) != 0) {
1125 goto fail; 1125 goto fail;
1126 } 1126 }
1127 } 1127 }
1128 return 0; 1128 return 0;
1129 1129
1130fail: iwm_free_rx_ring(sc, ring); 1130fail: iwm_free_rx_ring(sc, ring);
1131 return error; 1131 return error;
1132} 1132}
1133 1133
1134static void 1134static void
1135iwm_reset_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring) 1135iwm_reset_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring)
1136{ 1136{
1137 int ntries; 1137 int ntries;
1138 1138
1139 if (iwm_nic_lock(sc)) { 1139 if (iwm_nic_lock(sc)) {
1140 IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); 1140 IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
1141 for (ntries = 0; ntries < 1000; ntries++) { 1141 for (ntries = 0; ntries < 1000; ntries++) {
1142 if (IWM_READ(sc, IWM_FH_MEM_RSSR_RX_STATUS_REG) & 1142 if (IWM_READ(sc, IWM_FH_MEM_RSSR_RX_STATUS_REG) &
1143 IWM_FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE) 1143 IWM_FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE)
1144 break; 1144 break;
1145 DELAY(10); 1145 DELAY(10);
1146 } 1146 }
1147 iwm_nic_unlock(sc); 1147 iwm_nic_unlock(sc);
1148 } 1148 }
1149 ring->cur = 0; 1149 ring->cur = 0;
1150} 1150}
1151 1151
1152static void 1152static void
1153iwm_free_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring) 1153iwm_free_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring)
1154{ 1154{
1155 int i; 1155 int i;
1156 1156
1157 iwm_dma_contig_free(&ring->desc_dma); 1157 iwm_dma_contig_free(&ring->desc_dma);
1158 iwm_dma_contig_free(&ring->stat_dma); 1158 iwm_dma_contig_free(&ring->stat_dma);
1159 1159
1160 for (i = 0; i < IWM_RX_RING_COUNT; i++) { 1160 for (i = 0; i < IWM_RX_RING_COUNT; i++) {
1161 struct iwm_rx_data *data = &ring->data[i]; 1161 struct iwm_rx_data *data = &ring->data[i];
1162 1162
1163 if (data->m != NULL) { 1163 if (data->m != NULL) {
1164 bus_dmamap_sync(sc->sc_dmat, data->map, 0, 1164 bus_dmamap_sync(sc->sc_dmat, data->map, 0,
1165 data->map->dm_mapsize, BUS_DMASYNC_POSTREAD); 1165 data->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
1166 bus_dmamap_unload(sc->sc_dmat, data->map); 1166 bus_dmamap_unload(sc->sc_dmat, data->map);
1167 m_freem(data->m); 1167 m_freem(data->m);
1168 } 1168 }
1169 if (data->map != NULL) 1169 if (data->map != NULL)
1170 bus_dmamap_destroy(sc->sc_dmat, data->map); 1170 bus_dmamap_destroy(sc->sc_dmat, data->map);
1171 } 1171 }
1172} 1172}
1173 1173
1174static int 1174static int
1175iwm_alloc_tx_ring(struct iwm_softc *sc, struct iwm_tx_ring *ring, int qid) 1175iwm_alloc_tx_ring(struct iwm_softc *sc, struct iwm_tx_ring *ring, int qid)
1176{ 1176{
1177 bus_addr_t paddr; 1177 bus_addr_t paddr;
1178 bus_size_t size; 1178 bus_size_t size;
1179 int i, error; 1179 int i, error;
1180 1180
1181 ring->qid = qid; 1181 ring->qid = qid;
1182 ring->queued = 0; 1182 ring->queued = 0;
1183 ring->cur = 0; 1183 ring->cur = 0;
1184 1184
1185 /* Allocate TX descriptors (256-byte aligned). */ 1185 /* Allocate TX descriptors (256-byte aligned). */
1186 size = IWM_TX_RING_COUNT * sizeof (struct iwm_tfd); 1186 size = IWM_TX_RING_COUNT * sizeof (struct iwm_tfd);
1187 error = iwm_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma, size, 256); 1187 error = iwm_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma, size, 256);
1188 if (error != 0) { 1188 if (error != 0) {
1189 aprint_error_dev(sc->sc_dev, 1189 aprint_error_dev(sc->sc_dev,
1190 "could not allocate TX ring DMA memory\n"); 1190 "could not allocate TX ring DMA memory\n");
1191 goto fail; 1191 goto fail;
1192 } 1192 }
1193 ring->desc = ring->desc_dma.vaddr; 1193 ring->desc = ring->desc_dma.vaddr;
1194 1194
1195 /* 1195 /*
1196 * We only use rings 0 through 9 (4 EDCA + cmd) so there is no need 1196 * We only use rings 0 through 9 (4 EDCA + cmd) so there is no need
1197 * to allocate commands space for other rings. 1197 * to allocate commands space for other rings.
1198 */ 1198 */
1199 if (qid > IWM_MVM_CMD_QUEUE) 1199 if (qid > IWM_MVM_CMD_QUEUE)
1200 return 0; 1200 return 0;
1201 1201
1202 size = IWM_TX_RING_COUNT * sizeof(struct iwm_device_cmd); 1202 size = IWM_TX_RING_COUNT * sizeof(struct iwm_device_cmd);
1203 error = iwm_dma_contig_alloc(sc->sc_dmat, &ring->cmd_dma, size, 4); 1203 error = iwm_dma_contig_alloc(sc->sc_dmat, &ring->cmd_dma, size, 4);
1204 if (error != 0) { 1204 if (error != 0) {
1205 aprint_error_dev(sc->sc_dev, 1205 aprint_error_dev(sc->sc_dev,
1206 "could not allocate TX cmd DMA memory\n"); 1206 "could not allocate TX cmd DMA memory\n");
1207 goto fail; 1207 goto fail;
1208 } 1208 }
1209 ring->cmd = ring->cmd_dma.vaddr; 1209 ring->cmd = ring->cmd_dma.vaddr;
1210 1210
1211 paddr = ring->cmd_dma.paddr; 1211 paddr = ring->cmd_dma.paddr;
1212 for (i = 0; i < IWM_TX_RING_COUNT; i++) { 1212 for (i = 0; i < IWM_TX_RING_COUNT; i++) {
1213 struct iwm_tx_data *data = &ring->data[i]; 1213 struct iwm_tx_data *data = &ring->data[i];
1214 1214
1215 data->cmd_paddr = paddr; 1215 data->cmd_paddr = paddr;
1216 data->scratch_paddr = paddr + sizeof(struct iwm_cmd_header) 1216 data->scratch_paddr = paddr + sizeof(struct iwm_cmd_header)
1217 + offsetof(struct iwm_tx_cmd, scratch); 1217 + offsetof(struct iwm_tx_cmd, scratch);
1218 paddr += sizeof(struct iwm_device_cmd); 1218 paddr += sizeof(struct iwm_device_cmd);
1219 1219
1220 error = bus_dmamap_create(sc->sc_dmat, IWM_RBUF_SIZE, 1220 error = bus_dmamap_create(sc->sc_dmat, IWM_RBUF_SIZE,
1221 IWM_NUM_OF_TBS, IWM_RBUF_SIZE, 0, BUS_DMA_NOWAIT, 1221 IWM_NUM_OF_TBS, IWM_RBUF_SIZE, 0, BUS_DMA_NOWAIT,
1222 &data->map); 1222 &data->map);
1223 if (error != 0) { 1223 if (error != 0) {
1224 aprint_error_dev(sc->sc_dev, 1224 aprint_error_dev(sc->sc_dev,
1225 "could not create TX buf DMA map\n"); 1225 "could not create TX buf DMA map\n");
1226 goto fail; 1226 goto fail;
1227 } 1227 }
1228 } 1228 }
1229 KASSERT(paddr == ring->cmd_dma.paddr + size); 1229 KASSERT(paddr == ring->cmd_dma.paddr + size);
1230 return 0; 1230 return 0;
1231 1231
1232fail: iwm_free_tx_ring(sc, ring); 1232fail: iwm_free_tx_ring(sc, ring);
1233 return error; 1233 return error;
1234} 1234}
1235 1235
1236static void 1236static void
1237iwm_reset_tx_ring(struct iwm_softc *sc, struct iwm_tx_ring *ring) 1237iwm_reset_tx_ring(struct iwm_softc *sc, struct iwm_tx_ring *ring)
1238{ 1238{
1239 int i; 1239 int i;
1240 1240
1241 for (i = 0; i < IWM_TX_RING_COUNT; i++) { 1241 for (i = 0; i < IWM_TX_RING_COUNT; i++) {
1242 struct iwm_tx_data *data = &ring->data[i]; 1242 struct iwm_tx_data *data = &ring->data[i];
1243 1243
1244 if (data->m != NULL) { 1244 if (data->m != NULL) {
1245 bus_dmamap_sync(sc->sc_dmat, data->map, 0, 1245 bus_dmamap_sync(sc->sc_dmat, data->map, 0,
1246 data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE); 1246 data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1247 bus_dmamap_unload(sc->sc_dmat, data->map); 1247 bus_dmamap_unload(sc->sc_dmat, data->map);
1248 m_freem(data->m); 1248 m_freem(data->m);
1249 data->m = NULL; 1249 data->m = NULL;
1250 } 1250 }
1251 } 1251 }
1252 /* Clear TX descriptors. */ 1252 /* Clear TX descriptors. */
1253 memset(ring->desc, 0, ring->desc_dma.size); 1253 memset(ring->desc, 0, ring->desc_dma.size);
1254 bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0, 1254 bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0,
1255 ring->desc_dma.size, BUS_DMASYNC_PREWRITE); 1255 ring->desc_dma.size, BUS_DMASYNC_PREWRITE);
1256 sc->qfullmsk &= ~(1 << ring->qid); 1256 sc->qfullmsk &= ~(1 << ring->qid);
1257 ring->queued = 0; 1257 ring->queued = 0;
1258 ring->cur = 0; 1258 ring->cur = 0;
1259} 1259}
1260 1260
1261static void 1261static void
1262iwm_free_tx_ring(struct iwm_softc *sc, struct iwm_tx_ring *ring) 1262iwm_free_tx_ring(struct iwm_softc *sc, struct iwm_tx_ring *ring)
1263{ 1263{
1264 int i; 1264 int i;
1265 1265
1266 iwm_dma_contig_free(&ring->desc_dma); 1266 iwm_dma_contig_free(&ring->desc_dma);
1267 iwm_dma_contig_free(&ring->cmd_dma); 1267 iwm_dma_contig_free(&ring->cmd_dma);
1268 1268
1269 for (i = 0; i < IWM_TX_RING_COUNT; i++) { 1269 for (i = 0; i < IWM_TX_RING_COUNT; i++) {
1270 struct iwm_tx_data *data = &ring->data[i]; 1270 struct iwm_tx_data *data = &ring->data[i];
1271 1271
1272 if (data->m != NULL) { 1272 if (data->m != NULL) {
1273 bus_dmamap_sync(sc->sc_dmat, data->map, 0, 1273 bus_dmamap_sync(sc->sc_dmat, data->map, 0,
1274 data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE); 1274 data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1275 bus_dmamap_unload(sc->sc_dmat, data->map); 1275 bus_dmamap_unload(sc->sc_dmat, data->map);
1276 m_freem(data->m); 1276 m_freem(data->m);
1277 } 1277 }
1278 if (data->map != NULL) 1278 if (data->map != NULL)
1279 bus_dmamap_destroy(sc->sc_dmat, data->map); 1279 bus_dmamap_destroy(sc->sc_dmat, data->map);
1280 } 1280 }
1281} 1281}
1282 1282
1283/* 1283/*
1284 * High-level hardware frobbing routines 1284 * High-level hardware frobbing routines
1285 */ 1285 */
1286 1286
1287static void 1287static void
1288iwm_enable_rfkill_int(struct iwm_softc *sc) 1288iwm_enable_rfkill_int(struct iwm_softc *sc)
1289{ 1289{
1290 sc->sc_intmask = IWM_CSR_INT_BIT_RF_KILL; 1290 sc->sc_intmask = IWM_CSR_INT_BIT_RF_KILL;
1291 IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask); 1291 IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);
1292} 1292}
1293 1293
1294static int 1294static int
1295iwm_check_rfkill(struct iwm_softc *sc) 1295iwm_check_rfkill(struct iwm_softc *sc)
1296{ 1296{
1297 uint32_t v; 1297 uint32_t v;
1298 int s; 1298 int s;
1299 int rv; 1299 int rv;
1300 1300
1301 s = splnet(); 1301 s = splnet();
1302 1302
1303 /* 1303 /*
1304 * "documentation" is not really helpful here: 1304 * "documentation" is not really helpful here:
1305 * 27: HW_RF_KILL_SW 1305 * 27: HW_RF_KILL_SW
1306 * Indicates state of (platform's) hardware RF-Kill switch 1306 * Indicates state of (platform's) hardware RF-Kill switch
1307 * 1307 *
1308 * But apparently when it's off, it's on ... 1308 * But apparently when it's off, it's on ...
1309 */ 1309 */
1310 v = IWM_READ(sc, IWM_CSR_GP_CNTRL); 1310 v = IWM_READ(sc, IWM_CSR_GP_CNTRL);
1311 rv = (v & IWM_CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) == 0; 1311 rv = (v & IWM_CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) == 0;
1312 if (rv) { 1312 if (rv) {
1313 sc->sc_flags |= IWM_FLAG_RFKILL; 1313 sc->sc_flags |= IWM_FLAG_RFKILL;
1314 } else { 1314 } else {
1315 sc->sc_flags &= ~IWM_FLAG_RFKILL; 1315 sc->sc_flags &= ~IWM_FLAG_RFKILL;
1316 } 1316 }
1317 1317
1318 splx(s); 1318 splx(s);
1319 return rv; 1319 return rv;
1320} 1320}
1321 1321
1322static void 1322static void
1323iwm_enable_interrupts(struct iwm_softc *sc) 1323iwm_enable_interrupts(struct iwm_softc *sc)
1324{ 1324{
1325 sc->sc_intmask = IWM_CSR_INI_SET_MASK; 1325 sc->sc_intmask = IWM_CSR_INI_SET_MASK;
1326 IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask); 1326 IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);
1327} 1327}
1328 1328
1329static void 1329static void
1330iwm_restore_interrupts(struct iwm_softc *sc) 1330iwm_restore_interrupts(struct iwm_softc *sc)
1331{ 1331{
1332 IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask); 1332 IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);
1333} 1333}
1334 1334
1335static void 1335static void
1336iwm_disable_interrupts(struct iwm_softc *sc) 1336iwm_disable_interrupts(struct iwm_softc *sc)
1337{ 1337{
1338 int s = splnet(); 1338 int s = splnet();
1339 1339
1340 /* disable interrupts */ 1340 /* disable interrupts */
1341 IWM_WRITE(sc, IWM_CSR_INT_MASK, 0); 1341 IWM_WRITE(sc, IWM_CSR_INT_MASK, 0);
1342 1342
1343 /* acknowledge all interrupts */ 1343 /* acknowledge all interrupts */
1344 IWM_WRITE(sc, IWM_CSR_INT, ~0); 1344 IWM_WRITE(sc, IWM_CSR_INT, ~0);
1345 IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, ~0); 1345 IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, ~0);
1346 1346
1347 splx(s); 1347 splx(s);
1348} 1348}
1349 1349
1350static void 1350static void
1351iwm_ict_reset(struct iwm_softc *sc) 1351iwm_ict_reset(struct iwm_softc *sc)
1352{ 1352{
1353 iwm_disable_interrupts(sc); 1353 iwm_disable_interrupts(sc);
1354 1354
1355 /* Reset ICT table. */ 1355 /* Reset ICT table. */
1356 memset(sc->ict_dma.vaddr, 0, IWM_ICT_SIZE); 1356 memset(sc->ict_dma.vaddr, 0, IWM_ICT_SIZE);
1357 sc->ict_cur = 0; 1357 sc->ict_cur = 0;
1358 1358
1359 /* Set physical address of ICT table (4KB aligned). */ 1359 /* Set physical address of ICT table (4KB aligned). */
1360 IWM_WRITE(sc, IWM_CSR_DRAM_INT_TBL_REG, 1360 IWM_WRITE(sc, IWM_CSR_DRAM_INT_TBL_REG,
1361 IWM_CSR_DRAM_INT_TBL_ENABLE 1361 IWM_CSR_DRAM_INT_TBL_ENABLE
1362 | IWM_CSR_DRAM_INIT_TBL_WRAP_CHECK 1362 | IWM_CSR_DRAM_INIT_TBL_WRAP_CHECK
1363 | sc->ict_dma.paddr >> IWM_ICT_PADDR_SHIFT); 1363 | sc->ict_dma.paddr >> IWM_ICT_PADDR_SHIFT);
1364 1364
1365 /* Switch to ICT interrupt mode in driver. */ 1365 /* Switch to ICT interrupt mode in driver. */
1366 sc->sc_flags |= IWM_FLAG_USE_ICT; 1366 sc->sc_flags |= IWM_FLAG_USE_ICT;
1367 1367
1368 /* Re-enable interrupts. */ 1368 /* Re-enable interrupts. */
1369 IWM_WRITE(sc, IWM_CSR_INT, ~0); 1369 IWM_WRITE(sc, IWM_CSR_INT, ~0);
1370 iwm_enable_interrupts(sc); 1370 iwm_enable_interrupts(sc);
1371} 1371}
1372 1372
1373#define IWM_HW_READY_TIMEOUT 50 1373#define IWM_HW_READY_TIMEOUT 50
1374static int 1374static int
1375iwm_set_hw_ready(struct iwm_softc *sc) 1375iwm_set_hw_ready(struct iwm_softc *sc)
1376{ 1376{
1377 IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG, 1377 IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
1378 IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); 1378 IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
1379 1379
1380 return iwm_poll_bit(sc, IWM_CSR_HW_IF_CONFIG_REG, 1380 return iwm_poll_bit(sc, IWM_CSR_HW_IF_CONFIG_REG,
1381 IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, 1381 IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
1382 IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, 1382 IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
1383 IWM_HW_READY_TIMEOUT); 1383 IWM_HW_READY_TIMEOUT);
1384} 1384}
1385#undef IWM_HW_READY_TIMEOUT 1385#undef IWM_HW_READY_TIMEOUT
1386 1386
1387static int 1387static int
1388iwm_prepare_card_hw(struct iwm_softc *sc) 1388iwm_prepare_card_hw(struct iwm_softc *sc)
1389{ 1389{
1390 int rv = 0; 1390 int rv = 0;
1391 int t = 0; 1391 int t = 0;
1392 1392
1393 if (iwm_set_hw_ready(sc)) 1393 if (iwm_set_hw_ready(sc))
1394 goto out; 1394 goto out;
1395 1395
1396 /* If HW is not ready, prepare the conditions to check again */ 1396 /* If HW is not ready, prepare the conditions to check again */
1397 IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG, 1397 IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
1398 IWM_CSR_HW_IF_CONFIG_REG_PREPARE); 1398 IWM_CSR_HW_IF_CONFIG_REG_PREPARE);
1399 1399
1400 do { 1400 do {
1401 if (iwm_set_hw_ready(sc)) 1401 if (iwm_set_hw_ready(sc))
1402 goto out; 1402 goto out;
1403 DELAY(200); 1403 DELAY(200);
1404 t += 200; 1404 t += 200;
1405 } while (t < 150000); 1405 } while (t < 150000);
1406 1406
1407 rv = ETIMEDOUT; 1407 rv = ETIMEDOUT;
1408 1408
1409 out: 1409 out:
1410 return rv; 1410 return rv;
1411} 1411}
1412 1412
1413static void 1413static void
1414iwm_apm_config(struct iwm_softc *sc) 1414iwm_apm_config(struct iwm_softc *sc)
1415{ 1415{
1416 pcireg_t reg; 1416 pcireg_t reg;
1417 1417
1418 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 1418 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
1419 sc->sc_cap_off + PCIE_LCSR); 1419 sc->sc_cap_off + PCIE_LCSR);
1420 if (reg & PCIE_LCSR_ASPM_L1) { 1420 if (reg & PCIE_LCSR_ASPM_L1) {
1421 /* Um the Linux driver prints "Disabling L0S for this one ... */ 1421 /* Um the Linux driver prints "Disabling L0S for this one ... */
1422 IWM_SETBITS(sc, IWM_CSR_GIO_REG, 1422 IWM_SETBITS(sc, IWM_CSR_GIO_REG,
1423 IWM_CSR_GIO_REG_VAL_L0S_ENABLED); 1423 IWM_CSR_GIO_REG_VAL_L0S_ENABLED);
1424 } else { 1424 } else {
1425 /* ... and "Enabling" here */ 1425 /* ... and "Enabling" here */
1426 IWM_CLRBITS(sc, IWM_CSR_GIO_REG, 1426 IWM_CLRBITS(sc, IWM_CSR_GIO_REG,
1427 IWM_CSR_GIO_REG_VAL_L0S_ENABLED); 1427 IWM_CSR_GIO_REG_VAL_L0S_ENABLED);
1428 } 1428 }
1429} 1429}
1430 1430
1431/* 1431/*
1432 * Start up NIC's basic functionality after it has been reset 1432 * Start up NIC's basic functionality after it has been reset
1433 * (e.g. after platform boot, or shutdown via iwm_pcie_apm_stop()) 1433 * (e.g. after platform boot, or shutdown via iwm_pcie_apm_stop())
1434 * NOTE: This does not load uCode nor start the embedded processor 1434 * NOTE: This does not load uCode nor start the embedded processor
1435 */ 1435 */
1436static int 1436static int
1437iwm_apm_init(struct iwm_softc *sc) 1437iwm_apm_init(struct iwm_softc *sc)
1438{ 1438{
1439 int error = 0; 1439 int error = 0;
1440 1440
1441 DPRINTF(("iwm apm start\n")); 1441 DPRINTF(("iwm apm start\n"));
1442 1442
1443 /* Disable L0S exit timer (platform NMI Work/Around) */ 1443 /* Disable L0S exit timer (platform NMI Work/Around) */
1444 IWM_SETBITS(sc, IWM_CSR_GIO_CHICKEN_BITS, 1444 IWM_SETBITS(sc, IWM_CSR_GIO_CHICKEN_BITS,
1445 IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); 1445 IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
1446 1446
1447 /* 1447 /*
1448 * Disable L0s without affecting L1; 1448 * Disable L0s without affecting L1;
1449 * don't wait for ICH L0s (ICH bug W/A) 1449 * don't wait for ICH L0s (ICH bug W/A)
1450 */ 1450 */
1451 IWM_SETBITS(sc, IWM_CSR_GIO_CHICKEN_BITS, 1451 IWM_SETBITS(sc, IWM_CSR_GIO_CHICKEN_BITS,
1452 IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); 1452 IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
1453 1453
1454 /* Set FH wait threshold to maximum (HW error during stress W/A) */ 1454 /* Set FH wait threshold to maximum (HW error during stress W/A) */
1455 IWM_SETBITS(sc, IWM_CSR_DBG_HPET_MEM_REG, IWM_CSR_DBG_HPET_MEM_REG_VAL); 1455 IWM_SETBITS(sc, IWM_CSR_DBG_HPET_MEM_REG, IWM_CSR_DBG_HPET_MEM_REG_VAL);
1456 1456
1457 /* 1457 /*
1458 * Enable HAP INTA (interrupt from management bus) to 1458 * Enable HAP INTA (interrupt from management bus) to
1459 * wake device's PCI Express link L1a -> L0s 1459 * wake device's PCI Express link L1a -> L0s
1460 */ 1460 */
1461 IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG, 1461 IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
1462 IWM_CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); 1462 IWM_CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
1463 1463
1464 iwm_apm_config(sc); 1464 iwm_apm_config(sc);
1465 1465
1466#if 0 /* not for 7k */ 1466#if 0 /* not for 7k */
1467 /* Configure analog phase-lock-loop before activating to D0A */ 1467 /* Configure analog phase-lock-loop before activating to D0A */
1468 if (trans->cfg->base_params->pll_cfg_val) 1468 if (trans->cfg->base_params->pll_cfg_val)
1469 IWM_SETBITS(trans, IWM_CSR_ANA_PLL_CFG, 1469 IWM_SETBITS(trans, IWM_CSR_ANA_PLL_CFG,
1470 trans->cfg->base_params->pll_cfg_val); 1470 trans->cfg->base_params->pll_cfg_val);
1471#endif 1471#endif
1472 1472
1473 /* 1473 /*
1474 * Set "initialization complete" bit to move adapter from 1474 * Set "initialization complete" bit to move adapter from
1475 * D0U* --> D0A* (powered-up active) state. 1475 * D0U* --> D0A* (powered-up active) state.
1476 */ 1476 */
1477 IWM_SETBITS(sc, IWM_CSR_GP_CNTRL, IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE); 1477 IWM_SETBITS(sc, IWM_CSR_GP_CNTRL, IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
1478 1478
1479 /* 1479 /*
1480 * Wait for clock stabilization; once stabilized, access to 1480 * Wait for clock stabilization; once stabilized, access to
1481 * device-internal resources is supported, e.g. iwm_write_prph() 1481 * device-internal resources is supported, e.g. iwm_write_prph()
1482 * and accesses to uCode SRAM. 1482 * and accesses to uCode SRAM.
1483 */ 1483 */
1484 if (!iwm_poll_bit(sc, IWM_CSR_GP_CNTRL, 1484 if (!iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
1485 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 1485 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
1486 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000)) { 1486 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000)) {
1487 aprint_error_dev(sc->sc_dev, 1487 aprint_error_dev(sc->sc_dev,
1488 "timeout waiting for clock stabilization\n"); 1488 "timeout waiting for clock stabilization\n");
1489 goto out; 1489 goto out;
1490 } 1490 }
1491 1491
1492 /* 1492 if (sc->host_interrupt_operation_mode) {
1493 * This is a bit of an abuse - This is needed for 7260 / 3160 1493 /*
1494 * only check host_interrupt_operation_mode even if this is 1494 * This is a bit of an abuse - This is needed for 7260 / 3160
1495 * not related to host_interrupt_operation_mode. 1495 * only check host_interrupt_operation_mode even if this is
1496 * 1496 * not related to host_interrupt_operation_mode.
1497 * Enable the oscillator to count wake up time for L1 exit. This 1497 *
1498 * consumes slightly more power (100uA) - but allows to be sure 1498 * Enable the oscillator to count wake up time for L1 exit. This
1499 * that we wake up from L1 on time. 1499 * consumes slightly more power (100uA) - but allows to be sure
1500 * 1500 * that we wake up from L1 on time.
1501 * This looks weird: read twice the same register, discard the 1501 *
1502 * value, set a bit, and yet again, read that same register 1502 * This looks weird: read twice the same register, discard the
1503 * just to discard the value. But that's the way the hardware 1503 * value, set a bit, and yet again, read that same register
1504 * seems to like it. 1504 * just to discard the value. But that's the way the hardware
1505 */ 1505 * seems to like it.
1506 iwm_read_prph(sc, IWM_OSC_CLK); 1506 */
1507 iwm_read_prph(sc, IWM_OSC_CLK); 1507 iwm_read_prph(sc, IWM_OSC_CLK);
1508 iwm_set_bits_prph(sc, IWM_OSC_CLK, IWM_OSC_CLK_FORCE_CONTROL); 1508 iwm_read_prph(sc, IWM_OSC_CLK);
1509 iwm_read_prph(sc, IWM_OSC_CLK); 1509 iwm_set_bits_prph(sc, IWM_OSC_CLK, IWM_OSC_CLK_FORCE_CONTROL);
1510 iwm_read_prph(sc, IWM_OSC_CLK); 1510 iwm_read_prph(sc, IWM_OSC_CLK);
 1511 iwm_read_prph(sc, IWM_OSC_CLK);
 1512 }
1511 1513
1512 /* 1514 /*
1513 * Enable DMA clock and wait for it to stabilize. 1515 * Enable DMA clock and wait for it to stabilize.
1514 * 1516 *
1515 * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits 1517 * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits
1516 * do not disable clocks. This preserves any hardware bits already 1518 * do not disable clocks. This preserves any hardware bits already
1517 * set by default in "CLK_CTRL_REG" after reset. 1519 * set by default in "CLK_CTRL_REG" after reset.
1518 */ 1520 */
1519 iwm_write_prph(sc, IWM_APMG_CLK_EN_REG, IWM_APMG_CLK_VAL_DMA_CLK_RQT); 1521 iwm_write_prph(sc, IWM_APMG_CLK_EN_REG, IWM_APMG_CLK_VAL_DMA_CLK_RQT);
1520 //kpause("iwmapm", 0, mstohz(20), NULL); 1522 //kpause("iwmapm", 0, mstohz(20), NULL);
1521 DELAY(20); 1523 DELAY(20);
1522 1524
1523 /* Disable L1-Active */ 1525 /* Disable L1-Active */
1524 iwm_set_bits_prph(sc, IWM_APMG_PCIDEV_STT_REG, 1526 iwm_set_bits_prph(sc, IWM_APMG_PCIDEV_STT_REG,
1525 IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS); 1527 IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
1526 1528
1527 /* Clear the interrupt in APMG if the NIC is in RFKILL */ 1529 /* Clear the interrupt in APMG if the NIC is in RFKILL */
1528 iwm_write_prph(sc, IWM_APMG_RTC_INT_STT_REG, 1530 iwm_write_prph(sc, IWM_APMG_RTC_INT_STT_REG,
1529 IWM_APMG_RTC_INT_STT_RFKILL); 1531 IWM_APMG_RTC_INT_STT_RFKILL);
1530 1532
1531 out: 1533 out:
1532 if (error) 1534 if (error)
1533 aprint_error_dev(sc->sc_dev, "apm init error %d\n", error); 1535 aprint_error_dev(sc->sc_dev, "apm init error %d\n", error);
1534 return error; 1536 return error;
1535} 1537}
1536 1538
1537/* iwlwifi/pcie/trans.c */ 1539/* iwlwifi/pcie/trans.c */
1538static void 1540static void
1539iwm_apm_stop(struct iwm_softc *sc) 1541iwm_apm_stop(struct iwm_softc *sc)
1540{ 1542{
1541 /* stop device's busmaster DMA activity */ 1543 /* stop device's busmaster DMA activity */
1542 IWM_SETBITS(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_STOP_MASTER); 1544 IWM_SETBITS(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_STOP_MASTER);
1543 1545
1544 if (!iwm_poll_bit(sc, IWM_CSR_RESET, 1546 if (!iwm_poll_bit(sc, IWM_CSR_RESET,
1545 IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED, 1547 IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED,
1546 IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED, 100)) 1548 IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED, 100))
1547 aprint_error_dev(sc->sc_dev, "timeout waiting for master\n"); 1549 aprint_error_dev(sc->sc_dev, "timeout waiting for master\n");
1548 DPRINTF(("iwm apm stop\n")); 1550 DPRINTF(("iwm apm stop\n"));
1549} 1551}
1550 1552
1551/* iwlwifi pcie/trans.c */ 1553/* iwlwifi pcie/trans.c */
1552static int 1554static int
1553iwm_start_hw(struct iwm_softc *sc) 1555iwm_start_hw(struct iwm_softc *sc)
1554{ 1556{
1555 int error; 1557 int error;
1556 1558
1557 if ((error = iwm_prepare_card_hw(sc)) != 0) 1559 if ((error = iwm_prepare_card_hw(sc)) != 0)
1558 return error; 1560 return error;
1559 1561
1560 /* Reset the entire device */ 1562 /* Reset the entire device */
1561 IWM_WRITE(sc, IWM_CSR_RESET, 1563 IWM_WRITE(sc, IWM_CSR_RESET,
1562 IWM_CSR_RESET_REG_FLAG_SW_RESET | 1564 IWM_CSR_RESET_REG_FLAG_SW_RESET |
1563 IWM_CSR_RESET_REG_FLAG_NEVO_RESET); 1565 IWM_CSR_RESET_REG_FLAG_NEVO_RESET);
1564 DELAY(10); 1566 DELAY(10);
1565 1567
1566 if ((error = iwm_apm_init(sc)) != 0) 1568 if ((error = iwm_apm_init(sc)) != 0)
1567 return error; 1569 return error;
1568 1570
1569 iwm_enable_rfkill_int(sc); 1571 iwm_enable_rfkill_int(sc);
1570 iwm_check_rfkill(sc); 1572 iwm_check_rfkill(sc);
1571 1573
1572 return 0; 1574 return 0;
1573} 1575}
1574 1576
1575/* iwlwifi pcie/trans.c */ 1577/* iwlwifi pcie/trans.c */
1576 1578
1577static void 1579static void
1578iwm_stop_device(struct iwm_softc *sc) 1580iwm_stop_device(struct iwm_softc *sc)
1579{ 1581{
1580 int chnl, ntries; 1582 int chnl, ntries;
1581 int qid; 1583 int qid;
1582 1584
1583 /* tell the device to stop sending interrupts */ 1585 /* tell the device to stop sending interrupts */
1584 iwm_disable_interrupts(sc); 1586 iwm_disable_interrupts(sc);
1585 1587
1586 /* device going down, Stop using ICT table */ 1588 /* device going down, Stop using ICT table */
1587 sc->sc_flags &= ~IWM_FLAG_USE_ICT; 1589 sc->sc_flags &= ~IWM_FLAG_USE_ICT;
1588 1590
1589 /* stop tx and rx. tx and rx bits, as usual, are from if_iwn */ 1591 /* stop tx and rx. tx and rx bits, as usual, are from if_iwn */
1590 1592
1591 iwm_write_prph(sc, IWM_SCD_TXFACT, 0); 1593 iwm_write_prph(sc, IWM_SCD_TXFACT, 0);
1592 1594
1593 /* Stop all DMA channels. */ 1595 /* Stop all DMA channels. */
1594 if (iwm_nic_lock(sc)) { 1596 if (iwm_nic_lock(sc)) {
1595 for (chnl = 0; chnl < IWM_FH_TCSR_CHNL_NUM; chnl++) { 1597 for (chnl = 0; chnl < IWM_FH_TCSR_CHNL_NUM; chnl++) {
1596 IWM_WRITE(sc, 1598 IWM_WRITE(sc,
1597 IWM_FH_TCSR_CHNL_TX_CONFIG_REG(chnl), 0); 1599 IWM_FH_TCSR_CHNL_TX_CONFIG_REG(chnl), 0);
1598 for (ntries = 0; ntries < 200; ntries++) { 1600 for (ntries = 0; ntries < 200; ntries++) {
1599 uint32_t r; 1601 uint32_t r;
1600 1602
1601 r = IWM_READ(sc, IWM_FH_TSSR_TX_STATUS_REG); 1603 r = IWM_READ(sc, IWM_FH_TSSR_TX_STATUS_REG);
1602 if (r & IWM_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE( 1604 if (r & IWM_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(
1603 chnl)) 1605 chnl))
1604 break; 1606 break;
1605 DELAY(20); 1607 DELAY(20);
1606 } 1608 }
1607 } 1609 }
1608 iwm_nic_unlock(sc); 1610 iwm_nic_unlock(sc);
1609 } 1611 }
1610 1612
1611 /* Stop RX ring. */ 1613 /* Stop RX ring. */
1612 iwm_reset_rx_ring(sc, &sc->rxq); 1614 iwm_reset_rx_ring(sc, &sc->rxq);
1613 1615
1614 /* Reset all TX rings. */ 1616 /* Reset all TX rings. */
1615 for (qid = 0; qid < __arraycount(sc->txq); qid++) 1617 for (qid = 0; qid < __arraycount(sc->txq); qid++)
1616 iwm_reset_tx_ring(sc, &sc->txq[qid]); 1618 iwm_reset_tx_ring(sc, &sc->txq[qid]);
1617 1619
1618 /* 1620 /*
1619 * Power-down device's busmaster DMA clocks 1621 * Power-down device's busmaster DMA clocks
1620 */ 1622 */
1621 iwm_write_prph(sc, IWM_APMG_CLK_DIS_REG, IWM_APMG_CLK_VAL_DMA_CLK_RQT); 1623 iwm_write_prph(sc, IWM_APMG_CLK_DIS_REG, IWM_APMG_CLK_VAL_DMA_CLK_RQT);
1622 DELAY(5); 1624 DELAY(5);
1623 1625
1624 /* Make sure (redundant) we've released our request to stay awake */ 1626 /* Make sure (redundant) we've released our request to stay awake */
1625 IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL, 1627 IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
1626 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 1628 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1627 1629
1628 /* Stop the device, and put it in low power state */ 1630 /* Stop the device, and put it in low power state */
1629 iwm_apm_stop(sc); 1631 iwm_apm_stop(sc);
1630 1632
1631 /* Upon stop, the APM issues an interrupt if HW RF kill is set. 1633 /* Upon stop, the APM issues an interrupt if HW RF kill is set.
1632 * Clean again the interrupt here 1634 * Clean again the interrupt here
1633 */ 1635 */
1634 iwm_disable_interrupts(sc); 1636 iwm_disable_interrupts(sc);
1635 /* stop and reset the on-board processor */ 1637 /* stop and reset the on-board processor */
1636 IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_NEVO_RESET); 1638 IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_NEVO_RESET);
1637 1639
1638 /* 1640 /*
1639 * Even if we stop the HW, we still want the RF kill 1641 * Even if we stop the HW, we still want the RF kill
1640 * interrupt 1642 * interrupt
1641 */ 1643 */
1642 iwm_enable_rfkill_int(sc); 1644 iwm_enable_rfkill_int(sc);
1643 iwm_check_rfkill(sc); 1645 iwm_check_rfkill(sc);
1644} 1646}
1645 1647
1646/* iwlwifi pcie/trans.c (always main power) */ 1648/* iwlwifi pcie/trans.c (always main power) */
1647static void 1649static void
1648iwm_set_pwr(struct iwm_softc *sc) 1650iwm_set_pwr(struct iwm_softc *sc)
1649{ 1651{
1650 iwm_set_bits_mask_prph(sc, IWM_APMG_PS_CTRL_REG, 1652 iwm_set_bits_mask_prph(sc, IWM_APMG_PS_CTRL_REG,
1651 IWM_APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, ~IWM_APMG_PS_CTRL_MSK_PWR_SRC); 1653 IWM_APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, ~IWM_APMG_PS_CTRL_MSK_PWR_SRC);
1652} 1654}
1653 1655
1654/* iwlwifi: mvm/ops.c */ 1656/* iwlwifi: mvm/ops.c */
1655static void 1657static void
1656iwm_mvm_nic_config(struct iwm_softc *sc) 1658iwm_mvm_nic_config(struct iwm_softc *sc)
1657{ 1659{
1658 uint8_t radio_cfg_type, radio_cfg_step, radio_cfg_dash; 1660 uint8_t radio_cfg_type, radio_cfg_step, radio_cfg_dash;
1659 uint32_t reg_val = 0; 1661 uint32_t reg_val = 0;
1660 1662
1661 radio_cfg_type = (sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RADIO_TYPE) >> 1663 radio_cfg_type = (sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RADIO_TYPE) >>
1662 IWM_FW_PHY_CFG_RADIO_TYPE_POS; 1664 IWM_FW_PHY_CFG_RADIO_TYPE_POS;
1663 radio_cfg_step = (sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RADIO_STEP) >> 1665 radio_cfg_step = (sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RADIO_STEP) >>
1664 IWM_FW_PHY_CFG_RADIO_STEP_POS; 1666 IWM_FW_PHY_CFG_RADIO_STEP_POS;
1665 radio_cfg_dash = (sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RADIO_DASH) >> 1667 radio_cfg_dash = (sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RADIO_DASH) >>
1666 IWM_FW_PHY_CFG_RADIO_DASH_POS; 1668 IWM_FW_PHY_CFG_RADIO_DASH_POS;
1667 1669
1668 /* SKU control */ 1670 /* SKU control */
1669 reg_val |= IWM_CSR_HW_REV_STEP(sc->sc_hw_rev) << 1671 reg_val |= IWM_CSR_HW_REV_STEP(sc->sc_hw_rev) <<
1670 IWM_CSR_HW_IF_CONFIG_REG_POS_MAC_STEP; 1672 IWM_CSR_HW_IF_CONFIG_REG_POS_MAC_STEP;
1671 reg_val |= IWM_CSR_HW_REV_DASH(sc->sc_hw_rev) << 1673 reg_val |= IWM_CSR_HW_REV_DASH(sc->sc_hw_rev) <<
1672 IWM_CSR_HW_IF_CONFIG_REG_POS_MAC_DASH; 1674 IWM_CSR_HW_IF_CONFIG_REG_POS_MAC_DASH;
1673 1675
1674 /* radio configuration */ 1676 /* radio configuration */
1675 reg_val |= radio_cfg_type << IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE; 1677 reg_val |= radio_cfg_type << IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE;
1676 reg_val |= radio_cfg_step << IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_STEP; 1678 reg_val |= radio_cfg_step << IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_STEP;
1677 reg_val |= radio_cfg_dash << IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_DASH; 1679 reg_val |= radio_cfg_dash << IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_DASH;
1678 1680
1679 IWM_WRITE(sc, IWM_CSR_HW_IF_CONFIG_REG, reg_val); 1681 IWM_WRITE(sc, IWM_CSR_HW_IF_CONFIG_REG, reg_val);
1680 1682
1681 DPRINTF(("Radio type=0x%x-0x%x-0x%x\n", radio_cfg_type, 1683 DPRINTF(("Radio type=0x%x-0x%x-0x%x\n", radio_cfg_type,
1682 radio_cfg_step, radio_cfg_dash)); 1684 radio_cfg_step, radio_cfg_dash));
1683 1685
1684 /* 1686 /*
1685 * W/A : NIC is stuck in a reset state after Early PCIe power off 1687 * W/A : NIC is stuck in a reset state after Early PCIe power off
1686 * (PCIe power is lost before PERST# is asserted), causing ME FW 1688 * (PCIe power is lost before PERST# is asserted), causing ME FW
1687 * to lose ownership and not being able to obtain it back. 1689 * to lose ownership and not being able to obtain it back.
1688 */ 1690 */
1689 iwm_set_bits_mask_prph(sc, IWM_APMG_PS_CTRL_REG, 1691 iwm_set_bits_mask_prph(sc, IWM_APMG_PS_CTRL_REG,
1690 IWM_APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, 1692 IWM_APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
1691 ~IWM_APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); 1693 ~IWM_APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
1692} 1694}
1693 1695
1694static int 1696static int
1695iwm_nic_rx_init(struct iwm_softc *sc) 1697iwm_nic_rx_init(struct iwm_softc *sc)
1696{ 1698{
1697 if (!iwm_nic_lock(sc)) 1699 if (!iwm_nic_lock(sc))
1698 return EBUSY; 1700 return EBUSY;
1699 1701
1700 /* 1702 /*
1701 * Initialize RX ring. This is from the iwn driver. 1703 * Initialize RX ring. This is from the iwn driver.
1702 */ 1704 */
1703 memset(sc->rxq.stat, 0, sizeof(*sc->rxq.stat)); 1705 memset(sc->rxq.stat, 0, sizeof(*sc->rxq.stat));
1704 1706
1705 /* stop DMA */ 1707 /* stop DMA */
1706 IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); 1708 IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
1707 IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_RBDCB_WPTR, 0); 1709 IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_RBDCB_WPTR, 0);
1708 IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_FLUSH_RB_REQ, 0); 1710 IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_FLUSH_RB_REQ, 0);
1709 IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_RDPTR, 0); 1711 IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_RDPTR, 0);
1710 IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); 1712 IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
1711 1713
1712 /* Set physical address of RX ring (256-byte aligned). */ 1714 /* Set physical address of RX ring (256-byte aligned). */
1713 IWM_WRITE(sc, 1715 IWM_WRITE(sc,
1714 IWM_FH_RSCSR_CHNL0_RBDCB_BASE_REG, sc->rxq.desc_dma.paddr >> 8); 1716 IWM_FH_RSCSR_CHNL0_RBDCB_BASE_REG, sc->rxq.desc_dma.paddr >> 8);
1715 1717
1716 /* Set physical address of RX status (16-byte aligned). */ 1718 /* Set physical address of RX status (16-byte aligned). */
1717 IWM_WRITE(sc, 1719 IWM_WRITE(sc,
1718 IWM_FH_RSCSR_CHNL0_STTS_WPTR_REG, sc->rxq.stat_dma.paddr >> 4); 1720 IWM_FH_RSCSR_CHNL0_STTS_WPTR_REG, sc->rxq.stat_dma.paddr >> 4);
1719 1721
1720 /* Enable RX. */ 1722 /* Enable RX. */
1721 /* 1723 /*
1722 * Note: Linux driver also sets this: 1724 * Note: Linux driver also sets this:
1723 * (IWM_RX_RB_TIMEOUT << IWM_FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS) | 1725 * (IWM_RX_RB_TIMEOUT << IWM_FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS) |
1724 * 1726 *
1725 * It causes weird behavior. YMMV. 1727 * It causes weird behavior. YMMV.
1726 */ 1728 */
1727 IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG, 1729 IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG,
1728 IWM_FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | 1730 IWM_FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
1729 IWM_FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | /* HW bug */ 1731 IWM_FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | /* HW bug */
1730 IWM_FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | 1732 IWM_FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
1731 IWM_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K | 1733 IWM_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K |
1732 IWM_RX_QUEUE_SIZE_LOG << IWM_FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS); 1734 IWM_RX_QUEUE_SIZE_LOG << IWM_FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS);
1733 1735
1734 IWM_WRITE_1(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_TIMEOUT_DEF); 1736 IWM_WRITE_1(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_TIMEOUT_DEF);
1735 IWM_SETBITS(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_OPER_MODE); 1737
 1738 /* W/A for interrupt coalescing bug in 7260 and 3160 */
 1739 if (sc->host_interrupt_operation_mode)
 1740 IWM_SETBITS(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_OPER_MODE);
1736 1741
1737 /* 1742 /*
1738 * Thus sayeth el jefe (iwlwifi) via a comment: 1743 * Thus sayeth el jefe (iwlwifi) via a comment:
1739 * 1744 *
1740 * This value should initially be 0 (before preparing any 1745 * This value should initially be 0 (before preparing any
1741 * RBs), should be 8 after preparing the first 8 RBs (for example) 1746 * RBs), should be 8 after preparing the first 8 RBs (for example)
1742 */ 1747 */
1743 IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_WPTR, 8); 1748 IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_WPTR, 8);
1744 1749
1745 iwm_nic_unlock(sc); 1750 iwm_nic_unlock(sc);
1746 1751
1747 return 0; 1752 return 0;
1748} 1753}
1749 1754
1750static int 1755static int
1751iwm_nic_tx_init(struct iwm_softc *sc) 1756iwm_nic_tx_init(struct iwm_softc *sc)
1752{ 1757{
1753 int qid; 1758 int qid;
1754 1759
1755 if (!iwm_nic_lock(sc)) 1760 if (!iwm_nic_lock(sc))
1756 return EBUSY; 1761 return EBUSY;
1757 1762
1758 /* Deactivate TX scheduler. */ 1763 /* Deactivate TX scheduler. */
1759 iwm_write_prph(sc, IWM_SCD_TXFACT, 0); 1764 iwm_write_prph(sc, IWM_SCD_TXFACT, 0);
1760 1765
1761 /* Set physical address of "keep warm" page (16-byte aligned). */ 1766 /* Set physical address of "keep warm" page (16-byte aligned). */
1762 IWM_WRITE(sc, IWM_FH_KW_MEM_ADDR_REG, sc->kw_dma.paddr >> 4); 1767 IWM_WRITE(sc, IWM_FH_KW_MEM_ADDR_REG, sc->kw_dma.paddr >> 4);
1763 1768
1764 /* Initialize TX rings. */ 1769 /* Initialize TX rings. */
1765 for (qid = 0; qid < __arraycount(sc->txq); qid++) { 1770 for (qid = 0; qid < __arraycount(sc->txq); qid++) {
1766 struct iwm_tx_ring *txq = &sc->txq[qid]; 1771 struct iwm_tx_ring *txq = &sc->txq[qid];
1767 1772
1768 /* Set physical address of TX ring (256-byte aligned). */ 1773 /* Set physical address of TX ring (256-byte aligned). */
1769 IWM_WRITE(sc, IWM_FH_MEM_CBBC_QUEUE(qid), 1774 IWM_WRITE(sc, IWM_FH_MEM_CBBC_QUEUE(qid),
1770 txq->desc_dma.paddr >> 8); 1775 txq->desc_dma.paddr >> 8);
1771 DPRINTF(("loading ring %d descriptors (%p) at %"PRIxMAX"\n", 1776 DPRINTF(("loading ring %d descriptors (%p) at %"PRIxMAX"\n",
1772 qid, txq->desc, (uintmax_t)(txq->desc_dma.paddr >> 8))); 1777 qid, txq->desc, (uintmax_t)(txq->desc_dma.paddr >> 8)));
1773 } 1778 }
1774 iwm_nic_unlock(sc); 1779 iwm_nic_unlock(sc);
1775 1780
1776 return 0; 1781 return 0;
1777} 1782}
1778 1783
1779static int 1784static int
1780iwm_nic_init(struct iwm_softc *sc) 1785iwm_nic_init(struct iwm_softc *sc)
1781{ 1786{
1782 int error; 1787 int error;
1783 1788
1784 iwm_apm_init(sc); 1789 iwm_apm_init(sc);
1785 iwm_set_pwr(sc); 1790 iwm_set_pwr(sc);
1786 1791
1787 iwm_mvm_nic_config(sc); 1792 iwm_mvm_nic_config(sc);
1788 1793
1789 if ((error = iwm_nic_rx_init(sc)) != 0) 1794 if ((error = iwm_nic_rx_init(sc)) != 0)
1790 return error; 1795 return error;
1791 1796
1792 /* 1797 /*
1793 * Ditto for TX, from iwn 1798 * Ditto for TX, from iwn
1794 */ 1799 */
1795 if ((error = iwm_nic_tx_init(sc)) != 0) 1800 if ((error = iwm_nic_tx_init(sc)) != 0)
1796 return error; 1801 return error;
1797 1802
1798 DPRINTF(("shadow registers enabled\n")); 1803 DPRINTF(("shadow registers enabled\n"));
1799 IWM_SETBITS(sc, IWM_CSR_MAC_SHADOW_REG_CTRL, 0x800fffff); 1804 IWM_SETBITS(sc, IWM_CSR_MAC_SHADOW_REG_CTRL, 0x800fffff);
1800 1805
1801 return 0; 1806 return 0;
1802} 1807}
1803 1808
1804#if 0 1809#if 0
1805enum iwm_mvm_tx_fifo { 1810enum iwm_mvm_tx_fifo {
1806 IWM_MVM_TX_FIFO_BK = 0, 1811 IWM_MVM_TX_FIFO_BK = 0,
1807 IWM_MVM_TX_FIFO_BE, 1812 IWM_MVM_TX_FIFO_BE,
1808 IWM_MVM_TX_FIFO_VI, 1813 IWM_MVM_TX_FIFO_VI,
1809 IWM_MVM_TX_FIFO_VO, 1814 IWM_MVM_TX_FIFO_VO,
1810 IWM_MVM_TX_FIFO_MCAST = 5, 1815 IWM_MVM_TX_FIFO_MCAST = 5,
1811}; 1816};
1812 1817
1813static const uint8_t iwm_mvm_ac_to_tx_fifo[] = { 1818static const uint8_t iwm_mvm_ac_to_tx_fifo[] = {
1814 IWM_MVM_TX_FIFO_VO, 1819 IWM_MVM_TX_FIFO_VO,
1815 IWM_MVM_TX_FIFO_VI, 1820 IWM_MVM_TX_FIFO_VI,
1816 IWM_MVM_TX_FIFO_BE, 1821 IWM_MVM_TX_FIFO_BE,
1817 IWM_MVM_TX_FIFO_BK, 1822 IWM_MVM_TX_FIFO_BK,
1818}; 1823};
1819#endif 1824#endif
1820 1825
1821static void 1826static void
1822iwm_enable_txq(struct iwm_softc *sc, int qid, int fifo) 1827iwm_enable_txq(struct iwm_softc *sc, int qid, int fifo)
1823{ 1828{
1824 if (!iwm_nic_lock(sc)) { 1829 if (!iwm_nic_lock(sc)) {
1825 DPRINTF(("%s: cannot enable txq %d\n", DEVNAME(sc), qid)); 1830 DPRINTF(("%s: cannot enable txq %d\n", DEVNAME(sc), qid));
1826 return; /* XXX return EBUSY */ 1831 return; /* XXX return EBUSY */
1827 } 1832 }
1828 1833
1829 /* unactivate before configuration */ 1834 /* unactivate before configuration */
1830 iwm_write_prph(sc, IWM_SCD_QUEUE_STATUS_BITS(qid), 1835 iwm_write_prph(sc, IWM_SCD_QUEUE_STATUS_BITS(qid),
1831 (0 << IWM_SCD_QUEUE_STTS_REG_POS_ACTIVE) 1836 (0 << IWM_SCD_QUEUE_STTS_REG_POS_ACTIVE)
1832 | (1 << IWM_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); 1837 | (1 << IWM_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
1833 1838
1834 if (qid != IWM_MVM_CMD_QUEUE) { 1839 if (qid != IWM_MVM_CMD_QUEUE) {
1835 iwm_set_bits_prph(sc, IWM_SCD_QUEUECHAIN_SEL, (1 << qid)); 1840 iwm_set_bits_prph(sc, IWM_SCD_QUEUECHAIN_SEL, (1 << qid));
1836 } 1841 }
1837 1842
1838 iwm_clear_bits_prph(sc, IWM_SCD_AGGR_SEL, (1 << qid)); 1843 iwm_clear_bits_prph(sc, IWM_SCD_AGGR_SEL, (1 << qid));
1839 1844
1840 IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, qid << 8 | 0); 1845 IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, qid << 8 | 0);
1841 iwm_write_prph(sc, IWM_SCD_QUEUE_RDPTR(qid), 0); 1846 iwm_write_prph(sc, IWM_SCD_QUEUE_RDPTR(qid), 0);
1842 1847
1843 iwm_write_mem32(sc, sc->sched_base + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid), 0); 1848 iwm_write_mem32(sc, sc->sched_base + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid), 0);
1844 /* Set scheduler window size and frame limit. */ 1849 /* Set scheduler window size and frame limit. */
1845 iwm_write_mem32(sc, 1850 iwm_write_mem32(sc,
1846 sc->sched_base + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid) + 1851 sc->sched_base + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid) +
1847 sizeof(uint32_t), 1852 sizeof(uint32_t),
1848 ((IWM_FRAME_LIMIT << IWM_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & 1853 ((IWM_FRAME_LIMIT << IWM_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
1849 IWM_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | 1854 IWM_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
1850 ((IWM_FRAME_LIMIT << IWM_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & 1855 ((IWM_FRAME_LIMIT << IWM_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
1851 IWM_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); 1856 IWM_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
1852 1857
1853 iwm_write_prph(sc, IWM_SCD_QUEUE_STATUS_BITS(qid), 1858 iwm_write_prph(sc, IWM_SCD_QUEUE_STATUS_BITS(qid),
1854 (1 << IWM_SCD_QUEUE_STTS_REG_POS_ACTIVE) | 1859 (1 << IWM_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
1855 (fifo << IWM_SCD_QUEUE_STTS_REG_POS_TXF) | 1860 (fifo << IWM_SCD_QUEUE_STTS_REG_POS_TXF) |
1856 (1 << IWM_SCD_QUEUE_STTS_REG_POS_WSL) | 1861 (1 << IWM_SCD_QUEUE_STTS_REG_POS_WSL) |
1857 IWM_SCD_QUEUE_STTS_REG_MSK); 1862 IWM_SCD_QUEUE_STTS_REG_MSK);
1858 1863
1859 iwm_nic_unlock(sc); 1864 iwm_nic_unlock(sc);
1860 1865
1861 DPRINTF(("enabled txq %d FIFO %d\n", qid, fifo)); 1866 DPRINTF(("enabled txq %d FIFO %d\n", qid, fifo));
1862} 1867}
1863 1868
1864static int 1869static int
1865iwm_post_alive(struct iwm_softc *sc) 1870iwm_post_alive(struct iwm_softc *sc)
1866{ 1871{
1867 int nwords; 1872 int nwords;
1868 int error, chnl; 1873 int error, chnl;
1869 1874
1870 if (!iwm_nic_lock(sc)) 1875 if (!iwm_nic_lock(sc))
1871 return EBUSY; 1876 return EBUSY;
1872 1877
1873 if (sc->sched_base != iwm_read_prph(sc, IWM_SCD_SRAM_BASE_ADDR)) { 1878 if (sc->sched_base != iwm_read_prph(sc, IWM_SCD_SRAM_BASE_ADDR)) {
1874 DPRINTF(("%s: sched addr mismatch\n", DEVNAME(sc))); 1879 DPRINTF(("%s: sched addr mismatch\n", DEVNAME(sc)));
1875 error = EINVAL; 1880 error = EINVAL;
1876 goto out; 1881 goto out;
1877 } 1882 }
1878 1883
1879 iwm_ict_reset(sc); 1884 iwm_ict_reset(sc);
1880 1885
1881 /* Clear TX scheduler state in SRAM. */ 1886 /* Clear TX scheduler state in SRAM. */
1882 nwords = (IWM_SCD_TRANS_TBL_MEM_UPPER_BOUND - 1887 nwords = (IWM_SCD_TRANS_TBL_MEM_UPPER_BOUND -
1883 IWM_SCD_CONTEXT_MEM_LOWER_BOUND) 1888 IWM_SCD_CONTEXT_MEM_LOWER_BOUND)
1884 / sizeof(uint32_t); 1889 / sizeof(uint32_t);
1885 error = iwm_write_mem(sc, 1890 error = iwm_write_mem(sc,
1886 sc->sched_base + IWM_SCD_CONTEXT_MEM_LOWER_BOUND, 1891 sc->sched_base + IWM_SCD_CONTEXT_MEM_LOWER_BOUND,
1887 NULL, nwords); 1892 NULL, nwords);
1888 if (error) 1893 if (error)
1889 goto out; 1894 goto out;
1890 1895
1891 /* Set physical address of TX scheduler rings (1KB aligned). */ 1896 /* Set physical address of TX scheduler rings (1KB aligned). */
1892 iwm_write_prph(sc, IWM_SCD_DRAM_BASE_ADDR, sc->sched_dma.paddr >> 10); 1897 iwm_write_prph(sc, IWM_SCD_DRAM_BASE_ADDR, sc->sched_dma.paddr >> 10);
1893 1898
1894 iwm_write_prph(sc, IWM_SCD_CHAINEXT_EN, 0); 1899 iwm_write_prph(sc, IWM_SCD_CHAINEXT_EN, 0);
1895 1900
1896 /* enable command channel */ 1901 /* enable command channel */
1897 iwm_enable_txq(sc, IWM_MVM_CMD_QUEUE, 7); 1902 iwm_enable_txq(sc, IWM_MVM_CMD_QUEUE, 7);
1898 1903
1899 iwm_write_prph(sc, IWM_SCD_TXFACT, 0xff); 1904 iwm_write_prph(sc, IWM_SCD_TXFACT, 0xff);
1900 1905
1901 /* Enable DMA channels. */ 1906 /* Enable DMA channels. */
1902 for (chnl = 0; chnl < IWM_FH_TCSR_CHNL_NUM; chnl++) { 1907 for (chnl = 0; chnl < IWM_FH_TCSR_CHNL_NUM; chnl++) {
1903 IWM_WRITE(sc, IWM_FH_TCSR_CHNL_TX_CONFIG_REG(chnl), 1908 IWM_WRITE(sc, IWM_FH_TCSR_CHNL_TX_CONFIG_REG(chnl),
1904 IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | 1909 IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
1905 IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); 1910 IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
1906 } 1911 }
1907 1912
1908 IWM_SETBITS(sc, IWM_FH_TX_CHICKEN_BITS_REG, 1913 IWM_SETBITS(sc, IWM_FH_TX_CHICKEN_BITS_REG,
1909 IWM_FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); 1914 IWM_FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
1910 1915
1911 /* Enable L1-Active */ 1916 /* Enable L1-Active */
1912 iwm_clear_bits_prph(sc, IWM_APMG_PCIDEV_STT_REG, 1917 iwm_clear_bits_prph(sc, IWM_APMG_PCIDEV_STT_REG,
1913 IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS); 1918 IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
1914 1919
1915 out: 1920 out:
1916 iwm_nic_unlock(sc); 1921 iwm_nic_unlock(sc);
1917 return error; 1922 return error;
1918} 1923}
1919 1924
1920/* 1925/*
1921 * PHY db 1926 * PHY db
1922 * iwlwifi/iwl-phy-db.c 1927 * iwlwifi/iwl-phy-db.c
1923 */ 1928 */
1924 1929
1925/* 1930/*
1926 * BEGIN iwl-phy-db.c 1931 * BEGIN iwl-phy-db.c
1927 */ 1932 */
1928 1933
1929enum iwm_phy_db_section_type { 1934enum iwm_phy_db_section_type {
1930 IWM_PHY_DB_CFG = 1, 1935 IWM_PHY_DB_CFG = 1,
1931 IWM_PHY_DB_CALIB_NCH, 1936 IWM_PHY_DB_CALIB_NCH,
1932 IWM_PHY_DB_UNUSED, 1937 IWM_PHY_DB_UNUSED,
1933 IWM_PHY_DB_CALIB_CHG_PAPD, 1938 IWM_PHY_DB_CALIB_CHG_PAPD,
1934 IWM_PHY_DB_CALIB_CHG_TXP, 1939 IWM_PHY_DB_CALIB_CHG_TXP,
1935 IWM_PHY_DB_MAX 1940 IWM_PHY_DB_MAX
1936}; 1941};
1937 1942
1938#define IWM_PHY_DB_CMD 0x6c /* TEMP API - The actual is 0x8c */ 1943#define IWM_PHY_DB_CMD 0x6c /* TEMP API - The actual is 0x8c */
1939 1944
1940/* 1945/*
1941 * phy db - configure operational ucode 1946 * phy db - configure operational ucode
1942 */ 1947 */
1943struct iwm_phy_db_cmd { 1948struct iwm_phy_db_cmd {
1944 uint16_t type; 1949 uint16_t type;
1945 uint16_t length; 1950 uint16_t length;
1946 uint8_t data[]; 1951 uint8_t data[];
1947} __packed; 1952} __packed;
1948 1953
1949/* for parsing of tx power channel group data that comes from the firmware*/ 1954/* for parsing of tx power channel group data that comes from the firmware*/
1950struct iwm_phy_db_chg_txp { 1955struct iwm_phy_db_chg_txp {
1951 uint32_t space; 1956 uint32_t space;
1952 uint16_t max_channel_idx; 1957 uint16_t max_channel_idx;
1953} __packed; 1958} __packed;
1954 1959
1955/* 1960/*
1956 * phy db - Receive phy db chunk after calibrations 1961 * phy db - Receive phy db chunk after calibrations
1957 */ 1962 */
1958struct iwm_calib_res_notif_phy_db { 1963struct iwm_calib_res_notif_phy_db {
1959 uint16_t type; 1964 uint16_t type;
1960 uint16_t length; 1965 uint16_t length;
1961 uint8_t data[]; 1966 uint8_t data[];
1962} __packed; 1967} __packed;
1963 1968
1964/* 1969/*
1965 * get phy db section: returns a pointer to a phy db section specified by 1970 * get phy db section: returns a pointer to a phy db section specified by
1966 * type and channel group id. 1971 * type and channel group id.
1967 */ 1972 */
1968static struct iwm_phy_db_entry * 1973static struct iwm_phy_db_entry *
1969iwm_phy_db_get_section(struct iwm_softc *sc, 1974iwm_phy_db_get_section(struct iwm_softc *sc,
1970 enum iwm_phy_db_section_type type, uint16_t chg_id) 1975 enum iwm_phy_db_section_type type, uint16_t chg_id)
1971{ 1976{
1972 struct iwm_phy_db *phy_db = &sc->sc_phy_db; 1977 struct iwm_phy_db *phy_db = &sc->sc_phy_db;
1973 1978
1974 if (type >= IWM_PHY_DB_MAX) 1979 if (type >= IWM_PHY_DB_MAX)
1975 return NULL; 1980 return NULL;
1976 1981
1977 switch (type) { 1982 switch (type) {
1978 case IWM_PHY_DB_CFG: 1983 case IWM_PHY_DB_CFG:
1979 return &phy_db->cfg; 1984 return &phy_db->cfg;
1980 case IWM_PHY_DB_CALIB_NCH: 1985 case IWM_PHY_DB_CALIB_NCH:
1981 return &phy_db->calib_nch; 1986 return &phy_db->calib_nch;
1982 case IWM_PHY_DB_CALIB_CHG_PAPD: 1987 case IWM_PHY_DB_CALIB_CHG_PAPD:
1983 if (chg_id >= IWM_NUM_PAPD_CH_GROUPS) 1988 if (chg_id >= IWM_NUM_PAPD_CH_GROUPS)
1984 return NULL; 1989 return NULL;
1985 return &phy_db->calib_ch_group_papd[chg_id]; 1990 return &phy_db->calib_ch_group_papd[chg_id];
1986 case IWM_PHY_DB_CALIB_CHG_TXP: 1991 case IWM_PHY_DB_CALIB_CHG_TXP:
1987 if (chg_id >= IWM_NUM_TXP_CH_GROUPS) 1992 if (chg_id >= IWM_NUM_TXP_CH_GROUPS)
1988 return NULL; 1993 return NULL;
1989 return &phy_db->calib_ch_group_txp[chg_id]; 1994 return &phy_db->calib_ch_group_txp[chg_id];
1990 default: 1995 default:
1991 return NULL; 1996 return NULL;
1992 } 1997 }
1993 return NULL; 1998 return NULL;
1994} 1999}
1995 2000
1996static int 2001static int
1997iwm_phy_db_set_section(struct iwm_softc *sc, 2002iwm_phy_db_set_section(struct iwm_softc *sc,
1998 struct iwm_calib_res_notif_phy_db *phy_db_notif, uint16_t size) 2003 struct iwm_calib_res_notif_phy_db *phy_db_notif, uint16_t size)
1999{ 2004{
2000 enum iwm_phy_db_section_type type = le16toh(phy_db_notif->type); 2005 enum iwm_phy_db_section_type type = le16toh(phy_db_notif->type);
2001 struct iwm_phy_db_entry *entry; 2006 struct iwm_phy_db_entry *entry;
2002 uint16_t chg_id = 0; 2007 uint16_t chg_id = 0;
2003 2008
2004 if (type == IWM_PHY_DB_CALIB_CHG_PAPD || 2009 if (type == IWM_PHY_DB_CALIB_CHG_PAPD ||
2005 type == IWM_PHY_DB_CALIB_CHG_TXP) 2010 type == IWM_PHY_DB_CALIB_CHG_TXP)
2006 chg_id = le16toh(*(uint16_t *)phy_db_notif->data); 2011 chg_id = le16toh(*(uint16_t *)phy_db_notif->data);
2007 2012
2008 entry = iwm_phy_db_get_section(sc, type, chg_id); 2013 entry = iwm_phy_db_get_section(sc, type, chg_id);
2009 if (!entry) 2014 if (!entry)
2010 return EINVAL; 2015 return EINVAL;
2011 2016
2012 if (entry->data) 2017 if (entry->data)
2013 kmem_intr_free(entry->data, entry->size); 2018 kmem_intr_free(entry->data, entry->size);
2014 entry->data = kmem_intr_alloc(size, KM_NOSLEEP); 2019 entry->data = kmem_intr_alloc(size, KM_NOSLEEP);
2015 if (!entry->data) { 2020 if (!entry->data) {
2016 entry->size = 0; 2021 entry->size = 0;
2017 return ENOMEM; 2022 return ENOMEM;
2018 } 2023 }
2019 memcpy(entry->data, phy_db_notif->data, size); 2024 memcpy(entry->data, phy_db_notif->data, size);
2020 entry->size = size; 2025 entry->size = size;
2021 2026
2022 DPRINTFN(10, ("%s(%d): [PHYDB]SET: Type %d, Size: %d, data: %p\n", 2027 DPRINTFN(10, ("%s(%d): [PHYDB]SET: Type %d, Size: %d, data: %p\n",
2023 __func__, __LINE__, type, size, entry->data)); 2028 __func__, __LINE__, type, size, entry->data));
2024 2029
2025 return 0; 2030 return 0;
2026} 2031}
2027 2032
2028static int 2033static int
2029iwm_is_valid_channel(uint16_t ch_id) 2034iwm_is_valid_channel(uint16_t ch_id)
2030{ 2035{
2031 if (ch_id <= 14 || 2036 if (ch_id <= 14 ||
2032 (36 <= ch_id && ch_id <= 64 && ch_id % 4 == 0) || 2037 (36 <= ch_id && ch_id <= 64 && ch_id % 4 == 0) ||
2033 (100 <= ch_id && ch_id <= 140 && ch_id % 4 == 0) || 2038 (100 <= ch_id && ch_id <= 140 && ch_id % 4 == 0) ||
2034 (145 <= ch_id && ch_id <= 165 && ch_id % 4 == 1)) 2039 (145 <= ch_id && ch_id <= 165 && ch_id % 4 == 1))
2035 return 1; 2040 return 1;
2036 return 0; 2041 return 0;
2037} 2042}
2038 2043
2039static uint8_t 2044static uint8_t
2040iwm_ch_id_to_ch_index(uint16_t ch_id) 2045iwm_ch_id_to_ch_index(uint16_t ch_id)
2041{ 2046{
2042 if (!iwm_is_valid_channel(ch_id)) 2047 if (!iwm_is_valid_channel(ch_id))
2043 return 0xff; 2048 return 0xff;
2044 2049
2045 if (ch_id <= 14) 2050 if (ch_id <= 14)
2046 return ch_id - 1; 2051 return ch_id - 1;
2047 if (ch_id <= 64) 2052 if (ch_id <= 64)
2048 return (ch_id + 20) / 4; 2053 return (ch_id + 20) / 4;
2049 if (ch_id <= 140) 2054 if (ch_id <= 140)
2050 return (ch_id - 12) / 4; 2055 return (ch_id - 12) / 4;
2051 return (ch_id - 13) / 4; 2056 return (ch_id - 13) / 4;
2052} 2057}
2053 2058
2054 2059
2055static uint16_t 2060static uint16_t
2056iwm_channel_id_to_papd(uint16_t ch_id) 2061iwm_channel_id_to_papd(uint16_t ch_id)
2057{ 2062{
2058 if (!iwm_is_valid_channel(ch_id)) 2063 if (!iwm_is_valid_channel(ch_id))
2059 return 0xff; 2064 return 0xff;
2060 2065
2061 if (1 <= ch_id && ch_id <= 14) 2066 if (1 <= ch_id && ch_id <= 14)
2062 return 0; 2067 return 0;
2063 if (36 <= ch_id && ch_id <= 64) 2068 if (36 <= ch_id && ch_id <= 64)
2064 return 1; 2069 return 1;
2065 if (100 <= ch_id && ch_id <= 140) 2070 if (100 <= ch_id && ch_id <= 140)
2066 return 2; 2071 return 2;
2067 return 3; 2072 return 3;
2068} 2073}
2069 2074
2070static uint16_t 2075static uint16_t
2071iwm_channel_id_to_txp(struct iwm_softc *sc, uint16_t ch_id) 2076iwm_channel_id_to_txp(struct iwm_softc *sc, uint16_t ch_id)
2072{ 2077{
2073 struct iwm_phy_db *phy_db = &sc->sc_phy_db; 2078 struct iwm_phy_db *phy_db = &sc->sc_phy_db;
2074 struct iwm_phy_db_chg_txp *txp_chg; 2079 struct iwm_phy_db_chg_txp *txp_chg;
2075 int i; 2080 int i;
2076 uint8_t ch_index = iwm_ch_id_to_ch_index(ch_id); 2081 uint8_t ch_index = iwm_ch_id_to_ch_index(ch_id);
2077 2082
2078 if (ch_index == 0xff) 2083 if (ch_index == 0xff)
2079 return 0xff; 2084 return 0xff;
2080 2085
2081 for (i = 0; i < IWM_NUM_TXP_CH_GROUPS; i++) { 2086 for (i = 0; i < IWM_NUM_TXP_CH_GROUPS; i++) {
2082 txp_chg = (void *)phy_db->calib_ch_group_txp[i].data; 2087 txp_chg = (void *)phy_db->calib_ch_group_txp[i].data;
2083 if (!txp_chg) 2088 if (!txp_chg)
2084 return 0xff; 2089 return 0xff;
2085 /* 2090 /*
2086 * Looking for the first channel group that its max channel is 2091 * Looking for the first channel group that its max channel is
2087 * higher then wanted channel. 2092 * higher then wanted channel.
2088 */ 2093 */
2089 if (le16toh(txp_chg->max_channel_idx) >= ch_index) 2094 if (le16toh(txp_chg->max_channel_idx) >= ch_index)
2090 return i; 2095 return i;
2091 } 2096 }
2092 return 0xff; 2097 return 0xff;
2093} 2098}
2094 2099
2095static int 2100static int
2096iwm_phy_db_get_section_data(struct iwm_softc *sc, 2101iwm_phy_db_get_section_data(struct iwm_softc *sc,
2097 uint32_t type, uint8_t **data, uint16_t *size, uint16_t ch_id) 2102 uint32_t type, uint8_t **data, uint16_t *size, uint16_t ch_id)
2098{ 2103{
2099 struct iwm_phy_db_entry *entry; 2104 struct iwm_phy_db_entry *entry;
2100 uint16_t ch_group_id = 0; 2105 uint16_t ch_group_id = 0;
2101 2106
2102 /* find wanted channel group */ 2107 /* find wanted channel group */
2103 if (type == IWM_PHY_DB_CALIB_CHG_PAPD) 2108 if (type == IWM_PHY_DB_CALIB_CHG_PAPD)
2104 ch_group_id = iwm_channel_id_to_papd(ch_id); 2109 ch_group_id = iwm_channel_id_to_papd(ch_id);
2105 else if (type == IWM_PHY_DB_CALIB_CHG_TXP) 2110 else if (type == IWM_PHY_DB_CALIB_CHG_TXP)
2106 ch_group_id = iwm_channel_id_to_txp(sc, ch_id); 2111 ch_group_id = iwm_channel_id_to_txp(sc, ch_id);
2107 2112
2108 entry = iwm_phy_db_get_section(sc, type, ch_group_id); 2113 entry = iwm_phy_db_get_section(sc, type, ch_group_id);
2109 if (!entry) 2114 if (!entry)
2110 return EINVAL; 2115 return EINVAL;
2111 2116
2112 *data = entry->data; 2117 *data = entry->data;
2113 *size = entry->size; 2118 *size = entry->size;
2114 2119
2115 DPRINTFN(10, ("%s(%d): [PHYDB] GET: Type %d , Size: %d\n", 2120 DPRINTFN(10, ("%s(%d): [PHYDB] GET: Type %d , Size: %d\n",
2116 __func__, __LINE__, type, *size)); 2121 __func__, __LINE__, type, *size));
2117 2122
2118 return 0; 2123 return 0;
2119} 2124}
2120 2125
2121static int 2126static int
2122iwm_send_phy_db_cmd(struct iwm_softc *sc, uint16_t type, 2127iwm_send_phy_db_cmd(struct iwm_softc *sc, uint16_t type,
2123 uint16_t length, void *data) 2128 uint16_t length, void *data)
2124{ 2129{
2125 struct iwm_phy_db_cmd phy_db_cmd; 2130 struct iwm_phy_db_cmd phy_db_cmd;
2126 struct iwm_host_cmd cmd = { 2131 struct iwm_host_cmd cmd = {
2127 .id = IWM_PHY_DB_CMD, 2132 .id = IWM_PHY_DB_CMD,
2128 .flags = IWM_CMD_SYNC, 2133 .flags = IWM_CMD_SYNC,
2129 }; 2134 };
2130 2135
2131 DPRINTFN(10, ("Sending PHY-DB hcmd of type %d, of length %d\n", 2136 DPRINTFN(10, ("Sending PHY-DB hcmd of type %d, of length %d\n",
2132 type, length)); 2137 type, length));
2133 2138
2134 /* Set phy db cmd variables */ 2139 /* Set phy db cmd variables */
2135 phy_db_cmd.type = le16toh(type); 2140 phy_db_cmd.type = le16toh(type);
2136 phy_db_cmd.length = le16toh(length); 2141 phy_db_cmd.length = le16toh(length);
2137 2142
2138 /* Set hcmd variables */ 2143 /* Set hcmd variables */
2139 cmd.data[0] = &phy_db_cmd; 2144 cmd.data[0] = &phy_db_cmd;
2140 cmd.len[0] = sizeof(struct iwm_phy_db_cmd); 2145 cmd.len[0] = sizeof(struct iwm_phy_db_cmd);
2141 cmd.data[1] = data; 2146 cmd.data[1] = data;
2142 cmd.len[1] = length; 2147 cmd.len[1] = length;
2143 cmd.dataflags[1] = IWM_HCMD_DFL_NOCOPY; 2148 cmd.dataflags[1] = IWM_HCMD_DFL_NOCOPY;
2144 2149
2145 return iwm_send_cmd(sc, &cmd); 2150 return iwm_send_cmd(sc, &cmd);
2146} 2151}
2147 2152
2148static int 2153static int
2149iwm_phy_db_send_all_channel_groups(struct iwm_softc *sc, 2154iwm_phy_db_send_all_channel_groups(struct iwm_softc *sc,
2150 enum iwm_phy_db_section_type type, uint8_t max_ch_groups) 2155 enum iwm_phy_db_section_type type, uint8_t max_ch_groups)
2151{ 2156{
2152 uint16_t i; 2157 uint16_t i;
2153 int err; 2158 int err;
2154 struct iwm_phy_db_entry *entry; 2159 struct iwm_phy_db_entry *entry;
2155 2160
2156 /* Send all the channel-specific groups to operational fw */ 2161 /* Send all the channel-specific groups to operational fw */
2157 for (i = 0; i < max_ch_groups; i++) { 2162 for (i = 0; i < max_ch_groups; i++) {
2158 entry = iwm_phy_db_get_section(sc, type, i); 2163 entry = iwm_phy_db_get_section(sc, type, i);
2159 if (!entry) 2164 if (!entry)
2160 return EINVAL; 2165 return EINVAL;
2161 2166
2162 if (!entry->size) 2167 if (!entry->size)
2163 continue; 2168 continue;
2164 2169
2165 /* Send the requested PHY DB section */ 2170 /* Send the requested PHY DB section */
2166 err = iwm_send_phy_db_cmd(sc, type, entry->size, entry->data); 2171 err = iwm_send_phy_db_cmd(sc, type, entry->size, entry->data);
2167 if (err) { 2172 if (err) {
2168 DPRINTF(("%s: Can't SEND phy_db section %d (%d), " 2173 DPRINTF(("%s: Can't SEND phy_db section %d (%d), "
2169 "err %d\n", DEVNAME(sc), type, i, err)); 2174 "err %d\n", DEVNAME(sc), type, i, err));
2170 return err; 2175 return err;
2171 } 2176 }
2172 2177
2173 DPRINTFN(10, ("Sent PHY_DB HCMD, type = %d num = %d\n", type, i)); 2178 DPRINTFN(10, ("Sent PHY_DB HCMD, type = %d num = %d\n", type, i));
2174 } 2179 }
2175 2180
2176 return 0; 2181 return 0;
2177} 2182}
2178 2183
2179static int 2184static int
2180iwm_send_phy_db_data(struct iwm_softc *sc) 2185iwm_send_phy_db_data(struct iwm_softc *sc)
2181{ 2186{
2182 uint8_t *data = NULL; 2187 uint8_t *data = NULL;
2183 uint16_t size = 0; 2188 uint16_t size = 0;
2184 int err; 2189 int err;
2185 2190
2186 DPRINTF(("Sending phy db data and configuration to runtime image\n")); 2191 DPRINTF(("Sending phy db data and configuration to runtime image\n"));
2187 2192
2188 /* Send PHY DB CFG section */ 2193 /* Send PHY DB CFG section */
2189 err = iwm_phy_db_get_section_data(sc, IWM_PHY_DB_CFG, &data, &size, 0); 2194 err = iwm_phy_db_get_section_data(sc, IWM_PHY_DB_CFG, &data, &size, 0);
2190 if (err) { 2195 if (err) {
2191 DPRINTF(("%s: Cannot get Phy DB cfg section, %d\n", 2196 DPRINTF(("%s: Cannot get Phy DB cfg section, %d\n",
2192 DEVNAME(sc), err)); 2197 DEVNAME(sc), err));
2193 return err; 2198 return err;
2194 } 2199 }
2195 2200
2196 err = iwm_send_phy_db_cmd(sc, IWM_PHY_DB_CFG, size, data); 2201 err = iwm_send_phy_db_cmd(sc, IWM_PHY_DB_CFG, size, data);
2197 if (err) { 2202 if (err) {
2198 DPRINTF(("%s: Cannot send HCMD of Phy DB cfg section, %d\n", 2203 DPRINTF(("%s: Cannot send HCMD of Phy DB cfg section, %d\n",
2199 DEVNAME(sc), err)); 2204 DEVNAME(sc), err));
2200 return err; 2205 return err;
2201 } 2206 }
2202 2207
2203 err = iwm_phy_db_get_section_data(sc, IWM_PHY_DB_CALIB_NCH, 2208 err = iwm_phy_db_get_section_data(sc, IWM_PHY_DB_CALIB_NCH,
2204 &data, &size, 0); 2209 &data, &size, 0);
2205 if (err) { 2210 if (err) {
2206 DPRINTF(("%s: Cannot get Phy DB non specific channel section, " 2211 DPRINTF(("%s: Cannot get Phy DB non specific channel section, "
2207 "%d\n", DEVNAME(sc), err)); 2212 "%d\n", DEVNAME(sc), err));
2208 return err; 2213 return err;
2209 } 2214 }
2210 2215
2211 err = iwm_send_phy_db_cmd(sc, IWM_PHY_DB_CALIB_NCH, size, data); 2216 err = iwm_send_phy_db_cmd(sc, IWM_PHY_DB_CALIB_NCH, size, data);
2212 if (err) { 2217 if (err) {
2213 DPRINTF(("%s: Cannot send HCMD of Phy DB non specific channel " 2218 DPRINTF(("%s: Cannot send HCMD of Phy DB non specific channel "
2214 "sect, %d\n", DEVNAME(sc), err)); 2219 "sect, %d\n", DEVNAME(sc), err));
2215 return err; 2220 return err;
2216 } 2221 }
2217 2222
2218 /* Send all the TXP channel specific data */ 2223 /* Send all the TXP channel specific data */
2219 err = iwm_phy_db_send_all_channel_groups(sc, 2224 err = iwm_phy_db_send_all_channel_groups(sc,
2220 IWM_PHY_DB_CALIB_CHG_PAPD, IWM_NUM_PAPD_CH_GROUPS); 2225 IWM_PHY_DB_CALIB_CHG_PAPD, IWM_NUM_PAPD_CH_GROUPS);
2221 if (err) { 2226 if (err) {
2222 DPRINTF(("%s: Cannot send channel specific PAPD groups, %d\n", 2227 DPRINTF(("%s: Cannot send channel specific PAPD groups, %d\n",
2223 DEVNAME(sc), err)); 2228 DEVNAME(sc), err));
2224 return err; 2229 return err;
2225 } 2230 }
2226 2231
2227 /* Send all the TXP channel specific data */ 2232 /* Send all the TXP channel specific data */
2228 err = iwm_phy_db_send_all_channel_groups(sc, 2233 err = iwm_phy_db_send_all_channel_groups(sc,
2229 IWM_PHY_DB_CALIB_CHG_TXP, IWM_NUM_TXP_CH_GROUPS); 2234 IWM_PHY_DB_CALIB_CHG_TXP, IWM_NUM_TXP_CH_GROUPS);
2230 if (err) { 2235 if (err) {
2231 DPRINTF(("%s: Cannot send channel specific TX power groups, " 2236 DPRINTF(("%s: Cannot send channel specific TX power groups, "
2232 "%d\n", DEVNAME(sc), err)); 2237 "%d\n", DEVNAME(sc), err));
2233 return err; 2238 return err;
2234 } 2239 }
2235 2240
2236 DPRINTF(("Finished sending phy db non channel data\n")); 2241 DPRINTF(("Finished sending phy db non channel data\n"));
2237 return 0; 2242 return 0;
2238} 2243}
2239 2244
2240/* 2245/*
2241 * END iwl-phy-db.c 2246 * END iwl-phy-db.c
2242 */ 2247 */
2243 2248
2244/* 2249/*
2245 * BEGIN iwlwifi/mvm/time-event.c 2250 * BEGIN iwlwifi/mvm/time-event.c
2246 */ 2251 */
2247 2252
2248/* 2253/*
2249 * For the high priority TE use a time event type that has similar priority to 2254 * For the high priority TE use a time event type that has similar priority to
2250 * the FW's action scan priority. 2255 * the FW's action scan priority.
2251 */ 2256 */
2252#define IWM_MVM_ROC_TE_TYPE_NORMAL IWM_TE_P2P_DEVICE_DISCOVERABLE 2257#define IWM_MVM_ROC_TE_TYPE_NORMAL IWM_TE_P2P_DEVICE_DISCOVERABLE
2253#define IWM_MVM_ROC_TE_TYPE_MGMT_TX IWM_TE_P2P_CLIENT_ASSOC 2258#define IWM_MVM_ROC_TE_TYPE_MGMT_TX IWM_TE_P2P_CLIENT_ASSOC
2254 2259
2255/* used to convert from time event API v2 to v1 */ 2260/* used to convert from time event API v2 to v1 */
2256#define IWM_TE_V2_DEP_POLICY_MSK (IWM_TE_V2_DEP_OTHER | IWM_TE_V2_DEP_TSF |\ 2261#define IWM_TE_V2_DEP_POLICY_MSK (IWM_TE_V2_DEP_OTHER | IWM_TE_V2_DEP_TSF |\
2257 IWM_TE_V2_EVENT_SOCIOPATHIC) 2262 IWM_TE_V2_EVENT_SOCIOPATHIC)
2258static inline uint16_t 2263static inline uint16_t
2259iwm_te_v2_get_notify(uint16_t policy) 2264iwm_te_v2_get_notify(uint16_t policy)
2260{ 2265{
2261 return le16toh(policy) & IWM_TE_V2_NOTIF_MSK; 2266 return le16toh(policy) & IWM_TE_V2_NOTIF_MSK;
2262} 2267}
2263 2268
2264static inline uint16_t 2269static inline uint16_t
2265iwm_te_v2_get_dep_policy(uint16_t policy) 2270iwm_te_v2_get_dep_policy(uint16_t policy)
2266{ 2271{
2267 return (le16toh(policy) & IWM_TE_V2_DEP_POLICY_MSK) >> 2272 return (le16toh(policy) & IWM_TE_V2_DEP_POLICY_MSK) >>
2268 IWM_TE_V2_PLACEMENT_POS; 2273 IWM_TE_V2_PLACEMENT_POS;
2269} 2274}
2270 2275
2271static inline uint16_t 2276static inline uint16_t
2272iwm_te_v2_get_absence(uint16_t policy) 2277iwm_te_v2_get_absence(uint16_t policy)
2273{ 2278{
2274 return (le16toh(policy) & IWM_TE_V2_ABSENCE) >> IWM_TE_V2_ABSENCE_POS; 2279 return (le16toh(policy) & IWM_TE_V2_ABSENCE) >> IWM_TE_V2_ABSENCE_POS;
2275} 2280}
2276 2281
2277static void 2282static void
2278iwm_mvm_te_v2_to_v1(const struct iwm_time_event_cmd_v2 *cmd_v2, 2283iwm_mvm_te_v2_to_v1(const struct iwm_time_event_cmd_v2 *cmd_v2,
2279 struct iwm_time_event_cmd_v1 *cmd_v1) 2284 struct iwm_time_event_cmd_v1 *cmd_v1)
2280{ 2285{
2281 cmd_v1->id_and_color = cmd_v2->id_and_color; 2286 cmd_v1->id_and_color = cmd_v2->id_and_color;
2282 cmd_v1->action = cmd_v2->action; 2287 cmd_v1->action = cmd_v2->action;
2283 cmd_v1->id = cmd_v2->id; 2288 cmd_v1->id = cmd_v2->id;
2284 cmd_v1->apply_time = cmd_v2->apply_time; 2289 cmd_v1->apply_time = cmd_v2->apply_time;
2285 cmd_v1->max_delay = cmd_v2->max_delay; 2290 cmd_v1->max_delay = cmd_v2->max_delay;
2286 cmd_v1->depends_on = cmd_v2->depends_on; 2291 cmd_v1->depends_on = cmd_v2->depends_on;
2287 cmd_v1->interval = cmd_v2->interval; 2292 cmd_v1->interval = cmd_v2->interval;
2288 cmd_v1->duration = cmd_v2->duration; 2293 cmd_v1->duration = cmd_v2->duration;
2289 if (cmd_v2->repeat == IWM_TE_V2_REPEAT_ENDLESS) 2294 if (cmd_v2->repeat == IWM_TE_V2_REPEAT_ENDLESS)
2290 cmd_v1->repeat = htole32(IWM_TE_V1_REPEAT_ENDLESS); 2295 cmd_v1->repeat = htole32(IWM_TE_V1_REPEAT_ENDLESS);
2291 else 2296 else
2292 cmd_v1->repeat = htole32(cmd_v2->repeat); 2297 cmd_v1->repeat = htole32(cmd_v2->repeat);
2293 cmd_v1->max_frags = htole32(cmd_v2->max_frags); 2298 cmd_v1->max_frags = htole32(cmd_v2->max_frags);
2294 cmd_v1->interval_reciprocal = 0; /* unused */ 2299 cmd_v1->interval_reciprocal = 0; /* unused */
2295 2300
2296 cmd_v1->dep_policy = htole32(iwm_te_v2_get_dep_policy(cmd_v2->policy)); 2301 cmd_v1->dep_policy = htole32(iwm_te_v2_get_dep_policy(cmd_v2->policy));
2297 cmd_v1->is_present = htole32(!iwm_te_v2_get_absence(cmd_v2->policy)); 2302 cmd_v1->is_present = htole32(!iwm_te_v2_get_absence(cmd_v2->policy));
2298 cmd_v1->notify = htole32(iwm_te_v2_get_notify(cmd_v2->policy)); 2303 cmd_v1->notify = htole32(iwm_te_v2_get_notify(cmd_v2->policy));
2299} 2304}
2300 2305
2301static int 2306static int
2302iwm_mvm_send_time_event_cmd(struct iwm_softc *sc, 2307iwm_mvm_send_time_event_cmd(struct iwm_softc *sc,
2303 const struct iwm_time_event_cmd_v2 *cmd) 2308 const struct iwm_time_event_cmd_v2 *cmd)
2304{ 2309{
2305 struct iwm_time_event_cmd_v1 cmd_v1; 2310 struct iwm_time_event_cmd_v1 cmd_v1;
2306 2311
2307 if (sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_TIME_EVENT_API_V2) 2312 if (sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_TIME_EVENT_API_V2)
2308 return iwm_mvm_send_cmd_pdu(sc, IWM_TIME_EVENT_CMD, 2313 return iwm_mvm_send_cmd_pdu(sc, IWM_TIME_EVENT_CMD,
2309 IWM_CMD_SYNC, sizeof(*cmd), cmd); 2314 IWM_CMD_SYNC, sizeof(*cmd), cmd);
2310 2315
2311 iwm_mvm_te_v2_to_v1(cmd, &cmd_v1); 2316 iwm_mvm_te_v2_to_v1(cmd, &cmd_v1);
2312 return iwm_mvm_send_cmd_pdu(sc, IWM_TIME_EVENT_CMD, IWM_CMD_SYNC, 2317 return iwm_mvm_send_cmd_pdu(sc, IWM_TIME_EVENT_CMD, IWM_CMD_SYNC,
2313 sizeof(cmd_v1), &cmd_v1); 2318 sizeof(cmd_v1), &cmd_v1);
2314} 2319}
2315 2320
2316static int 2321static int
2317iwm_mvm_time_event_send_add(struct iwm_softc *sc, struct iwm_node *in, 2322iwm_mvm_time_event_send_add(struct iwm_softc *sc, struct iwm_node *in,
2318 void *te_data, struct iwm_time_event_cmd_v2 *te_cmd) 2323 void *te_data, struct iwm_time_event_cmd_v2 *te_cmd)
2319{ 2324{
2320 int ret; 2325 int ret;
2321 2326
2322 DPRINTF(("Add new TE, duration %d TU\n", le32toh(te_cmd->duration))); 2327 DPRINTF(("Add new TE, duration %d TU\n", le32toh(te_cmd->duration)));
2323 2328
2324 ret = iwm_mvm_send_time_event_cmd(sc, te_cmd); 2329 ret = iwm_mvm_send_time_event_cmd(sc, te_cmd);
2325 if (ret) { 2330 if (ret) {
2326 DPRINTF(("%s: Couldn't send IWM_TIME_EVENT_CMD: %d\n", 2331 DPRINTF(("%s: Couldn't send IWM_TIME_EVENT_CMD: %d\n",
2327 DEVNAME(sc), ret)); 2332 DEVNAME(sc), ret));
2328 } 2333 }
2329 2334
2330 return ret; 2335 return ret;
2331} 2336}
2332 2337
2333static void 2338static void
2334iwm_mvm_protect_session(struct iwm_softc *sc, struct iwm_node *in, 2339iwm_mvm_protect_session(struct iwm_softc *sc, struct iwm_node *in,
2335 uint32_t duration, uint32_t min_duration, uint32_t max_delay) 2340 uint32_t duration, uint32_t min_duration, uint32_t max_delay)
2336{ 2341{
2337 struct iwm_time_event_cmd_v2 time_cmd; 2342 struct iwm_time_event_cmd_v2 time_cmd;
2338 2343
2339 memset(&time_cmd, 0, sizeof(time_cmd)); 2344 memset(&time_cmd, 0, sizeof(time_cmd));
2340 2345
2341 time_cmd.action = htole32(IWM_FW_CTXT_ACTION_ADD); 2346 time_cmd.action = htole32(IWM_FW_CTXT_ACTION_ADD);
2342 time_cmd.id_and_color = 2347 time_cmd.id_and_color =
2343 htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color)); 2348 htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));
2344 time_cmd.id = htole32(IWM_TE_BSS_STA_AGGRESSIVE_ASSOC); 2349 time_cmd.id = htole32(IWM_TE_BSS_STA_AGGRESSIVE_ASSOC);
2345 2350
2346 time_cmd.apply_time = htole32(iwm_read_prph(sc, 2351 time_cmd.apply_time = htole32(iwm_read_prph(sc,
2347 IWM_DEVICE_SYSTEM_TIME_REG)); 2352 IWM_DEVICE_SYSTEM_TIME_REG));
2348 2353
2349 time_cmd.max_frags = IWM_TE_V2_FRAG_NONE; 2354 time_cmd.max_frags = IWM_TE_V2_FRAG_NONE;
2350 time_cmd.max_delay = htole32(max_delay); 2355 time_cmd.max_delay = htole32(max_delay);
2351 /* TODO: why do we need to interval = bi if it is not periodic? */ 2356 /* TODO: why do we need to interval = bi if it is not periodic? */
2352 time_cmd.interval = htole32(1); 2357 time_cmd.interval = htole32(1);
2353 time_cmd.duration = htole32(duration); 2358 time_cmd.duration = htole32(duration);
2354 time_cmd.repeat = 1; 2359 time_cmd.repeat = 1;
2355 time_cmd.policy 2360 time_cmd.policy
2356 = htole32(IWM_TE_V2_NOTIF_HOST_EVENT_START | 2361 = htole32(IWM_TE_V2_NOTIF_HOST_EVENT_START |
2357 IWM_TE_V2_NOTIF_HOST_EVENT_END); 2362 IWM_TE_V2_NOTIF_HOST_EVENT_END);
2358 2363
2359 iwm_mvm_time_event_send_add(sc, in, /*te_data*/NULL, &time_cmd); 2364 iwm_mvm_time_event_send_add(sc, in, /*te_data*/NULL, &time_cmd);
2360} 2365}
2361 2366
2362/* 2367/*
2363 * END iwlwifi/mvm/time-event.c 2368 * END iwlwifi/mvm/time-event.c
2364 */ 2369 */
2365 2370
2366/* 2371/*
2367 * NVM read access and content parsing. We do not support 2372 * NVM read access and content parsing. We do not support
2368 * external NVM or writing NVM. 2373 * external NVM or writing NVM.
2369 * iwlwifi/mvm/nvm.c 2374 * iwlwifi/mvm/nvm.c
2370 */ 2375 */
2371 2376
2372/* list of NVM sections we are allowed/need to read */ 2377/* list of NVM sections we are allowed/need to read */
2373static const int nvm_to_read[] = { 2378static const int nvm_to_read[] = {
2374 IWM_NVM_SECTION_TYPE_HW, 2379 IWM_NVM_SECTION_TYPE_HW,
2375 IWM_NVM_SECTION_TYPE_SW, 2380 IWM_NVM_SECTION_TYPE_SW,
2376 IWM_NVM_SECTION_TYPE_CALIBRATION, 2381 IWM_NVM_SECTION_TYPE_CALIBRATION,
2377 IWM_NVM_SECTION_TYPE_PRODUCTION, 2382 IWM_NVM_SECTION_TYPE_PRODUCTION,
2378}; 2383};
2379 2384
2380/* Default NVM size to read */ 2385/* Default NVM size to read */
2381#define IWM_NVM_DEFAULT_CHUNK_SIZE (2*1024) 2386#define IWM_NVM_DEFAULT_CHUNK_SIZE (2*1024)
2382#define IWM_MAX_NVM_SECTION_SIZE 7000 2387#define IWM_MAX_NVM_SECTION_SIZE 7000
2383 2388
2384#define IWM_NVM_WRITE_OPCODE 1 2389#define IWM_NVM_WRITE_OPCODE 1
2385#define IWM_NVM_READ_OPCODE 0 2390#define IWM_NVM_READ_OPCODE 0
2386 2391
2387static int 2392static int
2388iwm_nvm_read_chunk(struct iwm_softc *sc, uint16_t section, 2393iwm_nvm_read_chunk(struct iwm_softc *sc, uint16_t section,
2389 uint16_t offset, uint16_t length, uint8_t *data, uint16_t *len) 2394 uint16_t offset, uint16_t length, uint8_t *data, uint16_t *len)
2390{ 2395{
2391 offset = 0; 2396 offset = 0;
2392 struct iwm_nvm_access_cmd nvm_access_cmd = { 2397 struct iwm_nvm_access_cmd nvm_access_cmd = {
2393 .offset = htole16(offset), 2398 .offset = htole16(offset),
2394 .length = htole16(length), 2399 .length = htole16(length),
2395 .type = htole16(section), 2400 .type = htole16(section),
2396 .op_code = IWM_NVM_READ_OPCODE, 2401 .op_code = IWM_NVM_READ_OPCODE,
2397 }; 2402 };
2398 struct iwm_nvm_access_resp *nvm_resp; 2403 struct iwm_nvm_access_resp *nvm_resp;
2399 struct iwm_rx_packet *pkt; 2404 struct iwm_rx_packet *pkt;
2400 struct iwm_host_cmd cmd = { 2405 struct iwm_host_cmd cmd = {
2401 .id = IWM_NVM_ACCESS_CMD, 2406 .id = IWM_NVM_ACCESS_CMD,
2402 .flags = IWM_CMD_SYNC | IWM_CMD_WANT_SKB | 2407 .flags = IWM_CMD_SYNC | IWM_CMD_WANT_SKB |
2403 IWM_CMD_SEND_IN_RFKILL, 2408 IWM_CMD_SEND_IN_RFKILL,
2404 .data = { &nvm_access_cmd, }, 2409 .data = { &nvm_access_cmd, },
2405 }; 2410 };
2406 int ret, bytes_read, offset_read; 2411 int ret, bytes_read, offset_read;
2407 uint8_t *resp_data; 2412 uint8_t *resp_data;
2408 2413
2409 cmd.len[0] = sizeof(struct iwm_nvm_access_cmd); 2414 cmd.len[0] = sizeof(struct iwm_nvm_access_cmd);
2410 2415
2411 ret = iwm_send_cmd(sc, &cmd); 2416 ret = iwm_send_cmd(sc, &cmd);
2412 if (ret) 2417 if (ret)
2413 return ret; 2418 return ret;
2414 2419
2415 pkt = cmd.resp_pkt; 2420 pkt = cmd.resp_pkt;
2416 if (pkt->hdr.flags & IWM_CMD_FAILED_MSK) { 2421 if (pkt->hdr.flags & IWM_CMD_FAILED_MSK) {
2417 DPRINTF(("%s: Bad return from IWM_NVM_ACCES_COMMAND (0x%08X)\n", 2422 DPRINTF(("%s: Bad return from IWM_NVM_ACCES_COMMAND (0x%08X)\n",
2418 DEVNAME(sc), pkt->hdr.flags)); 2423 DEVNAME(sc), pkt->hdr.flags));
2419 ret = EIO; 2424 ret = EIO;
2420 goto exit; 2425 goto exit;
2421 } 2426 }
2422 2427
2423 /* Extract NVM response */ 2428 /* Extract NVM response */
2424 nvm_resp = (void *)pkt->data; 2429 nvm_resp = (void *)pkt->data;
2425 2430
2426 ret = le16toh(nvm_resp->status); 2431 ret = le16toh(nvm_resp->status);
2427 bytes_read = le16toh(nvm_resp->length); 2432 bytes_read = le16toh(nvm_resp->length);
2428 offset_read = le16toh(nvm_resp->offset); 2433 offset_read = le16toh(nvm_resp->offset);
2429 resp_data = nvm_resp->data; 2434 resp_data = nvm_resp->data;
2430 if (ret) { 2435 if (ret) {
2431 DPRINTF(("%s: NVM access command failed with status %d\n", 2436 DPRINTF(("%s: NVM access command failed with status %d\n",
2432 DEVNAME(sc), ret)); 2437 DEVNAME(sc), ret));
2433 ret = EINVAL; 2438 ret = EINVAL;
2434 goto exit; 2439 goto exit;
2435 } 2440 }
2436 2441
2437 if (offset_read != offset) { 2442 if (offset_read != offset) {
2438 DPRINTF(("%s: NVM ACCESS response with invalid offset %d\n", 2443 DPRINTF(("%s: NVM ACCESS response with invalid offset %d\n",
2439 DEVNAME(sc), offset_read)); 2444 DEVNAME(sc), offset_read));
2440 ret = EINVAL; 2445 ret = EINVAL;
2441 goto exit; 2446 goto exit;
2442 } 2447 }
2443 2448
2444 memcpy(data + offset, resp_data, bytes_read); 2449 memcpy(data + offset, resp_data, bytes_read);
2445 *len = bytes_read; 2450 *len = bytes_read;
2446 2451
2447 exit: 2452 exit:
2448 iwm_free_resp(sc, &cmd); 2453 iwm_free_resp(sc, &cmd);
2449 return ret; 2454 return ret;
2450} 2455}
2451 2456
2452/* 2457/*
2453 * Reads an NVM section completely. 2458 * Reads an NVM section completely.
2454 * NICs prior to 7000 family doesn't have a real NVM, but just read 2459 * NICs prior to 7000 family doesn't have a real NVM, but just read
2455 * section 0 which is the EEPROM. Because the EEPROM reading is unlimited 2460 * section 0 which is the EEPROM. Because the EEPROM reading is unlimited
2456 * by uCode, we need to manually check in this case that we don't 2461 * by uCode, we need to manually check in this case that we don't
2457 * overflow and try to read more than the EEPROM size. 2462 * overflow and try to read more than the EEPROM size.
2458 * For 7000 family NICs, we supply the maximal size we can read, and 2463 * For 7000 family NICs, we supply the maximal size we can read, and
2459 * the uCode fills the response with as much data as we can, 2464 * the uCode fills the response with as much data as we can,
2460 * without overflowing, so no check is needed. 2465 * without overflowing, so no check is needed.
2461 */ 2466 */
2462static int 2467static int
2463iwm_nvm_read_section(struct iwm_softc *sc, 2468iwm_nvm_read_section(struct iwm_softc *sc,
2464 uint16_t section, uint8_t *data, uint16_t *len) 2469 uint16_t section, uint8_t *data, uint16_t *len)
2465{ 2470{
2466 uint16_t length, seglen; 2471 uint16_t length, seglen;
2467 int error; 2472 int error;
2468 2473
2469 /* Set nvm section read length */ 2474 /* Set nvm section read length */
2470 length = seglen = IWM_NVM_DEFAULT_CHUNK_SIZE; 2475 length = seglen = IWM_NVM_DEFAULT_CHUNK_SIZE;
2471 *len = 0; 2476 *len = 0;
2472 2477
2473 /* Read the NVM until exhausted (reading less than requested) */ 2478 /* Read the NVM until exhausted (reading less than requested) */
2474 while (seglen == length) { 2479 while (seglen == length) {
2475 error = iwm_nvm_read_chunk(sc, 2480 error = iwm_nvm_read_chunk(sc,
2476 section, *len, length, data, &seglen); 2481 section, *len, length, data, &seglen);
2477 if (error) { 2482 if (error) {
2478 aprint_error_dev(sc->sc_dev, 2483 aprint_error_dev(sc->sc_dev,
2479 "Cannot read NVM from section %d offset %d, " 2484 "Cannot read NVM from section %d offset %d, "
2480 "length %d\n", section, *len, length); 2485 "length %d\n", section, *len, length);
2481 return error; 2486 return error;
2482 } 2487 }
2483 *len += seglen; 2488 *len += seglen;
2484 } 2489 }
2485 2490
2486 DPRINTFN(4, ("NVM section %d read completed\n", section)); 2491 DPRINTFN(4, ("NVM section %d read completed\n", section));
2487 return 0; 2492 return 0;
2488} 2493}
2489 2494
2490/* 2495/*
2491 * BEGIN IWM_NVM_PARSE 2496 * BEGIN IWM_NVM_PARSE
2492 */ 2497 */
2493 2498
2494/* iwlwifi/iwl-nvm-parse.c */ 2499/* iwlwifi/iwl-nvm-parse.c */
2495 2500
2496/* NVM offsets (in words) definitions */ 2501/* NVM offsets (in words) definitions */
2497enum wkp_nvm_offsets { 2502enum wkp_nvm_offsets {
2498 /* NVM HW-Section offset (in words) definitions */ 2503 /* NVM HW-Section offset (in words) definitions */
2499 IWM_HW_ADDR = 0x15, 2504 IWM_HW_ADDR = 0x15,
2500 2505
2501/* NVM SW-Section offset (in words) definitions */ 2506/* NVM SW-Section offset (in words) definitions */
2502 IWM_NVM_SW_SECTION = 0x1C0, 2507 IWM_NVM_SW_SECTION = 0x1C0,
2503 IWM_NVM_VERSION = 0, 2508 IWM_NVM_VERSION = 0,
2504 IWM_RADIO_CFG = 1, 2509 IWM_RADIO_CFG = 1,
2505 IWM_SKU = 2, 2510 IWM_SKU = 2,
2506 IWM_N_HW_ADDRS = 3, 2511 IWM_N_HW_ADDRS = 3,
2507 IWM_NVM_CHANNELS = 0x1E0 - IWM_NVM_SW_SECTION, 2512 IWM_NVM_CHANNELS = 0x1E0 - IWM_NVM_SW_SECTION,
2508 2513
2509/* NVM calibration section offset (in words) definitions */ 2514/* NVM calibration section offset (in words) definitions */
2510 IWM_NVM_CALIB_SECTION = 0x2B8, 2515 IWM_NVM_CALIB_SECTION = 0x2B8,
2511 IWM_XTAL_CALIB = 0x316 - IWM_NVM_CALIB_SECTION 2516 IWM_XTAL_CALIB = 0x316 - IWM_NVM_CALIB_SECTION
2512}; 2517};
2513 2518
2514/* SKU Capabilities (actual values from NVM definition) */ 2519/* SKU Capabilities (actual values from NVM definition) */
2515enum nvm_sku_bits { 2520enum nvm_sku_bits {
2516 IWM_NVM_SKU_CAP_BAND_24GHZ = (1 << 0), 2521 IWM_NVM_SKU_CAP_BAND_24GHZ = (1 << 0),
2517 IWM_NVM_SKU_CAP_BAND_52GHZ = (1 << 1), 2522 IWM_NVM_SKU_CAP_BAND_52GHZ = (1 << 1),
2518 IWM_NVM_SKU_CAP_11N_ENABLE = (1 << 2), 2523 IWM_NVM_SKU_CAP_11N_ENABLE = (1 << 2),
2519 IWM_NVM_SKU_CAP_11AC_ENABLE = (1 << 3), 2524 IWM_NVM_SKU_CAP_11AC_ENABLE = (1 << 3),
2520}; 2525};
2521 2526
2522/* radio config bits (actual values from NVM definition) */ 2527/* radio config bits (actual values from NVM definition) */
2523#define IWM_NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */ 2528#define IWM_NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */
2524#define IWM_NVM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */ 2529#define IWM_NVM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */
2525#define IWM_NVM_RF_CFG_TYPE_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */ 2530#define IWM_NVM_RF_CFG_TYPE_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */
2526#define IWM_NVM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */ 2531#define IWM_NVM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */
2527#define IWM_NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */ 2532#define IWM_NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
2528#define IWM_NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */ 2533#define IWM_NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
2529 2534
2530#define DEFAULT_MAX_TX_POWER 16 2535#define DEFAULT_MAX_TX_POWER 16
2531 2536
2532/** 2537/**
2533 * enum iwm_nvm_channel_flags - channel flags in NVM 2538 * enum iwm_nvm_channel_flags - channel flags in NVM
2534 * @IWM_NVM_CHANNEL_VALID: channel is usable for this SKU/geo 2539 * @IWM_NVM_CHANNEL_VALID: channel is usable for this SKU/geo
2535 * @IWM_NVM_CHANNEL_IBSS: usable as an IBSS channel 2540 * @IWM_NVM_CHANNEL_IBSS: usable as an IBSS channel
2536 * @IWM_NVM_CHANNEL_ACTIVE: active scanning allowed 2541 * @IWM_NVM_CHANNEL_ACTIVE: active scanning allowed
2537 * @IWM_NVM_CHANNEL_RADAR: radar detection required 2542 * @IWM_NVM_CHANNEL_RADAR: radar detection required
2538 * @IWM_NVM_CHANNEL_DFS: dynamic freq selection candidate 2543 * @IWM_NVM_CHANNEL_DFS: dynamic freq selection candidate
2539 * @IWM_NVM_CHANNEL_WIDE: 20 MHz channel okay (?) 2544 * @IWM_NVM_CHANNEL_WIDE: 20 MHz channel okay (?)
2540 * @IWM_NVM_CHANNEL_40MHZ: 40 MHz channel okay (?) 2545 * @IWM_NVM_CHANNEL_40MHZ: 40 MHz channel okay (?)
2541 * @IWM_NVM_CHANNEL_80MHZ: 80 MHz channel okay (?) 2546 * @IWM_NVM_CHANNEL_80MHZ: 80 MHz channel okay (?)
2542 * @IWM_NVM_CHANNEL_160MHZ: 160 MHz channel okay (?) 2547 * @IWM_NVM_CHANNEL_160MHZ: 160 MHz channel okay (?)
2543 */ 2548 */
2544enum iwm_nvm_channel_flags { 2549enum iwm_nvm_channel_flags {
2545 IWM_NVM_CHANNEL_VALID = (1 << 0), 2550 IWM_NVM_CHANNEL_VALID = (1 << 0),
2546 IWM_NVM_CHANNEL_IBSS = (1 << 1), 2551 IWM_NVM_CHANNEL_IBSS = (1 << 1),
2547 IWM_NVM_CHANNEL_ACTIVE = (1 << 3), 2552 IWM_NVM_CHANNEL_ACTIVE = (1 << 3),
2548 IWM_NVM_CHANNEL_RADAR = (1 << 4), 2553 IWM_NVM_CHANNEL_RADAR = (1 << 4),
2549 IWM_NVM_CHANNEL_DFS = (1 << 7), 2554 IWM_NVM_CHANNEL_DFS = (1 << 7),
2550 IWM_NVM_CHANNEL_WIDE = (1 << 8), 2555 IWM_NVM_CHANNEL_WIDE = (1 << 8),
2551 IWM_NVM_CHANNEL_40MHZ = (1 << 9), 2556 IWM_NVM_CHANNEL_40MHZ = (1 << 9),
2552 IWM_NVM_CHANNEL_80MHZ = (1 << 10), 2557 IWM_NVM_CHANNEL_80MHZ = (1 << 10),
2553 IWM_NVM_CHANNEL_160MHZ = (1 << 11), 2558 IWM_NVM_CHANNEL_160MHZ = (1 << 11),
2554}; 2559};
2555 2560
2556static void 2561static void
2557iwm_init_channel_map(struct iwm_softc *sc, const uint16_t * const nvm_ch_flags) 2562iwm_init_channel_map(struct iwm_softc *sc, const uint16_t * const nvm_ch_flags)
2558{ 2563{
2559 struct ieee80211com *ic = &sc->sc_ic; 2564 struct ieee80211com *ic = &sc->sc_ic;
2560 struct iwm_nvm_data *data = &sc->sc_nvm; 2565 struct iwm_nvm_data *data = &sc->sc_nvm;
2561 int ch_idx; 2566 int ch_idx;
2562 struct ieee80211_channel *channel; 2567 struct ieee80211_channel *channel;
2563 uint16_t ch_flags; 2568 uint16_t ch_flags;
2564 int is_5ghz; 2569 int is_5ghz;
2565 int flags, hw_value; 2570 int flags, hw_value;
2566 2571
2567 for (ch_idx = 0; ch_idx < __arraycount(iwm_nvm_channels); ch_idx++) { 2572 for (ch_idx = 0; ch_idx < __arraycount(iwm_nvm_channels); ch_idx++) {
2568 ch_flags = le16_to_cpup(nvm_ch_flags + ch_idx); 2573 ch_flags = le16_to_cpup(nvm_ch_flags + ch_idx);
2569 2574
2570 if (ch_idx >= IWM_NUM_2GHZ_CHANNELS && 2575 if (ch_idx >= IWM_NUM_2GHZ_CHANNELS &&
2571 !data->sku_cap_band_52GHz_enable) 2576 !data->sku_cap_band_52GHz_enable)
2572 ch_flags &= ~IWM_NVM_CHANNEL_VALID; 2577 ch_flags &= ~IWM_NVM_CHANNEL_VALID;
2573 2578
2574 if (!(ch_flags & IWM_NVM_CHANNEL_VALID)) { 2579 if (!(ch_flags & IWM_NVM_CHANNEL_VALID)) {
2575 DPRINTF(("Ch. %d Flags %x [%sGHz] - No traffic\n", 2580 DPRINTF(("Ch. %d Flags %x [%sGHz] - No traffic\n",
2576 iwm_nvm_channels[ch_idx], 2581 iwm_nvm_channels[ch_idx],
2577 ch_flags, 2582 ch_flags,
2578 (ch_idx >= IWM_NUM_2GHZ_CHANNELS) ? 2583 (ch_idx >= IWM_NUM_2GHZ_CHANNELS) ?
2579 "5.2" : "2.4")); 2584 "5.2" : "2.4"));
2580 continue; 2585 continue;
2581 } 2586 }
2582 2587
2583 hw_value = iwm_nvm_channels[ch_idx]; 2588 hw_value = iwm_nvm_channels[ch_idx];
2584 channel = &ic->ic_channels[hw_value]; 2589 channel = &ic->ic_channels[hw_value];
2585 2590
2586 is_5ghz = ch_idx >= IWM_NUM_2GHZ_CHANNELS; 2591 is_5ghz = ch_idx >= IWM_NUM_2GHZ_CHANNELS;
2587 if (!is_5ghz) { 2592 if (!is_5ghz) {
2588 flags = IEEE80211_CHAN_2GHZ; 2593 flags = IEEE80211_CHAN_2GHZ;
2589 channel->ic_flags 2594 channel->ic_flags
2590 = IEEE80211_CHAN_CCK 2595 = IEEE80211_CHAN_CCK
2591 | IEEE80211_CHAN_OFDM 2596 | IEEE80211_CHAN_OFDM
2592 | IEEE80211_CHAN_DYN 2597 | IEEE80211_CHAN_DYN
2593 | IEEE80211_CHAN_2GHZ; 2598 | IEEE80211_CHAN_2GHZ;
2594 } else { 2599 } else {
2595 flags = IEEE80211_CHAN_5GHZ; 2600 flags = IEEE80211_CHAN_5GHZ;
2596 channel->ic_flags = 2601 channel->ic_flags =
2597 IEEE80211_CHAN_A; 2602 IEEE80211_CHAN_A;
2598 } 2603 }
2599 channel->ic_freq = ieee80211_ieee2mhz(hw_value, flags); 2604 channel->ic_freq = ieee80211_ieee2mhz(hw_value, flags);
2600 2605
2601 if (!(ch_flags & IWM_NVM_CHANNEL_ACTIVE)) 2606 if (!(ch_flags & IWM_NVM_CHANNEL_ACTIVE))
2602 channel->ic_flags |= IEEE80211_CHAN_PASSIVE; 2607 channel->ic_flags |= IEEE80211_CHAN_PASSIVE;
2603 } 2608 }
2604} 2609}
2605 2610
2606static int 2611static int
2607iwm_parse_nvm_data(struct iwm_softc *sc, 2612iwm_parse_nvm_data(struct iwm_softc *sc,
2608 const uint16_t *nvm_hw, const uint16_t *nvm_sw, 2613 const uint16_t *nvm_hw, const uint16_t *nvm_sw,
2609 const uint16_t *nvm_calib, uint8_t tx_chains, uint8_t rx_chains) 2614 const uint16_t *nvm_calib, uint8_t tx_chains, uint8_t rx_chains)
2610{ 2615{
2611 struct iwm_nvm_data *data = &sc->sc_nvm; 2616 struct iwm_nvm_data *data = &sc->sc_nvm;
2612 uint8_t hw_addr[ETHER_ADDR_LEN]; 2617 uint8_t hw_addr[ETHER_ADDR_LEN];
2613 uint16_t radio_cfg, sku; 2618 uint16_t radio_cfg, sku;
2614 2619
2615 data->nvm_version = le16_to_cpup(nvm_sw + IWM_NVM_VERSION); 2620 data->nvm_version = le16_to_cpup(nvm_sw + IWM_NVM_VERSION);
2616 2621
2617 radio_cfg = le16_to_cpup(nvm_sw + IWM_RADIO_CFG); 2622 radio_cfg = le16_to_cpup(nvm_sw + IWM_RADIO_CFG);
2618 data->radio_cfg_type = IWM_NVM_RF_CFG_TYPE_MSK(radio_cfg); 2623 data->radio_cfg_type = IWM_NVM_RF_CFG_TYPE_MSK(radio_cfg);
2619 data->radio_cfg_step = IWM_NVM_RF_CFG_STEP_MSK(radio_cfg); 2624 data->radio_cfg_step = IWM_NVM_RF_CFG_STEP_MSK(radio_cfg);
2620 data->radio_cfg_dash = IWM_NVM_RF_CFG_DASH_MSK(radio_cfg); 2625 data->radio_cfg_dash = IWM_NVM_RF_CFG_DASH_MSK(radio_cfg);
2621 data->radio_cfg_pnum = IWM_NVM_RF_CFG_PNUM_MSK(radio_cfg); 2626 data->radio_cfg_pnum = IWM_NVM_RF_CFG_PNUM_MSK(radio_cfg);
2622 data->valid_tx_ant = IWM_NVM_RF_CFG_TX_ANT_MSK(radio_cfg); 2627 data->valid_tx_ant = IWM_NVM_RF_CFG_TX_ANT_MSK(radio_cfg);
2623 data->valid_rx_ant = IWM_NVM_RF_CFG_RX_ANT_MSK(radio_cfg); 2628 data->valid_rx_ant = IWM_NVM_RF_CFG_RX_ANT_MSK(radio_cfg);
2624 2629
2625 sku = le16_to_cpup(nvm_sw + IWM_SKU); 2630 sku = le16_to_cpup(nvm_sw + IWM_SKU);
2626 data->sku_cap_band_24GHz_enable = sku & IWM_NVM_SKU_CAP_BAND_24GHZ; 2631 data->sku_cap_band_24GHz_enable = sku & IWM_NVM_SKU_CAP_BAND_24GHZ;
2627#ifndef IWM_NO_5GHZ 2632#ifndef IWM_NO_5GHZ
2628 data->sku_cap_band_52GHz_enable = sku & IWM_NVM_SKU_CAP_BAND_52GHZ; 2633 data->sku_cap_band_52GHz_enable = sku & IWM_NVM_SKU_CAP_BAND_52GHZ;
2629#else 2634#else
2630 data->sku_cap_band_52GHz_enable = 0; 2635 data->sku_cap_band_52GHz_enable = 0;
2631#endif 2636#endif
2632 data->sku_cap_11n_enable = 0; 2637 data->sku_cap_11n_enable = 0;
2633 2638
2634 if (!data->valid_tx_ant || !data->valid_rx_ant) { 2639 if (!data->valid_tx_ant || !data->valid_rx_ant) {
2635 DPRINTF(("%s: invalid antennas (0x%x, 0x%x)\n", DEVNAME(sc), 2640 DPRINTF(("%s: invalid antennas (0x%x, 0x%x)\n", DEVNAME(sc),
2636 data->valid_tx_ant, data->valid_rx_ant)); 2641 data->valid_tx_ant, data->valid_rx_ant));
2637 return EINVAL; 2642 return EINVAL;
2638 } 2643 }
2639 2644
2640 data->n_hw_addrs = le16_to_cpup(nvm_sw + IWM_N_HW_ADDRS); 2645 data->n_hw_addrs = le16_to_cpup(nvm_sw + IWM_N_HW_ADDRS);
2641 2646
2642 data->xtal_calib[0] = *(nvm_calib + IWM_XTAL_CALIB); 2647 data->xtal_calib[0] = *(nvm_calib + IWM_XTAL_CALIB);
2643 data->xtal_calib[1] = *(nvm_calib + IWM_XTAL_CALIB + 1); 2648 data->xtal_calib[1] = *(nvm_calib + IWM_XTAL_CALIB + 1);
2644 2649
2645 /* The byte order is little endian 16 bit, meaning 214365 */ 2650 /* The byte order is little endian 16 bit, meaning 214365 */
2646 memcpy(hw_addr, nvm_hw + IWM_HW_ADDR, ETHER_ADDR_LEN); 2651 memcpy(hw_addr, nvm_hw + IWM_HW_ADDR, ETHER_ADDR_LEN);
2647 data->hw_addr[0] = hw_addr[1]; 2652 data->hw_addr[0] = hw_addr[1];
2648 data->hw_addr[1] = hw_addr[0]; 2653 data->hw_addr[1] = hw_addr[0];
2649 data->hw_addr[2] = hw_addr[3]; 2654 data->hw_addr[2] = hw_addr[3];
2650 data->hw_addr[3] = hw_addr[2]; 2655 data->hw_addr[3] = hw_addr[2];
2651 data->hw_addr[4] = hw_addr[5]; 2656 data->hw_addr[4] = hw_addr[5];
2652 data->hw_addr[5] = hw_addr[4]; 2657 data->hw_addr[5] = hw_addr[4];
2653 2658
2654 iwm_init_channel_map(sc, &nvm_sw[IWM_NVM_CHANNELS]); 2659 iwm_init_channel_map(sc, &nvm_sw[IWM_NVM_CHANNELS]);
2655 data->calib_version = 255; /* TODO: 2660 data->calib_version = 255; /* TODO:
2656 this value will prevent some checks from 2661 this value will prevent some checks from
2657 failing, we need to check if this 2662 failing, we need to check if this
2658 field is still needed, and if it does, 2663 field is still needed, and if it does,
2659 where is it in the NVM */ 2664 where is it in the NVM */
2660 2665
2661 return 0; 2666 return 0;
2662} 2667}
2663 2668
2664/* 2669/*
2665 * END NVM PARSE 2670 * END NVM PARSE
2666 */ 2671 */
2667 2672
2668struct iwm_nvm_section { 2673struct iwm_nvm_section {
2669 uint16_t length; 2674 uint16_t length;
2670 const uint8_t *data; 2675 const uint8_t *data;
2671}; 2676};
2672 2677
2673#define IWM_FW_VALID_TX_ANT(sc) \ 2678#define IWM_FW_VALID_TX_ANT(sc) \
2674 ((sc->sc_fw_phy_config & IWM_FW_PHY_CFG_TX_CHAIN) \ 2679 ((sc->sc_fw_phy_config & IWM_FW_PHY_CFG_TX_CHAIN) \
2675 >> IWM_FW_PHY_CFG_TX_CHAIN_POS) 2680 >> IWM_FW_PHY_CFG_TX_CHAIN_POS)
2676#define IWM_FW_VALID_RX_ANT(sc) \ 2681#define IWM_FW_VALID_RX_ANT(sc) \
2677 ((sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RX_CHAIN) \ 2682 ((sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RX_CHAIN) \
2678 >> IWM_FW_PHY_CFG_RX_CHAIN_POS) 2683 >> IWM_FW_PHY_CFG_RX_CHAIN_POS)
2679 2684
2680static int 2685static int
2681iwm_parse_nvm_sections(struct iwm_softc *sc, struct iwm_nvm_section *sections) 2686iwm_parse_nvm_sections(struct iwm_softc *sc, struct iwm_nvm_section *sections)
2682{ 2687{
2683 const uint16_t *hw, *sw, *calib; 2688 const uint16_t *hw, *sw, *calib;
2684 2689
2685 /* Checking for required sections */ 2690 /* Checking for required sections */
2686 if (!sections[IWM_NVM_SECTION_TYPE_SW].data || 2691 if (!sections[IWM_NVM_SECTION_TYPE_SW].data ||
2687 !sections[IWM_NVM_SECTION_TYPE_HW].data) { 2692 !sections[IWM_NVM_SECTION_TYPE_HW].data) {
2688 DPRINTF(("%s: Can't parse empty NVM sections\n", DEVNAME(sc))); 2693 DPRINTF(("%s: Can't parse empty NVM sections\n", DEVNAME(sc)));
2689 return ENOENT; 2694 return ENOENT;
2690 } 2695 }
2691 2696
2692 hw = (const uint16_t *)sections[IWM_NVM_SECTION_TYPE_HW].data; 2697 hw = (const uint16_t *)sections[IWM_NVM_SECTION_TYPE_HW].data;
2693 sw = (const uint16_t *)sections[IWM_NVM_SECTION_TYPE_SW].data; 2698 sw = (const uint16_t *)sections[IWM_NVM_SECTION_TYPE_SW].data;
2694 calib = (const uint16_t *)sections[IWM_NVM_SECTION_TYPE_CALIBRATION].data; 2699 calib = (const uint16_t *)sections[IWM_NVM_SECTION_TYPE_CALIBRATION].data;
2695 return iwm_parse_nvm_data(sc, hw, sw, calib, 2700 return iwm_parse_nvm_data(sc, hw, sw, calib,
2696 IWM_FW_VALID_TX_ANT(sc), IWM_FW_VALID_RX_ANT(sc)); 2701 IWM_FW_VALID_TX_ANT(sc), IWM_FW_VALID_RX_ANT(sc));
2697} 2702}
2698 2703
2699static int 2704static int
2700iwm_nvm_init(struct iwm_softc *sc) 2705iwm_nvm_init(struct iwm_softc *sc)
2701{ 2706{
2702 struct iwm_nvm_section nvm_sections[IWM_NVM_NUM_OF_SECTIONS]; 2707 struct iwm_nvm_section nvm_sections[IWM_NVM_NUM_OF_SECTIONS];
2703 int i, section, error; 2708 int i, section, error;
2704 uint16_t len; 2709 uint16_t len;
2705 uint8_t *nvm_buffer, *temp; 2710 uint8_t *nvm_buffer, *temp;
2706 2711
2707 /* Read From FW NVM */ 2712 /* Read From FW NVM */
2708 DPRINTF(("Read NVM\n")); 2713 DPRINTF(("Read NVM\n"));
2709 2714
2710 /* TODO: find correct NVM max size for a section */ 2715 /* TODO: find correct NVM max size for a section */
2711 nvm_buffer = kmem_alloc(IWM_OTP_LOW_IMAGE_SIZE, KM_SLEEP); 2716 nvm_buffer = kmem_alloc(IWM_OTP_LOW_IMAGE_SIZE, KM_SLEEP);
2712 for (i = 0; i < __arraycount(nvm_to_read); i++) { 2717 for (i = 0; i < __arraycount(nvm_to_read); i++) {
2713 section = nvm_to_read[i]; 2718 section = nvm_to_read[i];
2714 KASSERT(section <= __arraycount(nvm_sections)); 2719 KASSERT(section <= __arraycount(nvm_sections));
2715 2720
2716 error = iwm_nvm_read_section(sc, section, nvm_buffer, &len); 2721 error = iwm_nvm_read_section(sc, section, nvm_buffer, &len);
2717 if (error) 2722 if (error)
2718 break; 2723 break;
2719 2724
2720 temp = kmem_alloc(len, KM_SLEEP); 2725 temp = kmem_alloc(len, KM_SLEEP);
2721 memcpy(temp, nvm_buffer, len); 2726 memcpy(temp, nvm_buffer, len);
2722 nvm_sections[section].data = temp; 2727 nvm_sections[section].data = temp;
2723 nvm_sections[section].length = len; 2728 nvm_sections[section].length = len;
2724 } 2729 }
2725 kmem_free(nvm_buffer, IWM_OTP_LOW_IMAGE_SIZE); 2730 kmem_free(nvm_buffer, IWM_OTP_LOW_IMAGE_SIZE);
2726 if (error) 2731 if (error)
2727 return error; 2732 return error;
2728 2733
2729 return iwm_parse_nvm_sections(sc, nvm_sections); 2734 return iwm_parse_nvm_sections(sc, nvm_sections);
2730} 2735}
2731 2736
2732/* 2737/*
2733 * Firmware loading gunk. This is kind of a weird hybrid between the 2738 * Firmware loading gunk. This is kind of a weird hybrid between the
2734 * iwn driver and the Linux iwlwifi driver. 2739 * iwn driver and the Linux iwlwifi driver.
@@ -5694,1173 +5699,1176 @@ iwm_allow_mcast(struct iwm_softc *sc) @@ -5694,1173 +5699,1176 @@ iwm_allow_mcast(struct iwm_softc *sc)
5694 5699
5695 size = roundup(sizeof(*cmd), 4); 5700 size = roundup(sizeof(*cmd), 4);
5696 cmd = kmem_intr_zalloc(size, KM_NOSLEEP); 5701 cmd = kmem_intr_zalloc(size, KM_NOSLEEP);
5697 if (cmd == NULL) 5702 if (cmd == NULL)
5698 return ENOMEM; 5703 return ENOMEM;
5699 cmd->filter_own = 1; 5704 cmd->filter_own = 1;
5700 cmd->port_id = 0; 5705 cmd->port_id = 0;
5701 cmd->count = 0; 5706 cmd->count = 0;
5702 cmd->pass_all = 1; 5707 cmd->pass_all = 1;
5703 IEEE80211_ADDR_COPY(cmd->bssid, ni->ni_bssid); 5708 IEEE80211_ADDR_COPY(cmd->bssid, ni->ni_bssid);
5704 5709
5705 error = iwm_mvm_send_cmd_pdu(sc, IWM_MCAST_FILTER_CMD, 5710 error = iwm_mvm_send_cmd_pdu(sc, IWM_MCAST_FILTER_CMD,
5706 IWM_CMD_SYNC, size, cmd); 5711 IWM_CMD_SYNC, size, cmd);
5707 kmem_intr_free(cmd, size); 5712 kmem_intr_free(cmd, size);
5708 return error; 5713 return error;
5709} 5714}
5710 5715
5711/* 5716/*
5712 * ifnet interfaces 5717 * ifnet interfaces
5713 */ 5718 */
5714 5719
5715static int 5720static int
5716iwm_init(struct ifnet *ifp) 5721iwm_init(struct ifnet *ifp)
5717{ 5722{
5718 struct iwm_softc *sc = ifp->if_softc; 5723 struct iwm_softc *sc = ifp->if_softc;
5719 int error; 5724 int error;
5720 5725
5721 if (sc->sc_flags & IWM_FLAG_HW_INITED) { 5726 if (sc->sc_flags & IWM_FLAG_HW_INITED) {
5722 return 0; 5727 return 0;
5723 } 5728 }
5724 sc->sc_generation++; 5729 sc->sc_generation++;
5725 sc->sc_flags &= ~IWM_FLAG_STOPPED; 5730 sc->sc_flags &= ~IWM_FLAG_STOPPED;
5726 5731
5727 if ((error = iwm_init_hw(sc)) != 0) { 5732 if ((error = iwm_init_hw(sc)) != 0) {
5728 iwm_stop(ifp, 1); 5733 iwm_stop(ifp, 1);
5729 return error; 5734 return error;
5730 } 5735 }
5731 5736
5732 /* 5737 /*
5733 * Ok, firmware loaded and we are jogging 5738 * Ok, firmware loaded and we are jogging
5734 */ 5739 */
5735 5740
5736 ifp->if_flags &= ~IFF_OACTIVE; 5741 ifp->if_flags &= ~IFF_OACTIVE;
5737 ifp->if_flags |= IFF_RUNNING; 5742 ifp->if_flags |= IFF_RUNNING;
5738 5743
5739 ieee80211_begin_scan(&sc->sc_ic, 0); 5744 ieee80211_begin_scan(&sc->sc_ic, 0);
5740 sc->sc_flags |= IWM_FLAG_HW_INITED; 5745 sc->sc_flags |= IWM_FLAG_HW_INITED;
5741 5746
5742 return 0; 5747 return 0;
5743} 5748}
5744 5749
5745/* 5750/*
5746 * Dequeue packets from sendq and call send. 5751 * Dequeue packets from sendq and call send.
5747 * mostly from iwn 5752 * mostly from iwn
5748 */ 5753 */
5749static void 5754static void
5750iwm_start(struct ifnet *ifp) 5755iwm_start(struct ifnet *ifp)
5751{ 5756{
5752 struct iwm_softc *sc = ifp->if_softc; 5757 struct iwm_softc *sc = ifp->if_softc;
5753 struct ieee80211com *ic = &sc->sc_ic; 5758 struct ieee80211com *ic = &sc->sc_ic;
5754 struct ieee80211_node *ni; 5759 struct ieee80211_node *ni;
5755 struct ether_header *eh; 5760 struct ether_header *eh;
5756 struct mbuf *m; 5761 struct mbuf *m;
5757 int ac; 5762 int ac;
5758 5763
5759 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 5764 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
5760 return; 5765 return;
5761 5766
5762 for (;;) { 5767 for (;;) {
5763 /* why isn't this done per-queue? */ 5768 /* why isn't this done per-queue? */
5764 if (sc->qfullmsk != 0) { 5769 if (sc->qfullmsk != 0) {
5765 ifp->if_flags |= IFF_OACTIVE; 5770 ifp->if_flags |= IFF_OACTIVE;
5766 break; 5771 break;
5767 } 5772 }
5768 5773
5769 /* need to send management frames even if we're not RUNning */ 5774 /* need to send management frames even if we're not RUNning */
5770 IF_DEQUEUE(&ic->ic_mgtq, m); 5775 IF_DEQUEUE(&ic->ic_mgtq, m);
5771 if (m) { 5776 if (m) {
5772 ni = (void *)m->m_pkthdr.rcvif; 5777 ni = (void *)m->m_pkthdr.rcvif;
5773 ac = 0; 5778 ac = 0;
5774 goto sendit; 5779 goto sendit;
5775 } 5780 }
5776 if (ic->ic_state != IEEE80211_S_RUN) { 5781 if (ic->ic_state != IEEE80211_S_RUN) {
5777 break; 5782 break;
5778 } 5783 }
5779 5784
5780 IFQ_DEQUEUE(&ifp->if_snd, m); 5785 IFQ_DEQUEUE(&ifp->if_snd, m);
5781 if (!m) 5786 if (!m)
5782 break; 5787 break;
5783 if (m->m_len < sizeof (*eh) && 5788 if (m->m_len < sizeof (*eh) &&
5784 (m = m_pullup(m, sizeof (*eh))) == NULL) { 5789 (m = m_pullup(m, sizeof (*eh))) == NULL) {
5785 ifp->if_oerrors++; 5790 ifp->if_oerrors++;
5786 continue; 5791 continue;
5787 } 5792 }
5788 if (ifp->if_bpf != NULL) 5793 if (ifp->if_bpf != NULL)
5789 bpf_mtap(ifp, m); 5794 bpf_mtap(ifp, m);
5790 5795
5791 eh = mtod(m, struct ether_header *); 5796 eh = mtod(m, struct ether_header *);
5792 ni = ieee80211_find_txnode(ic, eh->ether_dhost); 5797 ni = ieee80211_find_txnode(ic, eh->ether_dhost);
5793 if (ni == NULL) { 5798 if (ni == NULL) {
5794 m_freem(m); 5799 m_freem(m);
5795 ifp->if_oerrors++; 5800 ifp->if_oerrors++;
5796 continue; 5801 continue;
5797 } 5802 }
5798 /* classify mbuf so we can find which tx ring to use */ 5803 /* classify mbuf so we can find which tx ring to use */
5799 if (ieee80211_classify(ic, m, ni) != 0) { 5804 if (ieee80211_classify(ic, m, ni) != 0) {
5800 m_freem(m); 5805 m_freem(m);
5801 ieee80211_free_node(ni); 5806 ieee80211_free_node(ni);
5802 ifp->if_oerrors++; 5807 ifp->if_oerrors++;
5803 continue; 5808 continue;
5804 } 5809 }
5805 5810
5806 /* No QoS encapsulation for EAPOL frames. */ 5811 /* No QoS encapsulation for EAPOL frames. */
5807 ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ? 5812 ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ?
5808 M_WME_GETAC(m) : WME_AC_BE; 5813 M_WME_GETAC(m) : WME_AC_BE;
5809 5814
5810 if ((m = ieee80211_encap(ic, m, ni)) == NULL) { 5815 if ((m = ieee80211_encap(ic, m, ni)) == NULL) {
5811 ieee80211_free_node(ni); 5816 ieee80211_free_node(ni);
5812 ifp->if_oerrors++; 5817 ifp->if_oerrors++;
5813 continue; 5818 continue;
5814 } 5819 }
5815 5820
5816 sendit: 5821 sendit:
5817 if (ic->ic_rawbpf != NULL) 5822 if (ic->ic_rawbpf != NULL)
5818 bpf_mtap3(ic->ic_rawbpf, m); 5823 bpf_mtap3(ic->ic_rawbpf, m);
5819 if (iwm_tx(sc, m, ni, ac) != 0) { 5824 if (iwm_tx(sc, m, ni, ac) != 0) {
5820 ieee80211_free_node(ni); 5825 ieee80211_free_node(ni);
5821 ifp->if_oerrors++; 5826 ifp->if_oerrors++;
5822 continue; 5827 continue;
5823 } 5828 }
5824 5829
5825 if (ifp->if_flags & IFF_UP) { 5830 if (ifp->if_flags & IFF_UP) {
5826 sc->sc_tx_timer = 15; 5831 sc->sc_tx_timer = 15;
5827 ifp->if_timer = 1; 5832 ifp->if_timer = 1;
5828 } 5833 }
5829 } 5834 }
5830 5835
5831 return; 5836 return;
5832} 5837}
5833 5838
5834static void 5839static void
5835iwm_stop(struct ifnet *ifp, int disable) 5840iwm_stop(struct ifnet *ifp, int disable)
5836{ 5841{
5837 struct iwm_softc *sc = ifp->if_softc; 5842 struct iwm_softc *sc = ifp->if_softc;
5838 struct ieee80211com *ic = &sc->sc_ic; 5843 struct ieee80211com *ic = &sc->sc_ic;
5839 5844
5840 sc->sc_flags &= ~IWM_FLAG_HW_INITED; 5845 sc->sc_flags &= ~IWM_FLAG_HW_INITED;
5841 sc->sc_flags |= IWM_FLAG_STOPPED; 5846 sc->sc_flags |= IWM_FLAG_STOPPED;
5842 sc->sc_generation++; 5847 sc->sc_generation++;
5843 sc->sc_scanband = 0; 5848 sc->sc_scanband = 0;
5844 sc->sc_auth_prot = 0; 5849 sc->sc_auth_prot = 0;
5845 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 5850 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
5846 5851
5847 if (ic->ic_state != IEEE80211_S_INIT) 5852 if (ic->ic_state != IEEE80211_S_INIT)
5848 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 5853 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
5849 5854
5850 ifp->if_timer = sc->sc_tx_timer = 0; 5855 ifp->if_timer = sc->sc_tx_timer = 0;
5851 iwm_stop_device(sc); 5856 iwm_stop_device(sc);
5852} 5857}
5853 5858
5854static void 5859static void
5855iwm_watchdog(struct ifnet *ifp) 5860iwm_watchdog(struct ifnet *ifp)
5856{ 5861{
5857 struct iwm_softc *sc = ifp->if_softc; 5862 struct iwm_softc *sc = ifp->if_softc;
5858 5863
5859 ifp->if_timer = 0; 5864 ifp->if_timer = 0;
5860 if (sc->sc_tx_timer > 0) { 5865 if (sc->sc_tx_timer > 0) {
5861 if (--sc->sc_tx_timer == 0) { 5866 if (--sc->sc_tx_timer == 0) {
5862 aprint_error_dev(sc->sc_dev, "device timeout\n"); 5867 aprint_error_dev(sc->sc_dev, "device timeout\n");
5863#ifdef IWM_DEBUG 5868#ifdef IWM_DEBUG
5864 iwm_nic_error(sc); 5869 iwm_nic_error(sc);
5865#endif 5870#endif
5866 ifp->if_flags &= ~IFF_UP; 5871 ifp->if_flags &= ~IFF_UP;
5867 iwm_stop(ifp, 1); 5872 iwm_stop(ifp, 1);
5868 ifp->if_oerrors++; 5873 ifp->if_oerrors++;
5869 return; 5874 return;
5870 } 5875 }
5871 ifp->if_timer = 1; 5876 ifp->if_timer = 1;
5872 } 5877 }
5873 5878
5874 ieee80211_watchdog(&sc->sc_ic); 5879 ieee80211_watchdog(&sc->sc_ic);
5875} 5880}
5876 5881
5877static int 5882static int
5878iwm_ioctl(struct ifnet *ifp, u_long cmd, void *data) 5883iwm_ioctl(struct ifnet *ifp, u_long cmd, void *data)
5879{ 5884{
5880 struct iwm_softc *sc = ifp->if_softc; 5885 struct iwm_softc *sc = ifp->if_softc;
5881 struct ieee80211com *ic = &sc->sc_ic; 5886 struct ieee80211com *ic = &sc->sc_ic;
5882 const struct sockaddr *sa; 5887 const struct sockaddr *sa;
5883 int s, error = 0; 5888 int s, error = 0;
5884 5889
5885 s = splnet(); 5890 s = splnet();
5886 5891
5887 switch (cmd) { 5892 switch (cmd) {
5888 case SIOCSIFADDR: 5893 case SIOCSIFADDR:
5889 ifp->if_flags |= IFF_UP; 5894 ifp->if_flags |= IFF_UP;
5890 /* FALLTHROUGH */ 5895 /* FALLTHROUGH */
5891 case SIOCSIFFLAGS: 5896 case SIOCSIFFLAGS:
5892 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 5897 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
5893 break; 5898 break;
5894 if (ifp->if_flags & IFF_UP) { 5899 if (ifp->if_flags & IFF_UP) {
5895 if (!(ifp->if_flags & IFF_RUNNING)) { 5900 if (!(ifp->if_flags & IFF_RUNNING)) {
5896 if ((error = iwm_init(ifp)) != 0) 5901 if ((error = iwm_init(ifp)) != 0)
5897 ifp->if_flags &= ~IFF_UP; 5902 ifp->if_flags &= ~IFF_UP;
5898 } 5903 }
5899 } else { 5904 } else {
5900 if (ifp->if_flags & IFF_RUNNING) 5905 if (ifp->if_flags & IFF_RUNNING)
5901 iwm_stop(ifp, 1); 5906 iwm_stop(ifp, 1);
5902 } 5907 }
5903 break; 5908 break;
5904 5909
5905 case SIOCADDMULTI: 5910 case SIOCADDMULTI:
5906 case SIOCDELMULTI: 5911 case SIOCDELMULTI:
5907 sa = ifreq_getaddr(SIOCADDMULTI, (struct ifreq *)data); 5912 sa = ifreq_getaddr(SIOCADDMULTI, (struct ifreq *)data);
5908 error = (cmd == SIOCADDMULTI) ? 5913 error = (cmd == SIOCADDMULTI) ?
5909 ether_addmulti(sa, &sc->sc_ec) : 5914 ether_addmulti(sa, &sc->sc_ec) :
5910 ether_delmulti(sa, &sc->sc_ec); 5915 ether_delmulti(sa, &sc->sc_ec);
5911 5916
5912 if (error == ENETRESET) 5917 if (error == ENETRESET)
5913 error = 0; 5918 error = 0;
5914 break; 5919 break;
5915 5920
5916 default: 5921 default:
5917 error = ieee80211_ioctl(ic, cmd, data); 5922 error = ieee80211_ioctl(ic, cmd, data);
5918 } 5923 }
5919 5924
5920 if (error == ENETRESET) { 5925 if (error == ENETRESET) {
5921 error = 0; 5926 error = 0;
5922 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == 5927 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
5923 (IFF_UP | IFF_RUNNING)) { 5928 (IFF_UP | IFF_RUNNING)) {
5924 iwm_stop(ifp, 0); 5929 iwm_stop(ifp, 0);
5925 error = iwm_init(ifp); 5930 error = iwm_init(ifp);
5926 } 5931 }
5927 } 5932 }
5928 5933
5929 splx(s); 5934 splx(s);
5930 return error; 5935 return error;
5931} 5936}
5932 5937
5933/* 5938/*
5934 * The interrupt side of things 5939 * The interrupt side of things
5935 */ 5940 */
5936 5941
5937/* 5942/*
5938 * error dumping routines are from iwlwifi/mvm/utils.c 5943 * error dumping routines are from iwlwifi/mvm/utils.c
5939 */ 5944 */
5940 5945
5941/* 5946/*
5942 * Note: This structure is read from the device with IO accesses, 5947 * Note: This structure is read from the device with IO accesses,
5943 * and the reading already does the endian conversion. As it is 5948 * and the reading already does the endian conversion. As it is
5944 * read with uint32_t-sized accesses, any members with a different size 5949 * read with uint32_t-sized accesses, any members with a different size
5945 * need to be ordered correctly though! 5950 * need to be ordered correctly though!
5946 */ 5951 */
5947struct iwm_error_event_table { 5952struct iwm_error_event_table {
5948 uint32_t valid; /* (nonzero) valid, (0) log is empty */ 5953 uint32_t valid; /* (nonzero) valid, (0) log is empty */
5949 uint32_t error_id; /* type of error */ 5954 uint32_t error_id; /* type of error */
5950 uint32_t pc; /* program counter */ 5955 uint32_t pc; /* program counter */
5951 uint32_t blink1; /* branch link */ 5956 uint32_t blink1; /* branch link */
5952 uint32_t blink2; /* branch link */ 5957 uint32_t blink2; /* branch link */
5953 uint32_t ilink1; /* interrupt link */ 5958 uint32_t ilink1; /* interrupt link */
5954 uint32_t ilink2; /* interrupt link */ 5959 uint32_t ilink2; /* interrupt link */
5955 uint32_t data1; /* error-specific data */ 5960 uint32_t data1; /* error-specific data */
5956 uint32_t data2; /* error-specific data */ 5961 uint32_t data2; /* error-specific data */
5957 uint32_t data3; /* error-specific data */ 5962 uint32_t data3; /* error-specific data */
5958 uint32_t bcon_time; /* beacon timer */ 5963 uint32_t bcon_time; /* beacon timer */
5959 uint32_t tsf_low; /* network timestamp function timer */ 5964 uint32_t tsf_low; /* network timestamp function timer */
5960 uint32_t tsf_hi; /* network timestamp function timer */ 5965 uint32_t tsf_hi; /* network timestamp function timer */
5961 uint32_t gp1; /* GP1 timer register */ 5966 uint32_t gp1; /* GP1 timer register */
5962 uint32_t gp2; /* GP2 timer register */ 5967 uint32_t gp2; /* GP2 timer register */
5963 uint32_t gp3; /* GP3 timer register */ 5968 uint32_t gp3; /* GP3 timer register */
5964 uint32_t ucode_ver; /* uCode version */ 5969 uint32_t ucode_ver; /* uCode version */
5965 uint32_t hw_ver; /* HW Silicon version */ 5970 uint32_t hw_ver; /* HW Silicon version */
5966 uint32_t brd_ver; /* HW board version */ 5971 uint32_t brd_ver; /* HW board version */
5967 uint32_t log_pc; /* log program counter */ 5972 uint32_t log_pc; /* log program counter */
5968 uint32_t frame_ptr; /* frame pointer */ 5973 uint32_t frame_ptr; /* frame pointer */
5969 uint32_t stack_ptr; /* stack pointer */ 5974 uint32_t stack_ptr; /* stack pointer */
5970 uint32_t hcmd; /* last host command header */ 5975 uint32_t hcmd; /* last host command header */
5971 uint32_t isr0; /* isr status register LMPM_NIC_ISR0: 5976 uint32_t isr0; /* isr status register LMPM_NIC_ISR0:
5972 * rxtx_flag */ 5977 * rxtx_flag */
5973 uint32_t isr1; /* isr status register LMPM_NIC_ISR1: 5978 uint32_t isr1; /* isr status register LMPM_NIC_ISR1:
5974 * host_flag */ 5979 * host_flag */
5975 uint32_t isr2; /* isr status register LMPM_NIC_ISR2: 5980 uint32_t isr2; /* isr status register LMPM_NIC_ISR2:
5976 * enc_flag */ 5981 * enc_flag */
5977 uint32_t isr3; /* isr status register LMPM_NIC_ISR3: 5982 uint32_t isr3; /* isr status register LMPM_NIC_ISR3:
5978 * time_flag */ 5983 * time_flag */
5979 uint32_t isr4; /* isr status register LMPM_NIC_ISR4: 5984 uint32_t isr4; /* isr status register LMPM_NIC_ISR4:
5980 * wico interrupt */ 5985 * wico interrupt */
5981 uint32_t isr_pref; /* isr status register LMPM_NIC_PREF_STAT */ 5986 uint32_t isr_pref; /* isr status register LMPM_NIC_PREF_STAT */
5982 uint32_t wait_event; /* wait event() caller address */ 5987 uint32_t wait_event; /* wait event() caller address */
5983 uint32_t l2p_control; /* L2pControlField */ 5988 uint32_t l2p_control; /* L2pControlField */
5984 uint32_t l2p_duration; /* L2pDurationField */ 5989 uint32_t l2p_duration; /* L2pDurationField */
5985 uint32_t l2p_mhvalid; /* L2pMhValidBits */ 5990 uint32_t l2p_mhvalid; /* L2pMhValidBits */
5986 uint32_t l2p_addr_match; /* L2pAddrMatchStat */ 5991 uint32_t l2p_addr_match; /* L2pAddrMatchStat */
5987 uint32_t lmpm_pmg_sel; /* indicate which clocks are turned on 5992 uint32_t lmpm_pmg_sel; /* indicate which clocks are turned on
5988 * (LMPM_PMG_SEL) */ 5993 * (LMPM_PMG_SEL) */
5989 uint32_t u_timestamp; /* indicate when the date and time of the 5994 uint32_t u_timestamp; /* indicate when the date and time of the
5990 * compilation */ 5995 * compilation */
5991 uint32_t flow_handler; /* FH read/write pointers, RX credit */ 5996 uint32_t flow_handler; /* FH read/write pointers, RX credit */
5992} __packed; 5997} __packed;
5993 5998
5994#define ERROR_START_OFFSET (1 * sizeof(uint32_t)) 5999#define ERROR_START_OFFSET (1 * sizeof(uint32_t))
5995#define ERROR_ELEM_SIZE (7 * sizeof(uint32_t)) 6000#define ERROR_ELEM_SIZE (7 * sizeof(uint32_t))
5996 6001
5997#ifdef IWM_DEBUG 6002#ifdef IWM_DEBUG
5998static const struct { 6003static const struct {
5999 const char *name; 6004 const char *name;
6000 uint8_t num; 6005 uint8_t num;
6001} advanced_lookup[] = { 6006} advanced_lookup[] = {
6002 { "NMI_INTERRUPT_WDG", 0x34 }, 6007 { "NMI_INTERRUPT_WDG", 0x34 },
6003 { "SYSASSERT", 0x35 }, 6008 { "SYSASSERT", 0x35 },
6004 { "UCODE_VERSION_MISMATCH", 0x37 }, 6009 { "UCODE_VERSION_MISMATCH", 0x37 },
6005 { "BAD_COMMAND", 0x38 }, 6010 { "BAD_COMMAND", 0x38 },
6006 { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C }, 6011 { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
6007 { "FATAL_ERROR", 0x3D }, 6012 { "FATAL_ERROR", 0x3D },
6008 { "NMI_TRM_HW_ERR", 0x46 }, 6013 { "NMI_TRM_HW_ERR", 0x46 },
6009 { "NMI_INTERRUPT_TRM", 0x4C }, 6014 { "NMI_INTERRUPT_TRM", 0x4C },
6010 { "NMI_INTERRUPT_BREAK_POINT", 0x54 }, 6015 { "NMI_INTERRUPT_BREAK_POINT", 0x54 },
6011 { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C }, 6016 { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C },
6012 { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 }, 6017 { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 },
6013 { "NMI_INTERRUPT_HOST", 0x66 }, 6018 { "NMI_INTERRUPT_HOST", 0x66 },
6014 { "NMI_INTERRUPT_ACTION_PT", 0x7C }, 6019 { "NMI_INTERRUPT_ACTION_PT", 0x7C },
6015 { "NMI_INTERRUPT_UNKNOWN", 0x84 }, 6020 { "NMI_INTERRUPT_UNKNOWN", 0x84 },
6016 { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 }, 6021 { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 },
6017 { "ADVANCED_SYSASSERT", 0 }, 6022 { "ADVANCED_SYSASSERT", 0 },
6018}; 6023};
6019 6024
6020static const char * 6025static const char *
6021iwm_desc_lookup(uint32_t num) 6026iwm_desc_lookup(uint32_t num)
6022{ 6027{
6023 int i; 6028 int i;
6024 6029
6025 for (i = 0; i < __arraycount(advanced_lookup) - 1; i++) 6030 for (i = 0; i < __arraycount(advanced_lookup) - 1; i++)
6026 if (advanced_lookup[i].num == num) 6031 if (advanced_lookup[i].num == num)
6027 return advanced_lookup[i].name; 6032 return advanced_lookup[i].name;
6028 6033
6029 /* No entry matches 'num', so it is the last: ADVANCED_SYSASSERT */ 6034 /* No entry matches 'num', so it is the last: ADVANCED_SYSASSERT */
6030 return advanced_lookup[i].name; 6035 return advanced_lookup[i].name;
6031} 6036}
6032 6037
6033/* 6038/*
6034 * Support for dumping the error log seemed like a good idea ... 6039 * Support for dumping the error log seemed like a good idea ...
6035 * but it's mostly hex junk and the only sensible thing is the 6040 * but it's mostly hex junk and the only sensible thing is the
6036 * hw/ucode revision (which we know anyway). Since it's here, 6041 * hw/ucode revision (which we know anyway). Since it's here,
6037 * I'll just leave it in, just in case e.g. the Intel guys want to 6042 * I'll just leave it in, just in case e.g. the Intel guys want to
6038 * help us decipher some "ADVANCED_SYSASSERT" later. 6043 * help us decipher some "ADVANCED_SYSASSERT" later.
6039 */ 6044 */
6040static void 6045static void
6041iwm_nic_error(struct iwm_softc *sc) 6046iwm_nic_error(struct iwm_softc *sc)
6042{ 6047{
6043 struct iwm_error_event_table table; 6048 struct iwm_error_event_table table;
6044 uint32_t base; 6049 uint32_t base;
6045 6050
6046 aprint_error_dev(sc->sc_dev, "dumping device error log\n"); 6051 aprint_error_dev(sc->sc_dev, "dumping device error log\n");
6047 base = sc->sc_uc.uc_error_event_table; 6052 base = sc->sc_uc.uc_error_event_table;
6048 if (base < 0x800000 || base >= 0x80C000) { 6053 if (base < 0x800000 || base >= 0x80C000) {
6049 aprint_error_dev(sc->sc_dev, 6054 aprint_error_dev(sc->sc_dev,
6050 "Not valid error log pointer 0x%08x\n", base); 6055 "Not valid error log pointer 0x%08x\n", base);
6051 return; 6056 return;
6052 } 6057 }
6053 6058
6054 if (iwm_read_mem(sc, base, &table, sizeof(table)/sizeof(uint32_t)) != 0) { 6059 if (iwm_read_mem(sc, base, &table, sizeof(table)/sizeof(uint32_t)) != 0) {
6055 aprint_error_dev(sc->sc_dev, "reading errlog failed\n"); 6060 aprint_error_dev(sc->sc_dev, "reading errlog failed\n");
6056 return; 6061 return;
6057 } 6062 }
6058 6063
6059 if (!table.valid) { 6064 if (!table.valid) {
6060 aprint_error_dev(sc->sc_dev, "errlog not found, skipping\n"); 6065 aprint_error_dev(sc->sc_dev, "errlog not found, skipping\n");
6061 return; 6066 return;
6062 } 6067 }
6063 6068
6064 if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { 6069 if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
6065 aprint_error_dev(sc->sc_dev, "Start IWL Error Log Dump:\n"); 6070 aprint_error_dev(sc->sc_dev, "Start IWL Error Log Dump:\n");
6066 aprint_error_dev(sc->sc_dev, "Status: 0x%x, count: %d\n", 6071 aprint_error_dev(sc->sc_dev, "Status: 0x%x, count: %d\n",
6067 sc->sc_flags, table.valid); 6072 sc->sc_flags, table.valid);
6068 } 6073 }
6069 6074
6070 aprint_error_dev(sc->sc_dev, "%08X | %-28s\n", table.error_id, 6075 aprint_error_dev(sc->sc_dev, "%08X | %-28s\n", table.error_id,
6071 iwm_desc_lookup(table.error_id)); 6076 iwm_desc_lookup(table.error_id));
6072 aprint_error_dev(sc->sc_dev, "%08X | uPc\n", table.pc); 6077 aprint_error_dev(sc->sc_dev, "%08X | uPc\n", table.pc);
6073 aprint_error_dev(sc->sc_dev, "%08X | branchlink1\n", table.blink1); 6078 aprint_error_dev(sc->sc_dev, "%08X | branchlink1\n", table.blink1);
6074 aprint_error_dev(sc->sc_dev, "%08X | branchlink2\n", table.blink2); 6079 aprint_error_dev(sc->sc_dev, "%08X | branchlink2\n", table.blink2);
6075 aprint_error_dev(sc->sc_dev, "%08X | interruptlink1\n", table.ilink1); 6080 aprint_error_dev(sc->sc_dev, "%08X | interruptlink1\n", table.ilink1);
6076 aprint_error_dev(sc->sc_dev, "%08X | interruptlink2\n", table.ilink2); 6081 aprint_error_dev(sc->sc_dev, "%08X | interruptlink2\n", table.ilink2);
6077 aprint_error_dev(sc->sc_dev, "%08X | data1\n", table.data1); 6082 aprint_error_dev(sc->sc_dev, "%08X | data1\n", table.data1);
6078 aprint_error_dev(sc->sc_dev, "%08X | data2\n", table.data2); 6083 aprint_error_dev(sc->sc_dev, "%08X | data2\n", table.data2);
6079 aprint_error_dev(sc->sc_dev, "%08X | data3\n", table.data3); 6084 aprint_error_dev(sc->sc_dev, "%08X | data3\n", table.data3);
6080 aprint_error_dev(sc->sc_dev, "%08X | beacon time\n", table.bcon_time); 6085 aprint_error_dev(sc->sc_dev, "%08X | beacon time\n", table.bcon_time);
6081 aprint_error_dev(sc->sc_dev, "%08X | tsf low\n", table.tsf_low); 6086 aprint_error_dev(sc->sc_dev, "%08X | tsf low\n", table.tsf_low);
6082 aprint_error_dev(sc->sc_dev, "%08X | tsf hi\n", table.tsf_hi); 6087 aprint_error_dev(sc->sc_dev, "%08X | tsf hi\n", table.tsf_hi);
6083 aprint_error_dev(sc->sc_dev, "%08X | time gp1\n", table.gp1); 6088 aprint_error_dev(sc->sc_dev, "%08X | time gp1\n", table.gp1);
6084 aprint_error_dev(sc->sc_dev, "%08X | time gp2\n", table.gp2); 6089 aprint_error_dev(sc->sc_dev, "%08X | time gp2\n", table.gp2);
6085 aprint_error_dev(sc->sc_dev, "%08X | time gp3\n", table.gp3); 6090 aprint_error_dev(sc->sc_dev, "%08X | time gp3\n", table.gp3);
6086 aprint_error_dev(sc->sc_dev, "%08X | uCode version\n", table.ucode_ver); 6091 aprint_error_dev(sc->sc_dev, "%08X | uCode version\n", table.ucode_ver);
6087 aprint_error_dev(sc->sc_dev, "%08X | hw version\n", table.hw_ver); 6092 aprint_error_dev(sc->sc_dev, "%08X | hw version\n", table.hw_ver);
6088 aprint_error_dev(sc->sc_dev, "%08X | board version\n", table.brd_ver); 6093 aprint_error_dev(sc->sc_dev, "%08X | board version\n", table.brd_ver);
6089 aprint_error_dev(sc->sc_dev, "%08X | hcmd\n", table.hcmd); 6094 aprint_error_dev(sc->sc_dev, "%08X | hcmd\n", table.hcmd);
6090 aprint_error_dev(sc->sc_dev, "%08X | isr0\n", table.isr0); 6095 aprint_error_dev(sc->sc_dev, "%08X | isr0\n", table.isr0);
6091 aprint_error_dev(sc->sc_dev, "%08X | isr1\n", table.isr1); 6096 aprint_error_dev(sc->sc_dev, "%08X | isr1\n", table.isr1);
6092 aprint_error_dev(sc->sc_dev, "%08X | isr2\n", table.isr2); 6097 aprint_error_dev(sc->sc_dev, "%08X | isr2\n", table.isr2);
6093 aprint_error_dev(sc->sc_dev, "%08X | isr3\n", table.isr3); 6098 aprint_error_dev(sc->sc_dev, "%08X | isr3\n", table.isr3);
6094 aprint_error_dev(sc->sc_dev, "%08X | isr4\n", table.isr4); 6099 aprint_error_dev(sc->sc_dev, "%08X | isr4\n", table.isr4);
6095 aprint_error_dev(sc->sc_dev, "%08X | isr_pref\n", table.isr_pref); 6100 aprint_error_dev(sc->sc_dev, "%08X | isr_pref\n", table.isr_pref);
6096 aprint_error_dev(sc->sc_dev, "%08X | wait_event\n", table.wait_event); 6101 aprint_error_dev(sc->sc_dev, "%08X | wait_event\n", table.wait_event);
6097 aprint_error_dev(sc->sc_dev, "%08X | l2p_control\n", table.l2p_control); 6102 aprint_error_dev(sc->sc_dev, "%08X | l2p_control\n", table.l2p_control);
6098 aprint_error_dev(sc->sc_dev, "%08X | l2p_duration\n", 6103 aprint_error_dev(sc->sc_dev, "%08X | l2p_duration\n",
6099 table.l2p_duration); 6104 table.l2p_duration);
6100 aprint_error_dev(sc->sc_dev, "%08X | l2p_mhvalid\n", table.l2p_mhvalid); 6105 aprint_error_dev(sc->sc_dev, "%08X | l2p_mhvalid\n", table.l2p_mhvalid);
6101 aprint_error_dev(sc->sc_dev, "%08X | l2p_addr_match\n", 6106 aprint_error_dev(sc->sc_dev, "%08X | l2p_addr_match\n",
6102 table.l2p_addr_match); 6107 table.l2p_addr_match);
6103 aprint_error_dev(sc->sc_dev, "%08X | lmpm_pmg_sel\n", 6108 aprint_error_dev(sc->sc_dev, "%08X | lmpm_pmg_sel\n",
6104 table.lmpm_pmg_sel); 6109 table.lmpm_pmg_sel);
6105 aprint_error_dev(sc->sc_dev, "%08X | timestamp\n", table.u_timestamp); 6110 aprint_error_dev(sc->sc_dev, "%08X | timestamp\n", table.u_timestamp);
6106 aprint_error_dev(sc->sc_dev, "%08X | flow_handler\n", 6111 aprint_error_dev(sc->sc_dev, "%08X | flow_handler\n",
6107 table.flow_handler); 6112 table.flow_handler);
6108} 6113}
6109#endif 6114#endif
6110 6115
6111#define SYNC_RESP_STRUCT(_var_, _pkt_) \ 6116#define SYNC_RESP_STRUCT(_var_, _pkt_) \
6112do { \ 6117do { \
6113 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*(_pkt_)), \ 6118 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*(_pkt_)), \
6114 sizeof(*(_var_)), BUS_DMASYNC_POSTREAD); \ 6119 sizeof(*(_var_)), BUS_DMASYNC_POSTREAD); \
6115 _var_ = (void *)((_pkt_)+1); \ 6120 _var_ = (void *)((_pkt_)+1); \
6116} while (/*CONSTCOND*/0) 6121} while (/*CONSTCOND*/0)
6117 6122
6118#define SYNC_RESP_PTR(_ptr_, _len_, _pkt_) \ 6123#define SYNC_RESP_PTR(_ptr_, _len_, _pkt_) \
6119do { \ 6124do { \
6120 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*(_pkt_)), \ 6125 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*(_pkt_)), \
6121 sizeof(len), BUS_DMASYNC_POSTREAD); \ 6126 sizeof(len), BUS_DMASYNC_POSTREAD); \
6122 _ptr_ = (void *)((_pkt_)+1); \ 6127 _ptr_ = (void *)((_pkt_)+1); \
6123} while (/*CONSTCOND*/0) 6128} while (/*CONSTCOND*/0)
6124 6129
6125#define ADVANCE_RXQ(sc) (sc->rxq.cur = (sc->rxq.cur + 1) % IWM_RX_RING_COUNT); 6130#define ADVANCE_RXQ(sc) (sc->rxq.cur = (sc->rxq.cur + 1) % IWM_RX_RING_COUNT);
6126 6131
6127/* 6132/*
6128 * Process an IWM_CSR_INT_BIT_FH_RX or IWM_CSR_INT_BIT_SW_RX interrupt. 6133 * Process an IWM_CSR_INT_BIT_FH_RX or IWM_CSR_INT_BIT_SW_RX interrupt.
6129 * Basic structure from if_iwn 6134 * Basic structure from if_iwn
6130 */ 6135 */
6131static void 6136static void
6132iwm_notif_intr(struct iwm_softc *sc) 6137iwm_notif_intr(struct iwm_softc *sc)
6133{ 6138{
6134 uint16_t hw; 6139 uint16_t hw;
6135 6140
6136 bus_dmamap_sync(sc->sc_dmat, sc->rxq.stat_dma.map, 6141 bus_dmamap_sync(sc->sc_dmat, sc->rxq.stat_dma.map,
6137 0, sc->rxq.stat_dma.size, BUS_DMASYNC_POSTREAD); 6142 0, sc->rxq.stat_dma.size, BUS_DMASYNC_POSTREAD);
6138 6143
6139 hw = le16toh(sc->rxq.stat->closed_rb_num) & 0xfff; 6144 hw = le16toh(sc->rxq.stat->closed_rb_num) & 0xfff;
6140 while (sc->rxq.cur != hw) { 6145 while (sc->rxq.cur != hw) {
6141 struct iwm_rx_data *data = &sc->rxq.data[sc->rxq.cur]; 6146 struct iwm_rx_data *data = &sc->rxq.data[sc->rxq.cur];
6142 struct iwm_rx_packet *pkt, tmppkt; 6147 struct iwm_rx_packet *pkt, tmppkt;
6143 struct iwm_cmd_response *cresp; 6148 struct iwm_cmd_response *cresp;
6144 int qid, idx; 6149 int qid, idx;
6145 6150
6146 bus_dmamap_sync(sc->sc_dmat, data->map, 0, sizeof(*pkt), 6151 bus_dmamap_sync(sc->sc_dmat, data->map, 0, sizeof(*pkt),
6147 BUS_DMASYNC_POSTREAD); 6152 BUS_DMASYNC_POSTREAD);
6148 pkt = mtod(data->m, struct iwm_rx_packet *); 6153 pkt = mtod(data->m, struct iwm_rx_packet *);
6149 6154
6150 qid = pkt->hdr.qid & ~0x80; 6155 qid = pkt->hdr.qid & ~0x80;
6151 idx = pkt->hdr.idx; 6156 idx = pkt->hdr.idx;
6152 6157
6153 DPRINTFN(12, ("rx packet qid=%d idx=%d flags=%x type=%x %d %d\n", 6158 DPRINTFN(12, ("rx packet qid=%d idx=%d flags=%x type=%x %d %d\n",
6154 pkt->hdr.qid & ~0x80, pkt->hdr.idx, pkt->hdr.flags, 6159 pkt->hdr.qid & ~0x80, pkt->hdr.idx, pkt->hdr.flags,
6155 pkt->hdr.code, sc->rxq.cur, hw)); 6160 pkt->hdr.code, sc->rxq.cur, hw));
6156 6161
6157 /* 6162 /*
6158 * randomly get these from the firmware, no idea why. 6163 * randomly get these from the firmware, no idea why.
6159 * they at least seem harmless, so just ignore them for now 6164 * they at least seem harmless, so just ignore them for now
6160 */ 6165 */
6161 if (__predict_false((pkt->hdr.code == 0 && qid == 0 && idx == 0) 6166 if (__predict_false((pkt->hdr.code == 0 && qid == 0 && idx == 0)
6162 || pkt->len_n_flags == htole32(0x55550000))) { 6167 || pkt->len_n_flags == htole32(0x55550000))) {
6163 ADVANCE_RXQ(sc); 6168 ADVANCE_RXQ(sc);
6164 continue; 6169 continue;
6165 } 6170 }
6166 6171
6167 switch (pkt->hdr.code) { 6172 switch (pkt->hdr.code) {
6168 case IWM_REPLY_RX_PHY_CMD: 6173 case IWM_REPLY_RX_PHY_CMD:
6169 iwm_mvm_rx_rx_phy_cmd(sc, pkt, data); 6174 iwm_mvm_rx_rx_phy_cmd(sc, pkt, data);
6170 break; 6175 break;
6171 6176
6172 case IWM_REPLY_RX_MPDU_CMD: 6177 case IWM_REPLY_RX_MPDU_CMD:
6173 tmppkt = *pkt; // XXX m is freed by ieee80211_input() 6178 tmppkt = *pkt; // XXX m is freed by ieee80211_input()
6174 iwm_mvm_rx_rx_mpdu(sc, pkt, data); 6179 iwm_mvm_rx_rx_mpdu(sc, pkt, data);
6175 pkt = &tmppkt; 6180 pkt = &tmppkt;
6176 break; 6181 break;
6177 6182
6178 case IWM_TX_CMD: 6183 case IWM_TX_CMD:
6179 iwm_mvm_rx_tx_cmd(sc, pkt, data); 6184 iwm_mvm_rx_tx_cmd(sc, pkt, data);
6180 break; 6185 break;
6181 6186
6182 case IWM_MISSED_BEACONS_NOTIFICATION: 6187 case IWM_MISSED_BEACONS_NOTIFICATION:
6183 iwm_mvm_rx_missed_beacons_notif(sc, pkt, data); 6188 iwm_mvm_rx_missed_beacons_notif(sc, pkt, data);
6184 break; 6189 break;
6185 6190
6186 case IWM_MVM_ALIVE: { 6191 case IWM_MVM_ALIVE: {
6187 struct iwm_mvm_alive_resp *resp; 6192 struct iwm_mvm_alive_resp *resp;
6188 SYNC_RESP_STRUCT(resp, pkt); 6193 SYNC_RESP_STRUCT(resp, pkt);
6189 6194
6190 sc->sc_uc.uc_error_event_table 6195 sc->sc_uc.uc_error_event_table
6191 = le32toh(resp->error_event_table_ptr); 6196 = le32toh(resp->error_event_table_ptr);
6192 sc->sc_uc.uc_log_event_table 6197 sc->sc_uc.uc_log_event_table
6193 = le32toh(resp->log_event_table_ptr); 6198 = le32toh(resp->log_event_table_ptr);
6194 sc->sched_base = le32toh(resp->scd_base_ptr); 6199 sc->sched_base = le32toh(resp->scd_base_ptr);
6195 sc->sc_uc.uc_ok = resp->status == IWM_ALIVE_STATUS_OK; 6200 sc->sc_uc.uc_ok = resp->status == IWM_ALIVE_STATUS_OK;
6196 6201
6197 sc->sc_uc.uc_intr = 1; 6202 sc->sc_uc.uc_intr = 1;
6198 wakeup(&sc->sc_uc); 6203 wakeup(&sc->sc_uc);
6199 break; } 6204 break; }
6200 6205
6201 case IWM_CALIB_RES_NOTIF_PHY_DB: { 6206 case IWM_CALIB_RES_NOTIF_PHY_DB: {
6202 struct iwm_calib_res_notif_phy_db *phy_db_notif; 6207 struct iwm_calib_res_notif_phy_db *phy_db_notif;
6203 SYNC_RESP_STRUCT(phy_db_notif, pkt); 6208 SYNC_RESP_STRUCT(phy_db_notif, pkt);
6204 6209
6205 uint16_t size = le16toh(phy_db_notif->length); 6210 uint16_t size = le16toh(phy_db_notif->length);
6206 bus_dmamap_sync(sc->sc_dmat, data->map, 6211 bus_dmamap_sync(sc->sc_dmat, data->map,
6207 sizeof(*pkt) + sizeof(*phy_db_notif), 6212 sizeof(*pkt) + sizeof(*phy_db_notif),
6208 size, BUS_DMASYNC_POSTREAD); 6213 size, BUS_DMASYNC_POSTREAD);
6209 iwm_phy_db_set_section(sc, phy_db_notif, size); 6214 iwm_phy_db_set_section(sc, phy_db_notif, size);
6210 6215
6211 break; } 6216 break; }
6212 6217
6213 case IWM_STATISTICS_NOTIFICATION: { 6218 case IWM_STATISTICS_NOTIFICATION: {
6214 struct iwm_notif_statistics *stats; 6219 struct iwm_notif_statistics *stats;
6215 SYNC_RESP_STRUCT(stats, pkt); 6220 SYNC_RESP_STRUCT(stats, pkt);
6216 memcpy(&sc->sc_stats, stats, sizeof(sc->sc_stats)); 6221 memcpy(&sc->sc_stats, stats, sizeof(sc->sc_stats));
6217 sc->sc_noise = iwm_get_noise(&stats->rx.general); 6222 sc->sc_noise = iwm_get_noise(&stats->rx.general);
6218 break; } 6223 break; }
6219 6224
6220 case IWM_NVM_ACCESS_CMD: 6225 case IWM_NVM_ACCESS_CMD:
6221 if (sc->sc_wantresp == ((qid << 16) | idx)) { 6226 if (sc->sc_wantresp == ((qid << 16) | idx)) {
6222 bus_dmamap_sync(sc->sc_dmat, data->map, 0, 6227 bus_dmamap_sync(sc->sc_dmat, data->map, 0,
6223 sizeof(sc->sc_cmd_resp), 6228 sizeof(sc->sc_cmd_resp),
6224 BUS_DMASYNC_POSTREAD); 6229 BUS_DMASYNC_POSTREAD);
6225 memcpy(sc->sc_cmd_resp, 6230 memcpy(sc->sc_cmd_resp,
6226 pkt, sizeof(sc->sc_cmd_resp)); 6231 pkt, sizeof(sc->sc_cmd_resp));
6227 } 6232 }
6228 break; 6233 break;
6229 6234
6230 case IWM_PHY_CONFIGURATION_CMD: 6235 case IWM_PHY_CONFIGURATION_CMD:
6231 case IWM_TX_ANT_CONFIGURATION_CMD: 6236 case IWM_TX_ANT_CONFIGURATION_CMD:
6232 case IWM_ADD_STA: 6237 case IWM_ADD_STA:
6233 case IWM_MAC_CONTEXT_CMD: 6238 case IWM_MAC_CONTEXT_CMD:
6234 case IWM_REPLY_SF_CFG_CMD: 6239 case IWM_REPLY_SF_CFG_CMD:
6235 case IWM_POWER_TABLE_CMD: 6240 case IWM_POWER_TABLE_CMD:
6236 case IWM_PHY_CONTEXT_CMD: 6241 case IWM_PHY_CONTEXT_CMD:
6237 case IWM_BINDING_CONTEXT_CMD: 6242 case IWM_BINDING_CONTEXT_CMD:
6238 case IWM_TIME_EVENT_CMD: 6243 case IWM_TIME_EVENT_CMD:
6239 case IWM_SCAN_REQUEST_CMD: 6244 case IWM_SCAN_REQUEST_CMD:
6240 case IWM_REPLY_BEACON_FILTERING_CMD: 6245 case IWM_REPLY_BEACON_FILTERING_CMD:
6241 case IWM_MAC_PM_POWER_TABLE: 6246 case IWM_MAC_PM_POWER_TABLE:
6242 case IWM_TIME_QUOTA_CMD: 6247 case IWM_TIME_QUOTA_CMD:
6243 case IWM_REMOVE_STA: 6248 case IWM_REMOVE_STA:
6244 case IWM_TXPATH_FLUSH: 6249 case IWM_TXPATH_FLUSH:
6245 case IWM_LQ_CMD: 6250 case IWM_LQ_CMD:
6246 SYNC_RESP_STRUCT(cresp, pkt); 6251 SYNC_RESP_STRUCT(cresp, pkt);
6247 if (sc->sc_wantresp == ((qid << 16) | idx)) { 6252 if (sc->sc_wantresp == ((qid << 16) | idx)) {
6248 memcpy(sc->sc_cmd_resp, 6253 memcpy(sc->sc_cmd_resp,
6249 pkt, sizeof(*pkt)+sizeof(*cresp)); 6254 pkt, sizeof(*pkt)+sizeof(*cresp));
6250 } 6255 }
6251 break; 6256 break;
6252 6257
6253 /* ignore */ 6258 /* ignore */
6254 case 0x6c: /* IWM_PHY_DB_CMD, no idea why it's not in fw-api.h */ 6259 case 0x6c: /* IWM_PHY_DB_CMD, no idea why it's not in fw-api.h */
6255 break; 6260 break;
6256 6261
6257 case IWM_INIT_COMPLETE_NOTIF: 6262 case IWM_INIT_COMPLETE_NOTIF:
6258 sc->sc_init_complete = 1; 6263 sc->sc_init_complete = 1;
6259 wakeup(&sc->sc_init_complete); 6264 wakeup(&sc->sc_init_complete);
6260 break; 6265 break;
6261 6266
6262 case IWM_SCAN_COMPLETE_NOTIFICATION: { 6267 case IWM_SCAN_COMPLETE_NOTIFICATION: {
6263 struct iwm_scan_complete_notif *notif; 6268 struct iwm_scan_complete_notif *notif;
6264 SYNC_RESP_STRUCT(notif, pkt); 6269 SYNC_RESP_STRUCT(notif, pkt);
6265 6270
6266 workqueue_enqueue(sc->sc_eswq, &sc->sc_eswk, NULL); 6271 workqueue_enqueue(sc->sc_eswq, &sc->sc_eswk, NULL);
6267 break; } 6272 break; }
6268 6273
6269 case IWM_REPLY_ERROR: { 6274 case IWM_REPLY_ERROR: {
6270 struct iwm_error_resp *resp; 6275 struct iwm_error_resp *resp;
6271 SYNC_RESP_STRUCT(resp, pkt); 6276 SYNC_RESP_STRUCT(resp, pkt);
6272 6277
6273 aprint_error_dev(sc->sc_dev, 6278 aprint_error_dev(sc->sc_dev,
6274 "firmware error 0x%x, cmd 0x%x\n", 6279 "firmware error 0x%x, cmd 0x%x\n",
6275 le32toh(resp->error_type), resp->cmd_id); 6280 le32toh(resp->error_type), resp->cmd_id);
6276 break; } 6281 break; }
6277 6282
6278 case IWM_TIME_EVENT_NOTIFICATION: { 6283 case IWM_TIME_EVENT_NOTIFICATION: {
6279 struct iwm_time_event_notif *notif; 6284 struct iwm_time_event_notif *notif;
6280 SYNC_RESP_STRUCT(notif, pkt); 6285 SYNC_RESP_STRUCT(notif, pkt);
6281 6286
6282 if (notif->status) { 6287 if (notif->status) {
6283 if (le32toh(notif->action) & 6288 if (le32toh(notif->action) &
6284 IWM_TE_V2_NOTIF_HOST_EVENT_START) 6289 IWM_TE_V2_NOTIF_HOST_EVENT_START)
6285 sc->sc_auth_prot = 2; 6290 sc->sc_auth_prot = 2;
6286 else 6291 else
6287 sc->sc_auth_prot = 0; 6292 sc->sc_auth_prot = 0;
6288 } else { 6293 } else {
6289 sc->sc_auth_prot = -1; 6294 sc->sc_auth_prot = -1;
6290 } 6295 }
6291 wakeup(&sc->sc_auth_prot); 6296 wakeup(&sc->sc_auth_prot);
6292 break; } 6297 break; }
6293 6298
6294 case IWM_MCAST_FILTER_CMD: 6299 case IWM_MCAST_FILTER_CMD:
6295 break; 6300 break;
6296 6301
6297 default: 6302 default:
6298 aprint_error_dev(sc->sc_dev, 6303 aprint_error_dev(sc->sc_dev,
6299 "code %02x frame %d/%d %x UNHANDLED " 6304 "code %02x frame %d/%d %x UNHANDLED "
6300 "(this should not happen)\n", 6305 "(this should not happen)\n",
6301 pkt->hdr.code, qid, idx, pkt->len_n_flags); 6306 pkt->hdr.code, qid, idx, pkt->len_n_flags);
6302 break; 6307 break;
6303 } 6308 }
6304 6309
6305 /* 6310 /*
6306 * Why test bit 0x80? The Linux driver: 6311 * Why test bit 0x80? The Linux driver:
6307 * 6312 *
6308 * There is one exception: uCode sets bit 15 when it 6313 * There is one exception: uCode sets bit 15 when it
6309 * originates the response/notification, i.e. when the 6314 * originates the response/notification, i.e. when the
6310 * response/notification is not a direct response to a 6315 * response/notification is not a direct response to a
6311 * command sent by the driver. For example, uCode issues 6316 * command sent by the driver. For example, uCode issues
6312 * IWM_REPLY_RX when it sends a received frame to the driver; 6317 * IWM_REPLY_RX when it sends a received frame to the driver;
6313 * it is not a direct response to any driver command. 6318 * it is not a direct response to any driver command.
6314 * 6319 *
6315 * Ok, so since when is 7 == 15? Well, the Linux driver 6320 * Ok, so since when is 7 == 15? Well, the Linux driver
6316 * uses a slightly different format for pkt->hdr, and "qid" 6321 * uses a slightly different format for pkt->hdr, and "qid"
6317 * is actually the upper byte of a two-byte field. 6322 * is actually the upper byte of a two-byte field.
6318 */ 6323 */
6319 if (!(pkt->hdr.qid & (1 << 7))) { 6324 if (!(pkt->hdr.qid & (1 << 7))) {
6320 iwm_cmd_done(sc, pkt); 6325 iwm_cmd_done(sc, pkt);
6321 } 6326 }
6322 6327
6323 ADVANCE_RXQ(sc); 6328 ADVANCE_RXQ(sc);
6324 } 6329 }
6325 6330
6326 IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL, 6331 IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
6327 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 6332 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
6328 6333
6329 /* 6334 /*
6330 * Tell the firmware what we have processed. 6335 * Tell the firmware what we have processed.
6331 * Seems like the hardware gets upset unless we align 6336 * Seems like the hardware gets upset unless we align
6332 * the write by 8?? 6337 * the write by 8??
6333 */ 6338 */
6334 hw = (hw == 0) ? IWM_RX_RING_COUNT - 1 : hw - 1; 6339 hw = (hw == 0) ? IWM_RX_RING_COUNT - 1 : hw - 1;
6335 IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_WPTR, hw & ~7); 6340 IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_WPTR, hw & ~7);
6336} 6341}
6337 6342
6338static int 6343static int
6339iwm_intr(void *arg) 6344iwm_intr(void *arg)
6340{ 6345{
6341 struct iwm_softc *sc = arg; 6346 struct iwm_softc *sc = arg;
6342 struct ifnet *ifp = IC2IFP(&sc->sc_ic); 6347 struct ifnet *ifp = IC2IFP(&sc->sc_ic);
6343 int handled = 0; 6348 int handled = 0;
6344 int r1, r2, rv = 0; 6349 int r1, r2, rv = 0;
6345 int isperiodic = 0; 6350 int isperiodic = 0;
6346 6351
6347 IWM_WRITE(sc, IWM_CSR_INT_MASK, 0); 6352 IWM_WRITE(sc, IWM_CSR_INT_MASK, 0);
6348 6353
6349 if (sc->sc_flags & IWM_FLAG_USE_ICT) { 6354 if (sc->sc_flags & IWM_FLAG_USE_ICT) {
6350 uint32_t *ict = sc->ict_dma.vaddr; 6355 uint32_t *ict = sc->ict_dma.vaddr;
6351 int tmp; 6356 int tmp;
6352 6357
6353 tmp = htole32(ict[sc->ict_cur]); 6358 tmp = htole32(ict[sc->ict_cur]);
6354 if (!tmp) 6359 if (!tmp)
6355 goto out_ena; 6360 goto out_ena;
6356 6361
6357 /* 6362 /*
6358 * ok, there was something. keep plowing until we have all. 6363 * ok, there was something. keep plowing until we have all.
6359 */ 6364 */
6360 r1 = r2 = 0; 6365 r1 = r2 = 0;
6361 while (tmp) { 6366 while (tmp) {
6362 r1 |= tmp; 6367 r1 |= tmp;
6363 ict[sc->ict_cur] = 0; 6368 ict[sc->ict_cur] = 0;
6364 sc->ict_cur = (sc->ict_cur+1) % IWM_ICT_COUNT; 6369 sc->ict_cur = (sc->ict_cur+1) % IWM_ICT_COUNT;
6365 tmp = htole32(ict[sc->ict_cur]); 6370 tmp = htole32(ict[sc->ict_cur]);
6366 } 6371 }
6367 6372
6368 /* this is where the fun begins. don't ask */ 6373 /* this is where the fun begins. don't ask */
6369 if (r1 == 0xffffffff) 6374 if (r1 == 0xffffffff)
6370 r1 = 0; 6375 r1 = 0;
6371 6376
6372 /* i am not expected to understand this */ 6377 /* i am not expected to understand this */
6373 if (r1 & 0xc0000) 6378 if (r1 & 0xc0000)
6374 r1 |= 0x8000; 6379 r1 |= 0x8000;
6375 r1 = (0xff & r1) | ((0xff00 & r1) << 16); 6380 r1 = (0xff & r1) | ((0xff00 & r1) << 16);
6376 } else { 6381 } else {
6377 r1 = IWM_READ(sc, IWM_CSR_INT); 6382 r1 = IWM_READ(sc, IWM_CSR_INT);
6378 /* "hardware gone" (where, fishing?) */ 6383 /* "hardware gone" (where, fishing?) */
6379 if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0) 6384 if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0)
6380 goto out; 6385 goto out;
6381 r2 = IWM_READ(sc, IWM_CSR_FH_INT_STATUS); 6386 r2 = IWM_READ(sc, IWM_CSR_FH_INT_STATUS);
6382 } 6387 }
6383 if (r1 == 0 && r2 == 0) { 6388 if (r1 == 0 && r2 == 0) {
6384 goto out_ena; 6389 goto out_ena;
6385 } 6390 }
6386 6391
6387 IWM_WRITE(sc, IWM_CSR_INT, r1 | ~sc->sc_intmask); 6392 IWM_WRITE(sc, IWM_CSR_INT, r1 | ~sc->sc_intmask);
6388 6393
6389 /* ignored */ 6394 /* ignored */
6390 handled |= (r1 & (IWM_CSR_INT_BIT_ALIVE /*| IWM_CSR_INT_BIT_SCD*/)); 6395 handled |= (r1 & (IWM_CSR_INT_BIT_ALIVE /*| IWM_CSR_INT_BIT_SCD*/));
6391 6396
6392 if (r1 & IWM_CSR_INT_BIT_SW_ERR) { 6397 if (r1 & IWM_CSR_INT_BIT_SW_ERR) {
6393#ifdef IWM_DEBUG 6398#ifdef IWM_DEBUG
6394 int i; 6399 int i;
6395 6400
6396 iwm_nic_error(sc); 6401 iwm_nic_error(sc);
6397 6402
6398 /* Dump driver status (TX and RX rings) while we're here. */ 6403 /* Dump driver status (TX and RX rings) while we're here. */
6399 DPRINTF(("driver status:\n")); 6404 DPRINTF(("driver status:\n"));
6400 for (i = 0; i < IWM_MVM_MAX_QUEUES; i++) { 6405 for (i = 0; i < IWM_MVM_MAX_QUEUES; i++) {
6401 struct iwm_tx_ring *ring = &sc->txq[i]; 6406 struct iwm_tx_ring *ring = &sc->txq[i];
6402 DPRINTF((" tx ring %2d: qid=%-2d cur=%-3d " 6407 DPRINTF((" tx ring %2d: qid=%-2d cur=%-3d "
6403 "queued=%-3d\n", 6408 "queued=%-3d\n",
6404 i, ring->qid, ring->cur, ring->queued)); 6409 i, ring->qid, ring->cur, ring->queued));
6405 } 6410 }
6406 DPRINTF((" rx ring: cur=%d\n", sc->rxq.cur)); 6411 DPRINTF((" rx ring: cur=%d\n", sc->rxq.cur));
6407 DPRINTF((" 802.11 state %d\n", sc->sc_ic.ic_state)); 6412 DPRINTF((" 802.11 state %d\n", sc->sc_ic.ic_state));
6408#endif 6413#endif
6409 6414
6410 aprint_error_dev(sc->sc_dev, "fatal firmware error\n"); 6415 aprint_error_dev(sc->sc_dev, "fatal firmware error\n");
6411 ifp->if_flags &= ~IFF_UP; 6416 ifp->if_flags &= ~IFF_UP;
6412 iwm_stop(ifp, 1); 6417 iwm_stop(ifp, 1);
6413 rv = 1; 6418 rv = 1;
6414 goto out; 6419 goto out;
6415 6420
6416 } 6421 }
6417 6422
6418 if (r1 & IWM_CSR_INT_BIT_HW_ERR) { 6423 if (r1 & IWM_CSR_INT_BIT_HW_ERR) {
6419 handled |= IWM_CSR_INT_BIT_HW_ERR; 6424 handled |= IWM_CSR_INT_BIT_HW_ERR;
6420 aprint_error_dev(sc->sc_dev, 6425 aprint_error_dev(sc->sc_dev,
6421 "hardware error, stopping device\n"); 6426 "hardware error, stopping device\n");
6422 ifp->if_flags &= ~IFF_UP; 6427 ifp->if_flags &= ~IFF_UP;
6423 iwm_stop(ifp, 1); 6428 iwm_stop(ifp, 1);
6424 rv = 1; 6429 rv = 1;
6425 goto out; 6430 goto out;
6426 } 6431 }
6427 6432
6428 /* firmware chunk loaded */ 6433 /* firmware chunk loaded */
6429 if (r1 & IWM_CSR_INT_BIT_FH_TX) { 6434 if (r1 & IWM_CSR_INT_BIT_FH_TX) {
6430 IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, IWM_CSR_FH_INT_TX_MASK); 6435 IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, IWM_CSR_FH_INT_TX_MASK);
6431 handled |= IWM_CSR_INT_BIT_FH_TX; 6436 handled |= IWM_CSR_INT_BIT_FH_TX;
6432 6437
6433 sc->sc_fw_chunk_done = 1; 6438 sc->sc_fw_chunk_done = 1;
6434 wakeup(&sc->sc_fw); 6439 wakeup(&sc->sc_fw);
6435 } 6440 }
6436 6441
6437 if (r1 & IWM_CSR_INT_BIT_RF_KILL) { 6442 if (r1 & IWM_CSR_INT_BIT_RF_KILL) {
6438 handled |= IWM_CSR_INT_BIT_RF_KILL; 6443 handled |= IWM_CSR_INT_BIT_RF_KILL;
6439 if (iwm_check_rfkill(sc) && (ifp->if_flags & IFF_UP)) { 6444 if (iwm_check_rfkill(sc) && (ifp->if_flags & IFF_UP)) {
6440 DPRINTF(("%s: rfkill switch, disabling interface\n", 6445 DPRINTF(("%s: rfkill switch, disabling interface\n",
6441 DEVNAME(sc))); 6446 DEVNAME(sc)));
6442 ifp->if_flags &= ~IFF_UP; 6447 ifp->if_flags &= ~IFF_UP;
6443 iwm_stop(ifp, 1); 6448 iwm_stop(ifp, 1);
6444 } 6449 }
6445 } 6450 }
6446 6451
6447 /* 6452 /*
6448 * The Linux driver uses periodic interrupts to avoid races. 6453 * The Linux driver uses periodic interrupts to avoid races.
6449 * We cargo-cult like it's going out of fashion. 6454 * We cargo-cult like it's going out of fashion.
6450 */ 6455 */
6451 if (r1 & IWM_CSR_INT_BIT_RX_PERIODIC) { 6456 if (r1 & IWM_CSR_INT_BIT_RX_PERIODIC) {
6452 handled |= IWM_CSR_INT_BIT_RX_PERIODIC; 6457 handled |= IWM_CSR_INT_BIT_RX_PERIODIC;
6453 IWM_WRITE(sc, IWM_CSR_INT, IWM_CSR_INT_BIT_RX_PERIODIC); 6458 IWM_WRITE(sc, IWM_CSR_INT, IWM_CSR_INT_BIT_RX_PERIODIC);
6454 if ((r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX)) == 0) 6459 if ((r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX)) == 0)
6455 IWM_WRITE_1(sc, 6460 IWM_WRITE_1(sc,
6456 IWM_CSR_INT_PERIODIC_REG, IWM_CSR_INT_PERIODIC_DIS); 6461 IWM_CSR_INT_PERIODIC_REG, IWM_CSR_INT_PERIODIC_DIS);
6457 isperiodic = 1; 6462 isperiodic = 1;
6458 } 6463 }
6459 6464
6460 if ((r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX)) || isperiodic) { 6465 if ((r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX)) || isperiodic) {
6461 handled |= (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX); 6466 handled |= (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX);
6462 IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, IWM_CSR_FH_INT_RX_MASK); 6467 IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, IWM_CSR_FH_INT_RX_MASK);
6463 6468
6464 iwm_notif_intr(sc); 6469 iwm_notif_intr(sc);
6465 6470
6466 /* enable periodic interrupt, see above */ 6471 /* enable periodic interrupt, see above */
6467 if (r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX) && !isperiodic) 6472 if (r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX) && !isperiodic)
6468 IWM_WRITE_1(sc, IWM_CSR_INT_PERIODIC_REG, 6473 IWM_WRITE_1(sc, IWM_CSR_INT_PERIODIC_REG,
6469 IWM_CSR_INT_PERIODIC_ENA); 6474 IWM_CSR_INT_PERIODIC_ENA);
6470 } 6475 }
6471 6476
6472 if (__predict_false(r1 & ~handled)) 6477 if (__predict_false(r1 & ~handled))
6473 DPRINTF(("%s: unhandled interrupts: %x\n", DEVNAME(sc), r1)); 6478 DPRINTF(("%s: unhandled interrupts: %x\n", DEVNAME(sc), r1));
6474 rv = 1; 6479 rv = 1;
6475 6480
6476 out_ena: 6481 out_ena:
6477 iwm_restore_interrupts(sc); 6482 iwm_restore_interrupts(sc);
6478 out: 6483 out:
6479 return rv; 6484 return rv;
6480} 6485}
6481 6486
6482/* 6487/*
6483 * Autoconf glue-sniffing 6488 * Autoconf glue-sniffing
6484 */ 6489 */
6485 6490
6486static const pci_product_id_t iwm_devices[] = { 6491static const pci_product_id_t iwm_devices[] = {
6487 PCI_PRODUCT_INTEL_WIFI_LINK_7260_1, 6492 PCI_PRODUCT_INTEL_WIFI_LINK_7260_1,
6488 PCI_PRODUCT_INTEL_WIFI_LINK_7260_2, 6493 PCI_PRODUCT_INTEL_WIFI_LINK_7260_2,
6489 PCI_PRODUCT_INTEL_WIFI_LINK_3160_1, 6494 PCI_PRODUCT_INTEL_WIFI_LINK_3160_1,
6490 PCI_PRODUCT_INTEL_WIFI_LINK_3160_2, 6495 PCI_PRODUCT_INTEL_WIFI_LINK_3160_2,
6491 PCI_PRODUCT_INTEL_WIFI_LINK_7265_1, 6496 PCI_PRODUCT_INTEL_WIFI_LINK_7265_1,
6492 PCI_PRODUCT_INTEL_WIFI_LINK_7265_2, 6497 PCI_PRODUCT_INTEL_WIFI_LINK_7265_2,
6493}; 6498};
6494 6499
6495static int 6500static int
6496iwm_match(device_t parent, cfdata_t match __unused, void *aux) 6501iwm_match(device_t parent, cfdata_t match __unused, void *aux)
6497{ 6502{
6498 struct pci_attach_args *pa = aux; 6503 struct pci_attach_args *pa = aux;
6499 6504
6500 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL) 6505 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL)
6501 return 0; 6506 return 0;
6502 6507
6503 for (size_t i = 0; i < __arraycount(iwm_devices); i++) 6508 for (size_t i = 0; i < __arraycount(iwm_devices); i++)
6504 if (PCI_PRODUCT(pa->pa_id) == iwm_devices[i]) 6509 if (PCI_PRODUCT(pa->pa_id) == iwm_devices[i])
6505 return 1; 6510 return 1;
6506 6511
6507 return 0; 6512 return 0;
6508} 6513}
6509 6514
6510static int 6515static int
6511iwm_preinit(struct iwm_softc *sc) 6516iwm_preinit(struct iwm_softc *sc)
6512{ 6517{
6513 int error; 6518 int error;
6514 6519
6515 if ((error = iwm_prepare_card_hw(sc)) != 0) { 6520 if ((error = iwm_prepare_card_hw(sc)) != 0) {
6516 aprint_error_dev(sc->sc_dev, "could not initialize hardware\n"); 6521 aprint_error_dev(sc->sc_dev, "could not initialize hardware\n");
6517 return error; 6522 return error;
6518 } 6523 }
6519 6524
6520 if (sc->sc_flags & IWM_FLAG_ATTACHED) 6525 if (sc->sc_flags & IWM_FLAG_ATTACHED)
6521 return 0; 6526 return 0;
6522 6527
6523 if ((error = iwm_start_hw(sc)) != 0) { 6528 if ((error = iwm_start_hw(sc)) != 0) {
6524 aprint_error_dev(sc->sc_dev, "could not initialize hardware\n"); 6529 aprint_error_dev(sc->sc_dev, "could not initialize hardware\n");
6525 return error; 6530 return error;
6526 } 6531 }
6527 6532
6528 error = iwm_run_init_mvm_ucode(sc, 1); 6533 error = iwm_run_init_mvm_ucode(sc, 1);
6529 iwm_stop_device(sc); 6534 iwm_stop_device(sc);
6530 return error; 6535 return error;
6531} 6536}
6532 6537
6533static void 6538static void
6534iwm_attach_hook(device_t dev) 6539iwm_attach_hook(device_t dev)
6535{ 6540{
6536 struct iwm_softc *sc = device_private(dev); 6541 struct iwm_softc *sc = device_private(dev);
6537 struct ieee80211com *ic = &sc->sc_ic; 6542 struct ieee80211com *ic = &sc->sc_ic;
6538 struct ifnet *ifp = &sc->sc_ec.ec_if; 6543 struct ifnet *ifp = &sc->sc_ec.ec_if;
6539 6544
6540 KASSERT(!cold); 6545 KASSERT(!cold);
6541 6546
6542 if (iwm_preinit(sc) != 0) 6547 if (iwm_preinit(sc) != 0)
6543 return; 6548 return;
6544 6549
6545 sc->sc_flags |= IWM_FLAG_ATTACHED; 6550 sc->sc_flags |= IWM_FLAG_ATTACHED;
6546 6551
6547 aprint_normal_dev(sc->sc_dev, 6552 aprint_normal_dev(sc->sc_dev,
6548 "hw rev: 0x%x, fw ver %d.%d (API ver %d), address %s\n", 6553 "hw rev: 0x%x, fw ver %d.%d (API ver %d), address %s\n",
6549 sc->sc_hw_rev & IWM_CSR_HW_REV_TYPE_MSK, 6554 sc->sc_hw_rev & IWM_CSR_HW_REV_TYPE_MSK,
6550 IWM_UCODE_MAJOR(sc->sc_fwver), 6555 IWM_UCODE_MAJOR(sc->sc_fwver),
6551 IWM_UCODE_MINOR(sc->sc_fwver), 6556 IWM_UCODE_MINOR(sc->sc_fwver),
6552 IWM_UCODE_API(sc->sc_fwver), 6557 IWM_UCODE_API(sc->sc_fwver),
6553 ether_sprintf(sc->sc_nvm.hw_addr)); 6558 ether_sprintf(sc->sc_nvm.hw_addr));
6554 6559
6555 ic->ic_ifp = ifp; 6560 ic->ic_ifp = ifp;
6556 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 6561 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
6557 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ 6562 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
6558 ic->ic_state = IEEE80211_S_INIT; 6563 ic->ic_state = IEEE80211_S_INIT;
6559 6564
6560 /* Set device capabilities. */ 6565 /* Set device capabilities. */
6561 ic->ic_caps = 6566 ic->ic_caps =
6562 IEEE80211_C_WEP | /* WEP */ 6567 IEEE80211_C_WEP | /* WEP */
6563 IEEE80211_C_WPA | /* 802.11i */ 6568 IEEE80211_C_WPA | /* 802.11i */
6564 IEEE80211_C_SHSLOT | /* short slot time supported */ 6569 IEEE80211_C_SHSLOT | /* short slot time supported */
6565 IEEE80211_C_SHPREAMBLE; /* short preamble supported */ 6570 IEEE80211_C_SHPREAMBLE; /* short preamble supported */
6566 6571
6567#ifndef IWM_NO_5GHZ 6572#ifndef IWM_NO_5GHZ
6568 ic->ic_sup_rates[IEEE80211_MODE_11A] = ieee80211_std_rateset_11a; 6573 ic->ic_sup_rates[IEEE80211_MODE_11A] = ieee80211_std_rateset_11a;
6569#endif 6574#endif
6570 ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b; 6575 ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
6571 ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g; 6576 ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
6572 6577
6573 for (int i = 0; i < __arraycount(sc->sc_phyctxt); i++) { 6578 for (int i = 0; i < __arraycount(sc->sc_phyctxt); i++) {
6574 sc->sc_phyctxt[i].id = i; 6579 sc->sc_phyctxt[i].id = i;
6575 } 6580 }
6576 6581
6577 sc->sc_amrr.amrr_min_success_threshold = 1; 6582 sc->sc_amrr.amrr_min_success_threshold = 1;
6578 sc->sc_amrr.amrr_max_success_threshold = 15; 6583 sc->sc_amrr.amrr_max_success_threshold = 15;
6579 6584
6580 /* IBSS channel undefined for now. */ 6585 /* IBSS channel undefined for now. */
6581 ic->ic_ibss_chan = &ic->ic_channels[1]; 6586 ic->ic_ibss_chan = &ic->ic_channels[1];
6582 6587
6583#if 0 6588#if 0
6584 /* Max RSSI */ 6589 /* Max RSSI */
6585 ic->ic_max_rssi = IWM_MAX_DBM - IWM_MIN_DBM; 6590 ic->ic_max_rssi = IWM_MAX_DBM - IWM_MIN_DBM;
6586#endif 6591#endif
6587 6592
6588 ifp->if_softc = sc; 6593 ifp->if_softc = sc;
6589 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 6594 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
6590 ifp->if_init = iwm_init; 6595 ifp->if_init = iwm_init;
6591 ifp->if_stop = iwm_stop; 6596 ifp->if_stop = iwm_stop;
6592 ifp->if_ioctl = iwm_ioctl; 6597 ifp->if_ioctl = iwm_ioctl;
6593 ifp->if_start = iwm_start; 6598 ifp->if_start = iwm_start;
6594 ifp->if_watchdog = iwm_watchdog; 6599 ifp->if_watchdog = iwm_watchdog;
6595 IFQ_SET_READY(&ifp->if_snd); 6600 IFQ_SET_READY(&ifp->if_snd);
6596 memcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ); 6601 memcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
6597 6602
6598 if_initialize(ifp); 6603 if_initialize(ifp);
6599 ieee80211_ifattach(ic); 6604 ieee80211_ifattach(ic);
6600 if_register(ifp); 6605 if_register(ifp);
6601 6606
6602 ic->ic_node_alloc = iwm_node_alloc; 6607 ic->ic_node_alloc = iwm_node_alloc;
6603 6608
6604 /* Override 802.11 state transition machine. */ 6609 /* Override 802.11 state transition machine. */
6605 sc->sc_newstate = ic->ic_newstate; 6610 sc->sc_newstate = ic->ic_newstate;
6606 ic->ic_newstate = iwm_newstate; 6611 ic->ic_newstate = iwm_newstate;
6607 ieee80211_media_init(ic, iwm_media_change, ieee80211_media_status); 6612 ieee80211_media_init(ic, iwm_media_change, ieee80211_media_status);
6608 ieee80211_announce(ic); 6613 ieee80211_announce(ic);
6609 6614
6610 iwm_radiotap_attach(sc); 6615 iwm_radiotap_attach(sc);
6611 callout_init(&sc->sc_calib_to, 0); 6616 callout_init(&sc->sc_calib_to, 0);
6612 callout_setfunc(&sc->sc_calib_to, iwm_calib_timeout, sc); 6617 callout_setfunc(&sc->sc_calib_to, iwm_calib_timeout, sc);
6613 6618
6614 //task_set(&sc->init_task, iwm_init_task, sc); 6619 //task_set(&sc->init_task, iwm_init_task, sc);
6615} 6620}
6616 6621
6617static void 6622static void
6618iwm_attach(device_t parent, device_t self, void *aux) 6623iwm_attach(device_t parent, device_t self, void *aux)
6619{ 6624{
6620 struct iwm_softc *sc = device_private(self); 6625 struct iwm_softc *sc = device_private(self);
6621 struct pci_attach_args *pa = aux; 6626 struct pci_attach_args *pa = aux;
6622 pci_intr_handle_t ih; 6627 pci_intr_handle_t ih;
6623 pcireg_t reg, memtype; 6628 pcireg_t reg, memtype;
6624 const char *intrstr; 6629 const char *intrstr;
6625 int error; 6630 int error;
6626 int txq_i; 6631 int txq_i;
6627 6632
6628 sc->sc_dev = self; 6633 sc->sc_dev = self;
6629 sc->sc_pct = pa->pa_pc; 6634 sc->sc_pct = pa->pa_pc;
6630 sc->sc_pcitag = pa->pa_tag; 6635 sc->sc_pcitag = pa->pa_tag;
6631 sc->sc_dmat = pa->pa_dmat; 6636 sc->sc_dmat = pa->pa_dmat;
6632 sc->sc_pciid = pa->pa_id; 6637 sc->sc_pciid = pa->pa_id;
6633 6638
6634 pci_aprint_devinfo(pa, NULL); 6639 pci_aprint_devinfo(pa, NULL);
6635 6640
6636 /* 6641 /*
6637 * Get the offset of the PCI Express Capability Structure in PCI 6642 * Get the offset of the PCI Express Capability Structure in PCI
6638 * Configuration Space. 6643 * Configuration Space.
6639 */ 6644 */
6640 error = pci_get_capability(sc->sc_pct, sc->sc_pcitag, 6645 error = pci_get_capability(sc->sc_pct, sc->sc_pcitag,
6641 PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, NULL); 6646 PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, NULL);
6642 if (error == 0) { 6647 if (error == 0) {
6643 aprint_error_dev(self, 6648 aprint_error_dev(self,
6644 "PCIe capability structure not found!\n"); 6649 "PCIe capability structure not found!\n");
6645 return; 6650 return;
6646 } 6651 }
6647 6652
6648 /* Clear device-specific "PCI retry timeout" register (41h). */ 6653 /* Clear device-specific "PCI retry timeout" register (41h). */
6649 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40); 6654 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
6650 pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00); 6655 pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);
6651 6656
6652 /* Enable bus-mastering and hardware bug workaround. */ 6657 /* Enable bus-mastering and hardware bug workaround. */
6653 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG); 6658 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);
6654 reg |= PCI_COMMAND_MASTER_ENABLE; 6659 reg |= PCI_COMMAND_MASTER_ENABLE;
6655 /* if !MSI */ 6660 /* if !MSI */
6656 if (reg & PCI_COMMAND_INTERRUPT_DISABLE) { 6661 if (reg & PCI_COMMAND_INTERRUPT_DISABLE) {
6657 reg &= ~PCI_COMMAND_INTERRUPT_DISABLE; 6662 reg &= ~PCI_COMMAND_INTERRUPT_DISABLE;
6658 } 6663 }
6659 pci_conf_write(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, reg); 6664 pci_conf_write(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, reg);
6660 6665
6661 memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START); 6666 memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START);
6662 error = pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0, 6667 error = pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0,
6663 &sc->sc_st, &sc->sc_sh, NULL, &sc->sc_sz); 6668 &sc->sc_st, &sc->sc_sh, NULL, &sc->sc_sz);
6664 if (error != 0) { 6669 if (error != 0) {
6665 aprint_error_dev(self, "can't map mem space\n"); 6670 aprint_error_dev(self, "can't map mem space\n");
6666 return; 6671 return;
6667 } 6672 }
6668 6673
6669 /* Install interrupt handler. */ 6674 /* Install interrupt handler. */
6670 if (pci_intr_map(pa, &ih)) { 6675 if (pci_intr_map(pa, &ih)) {
6671 aprint_error_dev(self, "can't map interrupt\n"); 6676 aprint_error_dev(self, "can't map interrupt\n");
6672 return; 6677 return;
6673 } 6678 }
6674 6679
6675 char intrbuf[PCI_INTRSTR_LEN]; 6680 char intrbuf[PCI_INTRSTR_LEN];
6676 intrstr = pci_intr_string(sc->sc_pct, ih, intrbuf, sizeof(intrbuf)); 6681 intrstr = pci_intr_string(sc->sc_pct, ih, intrbuf, sizeof(intrbuf));
6677 sc->sc_ih = pci_intr_establish(sc->sc_pct, ih, IPL_NET, iwm_intr, sc); 6682 sc->sc_ih = pci_intr_establish(sc->sc_pct, ih, IPL_NET, iwm_intr, sc);
6678 if (sc->sc_ih == NULL) { 6683 if (sc->sc_ih == NULL) {
6679 aprint_error_dev(self, "can't establish interrupt"); 6684 aprint_error_dev(self, "can't establish interrupt");
6680 if (intrstr != NULL) 6685 if (intrstr != NULL)
6681 aprint_error(" at %s", intrstr); 6686 aprint_error(" at %s", intrstr);
6682 aprint_error("\n"); 6687 aprint_error("\n");
6683 return; 6688 return;
6684 } 6689 }
6685 aprint_normal_dev(self, "interrupting at %s\n", intrstr); 6690 aprint_normal_dev(self, "interrupting at %s\n", intrstr);
6686 6691
6687 sc->sc_wantresp = -1; 6692 sc->sc_wantresp = -1;
6688 6693
6689 switch (PCI_PRODUCT(sc->sc_pciid)) { 6694 switch (PCI_PRODUCT(sc->sc_pciid)) {
6690 case PCI_PRODUCT_INTEL_WIFI_LINK_7260_1: 6695 case PCI_PRODUCT_INTEL_WIFI_LINK_7260_1:
6691 case PCI_PRODUCT_INTEL_WIFI_LINK_7260_2: 6696 case PCI_PRODUCT_INTEL_WIFI_LINK_7260_2:
6692 sc->sc_fwname = "iwlwifi-7260-9.ucode"; 6697 sc->sc_fwname = "iwlwifi-7260-9.ucode";
 6698 sc->host_interrupt_operation_mode = 1;
6693 break; 6699 break;
6694 case PCI_PRODUCT_INTEL_WIFI_LINK_3160_1: 6700 case PCI_PRODUCT_INTEL_WIFI_LINK_3160_1:
6695 case PCI_PRODUCT_INTEL_WIFI_LINK_3160_2: 6701 case PCI_PRODUCT_INTEL_WIFI_LINK_3160_2:
6696 sc->sc_fwname = "iwlwifi-3160-9.ucode"; 6702 sc->sc_fwname = "iwlwifi-3160-9.ucode";
 6703 sc->host_interrupt_operation_mode = 1;
6697 break; 6704 break;
6698 case PCI_PRODUCT_INTEL_WIFI_LINK_7265_1: 6705 case PCI_PRODUCT_INTEL_WIFI_LINK_7265_1:
6699 case PCI_PRODUCT_INTEL_WIFI_LINK_7265_2: 6706 case PCI_PRODUCT_INTEL_WIFI_LINK_7265_2:
6700 sc->sc_fwname = "iwlwifi-7265-9.ucode"; 6707 sc->sc_fwname = "iwlwifi-7265-9.ucode";
 6708 sc->host_interrupt_operation_mode = 0;
6701 break; 6709 break;
6702 default: 6710 default:
6703 aprint_error_dev(self, "unknown product %#x", 6711 aprint_error_dev(self, "unknown product %#x",
6704 PCI_PRODUCT(sc->sc_pciid)); 6712 PCI_PRODUCT(sc->sc_pciid));
6705 return; 6713 return;
6706 } 6714 }
6707 DPRINTF(("%s: firmware=%s\n", DEVNAME(sc), sc->sc_fwname)); 6715 DPRINTF(("%s: firmware=%s\n", DEVNAME(sc), sc->sc_fwname));
6708 sc->sc_fwdmasegsz = IWM_FWDMASEGSZ; 6716 sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
6709 6717
6710 /* 6718 /*
6711 * We now start fiddling with the hardware 6719 * We now start fiddling with the hardware
6712 */ 6720 */
6713 6721
6714 sc->sc_hw_rev = IWM_READ(sc, IWM_CSR_HW_REV); 6722 sc->sc_hw_rev = IWM_READ(sc, IWM_CSR_HW_REV);
6715 if (iwm_prepare_card_hw(sc) != 0) { 6723 if (iwm_prepare_card_hw(sc) != 0) {
6716 aprint_error_dev(sc->sc_dev, "could not initialize hardware\n"); 6724 aprint_error_dev(sc->sc_dev, "could not initialize hardware\n");
6717 return; 6725 return;
6718 } 6726 }
6719 6727
6720 /* Allocate DMA memory for firmware transfers. */ 6728 /* Allocate DMA memory for firmware transfers. */
6721 if ((error = iwm_alloc_fwmem(sc)) != 0) { 6729 if ((error = iwm_alloc_fwmem(sc)) != 0) {
6722 aprint_error_dev(sc->sc_dev, 6730 aprint_error_dev(sc->sc_dev,
6723 "could not allocate memory for firmware\n"); 6731 "could not allocate memory for firmware\n");
6724 return; 6732 return;
6725 } 6733 }
6726 6734
6727 /* Allocate "Keep Warm" page. */ 6735 /* Allocate "Keep Warm" page. */
6728 if ((error = iwm_alloc_kw(sc)) != 0) { 6736 if ((error = iwm_alloc_kw(sc)) != 0) {
6729 aprint_error_dev(sc->sc_dev, 6737 aprint_error_dev(sc->sc_dev,
6730 "could not allocate keep warm page\n"); 6738 "could not allocate keep warm page\n");
6731 goto fail1; 6739 goto fail1;
6732 } 6740 }
6733 6741
6734 /* We use ICT interrupts */ 6742 /* We use ICT interrupts */
6735 if ((error = iwm_alloc_ict(sc)) != 0) { 6743 if ((error = iwm_alloc_ict(sc)) != 0) {
6736 aprint_error_dev(sc->sc_dev, "could not allocate ICT table\n"); 6744 aprint_error_dev(sc->sc_dev, "could not allocate ICT table\n");
6737 goto fail2; 6745 goto fail2;
6738 } 6746 }
6739 6747
6740 /* Allocate TX scheduler "rings". */ 6748 /* Allocate TX scheduler "rings". */
6741 if ((error = iwm_alloc_sched(sc)) != 0) { 6749 if ((error = iwm_alloc_sched(sc)) != 0) {
6742 aprint_error_dev(sc->sc_dev, 6750 aprint_error_dev(sc->sc_dev,
6743 "could not allocate TX scheduler rings\n"); 6751 "could not allocate TX scheduler rings\n");
6744 goto fail3; 6752 goto fail3;
6745 } 6753 }
6746 6754
6747 /* Allocate TX rings */ 6755 /* Allocate TX rings */
6748 for (txq_i = 0; txq_i < __arraycount(sc->txq); txq_i++) { 6756 for (txq_i = 0; txq_i < __arraycount(sc->txq); txq_i++) {
6749 if ((error = iwm_alloc_tx_ring(sc, 6757 if ((error = iwm_alloc_tx_ring(sc,
6750 &sc->txq[txq_i], txq_i)) != 0) { 6758 &sc->txq[txq_i], txq_i)) != 0) {
6751 aprint_error_dev(sc->sc_dev, 6759 aprint_error_dev(sc->sc_dev,
6752 "could not allocate TX ring %d\n", txq_i); 6760 "could not allocate TX ring %d\n", txq_i);
6753 goto fail4; 6761 goto fail4;
6754 } 6762 }
6755 } 6763 }
6756 6764
6757 /* Allocate RX ring. */ 6765 /* Allocate RX ring. */
6758 if ((error = iwm_alloc_rx_ring(sc, &sc->rxq)) != 0) { 6766 if ((error = iwm_alloc_rx_ring(sc, &sc->rxq)) != 0) {
6759 aprint_error_dev(sc->sc_dev, "could not allocate RX ring\n"); 6767 aprint_error_dev(sc->sc_dev, "could not allocate RX ring\n");
6760 goto fail4; 6768 goto fail4;
6761 } 6769 }
6762 6770
6763 workqueue_create(&sc->sc_eswq, "iwmes", 6771 workqueue_create(&sc->sc_eswq, "iwmes",
6764 iwm_endscan_cb, sc, PRI_NONE, IPL_NET, 0); 6772 iwm_endscan_cb, sc, PRI_NONE, IPL_NET, 0);
6765 workqueue_create(&sc->sc_nswq, "iwmns", 6773 workqueue_create(&sc->sc_nswq, "iwmns",
6766 iwm_newstate_cb, sc, PRI_NONE, IPL_NET, 0); 6774 iwm_newstate_cb, sc, PRI_NONE, IPL_NET, 0);
6767 6775
6768 /* Clear pending interrupts. */ 6776 /* Clear pending interrupts. */
6769 IWM_WRITE(sc, IWM_CSR_INT, 0xffffffff); 6777 IWM_WRITE(sc, IWM_CSR_INT, 0xffffffff);
6770 6778
6771 /* 6779 /*
6772 * We can't do normal attach before the file system is mounted 6780 * We can't do normal attach before the file system is mounted
6773 * because we cannot read the MAC address without loading the 6781 * because we cannot read the MAC address without loading the
6774 * firmware from disk. So we postpone until mountroot is done. 6782 * firmware from disk. So we postpone until mountroot is done.
6775 * Notably, this will require a full driver unload/load cycle 6783 * Notably, this will require a full driver unload/load cycle
6776 * (or reboot) in case the firmware is not present when the 6784 * (or reboot) in case the firmware is not present when the
6777 * hook runs. 6785 * hook runs.
6778 */ 6786 */
6779 config_mountroot(self, iwm_attach_hook); 6787 config_mountroot(self, iwm_attach_hook);
6780 6788
6781 return; 6789 return;
6782 6790
6783 /* Free allocated memory if something failed during attachment. */ 6791 /* Free allocated memory if something failed during attachment. */
6784fail4: while (--txq_i >= 0) 6792fail4: while (--txq_i >= 0)
6785 iwm_free_tx_ring(sc, &sc->txq[txq_i]); 6793 iwm_free_tx_ring(sc, &sc->txq[txq_i]);
6786 iwm_free_sched(sc); 6794 iwm_free_sched(sc);
6787fail3: if (sc->ict_dma.vaddr != NULL) 6795fail3: if (sc->ict_dma.vaddr != NULL)
6788 iwm_free_ict(sc); 6796 iwm_free_ict(sc);
6789fail2: iwm_free_kw(sc); 6797fail2: iwm_free_kw(sc);
6790fail1: iwm_free_fwmem(sc); 6798fail1: iwm_free_fwmem(sc);
6791} 6799}
6792 6800
6793/* 6801/*
6794 * Attach the interface to 802.11 radiotap. 6802 * Attach the interface to 802.11 radiotap.
6795 */ 6803 */
6796void 6804void
6797iwm_radiotap_attach(struct iwm_softc *sc) 6805iwm_radiotap_attach(struct iwm_softc *sc)
6798{ 6806{
6799 struct ifnet *ifp = sc->sc_ic.ic_ifp; 6807 struct ifnet *ifp = sc->sc_ic.ic_ifp;
6800 6808
6801 bpf_attach2(ifp, DLT_IEEE802_11_RADIO, 6809 bpf_attach2(ifp, DLT_IEEE802_11_RADIO,
6802 sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN, 6810 sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN,
6803 &sc->sc_drvbpf); 6811 &sc->sc_drvbpf);
6804 6812
6805 sc->sc_rxtap_len = sizeof sc->sc_rxtapu; 6813 sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
6806 sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); 6814 sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
6807 sc->sc_rxtap.wr_ihdr.it_present = htole32(IWM_RX_RADIOTAP_PRESENT); 6815 sc->sc_rxtap.wr_ihdr.it_present = htole32(IWM_RX_RADIOTAP_PRESENT);
6808 6816
6809 sc->sc_txtap_len = sizeof sc->sc_txtapu; 6817 sc->sc_txtap_len = sizeof sc->sc_txtapu;
6810 sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); 6818 sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
6811 sc->sc_txtap.wt_ihdr.it_present = htole32(IWM_TX_RADIOTAP_PRESENT); 6819 sc->sc_txtap.wt_ihdr.it_present = htole32(IWM_TX_RADIOTAP_PRESENT);
6812} 6820}
6813 6821
6814#if 0 6822#if 0
6815static void 6823static void
6816iwm_init_task(void *arg1) 6824iwm_init_task(void *arg1)
6817{ 6825{
6818 struct iwm_softc *sc = arg1; 6826 struct iwm_softc *sc = arg1;
6819 struct ifnet *ifp = &sc->sc_ic.ic_if; 6827 struct ifnet *ifp = &sc->sc_ic.ic_if;
6820 int s; 6828 int s;
6821 6829
6822 s = splnet(); 6830 s = splnet();
6823 while (sc->sc_flags & IWM_FLAG_BUSY) 6831 while (sc->sc_flags & IWM_FLAG_BUSY)
6824 tsleep(&sc->sc_flags, 0, "iwmpwr", 0); 6832 tsleep(&sc->sc_flags, 0, "iwmpwr", 0);
6825 sc->sc_flags |= IWM_FLAG_BUSY; 6833 sc->sc_flags |= IWM_FLAG_BUSY;
6826 6834
6827 iwm_stop(ifp, 0); 6835 iwm_stop(ifp, 0);
6828 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP) 6836 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP)
6829 iwm_init(ifp); 6837 iwm_init(ifp);
6830 6838
6831 sc->sc_flags &= ~IWM_FLAG_BUSY; 6839 sc->sc_flags &= ~IWM_FLAG_BUSY;
6832 wakeup(&sc->sc_flags); 6840 wakeup(&sc->sc_flags);
6833 splx(s); 6841 splx(s);
6834} 6842}
6835 6843
6836static void 6844static void
6837iwm_wakeup(struct iwm_softc *sc) 6845iwm_wakeup(struct iwm_softc *sc)
6838{ 6846{
6839 pcireg_t reg; 6847 pcireg_t reg;
6840 6848
6841 /* Clear device-specific "PCI retry timeout" register (41h). */ 6849 /* Clear device-specific "PCI retry timeout" register (41h). */
6842 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40); 6850 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
6843 pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00); 6851 pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);
6844 6852
6845 iwm_init_task(sc); 6853 iwm_init_task(sc);
6846} 6854}
6847 6855
6848static int 6856static int
6849iwm_activate(device_t self, enum devact act) 6857iwm_activate(device_t self, enum devact act)
6850{ 6858{
6851 struct iwm_softc *sc = device_private(self); 6859 struct iwm_softc *sc = device_private(self);
6852 struct ifnet *ifp = IC2IFP(&sc->sc_ic); 6860 struct ifnet *ifp = IC2IFP(&sc->sc_ic);
6853 6861
6854 switch (act) { 6862 switch (act) {
6855 case DVACT_DEACTIVATE: 6863 case DVACT_DEACTIVATE:
6856 if (ifp->if_flags & IFF_RUNNING) 6864 if (ifp->if_flags & IFF_RUNNING)
6857 iwm_stop(ifp, 0); 6865 iwm_stop(ifp, 0);
6858 return 0; 6866 return 0;
6859 default: 6867 default:
6860 return EOPNOTSUPP; 6868 return EOPNOTSUPP;
6861 } 6869 }
6862} 6870}
6863#endif 6871#endif
6864 6872
6865CFATTACH_DECL_NEW(iwm, sizeof(struct iwm_softc), iwm_match, iwm_attach, 6873CFATTACH_DECL_NEW(iwm, sizeof(struct iwm_softc), iwm_match, iwm_attach,
6866 NULL, NULL); 6874 NULL, NULL);

cvs diff -r1.4 -r1.5 src/sys/dev/pci/if_iwmvar.h (switch to unified diff)

--- src/sys/dev/pci/if_iwmvar.h 2015/02/16 13:22:19 1.4
+++ src/sys/dev/pci/if_iwmvar.h 2015/03/03 09:10:45 1.5
@@ -1,513 +1,515 @@ @@ -1,513 +1,515 @@
1/* $NetBSD: if_iwmvar.h,v 1.4 2015/02/16 13:22:19 nonaka Exp $ */ 1/* $NetBSD: if_iwmvar.h,v 1.5 2015/03/03 09:10:45 nonaka Exp $ */
2/* OpenBSD: if_iwmvar.h,v 1.3 2015/02/07 07:10:44 phessler Exp */ 2/* OpenBSD: if_iwmvar.h,v 1.7 2015/03/02 13:51:10 jsg Exp */
3 3
4/* 4/*
5 * Copyright (c) 2014 genua mbh <info@genua.de> 5 * Copyright (c) 2014 genua mbh <info@genua.de>
6 * Copyright (c) 2014 Fixup Software Ltd. 6 * Copyright (c) 2014 Fixup Software Ltd.
7 * 7 *
8 * Permission to use, copy, modify, and distribute this software for any 8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above 9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies. 10 * copyright notice and this permission notice appear in all copies.
11 * 11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */ 19 */
20 20
21/*- 21/*-
22 * Based on BSD-licensed source modules in the Linux iwlwifi driver, 22 * Based on BSD-licensed source modules in the Linux iwlwifi driver,
23 * which were used as the reference documentation for this implementation. 23 * which were used as the reference documentation for this implementation.
24 * 24 *
25 * Driver version we are currently based off of is 25 * Driver version we are currently based off of is
26 * Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd) 26 * Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
27 * 27 *
28 *********************************************************************** 28 ***********************************************************************
29 * 29 *
30 * This file is provided under a dual BSD/GPLv2 license. When using or 30 * This file is provided under a dual BSD/GPLv2 license. When using or
31 * redistributing this file, you may do so under either license. 31 * redistributing this file, you may do so under either license.
32 * 32 *
33 * GPL LICENSE SUMMARY 33 * GPL LICENSE SUMMARY
34 * 34 *
35 * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. 35 * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
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 <ilw@linux.intel.com> 55 * Intel Linux Wireless <ilw@linux.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 * 58 *
59 * BSD LICENSE 59 * BSD LICENSE
60 * 60 *
61 * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. 61 * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
62 * All rights reserved. 62 * All rights reserved.
63 * 63 *
64 * Redistribution and use in source and binary forms, with or without 64 * Redistribution and use in source and binary forms, with or without
65 * modification, are permitted provided that the following conditions 65 * modification, are permitted provided that the following conditions
66 * are met: 66 * are met:
67 * 67 *
68 * * Redistributions of source code must retain the above copyright 68 * * Redistributions of source code must retain the above copyright
69 * notice, this list of conditions and the following disclaimer. 69 * notice, this list of conditions and the following disclaimer.
70 * * Redistributions in binary form must reproduce the above copyright 70 * * Redistributions in binary form must reproduce the above copyright
71 * notice, this list of conditions and the following disclaimer in 71 * notice, this list of conditions and the following disclaimer in
72 * the documentation and/or other materials provided with the 72 * the documentation and/or other materials provided with the
73 * distribution. 73 * distribution.
74 * * Neither the name Intel Corporation nor the names of its 74 * * Neither the name Intel Corporation nor the names of its
75 * contributors may be used to endorse or promote products derived 75 * contributors may be used to endorse or promote products derived
76 * from this software without specific prior written permission. 76 * from this software without specific prior written permission.
77 * 77 *
78 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 78 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
79 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 79 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
80 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 80 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
81 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 81 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
82 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 82 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
83 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 83 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
84 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 84 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
85 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 85 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
86 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 86 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
87 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 87 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
88 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 88 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
89 */ 89 */
90 90
91/*- 91/*-
92 * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr> 92 * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
93 * 93 *
94 * Permission to use, copy, modify, and distribute this software for any 94 * Permission to use, copy, modify, and distribute this software for any
95 * purpose with or without fee is hereby granted, provided that the above 95 * purpose with or without fee is hereby granted, provided that the above
96 * copyright notice and this permission notice appear in all copies. 96 * copyright notice and this permission notice appear in all copies.
97 * 97 *
98 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 98 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
99 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 99 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
100 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 100 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
101 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 101 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
102 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 102 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
103 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 103 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
104 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 104 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
105 */ 105 */
106 106
107struct iwm_rx_radiotap_header { 107struct iwm_rx_radiotap_header {
108 struct ieee80211_radiotap_header wr_ihdr; 108 struct ieee80211_radiotap_header wr_ihdr;
109 uint64_t wr_tsft; 109 uint64_t wr_tsft;
110 uint8_t wr_flags; 110 uint8_t wr_flags;
111 uint8_t wr_rate; 111 uint8_t wr_rate;
112 uint16_t wr_chan_freq; 112 uint16_t wr_chan_freq;
113 uint16_t wr_chan_flags; 113 uint16_t wr_chan_flags;
114 int8_t wr_dbm_antsignal; 114 int8_t wr_dbm_antsignal;
115 int8_t wr_dbm_antnoise; 115 int8_t wr_dbm_antnoise;
116} __packed; 116} __packed;
117 117
118#define IWM_RX_RADIOTAP_PRESENT \ 118#define IWM_RX_RADIOTAP_PRESENT \
119 ((1 << IEEE80211_RADIOTAP_TSFT) | \ 119 ((1 << IEEE80211_RADIOTAP_TSFT) | \
120 (1 << IEEE80211_RADIOTAP_FLAGS) | \ 120 (1 << IEEE80211_RADIOTAP_FLAGS) | \
121 (1 << IEEE80211_RADIOTAP_RATE) | \ 121 (1 << IEEE80211_RADIOTAP_RATE) | \
122 (1 << IEEE80211_RADIOTAP_CHANNEL) | \ 122 (1 << IEEE80211_RADIOTAP_CHANNEL) | \
123 (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \ 123 (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
124 (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE)) 124 (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE))
125 125
126struct iwm_tx_radiotap_header { 126struct iwm_tx_radiotap_header {
127 struct ieee80211_radiotap_header wt_ihdr; 127 struct ieee80211_radiotap_header wt_ihdr;
128 uint8_t wt_flags; 128 uint8_t wt_flags;
129 uint8_t wt_rate; 129 uint8_t wt_rate;
130 uint16_t wt_chan_freq; 130 uint16_t wt_chan_freq;
131 uint16_t wt_chan_flags; 131 uint16_t wt_chan_flags;
132 uint8_t wt_hwqueue; 132 uint8_t wt_hwqueue;
133} __packed; 133} __packed;
134 134
135#define IWM_TX_RADIOTAP_PRESENT \ 135#define IWM_TX_RADIOTAP_PRESENT \
136 ((1 << IEEE80211_RADIOTAP_FLAGS) | \ 136 ((1 << IEEE80211_RADIOTAP_FLAGS) | \
137 (1 << IEEE80211_RADIOTAP_RATE) | \ 137 (1 << IEEE80211_RADIOTAP_RATE) | \
138 (1 << IEEE80211_RADIOTAP_CHANNEL)) 138 (1 << IEEE80211_RADIOTAP_CHANNEL))
139 139
140#define IWM_UCODE_SECT_MAX 6 140#define IWM_UCODE_SECT_MAX 6
141#define IWM_FWDMASEGSZ (192*1024) 141#define IWM_FWDMASEGSZ (192*1024)
142/* sanity check value */ 142/* sanity check value */
143#define IWM_FWMAXSIZE (2*1024*1024) 143#define IWM_FWMAXSIZE (2*1024*1024)
144 144
145/* 145/*
146 * fw_status is used to determine if we've already parsed the firmware file 146 * fw_status is used to determine if we've already parsed the firmware file
147 * 147 *
148 * In addition to the following, status < 0 ==> -error 148 * In addition to the following, status < 0 ==> -error
149 */ 149 */
150#define IWM_FW_STATUS_NONE 0 150#define IWM_FW_STATUS_NONE 0
151#define IWM_FW_STATUS_INPROGRESS 1 151#define IWM_FW_STATUS_INPROGRESS 1
152#define IWM_FW_STATUS_DONE 2 152#define IWM_FW_STATUS_DONE 2
153 153
154enum iwm_ucode_type { 154enum iwm_ucode_type {
155 IWM_UCODE_TYPE_INIT, 155 IWM_UCODE_TYPE_INIT,
156 IWM_UCODE_TYPE_REGULAR, 156 IWM_UCODE_TYPE_REGULAR,
157 IWM_UCODE_TYPE_WOW, 157 IWM_UCODE_TYPE_WOW,
158 IWM_UCODE_TYPE_MAX 158 IWM_UCODE_TYPE_MAX
159}; 159};
160 160
161struct iwm_fw_info { 161struct iwm_fw_info {
162 void *fw_rawdata; 162 void *fw_rawdata;
163 size_t fw_rawsize; 163 size_t fw_rawsize;
164 int fw_status; 164 int fw_status;
165 165
166 struct iwm_fw_sects { 166 struct iwm_fw_sects {
167 struct iwm_fw_onesect { 167 struct iwm_fw_onesect {
168 void *fws_data; 168 void *fws_data;
169 uint32_t fws_len; 169 uint32_t fws_len;
170 uint32_t fws_devoff; 170 uint32_t fws_devoff;
171 171
172 void *fws_alloc; 172 void *fws_alloc;
173 size_t fws_allocsize; 173 size_t fws_allocsize;
174 } fw_sect[IWM_UCODE_SECT_MAX]; 174 } fw_sect[IWM_UCODE_SECT_MAX];
175 size_t fw_totlen; 175 size_t fw_totlen;
176 int fw_count; 176 int fw_count;
177 } fw_sects[IWM_UCODE_TYPE_MAX]; 177 } fw_sects[IWM_UCODE_TYPE_MAX];
178}; 178};
179 179
180struct iwm_nvm_data { 180struct iwm_nvm_data {
181 int n_hw_addrs; 181 int n_hw_addrs;
182 uint8_t hw_addr[ETHER_ADDR_LEN]; 182 uint8_t hw_addr[ETHER_ADDR_LEN];
183 183
184 uint8_t calib_version; 184 uint8_t calib_version;
185 uint16_t calib_voltage; 185 uint16_t calib_voltage;
186 186
187 uint16_t raw_temperature; 187 uint16_t raw_temperature;
188 uint16_t kelvin_temperature; 188 uint16_t kelvin_temperature;
189 uint16_t kelvin_voltage; 189 uint16_t kelvin_voltage;
190 uint16_t xtal_calib[2]; 190 uint16_t xtal_calib[2];
191 191
192 int sku_cap_band_24GHz_enable; 192 int sku_cap_band_24GHz_enable;
193 int sku_cap_band_52GHz_enable; 193 int sku_cap_band_52GHz_enable;
194 int sku_cap_11n_enable; 194 int sku_cap_11n_enable;
195 int sku_cap_amt_enable; 195 int sku_cap_amt_enable;
196 int sku_cap_ipan_enable; 196 int sku_cap_ipan_enable;
197 197
198 uint8_t radio_cfg_type; 198 uint8_t radio_cfg_type;
199 uint8_t radio_cfg_step; 199 uint8_t radio_cfg_step;
200 uint8_t radio_cfg_dash; 200 uint8_t radio_cfg_dash;
201 uint8_t radio_cfg_pnum; 201 uint8_t radio_cfg_pnum;
202 uint8_t valid_tx_ant, valid_rx_ant; 202 uint8_t valid_tx_ant, valid_rx_ant;
203 203
204 uint16_t nvm_version; 204 uint16_t nvm_version;
205 uint8_t max_tx_pwr_half_dbm; 205 uint8_t max_tx_pwr_half_dbm;
206}; 206};
207 207
208/* max bufs per tfd the driver will use */ 208/* max bufs per tfd the driver will use */
209#define IWM_MAX_CMD_TBS_PER_TFD 2 209#define IWM_MAX_CMD_TBS_PER_TFD 2
210 210
211struct iwm_rx_packet; 211struct iwm_rx_packet;
212struct iwm_host_cmd { 212struct iwm_host_cmd {
213 const void *data[IWM_MAX_CMD_TBS_PER_TFD]; 213 const void *data[IWM_MAX_CMD_TBS_PER_TFD];
214 struct iwm_rx_packet *resp_pkt; 214 struct iwm_rx_packet *resp_pkt;
215 unsigned long _rx_page_addr; 215 unsigned long _rx_page_addr;
216 uint32_t _rx_page_order; 216 uint32_t _rx_page_order;
217 int handler_status; 217 int handler_status;
218 218
219 uint32_t flags; 219 uint32_t flags;
220 uint16_t len[IWM_MAX_CMD_TBS_PER_TFD]; 220 uint16_t len[IWM_MAX_CMD_TBS_PER_TFD];
221 uint8_t dataflags[IWM_MAX_CMD_TBS_PER_TFD]; 221 uint8_t dataflags[IWM_MAX_CMD_TBS_PER_TFD];
222 uint8_t id; 222 uint8_t id;
223}; 223};
224 224
225/* 225/*
226 * DMA glue is from iwn 226 * DMA glue is from iwn
227 */ 227 */
228 228
229struct iwm_dma_info { 229struct iwm_dma_info {
230 bus_dma_tag_t tag; 230 bus_dma_tag_t tag;
231 bus_dmamap_t map; 231 bus_dmamap_t map;
232 bus_dma_segment_t seg; 232 bus_dma_segment_t seg;
233 bus_addr_t paddr; 233 bus_addr_t paddr;
234 void *vaddr; 234 void *vaddr;
235 bus_size_t size; 235 bus_size_t size;
236}; 236};
237 237
238#define IWM_TX_RING_COUNT 256 238#define IWM_TX_RING_COUNT 256
239#define IWM_TX_RING_LOMARK 192 239#define IWM_TX_RING_LOMARK 192
240#define IWM_TX_RING_HIMARK 224 240#define IWM_TX_RING_HIMARK 224
241 241
242struct iwm_tx_data { 242struct iwm_tx_data {
243 bus_dmamap_t map; 243 bus_dmamap_t map;
244 bus_addr_t cmd_paddr; 244 bus_addr_t cmd_paddr;
245 bus_addr_t scratch_paddr; 245 bus_addr_t scratch_paddr;
246 struct mbuf *m; 246 struct mbuf *m;
247 struct iwm_node *in; 247 struct iwm_node *in;
248 int done; 248 int done;
249}; 249};
250 250
251struct iwm_tx_ring { 251struct iwm_tx_ring {
252 struct iwm_dma_info desc_dma; 252 struct iwm_dma_info desc_dma;
253 struct iwm_dma_info cmd_dma; 253 struct iwm_dma_info cmd_dma;
254 struct iwm_tfd *desc; 254 struct iwm_tfd *desc;
255 struct iwm_device_cmd *cmd; 255 struct iwm_device_cmd *cmd;
256 struct iwm_tx_data data[IWM_TX_RING_COUNT]; 256 struct iwm_tx_data data[IWM_TX_RING_COUNT];
257 int qid; 257 int qid;
258 int queued; 258 int queued;
259 int cur; 259 int cur;
260}; 260};
261 261
262#define IWM_RX_RING_COUNT 256 262#define IWM_RX_RING_COUNT 256
263#define IWM_RBUF_COUNT (IWM_RX_RING_COUNT + 32) 263#define IWM_RBUF_COUNT (IWM_RX_RING_COUNT + 32)
264/* Linux driver optionally uses 8k buffer */ 264/* Linux driver optionally uses 8k buffer */
265#define IWM_RBUF_SIZE 4096 265#define IWM_RBUF_SIZE 4096
266 266
267struct iwm_softc; 267struct iwm_softc;
268struct iwm_rbuf { 268struct iwm_rbuf {
269 struct iwm_softc *sc; 269 struct iwm_softc *sc;
270 void *vaddr; 270 void *vaddr;
271 bus_addr_t paddr; 271 bus_addr_t paddr;
272}; 272};
273 273
274struct iwm_rx_data { 274struct iwm_rx_data {
275 struct mbuf *m; 275 struct mbuf *m;
276 bus_dmamap_t map; 276 bus_dmamap_t map;
277 int wantresp; 277 int wantresp;
278}; 278};
279 279
280struct iwm_rx_ring { 280struct iwm_rx_ring {
281 struct iwm_dma_info desc_dma; 281 struct iwm_dma_info desc_dma;
282 struct iwm_dma_info stat_dma; 282 struct iwm_dma_info stat_dma;
283 struct iwm_dma_info buf_dma; 283 struct iwm_dma_info buf_dma;
284 uint32_t *desc; 284 uint32_t *desc;
285 struct iwm_rb_status *stat; 285 struct iwm_rb_status *stat;
286 struct iwm_rx_data data[IWM_RX_RING_COUNT]; 286 struct iwm_rx_data data[IWM_RX_RING_COUNT];
287 int cur; 287 int cur;
288}; 288};
289 289
290#define IWM_FLAG_USE_ICT 0x01 290#define IWM_FLAG_USE_ICT 0x01
291#define IWM_FLAG_HW_INITED 0x02 291#define IWM_FLAG_HW_INITED 0x02
292#define IWM_FLAG_STOPPED 0x04 292#define IWM_FLAG_STOPPED 0x04
293#define IWM_FLAG_RFKILL 0x08 293#define IWM_FLAG_RFKILL 0x08
294#define IWM_FLAG_BUSY 0x10 294#define IWM_FLAG_BUSY 0x10
295#define IWM_FLAG_ATTACHED 0x20 295#define IWM_FLAG_ATTACHED 0x20
296 296
297struct iwm_ucode_status { 297struct iwm_ucode_status {
298 uint32_t uc_error_event_table; 298 uint32_t uc_error_event_table;
299 uint32_t uc_log_event_table; 299 uint32_t uc_log_event_table;
300 300
301 int uc_ok; 301 int uc_ok;
302 int uc_intr; 302 int uc_intr;
303}; 303};
304 304
305#define IWM_CMD_RESP_MAX PAGE_SIZE 305#define IWM_CMD_RESP_MAX PAGE_SIZE
306 306
307#define IWM_OTP_LOW_IMAGE_SIZE 2048 307#define IWM_OTP_LOW_IMAGE_SIZE 2048
308 308
309#define IWM_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS 500 309#define IWM_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS 500
310#define IWM_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS 400 310#define IWM_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS 400
311 311
312/* 312/*
313 * Command headers are in iwl-trans.h, which is full of all 313 * Command headers are in iwl-trans.h, which is full of all
314 * kinds of other junk, so we just replicate the structures here. 314 * kinds of other junk, so we just replicate the structures here.
315 * First the software bits: 315 * First the software bits:
316 */ 316 */
317enum IWM_CMD_MODE { 317enum IWM_CMD_MODE {
318 IWM_CMD_SYNC = 0, 318 IWM_CMD_SYNC = 0,
319 IWM_CMD_ASYNC = (1 << 0), 319 IWM_CMD_ASYNC = (1 << 0),
320 IWM_CMD_WANT_SKB = (1 << 1), 320 IWM_CMD_WANT_SKB = (1 << 1),
321 IWM_CMD_SEND_IN_RFKILL = (1 << 2), 321 IWM_CMD_SEND_IN_RFKILL = (1 << 2),
322}; 322};
323enum iwm_hcmd_dataflag { 323enum iwm_hcmd_dataflag {
324 IWM_HCMD_DFL_NOCOPY = (1 << 0), 324 IWM_HCMD_DFL_NOCOPY = (1 << 0),
325 IWM_HCMD_DFL_DUP = (1 << 1), 325 IWM_HCMD_DFL_DUP = (1 << 1),
326}; 326};
327 327
328/* 328/*
329 * iwlwifi/iwl-phy-db 329 * iwlwifi/iwl-phy-db
330 */ 330 */
331 331
332#define IWM_NUM_PAPD_CH_GROUPS 4 332#define IWM_NUM_PAPD_CH_GROUPS 4
333#define IWM_NUM_TXP_CH_GROUPS 9 333#define IWM_NUM_TXP_CH_GROUPS 9
334 334
335struct iwm_phy_db_entry { 335struct iwm_phy_db_entry {
336 uint16_t size; 336 uint16_t size;
337 uint8_t *data; 337 uint8_t *data;
338}; 338};
339 339
340struct iwm_phy_db { 340struct iwm_phy_db {
341 struct iwm_phy_db_entry cfg; 341 struct iwm_phy_db_entry cfg;
342 struct iwm_phy_db_entry calib_nch; 342 struct iwm_phy_db_entry calib_nch;
343 struct iwm_phy_db_entry calib_ch_group_papd[IWM_NUM_PAPD_CH_GROUPS]; 343 struct iwm_phy_db_entry calib_ch_group_papd[IWM_NUM_PAPD_CH_GROUPS];
344 struct iwm_phy_db_entry calib_ch_group_txp[IWM_NUM_TXP_CH_GROUPS]; 344 struct iwm_phy_db_entry calib_ch_group_txp[IWM_NUM_TXP_CH_GROUPS];
345}; 345};
346 346
347struct iwm_int_sta { 347struct iwm_int_sta {
348 uint32_t sta_id; 348 uint32_t sta_id;
349 uint32_t tfd_queue_msk; 349 uint32_t tfd_queue_msk;
350}; 350};
351 351
352struct iwm_mvm_phy_ctxt { 352struct iwm_mvm_phy_ctxt {
353 uint16_t id; 353 uint16_t id;
354 uint16_t color; 354 uint16_t color;
355 uint32_t ref; 355 uint32_t ref;
356 struct ieee80211_channel *channel; 356 struct ieee80211_channel *channel;
357}; 357};
358 358
359struct iwm_bf_data { 359struct iwm_bf_data {
360 int bf_enabled; /* filtering */ 360 int bf_enabled; /* filtering */
361 int ba_enabled; /* abort */ 361 int ba_enabled; /* abort */
362 int ave_beacon_signal; 362 int ave_beacon_signal;
363 int last_cqm_event; 363 int last_cqm_event;
364}; 364};
365 365
366struct iwm_softc { 366struct iwm_softc {
367 device_t sc_dev; 367 device_t sc_dev;
368 struct ethercom sc_ec; 368 struct ethercom sc_ec;
369 struct ieee80211com sc_ic; 369 struct ieee80211com sc_ic;
370 370
371 int (*sc_newstate)(struct ieee80211com *, enum ieee80211_state, int); 371 int (*sc_newstate)(struct ieee80211com *, enum ieee80211_state, int);
372 int sc_newstate_pending; 372 int sc_newstate_pending;
373 373
374 struct ieee80211_amrr sc_amrr; 374 struct ieee80211_amrr sc_amrr;
375 struct callout sc_calib_to; 375 struct callout sc_calib_to;
376 376
377 bus_space_tag_t sc_st; 377 bus_space_tag_t sc_st;
378 bus_space_handle_t sc_sh; 378 bus_space_handle_t sc_sh;
379 379
380 bus_size_t sc_sz; 380 bus_size_t sc_sz;
381 bus_dma_tag_t sc_dmat; 381 bus_dma_tag_t sc_dmat;
382 pci_chipset_tag_t sc_pct; 382 pci_chipset_tag_t sc_pct;
383 pcitag_t sc_pcitag; 383 pcitag_t sc_pcitag;
384 pcireg_t sc_pciid; 384 pcireg_t sc_pciid;
385 const void *sc_ih; 385 const void *sc_ih;
386 386
387 /* TX scheduler rings. */ 387 /* TX scheduler rings. */
388 struct iwm_dma_info sched_dma; 388 struct iwm_dma_info sched_dma;
389 uint32_t sched_base; 389 uint32_t sched_base;
390 390
391 /* TX/RX rings. */ 391 /* TX/RX rings. */
392 struct iwm_tx_ring txq[IWM_MVM_MAX_QUEUES]; 392 struct iwm_tx_ring txq[IWM_MVM_MAX_QUEUES];
393 struct iwm_rx_ring rxq; 393 struct iwm_rx_ring rxq;
394 int qfullmsk; 394 int qfullmsk;
395 395
396 int sc_sf_state; 396 int sc_sf_state;
397 397
398 /* ICT table. */ 398 /* ICT table. */
399 struct iwm_dma_info ict_dma; 399 struct iwm_dma_info ict_dma;
400 int ict_cur; 400 int ict_cur;
401 401
402 int sc_hw_rev; 402 int sc_hw_rev;
403 int sc_hw_id; 403 int sc_hw_id;
404 404
405 struct iwm_dma_info kw_dma; 405 struct iwm_dma_info kw_dma;
406 struct iwm_dma_info fw_dma; 406 struct iwm_dma_info fw_dma;
407 407
408 int sc_fw_chunk_done; 408 int sc_fw_chunk_done;
409 int sc_init_complete; 409 int sc_init_complete;
410 410
411 struct iwm_ucode_status sc_uc; 411 struct iwm_ucode_status sc_uc;
412 enum iwm_ucode_type sc_uc_current; 412 enum iwm_ucode_type sc_uc_current;
413 int sc_fwver; 413 int sc_fwver;
414 414
415 int sc_capaflags; 415 int sc_capaflags;
416 int sc_capa_max_probe_len; 416 int sc_capa_max_probe_len;
417 417
418 int sc_intmask; 418 int sc_intmask;
419 int sc_flags; 419 int sc_flags;
420 420
421 /* 421 /*
422 * So why do we need a separate stopped flag and a generation? 422 * So why do we need a separate stopped flag and a generation?
423 * the former protects the device from issueing commands when it's 423 * the former protects the device from issueing commands when it's
424 * stopped (duh). The latter protects against race from a very 424 * stopped (duh). The latter protects against race from a very
425 * fast stop/unstop cycle where threads waiting for responses do 425 * fast stop/unstop cycle where threads waiting for responses do
426 * not have a chance to run in between. Notably: we want to stop 426 * not have a chance to run in between. Notably: we want to stop
427 * the device from interrupt context when it craps out, so we 427 * the device from interrupt context when it craps out, so we
428 * don't have the luxury of waiting for quiescense. 428 * don't have the luxury of waiting for quiescense.
429 */ 429 */
430 int sc_generation; 430 int sc_generation;
431 431
432 int sc_cap_off; /* PCIe caps */ 432 int sc_cap_off; /* PCIe caps */
433 433
434 const char *sc_fwname; 434 const char *sc_fwname;
435 bus_size_t sc_fwdmasegsz; 435 bus_size_t sc_fwdmasegsz;
436 struct iwm_fw_info sc_fw; 436 struct iwm_fw_info sc_fw;
437 int sc_fw_phy_config; 437 int sc_fw_phy_config;
438 struct iwm_tlv_calib_ctrl sc_default_calib[IWM_UCODE_TYPE_MAX]; 438 struct iwm_tlv_calib_ctrl sc_default_calib[IWM_UCODE_TYPE_MAX];
439 439
440 struct iwm_nvm_data sc_nvm; 440 struct iwm_nvm_data sc_nvm;
441 struct iwm_phy_db sc_phy_db; 441 struct iwm_phy_db sc_phy_db;
442 442
443 struct iwm_bf_data sc_bf; 443 struct iwm_bf_data sc_bf;
444 444
445 int sc_tx_timer; 445 int sc_tx_timer;
446 446
447 struct iwm_scan_cmd *sc_scan_cmd; 447 struct iwm_scan_cmd *sc_scan_cmd;
448 size_t sc_scan_cmd_len; 448 size_t sc_scan_cmd_len;
449 int sc_scan_last_antenna; 449 int sc_scan_last_antenna;
450 int sc_scanband; 450 int sc_scanband;
451 451
452 int sc_auth_prot; 452 int sc_auth_prot;
453 453
454 int sc_fixed_ridx; 454 int sc_fixed_ridx;
455 455
456 int sc_staid; 456 int sc_staid;
457 int sc_nodecolor; 457 int sc_nodecolor;
458 458
459 uint8_t sc_cmd_resp[IWM_CMD_RESP_MAX]; 459 uint8_t sc_cmd_resp[IWM_CMD_RESP_MAX];
460 int sc_wantresp; 460 int sc_wantresp;
461 461
462 struct workqueue *sc_nswq, *sc_eswq; 462 struct workqueue *sc_nswq, *sc_eswq;
463 struct work sc_eswk; 463 struct work sc_eswk;
464 464
465 struct iwm_rx_phy_info sc_last_phy_info; 465 struct iwm_rx_phy_info sc_last_phy_info;
466 int sc_ampdu_ref; 466 int sc_ampdu_ref;
467 467
468 struct iwm_int_sta sc_aux_sta; 468 struct iwm_int_sta sc_aux_sta;
469 469
470 /* phy contexts. we only use the first one */ 470 /* phy contexts. we only use the first one */
471 struct iwm_mvm_phy_ctxt sc_phyctxt[IWM_NUM_PHY_CTX]; 471 struct iwm_mvm_phy_ctxt sc_phyctxt[IWM_NUM_PHY_CTX];
472 472
473 struct iwm_notif_statistics sc_stats; 473 struct iwm_notif_statistics sc_stats;
474 int sc_noise; 474 int sc_noise;
475 475
 476 int host_interrupt_operation_mode;
 477
476 struct bpf_if * sc_drvbpf; 478 struct bpf_if * sc_drvbpf;
477 479
478 union { 480 union {
479 struct iwm_rx_radiotap_header th; 481 struct iwm_rx_radiotap_header th;
480 uint8_t pad[IEEE80211_RADIOTAP_HDRLEN]; 482 uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
481 } sc_rxtapu; 483 } sc_rxtapu;
482#define sc_rxtap sc_rxtapu.th 484#define sc_rxtap sc_rxtapu.th
483 int sc_rxtap_len; 485 int sc_rxtap_len;
484 486
485 union { 487 union {
486 struct iwm_tx_radiotap_header th; 488 struct iwm_tx_radiotap_header th;
487 uint8_t pad[IEEE80211_RADIOTAP_HDRLEN]; 489 uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
488 } sc_txtapu; 490 } sc_txtapu;
489#define sc_txtap sc_txtapu.th 491#define sc_txtap sc_txtapu.th
490 int sc_txtap_len; 492 int sc_txtap_len;
491}; 493};
492 494
493struct iwm_node { 495struct iwm_node {
494 struct ieee80211_node in_ni; 496 struct ieee80211_node in_ni;
495 struct iwm_mvm_phy_ctxt *in_phyctxt; 497 struct iwm_mvm_phy_ctxt *in_phyctxt;
496 498
497 uint16_t in_id; 499 uint16_t in_id;
498 uint16_t in_color; 500 uint16_t in_color;
499 int in_tsfid; 501 int in_tsfid;
500 502
501 /* status "bits" */ 503 /* status "bits" */
502 int in_assoc; 504 int in_assoc;
503 505
504 struct iwm_lq_cmd in_lq; 506 struct iwm_lq_cmd in_lq;
505 struct ieee80211_amrr_node in_amn; 507 struct ieee80211_amrr_node in_amn;
506 508
507 uint8_t in_ridx[IEEE80211_RATE_MAXSIZE]; 509 uint8_t in_ridx[IEEE80211_RATE_MAXSIZE];
508}; 510};
509#define IWM_STATION_ID 0 511#define IWM_STATION_ID 0
510 512
511#define IWM_ICT_SIZE 4096 513#define IWM_ICT_SIZE 4096
512#define IWM_ICT_COUNT (IWM_ICT_SIZE / sizeof (uint32_t)) 514#define IWM_ICT_COUNT (IWM_ICT_SIZE / sizeof (uint32_t))
513#define IWM_ICT_PADDR_SHIFT 12 515#define IWM_ICT_PADDR_SHIFT 12