Tue Mar 3 09:34:40 2015 UTC ()
sc_fixed_ridx is initialised to 0 but tested as it it were initialised
to -1.  The result of this is tx frames were always sent out at fixed
rate 0 instead of ni_txrate.

Match the iwn behaviour and test ic_fixed_rate for -1 instead.

From OpenBSD rev.1.29.


(nonaka)
diff -r1.20 -r1.21 src/sys/dev/pci/if_iwm.c

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

--- src/sys/dev/pci/if_iwm.c 2015/03/03 09:27:35 1.20
+++ src/sys/dev/pci/if_iwm.c 2015/03/03 09:34:40 1.21
@@ -1,1107 +1,1107 @@ @@ -1,1107 +1,1107 @@
1/* $NetBSD: if_iwm.c,v 1.20 2015/03/03 09:27:35 nonaka Exp $ */ 1/* $NetBSD: if_iwm.c,v 1.21 2015/03/03 09:34:40 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.20 2015/03/03 09:27:35 nonaka Exp $"); 108__KERNEL_RCSID(0, "$NetBSD: if_iwm.c,v 1.21 2015/03/03 09:34:40 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
@@ -2821,1999 +2821,1999 @@ iwm_load_firmware(struct iwm_softc *sc,  @@ -2821,1999 +2821,1999 @@ iwm_load_firmware(struct iwm_softc *sc,
2821} 2821}
2822 2822
2823/* iwlwifi: pcie/trans.c */ 2823/* iwlwifi: pcie/trans.c */
2824static int 2824static int
2825iwm_start_fw(struct iwm_softc *sc, enum iwm_ucode_type ucode_type) 2825iwm_start_fw(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
2826{ 2826{
2827 int error; 2827 int error;
2828 2828
2829 IWM_WRITE(sc, IWM_CSR_INT, ~0); 2829 IWM_WRITE(sc, IWM_CSR_INT, ~0);
2830 2830
2831 if ((error = iwm_nic_init(sc)) != 0) { 2831 if ((error = iwm_nic_init(sc)) != 0) {
2832 aprint_error_dev(sc->sc_dev, "Unable to init nic\n"); 2832 aprint_error_dev(sc->sc_dev, "Unable to init nic\n");
2833 return error; 2833 return error;
2834 } 2834 }
2835 2835
2836 /* make sure rfkill handshake bits are cleared */ 2836 /* make sure rfkill handshake bits are cleared */
2837 IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR, IWM_CSR_UCODE_SW_BIT_RFKILL); 2837 IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR, IWM_CSR_UCODE_SW_BIT_RFKILL);
2838 IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR, 2838 IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR,
2839 IWM_CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); 2839 IWM_CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
2840 2840
2841 /* clear (again), then enable host interrupts */ 2841 /* clear (again), then enable host interrupts */
2842 IWM_WRITE(sc, IWM_CSR_INT, ~0); 2842 IWM_WRITE(sc, IWM_CSR_INT, ~0);
2843 iwm_enable_interrupts(sc); 2843 iwm_enable_interrupts(sc);
2844 2844
2845 /* really make sure rfkill handshake bits are cleared */ 2845 /* really make sure rfkill handshake bits are cleared */
2846 /* maybe we should write a few times more? just to make sure */ 2846 /* maybe we should write a few times more? just to make sure */
2847 IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR, IWM_CSR_UCODE_SW_BIT_RFKILL); 2847 IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR, IWM_CSR_UCODE_SW_BIT_RFKILL);
2848 IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR, IWM_CSR_UCODE_SW_BIT_RFKILL); 2848 IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR, IWM_CSR_UCODE_SW_BIT_RFKILL);
2849 2849
2850 /* Load the given image to the HW */ 2850 /* Load the given image to the HW */
2851 error = iwm_load_firmware(sc, ucode_type); 2851 error = iwm_load_firmware(sc, ucode_type);
2852 if (error) { 2852 if (error) {
2853 aprint_error_dev(sc->sc_dev, "failed to load firmware: %d\n", 2853 aprint_error_dev(sc->sc_dev, "failed to load firmware: %d\n",
2854 error); 2854 error);
2855 } 2855 }
2856 return error; 2856 return error;
2857} 2857}
2858 2858
2859static int 2859static int
2860iwm_fw_alive(struct iwm_softc *sc, uint32_t sched_base) 2860iwm_fw_alive(struct iwm_softc *sc, uint32_t sched_base)
2861{ 2861{
2862 return iwm_post_alive(sc); 2862 return iwm_post_alive(sc);
2863} 2863}
2864 2864
2865static int 2865static int
2866iwm_send_tx_ant_cfg(struct iwm_softc *sc, uint8_t valid_tx_ant) 2866iwm_send_tx_ant_cfg(struct iwm_softc *sc, uint8_t valid_tx_ant)
2867{ 2867{
2868 struct iwm_tx_ant_cfg_cmd tx_ant_cmd = { 2868 struct iwm_tx_ant_cfg_cmd tx_ant_cmd = {
2869 .valid = htole32(valid_tx_ant), 2869 .valid = htole32(valid_tx_ant),
2870 }; 2870 };
2871 2871
2872 return iwm_mvm_send_cmd_pdu(sc, IWM_TX_ANT_CONFIGURATION_CMD, 2872 return iwm_mvm_send_cmd_pdu(sc, IWM_TX_ANT_CONFIGURATION_CMD,
2873 IWM_CMD_SYNC, sizeof(tx_ant_cmd), &tx_ant_cmd); 2873 IWM_CMD_SYNC, sizeof(tx_ant_cmd), &tx_ant_cmd);
2874} 2874}
2875 2875
2876/* iwlwifi: mvm/fw.c */ 2876/* iwlwifi: mvm/fw.c */
2877static int 2877static int
2878iwm_send_phy_cfg_cmd(struct iwm_softc *sc) 2878iwm_send_phy_cfg_cmd(struct iwm_softc *sc)
2879{ 2879{
2880 struct iwm_phy_cfg_cmd phy_cfg_cmd; 2880 struct iwm_phy_cfg_cmd phy_cfg_cmd;
2881 enum iwm_ucode_type ucode_type = sc->sc_uc_current; 2881 enum iwm_ucode_type ucode_type = sc->sc_uc_current;
2882 2882
2883 /* Set parameters */ 2883 /* Set parameters */
2884 phy_cfg_cmd.phy_cfg = htole32(sc->sc_fw_phy_config); 2884 phy_cfg_cmd.phy_cfg = htole32(sc->sc_fw_phy_config);
2885 phy_cfg_cmd.calib_control.event_trigger = 2885 phy_cfg_cmd.calib_control.event_trigger =
2886 sc->sc_default_calib[ucode_type].event_trigger; 2886 sc->sc_default_calib[ucode_type].event_trigger;
2887 phy_cfg_cmd.calib_control.flow_trigger = 2887 phy_cfg_cmd.calib_control.flow_trigger =
2888 sc->sc_default_calib[ucode_type].flow_trigger; 2888 sc->sc_default_calib[ucode_type].flow_trigger;
2889 2889
2890 DPRINTFN(10, ("Sending Phy CFG command: 0x%x\n", phy_cfg_cmd.phy_cfg)); 2890 DPRINTFN(10, ("Sending Phy CFG command: 0x%x\n", phy_cfg_cmd.phy_cfg));
2891 return iwm_mvm_send_cmd_pdu(sc, IWM_PHY_CONFIGURATION_CMD, IWM_CMD_SYNC, 2891 return iwm_mvm_send_cmd_pdu(sc, IWM_PHY_CONFIGURATION_CMD, IWM_CMD_SYNC,
2892 sizeof(phy_cfg_cmd), &phy_cfg_cmd); 2892 sizeof(phy_cfg_cmd), &phy_cfg_cmd);
2893} 2893}
2894 2894
2895static int 2895static int
2896iwm_mvm_load_ucode_wait_alive(struct iwm_softc *sc, 2896iwm_mvm_load_ucode_wait_alive(struct iwm_softc *sc,
2897 enum iwm_ucode_type ucode_type) 2897 enum iwm_ucode_type ucode_type)
2898{ 2898{
2899 enum iwm_ucode_type old_type = sc->sc_uc_current; 2899 enum iwm_ucode_type old_type = sc->sc_uc_current;
2900 int error; 2900 int error;
2901 2901
2902 if ((error = iwm_read_firmware(sc)) != 0) 2902 if ((error = iwm_read_firmware(sc)) != 0)
2903 return error; 2903 return error;
2904 2904
2905 sc->sc_uc_current = ucode_type; 2905 sc->sc_uc_current = ucode_type;
2906 error = iwm_start_fw(sc, ucode_type); 2906 error = iwm_start_fw(sc, ucode_type);
2907 if (error) { 2907 if (error) {
2908 sc->sc_uc_current = old_type; 2908 sc->sc_uc_current = old_type;
2909 return error; 2909 return error;
2910 } 2910 }
2911 2911
2912 return iwm_fw_alive(sc, sc->sched_base); 2912 return iwm_fw_alive(sc, sc->sched_base);
2913} 2913}
2914 2914
2915/* 2915/*
2916 * mvm misc bits 2916 * mvm misc bits
2917 */ 2917 */
2918 2918
2919/* 2919/*
2920 * follows iwlwifi/fw.c 2920 * follows iwlwifi/fw.c
2921 */ 2921 */
2922static int 2922static int
2923iwm_run_init_mvm_ucode(struct iwm_softc *sc, int justnvm) 2923iwm_run_init_mvm_ucode(struct iwm_softc *sc, int justnvm)
2924{ 2924{
2925 int error; 2925 int error;
2926 2926
2927 /* do not operate with rfkill switch turned on */ 2927 /* do not operate with rfkill switch turned on */
2928 if ((sc->sc_flags & IWM_FLAG_RFKILL) && !justnvm) { 2928 if ((sc->sc_flags & IWM_FLAG_RFKILL) && !justnvm) {
2929 aprint_error_dev(sc->sc_dev, 2929 aprint_error_dev(sc->sc_dev,
2930 "radio is disabled by hardware switch\n"); 2930 "radio is disabled by hardware switch\n");
2931 return EPERM; 2931 return EPERM;
2932 } 2932 }
2933 2933
2934 sc->sc_init_complete = 0; 2934 sc->sc_init_complete = 0;
2935 if ((error = iwm_mvm_load_ucode_wait_alive(sc, 2935 if ((error = iwm_mvm_load_ucode_wait_alive(sc,
2936 IWM_UCODE_TYPE_INIT)) != 0) 2936 IWM_UCODE_TYPE_INIT)) != 0)
2937 return error; 2937 return error;
2938 2938
2939 if (justnvm) { 2939 if (justnvm) {
2940 if ((error = iwm_nvm_init(sc)) != 0) { 2940 if ((error = iwm_nvm_init(sc)) != 0) {
2941 aprint_error_dev(sc->sc_dev, "failed to read nvm\n"); 2941 aprint_error_dev(sc->sc_dev, "failed to read nvm\n");
2942 return error; 2942 return error;
2943 } 2943 }
2944 memcpy(&sc->sc_ic.ic_myaddr, 2944 memcpy(&sc->sc_ic.ic_myaddr,
2945 &sc->sc_nvm.hw_addr, ETHER_ADDR_LEN); 2945 &sc->sc_nvm.hw_addr, ETHER_ADDR_LEN);
2946 2946
2947 sc->sc_scan_cmd_len = sizeof(struct iwm_scan_cmd) 2947 sc->sc_scan_cmd_len = sizeof(struct iwm_scan_cmd)
2948 + sc->sc_capa_max_probe_len 2948 + sc->sc_capa_max_probe_len
2949 + IWM_MAX_NUM_SCAN_CHANNELS 2949 + IWM_MAX_NUM_SCAN_CHANNELS
2950 * sizeof(struct iwm_scan_channel); 2950 * sizeof(struct iwm_scan_channel);
2951 sc->sc_scan_cmd = kmem_alloc(sc->sc_scan_cmd_len, KM_SLEEP); 2951 sc->sc_scan_cmd = kmem_alloc(sc->sc_scan_cmd_len, KM_SLEEP);
2952 2952
2953 return 0; 2953 return 0;
2954 } 2954 }
2955 2955
2956 /* Send TX valid antennas before triggering calibrations */ 2956 /* Send TX valid antennas before triggering calibrations */
2957 if ((error = iwm_send_tx_ant_cfg(sc, IWM_FW_VALID_TX_ANT(sc))) != 0) 2957 if ((error = iwm_send_tx_ant_cfg(sc, IWM_FW_VALID_TX_ANT(sc))) != 0)
2958 return error; 2958 return error;
2959 2959
2960 /* 2960 /*
2961 * Send phy configurations command to init uCode 2961 * Send phy configurations command to init uCode
2962 * to start the 16.0 uCode init image internal calibrations. 2962 * to start the 16.0 uCode init image internal calibrations.
2963 */ 2963 */
2964 if ((error = iwm_send_phy_cfg_cmd(sc)) != 0 ) { 2964 if ((error = iwm_send_phy_cfg_cmd(sc)) != 0 ) {
2965 DPRINTF(("%s: failed to run internal calibration: %d\n", 2965 DPRINTF(("%s: failed to run internal calibration: %d\n",
2966 DEVNAME(sc), error)); 2966 DEVNAME(sc), error));
2967 return error; 2967 return error;
2968 } 2968 }
2969 2969
2970 /* 2970 /*
2971 * Nothing to do but wait for the init complete notification 2971 * Nothing to do but wait for the init complete notification
2972 * from the firmware 2972 * from the firmware
2973 */ 2973 */
2974 while (!sc->sc_init_complete) 2974 while (!sc->sc_init_complete)
2975 if ((error = tsleep(&sc->sc_init_complete, 2975 if ((error = tsleep(&sc->sc_init_complete,
2976 0, "iwminit", 2*hz)) != 0) 2976 0, "iwminit", 2*hz)) != 0)
2977 break; 2977 break;
2978 2978
2979 return error; 2979 return error;
2980} 2980}
2981 2981
2982/* 2982/*
2983 * receive side 2983 * receive side
2984 */ 2984 */
2985 2985
2986/* (re)stock rx ring, called at init-time and at runtime */ 2986/* (re)stock rx ring, called at init-time and at runtime */
2987static int 2987static int
2988iwm_rx_addbuf(struct iwm_softc *sc, int size, int idx) 2988iwm_rx_addbuf(struct iwm_softc *sc, int size, int idx)
2989{ 2989{
2990 struct iwm_rx_ring *ring = &sc->rxq; 2990 struct iwm_rx_ring *ring = &sc->rxq;
2991 struct iwm_rx_data *data = &ring->data[idx]; 2991 struct iwm_rx_data *data = &ring->data[idx];
2992 struct mbuf *m; 2992 struct mbuf *m;
2993 int error; 2993 int error;
2994 int fatal = 0; 2994 int fatal = 0;
2995 2995
2996 m = m_gethdr(M_DONTWAIT, MT_DATA); 2996 m = m_gethdr(M_DONTWAIT, MT_DATA);
2997 if (m == NULL) 2997 if (m == NULL)
2998 return ENOBUFS; 2998 return ENOBUFS;
2999 2999
3000 if (size <= MCLBYTES) { 3000 if (size <= MCLBYTES) {
3001 MCLGET(m, M_DONTWAIT); 3001 MCLGET(m, M_DONTWAIT);
3002 } else { 3002 } else {
3003 MEXTMALLOC(m, IWM_RBUF_SIZE, M_DONTWAIT); 3003 MEXTMALLOC(m, IWM_RBUF_SIZE, M_DONTWAIT);
3004 } 3004 }
3005 if ((m->m_flags & M_EXT) == 0) { 3005 if ((m->m_flags & M_EXT) == 0) {
3006 m_freem(m); 3006 m_freem(m);
3007 return ENOBUFS; 3007 return ENOBUFS;
3008 } 3008 }
3009 3009
3010 if (data->m != NULL) { 3010 if (data->m != NULL) {
3011 bus_dmamap_unload(sc->sc_dmat, data->map); 3011 bus_dmamap_unload(sc->sc_dmat, data->map);
3012 fatal = 1; 3012 fatal = 1;
3013 } 3013 }
3014 3014
3015 m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 3015 m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
3016 if ((error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m, 3016 if ((error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m,
3017 BUS_DMA_READ|BUS_DMA_NOWAIT)) != 0) { 3017 BUS_DMA_READ|BUS_DMA_NOWAIT)) != 0) {
3018 /* XXX */ 3018 /* XXX */
3019 if (fatal) 3019 if (fatal)
3020 panic("iwm: could not load RX mbuf"); 3020 panic("iwm: could not load RX mbuf");
3021 m_freem(m); 3021 m_freem(m);
3022 return error; 3022 return error;
3023 } 3023 }
3024 data->m = m; 3024 data->m = m;
3025 bus_dmamap_sync(sc->sc_dmat, data->map, 0, size, BUS_DMASYNC_PREREAD); 3025 bus_dmamap_sync(sc->sc_dmat, data->map, 0, size, BUS_DMASYNC_PREREAD);
3026 3026
3027 /* Update RX descriptor. */ 3027 /* Update RX descriptor. */
3028 ring->desc[idx] = htole32(data->map->dm_segs[0].ds_addr >> 8); 3028 ring->desc[idx] = htole32(data->map->dm_segs[0].ds_addr >> 8);
3029 bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 3029 bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,
3030 idx * sizeof(uint32_t), sizeof(uint32_t), BUS_DMASYNC_PREWRITE); 3030 idx * sizeof(uint32_t), sizeof(uint32_t), BUS_DMASYNC_PREWRITE);
3031 3031
3032 return 0; 3032 return 0;
3033} 3033}
3034 3034
3035/* iwlwifi: mvm/rx.c */ 3035/* iwlwifi: mvm/rx.c */
3036#define IWM_RSSI_OFFSET 50 3036#define IWM_RSSI_OFFSET 50
3037static int 3037static int
3038iwm_mvm_calc_rssi(struct iwm_softc *sc, struct iwm_rx_phy_info *phy_info) 3038iwm_mvm_calc_rssi(struct iwm_softc *sc, struct iwm_rx_phy_info *phy_info)
3039{ 3039{
3040 int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm; 3040 int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm;
3041 uint32_t agc_a, agc_b; 3041 uint32_t agc_a, agc_b;
3042 uint32_t val; 3042 uint32_t val;
3043 3043
3044 val = le32toh(phy_info->non_cfg_phy[IWM_RX_INFO_AGC_IDX]); 3044 val = le32toh(phy_info->non_cfg_phy[IWM_RX_INFO_AGC_IDX]);
3045 agc_a = (val & IWM_OFDM_AGC_A_MSK) >> IWM_OFDM_AGC_A_POS; 3045 agc_a = (val & IWM_OFDM_AGC_A_MSK) >> IWM_OFDM_AGC_A_POS;
3046 agc_b = (val & IWM_OFDM_AGC_B_MSK) >> IWM_OFDM_AGC_B_POS; 3046 agc_b = (val & IWM_OFDM_AGC_B_MSK) >> IWM_OFDM_AGC_B_POS;
3047 3047
3048 val = le32toh(phy_info->non_cfg_phy[IWM_RX_INFO_RSSI_AB_IDX]); 3048 val = le32toh(phy_info->non_cfg_phy[IWM_RX_INFO_RSSI_AB_IDX]);
3049 rssi_a = (val & IWM_OFDM_RSSI_INBAND_A_MSK) >> IWM_OFDM_RSSI_A_POS; 3049 rssi_a = (val & IWM_OFDM_RSSI_INBAND_A_MSK) >> IWM_OFDM_RSSI_A_POS;
3050 rssi_b = (val & IWM_OFDM_RSSI_INBAND_B_MSK) >> IWM_OFDM_RSSI_B_POS; 3050 rssi_b = (val & IWM_OFDM_RSSI_INBAND_B_MSK) >> IWM_OFDM_RSSI_B_POS;
3051 3051
3052 /* 3052 /*
3053 * dBm = rssi dB - agc dB - constant. 3053 * dBm = rssi dB - agc dB - constant.
3054 * Higher AGC (higher radio gain) means lower signal. 3054 * Higher AGC (higher radio gain) means lower signal.
3055 */ 3055 */
3056 rssi_a_dbm = rssi_a - IWM_RSSI_OFFSET - agc_a; 3056 rssi_a_dbm = rssi_a - IWM_RSSI_OFFSET - agc_a;
3057 rssi_b_dbm = rssi_b - IWM_RSSI_OFFSET - agc_b; 3057 rssi_b_dbm = rssi_b - IWM_RSSI_OFFSET - agc_b;
3058 max_rssi_dbm = MAX(rssi_a_dbm, rssi_b_dbm); 3058 max_rssi_dbm = MAX(rssi_a_dbm, rssi_b_dbm);
3059 3059
3060 DPRINTF(("Rssi In A %d B %d Max %d AGCA %d AGCB %d\n", 3060 DPRINTF(("Rssi In A %d B %d Max %d AGCA %d AGCB %d\n",
3061 rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b)); 3061 rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b));
3062 3062
3063 return max_rssi_dbm; 3063 return max_rssi_dbm;
3064} 3064}
3065 3065
3066/* iwlwifi: mvm/rx.c */ 3066/* iwlwifi: mvm/rx.c */
3067/* 3067/*
3068 * iwm_mvm_get_signal_strength - use new rx PHY INFO API 3068 * iwm_mvm_get_signal_strength - use new rx PHY INFO API
3069 * values are reported by the fw as positive values - need to negate 3069 * values are reported by the fw as positive values - need to negate
3070 * to obtain their dBM. Account for missing antennas by replacing 0 3070 * to obtain their dBM. Account for missing antennas by replacing 0
3071 * values by -256dBm: practically 0 power and a non-feasible 8 bit value. 3071 * values by -256dBm: practically 0 power and a non-feasible 8 bit value.
3072 */ 3072 */
3073static int 3073static int
3074iwm_mvm_get_signal_strength(struct iwm_softc *sc, 3074iwm_mvm_get_signal_strength(struct iwm_softc *sc,
3075 struct iwm_rx_phy_info *phy_info) 3075 struct iwm_rx_phy_info *phy_info)
3076{ 3076{
3077 int energy_a, energy_b, energy_c, max_energy; 3077 int energy_a, energy_b, energy_c, max_energy;
3078 uint32_t val; 3078 uint32_t val;
3079 3079
3080 val = le32toh(phy_info->non_cfg_phy[IWM_RX_INFO_ENERGY_ANT_ABC_IDX]); 3080 val = le32toh(phy_info->non_cfg_phy[IWM_RX_INFO_ENERGY_ANT_ABC_IDX]);
3081 energy_a = (val & IWM_RX_INFO_ENERGY_ANT_A_MSK) >> 3081 energy_a = (val & IWM_RX_INFO_ENERGY_ANT_A_MSK) >>
3082 IWM_RX_INFO_ENERGY_ANT_A_POS; 3082 IWM_RX_INFO_ENERGY_ANT_A_POS;
3083 energy_a = energy_a ? -energy_a : -256; 3083 energy_a = energy_a ? -energy_a : -256;
3084 energy_b = (val & IWM_RX_INFO_ENERGY_ANT_B_MSK) >> 3084 energy_b = (val & IWM_RX_INFO_ENERGY_ANT_B_MSK) >>
3085 IWM_RX_INFO_ENERGY_ANT_B_POS; 3085 IWM_RX_INFO_ENERGY_ANT_B_POS;
3086 energy_b = energy_b ? -energy_b : -256; 3086 energy_b = energy_b ? -energy_b : -256;
3087 energy_c = (val & IWM_RX_INFO_ENERGY_ANT_C_MSK) >> 3087 energy_c = (val & IWM_RX_INFO_ENERGY_ANT_C_MSK) >>
3088 IWM_RX_INFO_ENERGY_ANT_C_POS; 3088 IWM_RX_INFO_ENERGY_ANT_C_POS;
3089 energy_c = energy_c ? -energy_c : -256; 3089 energy_c = energy_c ? -energy_c : -256;
3090 max_energy = MAX(energy_a, energy_b); 3090 max_energy = MAX(energy_a, energy_b);
3091 max_energy = MAX(max_energy, energy_c); 3091 max_energy = MAX(max_energy, energy_c);
3092 3092
3093 DPRINTFN(12, ("energy In A %d B %d C %d, and max %d\n", 3093 DPRINTFN(12, ("energy In A %d B %d C %d, and max %d\n",
3094 energy_a, energy_b, energy_c, max_energy)); 3094 energy_a, energy_b, energy_c, max_energy));
3095 3095
3096 return max_energy; 3096 return max_energy;
3097} 3097}
3098 3098
3099static void 3099static void
3100iwm_mvm_rx_rx_phy_cmd(struct iwm_softc *sc, 3100iwm_mvm_rx_rx_phy_cmd(struct iwm_softc *sc,
3101 struct iwm_rx_packet *pkt, struct iwm_rx_data *data) 3101 struct iwm_rx_packet *pkt, struct iwm_rx_data *data)
3102{ 3102{
3103 struct iwm_rx_phy_info *phy_info = (void *)pkt->data; 3103 struct iwm_rx_phy_info *phy_info = (void *)pkt->data;
3104 3104
3105 DPRINTFN(20, ("received PHY stats\n")); 3105 DPRINTFN(20, ("received PHY stats\n"));
3106 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*pkt), 3106 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*pkt),
3107 sizeof(*phy_info), BUS_DMASYNC_POSTREAD); 3107 sizeof(*phy_info), BUS_DMASYNC_POSTREAD);
3108 3108
3109 memcpy(&sc->sc_last_phy_info, phy_info, sizeof(sc->sc_last_phy_info)); 3109 memcpy(&sc->sc_last_phy_info, phy_info, sizeof(sc->sc_last_phy_info));
3110} 3110}
3111 3111
3112/* 3112/*
3113 * Retrieve the average noise (in dBm) among receivers. 3113 * Retrieve the average noise (in dBm) among receivers.
3114 */ 3114 */
3115static int 3115static int
3116iwm_get_noise(const struct iwm_mvm_statistics_rx_non_phy *stats) 3116iwm_get_noise(const struct iwm_mvm_statistics_rx_non_phy *stats)
3117{ 3117{
3118 int i, total, nbant, noise; 3118 int i, total, nbant, noise;
3119 3119
3120 total = nbant = noise = 0; 3120 total = nbant = noise = 0;
3121 for (i = 0; i < 3; i++) { 3121 for (i = 0; i < 3; i++) {
3122 noise = le32toh(stats->beacon_silence_rssi[i]) & 0xff; 3122 noise = le32toh(stats->beacon_silence_rssi[i]) & 0xff;
3123 if (noise) { 3123 if (noise) {
3124 total += noise; 3124 total += noise;
3125 nbant++; 3125 nbant++;
3126 } 3126 }
3127 } 3127 }
3128 3128
3129 /* There should be at least one antenna but check anyway. */ 3129 /* There should be at least one antenna but check anyway. */
3130 return (nbant == 0) ? -127 : (total / nbant) - 107; 3130 return (nbant == 0) ? -127 : (total / nbant) - 107;
3131} 3131}
3132 3132
3133/* 3133/*
3134 * iwm_mvm_rx_rx_mpdu - IWM_REPLY_RX_MPDU_CMD handler 3134 * iwm_mvm_rx_rx_mpdu - IWM_REPLY_RX_MPDU_CMD handler
3135 * 3135 *
3136 * Handles the actual data of the Rx packet from the fw 3136 * Handles the actual data of the Rx packet from the fw
3137 */ 3137 */
3138static void 3138static void
3139iwm_mvm_rx_rx_mpdu(struct iwm_softc *sc, 3139iwm_mvm_rx_rx_mpdu(struct iwm_softc *sc,
3140 struct iwm_rx_packet *pkt, struct iwm_rx_data *data) 3140 struct iwm_rx_packet *pkt, struct iwm_rx_data *data)
3141{ 3141{
3142 struct ieee80211com *ic = &sc->sc_ic; 3142 struct ieee80211com *ic = &sc->sc_ic;
3143 struct ieee80211_frame *wh; 3143 struct ieee80211_frame *wh;
3144 struct ieee80211_node *ni; 3144 struct ieee80211_node *ni;
3145 struct ieee80211_channel *c = NULL; 3145 struct ieee80211_channel *c = NULL;
3146 struct mbuf *m; 3146 struct mbuf *m;
3147 struct iwm_rx_phy_info *phy_info; 3147 struct iwm_rx_phy_info *phy_info;
3148 struct iwm_rx_mpdu_res_start *rx_res; 3148 struct iwm_rx_mpdu_res_start *rx_res;
3149 int device_timestamp; 3149 int device_timestamp;
3150 uint32_t len; 3150 uint32_t len;
3151 uint32_t rx_pkt_status; 3151 uint32_t rx_pkt_status;
3152 int rssi; 3152 int rssi;
3153 3153
3154 bus_dmamap_sync(sc->sc_dmat, data->map, 0, IWM_RBUF_SIZE, 3154 bus_dmamap_sync(sc->sc_dmat, data->map, 0, IWM_RBUF_SIZE,
3155 BUS_DMASYNC_POSTREAD); 3155 BUS_DMASYNC_POSTREAD);
3156 3156
3157 phy_info = &sc->sc_last_phy_info; 3157 phy_info = &sc->sc_last_phy_info;
3158 rx_res = (struct iwm_rx_mpdu_res_start *)pkt->data; 3158 rx_res = (struct iwm_rx_mpdu_res_start *)pkt->data;
3159 wh = (struct ieee80211_frame *)(pkt->data + sizeof(*rx_res)); 3159 wh = (struct ieee80211_frame *)(pkt->data + sizeof(*rx_res));
3160 len = le16toh(rx_res->byte_count); 3160 len = le16toh(rx_res->byte_count);
3161 rx_pkt_status = le32toh(*(uint32_t *)(pkt->data + sizeof(*rx_res) + len)); 3161 rx_pkt_status = le32toh(*(uint32_t *)(pkt->data + sizeof(*rx_res) + len));
3162 3162
3163 m = data->m; 3163 m = data->m;
3164 m->m_data = pkt->data + sizeof(*rx_res); 3164 m->m_data = pkt->data + sizeof(*rx_res);
3165 m->m_pkthdr.len = m->m_len = len; 3165 m->m_pkthdr.len = m->m_len = len;
3166 3166
3167 if (__predict_false(phy_info->cfg_phy_cnt > 20)) { 3167 if (__predict_false(phy_info->cfg_phy_cnt > 20)) {
3168 DPRINTF(("dsp size out of range [0,20]: %d\n", 3168 DPRINTF(("dsp size out of range [0,20]: %d\n",
3169 phy_info->cfg_phy_cnt)); 3169 phy_info->cfg_phy_cnt));
3170 return; 3170 return;
3171 } 3171 }
3172 3172
3173 if (!(rx_pkt_status & IWM_RX_MPDU_RES_STATUS_CRC_OK) || 3173 if (!(rx_pkt_status & IWM_RX_MPDU_RES_STATUS_CRC_OK) ||
3174 !(rx_pkt_status & IWM_RX_MPDU_RES_STATUS_OVERRUN_OK)) { 3174 !(rx_pkt_status & IWM_RX_MPDU_RES_STATUS_OVERRUN_OK)) {
3175 DPRINTF(("Bad CRC or FIFO: 0x%08X.\n", rx_pkt_status)); 3175 DPRINTF(("Bad CRC or FIFO: 0x%08X.\n", rx_pkt_status));
3176 return; /* drop */ 3176 return; /* drop */
3177 } 3177 }
3178 3178
3179 device_timestamp = le32toh(phy_info->system_timestamp); 3179 device_timestamp = le32toh(phy_info->system_timestamp);
3180 3180
3181 if (sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_RX_ENERGY_API) { 3181 if (sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_RX_ENERGY_API) {
3182 rssi = iwm_mvm_get_signal_strength(sc, phy_info); 3182 rssi = iwm_mvm_get_signal_strength(sc, phy_info);
3183 } else { 3183 } else {
3184 rssi = iwm_mvm_calc_rssi(sc, phy_info); 3184 rssi = iwm_mvm_calc_rssi(sc, phy_info);
3185 } 3185 }
3186 rssi = -rssi; 3186 rssi = -rssi;
3187 3187
3188 if (ic->ic_state == IEEE80211_S_SCAN) 3188 if (ic->ic_state == IEEE80211_S_SCAN)
3189 iwm_fix_channel(ic, m); 3189 iwm_fix_channel(ic, m);
3190 3190
3191 /* replenish ring for the buffer we're going to feed to the sharks */ 3191 /* replenish ring for the buffer we're going to feed to the sharks */
3192 if (iwm_rx_addbuf(sc, IWM_RBUF_SIZE, sc->rxq.cur) != 0) 3192 if (iwm_rx_addbuf(sc, IWM_RBUF_SIZE, sc->rxq.cur) != 0)
3193 return; 3193 return;
3194 3194
3195 m->m_pkthdr.rcvif = IC2IFP(ic); 3195 m->m_pkthdr.rcvif = IC2IFP(ic);
3196 3196
3197 if (sc->sc_scanband == IEEE80211_CHAN_5GHZ) { 3197 if (sc->sc_scanband == IEEE80211_CHAN_5GHZ) {
3198 if (le32toh(phy_info->channel) < __arraycount(ic->ic_channels)) 3198 if (le32toh(phy_info->channel) < __arraycount(ic->ic_channels))
3199 c = &ic->ic_channels[le32toh(phy_info->channel)]; 3199 c = &ic->ic_channels[le32toh(phy_info->channel)];
3200 } 3200 }
3201 3201
3202 ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); 3202 ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
3203 if (c) 3203 if (c)
3204 ni->ni_chan = c; 3204 ni->ni_chan = c;
3205 3205
3206 if (sc->sc_drvbpf != NULL) { 3206 if (sc->sc_drvbpf != NULL) {
3207 struct iwm_rx_radiotap_header *tap = &sc->sc_rxtap; 3207 struct iwm_rx_radiotap_header *tap = &sc->sc_rxtap;
3208 3208
3209 tap->wr_flags = 0; 3209 tap->wr_flags = 0;
3210 if (phy_info->phy_flags & htole16(IWM_PHY_INFO_FLAG_SHPREAMBLE)) 3210 if (phy_info->phy_flags & htole16(IWM_PHY_INFO_FLAG_SHPREAMBLE))
3211 tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; 3211 tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
3212 tap->wr_chan_freq = 3212 tap->wr_chan_freq =
3213 htole16(ic->ic_channels[phy_info->channel].ic_freq); 3213 htole16(ic->ic_channels[phy_info->channel].ic_freq);
3214 tap->wr_chan_flags = 3214 tap->wr_chan_flags =
3215 htole16(ic->ic_channels[phy_info->channel].ic_flags); 3215 htole16(ic->ic_channels[phy_info->channel].ic_flags);
3216 tap->wr_dbm_antsignal = (int8_t)rssi; 3216 tap->wr_dbm_antsignal = (int8_t)rssi;
3217 tap->wr_dbm_antnoise = (int8_t)sc->sc_noise; 3217 tap->wr_dbm_antnoise = (int8_t)sc->sc_noise;
3218 tap->wr_tsft = phy_info->system_timestamp; 3218 tap->wr_tsft = phy_info->system_timestamp;
3219 switch (phy_info->rate) { 3219 switch (phy_info->rate) {
3220 /* CCK rates. */ 3220 /* CCK rates. */
3221 case 10: tap->wr_rate = 2; break; 3221 case 10: tap->wr_rate = 2; break;
3222 case 20: tap->wr_rate = 4; break; 3222 case 20: tap->wr_rate = 4; break;
3223 case 55: tap->wr_rate = 11; break; 3223 case 55: tap->wr_rate = 11; break;
3224 case 110: tap->wr_rate = 22; break; 3224 case 110: tap->wr_rate = 22; break;
3225 /* OFDM rates. */ 3225 /* OFDM rates. */
3226 case 0xd: tap->wr_rate = 12; break; 3226 case 0xd: tap->wr_rate = 12; break;
3227 case 0xf: tap->wr_rate = 18; break; 3227 case 0xf: tap->wr_rate = 18; break;
3228 case 0x5: tap->wr_rate = 24; break; 3228 case 0x5: tap->wr_rate = 24; break;
3229 case 0x7: tap->wr_rate = 36; break; 3229 case 0x7: tap->wr_rate = 36; break;
3230 case 0x9: tap->wr_rate = 48; break; 3230 case 0x9: tap->wr_rate = 48; break;
3231 case 0xb: tap->wr_rate = 72; break; 3231 case 0xb: tap->wr_rate = 72; break;
3232 case 0x1: tap->wr_rate = 96; break; 3232 case 0x1: tap->wr_rate = 96; break;
3233 case 0x3: tap->wr_rate = 108; break; 3233 case 0x3: tap->wr_rate = 108; break;
3234 /* Unknown rate: should not happen. */ 3234 /* Unknown rate: should not happen. */
3235 default: tap->wr_rate = 0; 3235 default: tap->wr_rate = 0;
3236 } 3236 }
3237 3237
3238 bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m); 3238 bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);
3239 } 3239 }
3240 ieee80211_input(ic, m, ni, rssi, device_timestamp); 3240 ieee80211_input(ic, m, ni, rssi, device_timestamp);
3241 ieee80211_free_node(ni); 3241 ieee80211_free_node(ni);
3242} 3242}
3243 3243
3244static void 3244static void
3245iwm_mvm_rx_tx_cmd_single(struct iwm_softc *sc, struct iwm_rx_packet *pkt, 3245iwm_mvm_rx_tx_cmd_single(struct iwm_softc *sc, struct iwm_rx_packet *pkt,
3246 struct iwm_node *in) 3246 struct iwm_node *in)
3247{ 3247{
3248 struct ieee80211com *ic = &sc->sc_ic; 3248 struct ieee80211com *ic = &sc->sc_ic;
3249 struct ifnet *ifp = IC2IFP(ic); 3249 struct ifnet *ifp = IC2IFP(ic);
3250 struct iwm_mvm_tx_resp *tx_resp = (void *)pkt->data; 3250 struct iwm_mvm_tx_resp *tx_resp = (void *)pkt->data;
3251 int status = le16toh(tx_resp->status.status) & IWM_TX_STATUS_MSK; 3251 int status = le16toh(tx_resp->status.status) & IWM_TX_STATUS_MSK;
3252 int failack = tx_resp->failure_frame; 3252 int failack = tx_resp->failure_frame;
3253 3253
3254 KASSERT(tx_resp->frame_count == 1); 3254 KASSERT(tx_resp->frame_count == 1);
3255 3255
3256 /* Update rate control statistics. */ 3256 /* Update rate control statistics. */
3257 in->in_amn.amn_txcnt++; 3257 in->in_amn.amn_txcnt++;
3258 if (failack > 0) { 3258 if (failack > 0) {
3259 in->in_amn.amn_retrycnt++; 3259 in->in_amn.amn_retrycnt++;
3260 } 3260 }
3261 3261
3262 if (status != IWM_TX_STATUS_SUCCESS && 3262 if (status != IWM_TX_STATUS_SUCCESS &&
3263 status != IWM_TX_STATUS_DIRECT_DONE) 3263 status != IWM_TX_STATUS_DIRECT_DONE)
3264 ifp->if_oerrors++; 3264 ifp->if_oerrors++;
3265 else 3265 else
3266 ifp->if_opackets++; 3266 ifp->if_opackets++;
3267} 3267}
3268 3268
3269static void 3269static void
3270iwm_mvm_rx_tx_cmd(struct iwm_softc *sc, 3270iwm_mvm_rx_tx_cmd(struct iwm_softc *sc,
3271 struct iwm_rx_packet *pkt, struct iwm_rx_data *data) 3271 struct iwm_rx_packet *pkt, struct iwm_rx_data *data)
3272{ 3272{
3273 struct ieee80211com *ic = &sc->sc_ic; 3273 struct ieee80211com *ic = &sc->sc_ic;
3274 struct ifnet *ifp = IC2IFP(ic); 3274 struct ifnet *ifp = IC2IFP(ic);
3275 struct iwm_cmd_header *cmd_hdr = &pkt->hdr; 3275 struct iwm_cmd_header *cmd_hdr = &pkt->hdr;
3276 int idx = cmd_hdr->idx; 3276 int idx = cmd_hdr->idx;
3277 int qid = cmd_hdr->qid; 3277 int qid = cmd_hdr->qid;
3278 struct iwm_tx_ring *ring = &sc->txq[qid]; 3278 struct iwm_tx_ring *ring = &sc->txq[qid];
3279 struct iwm_tx_data *txd = &ring->data[idx]; 3279 struct iwm_tx_data *txd = &ring->data[idx];
3280 struct iwm_node *in = txd->in; 3280 struct iwm_node *in = txd->in;
3281 3281
3282 if (txd->done) { 3282 if (txd->done) {
3283 DPRINTF(("%s: got tx interrupt that's already been handled!\n", 3283 DPRINTF(("%s: got tx interrupt that's already been handled!\n",
3284 DEVNAME(sc))); 3284 DEVNAME(sc)));
3285 return; 3285 return;
3286 } 3286 }
3287 3287
3288 bus_dmamap_sync(sc->sc_dmat, data->map, 0, IWM_RBUF_SIZE, 3288 bus_dmamap_sync(sc->sc_dmat, data->map, 0, IWM_RBUF_SIZE,
3289 BUS_DMASYNC_POSTREAD); 3289 BUS_DMASYNC_POSTREAD);
3290 3290
3291 sc->sc_tx_timer = 0; 3291 sc->sc_tx_timer = 0;
3292 3292
3293 iwm_mvm_rx_tx_cmd_single(sc, pkt, in); 3293 iwm_mvm_rx_tx_cmd_single(sc, pkt, in);
3294 3294
3295 /* Unmap and free mbuf. */ 3295 /* Unmap and free mbuf. */
3296 bus_dmamap_sync(sc->sc_dmat, txd->map, 0, txd->map->dm_mapsize, 3296 bus_dmamap_sync(sc->sc_dmat, txd->map, 0, txd->map->dm_mapsize,
3297 BUS_DMASYNC_POSTWRITE); 3297 BUS_DMASYNC_POSTWRITE);
3298 bus_dmamap_unload(sc->sc_dmat, txd->map); 3298 bus_dmamap_unload(sc->sc_dmat, txd->map);
3299 m_freem(txd->m); 3299 m_freem(txd->m);
3300 3300
3301 DPRINTFN(8, ("free txd %p, in %p\n", txd, txd->in)); 3301 DPRINTFN(8, ("free txd %p, in %p\n", txd, txd->in));
3302 KASSERT(txd->done == 0); 3302 KASSERT(txd->done == 0);
3303 txd->done = 1; 3303 txd->done = 1;
3304 KASSERT(txd->in); 3304 KASSERT(txd->in);
3305 3305
3306 txd->m = NULL; 3306 txd->m = NULL;
3307 txd->in = NULL; 3307 txd->in = NULL;
3308 ieee80211_free_node(&in->in_ni); 3308 ieee80211_free_node(&in->in_ni);
3309 3309
3310 if (--ring->queued < IWM_TX_RING_LOMARK) { 3310 if (--ring->queued < IWM_TX_RING_LOMARK) {
3311 sc->qfullmsk &= ~(1 << ring->qid); 3311 sc->qfullmsk &= ~(1 << ring->qid);
3312 if (sc->qfullmsk == 0 && (ifp->if_flags & IFF_OACTIVE)) { 3312 if (sc->qfullmsk == 0 && (ifp->if_flags & IFF_OACTIVE)) {
3313 ifp->if_flags &= ~IFF_OACTIVE; 3313 ifp->if_flags &= ~IFF_OACTIVE;
3314 /* 3314 /*
3315 * Well, we're in interrupt context, but then again 3315 * Well, we're in interrupt context, but then again
3316 * I guess net80211 does all sorts of stunts in 3316 * I guess net80211 does all sorts of stunts in
3317 * interrupt context, so maybe this is no biggie. 3317 * interrupt context, so maybe this is no biggie.
3318 */ 3318 */
3319 (*ifp->if_start)(ifp); 3319 (*ifp->if_start)(ifp);
3320 } 3320 }
3321 } 3321 }
3322} 3322}
3323 3323
3324/* 3324/*
3325 * BEGIN iwlwifi/mvm/binding.c 3325 * BEGIN iwlwifi/mvm/binding.c
3326 */ 3326 */
3327 3327
3328static int 3328static int
3329iwm_mvm_binding_cmd(struct iwm_softc *sc, struct iwm_node *in, uint32_t action) 3329iwm_mvm_binding_cmd(struct iwm_softc *sc, struct iwm_node *in, uint32_t action)
3330{ 3330{
3331 struct iwm_binding_cmd cmd; 3331 struct iwm_binding_cmd cmd;
3332 struct iwm_mvm_phy_ctxt *phyctxt = in->in_phyctxt; 3332 struct iwm_mvm_phy_ctxt *phyctxt = in->in_phyctxt;
3333 int i, ret; 3333 int i, ret;
3334 uint32_t status; 3334 uint32_t status;
3335 3335
3336 memset(&cmd, 0, sizeof(cmd)); 3336 memset(&cmd, 0, sizeof(cmd));
3337 3337
3338 cmd.id_and_color 3338 cmd.id_and_color
3339 = htole32(IWM_FW_CMD_ID_AND_COLOR(phyctxt->id, phyctxt->color)); 3339 = htole32(IWM_FW_CMD_ID_AND_COLOR(phyctxt->id, phyctxt->color));
3340 cmd.action = htole32(action); 3340 cmd.action = htole32(action);
3341 cmd.phy = htole32(IWM_FW_CMD_ID_AND_COLOR(phyctxt->id, phyctxt->color)); 3341 cmd.phy = htole32(IWM_FW_CMD_ID_AND_COLOR(phyctxt->id, phyctxt->color));
3342 3342
3343 cmd.macs[0] = htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color)); 3343 cmd.macs[0] = htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));
3344 for (i = 1; i < IWM_MAX_MACS_IN_BINDING; i++) 3344 for (i = 1; i < IWM_MAX_MACS_IN_BINDING; i++)
3345 cmd.macs[i] = htole32(IWM_FW_CTXT_INVALID); 3345 cmd.macs[i] = htole32(IWM_FW_CTXT_INVALID);
3346 3346
3347 status = 0; 3347 status = 0;
3348 ret = iwm_mvm_send_cmd_pdu_status(sc, IWM_BINDING_CONTEXT_CMD, 3348 ret = iwm_mvm_send_cmd_pdu_status(sc, IWM_BINDING_CONTEXT_CMD,
3349 sizeof(cmd), &cmd, &status); 3349 sizeof(cmd), &cmd, &status);
3350 if (ret) { 3350 if (ret) {
3351 DPRINTF(("%s: Failed to send binding (action:%d): %d\n", 3351 DPRINTF(("%s: Failed to send binding (action:%d): %d\n",
3352 DEVNAME(sc), action, ret)); 3352 DEVNAME(sc), action, ret));
3353 return ret; 3353 return ret;
3354 } 3354 }
3355 3355
3356 if (status) { 3356 if (status) {
3357 DPRINTF(("%s: Binding command failed: %u\n", DEVNAME(sc), 3357 DPRINTF(("%s: Binding command failed: %u\n", DEVNAME(sc),
3358 status)); 3358 status));
3359 ret = EIO; 3359 ret = EIO;
3360 } 3360 }
3361 3361
3362 return ret; 3362 return ret;
3363} 3363}
3364 3364
3365static int 3365static int
3366iwm_mvm_binding_update(struct iwm_softc *sc, struct iwm_node *in, int add) 3366iwm_mvm_binding_update(struct iwm_softc *sc, struct iwm_node *in, int add)
3367{ 3367{
3368 return iwm_mvm_binding_cmd(sc, in, IWM_FW_CTXT_ACTION_ADD); 3368 return iwm_mvm_binding_cmd(sc, in, IWM_FW_CTXT_ACTION_ADD);
3369} 3369}
3370 3370
3371static int 3371static int
3372iwm_mvm_binding_add_vif(struct iwm_softc *sc, struct iwm_node *in) 3372iwm_mvm_binding_add_vif(struct iwm_softc *sc, struct iwm_node *in)
3373{ 3373{
3374 return iwm_mvm_binding_update(sc, in, IWM_FW_CTXT_ACTION_ADD); 3374 return iwm_mvm_binding_update(sc, in, IWM_FW_CTXT_ACTION_ADD);
3375} 3375}
3376 3376
3377/* 3377/*
3378 * END iwlwifi/mvm/binding.c 3378 * END iwlwifi/mvm/binding.c
3379 */ 3379 */
3380 3380
3381/* 3381/*
3382 * BEGIN iwlwifi/mvm/phy-ctxt.c 3382 * BEGIN iwlwifi/mvm/phy-ctxt.c
3383 */ 3383 */
3384 3384
3385/* 3385/*
3386 * Construct the generic fields of the PHY context command 3386 * Construct the generic fields of the PHY context command
3387 */ 3387 */
3388static void 3388static void
3389iwm_mvm_phy_ctxt_cmd_hdr(struct iwm_softc *sc, struct iwm_mvm_phy_ctxt *ctxt, 3389iwm_mvm_phy_ctxt_cmd_hdr(struct iwm_softc *sc, struct iwm_mvm_phy_ctxt *ctxt,
3390 struct iwm_phy_context_cmd *cmd, uint32_t action, uint32_t apply_time) 3390 struct iwm_phy_context_cmd *cmd, uint32_t action, uint32_t apply_time)
3391{ 3391{
3392 memset(cmd, 0, sizeof(struct iwm_phy_context_cmd)); 3392 memset(cmd, 0, sizeof(struct iwm_phy_context_cmd));
3393 3393
3394 cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(ctxt->id, 3394 cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(ctxt->id,
3395 ctxt->color)); 3395 ctxt->color));
3396 cmd->action = htole32(action); 3396 cmd->action = htole32(action);
3397 cmd->apply_time = htole32(apply_time); 3397 cmd->apply_time = htole32(apply_time);
3398} 3398}
3399 3399
3400/* 3400/*
3401 * Add the phy configuration to the PHY context command 3401 * Add the phy configuration to the PHY context command
3402 */ 3402 */
3403static void 3403static void
3404iwm_mvm_phy_ctxt_cmd_data(struct iwm_softc *sc, 3404iwm_mvm_phy_ctxt_cmd_data(struct iwm_softc *sc,
3405 struct iwm_phy_context_cmd *cmd, struct ieee80211_channel *chan, 3405 struct iwm_phy_context_cmd *cmd, struct ieee80211_channel *chan,
3406 uint8_t chains_static, uint8_t chains_dynamic) 3406 uint8_t chains_static, uint8_t chains_dynamic)
3407{ 3407{
3408 struct ieee80211com *ic = &sc->sc_ic; 3408 struct ieee80211com *ic = &sc->sc_ic;
3409 uint8_t active_cnt, idle_cnt; 3409 uint8_t active_cnt, idle_cnt;
3410 3410
3411 cmd->ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ? 3411 cmd->ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?
3412 IWM_PHY_BAND_24 : IWM_PHY_BAND_5; 3412 IWM_PHY_BAND_24 : IWM_PHY_BAND_5;
3413 3413
3414 cmd->ci.channel = ieee80211_chan2ieee(ic, chan); 3414 cmd->ci.channel = ieee80211_chan2ieee(ic, chan);
3415 cmd->ci.width = IWM_PHY_VHT_CHANNEL_MODE20; 3415 cmd->ci.width = IWM_PHY_VHT_CHANNEL_MODE20;
3416 cmd->ci.ctrl_pos = IWM_PHY_VHT_CTRL_POS_1_BELOW; 3416 cmd->ci.ctrl_pos = IWM_PHY_VHT_CTRL_POS_1_BELOW;
3417 3417
3418 /* Set rx the chains */ 3418 /* Set rx the chains */
3419 idle_cnt = chains_static; 3419 idle_cnt = chains_static;
3420 active_cnt = chains_dynamic; 3420 active_cnt = chains_dynamic;
3421 3421
3422 cmd->rxchain_info = htole32(IWM_FW_VALID_RX_ANT(sc) << 3422 cmd->rxchain_info = htole32(IWM_FW_VALID_RX_ANT(sc) <<
3423 IWM_PHY_RX_CHAIN_VALID_POS); 3423 IWM_PHY_RX_CHAIN_VALID_POS);
3424 cmd->rxchain_info |= htole32(idle_cnt << IWM_PHY_RX_CHAIN_CNT_POS); 3424 cmd->rxchain_info |= htole32(idle_cnt << IWM_PHY_RX_CHAIN_CNT_POS);
3425 cmd->rxchain_info |= htole32(active_cnt << 3425 cmd->rxchain_info |= htole32(active_cnt <<
3426 IWM_PHY_RX_CHAIN_MIMO_CNT_POS); 3426 IWM_PHY_RX_CHAIN_MIMO_CNT_POS);
3427 3427
3428 cmd->txchain_info = htole32(IWM_FW_VALID_TX_ANT(sc)); 3428 cmd->txchain_info = htole32(IWM_FW_VALID_TX_ANT(sc));
3429} 3429}
3430 3430
3431/* 3431/*
3432 * Send a command 3432 * Send a command
3433 * only if something in the configuration changed: in case that this is the 3433 * only if something in the configuration changed: in case that this is the
3434 * first time that the phy configuration is applied or in case that the phy 3434 * first time that the phy configuration is applied or in case that the phy
3435 * configuration changed from the previous apply. 3435 * configuration changed from the previous apply.
3436 */ 3436 */
3437static int 3437static int
3438iwm_mvm_phy_ctxt_apply(struct iwm_softc *sc, 3438iwm_mvm_phy_ctxt_apply(struct iwm_softc *sc,
3439 struct iwm_mvm_phy_ctxt *ctxt, 3439 struct iwm_mvm_phy_ctxt *ctxt,
3440 uint8_t chains_static, uint8_t chains_dynamic, 3440 uint8_t chains_static, uint8_t chains_dynamic,
3441 uint32_t action, uint32_t apply_time) 3441 uint32_t action, uint32_t apply_time)
3442{ 3442{
3443 struct iwm_phy_context_cmd cmd; 3443 struct iwm_phy_context_cmd cmd;
3444 int ret; 3444 int ret;
3445 3445
3446 /* Set the command header fields */ 3446 /* Set the command header fields */
3447 iwm_mvm_phy_ctxt_cmd_hdr(sc, ctxt, &cmd, action, apply_time); 3447 iwm_mvm_phy_ctxt_cmd_hdr(sc, ctxt, &cmd, action, apply_time);
3448 3448
3449 /* Set the command data */ 3449 /* Set the command data */
3450 iwm_mvm_phy_ctxt_cmd_data(sc, &cmd, ctxt->channel, 3450 iwm_mvm_phy_ctxt_cmd_data(sc, &cmd, ctxt->channel,
3451 chains_static, chains_dynamic); 3451 chains_static, chains_dynamic);
3452 3452
3453 ret = iwm_mvm_send_cmd_pdu(sc, IWM_PHY_CONTEXT_CMD, IWM_CMD_SYNC, 3453 ret = iwm_mvm_send_cmd_pdu(sc, IWM_PHY_CONTEXT_CMD, IWM_CMD_SYNC,
3454 sizeof(struct iwm_phy_context_cmd), &cmd); 3454 sizeof(struct iwm_phy_context_cmd), &cmd);
3455 if (ret) { 3455 if (ret) {
3456 DPRINTF(("PHY ctxt cmd error. ret=%d\n", ret)); 3456 DPRINTF(("PHY ctxt cmd error. ret=%d\n", ret));
3457 } 3457 }
3458 return ret; 3458 return ret;
3459} 3459}
3460 3460
3461/* 3461/*
3462 * Send a command to add a PHY context based on the current HW configuration. 3462 * Send a command to add a PHY context based on the current HW configuration.
3463 */ 3463 */
3464static int 3464static int
3465iwm_mvm_phy_ctxt_add(struct iwm_softc *sc, struct iwm_mvm_phy_ctxt *ctxt, 3465iwm_mvm_phy_ctxt_add(struct iwm_softc *sc, struct iwm_mvm_phy_ctxt *ctxt,
3466 struct ieee80211_channel *chan, 3466 struct ieee80211_channel *chan,
3467 uint8_t chains_static, uint8_t chains_dynamic) 3467 uint8_t chains_static, uint8_t chains_dynamic)
3468{ 3468{
3469 ctxt->channel = chan; 3469 ctxt->channel = chan;
3470 return iwm_mvm_phy_ctxt_apply(sc, ctxt, 3470 return iwm_mvm_phy_ctxt_apply(sc, ctxt,
3471 chains_static, chains_dynamic, IWM_FW_CTXT_ACTION_ADD, 0); 3471 chains_static, chains_dynamic, IWM_FW_CTXT_ACTION_ADD, 0);
3472} 3472}
3473 3473
3474/* 3474/*
3475 * Send a command to modify the PHY context based on the current HW 3475 * Send a command to modify the PHY context based on the current HW
3476 * configuration. Note that the function does not check that the configuration 3476 * configuration. Note that the function does not check that the configuration
3477 * changed. 3477 * changed.
3478 */ 3478 */
3479static int 3479static int
3480iwm_mvm_phy_ctxt_changed(struct iwm_softc *sc, 3480iwm_mvm_phy_ctxt_changed(struct iwm_softc *sc,
3481 struct iwm_mvm_phy_ctxt *ctxt, struct ieee80211_channel *chan, 3481 struct iwm_mvm_phy_ctxt *ctxt, struct ieee80211_channel *chan,
3482 uint8_t chains_static, uint8_t chains_dynamic) 3482 uint8_t chains_static, uint8_t chains_dynamic)
3483{ 3483{
3484 ctxt->channel = chan; 3484 ctxt->channel = chan;
3485 return iwm_mvm_phy_ctxt_apply(sc, ctxt, 3485 return iwm_mvm_phy_ctxt_apply(sc, ctxt,
3486 chains_static, chains_dynamic, IWM_FW_CTXT_ACTION_MODIFY, 0); 3486 chains_static, chains_dynamic, IWM_FW_CTXT_ACTION_MODIFY, 0);
3487} 3487}
3488 3488
3489/* 3489/*
3490 * END iwlwifi/mvm/phy-ctxt.c 3490 * END iwlwifi/mvm/phy-ctxt.c
3491 */ 3491 */
3492 3492
3493/* 3493/*
3494 * transmit side 3494 * transmit side
3495 */ 3495 */
3496 3496
3497/* 3497/*
3498 * Send a command to the firmware. We try to implement the Linux 3498 * Send a command to the firmware. We try to implement the Linux
3499 * driver interface for the routine. 3499 * driver interface for the routine.
3500 * mostly from if_iwn (iwn_cmd()). 3500 * mostly from if_iwn (iwn_cmd()).
3501 * 3501 *
3502 * For now, we always copy the first part and map the second one (if it exists). 3502 * For now, we always copy the first part and map the second one (if it exists).
3503 */ 3503 */
3504static int 3504static int
3505iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd) 3505iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
3506{ 3506{
3507 struct iwm_tx_ring *ring = &sc->txq[IWM_MVM_CMD_QUEUE]; 3507 struct iwm_tx_ring *ring = &sc->txq[IWM_MVM_CMD_QUEUE];
3508 struct iwm_tfd *desc; 3508 struct iwm_tfd *desc;
3509 struct iwm_tx_data *data; 3509 struct iwm_tx_data *data;
3510 struct iwm_device_cmd *cmd; 3510 struct iwm_device_cmd *cmd;
3511 struct mbuf *m; 3511 struct mbuf *m;
3512 bus_addr_t paddr; 3512 bus_addr_t paddr;
3513 uint32_t addr_lo; 3513 uint32_t addr_lo;
3514 int error = 0, i, paylen, off, s; 3514 int error = 0, i, paylen, off, s;
3515 int code; 3515 int code;
3516 int async, wantresp; 3516 int async, wantresp;
3517 3517
3518 code = hcmd->id; 3518 code = hcmd->id;
3519 async = hcmd->flags & IWM_CMD_ASYNC; 3519 async = hcmd->flags & IWM_CMD_ASYNC;
3520 wantresp = hcmd->flags & IWM_CMD_WANT_SKB; 3520 wantresp = hcmd->flags & IWM_CMD_WANT_SKB;
3521 3521
3522 for (i = 0, paylen = 0; i < __arraycount(hcmd->len); i++) { 3522 for (i = 0, paylen = 0; i < __arraycount(hcmd->len); i++) {
3523 paylen += hcmd->len[i]; 3523 paylen += hcmd->len[i];
3524 } 3524 }
3525 3525
3526 /* if the command wants an answer, busy sc_cmd_resp */ 3526 /* if the command wants an answer, busy sc_cmd_resp */
3527 if (wantresp) { 3527 if (wantresp) {
3528 KASSERT(!async); 3528 KASSERT(!async);
3529 while (sc->sc_wantresp != -1) 3529 while (sc->sc_wantresp != -1)
3530 tsleep(&sc->sc_wantresp, 0, "iwmcmdsl", 0); 3530 tsleep(&sc->sc_wantresp, 0, "iwmcmdsl", 0);
3531 sc->sc_wantresp = ring->qid << 16 | ring->cur; 3531 sc->sc_wantresp = ring->qid << 16 | ring->cur;
3532 DPRINTFN(12, ("wantresp is %x\n", sc->sc_wantresp)); 3532 DPRINTFN(12, ("wantresp is %x\n", sc->sc_wantresp));
3533 } 3533 }
3534 3534
3535 /* 3535 /*
3536 * Is the hardware still available? (after e.g. above wait). 3536 * Is the hardware still available? (after e.g. above wait).
3537 */ 3537 */
3538 s = splnet(); 3538 s = splnet();
3539 if (sc->sc_flags & IWM_FLAG_STOPPED) { 3539 if (sc->sc_flags & IWM_FLAG_STOPPED) {
3540 error = ENXIO; 3540 error = ENXIO;
3541 goto out; 3541 goto out;
3542 } 3542 }
3543 3543
3544 desc = &ring->desc[ring->cur]; 3544 desc = &ring->desc[ring->cur];
3545 data = &ring->data[ring->cur]; 3545 data = &ring->data[ring->cur];
3546 3546
3547 if (paylen > sizeof(cmd->data)) { 3547 if (paylen > sizeof(cmd->data)) {
3548 /* Command is too large */ 3548 /* Command is too large */
3549 if (sizeof(cmd->hdr) + paylen > IWM_RBUF_SIZE) { 3549 if (sizeof(cmd->hdr) + paylen > IWM_RBUF_SIZE) {
3550 error = EINVAL; 3550 error = EINVAL;
3551 goto out; 3551 goto out;
3552 } 3552 }
3553 m = m_gethdr(M_DONTWAIT, MT_DATA); 3553 m = m_gethdr(M_DONTWAIT, MT_DATA);
3554 if (m == NULL) { 3554 if (m == NULL) {
3555 error = ENOMEM; 3555 error = ENOMEM;
3556 goto out; 3556 goto out;
3557 } 3557 }
3558 MEXTMALLOC(m, IWM_RBUF_SIZE, M_DONTWAIT); 3558 MEXTMALLOC(m, IWM_RBUF_SIZE, M_DONTWAIT);
3559 if (!(m->m_flags & M_EXT)) { 3559 if (!(m->m_flags & M_EXT)) {
3560 m_freem(m); 3560 m_freem(m);
3561 error = ENOMEM; 3561 error = ENOMEM;
3562 goto out; 3562 goto out;
3563 } 3563 }
3564 cmd = mtod(m, struct iwm_device_cmd *); 3564 cmd = mtod(m, struct iwm_device_cmd *);
3565 error = bus_dmamap_load(sc->sc_dmat, data->map, cmd, 3565 error = bus_dmamap_load(sc->sc_dmat, data->map, cmd,
3566 IWM_RBUF_SIZE, NULL, BUS_DMA_NOWAIT | BUS_DMA_WRITE); 3566 IWM_RBUF_SIZE, NULL, BUS_DMA_NOWAIT | BUS_DMA_WRITE);
3567 if (error != 0) { 3567 if (error != 0) {
3568 m_freem(m); 3568 m_freem(m);
3569 goto out; 3569 goto out;
3570 } 3570 }
3571 data->m = m; 3571 data->m = m;
3572 paddr = data->map->dm_segs[0].ds_addr; 3572 paddr = data->map->dm_segs[0].ds_addr;
3573 } else { 3573 } else {
3574 cmd = &ring->cmd[ring->cur]; 3574 cmd = &ring->cmd[ring->cur];
3575 paddr = data->cmd_paddr; 3575 paddr = data->cmd_paddr;
3576 } 3576 }
3577 3577
3578 cmd->hdr.code = code; 3578 cmd->hdr.code = code;
3579 cmd->hdr.flags = 0; 3579 cmd->hdr.flags = 0;
3580 cmd->hdr.qid = ring->qid; 3580 cmd->hdr.qid = ring->qid;
3581 cmd->hdr.idx = ring->cur; 3581 cmd->hdr.idx = ring->cur;
3582 3582
3583 for (i = 0, off = 0; i < __arraycount(hcmd->data); i++) { 3583 for (i = 0, off = 0; i < __arraycount(hcmd->data); i++) {
3584 if (hcmd->len[i] == 0) 3584 if (hcmd->len[i] == 0)
3585 continue; 3585 continue;
3586 memcpy(cmd->data + off, hcmd->data[i], hcmd->len[i]); 3586 memcpy(cmd->data + off, hcmd->data[i], hcmd->len[i]);
3587 off += hcmd->len[i]; 3587 off += hcmd->len[i];
3588 } 3588 }
3589 KASSERT(off == paylen); 3589 KASSERT(off == paylen);
3590 3590
3591 /* lo field is not aligned */ 3591 /* lo field is not aligned */
3592 addr_lo = htole32((uint32_t)paddr); 3592 addr_lo = htole32((uint32_t)paddr);
3593 memcpy(&desc->tbs[0].lo, &addr_lo, sizeof(uint32_t)); 3593 memcpy(&desc->tbs[0].lo, &addr_lo, sizeof(uint32_t));
3594 desc->tbs[0].hi_n_len = htole16(iwm_get_dma_hi_addr(paddr) 3594 desc->tbs[0].hi_n_len = htole16(iwm_get_dma_hi_addr(paddr)
3595 | ((sizeof(cmd->hdr) + paylen) << 4)); 3595 | ((sizeof(cmd->hdr) + paylen) << 4));
3596 desc->num_tbs = 1; 3596 desc->num_tbs = 1;
3597 3597
3598 DPRINTFN(8, ("iwm_send_cmd 0x%x size=%zu %s\n", 3598 DPRINTFN(8, ("iwm_send_cmd 0x%x size=%zu %s\n",
3599 code, sizeof(cmd->hdr) + paylen, async ? " (async)" : "")); 3599 code, sizeof(cmd->hdr) + paylen, async ? " (async)" : ""));
3600 3600
3601 if (paylen > sizeof(cmd->data)) { 3601 if (paylen > sizeof(cmd->data)) {
3602 bus_dmamap_sync(sc->sc_dmat, data->map, 0, 3602 bus_dmamap_sync(sc->sc_dmat, data->map, 0,
3603 sizeof(cmd->hdr) + paylen, BUS_DMASYNC_PREWRITE); 3603 sizeof(cmd->hdr) + paylen, BUS_DMASYNC_PREWRITE);
3604 } else { 3604 } else {
3605 bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map, 3605 bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map,
3606 (char *)(void *)cmd - (char *)(void *)ring->cmd_dma.vaddr, 3606 (char *)(void *)cmd - (char *)(void *)ring->cmd_dma.vaddr,
3607 sizeof(cmd->hdr) + paylen, BUS_DMASYNC_PREWRITE); 3607 sizeof(cmd->hdr) + paylen, BUS_DMASYNC_PREWRITE);
3608 } 3608 }
3609 bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 3609 bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,
3610 (char *)(void *)desc - (char *)(void *)ring->desc_dma.vaddr, 3610 (char *)(void *)desc - (char *)(void *)ring->desc_dma.vaddr,
3611 sizeof (*desc), BUS_DMASYNC_PREWRITE); 3611 sizeof (*desc), BUS_DMASYNC_PREWRITE);
3612 3612
3613 IWM_SETBITS(sc, IWM_CSR_GP_CNTRL, 3613 IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
3614 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 3614 IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
3615 if (!iwm_poll_bit(sc, IWM_CSR_GP_CNTRL, 3615 if (!iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
3616 IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, 3616 IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
3617 (IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | 3617 (IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
3618 IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000)) { 3618 IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000)) {
3619 DPRINTF(("%s: acquiring device failed\n", DEVNAME(sc))); 3619 DPRINTF(("%s: acquiring device failed\n", DEVNAME(sc)));
3620 error = EBUSY; 3620 error = EBUSY;
3621 goto out; 3621 goto out;
3622 } 3622 }
3623 3623
3624#if 0 3624#if 0
3625 iwm_update_sched(sc, ring->qid, ring->cur, 0, 0); 3625 iwm_update_sched(sc, ring->qid, ring->cur, 0, 0);
3626#endif 3626#endif
3627 DPRINTF(("sending command 0x%x qid %d, idx %d\n", 3627 DPRINTF(("sending command 0x%x qid %d, idx %d\n",
3628 code, ring->qid, ring->cur)); 3628 code, ring->qid, ring->cur));
3629 3629
3630 /* Kick command ring. */ 3630 /* Kick command ring. */
3631 ring->cur = (ring->cur + 1) % IWM_TX_RING_COUNT; 3631 ring->cur = (ring->cur + 1) % IWM_TX_RING_COUNT;
3632 IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); 3632 IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
3633 3633
3634 if (!async) { 3634 if (!async) {
3635 /* m..m-mmyy-mmyyyy-mym-ym m-my generation */ 3635 /* m..m-mmyy-mmyyyy-mym-ym m-my generation */
3636 int generation = sc->sc_generation; 3636 int generation = sc->sc_generation;
3637 error = tsleep(desc, PCATCH, "iwmcmd", hz); 3637 error = tsleep(desc, PCATCH, "iwmcmd", hz);
3638 if (error == 0) { 3638 if (error == 0) {
3639 /* if hardware is no longer up, return error */ 3639 /* if hardware is no longer up, return error */
3640 if (generation != sc->sc_generation) { 3640 if (generation != sc->sc_generation) {
3641 error = ENXIO; 3641 error = ENXIO;
3642 } else { 3642 } else {
3643 hcmd->resp_pkt = (void *)sc->sc_cmd_resp; 3643 hcmd->resp_pkt = (void *)sc->sc_cmd_resp;
3644 } 3644 }
3645 } 3645 }
3646 } 3646 }
3647 out: 3647 out:
3648 if (wantresp && error != 0) { 3648 if (wantresp && error != 0) {
3649 iwm_free_resp(sc, hcmd); 3649 iwm_free_resp(sc, hcmd);
3650 } 3650 }
3651 splx(s); 3651 splx(s);
3652 3652
3653 return error; 3653 return error;
3654} 3654}
3655 3655
3656/* iwlwifi: mvm/utils.c */ 3656/* iwlwifi: mvm/utils.c */
3657static int 3657static int
3658iwm_mvm_send_cmd_pdu(struct iwm_softc *sc, uint8_t id, 3658iwm_mvm_send_cmd_pdu(struct iwm_softc *sc, uint8_t id,
3659 uint32_t flags, uint16_t len, const void *data) 3659 uint32_t flags, uint16_t len, const void *data)
3660{ 3660{
3661 struct iwm_host_cmd cmd = { 3661 struct iwm_host_cmd cmd = {
3662 .id = id, 3662 .id = id,
3663 .len = { len, }, 3663 .len = { len, },
3664 .data = { data, }, 3664 .data = { data, },
3665 .flags = flags, 3665 .flags = flags,
3666 }; 3666 };
3667 3667
3668 return iwm_send_cmd(sc, &cmd); 3668 return iwm_send_cmd(sc, &cmd);
3669} 3669}
3670 3670
3671/* iwlwifi: mvm/utils.c */ 3671/* iwlwifi: mvm/utils.c */
3672static int 3672static int
3673iwm_mvm_send_cmd_status(struct iwm_softc *sc, 3673iwm_mvm_send_cmd_status(struct iwm_softc *sc,
3674 struct iwm_host_cmd *cmd, uint32_t *status) 3674 struct iwm_host_cmd *cmd, uint32_t *status)
3675{ 3675{
3676 struct iwm_rx_packet *pkt; 3676 struct iwm_rx_packet *pkt;
3677 struct iwm_cmd_response *resp; 3677 struct iwm_cmd_response *resp;
3678 int error, resp_len; 3678 int error, resp_len;
3679 3679
3680 //lockdep_assert_held(&mvm->mutex); 3680 //lockdep_assert_held(&mvm->mutex);
3681 3681
3682 KASSERT((cmd->flags & IWM_CMD_WANT_SKB) == 0); 3682 KASSERT((cmd->flags & IWM_CMD_WANT_SKB) == 0);
3683 cmd->flags |= IWM_CMD_SYNC | IWM_CMD_WANT_SKB; 3683 cmd->flags |= IWM_CMD_SYNC | IWM_CMD_WANT_SKB;
3684 3684
3685 if ((error = iwm_send_cmd(sc, cmd)) != 0) 3685 if ((error = iwm_send_cmd(sc, cmd)) != 0)
3686 return error; 3686 return error;
3687 pkt = cmd->resp_pkt; 3687 pkt = cmd->resp_pkt;
3688 3688
3689 /* Can happen if RFKILL is asserted */ 3689 /* Can happen if RFKILL is asserted */
3690 if (!pkt) { 3690 if (!pkt) {
3691 error = 0; 3691 error = 0;
3692 goto out_free_resp; 3692 goto out_free_resp;
3693 } 3693 }
3694 3694
3695 if (pkt->hdr.flags & IWM_CMD_FAILED_MSK) { 3695 if (pkt->hdr.flags & IWM_CMD_FAILED_MSK) {
3696 error = EIO; 3696 error = EIO;
3697 goto out_free_resp; 3697 goto out_free_resp;
3698 } 3698 }
3699 3699
3700 resp_len = iwm_rx_packet_payload_len(pkt); 3700 resp_len = iwm_rx_packet_payload_len(pkt);
3701 if (resp_len != sizeof(*resp)) { 3701 if (resp_len != sizeof(*resp)) {
3702 error = EIO; 3702 error = EIO;
3703 goto out_free_resp; 3703 goto out_free_resp;
3704 } 3704 }
3705 3705
3706 resp = (void *)pkt->data; 3706 resp = (void *)pkt->data;
3707 *status = le32toh(resp->status); 3707 *status = le32toh(resp->status);
3708 out_free_resp: 3708 out_free_resp:
3709 iwm_free_resp(sc, cmd); 3709 iwm_free_resp(sc, cmd);
3710 return error; 3710 return error;
3711} 3711}
3712 3712
3713/* iwlwifi/mvm/utils.c */ 3713/* iwlwifi/mvm/utils.c */
3714static int 3714static int
3715iwm_mvm_send_cmd_pdu_status(struct iwm_softc *sc, uint8_t id, 3715iwm_mvm_send_cmd_pdu_status(struct iwm_softc *sc, uint8_t id,
3716 uint16_t len, const void *data, uint32_t *status) 3716 uint16_t len, const void *data, uint32_t *status)
3717{ 3717{
3718 struct iwm_host_cmd cmd = { 3718 struct iwm_host_cmd cmd = {
3719 .id = id, 3719 .id = id,
3720 .len = { len, }, 3720 .len = { len, },
3721 .data = { data, }, 3721 .data = { data, },
3722 }; 3722 };
3723 3723
3724 return iwm_mvm_send_cmd_status(sc, &cmd, status); 3724 return iwm_mvm_send_cmd_status(sc, &cmd, status);
3725} 3725}
3726 3726
3727static void 3727static void
3728iwm_free_resp(struct iwm_softc *sc, struct iwm_host_cmd *hcmd) 3728iwm_free_resp(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
3729{ 3729{
3730 KASSERT(sc->sc_wantresp != -1); 3730 KASSERT(sc->sc_wantresp != -1);
3731 KASSERT((hcmd->flags & (IWM_CMD_WANT_SKB|IWM_CMD_SYNC)) 3731 KASSERT((hcmd->flags & (IWM_CMD_WANT_SKB|IWM_CMD_SYNC))
3732 == (IWM_CMD_WANT_SKB|IWM_CMD_SYNC)); 3732 == (IWM_CMD_WANT_SKB|IWM_CMD_SYNC));
3733 sc->sc_wantresp = -1; 3733 sc->sc_wantresp = -1;
3734 wakeup(&sc->sc_wantresp); 3734 wakeup(&sc->sc_wantresp);
3735} 3735}
3736 3736
3737/* 3737/*
3738 * Process a "command done" firmware notification. This is where we wakeup 3738 * Process a "command done" firmware notification. This is where we wakeup
3739 * processes waiting for a synchronous command completion. 3739 * processes waiting for a synchronous command completion.
3740 * from if_iwn 3740 * from if_iwn
3741 */ 3741 */
3742static void 3742static void
3743iwm_cmd_done(struct iwm_softc *sc, struct iwm_rx_packet *pkt) 3743iwm_cmd_done(struct iwm_softc *sc, struct iwm_rx_packet *pkt)
3744{ 3744{
3745 struct iwm_tx_ring *ring = &sc->txq[IWM_MVM_CMD_QUEUE]; 3745 struct iwm_tx_ring *ring = &sc->txq[IWM_MVM_CMD_QUEUE];
3746 struct iwm_tx_data *data; 3746 struct iwm_tx_data *data;
3747 3747
3748 if (pkt->hdr.qid != IWM_MVM_CMD_QUEUE) { 3748 if (pkt->hdr.qid != IWM_MVM_CMD_QUEUE) {
3749 return; /* Not a command ack. */ 3749 return; /* Not a command ack. */
3750 } 3750 }
3751 3751
3752 data = &ring->data[pkt->hdr.idx]; 3752 data = &ring->data[pkt->hdr.idx];
3753 3753
3754 /* If the command was mapped in an mbuf, free it. */ 3754 /* If the command was mapped in an mbuf, free it. */
3755 if (data->m != NULL) { 3755 if (data->m != NULL) {
3756 bus_dmamap_sync(sc->sc_dmat, data->map, 0, 3756 bus_dmamap_sync(sc->sc_dmat, data->map, 0,
3757 data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE); 3757 data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
3758 bus_dmamap_unload(sc->sc_dmat, data->map); 3758 bus_dmamap_unload(sc->sc_dmat, data->map);
3759 m_freem(data->m); 3759 m_freem(data->m);
3760 data->m = NULL; 3760 data->m = NULL;
3761 } 3761 }
3762 wakeup(&ring->desc[pkt->hdr.idx]); 3762 wakeup(&ring->desc[pkt->hdr.idx]);
3763} 3763}
3764 3764
3765#if 0 3765#if 0
3766/* 3766/*
3767 * necessary only for block ack mode 3767 * necessary only for block ack mode
3768 */ 3768 */
3769void 3769void
3770iwm_update_sched(struct iwm_softc *sc, int qid, int idx, uint8_t sta_id, 3770iwm_update_sched(struct iwm_softc *sc, int qid, int idx, uint8_t sta_id,
3771 uint16_t len) 3771 uint16_t len)
3772{ 3772{
3773 struct iwm_agn_scd_bc_tbl *scd_bc_tbl; 3773 struct iwm_agn_scd_bc_tbl *scd_bc_tbl;
3774 uint16_t w_val; 3774 uint16_t w_val;
3775 3775
3776 scd_bc_tbl = sc->sched_dma.vaddr; 3776 scd_bc_tbl = sc->sched_dma.vaddr;
3777 3777
3778 len += 8; /* magic numbers came naturally from paris */ 3778 len += 8; /* magic numbers came naturally from paris */
3779 if (sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_DW_BC_TABLE) 3779 if (sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_DW_BC_TABLE)
3780 len = roundup(len, 4) / 4; 3780 len = roundup(len, 4) / 4;
3781 3781
3782 w_val = htole16(sta_id << 12 | len); 3782 w_val = htole16(sta_id << 12 | len);
3783 3783
3784 /* Update TX scheduler. */ 3784 /* Update TX scheduler. */
3785 scd_bc_tbl[qid].tfd_offset[idx] = w_val; 3785 scd_bc_tbl[qid].tfd_offset[idx] = w_val;
3786 bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map, 3786 bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map,
3787 (char *)(void *)w - (char *)(void *)sc->sched_dma.vaddr, 3787 (char *)(void *)w - (char *)(void *)sc->sched_dma.vaddr,
3788 sizeof(uint16_t), BUS_DMASYNC_PREWRITE); 3788 sizeof(uint16_t), BUS_DMASYNC_PREWRITE);
3789 3789
3790 /* I really wonder what this is ?!? */ 3790 /* I really wonder what this is ?!? */
3791 if (idx < IWM_TFD_QUEUE_SIZE_BC_DUP) { 3791 if (idx < IWM_TFD_QUEUE_SIZE_BC_DUP) {
3792 scd_bc_tbl[qid].tfd_offset[IWM_TFD_QUEUE_SIZE_MAX + idx] = w_val; 3792 scd_bc_tbl[qid].tfd_offset[IWM_TFD_QUEUE_SIZE_MAX + idx] = w_val;
3793 bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map, 3793 bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map,
3794 (char *)(void *)(w + IWM_TFD_QUEUE_SIZE_MAX) - 3794 (char *)(void *)(w + IWM_TFD_QUEUE_SIZE_MAX) -
3795 (char *)(void *)sc->sched_dma.vaddr, 3795 (char *)(void *)sc->sched_dma.vaddr,
3796 sizeof (uint16_t), BUS_DMASYNC_PREWRITE); 3796 sizeof (uint16_t), BUS_DMASYNC_PREWRITE);
3797 } 3797 }
3798} 3798}
3799#endif 3799#endif
3800 3800
3801/* 3801/*
3802 * Fill in various bit for management frames, and leave them 3802 * Fill in various bit for management frames, and leave them
3803 * unfilled for data frames (firmware takes care of that). 3803 * unfilled for data frames (firmware takes care of that).
3804 * Return the selected TX rate. 3804 * Return the selected TX rate.
3805 */ 3805 */
3806static const struct iwm_rate * 3806static const struct iwm_rate *
3807iwm_tx_fill_cmd(struct iwm_softc *sc, struct iwm_node *in, 3807iwm_tx_fill_cmd(struct iwm_softc *sc, struct iwm_node *in,
3808 struct ieee80211_frame *wh, struct iwm_tx_cmd *tx) 3808 struct ieee80211_frame *wh, struct iwm_tx_cmd *tx)
3809{ 3809{
3810 const struct iwm_rate *rinfo; 3810 const struct iwm_rate *rinfo;
3811 int type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 3811 int type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
3812 int ridx, rate_flags; 3812 int ridx, rate_flags;
3813 int nrates = in->in_ni.ni_rates.rs_nrates; 3813 int nrates = in->in_ni.ni_rates.rs_nrates;
3814 3814
3815 tx->rts_retry_limit = IWM_RTS_DFAULT_RETRY_LIMIT; 3815 tx->rts_retry_limit = IWM_RTS_DFAULT_RETRY_LIMIT;
3816 tx->data_retry_limit = IWM_DEFAULT_TX_RETRY; 3816 tx->data_retry_limit = IWM_DEFAULT_TX_RETRY;
3817 3817
3818 /* for data frames, use RS table */ 3818 /* for data frames, use RS table */
3819 if (type == IEEE80211_FC0_TYPE_DATA) { 3819 if (type == IEEE80211_FC0_TYPE_DATA) {
3820 if (sc->sc_fixed_ridx != -1) { 3820 if (sc->sc_ic.ic_fixed_rate != -1) {
3821 tx->initial_rate_index = sc->sc_fixed_ridx; 3821 tx->initial_rate_index = sc->sc_fixed_ridx;
3822 } else { 3822 } else {
3823 tx->initial_rate_index = (nrates-1) - in->in_ni.ni_txrate; 3823 tx->initial_rate_index = (nrates-1) - in->in_ni.ni_txrate;
3824 } 3824 }
3825 tx->tx_flags |= htole32(IWM_TX_CMD_FLG_STA_RATE); 3825 tx->tx_flags |= htole32(IWM_TX_CMD_FLG_STA_RATE);
3826 DPRINTFN(12, ("start with txrate %d\n", tx->initial_rate_index)); 3826 DPRINTFN(12, ("start with txrate %d\n", tx->initial_rate_index));
3827 return &iwm_rates[tx->initial_rate_index]; 3827 return &iwm_rates[tx->initial_rate_index];
3828 } 3828 }
3829 3829
3830 /* for non-data, use the lowest supported rate */ 3830 /* for non-data, use the lowest supported rate */
3831 ridx = in->in_ridx[0]; 3831 ridx = in->in_ridx[0];
3832 rinfo = &iwm_rates[ridx]; 3832 rinfo = &iwm_rates[ridx];
3833 3833
3834 rate_flags = 1 << IWM_RATE_MCS_ANT_POS; 3834 rate_flags = 1 << IWM_RATE_MCS_ANT_POS;
3835 if (IWM_RIDX_IS_CCK(ridx)) 3835 if (IWM_RIDX_IS_CCK(ridx))
3836 rate_flags |= IWM_RATE_MCS_CCK_MSK; 3836 rate_flags |= IWM_RATE_MCS_CCK_MSK;
3837 tx->rate_n_flags = htole32(rate_flags | rinfo->plcp); 3837 tx->rate_n_flags = htole32(rate_flags | rinfo->plcp);
3838 3838
3839 return rinfo; 3839 return rinfo;
3840} 3840}
3841 3841
3842#define TB0_SIZE 16 3842#define TB0_SIZE 16
3843static int 3843static int
3844iwm_tx(struct iwm_softc *sc, struct mbuf *m, struct ieee80211_node *ni, int ac) 3844iwm_tx(struct iwm_softc *sc, struct mbuf *m, struct ieee80211_node *ni, int ac)
3845{ 3845{
3846 struct ieee80211com *ic = &sc->sc_ic; 3846 struct ieee80211com *ic = &sc->sc_ic;
3847 struct iwm_node *in = (void *)ni; 3847 struct iwm_node *in = (void *)ni;
3848 struct iwm_tx_ring *ring; 3848 struct iwm_tx_ring *ring;
3849 struct iwm_tx_data *data; 3849 struct iwm_tx_data *data;
3850 struct iwm_tfd *desc; 3850 struct iwm_tfd *desc;
3851 struct iwm_device_cmd *cmd; 3851 struct iwm_device_cmd *cmd;
3852 struct iwm_tx_cmd *tx; 3852 struct iwm_tx_cmd *tx;
3853 struct ieee80211_frame *wh; 3853 struct ieee80211_frame *wh;
3854 struct ieee80211_key *k = NULL; 3854 struct ieee80211_key *k = NULL;
3855 struct mbuf *m1; 3855 struct mbuf *m1;
3856 const struct iwm_rate *rinfo; 3856 const struct iwm_rate *rinfo;
3857 uint32_t flags; 3857 uint32_t flags;
3858 u_int hdrlen; 3858 u_int hdrlen;
3859 bus_dma_segment_t *seg; 3859 bus_dma_segment_t *seg;
3860 uint8_t tid, type; 3860 uint8_t tid, type;
3861 int i, totlen, error, pad; 3861 int i, totlen, error, pad;
3862 int hdrlen2; 3862 int hdrlen2;
3863 3863
3864 wh = mtod(m, struct ieee80211_frame *); 3864 wh = mtod(m, struct ieee80211_frame *);
3865 hdrlen = ieee80211_anyhdrsize(wh); 3865 hdrlen = ieee80211_anyhdrsize(wh);
3866 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 3866 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
3867 3867
3868 hdrlen2 = (ieee80211_has_qos(wh)) ? 3868 hdrlen2 = (ieee80211_has_qos(wh)) ?
3869 sizeof (struct ieee80211_qosframe) : 3869 sizeof (struct ieee80211_qosframe) :
3870 sizeof (struct ieee80211_frame); 3870 sizeof (struct ieee80211_frame);
3871 3871
3872 if (hdrlen != hdrlen2) 3872 if (hdrlen != hdrlen2)
3873 DPRINTF(("%s: hdrlen error (%d != %d)\n", 3873 DPRINTF(("%s: hdrlen error (%d != %d)\n",
3874 DEVNAME(sc), hdrlen, hdrlen2)); 3874 DEVNAME(sc), hdrlen, hdrlen2));
3875 3875
3876 tid = 0; 3876 tid = 0;
3877 3877
3878 ring = &sc->txq[ac]; 3878 ring = &sc->txq[ac];
3879 desc = &ring->desc[ring->cur]; 3879 desc = &ring->desc[ring->cur];
3880 memset(desc, 0, sizeof(*desc)); 3880 memset(desc, 0, sizeof(*desc));
3881 data = &ring->data[ring->cur]; 3881 data = &ring->data[ring->cur];
3882 3882
3883 /* Fill out iwm_tx_cmd to send to the firmware */ 3883 /* Fill out iwm_tx_cmd to send to the firmware */
3884 cmd = &ring->cmd[ring->cur]; 3884 cmd = &ring->cmd[ring->cur];
3885 cmd->hdr.code = IWM_TX_CMD; 3885 cmd->hdr.code = IWM_TX_CMD;
3886 cmd->hdr.flags = 0; 3886 cmd->hdr.flags = 0;
3887 cmd->hdr.qid = ring->qid; 3887 cmd->hdr.qid = ring->qid;
3888 cmd->hdr.idx = ring->cur; 3888 cmd->hdr.idx = ring->cur;
3889 3889
3890 tx = (void *)cmd->data; 3890 tx = (void *)cmd->data;
3891 memset(tx, 0, sizeof(*tx)); 3891 memset(tx, 0, sizeof(*tx));
3892 3892
3893 rinfo = iwm_tx_fill_cmd(sc, in, wh, tx); 3893 rinfo = iwm_tx_fill_cmd(sc, in, wh, tx);
3894 3894
3895 if (sc->sc_drvbpf != NULL) { 3895 if (sc->sc_drvbpf != NULL) {
3896 struct iwm_tx_radiotap_header *tap = &sc->sc_txtap; 3896 struct iwm_tx_radiotap_header *tap = &sc->sc_txtap;
3897 3897
3898 tap->wt_flags = 0; 3898 tap->wt_flags = 0;
3899 tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq); 3899 tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq);
3900 tap->wt_chan_flags = htole16(ni->ni_chan->ic_flags); 3900 tap->wt_chan_flags = htole16(ni->ni_chan->ic_flags);
3901 tap->wt_rate = rinfo->rate; 3901 tap->wt_rate = rinfo->rate;
3902 tap->wt_hwqueue = ac; 3902 tap->wt_hwqueue = ac;
3903 if (wh->i_fc[1] & IEEE80211_FC1_WEP) 3903 if (wh->i_fc[1] & IEEE80211_FC1_WEP)
3904 tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP; 3904 tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
3905 3905
3906 bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m); 3906 bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m);
3907 } 3907 }
3908 3908
3909 /* Encrypt the frame if need be. */ 3909 /* Encrypt the frame if need be. */
3910 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 3910 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
3911 k = ieee80211_crypto_encap(ic, ni, m); 3911 k = ieee80211_crypto_encap(ic, ni, m);
3912 if (k == NULL) { 3912 if (k == NULL) {
3913 m_freem(m); 3913 m_freem(m);
3914 return ENOBUFS; 3914 return ENOBUFS;
3915 } 3915 }
3916 /* Packet header may have moved, reset our local pointer. */ 3916 /* Packet header may have moved, reset our local pointer. */
3917 wh = mtod(m, struct ieee80211_frame *); 3917 wh = mtod(m, struct ieee80211_frame *);
3918 } 3918 }
3919 totlen = m->m_pkthdr.len; 3919 totlen = m->m_pkthdr.len;
3920 3920
3921 flags = 0; 3921 flags = 0;
3922 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 3922 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
3923 flags |= IWM_TX_CMD_FLG_ACK; 3923 flags |= IWM_TX_CMD_FLG_ACK;
3924 } 3924 }
3925 3925
3926 if (type != IEEE80211_FC0_TYPE_DATA 3926 if (type != IEEE80211_FC0_TYPE_DATA
3927 && (totlen + IEEE80211_CRC_LEN > ic->ic_rtsthreshold) 3927 && (totlen + IEEE80211_CRC_LEN > ic->ic_rtsthreshold)
3928 && !IEEE80211_IS_MULTICAST(wh->i_addr1)) { 3928 && !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
3929 flags |= IWM_TX_CMD_FLG_PROT_REQUIRE; 3929 flags |= IWM_TX_CMD_FLG_PROT_REQUIRE;
3930 } 3930 }
3931 3931
3932 if (IEEE80211_IS_MULTICAST(wh->i_addr1) || 3932 if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
3933 type != IEEE80211_FC0_TYPE_DATA) 3933 type != IEEE80211_FC0_TYPE_DATA)
3934 tx->sta_id = sc->sc_aux_sta.sta_id; 3934 tx->sta_id = sc->sc_aux_sta.sta_id;
3935 else 3935 else
3936 tx->sta_id = IWM_STATION_ID; 3936 tx->sta_id = IWM_STATION_ID;
3937 3937
3938 if (type == IEEE80211_FC0_TYPE_MGT) { 3938 if (type == IEEE80211_FC0_TYPE_MGT) {
3939 uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 3939 uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
3940 3940
3941 if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ || 3941 if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ ||
3942 subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) 3942 subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ)
3943 tx->pm_frame_timeout = htole16(3); 3943 tx->pm_frame_timeout = htole16(3);
3944 else 3944 else
3945 tx->pm_frame_timeout = htole16(2); 3945 tx->pm_frame_timeout = htole16(2);
3946 } else { 3946 } else {
3947 tx->pm_frame_timeout = htole16(0); 3947 tx->pm_frame_timeout = htole16(0);
3948 } 3948 }
3949 3949
3950 if (hdrlen & 3) { 3950 if (hdrlen & 3) {
3951 /* First segment length must be a multiple of 4. */ 3951 /* First segment length must be a multiple of 4. */
3952 flags |= IWM_TX_CMD_FLG_MH_PAD; 3952 flags |= IWM_TX_CMD_FLG_MH_PAD;
3953 pad = 4 - (hdrlen & 3); 3953 pad = 4 - (hdrlen & 3);
3954 } else 3954 } else
3955 pad = 0; 3955 pad = 0;
3956 3956
3957 tx->driver_txop = 0; 3957 tx->driver_txop = 0;
3958 tx->next_frame_len = 0; 3958 tx->next_frame_len = 0;
3959 3959
3960 tx->len = htole16(totlen); 3960 tx->len = htole16(totlen);
3961 tx->tid_tspec = tid; 3961 tx->tid_tspec = tid;
3962 tx->life_time = htole32(IWM_TX_CMD_LIFE_TIME_INFINITE); 3962 tx->life_time = htole32(IWM_TX_CMD_LIFE_TIME_INFINITE);
3963 3963
3964 /* Set physical address of "scratch area". */ 3964 /* Set physical address of "scratch area". */
3965 tx->dram_lsb_ptr = htole32(data->scratch_paddr); 3965 tx->dram_lsb_ptr = htole32(data->scratch_paddr);
3966 tx->dram_msb_ptr = iwm_get_dma_hi_addr(data->scratch_paddr); 3966 tx->dram_msb_ptr = iwm_get_dma_hi_addr(data->scratch_paddr);
3967 3967
3968 /* Copy 802.11 header in TX command. */ 3968 /* Copy 802.11 header in TX command. */
3969 memcpy(((uint8_t *)tx) + sizeof(*tx), wh, hdrlen); 3969 memcpy(((uint8_t *)tx) + sizeof(*tx), wh, hdrlen);
3970 3970
3971 flags |= IWM_TX_CMD_FLG_BT_DIS | IWM_TX_CMD_FLG_SEQ_CTL; 3971 flags |= IWM_TX_CMD_FLG_BT_DIS | IWM_TX_CMD_FLG_SEQ_CTL;
3972 3972
3973 tx->sec_ctl = 0; 3973 tx->sec_ctl = 0;
3974 tx->tx_flags |= htole32(flags); 3974 tx->tx_flags |= htole32(flags);
3975 3975
3976 /* Trim 802.11 header. */ 3976 /* Trim 802.11 header. */
3977 m_adj(m, hdrlen); 3977 m_adj(m, hdrlen);
3978 3978
3979 error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m, 3979 error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m,
3980 BUS_DMA_NOWAIT | BUS_DMA_WRITE); 3980 BUS_DMA_NOWAIT | BUS_DMA_WRITE);
3981 if (error != 0) { 3981 if (error != 0) {
3982 if (error != EFBIG) { 3982 if (error != EFBIG) {
3983 aprint_error_dev(sc->sc_dev, 3983 aprint_error_dev(sc->sc_dev,
3984 "can't map mbuf (error %d)\n", error); 3984 "can't map mbuf (error %d)\n", error);
3985 m_freem(m); 3985 m_freem(m);
3986 return error; 3986 return error;
3987 } 3987 }
3988 /* Too many DMA segments, linearize mbuf. */ 3988 /* Too many DMA segments, linearize mbuf. */
3989 MGETHDR(m1, M_DONTWAIT, MT_DATA); 3989 MGETHDR(m1, M_DONTWAIT, MT_DATA);
3990 if (m1 == NULL) { 3990 if (m1 == NULL) {
3991 m_freem(m); 3991 m_freem(m);
3992 return ENOBUFS; 3992 return ENOBUFS;
3993 } 3993 }
3994 if (m->m_pkthdr.len > MHLEN) { 3994 if (m->m_pkthdr.len > MHLEN) {
3995 MCLGET(m1, M_DONTWAIT); 3995 MCLGET(m1, M_DONTWAIT);
3996 if (!(m1->m_flags & M_EXT)) { 3996 if (!(m1->m_flags & M_EXT)) {
3997 m_freem(m); 3997 m_freem(m);
3998 m_freem(m1); 3998 m_freem(m1);
3999 return ENOBUFS; 3999 return ENOBUFS;
4000 } 4000 }
4001 } 4001 }
4002 m_copydata(m, 0, m->m_pkthdr.len, mtod(m1, void *)); 4002 m_copydata(m, 0, m->m_pkthdr.len, mtod(m1, void *));
4003 m1->m_pkthdr.len = m1->m_len = m->m_pkthdr.len; 4003 m1->m_pkthdr.len = m1->m_len = m->m_pkthdr.len;
4004 m_freem(m); 4004 m_freem(m);
4005 m = m1; 4005 m = m1;
4006 4006
4007 error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m, 4007 error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m,
4008 BUS_DMA_NOWAIT | BUS_DMA_WRITE); 4008 BUS_DMA_NOWAIT | BUS_DMA_WRITE);
4009 if (error != 0) { 4009 if (error != 0) {
4010 aprint_error_dev(sc->sc_dev, 4010 aprint_error_dev(sc->sc_dev,
4011 "can't map mbuf (error %d)\n", error); 4011 "can't map mbuf (error %d)\n", error);
4012 m_freem(m); 4012 m_freem(m);
4013 return error; 4013 return error;
4014 } 4014 }
4015 } 4015 }
4016 data->m = m; 4016 data->m = m;
4017 data->in = in; 4017 data->in = in;
4018 data->done = 0; 4018 data->done = 0;
4019 4019
4020 DPRINTFN(8, ("sending txd %p, in %p\n", data, data->in)); 4020 DPRINTFN(8, ("sending txd %p, in %p\n", data, data->in));
4021 KASSERT(data->in != NULL); 4021 KASSERT(data->in != NULL);
4022 4022
4023 DPRINTFN(8, ("sending data: qid=%d idx=%d len=%d nsegs=%d\n", 4023 DPRINTFN(8, ("sending data: qid=%d idx=%d len=%d nsegs=%d\n",
4024 ring->qid, ring->cur, totlen, data->map->dm_nsegs)); 4024 ring->qid, ring->cur, totlen, data->map->dm_nsegs));
4025 4025
4026 /* Fill TX descriptor. */ 4026 /* Fill TX descriptor. */
4027 desc->num_tbs = 2 + data->map->dm_nsegs; 4027 desc->num_tbs = 2 + data->map->dm_nsegs;
4028 4028
4029 desc->tbs[0].lo = htole32(data->cmd_paddr); 4029 desc->tbs[0].lo = htole32(data->cmd_paddr);
4030 desc->tbs[0].hi_n_len = htole16(iwm_get_dma_hi_addr(data->cmd_paddr)) | 4030 desc->tbs[0].hi_n_len = htole16(iwm_get_dma_hi_addr(data->cmd_paddr)) |
4031 (TB0_SIZE << 4); 4031 (TB0_SIZE << 4);
4032 desc->tbs[1].lo = htole32(data->cmd_paddr + TB0_SIZE); 4032 desc->tbs[1].lo = htole32(data->cmd_paddr + TB0_SIZE);
4033 desc->tbs[1].hi_n_len = htole16(iwm_get_dma_hi_addr(data->cmd_paddr)) | 4033 desc->tbs[1].hi_n_len = htole16(iwm_get_dma_hi_addr(data->cmd_paddr)) |
4034 ((sizeof(struct iwm_cmd_header) + sizeof(*tx) 4034 ((sizeof(struct iwm_cmd_header) + sizeof(*tx)
4035 + hdrlen + pad - TB0_SIZE) << 4); 4035 + hdrlen + pad - TB0_SIZE) << 4);
4036 4036
4037 /* Other DMA segments are for data payload. */ 4037 /* Other DMA segments are for data payload. */
4038 seg = data->map->dm_segs; 4038 seg = data->map->dm_segs;
4039 for (i = 0; i < data->map->dm_nsegs; i++, seg++) { 4039 for (i = 0; i < data->map->dm_nsegs; i++, seg++) {
4040 desc->tbs[i+2].lo = htole32(seg->ds_addr); 4040 desc->tbs[i+2].lo = htole32(seg->ds_addr);
4041 desc->tbs[i+2].hi_n_len = \ 4041 desc->tbs[i+2].hi_n_len = \
4042 htole16(iwm_get_dma_hi_addr(seg->ds_addr)) 4042 htole16(iwm_get_dma_hi_addr(seg->ds_addr))
4043 | ((seg->ds_len) << 4); 4043 | ((seg->ds_len) << 4);
4044 } 4044 }
4045 4045
4046 bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize, 4046 bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
4047 BUS_DMASYNC_PREWRITE); 4047 BUS_DMASYNC_PREWRITE);
4048 bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map, 4048 bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map,
4049 (char *)(void *)cmd - (char *)(void *)ring->cmd_dma.vaddr, 4049 (char *)(void *)cmd - (char *)(void *)ring->cmd_dma.vaddr,
4050 sizeof (*cmd), BUS_DMASYNC_PREWRITE); 4050 sizeof (*cmd), BUS_DMASYNC_PREWRITE);
4051 bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 4051 bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,
4052 (char *)(void *)desc - (char *)(void *)ring->desc_dma.vaddr, 4052 (char *)(void *)desc - (char *)(void *)ring->desc_dma.vaddr,
4053 sizeof (*desc), BUS_DMASYNC_PREWRITE); 4053 sizeof (*desc), BUS_DMASYNC_PREWRITE);
4054 4054
4055#if 0 4055#if 0
4056 iwm_update_sched(sc, ring->qid, ring->cur, tx->sta_id, le16toh(tx->len)); 4056 iwm_update_sched(sc, ring->qid, ring->cur, tx->sta_id, le16toh(tx->len));
4057#endif 4057#endif
4058 4058
4059 /* Kick TX ring. */ 4059 /* Kick TX ring. */
4060 ring->cur = (ring->cur + 1) % IWM_TX_RING_COUNT; 4060 ring->cur = (ring->cur + 1) % IWM_TX_RING_COUNT;
4061 IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); 4061 IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
4062 4062
4063 /* Mark TX ring as full if we reach a certain threshold. */ 4063 /* Mark TX ring as full if we reach a certain threshold. */
4064 if (++ring->queued > IWM_TX_RING_HIMARK) { 4064 if (++ring->queued > IWM_TX_RING_HIMARK) {
4065 sc->qfullmsk |= 1 << ring->qid; 4065 sc->qfullmsk |= 1 << ring->qid;
4066 } 4066 }
4067 4067
4068 return 0; 4068 return 0;
4069} 4069}
4070 4070
4071#if 0 4071#if 0
4072/* not necessary? */ 4072/* not necessary? */
4073static int 4073static int
4074iwm_mvm_flush_tx_path(struct iwm_softc *sc, int tfd_msk, int sync) 4074iwm_mvm_flush_tx_path(struct iwm_softc *sc, int tfd_msk, int sync)
4075{ 4075{
4076 struct iwm_tx_path_flush_cmd flush_cmd = { 4076 struct iwm_tx_path_flush_cmd flush_cmd = {
4077 .queues_ctl = htole32(tfd_msk), 4077 .queues_ctl = htole32(tfd_msk),
4078 .flush_ctl = htole16(IWM_DUMP_TX_FIFO_FLUSH), 4078 .flush_ctl = htole16(IWM_DUMP_TX_FIFO_FLUSH),
4079 }; 4079 };
4080 int ret; 4080 int ret;
4081 4081
4082 ret = iwm_mvm_send_cmd_pdu(sc, IWM_TXPATH_FLUSH, 4082 ret = iwm_mvm_send_cmd_pdu(sc, IWM_TXPATH_FLUSH,
4083 sync ? IWM_CMD_SYNC : IWM_CMD_ASYNC, 4083 sync ? IWM_CMD_SYNC : IWM_CMD_ASYNC,
4084 sizeof(flush_cmd), &flush_cmd); 4084 sizeof(flush_cmd), &flush_cmd);
4085 if (ret) 4085 if (ret)
4086 aprint_error_dev(sc->sc_dev, "Flushing tx queue failed: %d\n", 4086 aprint_error_dev(sc->sc_dev, "Flushing tx queue failed: %d\n",
4087 ret); 4087 ret);
4088 return ret; 4088 return ret;
4089} 4089}
4090#endif 4090#endif
4091 4091
4092 4092
4093/* 4093/*
4094 * BEGIN mvm/power.c 4094 * BEGIN mvm/power.c
4095 */ 4095 */
4096 4096
4097#define IWM_POWER_KEEP_ALIVE_PERIOD_SEC 25 4097#define IWM_POWER_KEEP_ALIVE_PERIOD_SEC 25
4098 4098
4099static int 4099static int
4100iwm_mvm_beacon_filter_send_cmd(struct iwm_softc *sc, 4100iwm_mvm_beacon_filter_send_cmd(struct iwm_softc *sc,
4101 struct iwm_beacon_filter_cmd *cmd) 4101 struct iwm_beacon_filter_cmd *cmd)
4102{ 4102{
4103 int ret; 4103 int ret;
4104 4104
4105 ret = iwm_mvm_send_cmd_pdu(sc, IWM_REPLY_BEACON_FILTERING_CMD, 4105 ret = iwm_mvm_send_cmd_pdu(sc, IWM_REPLY_BEACON_FILTERING_CMD,
4106 IWM_CMD_SYNC, sizeof(struct iwm_beacon_filter_cmd), cmd); 4106 IWM_CMD_SYNC, sizeof(struct iwm_beacon_filter_cmd), cmd);
4107 4107
4108 if (!ret) { 4108 if (!ret) {
4109 DPRINTF(("ba_enable_beacon_abort is: %d\n", 4109 DPRINTF(("ba_enable_beacon_abort is: %d\n",
4110 le32toh(cmd->ba_enable_beacon_abort))); 4110 le32toh(cmd->ba_enable_beacon_abort)));
4111 DPRINTF(("ba_escape_timer is: %d\n", 4111 DPRINTF(("ba_escape_timer is: %d\n",
4112 le32toh(cmd->ba_escape_timer))); 4112 le32toh(cmd->ba_escape_timer)));
4113 DPRINTF(("bf_debug_flag is: %d\n", 4113 DPRINTF(("bf_debug_flag is: %d\n",
4114 le32toh(cmd->bf_debug_flag))); 4114 le32toh(cmd->bf_debug_flag)));
4115 DPRINTF(("bf_enable_beacon_filter is: %d\n", 4115 DPRINTF(("bf_enable_beacon_filter is: %d\n",
4116 le32toh(cmd->bf_enable_beacon_filter))); 4116 le32toh(cmd->bf_enable_beacon_filter)));
4117 DPRINTF(("bf_energy_delta is: %d\n", 4117 DPRINTF(("bf_energy_delta is: %d\n",
4118 le32toh(cmd->bf_energy_delta))); 4118 le32toh(cmd->bf_energy_delta)));
4119 DPRINTF(("bf_escape_timer is: %d\n", 4119 DPRINTF(("bf_escape_timer is: %d\n",
4120 le32toh(cmd->bf_escape_timer))); 4120 le32toh(cmd->bf_escape_timer)));
4121 DPRINTF(("bf_roaming_energy_delta is: %d\n", 4121 DPRINTF(("bf_roaming_energy_delta is: %d\n",
4122 le32toh(cmd->bf_roaming_energy_delta))); 4122 le32toh(cmd->bf_roaming_energy_delta)));
4123 DPRINTF(("bf_roaming_state is: %d\n", 4123 DPRINTF(("bf_roaming_state is: %d\n",
4124 le32toh(cmd->bf_roaming_state))); 4124 le32toh(cmd->bf_roaming_state)));
4125 DPRINTF(("bf_temp_threshold is: %d\n", 4125 DPRINTF(("bf_temp_threshold is: %d\n",
4126 le32toh(cmd->bf_temp_threshold))); 4126 le32toh(cmd->bf_temp_threshold)));
4127 DPRINTF(("bf_temp_fast_filter is: %d\n", 4127 DPRINTF(("bf_temp_fast_filter is: %d\n",
4128 le32toh(cmd->bf_temp_fast_filter))); 4128 le32toh(cmd->bf_temp_fast_filter)));
4129 DPRINTF(("bf_temp_slow_filter is: %d\n", 4129 DPRINTF(("bf_temp_slow_filter is: %d\n",
4130 le32toh(cmd->bf_temp_slow_filter))); 4130 le32toh(cmd->bf_temp_slow_filter)));
4131 } 4131 }
4132 return ret; 4132 return ret;
4133} 4133}
4134 4134
4135static void 4135static void
4136iwm_mvm_beacon_filter_set_cqm_params(struct iwm_softc *sc, 4136iwm_mvm_beacon_filter_set_cqm_params(struct iwm_softc *sc,
4137 struct iwm_node *in, struct iwm_beacon_filter_cmd *cmd) 4137 struct iwm_node *in, struct iwm_beacon_filter_cmd *cmd)
4138{ 4138{
4139 cmd->ba_enable_beacon_abort = htole32(sc->sc_bf.ba_enabled); 4139 cmd->ba_enable_beacon_abort = htole32(sc->sc_bf.ba_enabled);
4140} 4140}
4141 4141
4142static int 4142static int
4143iwm_mvm_update_beacon_abort(struct iwm_softc *sc, struct iwm_node *in, 4143iwm_mvm_update_beacon_abort(struct iwm_softc *sc, struct iwm_node *in,
4144 int enable) 4144 int enable)
4145{ 4145{
4146 struct iwm_beacon_filter_cmd cmd = { 4146 struct iwm_beacon_filter_cmd cmd = {
4147 IWM_BF_CMD_CONFIG_DEFAULTS, 4147 IWM_BF_CMD_CONFIG_DEFAULTS,
4148 .bf_enable_beacon_filter = htole32(1), 4148 .bf_enable_beacon_filter = htole32(1),
4149 .ba_enable_beacon_abort = htole32(enable), 4149 .ba_enable_beacon_abort = htole32(enable),
4150 }; 4150 };
4151 4151
4152 if (!sc->sc_bf.bf_enabled) 4152 if (!sc->sc_bf.bf_enabled)
4153 return 0; 4153 return 0;
4154 4154
4155 sc->sc_bf.ba_enabled = enable; 4155 sc->sc_bf.ba_enabled = enable;
4156 iwm_mvm_beacon_filter_set_cqm_params(sc, in, &cmd); 4156 iwm_mvm_beacon_filter_set_cqm_params(sc, in, &cmd);
4157 return iwm_mvm_beacon_filter_send_cmd(sc, &cmd); 4157 return iwm_mvm_beacon_filter_send_cmd(sc, &cmd);
4158} 4158}
4159 4159
4160static void 4160static void
4161iwm_mvm_power_log(struct iwm_softc *sc, struct iwm_mac_power_cmd *cmd) 4161iwm_mvm_power_log(struct iwm_softc *sc, struct iwm_mac_power_cmd *cmd)
4162{ 4162{
4163 DPRINTF(("Sending power table command on mac id 0x%X for " 4163 DPRINTF(("Sending power table command on mac id 0x%X for "
4164 "power level %d, flags = 0x%X\n", 4164 "power level %d, flags = 0x%X\n",
4165 cmd->id_and_color, IWM_POWER_SCHEME_CAM, le16toh(cmd->flags))); 4165 cmd->id_and_color, IWM_POWER_SCHEME_CAM, le16toh(cmd->flags)));
4166 DPRINTF(("Keep alive = %u sec\n", le16toh(cmd->keep_alive_seconds))); 4166 DPRINTF(("Keep alive = %u sec\n", le16toh(cmd->keep_alive_seconds)));
4167 4167
4168 if (!(cmd->flags & htole16(IWM_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK))) { 4168 if (!(cmd->flags & htole16(IWM_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK))) {
4169 DPRINTF(("Disable power management\n")); 4169 DPRINTF(("Disable power management\n"));
4170 return; 4170 return;
4171 } 4171 }
4172 KASSERT(0); 4172 KASSERT(0);
4173 4173
4174#if 0 4174#if 0
4175 DPRINTF(mvm, "Rx timeout = %u usec\n", 4175 DPRINTF(mvm, "Rx timeout = %u usec\n",
4176 le32_to_cpu(cmd->rx_data_timeout)); 4176 le32_to_cpu(cmd->rx_data_timeout));
4177 DPRINTF(mvm, "Tx timeout = %u usec\n", 4177 DPRINTF(mvm, "Tx timeout = %u usec\n",
4178 le32_to_cpu(cmd->tx_data_timeout)); 4178 le32_to_cpu(cmd->tx_data_timeout));
4179 if (cmd->flags & cpu_to_le16(IWM_POWER_FLAGS_SKIP_OVER_DTIM_MSK)) 4179 if (cmd->flags & cpu_to_le16(IWM_POWER_FLAGS_SKIP_OVER_DTIM_MSK))
4180 DPRINTF(mvm, "DTIM periods to skip = %u\n", 4180 DPRINTF(mvm, "DTIM periods to skip = %u\n",
4181 cmd->skip_dtim_periods); 4181 cmd->skip_dtim_periods);
4182 if (cmd->flags & cpu_to_le16(IWM_POWER_FLAGS_LPRX_ENA_MSK)) 4182 if (cmd->flags & cpu_to_le16(IWM_POWER_FLAGS_LPRX_ENA_MSK))
4183 DPRINTF(mvm, "LP RX RSSI threshold = %u\n", 4183 DPRINTF(mvm, "LP RX RSSI threshold = %u\n",
4184 cmd->lprx_rssi_threshold); 4184 cmd->lprx_rssi_threshold);
4185 if (cmd->flags & cpu_to_le16(IWM_POWER_FLAGS_ADVANCE_PM_ENA_MSK)) { 4185 if (cmd->flags & cpu_to_le16(IWM_POWER_FLAGS_ADVANCE_PM_ENA_MSK)) {
4186 DPRINTF(mvm, "uAPSD enabled\n"); 4186 DPRINTF(mvm, "uAPSD enabled\n");
4187 DPRINTF(mvm, "Rx timeout (uAPSD) = %u usec\n", 4187 DPRINTF(mvm, "Rx timeout (uAPSD) = %u usec\n",
4188 le32_to_cpu(cmd->rx_data_timeout_uapsd)); 4188 le32_to_cpu(cmd->rx_data_timeout_uapsd));
4189 DPRINTF(mvm, "Tx timeout (uAPSD) = %u usec\n", 4189 DPRINTF(mvm, "Tx timeout (uAPSD) = %u usec\n",
4190 le32_to_cpu(cmd->tx_data_timeout_uapsd)); 4190 le32_to_cpu(cmd->tx_data_timeout_uapsd));
4191 DPRINTF(mvm, "QNDP TID = %d\n", cmd->qndp_tid); 4191 DPRINTF(mvm, "QNDP TID = %d\n", cmd->qndp_tid);
4192 DPRINTF(mvm, "ACs flags = 0x%x\n", cmd->uapsd_ac_flags); 4192 DPRINTF(mvm, "ACs flags = 0x%x\n", cmd->uapsd_ac_flags);
4193 DPRINTF(mvm, "Max SP = %d\n", cmd->uapsd_max_sp); 4193 DPRINTF(mvm, "Max SP = %d\n", cmd->uapsd_max_sp);
4194 } 4194 }
4195#endif 4195#endif
4196} 4196}
4197 4197
4198static void 4198static void
4199iwm_mvm_power_build_cmd(struct iwm_softc *sc, struct iwm_node *in, 4199iwm_mvm_power_build_cmd(struct iwm_softc *sc, struct iwm_node *in,
4200 struct iwm_mac_power_cmd *cmd) 4200 struct iwm_mac_power_cmd *cmd)
4201{ 4201{
4202 struct ieee80211com *ic = &sc->sc_ic; 4202 struct ieee80211com *ic = &sc->sc_ic;
4203 struct ieee80211_node *ni = &in->in_ni; 4203 struct ieee80211_node *ni = &in->in_ni;
4204 int dtimper, dtimper_msec; 4204 int dtimper, dtimper_msec;
4205 int keep_alive; 4205 int keep_alive;
4206 4206
4207 cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, 4207 cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id,
4208 in->in_color)); 4208 in->in_color));
4209 dtimper = ic->ic_dtim_period ?: 1; 4209 dtimper = ic->ic_dtim_period ?: 1;
4210 4210
4211 /* 4211 /*
4212 * Regardless of power management state the driver must set 4212 * Regardless of power management state the driver must set
4213 * keep alive period. FW will use it for sending keep alive NDPs 4213 * keep alive period. FW will use it for sending keep alive NDPs
4214 * immediately after association. Check that keep alive period 4214 * immediately after association. Check that keep alive period
4215 * is at least 3 * DTIM 4215 * is at least 3 * DTIM
4216 */ 4216 */
4217 dtimper_msec = dtimper * ni->ni_intval; 4217 dtimper_msec = dtimper * ni->ni_intval;
4218 keep_alive 4218 keep_alive
4219 = MAX(3 * dtimper_msec, 1000 * IWM_POWER_KEEP_ALIVE_PERIOD_SEC); 4219 = MAX(3 * dtimper_msec, 1000 * IWM_POWER_KEEP_ALIVE_PERIOD_SEC);
4220 keep_alive = roundup(keep_alive, 1000) / 1000; 4220 keep_alive = roundup(keep_alive, 1000) / 1000;
4221 cmd->keep_alive_seconds = htole16(keep_alive); 4221 cmd->keep_alive_seconds = htole16(keep_alive);
4222} 4222}
4223 4223
4224static int 4224static int
4225iwm_mvm_power_mac_update_mode(struct iwm_softc *sc, struct iwm_node *in) 4225iwm_mvm_power_mac_update_mode(struct iwm_softc *sc, struct iwm_node *in)
4226{ 4226{
4227 int ret; 4227 int ret;
4228 int ba_enable; 4228 int ba_enable;
4229 struct iwm_mac_power_cmd cmd; 4229 struct iwm_mac_power_cmd cmd;
4230 4230
4231 memset(&cmd, 0, sizeof(cmd)); 4231 memset(&cmd, 0, sizeof(cmd));
4232 4232
4233 iwm_mvm_power_build_cmd(sc, in, &cmd); 4233 iwm_mvm_power_build_cmd(sc, in, &cmd);
4234 iwm_mvm_power_log(sc, &cmd); 4234 iwm_mvm_power_log(sc, &cmd);
4235 4235
4236 if ((ret = iwm_mvm_send_cmd_pdu(sc, IWM_MAC_PM_POWER_TABLE, 4236 if ((ret = iwm_mvm_send_cmd_pdu(sc, IWM_MAC_PM_POWER_TABLE,
4237 IWM_CMD_SYNC, sizeof(cmd), &cmd)) != 0) 4237 IWM_CMD_SYNC, sizeof(cmd), &cmd)) != 0)
4238 return ret; 4238 return ret;
4239 4239
4240 ba_enable = !!(cmd.flags & 4240 ba_enable = !!(cmd.flags &
4241 htole16(IWM_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)); 4241 htole16(IWM_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK));
4242 return iwm_mvm_update_beacon_abort(sc, in, ba_enable); 4242 return iwm_mvm_update_beacon_abort(sc, in, ba_enable);
4243} 4243}
4244 4244
4245static int 4245static int
4246iwm_mvm_power_update_device(struct iwm_softc *sc) 4246iwm_mvm_power_update_device(struct iwm_softc *sc)
4247{ 4247{
4248 struct iwm_device_power_cmd cmd = { 4248 struct iwm_device_power_cmd cmd = {
4249 .flags = htole16(IWM_DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK), 4249 .flags = htole16(IWM_DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK),
4250 }; 4250 };
4251 4251
4252 if (!(sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) 4252 if (!(sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_DEVICE_PS_CMD))
4253 return 0; 4253 return 0;
4254 4254
4255 cmd.flags |= htole16(IWM_DEVICE_POWER_FLAGS_CAM_MSK); 4255 cmd.flags |= htole16(IWM_DEVICE_POWER_FLAGS_CAM_MSK);
4256 DPRINTF(("Sending device power command with flags = 0x%X\n", cmd.flags)); 4256 DPRINTF(("Sending device power command with flags = 0x%X\n", cmd.flags));
4257 4257
4258 return iwm_mvm_send_cmd_pdu(sc, 4258 return iwm_mvm_send_cmd_pdu(sc,
4259 IWM_POWER_TABLE_CMD, IWM_CMD_SYNC, sizeof(cmd), &cmd); 4259 IWM_POWER_TABLE_CMD, IWM_CMD_SYNC, sizeof(cmd), &cmd);
4260} 4260}
4261 4261
4262static int 4262static int
4263iwm_mvm_enable_beacon_filter(struct iwm_softc *sc, struct iwm_node *in) 4263iwm_mvm_enable_beacon_filter(struct iwm_softc *sc, struct iwm_node *in)
4264{ 4264{
4265 struct iwm_beacon_filter_cmd cmd = { 4265 struct iwm_beacon_filter_cmd cmd = {
4266 IWM_BF_CMD_CONFIG_DEFAULTS, 4266 IWM_BF_CMD_CONFIG_DEFAULTS,
4267 .bf_enable_beacon_filter = htole32(1), 4267 .bf_enable_beacon_filter = htole32(1),
4268 }; 4268 };
4269 int ret; 4269 int ret;
4270 4270
4271 iwm_mvm_beacon_filter_set_cqm_params(sc, in, &cmd); 4271 iwm_mvm_beacon_filter_set_cqm_params(sc, in, &cmd);
4272 ret = iwm_mvm_beacon_filter_send_cmd(sc, &cmd); 4272 ret = iwm_mvm_beacon_filter_send_cmd(sc, &cmd);
4273 4273
4274 if (ret == 0) 4274 if (ret == 0)
4275 sc->sc_bf.bf_enabled = 1; 4275 sc->sc_bf.bf_enabled = 1;
4276 4276
4277 return ret; 4277 return ret;
4278} 4278}
4279 4279
4280static int 4280static int
4281iwm_mvm_disable_beacon_filter(struct iwm_softc *sc, struct iwm_node *in) 4281iwm_mvm_disable_beacon_filter(struct iwm_softc *sc, struct iwm_node *in)
4282{ 4282{
4283 struct iwm_beacon_filter_cmd cmd; 4283 struct iwm_beacon_filter_cmd cmd;
4284 int ret; 4284 int ret;
4285 4285
4286 memset(&cmd, 0, sizeof(cmd)); 4286 memset(&cmd, 0, sizeof(cmd));
4287 if ((sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_BF_UPDATED) == 0) 4287 if ((sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_BF_UPDATED) == 0)
4288 return 0; 4288 return 0;
4289 4289
4290 ret = iwm_mvm_beacon_filter_send_cmd(sc, &cmd); 4290 ret = iwm_mvm_beacon_filter_send_cmd(sc, &cmd);
4291 if (ret == 0) 4291 if (ret == 0)
4292 sc->sc_bf.bf_enabled = 0; 4292 sc->sc_bf.bf_enabled = 0;
4293 4293
4294 return ret; 4294 return ret;
4295} 4295}
4296 4296
4297#if 0 4297#if 0
4298static int 4298static int
4299iwm_mvm_update_beacon_filter(struct iwm_softc *sc, struct iwm_node *in) 4299iwm_mvm_update_beacon_filter(struct iwm_softc *sc, struct iwm_node *in)
4300{ 4300{
4301 if (!sc->sc_bf.bf_enabled) 4301 if (!sc->sc_bf.bf_enabled)
4302 return 0; 4302 return 0;
4303 4303
4304 return iwm_mvm_enable_beacon_filter(sc, in); 4304 return iwm_mvm_enable_beacon_filter(sc, in);
4305} 4305}
4306#endif 4306#endif
4307 4307
4308/* 4308/*
4309 * END mvm/power.c 4309 * END mvm/power.c
4310 */ 4310 */
4311 4311
4312/* 4312/*
4313 * BEGIN mvm/sta.c 4313 * BEGIN mvm/sta.c
4314 */ 4314 */
4315 4315
4316static void 4316static void
4317iwm_mvm_add_sta_cmd_v6_to_v5(struct iwm_mvm_add_sta_cmd_v6 *cmd_v6, 4317iwm_mvm_add_sta_cmd_v6_to_v5(struct iwm_mvm_add_sta_cmd_v6 *cmd_v6,
4318 struct iwm_mvm_add_sta_cmd_v5 *cmd_v5) 4318 struct iwm_mvm_add_sta_cmd_v5 *cmd_v5)
4319{ 4319{
4320 memset(cmd_v5, 0, sizeof(*cmd_v5)); 4320 memset(cmd_v5, 0, sizeof(*cmd_v5));
4321 4321
4322 cmd_v5->add_modify = cmd_v6->add_modify; 4322 cmd_v5->add_modify = cmd_v6->add_modify;
4323 cmd_v5->tid_disable_tx = cmd_v6->tid_disable_tx; 4323 cmd_v5->tid_disable_tx = cmd_v6->tid_disable_tx;
4324 cmd_v5->mac_id_n_color = cmd_v6->mac_id_n_color; 4324 cmd_v5->mac_id_n_color = cmd_v6->mac_id_n_color;
4325 memcpy(cmd_v5->addr, cmd_v6->addr, ETHER_ADDR_LEN); 4325 memcpy(cmd_v5->addr, cmd_v6->addr, ETHER_ADDR_LEN);
4326 cmd_v5->sta_id = cmd_v6->sta_id; 4326 cmd_v5->sta_id = cmd_v6->sta_id;
4327 cmd_v5->modify_mask = cmd_v6->modify_mask; 4327 cmd_v5->modify_mask = cmd_v6->modify_mask;
4328 cmd_v5->station_flags = cmd_v6->station_flags; 4328 cmd_v5->station_flags = cmd_v6->station_flags;
4329 cmd_v5->station_flags_msk = cmd_v6->station_flags_msk; 4329 cmd_v5->station_flags_msk = cmd_v6->station_flags_msk;
4330 cmd_v5->add_immediate_ba_tid = cmd_v6->add_immediate_ba_tid; 4330 cmd_v5->add_immediate_ba_tid = cmd_v6->add_immediate_ba_tid;
4331 cmd_v5->remove_immediate_ba_tid = cmd_v6->remove_immediate_ba_tid; 4331 cmd_v5->remove_immediate_ba_tid = cmd_v6->remove_immediate_ba_tid;
4332 cmd_v5->add_immediate_ba_ssn = cmd_v6->add_immediate_ba_ssn; 4332 cmd_v5->add_immediate_ba_ssn = cmd_v6->add_immediate_ba_ssn;
4333 cmd_v5->sleep_tx_count = cmd_v6->sleep_tx_count; 4333 cmd_v5->sleep_tx_count = cmd_v6->sleep_tx_count;
4334 cmd_v5->sleep_state_flags = cmd_v6->sleep_state_flags; 4334 cmd_v5->sleep_state_flags = cmd_v6->sleep_state_flags;
4335 cmd_v5->assoc_id = cmd_v6->assoc_id; 4335 cmd_v5->assoc_id = cmd_v6->assoc_id;
4336 cmd_v5->beamform_flags = cmd_v6->beamform_flags; 4336 cmd_v5->beamform_flags = cmd_v6->beamform_flags;
4337 cmd_v5->tfd_queue_msk = cmd_v6->tfd_queue_msk; 4337 cmd_v5->tfd_queue_msk = cmd_v6->tfd_queue_msk;
4338} 4338}
4339 4339
4340static int 4340static int
4341iwm_mvm_send_add_sta_cmd_status(struct iwm_softc *sc, 4341iwm_mvm_send_add_sta_cmd_status(struct iwm_softc *sc,
4342 struct iwm_mvm_add_sta_cmd_v6 *cmd, int *status) 4342 struct iwm_mvm_add_sta_cmd_v6 *cmd, int *status)
4343{ 4343{
4344 struct iwm_mvm_add_sta_cmd_v5 cmd_v5; 4344 struct iwm_mvm_add_sta_cmd_v5 cmd_v5;
4345 4345
4346 if (sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_STA_KEY_CMD) { 4346 if (sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_STA_KEY_CMD) {
4347 return iwm_mvm_send_cmd_pdu_status(sc, IWM_ADD_STA, 4347 return iwm_mvm_send_cmd_pdu_status(sc, IWM_ADD_STA,
4348 sizeof(*cmd), cmd, status); 4348 sizeof(*cmd), cmd, status);
4349 } 4349 }
4350 4350
4351 iwm_mvm_add_sta_cmd_v6_to_v5(cmd, &cmd_v5); 4351 iwm_mvm_add_sta_cmd_v6_to_v5(cmd, &cmd_v5);
4352 4352
4353 return iwm_mvm_send_cmd_pdu_status(sc, IWM_ADD_STA, sizeof(cmd_v5), 4353 return iwm_mvm_send_cmd_pdu_status(sc, IWM_ADD_STA, sizeof(cmd_v5),
4354 &cmd_v5, status); 4354 &cmd_v5, status);
4355} 4355}
4356 4356
4357/* send station add/update command to firmware */ 4357/* send station add/update command to firmware */
4358static int 4358static int
4359iwm_mvm_sta_send_to_fw(struct iwm_softc *sc, struct iwm_node *in, int update) 4359iwm_mvm_sta_send_to_fw(struct iwm_softc *sc, struct iwm_node *in, int update)
4360{ 4360{
4361 struct iwm_mvm_add_sta_cmd_v6 add_sta_cmd; 4361 struct iwm_mvm_add_sta_cmd_v6 add_sta_cmd;
4362 int ret; 4362 int ret;
4363 uint32_t status; 4363 uint32_t status;
4364 4364
4365 memset(&add_sta_cmd, 0, sizeof(add_sta_cmd)); 4365 memset(&add_sta_cmd, 0, sizeof(add_sta_cmd));
4366 4366
4367 add_sta_cmd.sta_id = IWM_STATION_ID; 4367 add_sta_cmd.sta_id = IWM_STATION_ID;
4368 add_sta_cmd.mac_id_n_color 4368 add_sta_cmd.mac_id_n_color
4369 = htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color)); 4369 = htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));
4370 if (!update) { 4370 if (!update) {
4371 add_sta_cmd.tfd_queue_msk = htole32(0xf); 4371 add_sta_cmd.tfd_queue_msk = htole32(0xf);
4372 IEEE80211_ADDR_COPY(&add_sta_cmd.addr, in->in_ni.ni_bssid); 4372 IEEE80211_ADDR_COPY(&add_sta_cmd.addr, in->in_ni.ni_bssid);
4373 } 4373 }
4374 add_sta_cmd.add_modify = update ? 1 : 0; 4374 add_sta_cmd.add_modify = update ? 1 : 0;
4375 add_sta_cmd.station_flags_msk 4375 add_sta_cmd.station_flags_msk
4376 |= htole32(IWM_STA_FLG_FAT_EN_MSK | IWM_STA_FLG_MIMO_EN_MSK); 4376 |= htole32(IWM_STA_FLG_FAT_EN_MSK | IWM_STA_FLG_MIMO_EN_MSK);
4377 4377
4378 status = IWM_ADD_STA_SUCCESS; 4378 status = IWM_ADD_STA_SUCCESS;
4379 ret = iwm_mvm_send_add_sta_cmd_status(sc, &add_sta_cmd, &status); 4379 ret = iwm_mvm_send_add_sta_cmd_status(sc, &add_sta_cmd, &status);
4380 if (ret) 4380 if (ret)
4381 return ret; 4381 return ret;
4382 4382
4383 switch (status) { 4383 switch (status) {
4384 case IWM_ADD_STA_SUCCESS: 4384 case IWM_ADD_STA_SUCCESS:
4385 break; 4385 break;
4386 default: 4386 default:
4387 ret = EIO; 4387 ret = EIO;
4388 DPRINTF(("IWM_ADD_STA failed\n")); 4388 DPRINTF(("IWM_ADD_STA failed\n"));
4389 break; 4389 break;
4390 } 4390 }
4391 4391
4392 return ret; 4392 return ret;
4393} 4393}
4394 4394
4395static int 4395static int
4396iwm_mvm_add_sta(struct iwm_softc *sc, struct iwm_node *in) 4396iwm_mvm_add_sta(struct iwm_softc *sc, struct iwm_node *in)
4397{ 4397{
4398 int ret; 4398 int ret;
4399 4399
4400 ret = iwm_mvm_sta_send_to_fw(sc, in, 0); 4400 ret = iwm_mvm_sta_send_to_fw(sc, in, 0);
4401 if (ret) 4401 if (ret)
4402 return ret; 4402 return ret;
4403 4403
4404 return 0; 4404 return 0;
4405} 4405}
4406 4406
4407static int 4407static int
4408iwm_mvm_update_sta(struct iwm_softc *sc, struct iwm_node *in) 4408iwm_mvm_update_sta(struct iwm_softc *sc, struct iwm_node *in)
4409{ 4409{
4410 return iwm_mvm_sta_send_to_fw(sc, in, 1); 4410 return iwm_mvm_sta_send_to_fw(sc, in, 1);
4411} 4411}
4412 4412
4413static int 4413static int
4414iwm_mvm_add_int_sta_common(struct iwm_softc *sc, struct iwm_int_sta *sta, 4414iwm_mvm_add_int_sta_common(struct iwm_softc *sc, struct iwm_int_sta *sta,
4415 const uint8_t *addr, uint16_t mac_id, uint16_t color) 4415 const uint8_t *addr, uint16_t mac_id, uint16_t color)
4416{ 4416{
4417 struct iwm_mvm_add_sta_cmd_v6 cmd; 4417 struct iwm_mvm_add_sta_cmd_v6 cmd;
4418 int ret; 4418 int ret;
4419 uint32_t status; 4419 uint32_t status;
4420 4420
4421 memset(&cmd, 0, sizeof(cmd)); 4421 memset(&cmd, 0, sizeof(cmd));
4422 cmd.sta_id = sta->sta_id; 4422 cmd.sta_id = sta->sta_id;
4423 cmd.mac_id_n_color = htole32(IWM_FW_CMD_ID_AND_COLOR(mac_id, color)); 4423 cmd.mac_id_n_color = htole32(IWM_FW_CMD_ID_AND_COLOR(mac_id, color));
4424 4424
4425 cmd.tfd_queue_msk = htole32(sta->tfd_queue_msk); 4425 cmd.tfd_queue_msk = htole32(sta->tfd_queue_msk);
4426 4426
4427 if (addr) 4427 if (addr)
4428 memcpy(cmd.addr, addr, ETHER_ADDR_LEN); 4428 memcpy(cmd.addr, addr, ETHER_ADDR_LEN);
4429 4429
4430 ret = iwm_mvm_send_add_sta_cmd_status(sc, &cmd, &status); 4430 ret = iwm_mvm_send_add_sta_cmd_status(sc, &cmd, &status);
4431 if (ret) 4431 if (ret)
4432 return ret; 4432 return ret;
4433 4433
4434 switch (status) { 4434 switch (status) {
4435 case IWM_ADD_STA_SUCCESS: 4435 case IWM_ADD_STA_SUCCESS:
4436 DPRINTF(("Internal station added.\n")); 4436 DPRINTF(("Internal station added.\n"));
4437 return 0; 4437 return 0;
4438 default: 4438 default:
4439 DPRINTF(("%s: Add internal station failed, status=0x%x\n", 4439 DPRINTF(("%s: Add internal station failed, status=0x%x\n",
4440 DEVNAME(sc), status)); 4440 DEVNAME(sc), status));
4441 ret = EIO; 4441 ret = EIO;
4442 break; 4442 break;
4443 } 4443 }
4444 return ret; 4444 return ret;
4445} 4445}
4446 4446
4447static int 4447static int
4448iwm_mvm_add_aux_sta(struct iwm_softc *sc) 4448iwm_mvm_add_aux_sta(struct iwm_softc *sc)
4449{ 4449{
4450 int ret; 4450 int ret;
4451 4451
4452 sc->sc_aux_sta.sta_id = 3; 4452 sc->sc_aux_sta.sta_id = 3;
4453 sc->sc_aux_sta.tfd_queue_msk = 0; 4453 sc->sc_aux_sta.tfd_queue_msk = 0;
4454 4454
4455 ret = iwm_mvm_add_int_sta_common(sc, 4455 ret = iwm_mvm_add_int_sta_common(sc,
4456 &sc->sc_aux_sta, NULL, IWM_MAC_INDEX_AUX, 0); 4456 &sc->sc_aux_sta, NULL, IWM_MAC_INDEX_AUX, 0);
4457 4457
4458 if (ret) 4458 if (ret)
4459 memset(&sc->sc_aux_sta, 0, sizeof(sc->sc_aux_sta)); 4459 memset(&sc->sc_aux_sta, 0, sizeof(sc->sc_aux_sta));
4460 return ret; 4460 return ret;
4461} 4461}
4462 4462
4463/* 4463/*
4464 * END mvm/sta.c 4464 * END mvm/sta.c
4465 */ 4465 */
4466 4466
4467/* 4467/*
4468 * BEGIN mvm/scan.c 4468 * BEGIN mvm/scan.c
4469 */ 4469 */
4470 4470
4471#define IWM_PLCP_QUIET_THRESH 1 4471#define IWM_PLCP_QUIET_THRESH 1
4472#define IWM_ACTIVE_QUIET_TIME 10 4472#define IWM_ACTIVE_QUIET_TIME 10
4473#define LONG_OUT_TIME_PERIOD 600 4473#define LONG_OUT_TIME_PERIOD 600
4474#define SHORT_OUT_TIME_PERIOD 200 4474#define SHORT_OUT_TIME_PERIOD 200
4475#define SUSPEND_TIME_PERIOD 100 4475#define SUSPEND_TIME_PERIOD 100
4476 4476
4477static uint16_t 4477static uint16_t
4478iwm_mvm_scan_rx_chain(struct iwm_softc *sc) 4478iwm_mvm_scan_rx_chain(struct iwm_softc *sc)
4479{ 4479{
4480 uint16_t rx_chain; 4480 uint16_t rx_chain;
4481 uint8_t rx_ant; 4481 uint8_t rx_ant;
4482 4482
4483 rx_ant = IWM_FW_VALID_RX_ANT(sc); 4483 rx_ant = IWM_FW_VALID_RX_ANT(sc);
4484 rx_chain = rx_ant << IWM_PHY_RX_CHAIN_VALID_POS; 4484 rx_chain = rx_ant << IWM_PHY_RX_CHAIN_VALID_POS;
4485 rx_chain |= rx_ant << IWM_PHY_RX_CHAIN_FORCE_MIMO_SEL_POS; 4485 rx_chain |= rx_ant << IWM_PHY_RX_CHAIN_FORCE_MIMO_SEL_POS;
4486 rx_chain |= rx_ant << IWM_PHY_RX_CHAIN_FORCE_SEL_POS; 4486 rx_chain |= rx_ant << IWM_PHY_RX_CHAIN_FORCE_SEL_POS;
4487 rx_chain |= 0x1 << IWM_PHY_RX_CHAIN_DRIVER_FORCE_POS; 4487 rx_chain |= 0x1 << IWM_PHY_RX_CHAIN_DRIVER_FORCE_POS;
4488 return htole16(rx_chain); 4488 return htole16(rx_chain);
4489} 4489}
4490 4490
4491#define ieee80211_tu_to_usec(a) (1024*(a)) 4491#define ieee80211_tu_to_usec(a) (1024*(a))
4492 4492
4493static uint32_t 4493static uint32_t
4494iwm_mvm_scan_max_out_time(struct iwm_softc *sc, uint32_t flags, int is_assoc) 4494iwm_mvm_scan_max_out_time(struct iwm_softc *sc, uint32_t flags, int is_assoc)
4495{ 4495{
4496 if (!is_assoc) 4496 if (!is_assoc)
4497 return 0; 4497 return 0;
4498 if (flags & 0x1) 4498 if (flags & 0x1)
4499 return htole32(ieee80211_tu_to_usec(SHORT_OUT_TIME_PERIOD)); 4499 return htole32(ieee80211_tu_to_usec(SHORT_OUT_TIME_PERIOD));
4500 return htole32(ieee80211_tu_to_usec(LONG_OUT_TIME_PERIOD)); 4500 return htole32(ieee80211_tu_to_usec(LONG_OUT_TIME_PERIOD));
4501} 4501}
4502 4502
4503static uint32_t 4503static uint32_t
4504iwm_mvm_scan_suspend_time(struct iwm_softc *sc, int is_assoc) 4504iwm_mvm_scan_suspend_time(struct iwm_softc *sc, int is_assoc)
4505{ 4505{
4506 if (!is_assoc) 4506 if (!is_assoc)
4507 return 0; 4507 return 0;
4508 return htole32(ieee80211_tu_to_usec(SUSPEND_TIME_PERIOD)); 4508 return htole32(ieee80211_tu_to_usec(SUSPEND_TIME_PERIOD));
4509} 4509}
4510 4510
4511static uint32_t 4511static uint32_t
4512iwm_mvm_scan_rxon_flags(struct iwm_softc *sc, int flags) 4512iwm_mvm_scan_rxon_flags(struct iwm_softc *sc, int flags)
4513{ 4513{
4514 if (flags & IEEE80211_CHAN_2GHZ) 4514 if (flags & IEEE80211_CHAN_2GHZ)
4515 return htole32(IWM_PHY_BAND_24); 4515 return htole32(IWM_PHY_BAND_24);
4516 else 4516 else
4517 return htole32(IWM_PHY_BAND_5); 4517 return htole32(IWM_PHY_BAND_5);
4518} 4518}
4519 4519
4520static uint32_t 4520static uint32_t
4521iwm_mvm_scan_rate_n_flags(struct iwm_softc *sc, int flags, int no_cck) 4521iwm_mvm_scan_rate_n_flags(struct iwm_softc *sc, int flags, int no_cck)
4522{ 4522{
4523 uint32_t tx_ant; 4523 uint32_t tx_ant;
4524 int i, ind; 4524 int i, ind;
4525 4525
4526 for (i = 0, ind = sc->sc_scan_last_antenna; 4526 for (i = 0, ind = sc->sc_scan_last_antenna;
4527 i < IWM_RATE_MCS_ANT_NUM; i++) { 4527 i < IWM_RATE_MCS_ANT_NUM; i++) {
4528 ind = (ind + 1) % IWM_RATE_MCS_ANT_NUM; 4528 ind = (ind + 1) % IWM_RATE_MCS_ANT_NUM;
4529 if (IWM_FW_VALID_TX_ANT(sc) & (1 << ind)) { 4529 if (IWM_FW_VALID_TX_ANT(sc) & (1 << ind)) {
4530 sc->sc_scan_last_antenna = ind; 4530 sc->sc_scan_last_antenna = ind;
4531 break; 4531 break;
4532 } 4532 }
4533 } 4533 }
4534 tx_ant = (1 << sc->sc_scan_last_antenna) << IWM_RATE_MCS_ANT_POS; 4534 tx_ant = (1 << sc->sc_scan_last_antenna) << IWM_RATE_MCS_ANT_POS;
4535 4535
4536 if ((flags & IEEE80211_CHAN_2GHZ) && !no_cck) 4536 if ((flags & IEEE80211_CHAN_2GHZ) && !no_cck)
4537 return htole32(IWM_RATE_1M_PLCP | IWM_RATE_MCS_CCK_MSK | 4537 return htole32(IWM_RATE_1M_PLCP | IWM_RATE_MCS_CCK_MSK |
4538 tx_ant); 4538 tx_ant);
4539 else 4539 else
4540 return htole32(IWM_RATE_6M_PLCP | tx_ant); 4540 return htole32(IWM_RATE_6M_PLCP | tx_ant);
4541} 4541}
4542 4542
4543/* 4543/*
4544 * If req->n_ssids > 0, it means we should do an active scan. 4544 * If req->n_ssids > 0, it means we should do an active scan.
4545 * In case of active scan w/o directed scan, we receive a zero-length SSID 4545 * In case of active scan w/o directed scan, we receive a zero-length SSID
4546 * just to notify that this scan is active and not passive. 4546 * just to notify that this scan is active and not passive.
4547 * In order to notify the FW of the number of SSIDs we wish to scan (including 4547 * In order to notify the FW of the number of SSIDs we wish to scan (including
4548 * the zero-length one), we need to set the corresponding bits in chan->type, 4548 * the zero-length one), we need to set the corresponding bits in chan->type,
4549 * one for each SSID, and set the active bit (first). If the first SSID is 4549 * one for each SSID, and set the active bit (first). If the first SSID is
4550 * already included in the probe template, so we need to set only 4550 * already included in the probe template, so we need to set only
4551 * req->n_ssids - 1 bits in addition to the first bit. 4551 * req->n_ssids - 1 bits in addition to the first bit.
4552 */ 4552 */
4553static uint16_t 4553static uint16_t
4554iwm_mvm_get_active_dwell(struct iwm_softc *sc, int flags, int n_ssids) 4554iwm_mvm_get_active_dwell(struct iwm_softc *sc, int flags, int n_ssids)
4555{ 4555{
4556 if (flags & IEEE80211_CHAN_2GHZ) 4556 if (flags & IEEE80211_CHAN_2GHZ)
4557 return 30 + 3 * (n_ssids + 1); 4557 return 30 + 3 * (n_ssids + 1);
4558 return 20 + 2 * (n_ssids + 1); 4558 return 20 + 2 * (n_ssids + 1);
4559} 4559}
4560 4560
4561static uint16_t 4561static uint16_t
4562iwm_mvm_get_passive_dwell(struct iwm_softc *sc, int flags) 4562iwm_mvm_get_passive_dwell(struct iwm_softc *sc, int flags)
4563{ 4563{
4564 return (flags & IEEE80211_CHAN_2GHZ) ? 100 + 20 : 100 + 10; 4564 return (flags & IEEE80211_CHAN_2GHZ) ? 100 + 20 : 100 + 10;
4565} 4565}
4566 4566
4567static int 4567static int
4568iwm_mvm_scan_fill_channels(struct iwm_softc *sc, struct iwm_scan_cmd *cmd, 4568iwm_mvm_scan_fill_channels(struct iwm_softc *sc, struct iwm_scan_cmd *cmd,
4569 int flags, int n_ssids, int basic_ssid) 4569 int flags, int n_ssids, int basic_ssid)
4570{ 4570{
4571 struct ieee80211com *ic = &sc->sc_ic; 4571 struct ieee80211com *ic = &sc->sc_ic;
4572 uint16_t passive_dwell = iwm_mvm_get_passive_dwell(sc, flags); 4572 uint16_t passive_dwell = iwm_mvm_get_passive_dwell(sc, flags);
4573 uint16_t active_dwell = iwm_mvm_get_active_dwell(sc, flags, n_ssids); 4573 uint16_t active_dwell = iwm_mvm_get_active_dwell(sc, flags, n_ssids);
4574 struct iwm_scan_channel *chan = (struct iwm_scan_channel *) 4574 struct iwm_scan_channel *chan = (struct iwm_scan_channel *)
4575 (cmd->data + le16toh(cmd->tx_cmd.len)); 4575 (cmd->data + le16toh(cmd->tx_cmd.len));
4576 int type = (1 << n_ssids) - 1; 4576 int type = (1 << n_ssids) - 1;
4577 struct ieee80211_channel *c; 4577 struct ieee80211_channel *c;
4578 int nchan; 4578 int nchan;
4579 4579
4580 if (!basic_ssid) 4580 if (!basic_ssid)
4581 type |= (1 << n_ssids); 4581 type |= (1 << n_ssids);
4582 4582
4583 for (nchan = 0, c = &ic->ic_channels[1]; 4583 for (nchan = 0, c = &ic->ic_channels[1];
4584 c <= &ic->ic_channels[IEEE80211_CHAN_MAX]; 4584 c <= &ic->ic_channels[IEEE80211_CHAN_MAX];
4585 c++) { 4585 c++) {
4586 if ((c->ic_flags & flags) != flags) 4586 if ((c->ic_flags & flags) != flags)
4587 continue; 4587 continue;
4588 4588
4589 chan->channel = htole16(ieee80211_mhz2ieee(c->ic_freq, flags)); 4589 chan->channel = htole16(ieee80211_mhz2ieee(c->ic_freq, flags));
4590 chan->type = htole32(type); 4590 chan->type = htole32(type);
4591 if (c->ic_flags & IEEE80211_CHAN_PASSIVE) 4591 if (c->ic_flags & IEEE80211_CHAN_PASSIVE)
4592 chan->type &= htole32(~IWM_SCAN_CHANNEL_TYPE_ACTIVE); 4592 chan->type &= htole32(~IWM_SCAN_CHANNEL_TYPE_ACTIVE);
4593 chan->active_dwell = htole16(active_dwell); 4593 chan->active_dwell = htole16(active_dwell);
4594 chan->passive_dwell = htole16(passive_dwell); 4594 chan->passive_dwell = htole16(passive_dwell);
4595 chan->iteration_count = htole16(1); 4595 chan->iteration_count = htole16(1);
4596 chan++; 4596 chan++;
4597 nchan++; 4597 nchan++;
4598 } 4598 }
4599 if (nchan == 0) 4599 if (nchan == 0)
4600 DPRINTF(("%s: NO CHANNEL!\n", DEVNAME(sc))); 4600 DPRINTF(("%s: NO CHANNEL!\n", DEVNAME(sc)));
4601 return nchan; 4601 return nchan;
4602} 4602}
4603 4603
4604/* 4604/*
4605 * Fill in probe request with the following parameters: 4605 * Fill in probe request with the following parameters:
4606 * TA is our vif HW address, which mac80211 ensures we have. 4606 * TA is our vif HW address, which mac80211 ensures we have.
4607 * Packet is broadcasted, so this is both SA and DA. 4607 * Packet is broadcasted, so this is both SA and DA.
4608 * The probe request IE is made out of two: first comes the most prioritized 4608 * The probe request IE is made out of two: first comes the most prioritized
4609 * SSID if a directed scan is requested. Second comes whatever extra 4609 * SSID if a directed scan is requested. Second comes whatever extra
4610 * information was given to us as the scan request IE. 4610 * information was given to us as the scan request IE.
4611 */ 4611 */
4612static uint16_t 4612static uint16_t
4613iwm_mvm_fill_probe_req(struct iwm_softc *sc, struct ieee80211_frame *frame, 4613iwm_mvm_fill_probe_req(struct iwm_softc *sc, struct ieee80211_frame *frame,
4614 const uint8_t *ta, int n_ssids, const uint8_t *ssid, int ssid_len, 4614 const uint8_t *ta, int n_ssids, const uint8_t *ssid, int ssid_len,
4615 const uint8_t *ie, int ie_len, int left) 4615 const uint8_t *ie, int ie_len, int left)
4616{ 4616{
4617 int len = 0; 4617 int len = 0;
4618 uint8_t *pos = NULL; 4618 uint8_t *pos = NULL;
4619 4619
4620 /* Make sure there is enough space for the probe request, 4620 /* Make sure there is enough space for the probe request,
4621 * two mandatory IEs and the data */ 4621 * two mandatory IEs and the data */
4622 left -= sizeof(*frame); 4622 left -= sizeof(*frame);
4623 if (left < 0) 4623 if (left < 0)
4624 return 0; 4624 return 0;
4625 4625
4626 frame->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | 4626 frame->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
4627 IEEE80211_FC0_SUBTYPE_PROBE_REQ; 4627 IEEE80211_FC0_SUBTYPE_PROBE_REQ;
4628 frame->i_fc[1] = IEEE80211_FC1_DIR_NODS; 4628 frame->i_fc[1] = IEEE80211_FC1_DIR_NODS;
4629 IEEE80211_ADDR_COPY(frame->i_addr1, etherbroadcastaddr); 4629 IEEE80211_ADDR_COPY(frame->i_addr1, etherbroadcastaddr);
4630 memcpy(frame->i_addr2, ta, ETHER_ADDR_LEN); 4630 memcpy(frame->i_addr2, ta, ETHER_ADDR_LEN);
4631 IEEE80211_ADDR_COPY(frame->i_addr3, etherbroadcastaddr); 4631 IEEE80211_ADDR_COPY(frame->i_addr3, etherbroadcastaddr);
4632 4632
4633 len += sizeof(*frame); 4633 len += sizeof(*frame);
4634 CTASSERT(sizeof(*frame) == 24); 4634 CTASSERT(sizeof(*frame) == 24);
4635 4635
4636 /* for passive scans, no need to fill anything */ 4636 /* for passive scans, no need to fill anything */
4637 if (n_ssids == 0) 4637 if (n_ssids == 0)
4638 return (uint16_t)len; 4638 return (uint16_t)len;
4639 4639
4640 /* points to the payload of the request */ 4640 /* points to the payload of the request */
4641 pos = (uint8_t *)frame + sizeof(*frame); 4641 pos = (uint8_t *)frame + sizeof(*frame);
4642 4642
4643 /* fill in our SSID IE */ 4643 /* fill in our SSID IE */
4644 left -= ssid_len + 2; 4644 left -= ssid_len + 2;
4645 if (left < 0) 4645 if (left < 0)
4646 return 0; 4646 return 0;
4647 *pos++ = IEEE80211_ELEMID_SSID; 4647 *pos++ = IEEE80211_ELEMID_SSID;
4648 *pos++ = ssid_len; 4648 *pos++ = ssid_len;
4649 if (ssid && ssid_len) { /* ssid_len may be == 0 even if ssid is valid */ 4649 if (ssid && ssid_len) { /* ssid_len may be == 0 even if ssid is valid */
4650 memcpy(pos, ssid, ssid_len); 4650 memcpy(pos, ssid, ssid_len);
4651 pos += ssid_len; 4651 pos += ssid_len;
4652 } 4652 }
4653 4653
4654 len += ssid_len + 2; 4654 len += ssid_len + 2;
4655 4655
4656 if (left < ie_len) 4656 if (left < ie_len)
4657 return len; 4657 return len;
4658 4658
4659 if (ie && ie_len) { 4659 if (ie && ie_len) {
4660 memcpy(pos, ie, ie_len); 4660 memcpy(pos, ie, ie_len);
4661 len += ie_len; 4661 len += ie_len;
4662 } 4662 }
4663 4663
4664 return (uint16_t)len; 4664 return (uint16_t)len;
4665} 4665}
4666 4666
4667static int 4667static int
4668iwm_mvm_scan_request(struct iwm_softc *sc, int flags, 4668iwm_mvm_scan_request(struct iwm_softc *sc, int flags,
4669 int n_ssids, uint8_t *ssid, int ssid_len) 4669 int n_ssids, uint8_t *ssid, int ssid_len)
4670{ 4670{
4671 struct ieee80211com *ic = &sc->sc_ic; 4671 struct ieee80211com *ic = &sc->sc_ic;
4672 struct iwm_host_cmd hcmd = { 4672 struct iwm_host_cmd hcmd = {
4673 .id = IWM_SCAN_REQUEST_CMD, 4673 .id = IWM_SCAN_REQUEST_CMD,
4674 .len = { 0, }, 4674 .len = { 0, },
4675 .data = { sc->sc_scan_cmd, }, 4675 .data = { sc->sc_scan_cmd, },
4676 .flags = IWM_CMD_SYNC, 4676 .flags = IWM_CMD_SYNC,
4677 .dataflags = { IWM_HCMD_DFL_NOCOPY, }, 4677 .dataflags = { IWM_HCMD_DFL_NOCOPY, },
4678 }; 4678 };
4679 struct iwm_scan_cmd *cmd = sc->sc_scan_cmd; 4679 struct iwm_scan_cmd *cmd = sc->sc_scan_cmd;
4680 int is_assoc = 0; 4680 int is_assoc = 0;
4681 int ret; 4681 int ret;
4682 uint32_t status; 4682 uint32_t status;
4683 int basic_ssid = !(sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_NO_BASIC_SSID); 4683 int basic_ssid = !(sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_NO_BASIC_SSID);
4684 4684
4685 //lockdep_assert_held(&mvm->mutex); 4685 //lockdep_assert_held(&mvm->mutex);
4686 4686
4687 sc->sc_scanband = flags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ); 4687 sc->sc_scanband = flags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ);
4688 4688
4689 DPRINTF(("Handling ieee80211 scan request\n")); 4689 DPRINTF(("Handling ieee80211 scan request\n"));
4690 memset(cmd, 0, sc->sc_scan_cmd_len); 4690 memset(cmd, 0, sc->sc_scan_cmd_len);
4691 4691
4692 cmd->quiet_time = htole16(IWM_ACTIVE_QUIET_TIME); 4692 cmd->quiet_time = htole16(IWM_ACTIVE_QUIET_TIME);
4693 cmd->quiet_plcp_th = htole16(IWM_PLCP_QUIET_THRESH); 4693 cmd->quiet_plcp_th = htole16(IWM_PLCP_QUIET_THRESH);
4694 cmd->rxchain_sel_flags = iwm_mvm_scan_rx_chain(sc); 4694 cmd->rxchain_sel_flags = iwm_mvm_scan_rx_chain(sc);
4695 cmd->max_out_time = iwm_mvm_scan_max_out_time(sc, 0, is_assoc); 4695 cmd->max_out_time = iwm_mvm_scan_max_out_time(sc, 0, is_assoc);
4696 cmd->suspend_time = iwm_mvm_scan_suspend_time(sc, is_assoc); 4696 cmd->suspend_time = iwm_mvm_scan_suspend_time(sc, is_assoc);
4697 cmd->rxon_flags = iwm_mvm_scan_rxon_flags(sc, flags); 4697 cmd->rxon_flags = iwm_mvm_scan_rxon_flags(sc, flags);
4698 cmd->filter_flags = htole32(IWM_MAC_FILTER_ACCEPT_GRP | 4698 cmd->filter_flags = htole32(IWM_MAC_FILTER_ACCEPT_GRP |
4699 IWM_MAC_FILTER_IN_BEACON); 4699 IWM_MAC_FILTER_IN_BEACON);
4700 4700
4701 cmd->type = htole32(IWM_SCAN_TYPE_FORCED); 4701 cmd->type = htole32(IWM_SCAN_TYPE_FORCED);
4702 cmd->repeats = htole32(1); 4702 cmd->repeats = htole32(1);
4703 4703
4704 /* 4704 /*
4705 * If the user asked for passive scan, don't change to active scan if 4705 * If the user asked for passive scan, don't change to active scan if
4706 * you see any activity on the channel - remain passive. 4706 * you see any activity on the channel - remain passive.
4707 */ 4707 */
4708 if (n_ssids > 0) { 4708 if (n_ssids > 0) {
4709 cmd->passive2active = htole16(1); 4709 cmd->passive2active = htole16(1);
4710 cmd->scan_flags |= IWM_SCAN_FLAGS_PASSIVE2ACTIVE; 4710 cmd->scan_flags |= IWM_SCAN_FLAGS_PASSIVE2ACTIVE;
4711#if 0 4711#if 0
4712 if (basic_ssid) { 4712 if (basic_ssid) {
4713 ssid = req->ssids[0].ssid; 4713 ssid = req->ssids[0].ssid;
4714 ssid_len = req->ssids[0].ssid_len; 4714 ssid_len = req->ssids[0].ssid_len;
4715 } 4715 }
4716#endif 4716#endif
4717 } else { 4717 } else {
4718 cmd->passive2active = 0; 4718 cmd->passive2active = 0;
4719 cmd->scan_flags &= ~IWM_SCAN_FLAGS_PASSIVE2ACTIVE; 4719 cmd->scan_flags &= ~IWM_SCAN_FLAGS_PASSIVE2ACTIVE;
4720 } 4720 }
4721 4721
4722 cmd->tx_cmd.tx_flags = htole32(IWM_TX_CMD_FLG_SEQ_CTL | 4722 cmd->tx_cmd.tx_flags = htole32(IWM_TX_CMD_FLG_SEQ_CTL |
4723 IWM_TX_CMD_FLG_BT_DIS); 4723 IWM_TX_CMD_FLG_BT_DIS);
4724 cmd->tx_cmd.sta_id = sc->sc_aux_sta.sta_id; 4724 cmd->tx_cmd.sta_id = sc->sc_aux_sta.sta_id;
4725 cmd->tx_cmd.life_time = htole32(IWM_TX_CMD_LIFE_TIME_INFINITE); 4725 cmd->tx_cmd.life_time = htole32(IWM_TX_CMD_LIFE_TIME_INFINITE);
4726 cmd->tx_cmd.rate_n_flags = iwm_mvm_scan_rate_n_flags(sc, flags, 1/*XXX*/); 4726 cmd->tx_cmd.rate_n_flags = iwm_mvm_scan_rate_n_flags(sc, flags, 1/*XXX*/);
4727 4727
4728 cmd->tx_cmd.len = htole16(iwm_mvm_fill_probe_req(sc, 4728 cmd->tx_cmd.len = htole16(iwm_mvm_fill_probe_req(sc,
4729 (struct ieee80211_frame *)cmd->data, 4729 (struct ieee80211_frame *)cmd->data,
4730 ic->ic_myaddr, n_ssids, ssid, ssid_len, 4730 ic->ic_myaddr, n_ssids, ssid, ssid_len,
4731 NULL, 0, sc->sc_capa_max_probe_len)); 4731 NULL, 0, sc->sc_capa_max_probe_len));
4732 4732
4733 cmd->channel_count 4733 cmd->channel_count
4734 = iwm_mvm_scan_fill_channels(sc, cmd, flags, n_ssids, basic_ssid); 4734 = iwm_mvm_scan_fill_channels(sc, cmd, flags, n_ssids, basic_ssid);
4735 4735
4736 cmd->len = htole16(sizeof(struct iwm_scan_cmd) + 4736 cmd->len = htole16(sizeof(struct iwm_scan_cmd) +
4737 le16toh(cmd->tx_cmd.len) + 4737 le16toh(cmd->tx_cmd.len) +
4738 (cmd->channel_count * sizeof(struct iwm_scan_channel))); 4738 (cmd->channel_count * sizeof(struct iwm_scan_channel)));
4739 hcmd.len[0] = le16toh(cmd->len); 4739 hcmd.len[0] = le16toh(cmd->len);
4740 4740
4741 status = IWM_SCAN_RESPONSE_OK; 4741 status = IWM_SCAN_RESPONSE_OK;
4742 ret = iwm_mvm_send_cmd_status(sc, &hcmd, &status); 4742 ret = iwm_mvm_send_cmd_status(sc, &hcmd, &status);
4743 if (!ret && status == IWM_SCAN_RESPONSE_OK) { 4743 if (!ret && status == IWM_SCAN_RESPONSE_OK) {
4744 DPRINTF(("Scan request was sent successfully\n")); 4744 DPRINTF(("Scan request was sent successfully\n"));
4745 } else { 4745 } else {
4746 /* 4746 /*
4747 * If the scan failed, it usually means that the FW was unable 4747 * If the scan failed, it usually means that the FW was unable
4748 * to allocate the time events. Warn on it, but maybe we 4748 * to allocate the time events. Warn on it, but maybe we
4749 * should try to send the command again with different params. 4749 * should try to send the command again with different params.
4750 */ 4750 */
4751 sc->sc_scanband = 0; 4751 sc->sc_scanband = 0;
4752 ret = EIO; 4752 ret = EIO;
4753 } 4753 }
4754 return ret; 4754 return ret;
4755} 4755}
4756 4756
4757/* 4757/*
4758 * END mvm/scan.c 4758 * END mvm/scan.c
4759 */ 4759 */
4760 4760
4761/* 4761/*
4762 * BEGIN mvm/mac-ctxt.c 4762 * BEGIN mvm/mac-ctxt.c
4763 */ 4763 */
4764 4764
4765static void 4765static void
4766iwm_mvm_ack_rates(struct iwm_softc *sc, struct iwm_node *in, 4766iwm_mvm_ack_rates(struct iwm_softc *sc, struct iwm_node *in,
4767 int *cck_rates, int *ofdm_rates) 4767 int *cck_rates, int *ofdm_rates)
4768{ 4768{
4769 int lowest_present_ofdm = 100; 4769 int lowest_present_ofdm = 100;
4770 int lowest_present_cck = 100; 4770 int lowest_present_cck = 100;
4771 uint8_t cck = 0; 4771 uint8_t cck = 0;
4772 uint8_t ofdm = 0; 4772 uint8_t ofdm = 0;
4773 int i; 4773 int i;
4774 4774
4775 for (i = 0; i <= IWM_LAST_CCK_RATE; i++) { 4775 for (i = 0; i <= IWM_LAST_CCK_RATE; i++) {
4776 cck |= (1 << i); 4776 cck |= (1 << i);
4777 if (lowest_present_cck > i) 4777 if (lowest_present_cck > i)
4778 lowest_present_cck = i; 4778 lowest_present_cck = i;
4779 } 4779 }
4780 for (i = IWM_FIRST_OFDM_RATE; i <= IWM_LAST_NON_HT_RATE; i++) { 4780 for (i = IWM_FIRST_OFDM_RATE; i <= IWM_LAST_NON_HT_RATE; i++) {
4781 int adj = i - IWM_FIRST_OFDM_RATE; 4781 int adj = i - IWM_FIRST_OFDM_RATE;
4782 ofdm |= (1 << adj); 4782 ofdm |= (1 << adj);
4783 if (lowest_present_ofdm > i) 4783 if (lowest_present_ofdm > i)
4784 lowest_present_ofdm = i; 4784 lowest_present_ofdm = i;
4785 } 4785 }
4786 4786
4787 /* 4787 /*
4788 * Now we've got the basic rates as bitmaps in the ofdm and cck 4788 * Now we've got the basic rates as bitmaps in the ofdm and cck
4789 * variables. This isn't sufficient though, as there might not 4789 * variables. This isn't sufficient though, as there might not
4790 * be all the right rates in the bitmap. E.g. if the only basic 4790 * be all the right rates in the bitmap. E.g. if the only basic
4791 * rates are 5.5 Mbps and 11 Mbps, we still need to add 1 Mbps 4791 * rates are 5.5 Mbps and 11 Mbps, we still need to add 1 Mbps
4792 * and 6 Mbps because the 802.11-2007 standard says in 9.6: 4792 * and 6 Mbps because the 802.11-2007 standard says in 9.6:
4793 * 4793 *
4794 * [...] a STA responding to a received frame shall transmit 4794 * [...] a STA responding to a received frame shall transmit
4795 * its Control Response frame [...] at the highest rate in the 4795 * its Control Response frame [...] at the highest rate in the
4796 * BSSBasicRateSet parameter that is less than or equal to the 4796 * BSSBasicRateSet parameter that is less than or equal to the
4797 * rate of the immediately previous frame in the frame exchange 4797 * rate of the immediately previous frame in the frame exchange
4798 * sequence ([...]) and that is of the same modulation class 4798 * sequence ([...]) and that is of the same modulation class
4799 * ([...]) as the received frame. If no rate contained in the 4799 * ([...]) as the received frame. If no rate contained in the
4800 * BSSBasicRateSet parameter meets these conditions, then the 4800 * BSSBasicRateSet parameter meets these conditions, then the
4801 * control frame sent in response to a received frame shall be 4801 * control frame sent in response to a received frame shall be
4802 * transmitted at the highest mandatory rate of the PHY that is 4802 * transmitted at the highest mandatory rate of the PHY that is
4803 * less than or equal to the rate of the received frame, and 4803 * less than or equal to the rate of the received frame, and
4804 * that is of the same modulation class as the received frame. 4804 * that is of the same modulation class as the received frame.
4805 * 4805 *
4806 * As a consequence, we need to add all mandatory rates that are 4806 * As a consequence, we need to add all mandatory rates that are
4807 * lower than all of the basic rates to these bitmaps. 4807 * lower than all of the basic rates to these bitmaps.
4808 */ 4808 */
4809 4809
4810 if (IWM_RATE_24M_INDEX < lowest_present_ofdm) 4810 if (IWM_RATE_24M_INDEX < lowest_present_ofdm)
4811 ofdm |= IWM_RATE_BIT_MSK(24) >> IWM_FIRST_OFDM_RATE; 4811 ofdm |= IWM_RATE_BIT_MSK(24) >> IWM_FIRST_OFDM_RATE;
4812 if (IWM_RATE_12M_INDEX < lowest_present_ofdm) 4812 if (IWM_RATE_12M_INDEX < lowest_present_ofdm)
4813 ofdm |= IWM_RATE_BIT_MSK(12) >> IWM_FIRST_OFDM_RATE; 4813 ofdm |= IWM_RATE_BIT_MSK(12) >> IWM_FIRST_OFDM_RATE;
4814 /* 6M already there or needed so always add */ 4814 /* 6M already there or needed so always add */
4815 ofdm |= IWM_RATE_BIT_MSK(6) >> IWM_FIRST_OFDM_RATE; 4815 ofdm |= IWM_RATE_BIT_MSK(6) >> IWM_FIRST_OFDM_RATE;
4816 4816
4817 /* 4817 /*
4818 * CCK is a bit more complex with DSSS vs. HR/DSSS vs. ERP. 4818 * CCK is a bit more complex with DSSS vs. HR/DSSS vs. ERP.
4819 * Note, however: 4819 * Note, however: