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