aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-07-12 13:44:50 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-07-12 13:44:50 -0400
commit38a00840638b4932152bca48098dbfa069d942a2 (patch)
treedd12897854f6df8aac237d5fd46551c74be8153a /drivers/net
parent391e5c22f5f4e55817f8ba18a08ea717ed2d4a1f (diff)
parent2f8684ce7a47c91da7e0ccba2686277c103d02b6 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wimax/i2400m/Kconfig22
-rw-r--r--drivers/net/wimax/i2400m/Makefile8
-rw-r--r--drivers/net/wimax/i2400m/driver.c3
-rw-r--r--drivers/net/wimax/i2400m/fw.c3
-rw-r--r--drivers/net/wimax/i2400m/i2400m-sdio.h157
-rw-r--r--drivers/net/wimax/i2400m/i2400m.h13
-rw-r--r--drivers/net/wimax/i2400m/sdio-debug-levels.h22
-rw-r--r--drivers/net/wimax/i2400m/sdio-fw.c210
-rw-r--r--drivers/net/wimax/i2400m/sdio-rx.c301
-rw-r--r--drivers/net/wimax/i2400m/sdio-tx.c177
-rw-r--r--drivers/net/wimax/i2400m/sdio.c602
-rw-r--r--drivers/net/wireless/Kconfig1
-rw-r--r--drivers/net/wireless/Makefile2
-rw-r--r--drivers/net/wireless/ath/ath5k/Kconfig8
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c17
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c13
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_hw.c87
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mci.c18
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_paprd.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c72
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h1284
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/gpio.c25
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c46
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c16
-rw-r--r--drivers/net/wireless/ath/ath9k/mci.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h16
-rw-r--r--drivers/net/wireless/ath/carl9170/carl9170.h11
-rw-r--r--drivers/net/wireless/ath/carl9170/fw.c3
-rw-r--r--drivers/net/wireless/ath/carl9170/fwdesc.h3
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c6
-rw-r--r--drivers/net/wireless/ath/carl9170/rx.c49
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c69
-rw-r--r--drivers/net/wireless/ath/carl9170/version.h8
-rw-r--r--drivers/net/wireless/b43/phy_n.c17
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/aiutils.c128
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/aiutils.h16
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/channel.c17
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/dma.c15
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c3
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.c87
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c22
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c140
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/pmu.c172
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/pmu.h3
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/pub.h2
-rw-r--r--drivers/net/wireless/brcm80211/include/soc.h62
-rw-r--r--drivers/net/wireless/iwlegacy/3945-rs.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/commands.h40
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/debugfs.c6
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/dev.h16
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/main.c56
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/scan.c37
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/ucode.c37
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-devtrace.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h27
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/internal.h3
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/rx.c3
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c36
-rw-r--r--drivers/net/wireless/iwmc3200wifi/Kconfig39
-rw-r--r--drivers/net/wireless/iwmc3200wifi/Makefile10
-rw-r--r--drivers/net/wireless/iwmc3200wifi/bus.h57
-rw-r--r--drivers/net/wireless/iwmc3200wifi/cfg80211.c882
-rw-r--r--drivers/net/wireless/iwmc3200wifi/cfg80211.h31
-rw-r--r--drivers/net/wireless/iwmc3200wifi/commands.c1002
-rw-r--r--drivers/net/wireless/iwmc3200wifi/commands.h509
-rw-r--r--drivers/net/wireless/iwmc3200wifi/debug.h123
-rw-r--r--drivers/net/wireless/iwmc3200wifi/debugfs.c488
-rw-r--r--drivers/net/wireless/iwmc3200wifi/eeprom.c234
-rw-r--r--drivers/net/wireless/iwmc3200wifi/eeprom.h127
-rw-r--r--drivers/net/wireless/iwmc3200wifi/fw.c416
-rw-r--r--drivers/net/wireless/iwmc3200wifi/fw.h100
-rw-r--r--drivers/net/wireless/iwmc3200wifi/hal.c470
-rw-r--r--drivers/net/wireless/iwmc3200wifi/hal.h237
-rw-r--r--drivers/net/wireless/iwmc3200wifi/iwm.h367
-rw-r--r--drivers/net/wireless/iwmc3200wifi/lmac.h484
-rw-r--r--drivers/net/wireless/iwmc3200wifi/main.c847
-rw-r--r--drivers/net/wireless/iwmc3200wifi/netdev.c191
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.c1701
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.h60
-rw-r--r--drivers/net/wireless/iwmc3200wifi/sdio.c509
-rw-r--r--drivers/net/wireless/iwmc3200wifi/sdio.h64
-rw-r--r--drivers/net/wireless/iwmc3200wifi/trace.c3
-rw-r--r--drivers/net/wireless/iwmc3200wifi/trace.h283
-rw-r--r--drivers/net/wireless/iwmc3200wifi/tx.c529
-rw-r--r--drivers/net/wireless/iwmc3200wifi/umac.h789
-rw-r--r--drivers/net/wireless/libertas/host.h1
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c12
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c76
-rw-r--r--drivers/net/wireless/mwifiex/fw.h21
-rw-r--r--drivers/net/wireless/mwifiex/ie.c185
-rw-r--r--drivers/net/wireless/mwifiex/ioctl.h5
-rw-r--r--drivers/net/wireless/mwifiex/main.h2
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c37
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c30
-rw-r--r--drivers/net/wireless/p54/txrx.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c29
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c10
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h5
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c20
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c26
-rw-r--r--drivers/net/wireless/ti/wl12xx/wl12xx.h14
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c27
-rw-r--r--drivers/net/wireless/ti/wl18xx/wl18xx.h7
-rw-r--r--drivers/net/wireless/ti/wlcore/boot.c55
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c22
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.h6
-rw-r--r--drivers/net/wireless/ti/wlcore/init.c16
-rw-r--r--drivers/net/wireless/ti/wlcore/io.c6
-rw-r--r--drivers/net/wireless/ti/wlcore/io.h13
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c77
-rw-r--r--drivers/net/wireless/ti/wlcore/scan.c11
-rw-r--r--drivers/net/wireless/ti/wlcore/sdio.c6
-rw-r--r--drivers/net/wireless/ti/wlcore/spi.c6
-rw-r--r--drivers/net/wireless/ti/wlcore/testmode.c13
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h25
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore_i.h16
128 files changed, 2633 insertions, 12976 deletions
diff --git a/drivers/net/wimax/i2400m/Kconfig b/drivers/net/wimax/i2400m/Kconfig
index 672de18a776c..71453db14258 100644
--- a/drivers/net/wimax/i2400m/Kconfig
+++ b/drivers/net/wimax/i2400m/Kconfig
@@ -7,9 +7,6 @@ config WIMAX_I2400M
7comment "Enable USB support to see WiMAX USB drivers" 7comment "Enable USB support to see WiMAX USB drivers"
8 depends on USB = n 8 depends on USB = n
9 9
10comment "Enable MMC support to see WiMAX SDIO drivers"
11 depends on MMC = n
12
13config WIMAX_I2400M_USB 10config WIMAX_I2400M_USB
14 tristate "Intel Wireless WiMAX Connection 2400 over USB (including 5x50)" 11 tristate "Intel Wireless WiMAX Connection 2400 over USB (including 5x50)"
15 depends on WIMAX && USB 12 depends on WIMAX && USB
@@ -21,25 +18,6 @@ config WIMAX_I2400M_USB
21 18
22 If unsure, it is safe to select M (module). 19 If unsure, it is safe to select M (module).
23 20
24config WIMAX_I2400M_SDIO
25 tristate "Intel Wireless WiMAX Connection 2400 over SDIO"
26 depends on WIMAX && MMC
27 select WIMAX_I2400M
28 help
29 Select if you have a device based on the Intel WiMAX
30 Connection 2400 over SDIO.
31
32 If unsure, it is safe to select M (module).
33
34config WIMAX_IWMC3200_SDIO
35 bool "Intel Wireless Multicom WiMAX Connection 3200 over SDIO (EXPERIMENTAL)"
36 depends on WIMAX_I2400M_SDIO
37 depends on EXPERIMENTAL
38 select IWMC3200TOP
39 help
40 Select if you have a device based on the Intel Multicom WiMAX
41 Connection 3200 over SDIO.
42
43config WIMAX_I2400M_DEBUG_LEVEL 21config WIMAX_I2400M_DEBUG_LEVEL
44 int "WiMAX i2400m debug level" 22 int "WiMAX i2400m debug level"
45 depends on WIMAX_I2400M 23 depends on WIMAX_I2400M
diff --git a/drivers/net/wimax/i2400m/Makefile b/drivers/net/wimax/i2400m/Makefile
index 5d9e018d31af..f6d19c348082 100644
--- a/drivers/net/wimax/i2400m/Makefile
+++ b/drivers/net/wimax/i2400m/Makefile
@@ -1,7 +1,6 @@
1 1
2obj-$(CONFIG_WIMAX_I2400M) += i2400m.o 2obj-$(CONFIG_WIMAX_I2400M) += i2400m.o
3obj-$(CONFIG_WIMAX_I2400M_USB) += i2400m-usb.o 3obj-$(CONFIG_WIMAX_I2400M_USB) += i2400m-usb.o
4obj-$(CONFIG_WIMAX_I2400M_SDIO) += i2400m-sdio.o
5 4
6i2400m-y := \ 5i2400m-y := \
7 control.o \ 6 control.o \
@@ -21,10 +20,3 @@ i2400m-usb-y := \
21 usb-tx.o \ 20 usb-tx.o \
22 usb-rx.o \ 21 usb-rx.o \
23 usb.o 22 usb.o
24
25
26i2400m-sdio-y := \
27 sdio.o \
28 sdio-tx.o \
29 sdio-fw.o \
30 sdio-rx.o
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c
index 47cae7150bc1..850b8bc38bee 100644
--- a/drivers/net/wimax/i2400m/driver.c
+++ b/drivers/net/wimax/i2400m/driver.c
@@ -754,8 +754,7 @@ EXPORT_SYMBOL_GPL(i2400m_error_recovery);
754/* 754/*
755 * Alloc the command and ack buffers for boot mode 755 * Alloc the command and ack buffers for boot mode
756 * 756 *
757 * Get the buffers needed to deal with boot mode messages. These 757 * Get the buffers needed to deal with boot mode messages.
758 * buffers need to be allocated before the sdio receive irq is setup.
759 */ 758 */
760static 759static
761int i2400m_bm_buf_alloc(struct i2400m *i2400m) 760int i2400m_bm_buf_alloc(struct i2400m *i2400m)
diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c
index d09e44970e63..283237f6f074 100644
--- a/drivers/net/wimax/i2400m/fw.c
+++ b/drivers/net/wimax/i2400m/fw.c
@@ -51,8 +51,7 @@
51 * firmware. Normal hardware takes only signed firmware. 51 * firmware. Normal hardware takes only signed firmware.
52 * 52 *
53 * On boot mode, in USB, we write to the device using the bulk out 53 * On boot mode, in USB, we write to the device using the bulk out
54 * endpoint and read from it in the notification endpoint. In SDIO we 54 * endpoint and read from it in the notification endpoint.
55 * talk to it via the write address and read from the read address.
56 * 55 *
57 * Upon entrance to boot mode, the device sends (preceded with a few 56 * Upon entrance to boot mode, the device sends (preceded with a few
58 * zero length packets (ZLPs) on the notification endpoint in USB) a 57 * zero length packets (ZLPs) on the notification endpoint in USB) a
diff --git a/drivers/net/wimax/i2400m/i2400m-sdio.h b/drivers/net/wimax/i2400m/i2400m-sdio.h
deleted file mode 100644
index 1d63ffdedfde..000000000000
--- a/drivers/net/wimax/i2400m/i2400m-sdio.h
+++ /dev/null
@@ -1,157 +0,0 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * SDIO-specific i2400m driver definitions
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Brian Bian <brian.bian@intel.com>
37 * Dirk Brandewie <dirk.j.brandewie@intel.com>
38 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
39 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
40 * - Initial implementation
41 *
42 *
43 * This driver implements the bus-specific part of the i2400m for
44 * SDIO. Check i2400m.h for a generic driver description.
45 *
46 * ARCHITECTURE
47 *
48 * This driver sits under the bus-generic i2400m driver, providing the
49 * connection to the device.
50 *
51 * When probed, all the function pointers are setup and then the
52 * bus-generic code called. The generic driver will then use the
53 * provided pointers for uploading firmware (i2400ms_bus_bm*() in
54 * sdio-fw.c) and then setting up the device (i2400ms_dev_*() in
55 * sdio.c).
56 *
57 * Once firmware is uploaded, TX functions (sdio-tx.c) are called when
58 * data is ready for transmission in the TX fifo; then the SDIO IRQ is
59 * fired and data is available (sdio-rx.c), it is sent to the generic
60 * driver for processing with i2400m_rx.
61 */
62
63#ifndef __I2400M_SDIO_H__
64#define __I2400M_SDIO_H__
65
66#include "i2400m.h"
67
68/* Host-Device interface for SDIO */
69enum {
70 I2400M_SDIO_BOOT_RETRIES = 3,
71 I2400MS_BLK_SIZE = 256,
72 I2400MS_PL_SIZE_MAX = 0x3E00,
73
74 I2400MS_DATA_ADDR = 0x0,
75 I2400MS_INTR_STATUS_ADDR = 0x13,
76 I2400MS_INTR_CLEAR_ADDR = 0x13,
77 I2400MS_INTR_ENABLE_ADDR = 0x14,
78 I2400MS_INTR_GET_SIZE_ADDR = 0x2C,
79 /* The number of ticks to wait for the device to signal that
80 * it is ready */
81 I2400MS_INIT_SLEEP_INTERVAL = 100,
82 /* How long to wait for the device to settle after reset */
83 I2400MS_SETTLE_TIME = 40,
84 /* The number of msec to wait for IOR after sending IOE */
85 IWMC3200_IOR_TIMEOUT = 10,
86};
87
88
89/**
90 * struct i2400ms - descriptor for a SDIO connected i2400m
91 *
92 * @i2400m: bus-generic i2400m implementation; has to be first (see
93 * it's documentation in i2400m.h).
94 *
95 * @func: pointer to our SDIO function
96 *
97 * @tx_worker: workqueue struct used to TX data when the bus-generic
98 * code signals packets are pending for transmission to the device.
99 *
100 * @tx_workqueue: workqeueue used for data TX; we don't use the
101 * system's workqueue as that might cause deadlocks with code in
102 * the bus-generic driver. The read/write operation to the queue
103 * is protected with spinlock (tx_lock in struct i2400m) to avoid
104 * the queue being destroyed in the middle of a the queue read/write
105 * operation.
106 *
107 * @debugfs_dentry: dentry for the SDIO specific debugfs files
108 *
109 * Note this value is set to NULL upon destruction; this is
110 * because some routinges use it to determine if we are inside the
111 * probe() path or some other path. When debugfs is disabled,
112 * creation sets the dentry to '(void*) -ENODEV', which is valid
113 * for the test.
114 */
115struct i2400ms {
116 struct i2400m i2400m; /* FIRST! See doc */
117 struct sdio_func *func;
118
119 struct work_struct tx_worker;
120 struct workqueue_struct *tx_workqueue;
121 char tx_wq_name[32];
122
123 struct dentry *debugfs_dentry;
124
125 wait_queue_head_t bm_wfa_wq;
126 int bm_wait_result;
127 size_t bm_ack_size;
128
129 /* Device is any of the iwmc3200 SKUs */
130 unsigned iwmc3200:1;
131};
132
133
134static inline
135void i2400ms_init(struct i2400ms *i2400ms)
136{
137 i2400m_init(&i2400ms->i2400m);
138}
139
140
141extern int i2400ms_rx_setup(struct i2400ms *);
142extern void i2400ms_rx_release(struct i2400ms *);
143
144extern int i2400ms_tx_setup(struct i2400ms *);
145extern void i2400ms_tx_release(struct i2400ms *);
146extern void i2400ms_bus_tx_kick(struct i2400m *);
147
148extern ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *,
149 const struct i2400m_bootrom_header *,
150 size_t, int);
151extern ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *,
152 struct i2400m_bootrom_header *,
153 size_t);
154extern void i2400ms_bus_bm_release(struct i2400m *);
155extern int i2400ms_bus_bm_setup(struct i2400m *);
156
157#endif /* #ifndef __I2400M_SDIO_H__ */
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h
index c806d4550212..79c6505b5c20 100644
--- a/drivers/net/wimax/i2400m/i2400m.h
+++ b/drivers/net/wimax/i2400m/i2400m.h
@@ -46,7 +46,7 @@
46 * - bus generic driver (this part) 46 * - bus generic driver (this part)
47 * 47 *
48 * The bus specific driver sets up stuff specific to the bus the 48 * The bus specific driver sets up stuff specific to the bus the
49 * device is connected to (USB, SDIO, PCI, tam-tam...non-authoritative 49 * device is connected to (USB, PCI, tam-tam...non-authoritative
50 * nor binding list) which is basically the device-model management 50 * nor binding list) which is basically the device-model management
51 * (probe/disconnect, etc), moving data from device to kernel and 51 * (probe/disconnect, etc), moving data from device to kernel and
52 * back, doing the power saving details and reseting the device. 52 * back, doing the power saving details and reseting the device.
@@ -238,14 +238,13 @@ struct i2400m_barker_db;
238 * amount needed for loading firmware, where us dev_start/stop setup 238 * amount needed for loading firmware, where us dev_start/stop setup
239 * the rest needed to do full data/control traffic. 239 * the rest needed to do full data/control traffic.
240 * 240 *
241 * @bus_tx_block_size: [fill] SDIO imposes a 256 block size, USB 16, 241 * @bus_tx_block_size: [fill] USB imposes a 16 block size, but other
242 * so we have a tx_blk_size variable that the bus layer sets to 242 * busses will differ. So we have a tx_blk_size variable that the
243 * tell the engine how much of that we need. 243 * bus layer sets to tell the engine how much of that we need.
244 * 244 *
245 * @bus_tx_room_min: [fill] Minimum room required while allocating 245 * @bus_tx_room_min: [fill] Minimum room required while allocating
246 * TX queue's buffer space for message header. SDIO requires 246 * TX queue's buffer space for message header. USB requires
247 * 224 bytes and USB 16 bytes. Refer bus specific driver code 247 * 16 bytes. Refer to bus specific driver code for details.
248 * for details.
249 * 248 *
250 * @bus_pl_size_max: [fill] Maximum payload size. 249 * @bus_pl_size_max: [fill] Maximum payload size.
251 * 250 *
diff --git a/drivers/net/wimax/i2400m/sdio-debug-levels.h b/drivers/net/wimax/i2400m/sdio-debug-levels.h
deleted file mode 100644
index c51998741301..000000000000
--- a/drivers/net/wimax/i2400m/sdio-debug-levels.h
+++ /dev/null
@@ -1,22 +0,0 @@
1/*
2 * debug levels control file for the i2400m module's
3 */
4#ifndef __debug_levels__h__
5#define __debug_levels__h__
6
7/* Maximum compile and run time debug level for all submodules */
8#define D_MODULENAME i2400m_sdio
9#define D_MASTER CONFIG_WIMAX_I2400M_DEBUG_LEVEL
10
11#include <linux/wimax/debug.h>
12
13/* List of all the enabled modules */
14enum d_module {
15 D_SUBMODULE_DECLARE(main),
16 D_SUBMODULE_DECLARE(tx),
17 D_SUBMODULE_DECLARE(rx),
18 D_SUBMODULE_DECLARE(fw)
19};
20
21
22#endif /* #ifndef __debug_levels__h__ */
diff --git a/drivers/net/wimax/i2400m/sdio-fw.c b/drivers/net/wimax/i2400m/sdio-fw.c
deleted file mode 100644
index 8e025418f5be..000000000000
--- a/drivers/net/wimax/i2400m/sdio-fw.c
+++ /dev/null
@@ -1,210 +0,0 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Firmware uploader's SDIO specifics
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
37 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
38 * - Initial implementation
39 *
40 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
41 * - Bus generic/specific split for USB
42 *
43 * Dirk Brandewie <dirk.j.brandewie@intel.com>
44 * - Initial implementation for SDIO
45 *
46 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
47 * - SDIO rehash for changes in the bus-driver model
48 *
49 * Dirk Brandewie <dirk.j.brandewie@intel.com>
50 * - Make it IRQ based, not polling
51 *
52 * THE PROCEDURE
53 *
54 * See fw.c for the generic description of this procedure.
55 *
56 * This file implements only the SDIO specifics. It boils down to how
57 * to send a command and waiting for an acknowledgement from the
58 * device.
59 *
60 * All this code is sequential -- all i2400ms_bus_bm_*() functions are
61 * executed in the same thread, except i2400ms_bm_irq() [on its own by
62 * the SDIO driver]. This makes it possible to avoid locking.
63 *
64 * COMMAND EXECUTION
65 *
66 * The generic firmware upload code will call i2400m_bus_bm_cmd_send()
67 * to send commands.
68 *
69 * The SDIO devices expects things in 256 byte blocks, so it will pad
70 * it, compute the checksum (if needed) and pass it to SDIO.
71 *
72 * ACK RECEPTION
73 *
74 * This works in IRQ mode -- the fw loader says when to wait for data
75 * and for that it calls i2400ms_bus_bm_wait_for_ack().
76 *
77 * This checks if there is any data available (RX size > 0); if not,
78 * waits for the IRQ handler to notify about it. Once there is data,
79 * it is read and passed to the caller. Doing it this way we don't
80 * need much coordination/locking, and it makes it much more difficult
81 * for an interrupt to be lost and the wait_for_ack() function getting
82 * stuck even when data is pending.
83 */
84#include <linux/mmc/sdio_func.h>
85#include "i2400m-sdio.h"
86
87
88#define D_SUBMODULE fw
89#include "sdio-debug-levels.h"
90
91
92/*
93 * Send a boot-mode command to the SDIO function
94 *
95 * We use a bounce buffer (i2400m->bm_cmd_buf) because we need to
96 * touch the header if the RAW flag is not set.
97 *
98 * @flags: pass thru from i2400m_bm_cmd()
99 * @return: cmd_size if ok, < 0 errno code on error.
100 *
101 * Note the command is padded to the SDIO block size for the device.
102 */
103ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *i2400m,
104 const struct i2400m_bootrom_header *_cmd,
105 size_t cmd_size, int flags)
106{
107 ssize_t result;
108 struct device *dev = i2400m_dev(i2400m);
109 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
110 int opcode = _cmd == NULL ? -1 : i2400m_brh_get_opcode(_cmd);
111 struct i2400m_bootrom_header *cmd;
112 /* SDIO restriction */
113 size_t cmd_size_a = ALIGN(cmd_size, I2400MS_BLK_SIZE);
114
115 d_fnstart(5, dev, "(i2400m %p cmd %p size %zu)\n",
116 i2400m, _cmd, cmd_size);
117 result = -E2BIG;
118 if (cmd_size > I2400M_BM_CMD_BUF_SIZE)
119 goto error_too_big;
120
121 if (_cmd != i2400m->bm_cmd_buf)
122 memmove(i2400m->bm_cmd_buf, _cmd, cmd_size);
123 cmd = i2400m->bm_cmd_buf;
124 if (cmd_size_a > cmd_size) /* Zero pad space */
125 memset(i2400m->bm_cmd_buf + cmd_size, 0, cmd_size_a - cmd_size);
126 if ((flags & I2400M_BM_CMD_RAW) == 0) {
127 if (WARN_ON(i2400m_brh_get_response_required(cmd) == 0))
128 dev_warn(dev, "SW BUG: response_required == 0\n");
129 i2400m_bm_cmd_prepare(cmd);
130 }
131 d_printf(4, dev, "BM cmd %d: %zu bytes (%zu padded)\n",
132 opcode, cmd_size, cmd_size_a);
133 d_dump(5, dev, cmd, cmd_size);
134
135 sdio_claim_host(i2400ms->func); /* Send & check */
136 result = sdio_memcpy_toio(i2400ms->func, I2400MS_DATA_ADDR,
137 i2400m->bm_cmd_buf, cmd_size_a);
138 sdio_release_host(i2400ms->func);
139 if (result < 0) {
140 dev_err(dev, "BM cmd %d: cannot send: %ld\n",
141 opcode, (long) result);
142 goto error_cmd_send;
143 }
144 result = cmd_size;
145error_cmd_send:
146error_too_big:
147 d_fnend(5, dev, "(i2400m %p cmd %p size %zu) = %d\n",
148 i2400m, _cmd, cmd_size, (int) result);
149 return result;
150}
151
152
153/*
154 * Read an ack from the device's boot-mode
155 *
156 * @i2400m:
157 * @_ack: pointer to where to store the read data
158 * @ack_size: how many bytes we should read
159 *
160 * Returns: < 0 errno code on error; otherwise, amount of received bytes.
161 *
162 * The ACK for a BM command is always at least sizeof(*ack) bytes, so
163 * check for that. We don't need to check for device reboots
164 *
165 */
166ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *i2400m,
167 struct i2400m_bootrom_header *ack,
168 size_t ack_size)
169{
170 ssize_t result;
171 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
172 struct sdio_func *func = i2400ms->func;
173 struct device *dev = &func->dev;
174 int size;
175
176 BUG_ON(sizeof(*ack) > ack_size);
177
178 d_fnstart(5, dev, "(i2400m %p ack %p size %zu)\n",
179 i2400m, ack, ack_size);
180
181 result = wait_event_timeout(i2400ms->bm_wfa_wq,
182 i2400ms->bm_ack_size != -EINPROGRESS,
183 2 * HZ);
184 if (result == 0) {
185 result = -ETIMEDOUT;
186 dev_err(dev, "BM: error waiting for an ack\n");
187 goto error_timeout;
188 }
189
190 spin_lock(&i2400m->rx_lock);
191 result = i2400ms->bm_ack_size;
192 BUG_ON(result == -EINPROGRESS);
193 if (result < 0) /* so we exit when rx_release() is called */
194 dev_err(dev, "BM: %s failed: %zd\n", __func__, result);
195 else {
196 size = min(ack_size, i2400ms->bm_ack_size);
197 memcpy(ack, i2400m->bm_ack_buf, size);
198 }
199 /*
200 * Remember always to clear the bm_ack_size to -EINPROGRESS
201 * after the RX data is processed
202 */
203 i2400ms->bm_ack_size = -EINPROGRESS;
204 spin_unlock(&i2400m->rx_lock);
205
206error_timeout:
207 d_fnend(5, dev, "(i2400m %p ack %p size %zu) = %zd\n",
208 i2400m, ack, ack_size, result);
209 return result;
210}
diff --git a/drivers/net/wimax/i2400m/sdio-rx.c b/drivers/net/wimax/i2400m/sdio-rx.c
deleted file mode 100644
index fb6396dd115f..000000000000
--- a/drivers/net/wimax/i2400m/sdio-rx.c
+++ /dev/null
@@ -1,301 +0,0 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * SDIO RX handling
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Dirk Brandewie <dirk.j.brandewie@intel.com>
37 * - Initial implementation
38 *
39 *
40 * This handles the RX path on SDIO.
41 *
42 * The SDIO bus driver calls the "irq" routine when data is available.
43 * This is not a traditional interrupt routine since the SDIO bus
44 * driver calls us from its irq thread context. Because of this
45 * sleeping in the SDIO RX IRQ routine is okay.
46 *
47 * From there on, we obtain the size of the data that is available,
48 * allocate an skb, copy it and then pass it to the generic driver's
49 * RX routine [i2400m_rx()].
50 *
51 * ROADMAP
52 *
53 * i2400ms_irq()
54 * i2400ms_rx()
55 * __i2400ms_rx_get_size()
56 * i2400m_is_boot_barker()
57 * i2400m_rx()
58 *
59 * i2400ms_rx_setup()
60 *
61 * i2400ms_rx_release()
62 */
63#include <linux/workqueue.h>
64#include <linux/wait.h>
65#include <linux/skbuff.h>
66#include <linux/mmc/sdio.h>
67#include <linux/mmc/sdio_func.h>
68#include <linux/slab.h>
69#include "i2400m-sdio.h"
70
71#define D_SUBMODULE rx
72#include "sdio-debug-levels.h"
73
74static const __le32 i2400m_ACK_BARKER[4] = {
75 __constant_cpu_to_le32(I2400M_ACK_BARKER),
76 __constant_cpu_to_le32(I2400M_ACK_BARKER),
77 __constant_cpu_to_le32(I2400M_ACK_BARKER),
78 __constant_cpu_to_le32(I2400M_ACK_BARKER)
79};
80
81
82/*
83 * Read and return the amount of bytes available for RX
84 *
85 * The RX size has to be read like this: byte reads of three
86 * sequential locations; then glue'em together.
87 *
88 * sdio_readl() doesn't work.
89 */
90static ssize_t __i2400ms_rx_get_size(struct i2400ms *i2400ms)
91{
92 int ret, cnt, val;
93 ssize_t rx_size;
94 unsigned xfer_size_addr;
95 struct sdio_func *func = i2400ms->func;
96 struct device *dev = &i2400ms->func->dev;
97
98 d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms);
99 xfer_size_addr = I2400MS_INTR_GET_SIZE_ADDR;
100 rx_size = 0;
101 for (cnt = 0; cnt < 3; cnt++) {
102 val = sdio_readb(func, xfer_size_addr + cnt, &ret);
103 if (ret < 0) {
104 dev_err(dev, "RX: Can't read byte %d of RX size from "
105 "0x%08x: %d\n", cnt, xfer_size_addr + cnt, ret);
106 rx_size = ret;
107 goto error_read;
108 }
109 rx_size = rx_size << 8 | (val & 0xff);
110 }
111 d_printf(6, dev, "RX: rx_size is %ld\n", (long) rx_size);
112error_read:
113 d_fnend(7, dev, "(i2400ms %p) = %ld\n", i2400ms, (long) rx_size);
114 return rx_size;
115}
116
117
118/*
119 * Read data from the device (when in normal)
120 *
121 * Allocate an SKB of the right size, read the data in and then
122 * deliver it to the generic layer.
123 *
124 * We also check for a reboot barker. That means the device died and
125 * we have to reboot it.
126 */
127static
128void i2400ms_rx(struct i2400ms *i2400ms)
129{
130 int ret;
131 struct sdio_func *func = i2400ms->func;
132 struct device *dev = &func->dev;
133 struct i2400m *i2400m = &i2400ms->i2400m;
134 struct sk_buff *skb;
135 ssize_t rx_size;
136
137 d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms);
138 rx_size = __i2400ms_rx_get_size(i2400ms);
139 if (rx_size < 0) {
140 ret = rx_size;
141 goto error_get_size;
142 }
143 /*
144 * Hardware quirk: make sure to clear the INTR status register
145 * AFTER getting the data transfer size.
146 */
147 sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret);
148
149 ret = -ENOMEM;
150 skb = alloc_skb(rx_size, GFP_ATOMIC);
151 if (NULL == skb) {
152 dev_err(dev, "RX: unable to alloc skb\n");
153 goto error_alloc_skb;
154 }
155 ret = sdio_memcpy_fromio(func, skb->data,
156 I2400MS_DATA_ADDR, rx_size);
157 if (ret < 0) {
158 dev_err(dev, "RX: SDIO data read failed: %d\n", ret);
159 goto error_memcpy_fromio;
160 }
161
162 rmb(); /* make sure we get boot_mode from dev_reset_handle */
163 if (unlikely(i2400m->boot_mode == 1)) {
164 spin_lock(&i2400m->rx_lock);
165 i2400ms->bm_ack_size = rx_size;
166 spin_unlock(&i2400m->rx_lock);
167 memcpy(i2400m->bm_ack_buf, skb->data, rx_size);
168 wake_up(&i2400ms->bm_wfa_wq);
169 d_printf(5, dev, "RX: SDIO boot mode message\n");
170 kfree_skb(skb);
171 goto out;
172 }
173 ret = -EIO;
174 if (unlikely(rx_size < sizeof(__le32))) {
175 dev_err(dev, "HW BUG? only %zu bytes received\n", rx_size);
176 goto error_bad_size;
177 }
178 if (likely(i2400m_is_d2h_barker(skb->data))) {
179 skb_put(skb, rx_size);
180 i2400m_rx(i2400m, skb);
181 } else if (unlikely(i2400m_is_boot_barker(i2400m,
182 skb->data, rx_size))) {
183 ret = i2400m_dev_reset_handle(i2400m, "device rebooted");
184 dev_err(dev, "RX: SDIO reboot barker\n");
185 kfree_skb(skb);
186 } else {
187 i2400m_unknown_barker(i2400m, skb->data, rx_size);
188 kfree_skb(skb);
189 }
190out:
191 d_fnend(7, dev, "(i2400ms %p) = void\n", i2400ms);
192 return;
193
194error_memcpy_fromio:
195 kfree_skb(skb);
196error_alloc_skb:
197error_get_size:
198error_bad_size:
199 d_fnend(7, dev, "(i2400ms %p) = %d\n", i2400ms, ret);
200}
201
202
203/*
204 * Process an interrupt from the SDIO card
205 *
206 * FIXME: need to process other events that are not just ready-to-read
207 *
208 * Checks there is data ready and then proceeds to read it.
209 */
210static
211void i2400ms_irq(struct sdio_func *func)
212{
213 int ret;
214 struct i2400ms *i2400ms = sdio_get_drvdata(func);
215 struct device *dev = &func->dev;
216 int val;
217
218 d_fnstart(6, dev, "(i2400ms %p)\n", i2400ms);
219 val = sdio_readb(func, I2400MS_INTR_STATUS_ADDR, &ret);
220 if (ret < 0) {
221 dev_err(dev, "RX: Can't read interrupt status: %d\n", ret);
222 goto error_no_irq;
223 }
224 if (!val) {
225 dev_err(dev, "RX: BUG? got IRQ but no interrupt ready?\n");
226 goto error_no_irq;
227 }
228 i2400ms_rx(i2400ms);
229error_no_irq:
230 d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms);
231}
232
233
234/*
235 * Setup SDIO RX
236 *
237 * Hooks up the IRQ handler and then enables IRQs.
238 */
239int i2400ms_rx_setup(struct i2400ms *i2400ms)
240{
241 int result;
242 struct sdio_func *func = i2400ms->func;
243 struct device *dev = &func->dev;
244 struct i2400m *i2400m = &i2400ms->i2400m;
245
246 d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
247
248 init_waitqueue_head(&i2400ms->bm_wfa_wq);
249 spin_lock(&i2400m->rx_lock);
250 i2400ms->bm_wait_result = -EINPROGRESS;
251 /*
252 * Before we are about to enable the RX interrupt, make sure
253 * bm_ack_size is cleared to -EINPROGRESS which indicates
254 * no RX interrupt happened yet or the previous interrupt
255 * has been handled, we are ready to take the new interrupt
256 */
257 i2400ms->bm_ack_size = -EINPROGRESS;
258 spin_unlock(&i2400m->rx_lock);
259
260 sdio_claim_host(func);
261 result = sdio_claim_irq(func, i2400ms_irq);
262 if (result < 0) {
263 dev_err(dev, "Cannot claim IRQ: %d\n", result);
264 goto error_irq_claim;
265 }
266 result = 0;
267 sdio_writeb(func, 1, I2400MS_INTR_ENABLE_ADDR, &result);
268 if (result < 0) {
269 sdio_release_irq(func);
270 dev_err(dev, "Failed to enable interrupts %d\n", result);
271 }
272error_irq_claim:
273 sdio_release_host(func);
274 d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
275 return result;
276}
277
278
279/*
280 * Tear down SDIO RX
281 *
282 * Disables IRQs in the device and removes the IRQ handler.
283 */
284void i2400ms_rx_release(struct i2400ms *i2400ms)
285{
286 int result;
287 struct sdio_func *func = i2400ms->func;
288 struct device *dev = &func->dev;
289 struct i2400m *i2400m = &i2400ms->i2400m;
290
291 d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
292 spin_lock(&i2400m->rx_lock);
293 i2400ms->bm_ack_size = -EINTR;
294 spin_unlock(&i2400m->rx_lock);
295 wake_up_all(&i2400ms->bm_wfa_wq);
296 sdio_claim_host(func);
297 sdio_writeb(func, 0, I2400MS_INTR_ENABLE_ADDR, &result);
298 sdio_release_irq(func);
299 sdio_release_host(func);
300 d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
301}
diff --git a/drivers/net/wimax/i2400m/sdio-tx.c b/drivers/net/wimax/i2400m/sdio-tx.c
deleted file mode 100644
index b53cd1c80e3e..000000000000
--- a/drivers/net/wimax/i2400m/sdio-tx.c
+++ /dev/null
@@ -1,177 +0,0 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * SDIO TX transaction backends
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Dirk Brandewie <dirk.j.brandewie@intel.com>
37 * - Initial implementation
38 *
39 *
40 * Takes the TX messages in the i2400m's driver TX FIFO and sends them
41 * to the device until there are no more.
42 *
43 * If we fail sending the message, we just drop it. There isn't much
44 * we can do at this point. Most of the traffic is network, which has
45 * recovery methods for dropped packets.
46 *
47 * The SDIO functions are not atomic, so we can't run from the context
48 * where i2400m->bus_tx_kick() [i2400ms_bus_tx_kick()] is being called
49 * (some times atomic). Thus, the actual TX work is deferred to a
50 * workqueue.
51 *
52 * ROADMAP
53 *
54 * i2400ms_bus_tx_kick()
55 * i2400ms_tx_submit() [through workqueue]
56 *
57 * i2400m_tx_setup()
58 *
59 * i2400m_tx_release()
60 */
61#include <linux/mmc/sdio_func.h>
62#include "i2400m-sdio.h"
63
64#define D_SUBMODULE tx
65#include "sdio-debug-levels.h"
66
67
68/*
69 * Pull TX transations from the TX FIFO and send them to the device
70 * until there are no more.
71 */
72static
73void i2400ms_tx_submit(struct work_struct *ws)
74{
75 int result;
76 struct i2400ms *i2400ms = container_of(ws, struct i2400ms, tx_worker);
77 struct i2400m *i2400m = &i2400ms->i2400m;
78 struct sdio_func *func = i2400ms->func;
79 struct device *dev = &func->dev;
80 struct i2400m_msg_hdr *tx_msg;
81 size_t tx_msg_size;
82
83 d_fnstart(4, dev, "(i2400ms %p, i2400m %p)\n", i2400ms, i2400ms);
84
85 while (NULL != (tx_msg = i2400m_tx_msg_get(i2400m, &tx_msg_size))) {
86 d_printf(2, dev, "TX: submitting %zu bytes\n", tx_msg_size);
87 d_dump(5, dev, tx_msg, tx_msg_size);
88
89 sdio_claim_host(func);
90 result = sdio_memcpy_toio(func, 0, tx_msg, tx_msg_size);
91 sdio_release_host(func);
92
93 i2400m_tx_msg_sent(i2400m);
94
95 if (result < 0) {
96 dev_err(dev, "TX: cannot submit TX; tx_msg @%zu %zu B:"
97 " %d\n", (void *) tx_msg - i2400m->tx_buf,
98 tx_msg_size, result);
99 }
100
101 if (result == -ETIMEDOUT) {
102 i2400m_error_recovery(i2400m);
103 break;
104 }
105 d_printf(2, dev, "TX: %zub submitted\n", tx_msg_size);
106 }
107
108 d_fnend(4, dev, "(i2400ms %p) = void\n", i2400ms);
109}
110
111
112/*
113 * The generic driver notifies us that there is data ready for TX
114 *
115 * Schedule a run of i2400ms_tx_submit() to handle it.
116 */
117void i2400ms_bus_tx_kick(struct i2400m *i2400m)
118{
119 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
120 struct device *dev = &i2400ms->func->dev;
121 unsigned long flags;
122
123 d_fnstart(3, dev, "(i2400m %p) = void\n", i2400m);
124
125 /* schedule tx work, this is because tx may block, therefore
126 * it has to run in a thread context.
127 */
128 spin_lock_irqsave(&i2400m->tx_lock, flags);
129 if (i2400ms->tx_workqueue != NULL)
130 queue_work(i2400ms->tx_workqueue, &i2400ms->tx_worker);
131 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
132
133 d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
134}
135
136int i2400ms_tx_setup(struct i2400ms *i2400ms)
137{
138 int result;
139 struct device *dev = &i2400ms->func->dev;
140 struct i2400m *i2400m = &i2400ms->i2400m;
141 struct workqueue_struct *tx_workqueue;
142 unsigned long flags;
143
144 d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
145
146 INIT_WORK(&i2400ms->tx_worker, i2400ms_tx_submit);
147 snprintf(i2400ms->tx_wq_name, sizeof(i2400ms->tx_wq_name),
148 "%s-tx", i2400m->wimax_dev.name);
149 tx_workqueue =
150 create_singlethread_workqueue(i2400ms->tx_wq_name);
151 if (tx_workqueue == NULL) {
152 dev_err(dev, "TX: failed to create workqueue\n");
153 result = -ENOMEM;
154 } else
155 result = 0;
156 spin_lock_irqsave(&i2400m->tx_lock, flags);
157 i2400ms->tx_workqueue = tx_workqueue;
158 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
159 d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
160 return result;
161}
162
163void i2400ms_tx_release(struct i2400ms *i2400ms)
164{
165 struct i2400m *i2400m = &i2400ms->i2400m;
166 struct workqueue_struct *tx_workqueue;
167 unsigned long flags;
168
169 tx_workqueue = i2400ms->tx_workqueue;
170
171 spin_lock_irqsave(&i2400m->tx_lock, flags);
172 i2400ms->tx_workqueue = NULL;
173 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
174
175 if (tx_workqueue)
176 destroy_workqueue(tx_workqueue);
177}
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c
deleted file mode 100644
index 21a9edd6e75d..000000000000
--- a/drivers/net/wimax/i2400m/sdio.c
+++ /dev/null
@@ -1,602 +0,0 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Linux driver model glue for the SDIO device, reset & fw upload
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com>
7 * Dirk Brandewie <dirk.j.brandewie@intel.com>
8 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
9 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License version
13 * 2 as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 * 02110-1301, USA.
24 *
25 *
26 * See i2400m-sdio.h for a general description of this driver.
27 *
28 * This file implements driver model glue, and hook ups for the
29 * generic driver to implement the bus-specific functions (device
30 * communication setup/tear down, firmware upload and resetting).
31 *
32 * ROADMAP
33 *
34 * i2400m_probe()
35 * alloc_netdev()
36 * i2400ms_netdev_setup()
37 * i2400ms_init()
38 * i2400m_netdev_setup()
39 * i2400ms_enable_function()
40 * i2400m_setup()
41 *
42 * i2400m_remove()
43 * i2400m_release()
44 * free_netdev(net_dev)
45 *
46 * i2400ms_bus_reset() Called by i2400m_reset
47 * __i2400ms_reset()
48 * __i2400ms_send_barker()
49 */
50
51#include <linux/slab.h>
52#include <linux/debugfs.h>
53#include <linux/mmc/sdio_ids.h>
54#include <linux/mmc/sdio.h>
55#include <linux/mmc/sdio_func.h>
56#include "i2400m-sdio.h"
57#include <linux/wimax/i2400m.h>
58#include <linux/module.h>
59
60#define D_SUBMODULE main
61#include "sdio-debug-levels.h"
62
63/* IOE WiMAX function timeout in seconds */
64static int ioe_timeout = 2;
65module_param(ioe_timeout, int, 0);
66
67static char i2400ms_debug_params[128];
68module_param_string(debug, i2400ms_debug_params, sizeof(i2400ms_debug_params),
69 0644);
70MODULE_PARM_DESC(debug,
71 "String of space-separated NAME:VALUE pairs, where NAMEs "
72 "are the different debug submodules and VALUE are the "
73 "initial debug value to set.");
74
75/* Our firmware file name list */
76static const char *i2400ms_bus_fw_names[] = {
77#define I2400MS_FW_FILE_NAME "i2400m-fw-sdio-1.3.sbcf"
78 I2400MS_FW_FILE_NAME,
79 NULL
80};
81
82
83static const struct i2400m_poke_table i2400ms_pokes[] = {
84 I2400M_FW_POKE(0x6BE260, 0x00000088),
85 I2400M_FW_POKE(0x080550, 0x00000005),
86 I2400M_FW_POKE(0xAE0000, 0x00000000),
87 I2400M_FW_POKE(0x000000, 0x00000000), /* MUST be 0 terminated or bad
88 * things will happen */
89};
90
91/*
92 * Enable the SDIO function
93 *
94 * Tries to enable the SDIO function; might fail if it is still not
95 * ready (in some hardware, the SDIO WiMAX function is only enabled
96 * when we ask it to explicitly doing). Tries until a timeout is
97 * reached.
98 *
99 * The @maxtries argument indicates how many times (at most) it should
100 * be tried to enable the function. 0 means forever. This acts along
101 * with the timeout (ie: it'll stop trying as soon as the maximum
102 * number of tries is reached _or_ as soon as the timeout is reached).
103 *
104 * The reverse of this is...sdio_disable_function()
105 *
106 * Returns: 0 if the SDIO function was enabled, < 0 errno code on
107 * error (-ENODEV when it was unable to enable the function).
108 */
109static
110int i2400ms_enable_function(struct i2400ms *i2400ms, unsigned maxtries)
111{
112 struct sdio_func *func = i2400ms->func;
113 u64 timeout;
114 int err;
115 struct device *dev = &func->dev;
116 unsigned tries = 0;
117
118 d_fnstart(3, dev, "(func %p)\n", func);
119 /* Setup timeout (FIXME: This needs to read the CIS table to
120 * get a real timeout) and then wait for the device to signal
121 * it is ready */
122 timeout = get_jiffies_64() + ioe_timeout * HZ;
123 err = -ENODEV;
124 while (err != 0 && time_before64(get_jiffies_64(), timeout)) {
125 sdio_claim_host(func);
126 /*
127 * There is a sillicon bug on the IWMC3200, where the
128 * IOE timeout will cause problems on Moorestown
129 * platforms (system hang). We explicitly overwrite
130 * func->enable_timeout here to work around the issue.
131 */
132 if (i2400ms->iwmc3200)
133 func->enable_timeout = IWMC3200_IOR_TIMEOUT;
134 err = sdio_enable_func(func);
135 if (0 == err) {
136 sdio_release_host(func);
137 d_printf(2, dev, "SDIO function enabled\n");
138 goto function_enabled;
139 }
140 d_printf(2, dev, "SDIO function failed to enable: %d\n", err);
141 sdio_release_host(func);
142 if (maxtries > 0 && ++tries >= maxtries) {
143 err = -ETIME;
144 break;
145 }
146 msleep(I2400MS_INIT_SLEEP_INTERVAL);
147 }
148 /* If timed out, device is not there yet -- get -ENODEV so
149 * the device driver core will retry later on. */
150 if (err == -ETIME) {
151 dev_err(dev, "Can't enable WiMAX function; "
152 " has the function been enabled?\n");
153 err = -ENODEV;
154 }
155function_enabled:
156 d_fnend(3, dev, "(func %p) = %d\n", func, err);
157 return err;
158}
159
160
161/*
162 * Setup minimal device communication infrastructure needed to at
163 * least be able to update the firmware.
164 *
165 * Note the ugly trick: if we are in the probe path
166 * (i2400ms->debugfs_dentry == NULL), we only retry function
167 * enablement one, to avoid racing with the iwmc3200 top controller.
168 */
169static
170int i2400ms_bus_setup(struct i2400m *i2400m)
171{
172 int result;
173 struct i2400ms *i2400ms =
174 container_of(i2400m, struct i2400ms, i2400m);
175 struct device *dev = i2400m_dev(i2400m);
176 struct sdio_func *func = i2400ms->func;
177 int retries;
178
179 sdio_claim_host(func);
180 result = sdio_set_block_size(func, I2400MS_BLK_SIZE);
181 sdio_release_host(func);
182 if (result < 0) {
183 dev_err(dev, "Failed to set block size: %d\n", result);
184 goto error_set_blk_size;
185 }
186
187 if (i2400ms->iwmc3200 && i2400ms->debugfs_dentry == NULL)
188 retries = 1;
189 else
190 retries = 0;
191 result = i2400ms_enable_function(i2400ms, retries);
192 if (result < 0) {
193 dev_err(dev, "Cannot enable SDIO function: %d\n", result);
194 goto error_func_enable;
195 }
196
197 result = i2400ms_tx_setup(i2400ms);
198 if (result < 0)
199 goto error_tx_setup;
200 result = i2400ms_rx_setup(i2400ms);
201 if (result < 0)
202 goto error_rx_setup;
203 return 0;
204
205error_rx_setup:
206 i2400ms_tx_release(i2400ms);
207error_tx_setup:
208 sdio_claim_host(func);
209 sdio_disable_func(func);
210 sdio_release_host(func);
211error_func_enable:
212error_set_blk_size:
213 return result;
214}
215
216
217/*
218 * Tear down minimal device communication infrastructure needed to at
219 * least be able to update the firmware.
220 */
221static
222void i2400ms_bus_release(struct i2400m *i2400m)
223{
224 struct i2400ms *i2400ms =
225 container_of(i2400m, struct i2400ms, i2400m);
226 struct sdio_func *func = i2400ms->func;
227
228 i2400ms_rx_release(i2400ms);
229 i2400ms_tx_release(i2400ms);
230 sdio_claim_host(func);
231 sdio_disable_func(func);
232 sdio_release_host(func);
233}
234
235
236/*
237 * Setup driver resources needed to communicate with the device
238 *
239 * The fw needs some time to settle, and it was just uploaded,
240 * so give it a break first. I'd prefer to just wait for the device to
241 * send something, but seems the poking we do to enable SDIO stuff
242 * interferes with it, so just give it a break before starting...
243 */
244static
245int i2400ms_bus_dev_start(struct i2400m *i2400m)
246{
247 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
248 struct sdio_func *func = i2400ms->func;
249 struct device *dev = &func->dev;
250
251 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
252 msleep(200);
253 d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, 0);
254 return 0;
255}
256
257
258/*
259 * Sends a barker buffer to the device
260 *
261 * This helper will allocate a kmalloced buffer and use it to transmit
262 * (then free it). Reason for this is that the SDIO host controller
263 * expects alignment (unknown exactly which) which the stack won't
264 * really provide and certain arches/host-controller combinations
265 * cannot use stack/vmalloc/text areas for DMA transfers.
266 */
267static
268int __i2400ms_send_barker(struct i2400ms *i2400ms,
269 const __le32 *barker, size_t barker_size)
270{
271 int ret;
272 struct sdio_func *func = i2400ms->func;
273 struct device *dev = &func->dev;
274 void *buffer;
275
276 ret = -ENOMEM;
277 buffer = kmalloc(I2400MS_BLK_SIZE, GFP_KERNEL);
278 if (buffer == NULL)
279 goto error_kzalloc;
280
281 memcpy(buffer, barker, barker_size);
282 sdio_claim_host(func);
283 ret = sdio_memcpy_toio(func, 0, buffer, I2400MS_BLK_SIZE);
284 sdio_release_host(func);
285
286 if (ret < 0)
287 d_printf(0, dev, "E: barker error: %d\n", ret);
288
289 kfree(buffer);
290error_kzalloc:
291 return ret;
292}
293
294
295/*
296 * Reset a device at different levels (warm, cold or bus)
297 *
298 * @i2400ms: device descriptor
299 * @reset_type: soft, warm or bus reset (I2400M_RT_WARM/SOFT/BUS)
300 *
301 * FIXME: not tested -- need to confirm expected effects
302 *
303 * Warm and cold resets get an SDIO reset if they fail (unimplemented)
304 *
305 * Warm reset:
306 *
307 * The device will be fully reset internally, but won't be
308 * disconnected from the bus (so no reenumeration will
309 * happen). Firmware upload will be necessary.
310 *
311 * The device will send a reboot barker that will trigger the driver
312 * to reinitialize the state via __i2400m_dev_reset_handle.
313 *
314 *
315 * Cold and bus reset:
316 *
317 * The device will be fully reset internally, disconnected from the
318 * bus an a reenumeration will happen. Firmware upload will be
319 * necessary. Thus, we don't do any locking or struct
320 * reinitialization, as we are going to be fully disconnected and
321 * reenumerated.
322 *
323 * Note we need to return -ENODEV if a warm reset was requested and we
324 * had to resort to a bus reset. See i2400m_op_reset(), wimax_reset()
325 * and wimax_dev->op_reset.
326 *
327 * WARNING: no driver state saved/fixed
328 */
329static
330int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt)
331{
332 int result = 0;
333 struct i2400ms *i2400ms =
334 container_of(i2400m, struct i2400ms, i2400m);
335 struct device *dev = i2400m_dev(i2400m);
336 static const __le32 i2400m_WARM_BOOT_BARKER[4] = {
337 cpu_to_le32(I2400M_WARM_RESET_BARKER),
338 cpu_to_le32(I2400M_WARM_RESET_BARKER),
339 cpu_to_le32(I2400M_WARM_RESET_BARKER),
340 cpu_to_le32(I2400M_WARM_RESET_BARKER),
341 };
342 static const __le32 i2400m_COLD_BOOT_BARKER[4] = {
343 cpu_to_le32(I2400M_COLD_RESET_BARKER),
344 cpu_to_le32(I2400M_COLD_RESET_BARKER),
345 cpu_to_le32(I2400M_COLD_RESET_BARKER),
346 cpu_to_le32(I2400M_COLD_RESET_BARKER),
347 };
348
349 if (rt == I2400M_RT_WARM)
350 result = __i2400ms_send_barker(i2400ms, i2400m_WARM_BOOT_BARKER,
351 sizeof(i2400m_WARM_BOOT_BARKER));
352 else if (rt == I2400M_RT_COLD)
353 result = __i2400ms_send_barker(i2400ms, i2400m_COLD_BOOT_BARKER,
354 sizeof(i2400m_COLD_BOOT_BARKER));
355 else if (rt == I2400M_RT_BUS) {
356do_bus_reset:
357
358 i2400ms_bus_release(i2400m);
359
360 /* Wait for the device to settle */
361 msleep(40);
362
363 result = i2400ms_bus_setup(i2400m);
364 } else
365 BUG();
366 if (result < 0 && rt != I2400M_RT_BUS) {
367 dev_err(dev, "%s reset failed (%d); trying SDIO reset\n",
368 rt == I2400M_RT_WARM ? "warm" : "cold", result);
369 rt = I2400M_RT_BUS;
370 goto do_bus_reset;
371 }
372 return result;
373}
374
375
376static
377void i2400ms_netdev_setup(struct net_device *net_dev)
378{
379 struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
380 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
381 i2400ms_init(i2400ms);
382 i2400m_netdev_setup(net_dev);
383}
384
385
386/*
387 * Debug levels control; see debug.h
388 */
389struct d_level D_LEVEL[] = {
390 D_SUBMODULE_DEFINE(main),
391 D_SUBMODULE_DEFINE(tx),
392 D_SUBMODULE_DEFINE(rx),
393 D_SUBMODULE_DEFINE(fw),
394};
395size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL);
396
397
398#define __debugfs_register(prefix, name, parent) \
399do { \
400 result = d_level_register_debugfs(prefix, name, parent); \
401 if (result < 0) \
402 goto error; \
403} while (0)
404
405
406static
407int i2400ms_debugfs_add(struct i2400ms *i2400ms)
408{
409 int result;
410 struct dentry *dentry = i2400ms->i2400m.wimax_dev.debugfs_dentry;
411
412 dentry = debugfs_create_dir("i2400m-sdio", dentry);
413 result = PTR_ERR(dentry);
414 if (IS_ERR(dentry)) {
415 if (result == -ENODEV)
416 result = 0; /* No debugfs support */
417 goto error;
418 }
419 i2400ms->debugfs_dentry = dentry;
420 __debugfs_register("dl_", main, dentry);
421 __debugfs_register("dl_", tx, dentry);
422 __debugfs_register("dl_", rx, dentry);
423 __debugfs_register("dl_", fw, dentry);
424
425 return 0;
426
427error:
428 debugfs_remove_recursive(i2400ms->debugfs_dentry);
429 i2400ms->debugfs_dentry = NULL;
430 return result;
431}
432
433
434static struct device_type i2400ms_type = {
435 .name = "wimax",
436};
437
438/*
439 * Probe a i2400m interface and register it
440 *
441 * @func: SDIO function
442 * @id: SDIO device ID
443 * @returns: 0 if ok, < 0 errno code on error.
444 *
445 * Alloc a net device, initialize the bus-specific details and then
446 * calls the bus-generic initialization routine. That will register
447 * the wimax and netdev devices, upload the firmware [using
448 * _bus_bm_*()], call _bus_dev_start() to finalize the setup of the
449 * communication with the device and then will start to talk to it to
450 * finnish setting it up.
451 *
452 * Initialization is tricky; some instances of the hw are packed with
453 * others in a way that requires a third driver that enables the WiMAX
454 * function. In those cases, we can't enable the SDIO function and
455 * we'll return with -ENODEV. When the driver that enables the WiMAX
456 * function does its thing, it has to do a bus_rescan_devices() on the
457 * SDIO bus so this driver is called again to enumerate the WiMAX
458 * function.
459 */
460static
461int i2400ms_probe(struct sdio_func *func,
462 const struct sdio_device_id *id)
463{
464 int result;
465 struct net_device *net_dev;
466 struct device *dev = &func->dev;
467 struct i2400m *i2400m;
468 struct i2400ms *i2400ms;
469
470 /* Allocate instance [calls i2400m_netdev_setup() on it]. */
471 result = -ENOMEM;
472 net_dev = alloc_netdev(sizeof(*i2400ms), "wmx%d",
473 i2400ms_netdev_setup);
474 if (net_dev == NULL) {
475 dev_err(dev, "no memory for network device instance\n");
476 goto error_alloc_netdev;
477 }
478 SET_NETDEV_DEV(net_dev, dev);
479 SET_NETDEV_DEVTYPE(net_dev, &i2400ms_type);
480 i2400m = net_dev_to_i2400m(net_dev);
481 i2400ms = container_of(i2400m, struct i2400ms, i2400m);
482 i2400m->wimax_dev.net_dev = net_dev;
483 i2400ms->func = func;
484 sdio_set_drvdata(func, i2400ms);
485
486 i2400m->bus_tx_block_size = I2400MS_BLK_SIZE;
487 /*
488 * Room required in the TX queue for SDIO message to accommodate
489 * a smallest payload while allocating header space is 224 bytes,
490 * which is the smallest message size(the block size 256 bytes)
491 * minus the smallest message header size(32 bytes).
492 */
493 i2400m->bus_tx_room_min = I2400MS_BLK_SIZE - I2400M_PL_ALIGN * 2;
494 i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX;
495 i2400m->bus_setup = i2400ms_bus_setup;
496 i2400m->bus_dev_start = i2400ms_bus_dev_start;
497 i2400m->bus_dev_stop = NULL;
498 i2400m->bus_release = i2400ms_bus_release;
499 i2400m->bus_tx_kick = i2400ms_bus_tx_kick;
500 i2400m->bus_reset = i2400ms_bus_reset;
501 /* The iwmc3200-wimax sometimes requires the driver to try
502 * hard when we paint it into a corner. */
503 i2400m->bus_bm_retries = I2400M_SDIO_BOOT_RETRIES;
504 i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send;
505 i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack;
506 i2400m->bus_fw_names = i2400ms_bus_fw_names;
507 i2400m->bus_bm_mac_addr_impaired = 1;
508 i2400m->bus_bm_pokes_table = &i2400ms_pokes[0];
509
510 switch (func->device) {
511 case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX:
512 case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5:
513 i2400ms->iwmc3200 = 1;
514 break;
515 default:
516 i2400ms->iwmc3200 = 0;
517 }
518
519 result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT);
520 if (result < 0) {
521 dev_err(dev, "cannot setup device: %d\n", result);
522 goto error_setup;
523 }
524
525 result = i2400ms_debugfs_add(i2400ms);
526 if (result < 0) {
527 dev_err(dev, "cannot create SDIO debugfs: %d\n",
528 result);
529 goto error_debugfs_add;
530 }
531 return 0;
532
533error_debugfs_add:
534 i2400m_release(i2400m);
535error_setup:
536 sdio_set_drvdata(func, NULL);
537 free_netdev(net_dev);
538error_alloc_netdev:
539 return result;
540}
541
542
543static
544void i2400ms_remove(struct sdio_func *func)
545{
546 struct device *dev = &func->dev;
547 struct i2400ms *i2400ms = sdio_get_drvdata(func);
548 struct i2400m *i2400m = &i2400ms->i2400m;
549 struct net_device *net_dev = i2400m->wimax_dev.net_dev;
550
551 d_fnstart(3, dev, "SDIO func %p\n", func);
552 debugfs_remove_recursive(i2400ms->debugfs_dentry);
553 i2400ms->debugfs_dentry = NULL;
554 i2400m_release(i2400m);
555 sdio_set_drvdata(func, NULL);
556 free_netdev(net_dev);
557 d_fnend(3, dev, "SDIO func %p\n", func);
558}
559
560static
561const struct sdio_device_id i2400ms_sdio_ids[] = {
562 /* Intel: i2400m WiMAX (iwmc3200) over SDIO */
563 { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL,
564 SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX) },
565 { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL,
566 SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5) },
567 { /* end: all zeroes */ },
568};
569MODULE_DEVICE_TABLE(sdio, i2400ms_sdio_ids);
570
571
572static
573struct sdio_driver i2400m_sdio_driver = {
574 .name = KBUILD_MODNAME,
575 .probe = i2400ms_probe,
576 .remove = i2400ms_remove,
577 .id_table = i2400ms_sdio_ids,
578};
579
580
581static
582int __init i2400ms_driver_init(void)
583{
584 d_parse_params(D_LEVEL, D_LEVEL_SIZE, i2400ms_debug_params,
585 "i2400m_sdio.debug");
586 return sdio_register_driver(&i2400m_sdio_driver);
587}
588module_init(i2400ms_driver_init);
589
590
591static
592void __exit i2400ms_driver_exit(void)
593{
594 sdio_unregister_driver(&i2400m_sdio_driver);
595}
596module_exit(i2400ms_driver_exit);
597
598
599MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>");
600MODULE_DESCRIPTION("Intel 2400M WiMAX networking for SDIO");
601MODULE_LICENSE("GPL");
602MODULE_FIRMWARE(I2400MS_FW_FILE_NAME);
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 5f58fa53238c..6deaae18db57 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -276,7 +276,6 @@ source "drivers/net/wireless/hostap/Kconfig"
276source "drivers/net/wireless/ipw2x00/Kconfig" 276source "drivers/net/wireless/ipw2x00/Kconfig"
277source "drivers/net/wireless/iwlwifi/Kconfig" 277source "drivers/net/wireless/iwlwifi/Kconfig"
278source "drivers/net/wireless/iwlegacy/Kconfig" 278source "drivers/net/wireless/iwlegacy/Kconfig"
279source "drivers/net/wireless/iwmc3200wifi/Kconfig"
280source "drivers/net/wireless/libertas/Kconfig" 279source "drivers/net/wireless/libertas/Kconfig"
281source "drivers/net/wireless/orinoco/Kconfig" 280source "drivers/net/wireless/orinoco/Kconfig"
282source "drivers/net/wireless/p54/Kconfig" 281source "drivers/net/wireless/p54/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 0ce218b931d4..062dfdff6364 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -53,8 +53,6 @@ obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
53 53
54obj-$(CONFIG_WL_TI) += ti/ 54obj-$(CONFIG_WL_TI) += ti/
55 55
56obj-$(CONFIG_IWM) += iwmc3200wifi/
57
58obj-$(CONFIG_MWIFIEX) += mwifiex/ 56obj-$(CONFIG_MWIFIEX) += mwifiex/
59 57
60obj-$(CONFIG_BRCMFMAC) += brcm80211/ 58obj-$(CONFIG_BRCMFMAC) += brcm80211/
diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig
index e18a9aa7b6ca..338c5c42357d 100644
--- a/drivers/net/wireless/ath/ath5k/Kconfig
+++ b/drivers/net/wireless/ath/ath5k/Kconfig
@@ -64,3 +64,11 @@ config ATH5K_PCI
64 ---help--- 64 ---help---
65 This adds support for PCI type chipsets of the 5xxx Atheros 65 This adds support for PCI type chipsets of the 5xxx Atheros
66 family. 66 family.
67
68config ATH5K_TEST_CHANNELS
69 bool "Enables testing channels on ath5k"
70 depends on ATH5K && CFG80211_CERTIFICATION_ONUS
71 ---help---
72 This enables non-standard IEEE 802.11 channels on ath5k, which
73 can be used for research purposes. This option should be disabled
74 unless doing research.
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 44ad6fe0278f..8c4c040a47b8 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -74,10 +74,6 @@ bool ath5k_modparam_nohwcrypt;
74module_param_named(nohwcrypt, ath5k_modparam_nohwcrypt, bool, S_IRUGO); 74module_param_named(nohwcrypt, ath5k_modparam_nohwcrypt, bool, S_IRUGO);
75MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); 75MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
76 76
77static bool modparam_all_channels;
78module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO);
79MODULE_PARM_DESC(all_channels, "Expose all channels the device can use.");
80
81static bool modparam_fastchanswitch; 77static bool modparam_fastchanswitch;
82module_param_named(fastchanswitch, modparam_fastchanswitch, bool, S_IRUGO); 78module_param_named(fastchanswitch, modparam_fastchanswitch, bool, S_IRUGO);
83MODULE_PARM_DESC(fastchanswitch, "Enable fast channel switching for AR2413/AR5413 radios."); 79MODULE_PARM_DESC(fastchanswitch, "Enable fast channel switching for AR2413/AR5413 radios.");
@@ -258,8 +254,15 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re
258\********************/ 254\********************/
259 255
260/* 256/*
261 * Returns true for the channel numbers used without all_channels modparam. 257 * Returns true for the channel numbers used.
262 */ 258 */
259#ifdef CONFIG_ATH5K_TEST_CHANNELS
260static bool ath5k_is_standard_channel(short chan, enum ieee80211_band band)
261{
262 return true;
263}
264
265#else
263static bool ath5k_is_standard_channel(short chan, enum ieee80211_band band) 266static bool ath5k_is_standard_channel(short chan, enum ieee80211_band band)
264{ 267{
265 if (band == IEEE80211_BAND_2GHZ && chan <= 14) 268 if (band == IEEE80211_BAND_2GHZ && chan <= 14)
@@ -276,6 +279,7 @@ static bool ath5k_is_standard_channel(short chan, enum ieee80211_band band)
276 /* 802.11j 4.9GHz (20MHz) */ 279 /* 802.11j 4.9GHz (20MHz) */
277 (chan == 184 || chan == 188 || chan == 192 || chan == 196)); 280 (chan == 184 || chan == 188 || chan == 192 || chan == 196));
278} 281}
282#endif
279 283
280static unsigned int 284static unsigned int
281ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels, 285ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
@@ -316,8 +320,7 @@ ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
316 if (!ath5k_channel_ok(ah, &channels[count])) 320 if (!ath5k_channel_ok(ah, &channels[count]))
317 continue; 321 continue;
318 322
319 if (!modparam_all_channels && 323 if (!ath5k_is_standard_channel(ch, band))
320 !ath5k_is_standard_channel(ch, band))
321 continue; 324 continue;
322 325
323 count++; 326 count++;
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index fd7dbd4609df..aca1d2689e90 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -3627,6 +3627,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
3627 wiphy->cipher_suites = cipher_suites; 3627 wiphy->cipher_suites = cipher_suites;
3628 wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 3628 wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
3629 3629
3630#ifdef CONFIG_PM
3630 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | 3631 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
3631 WIPHY_WOWLAN_DISCONNECT | 3632 WIPHY_WOWLAN_DISCONNECT |
3632 WIPHY_WOWLAN_GTK_REKEY_FAILURE | 3633 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
@@ -3636,6 +3637,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
3636 wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST; 3637 wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST;
3637 wiphy->wowlan.pattern_min_len = 1; 3638 wiphy->wowlan.pattern_min_len = 1;
3638 wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; 3639 wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE;
3640#endif
3639 3641
3640 wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS; 3642 wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS;
3641 3643
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 4a4e8a2b9d2c..3a69804f4c16 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -35,6 +35,10 @@ static const struct platform_device_id ath9k_platform_id_table[] = {
35 .name = "ar934x_wmac", 35 .name = "ar934x_wmac",
36 .driver_data = AR9300_DEVID_AR9340, 36 .driver_data = AR9300_DEVID_AR9340,
37 }, 37 },
38 {
39 .name = "qca955x_wmac",
40 .driver_data = AR9300_DEVID_QCA955X,
41 },
38 {}, 42 {},
39}; 43};
40 44
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index d7deb8c9f299..84b558d126ca 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -159,14 +159,11 @@ static bool ar9003_hw_calibrate(struct ath_hw *ah,
159 } 159 }
160 } 160 }
161 161
162 /* Do NF cal only at longer intervals */ 162 /*
163 if (longcal) { 163 * Do NF cal only at longer intervals. Get the value from
164 /* 164 * the previous NF cal and update history buffer.
165 * Get the value from the previous NF cal and update 165 */
166 * history buffer. 166 if (longcal && ath9k_hw_getnf(ah, chan)) {
167 */
168 ath9k_hw_getnf(ah, chan);
169
170 /* 167 /*
171 * Load the NF from history buffer of the current channel. 168 * Load the NF from history buffer of the current channel.
172 * NF is slow time-variant, so it is OK to use a historical 169 * NF is slow time-variant, so it is OK to use a historical
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index b1e59236d245..ab2bfcb3bed2 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -3509,7 +3509,7 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
3509 3509
3510 if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah)) 3510 if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
3511 REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias); 3511 REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
3512 else if (AR_SREV_9462(ah)) 3512 else if (AR_SREV_9462(ah) || AR_SREV_9550(ah))
3513 REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); 3513 REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
3514 else { 3514 else {
3515 REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); 3515 REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
@@ -3591,6 +3591,9 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
3591 if (AR_SREV_9462(ah)) { 3591 if (AR_SREV_9462(ah)) {
3592 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, 3592 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
3593 AR_SWITCH_TABLE_COM_AR9462_ALL, value); 3593 AR_SWITCH_TABLE_COM_AR9462_ALL, value);
3594 } else if (AR_SREV_9550(ah)) {
3595 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
3596 AR_SWITCH_TABLE_COM_AR9550_ALL, value);
3594 } else 3597 } else
3595 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, 3598 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
3596 AR_SWITCH_TABLE_COM_ALL, value); 3599 AR_SWITCH_TABLE_COM_ALL, value);
@@ -3957,7 +3960,7 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
3957 ar9003_hw_drive_strength_apply(ah); 3960 ar9003_hw_drive_strength_apply(ah);
3958 ar9003_hw_atten_apply(ah, chan); 3961 ar9003_hw_atten_apply(ah, chan);
3959 ar9003_hw_quick_drop_apply(ah, chan->channel); 3962 ar9003_hw_quick_drop_apply(ah, chan->channel);
3960 if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah)) 3963 if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) && !AR_SREV_9550(ah))
3961 ar9003_hw_internal_regulator_apply(ah); 3964 ar9003_hw_internal_regulator_apply(ah);
3962 if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah)) 3965 if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
3963 ar9003_hw_apply_tuning_caps(ah); 3966 ar9003_hw_apply_tuning_caps(ah);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index a0e3394b10dc..41e88c660e48 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -21,6 +21,7 @@
21#include "ar9340_initvals.h" 21#include "ar9340_initvals.h"
22#include "ar9330_1p1_initvals.h" 22#include "ar9330_1p1_initvals.h"
23#include "ar9330_1p2_initvals.h" 23#include "ar9330_1p2_initvals.h"
24#include "ar955x_1p0_initvals.h"
24#include "ar9580_1p0_initvals.h" 25#include "ar9580_1p0_initvals.h"
25#include "ar9462_2p0_initvals.h" 26#include "ar9462_2p0_initvals.h"
26 27
@@ -327,7 +328,61 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
327 328
328 INIT_INI_ARRAY(&ah->ini_japan2484, AR9462_BBC_TXIFR_COEFFJ, 329 INIT_INI_ARRAY(&ah->ini_japan2484, AR9462_BBC_TXIFR_COEFFJ,
329 ARRAY_SIZE(AR9462_BBC_TXIFR_COEFFJ), 2); 330 ARRAY_SIZE(AR9462_BBC_TXIFR_COEFFJ), 2);
331 } else if (AR_SREV_9550(ah)) {
332 /* mac */
333 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
334 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
335 ar955x_1p0_mac_core,
336 ARRAY_SIZE(ar955x_1p0_mac_core), 2);
337 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
338 ar955x_1p0_mac_postamble,
339 ARRAY_SIZE(ar955x_1p0_mac_postamble), 5);
340
341 /* bb */
342 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
343 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
344 ar955x_1p0_baseband_core,
345 ARRAY_SIZE(ar955x_1p0_baseband_core), 2);
346 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
347 ar955x_1p0_baseband_postamble,
348 ARRAY_SIZE(ar955x_1p0_baseband_postamble), 5);
349
350 /* radio */
351 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
352 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
353 ar955x_1p0_radio_core,
354 ARRAY_SIZE(ar955x_1p0_radio_core), 2);
355 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
356 ar955x_1p0_radio_postamble,
357 ARRAY_SIZE(ar955x_1p0_radio_postamble), 5);
358
359 /* soc */
360 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
361 ar955x_1p0_soc_preamble,
362 ARRAY_SIZE(ar955x_1p0_soc_preamble), 2);
363 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
364 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
365 ar955x_1p0_soc_postamble,
366 ARRAY_SIZE(ar955x_1p0_soc_postamble), 5);
330 367
368 /* rx/tx gain */
369 INIT_INI_ARRAY(&ah->iniModesRxGain,
370 ar955x_1p0_common_wo_xlna_rx_gain_table,
371 ARRAY_SIZE(ar955x_1p0_common_wo_xlna_rx_gain_table),
372 2);
373 INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
374 ar955x_1p0_common_wo_xlna_rx_gain_bounds,
375 ARRAY_SIZE(ar955x_1p0_common_wo_xlna_rx_gain_bounds),
376 5);
377 INIT_INI_ARRAY(&ah->iniModesTxGain,
378 ar955x_1p0_modes_xpa_tx_gain_table,
379 ARRAY_SIZE(ar955x_1p0_modes_xpa_tx_gain_table),
380 9);
381
382 /* Fast clock modal settings */
383 INIT_INI_ARRAY(&ah->iniModesFastClock,
384 ar955x_1p0_modes_fast_clock,
385 ARRAY_SIZE(ar955x_1p0_modes_fast_clock), 3);
331 } else if (AR_SREV_9580(ah)) { 386 } else if (AR_SREV_9580(ah)) {
332 /* mac */ 387 /* mac */
333 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); 388 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
@@ -470,6 +525,11 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah)
470 ar9485_modes_lowest_ob_db_tx_gain_1_1, 525 ar9485_modes_lowest_ob_db_tx_gain_1_1,
471 ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1), 526 ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
472 5); 527 5);
528 else if (AR_SREV_9550(ah))
529 INIT_INI_ARRAY(&ah->iniModesTxGain,
530 ar955x_1p0_modes_xpa_tx_gain_table,
531 ARRAY_SIZE(ar955x_1p0_modes_xpa_tx_gain_table),
532 9);
473 else if (AR_SREV_9580(ah)) 533 else if (AR_SREV_9580(ah))
474 INIT_INI_ARRAY(&ah->iniModesTxGain, 534 INIT_INI_ARRAY(&ah->iniModesTxGain,
475 ar9580_1p0_lowest_ob_db_tx_gain_table, 535 ar9580_1p0_lowest_ob_db_tx_gain_table,
@@ -514,6 +574,11 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah)
514 ar9580_1p0_high_ob_db_tx_gain_table, 574 ar9580_1p0_high_ob_db_tx_gain_table,
515 ARRAY_SIZE(ar9580_1p0_high_ob_db_tx_gain_table), 575 ARRAY_SIZE(ar9580_1p0_high_ob_db_tx_gain_table),
516 5); 576 5);
577 else if (AR_SREV_9550(ah))
578 INIT_INI_ARRAY(&ah->iniModesTxGain,
579 ar955x_1p0_modes_no_xpa_tx_gain_table,
580 ARRAY_SIZE(ar955x_1p0_modes_no_xpa_tx_gain_table),
581 9);
517 else if (AR_SREV_9462_20(ah)) 582 else if (AR_SREV_9462_20(ah))
518 INIT_INI_ARRAY(&ah->iniModesTxGain, 583 INIT_INI_ARRAY(&ah->iniModesTxGain,
519 ar9462_modes_high_ob_db_tx_gain_table_2p0, 584 ar9462_modes_high_ob_db_tx_gain_table_2p0,
@@ -635,7 +700,16 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah)
635 ar9485Common_wo_xlna_rx_gain_1_1, 700 ar9485Common_wo_xlna_rx_gain_1_1,
636 ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 701 ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
637 2); 702 2);
638 else if (AR_SREV_9580(ah)) 703 else if (AR_SREV_9550(ah)) {
704 INIT_INI_ARRAY(&ah->iniModesRxGain,
705 ar955x_1p0_common_rx_gain_table,
706 ARRAY_SIZE(ar955x_1p0_common_rx_gain_table),
707 2);
708 INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
709 ar955x_1p0_common_rx_gain_bounds,
710 ARRAY_SIZE(ar955x_1p0_common_rx_gain_bounds),
711 5);
712 } else if (AR_SREV_9580(ah))
639 INIT_INI_ARRAY(&ah->iniModesRxGain, 713 INIT_INI_ARRAY(&ah->iniModesRxGain,
640 ar9580_1p0_rx_gain_table, 714 ar9580_1p0_rx_gain_table,
641 ARRAY_SIZE(ar9580_1p0_rx_gain_table), 715 ARRAY_SIZE(ar9580_1p0_rx_gain_table),
@@ -679,7 +753,16 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah)
679 ar9462_common_wo_xlna_rx_gain_table_2p0, 753 ar9462_common_wo_xlna_rx_gain_table_2p0,
680 ARRAY_SIZE(ar9462_common_wo_xlna_rx_gain_table_2p0), 754 ARRAY_SIZE(ar9462_common_wo_xlna_rx_gain_table_2p0),
681 2); 755 2);
682 else if (AR_SREV_9580(ah)) 756 else if (AR_SREV_9550(ah)) {
757 INIT_INI_ARRAY(&ah->iniModesRxGain,
758 ar955x_1p0_common_wo_xlna_rx_gain_table,
759 ARRAY_SIZE(ar955x_1p0_common_wo_xlna_rx_gain_table),
760 2);
761 INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
762 ar955x_1p0_common_wo_xlna_rx_gain_bounds,
763 ARRAY_SIZE(ar955x_1p0_common_wo_xlna_rx_gain_bounds),
764 5);
765 } else if (AR_SREV_9580(ah))
683 INIT_INI_ARRAY(&ah->iniModesRxGain, 766 INIT_INI_ARRAY(&ah->iniModesRxGain,
684 ar9580_1p0_wo_xlna_rx_gain_table, 767 ar9580_1p0_wo_xlna_rx_gain_table,
685 ARRAY_SIZE(ar9580_1p0_wo_xlna_rx_gain_table), 768 ARRAY_SIZE(ar9580_1p0_wo_xlna_rx_gain_table),
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
index 61558375bfbf..9a34fcaae3ff 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
@@ -1015,12 +1015,9 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)
1015 return; 1015 return;
1016 1016
1017 if (mci->is_2g) { 1017 if (mci->is_2g) {
1018 if (!force) { 1018 ar9003_mci_send_2g5g_status(ah, true);
1019 ar9003_mci_send_2g5g_status(ah, true); 1019 ar9003_mci_send_lna_transfer(ah, true);
1020 1020 udelay(5);
1021 ar9003_mci_send_lna_transfer(ah, true);
1022 udelay(5);
1023 }
1024 1021
1025 REG_CLR_BIT(ah, AR_MCI_TX_CTRL, 1022 REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
1026 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 1023 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
@@ -1030,10 +1027,8 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)
1030 if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) 1027 if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
1031 ar9003_mci_osla_setup(ah, true); 1028 ar9003_mci_osla_setup(ah, true);
1032 } else { 1029 } else {
1033 if (!force) { 1030 ar9003_mci_send_lna_take(ah, true);
1034 ar9003_mci_send_lna_take(ah, true); 1031 udelay(5);
1035 udelay(5);
1036 }
1037 1032
1038 REG_SET_BIT(ah, AR_MCI_TX_CTRL, 1033 REG_SET_BIT(ah, AR_MCI_TX_CTRL,
1039 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 1034 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
@@ -1041,8 +1036,7 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)
1041 AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); 1036 AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
1042 1037
1043 ar9003_mci_osla_setup(ah, false); 1038 ar9003_mci_osla_setup(ah, false);
1044 if (!force) 1039 ar9003_mci_send_2g5g_status(ah, true);
1045 ar9003_mci_send_2g5g_status(ah, true);
1046 } 1040 }
1047} 1041}
1048 1042
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
index 3d400e8d6535..2c9f7d7ed4cc 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
@@ -211,7 +211,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
211 AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7); 211 AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7);
212 REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, 212 REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
213 AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1); 213 AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1);
214 if (AR_SREV_9485(ah) || AR_SREV_9462(ah)) 214 if (AR_SREV_9485(ah) || AR_SREV_9462(ah) || AR_SREV_9550(ah))
215 REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, 215 REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
216 AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, 216 AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
217 -3); 217 -3);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 6b91ebb158fe..d2346dbad6cd 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -99,7 +99,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
99 channelSel = (freq * 4) / 120; 99 channelSel = (freq * 4) / 120;
100 chan_frac = (((freq * 4) % 120) * 0x20000) / 120; 100 chan_frac = (((freq * 4) % 120) * 0x20000) / 120;
101 channelSel = (channelSel << 17) | chan_frac; 101 channelSel = (channelSel << 17) | chan_frac;
102 } else if (AR_SREV_9340(ah)) { 102 } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) {
103 if (ah->is_clk_25mhz) { 103 if (ah->is_clk_25mhz) {
104 u32 chan_frac; 104 u32 chan_frac;
105 105
@@ -113,7 +113,8 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
113 /* Set to 2G mode */ 113 /* Set to 2G mode */
114 bMode = 1; 114 bMode = 1;
115 } else { 115 } else {
116 if (AR_SREV_9340(ah) && ah->is_clk_25mhz) { 116 if ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) &&
117 ah->is_clk_25mhz) {
117 u32 chan_frac; 118 u32 chan_frac;
118 119
119 channelSel = (freq * 2) / 75; 120 channelSel = (freq * 2) / 75;
@@ -180,7 +181,8 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
180 * is out-of-band and can be ignored. 181 * is out-of-band and can be ignored.
181 */ 182 */
182 183
183 if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) { 184 if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) ||
185 AR_SREV_9550(ah)) {
184 if (spur_fbin_ptr[0] == 0) /* No spur */ 186 if (spur_fbin_ptr[0] == 0) /* No spur */
185 return; 187 return;
186 max_spur_cnts = 5; 188 max_spur_cnts = 5;
@@ -205,7 +207,8 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
205 if (AR_SREV_9462(ah) && (i == 0 || i == 3)) 207 if (AR_SREV_9462(ah) && (i == 0 || i == 3))
206 continue; 208 continue;
207 negative = 0; 209 negative = 0;
208 if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) 210 if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) ||
211 AR_SREV_9550(ah))
209 cur_bb_spur = ath9k_hw_fbin2freq(spur_fbin_ptr[i], 212 cur_bb_spur = ath9k_hw_fbin2freq(spur_fbin_ptr[i],
210 IS_CHAN_2GHZ(chan)); 213 IS_CHAN_2GHZ(chan));
211 else 214 else
@@ -618,6 +621,50 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah,
618 } 621 }
619} 622}
620 623
624static int ar9550_hw_get_modes_txgain_index(struct ath_hw *ah,
625 struct ath9k_channel *chan)
626{
627 int ret;
628
629 switch (chan->chanmode) {
630 case CHANNEL_A:
631 case CHANNEL_A_HT20:
632 if (chan->channel <= 5350)
633 ret = 1;
634 else if ((chan->channel > 5350) && (chan->channel <= 5600))
635 ret = 3;
636 else
637 ret = 5;
638 break;
639
640 case CHANNEL_A_HT40PLUS:
641 case CHANNEL_A_HT40MINUS:
642 if (chan->channel <= 5350)
643 ret = 2;
644 else if ((chan->channel > 5350) && (chan->channel <= 5600))
645 ret = 4;
646 else
647 ret = 6;
648 break;
649
650 case CHANNEL_G:
651 case CHANNEL_G_HT20:
652 case CHANNEL_B:
653 ret = 8;
654 break;
655
656 case CHANNEL_G_HT40PLUS:
657 case CHANNEL_G_HT40MINUS:
658 ret = 7;
659 break;
660
661 default:
662 ret = -EINVAL;
663 }
664
665 return ret;
666}
667
621static int ar9003_hw_process_ini(struct ath_hw *ah, 668static int ar9003_hw_process_ini(struct ath_hw *ah,
622 struct ath9k_channel *chan) 669 struct ath9k_channel *chan)
623{ 670{
@@ -659,7 +706,22 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
659 } 706 }
660 707
661 REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites); 708 REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites);
662 REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); 709 if (AR_SREV_9550(ah))
710 REG_WRITE_ARRAY(&ah->ini_modes_rx_gain_bounds, modesIndex,
711 regWrites);
712
713 if (AR_SREV_9550(ah)) {
714 int modes_txgain_index;
715
716 modes_txgain_index = ar9550_hw_get_modes_txgain_index(ah, chan);
717 if (modes_txgain_index < 0)
718 return -EINVAL;
719
720 REG_WRITE_ARRAY(&ah->iniModesTxGain, modes_txgain_index,
721 regWrites);
722 } else {
723 REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
724 }
663 725
664 /* 726 /*
665 * For 5GHz channels requiring Fast Clock, apply 727 * For 5GHz channels requiring Fast Clock, apply
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index ed662c3bae5b..751c83b21493 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -636,8 +636,8 @@
636 636
637#define AR_CH0_TOP (AR_SREV_9300(ah) ? 0x16288 : \ 637#define AR_CH0_TOP (AR_SREV_9300(ah) ? 0x16288 : \
638 ((AR_SREV_9462(ah) ? 0x1628c : 0x16280))) 638 ((AR_SREV_9462(ah) ? 0x1628c : 0x16280)))
639#define AR_CH0_TOP_XPABIASLVL (0x300) 639#define AR_CH0_TOP_XPABIASLVL (AR_SREV_9550(ah) ? 0x3c0 : 0x300)
640#define AR_CH0_TOP_XPABIASLVL_S (8) 640#define AR_CH0_TOP_XPABIASLVL_S (AR_SREV_9550(ah) ? 6 : 8)
641 641
642#define AR_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : \ 642#define AR_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : \
643 ((AR_SREV_9485(ah) ? 0x1628c : 0x16294))) 643 ((AR_SREV_9485(ah) ? 0x1628c : 0x16294)))
@@ -650,6 +650,8 @@
650#define AR_SWITCH_TABLE_COM_ALL_S (0) 650#define AR_SWITCH_TABLE_COM_ALL_S (0)
651#define AR_SWITCH_TABLE_COM_AR9462_ALL (0xffffff) 651#define AR_SWITCH_TABLE_COM_AR9462_ALL (0xffffff)
652#define AR_SWITCH_TABLE_COM_AR9462_ALL_S (0) 652#define AR_SWITCH_TABLE_COM_AR9462_ALL_S (0)
653#define AR_SWITCH_TABLE_COM_AR9550_ALL (0xffffff)
654#define AR_SWITCH_TABLE_COM_AR9550_ALL_S (0)
653#define AR_SWITCH_TABLE_COM_SPDT (0x00f00000) 655#define AR_SWITCH_TABLE_COM_SPDT (0x00f00000)
654#define AR_SWITCH_TABLE_COM_SPDT_ALL (0x0000fff0) 656#define AR_SWITCH_TABLE_COM_SPDT_ALL (0x0000fff0)
655#define AR_SWITCH_TABLE_COM_SPDT_ALL_S (4) 657#define AR_SWITCH_TABLE_COM_SPDT_ALL_S (4)
diff --git a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h
new file mode 100644
index 000000000000..df97f21c52dc
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h
@@ -0,0 +1,1284 @@
1/*
2 * Copyright (c) 2010-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#ifndef INITVALS_955X_1P0_H
19#define INITVALS_955X_1P0_H
20
21/* AR955X 1.0 */
22
23static const u32 ar955x_1p0_radio_postamble[][5] = {
24 /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
25 {0x00016098, 0xd2dd5554, 0xd2dd5554, 0xd28b3330, 0xd28b3330},
26 {0x0001609c, 0x0a566f3a, 0x0a566f3a, 0x06345f2a, 0x06345f2a},
27 {0x000160ac, 0xa4647c00, 0xa4647c00, 0xa4646800, 0xa4646800},
28 {0x000160b0, 0x01885f52, 0x01885f52, 0x04accf3a, 0x04accf3a},
29 {0x00016104, 0xb7a00001, 0xb7a00001, 0xb7a00001, 0xb7a00001},
30 {0x0001610c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000},
31 {0x00016140, 0x10804008, 0x10804008, 0x10804008, 0x10804008},
32 {0x00016504, 0xb7a00001, 0xb7a00001, 0xb7a00001, 0xb7a00001},
33 {0x0001650c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000},
34 {0x00016540, 0x10804008, 0x10804008, 0x10804008, 0x10804008},
35 {0x00016904, 0xb7a00001, 0xb7a00001, 0xb7a00001, 0xb7a00001},
36 {0x0001690c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000},
37 {0x00016940, 0x10804008, 0x10804008, 0x10804008, 0x10804008},
38};
39
40static const u32 ar955x_1p0_baseband_core_txfir_coeff_japan_2484[][2] = {
41 /* Addr allmodes */
42 {0x0000a398, 0x00000000},
43 {0x0000a39c, 0x6f7f0301},
44 {0x0000a3a0, 0xca9228ee},
45};
46
47static const u32 ar955x_1p0_baseband_postamble[][5] = {
48 /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
49 {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
50 {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
51 {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
52 {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
53 {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
54 {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
55 {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
56 {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
57 {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
58 {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
59 {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
60 {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
61 {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
62 {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
63 {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
64 {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
65 {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10822, 0xcfa10822},
66 {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
67 {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
68 {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
69 {0x0000a204, 0x005c0ec0, 0x005c0ec4, 0x005c0ec4, 0x005c0ec0},
70 {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
71 {0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f},
72 {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
73 {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
74 {0x0000a238, 0xffb01018, 0xffb01018, 0xffb01018, 0xffb01018},
75 {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
76 {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
77 {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
78 {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
79 {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
80 {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
81 {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
82 {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
83 {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
84 {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
85 {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
86 {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33},
87 {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982},
88 {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
89 {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
90 {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
91 {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
92 {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
93 {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
94 {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
95 {0x0000b284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
96 {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
97 {0x0000be04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
98 {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
99 {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
100 {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
101 {0x0000c284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
102};
103
104static const u32 ar955x_1p0_radio_core[][2] = {
105 /* Addr allmodes */
106 {0x00016000, 0x36db6db6},
107 {0x00016004, 0x6db6db40},
108 {0x00016008, 0x73f00000},
109 {0x0001600c, 0x00000000},
110 {0x00016040, 0x7f80fff8},
111 {0x0001604c, 0x76d005b5},
112 {0x00016050, 0x557cf031},
113 {0x00016054, 0x13449440},
114 {0x00016058, 0x0c51c92c},
115 {0x0001605c, 0x3db7fffc},
116 {0x00016060, 0xfffffffc},
117 {0x00016064, 0x000f0278},
118 {0x00016068, 0x6db6db6c},
119 {0x0001606c, 0x6db60000},
120 {0x00016080, 0x00080000},
121 {0x00016084, 0x0e48048c},
122 {0x00016088, 0x14214514},
123 {0x0001608c, 0x119f101e},
124 {0x00016090, 0x24926490},
125 {0x00016094, 0x00000000},
126 {0x000160a0, 0x0a108ffe},
127 {0x000160a4, 0x812fc370},
128 {0x000160a8, 0x423c8000},
129 {0x000160b4, 0x92480080},
130 {0x000160c0, 0x006db6d0},
131 {0x000160c4, 0x6db6db60},
132 {0x000160c8, 0x6db6db6c},
133 {0x000160cc, 0x01e6c000},
134 {0x00016100, 0x11999601},
135 {0x00016108, 0x00080010},
136 {0x00016144, 0x02084080},
137 {0x00016148, 0x000080c0},
138 {0x00016280, 0x01800804},
139 {0x00016284, 0x00038dc5},
140 {0x00016288, 0x00000000},
141 {0x0001628c, 0x00000040},
142 {0x00016380, 0x00000000},
143 {0x00016384, 0x00000000},
144 {0x00016388, 0x00400705},
145 {0x0001638c, 0x00800700},
146 {0x00016390, 0x00800700},
147 {0x00016394, 0x00000000},
148 {0x00016398, 0x00000000},
149 {0x0001639c, 0x00000000},
150 {0x000163a0, 0x00000001},
151 {0x000163a4, 0x00000001},
152 {0x000163a8, 0x00000000},
153 {0x000163ac, 0x00000000},
154 {0x000163b0, 0x00000000},
155 {0x000163b4, 0x00000000},
156 {0x000163b8, 0x00000000},
157 {0x000163bc, 0x00000000},
158 {0x000163c0, 0x000000a0},
159 {0x000163c4, 0x000c0000},
160 {0x000163c8, 0x14021402},
161 {0x000163cc, 0x00001402},
162 {0x000163d0, 0x00000000},
163 {0x000163d4, 0x00000000},
164 {0x00016400, 0x36db6db6},
165 {0x00016404, 0x6db6db40},
166 {0x00016408, 0x73f00000},
167 {0x0001640c, 0x00000000},
168 {0x00016440, 0x7f80fff8},
169 {0x0001644c, 0x76d005b5},
170 {0x00016450, 0x557cf031},
171 {0x00016454, 0x13449440},
172 {0x00016458, 0x0c51c92c},
173 {0x0001645c, 0x3db7fffc},
174 {0x00016460, 0xfffffffc},
175 {0x00016464, 0x000f0278},
176 {0x00016468, 0x6db6db6c},
177 {0x0001646c, 0x6db60000},
178 {0x00016500, 0x11999601},
179 {0x00016508, 0x00080010},
180 {0x00016544, 0x02084080},
181 {0x00016548, 0x000080c0},
182 {0x00016780, 0x00000000},
183 {0x00016784, 0x00000000},
184 {0x00016788, 0x00400705},
185 {0x0001678c, 0x00800700},
186 {0x00016790, 0x00800700},
187 {0x00016794, 0x00000000},
188 {0x00016798, 0x00000000},
189 {0x0001679c, 0x00000000},
190 {0x000167a0, 0x00000001},
191 {0x000167a4, 0x00000001},
192 {0x000167a8, 0x00000000},
193 {0x000167ac, 0x00000000},
194 {0x000167b0, 0x00000000},
195 {0x000167b4, 0x00000000},
196 {0x000167b8, 0x00000000},
197 {0x000167bc, 0x00000000},
198 {0x000167c0, 0x000000a0},
199 {0x000167c4, 0x000c0000},
200 {0x000167c8, 0x14021402},
201 {0x000167cc, 0x00001402},
202 {0x000167d0, 0x00000000},
203 {0x000167d4, 0x00000000},
204 {0x00016800, 0x36db6db6},
205 {0x00016804, 0x6db6db40},
206 {0x00016808, 0x73f00000},
207 {0x0001680c, 0x00000000},
208 {0x00016840, 0x7f80fff8},
209 {0x0001684c, 0x76d005b5},
210 {0x00016850, 0x557cf031},
211 {0x00016854, 0x13449440},
212 {0x00016858, 0x0c51c92c},
213 {0x0001685c, 0x3db7fffc},
214 {0x00016860, 0xfffffffc},
215 {0x00016864, 0x000f0278},
216 {0x00016868, 0x6db6db6c},
217 {0x0001686c, 0x6db60000},
218 {0x00016900, 0x11999601},
219 {0x00016908, 0x00080010},
220 {0x00016944, 0x02084080},
221 {0x00016948, 0x000080c0},
222 {0x00016b80, 0x00000000},
223 {0x00016b84, 0x00000000},
224 {0x00016b88, 0x00400705},
225 {0x00016b8c, 0x00800700},
226 {0x00016b90, 0x00800700},
227 {0x00016b94, 0x00000000},
228 {0x00016b98, 0x00000000},
229 {0x00016b9c, 0x00000000},
230 {0x00016ba0, 0x00000001},
231 {0x00016ba4, 0x00000001},
232 {0x00016ba8, 0x00000000},
233 {0x00016bac, 0x00000000},
234 {0x00016bb0, 0x00000000},
235 {0x00016bb4, 0x00000000},
236 {0x00016bb8, 0x00000000},
237 {0x00016bbc, 0x00000000},
238 {0x00016bc0, 0x000000a0},
239 {0x00016bc4, 0x000c0000},
240 {0x00016bc8, 0x14021402},
241 {0x00016bcc, 0x00001402},
242 {0x00016bd0, 0x00000000},
243 {0x00016bd4, 0x00000000},
244};
245
246static const u32 ar955x_1p0_modes_xpa_tx_gain_table[][9] = {
247 /* Addr 5G_HT20_L 5G_HT40_L 5G_HT20_M 5G_HT40_M 5G_HT20_H 5G_HT40_H 2G_HT40 2G_HT20 */
248 {0x0000a2dc, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xfffd5aaa, 0xfffd5aaa},
249 {0x0000a2e0, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xfffe9ccc, 0xfffe9ccc},
250 {0x0000a2e4, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xffffe0f0, 0xffffe0f0},
251 {0x0000a2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00},
252 {0x0000a410, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050da, 0x000050da},
253 {0x0000a500, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000000, 0x00000000},
254 {0x0000a504, 0x04000005, 0x04000005, 0x04000005, 0x04000005, 0x04000005, 0x04000005, 0x04000002, 0x04000002},
255 {0x0000a508, 0x08000009, 0x08000009, 0x08000009, 0x08000009, 0x08000009, 0x08000009, 0x08000004, 0x08000004},
256 {0x0000a50c, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c000006, 0x0c000006},
257 {0x0000a510, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x0f00000a, 0x0f00000a},
258 {0x0000a514, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x1300000c, 0x1300000c},
259 {0x0000a518, 0x19004008, 0x19004008, 0x19004008, 0x19004008, 0x18004008, 0x18004008, 0x1700000e, 0x1700000e},
260 {0x0000a51c, 0x1d00400a, 0x1d00400a, 0x1d00400a, 0x1d00400a, 0x1c00400a, 0x1c00400a, 0x1b000064, 0x1b000064},
261 {0x0000a520, 0x230020a2, 0x230020a2, 0x210020a2, 0x210020a2, 0x200020a2, 0x200020a2, 0x1f000242, 0x1f000242},
262 {0x0000a524, 0x2500006e, 0x2500006e, 0x2500006e, 0x2500006e, 0x2400006e, 0x2400006e, 0x23000229, 0x23000229},
263 {0x0000a528, 0x29022221, 0x29022221, 0x28022221, 0x28022221, 0x27022221, 0x27022221, 0x270002a2, 0x270002a2},
264 {0x0000a52c, 0x2d00062a, 0x2d00062a, 0x2c00062a, 0x2c00062a, 0x2a00062a, 0x2a00062a, 0x2c001203, 0x2c001203},
265 {0x0000a530, 0x340220a5, 0x340220a5, 0x320220a5, 0x320220a5, 0x2f0220a5, 0x2f0220a5, 0x30001803, 0x30001803},
266 {0x0000a534, 0x380022c5, 0x380022c5, 0x350022c5, 0x350022c5, 0x320022c5, 0x320022c5, 0x33000881, 0x33000881},
267 {0x0000a538, 0x3b002486, 0x3b002486, 0x39002486, 0x39002486, 0x36002486, 0x36002486, 0x38001809, 0x38001809},
268 {0x0000a53c, 0x3f00248a, 0x3f00248a, 0x3d00248a, 0x3d00248a, 0x3a00248a, 0x3a00248a, 0x3a000814, 0x3a000814},
269 {0x0000a540, 0x4202242c, 0x4202242c, 0x4102242c, 0x4102242c, 0x3f02242c, 0x3f02242c, 0x3f001a0c, 0x3f001a0c},
270 {0x0000a544, 0x490044c6, 0x490044c6, 0x460044c6, 0x460044c6, 0x420044c6, 0x420044c6, 0x43001a0e, 0x43001a0e},
271 {0x0000a548, 0x4d024485, 0x4d024485, 0x4a024485, 0x4a024485, 0x46024485, 0x46024485, 0x46001812, 0x46001812},
272 {0x0000a54c, 0x51044483, 0x51044483, 0x4e044483, 0x4e044483, 0x4a044483, 0x4a044483, 0x49001884, 0x49001884},
273 {0x0000a550, 0x5404a40c, 0x5404a40c, 0x5204a40c, 0x5204a40c, 0x4d04a40c, 0x4d04a40c, 0x4d001e84, 0x4d001e84},
274 {0x0000a554, 0x57024632, 0x57024632, 0x55024632, 0x55024632, 0x52024632, 0x52024632, 0x50001e69, 0x50001e69},
275 {0x0000a558, 0x5c00a634, 0x5c00a634, 0x5900a634, 0x5900a634, 0x5600a634, 0x5600a634, 0x550006f4, 0x550006f4},
276 {0x0000a55c, 0x5f026832, 0x5f026832, 0x5d026832, 0x5d026832, 0x5a026832, 0x5a026832, 0x59000ad3, 0x59000ad3},
277 {0x0000a560, 0x6602b012, 0x6602b012, 0x6202b012, 0x6202b012, 0x5d02b012, 0x5d02b012, 0x5e000ad5, 0x5e000ad5},
278 {0x0000a564, 0x6e02d0e1, 0x6e02d0e1, 0x6802d0e1, 0x6802d0e1, 0x6002d0e1, 0x6002d0e1, 0x61001ced, 0x61001ced},
279 {0x0000a568, 0x7202b4c4, 0x7202b4c4, 0x6c02b4c4, 0x6c02b4c4, 0x6502b4c4, 0x6502b4c4, 0x660018d4, 0x660018d4},
280 {0x0000a56c, 0x75007894, 0x75007894, 0x70007894, 0x70007894, 0x6b007894, 0x6b007894, 0x660018d4, 0x660018d4},
281 {0x0000a570, 0x7b025c74, 0x7b025c74, 0x75025c74, 0x75025c74, 0x70025c74, 0x70025c74, 0x660018d4, 0x660018d4},
282 {0x0000a574, 0x8300bcb5, 0x8300bcb5, 0x7a00bcb5, 0x7a00bcb5, 0x7600bcb5, 0x7600bcb5, 0x660018d4, 0x660018d4},
283 {0x0000a578, 0x8a04dc74, 0x8a04dc74, 0x7f04dc74, 0x7f04dc74, 0x7c04dc74, 0x7c04dc74, 0x660018d4, 0x660018d4},
284 {0x0000a57c, 0x8a04dc74, 0x8a04dc74, 0x7f04dc74, 0x7f04dc74, 0x7c04dc74, 0x7c04dc74, 0x660018d4, 0x660018d4},
285 {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
286 {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
287 {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
288 {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x03804000, 0x03804000},
289 {0x0000a610, 0x04c08c01, 0x04c08c01, 0x04808b01, 0x04808b01, 0x04808a01, 0x04808a01, 0x0300ca02, 0x0300ca02},
290 {0x0000a614, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00000e04, 0x00000e04},
291 {0x0000a618, 0x04010c01, 0x04010c01, 0x03c10b01, 0x03c10b01, 0x03810a01, 0x03810a01, 0x03014000, 0x03014000},
292 {0x0000a61c, 0x03814e05, 0x03814e05, 0x03414d05, 0x03414d05, 0x03414d05, 0x03414d05, 0x00000000, 0x00000000},
293 {0x0000a620, 0x04010303, 0x04010303, 0x03c10303, 0x03c10303, 0x03810303, 0x03810303, 0x00000000, 0x00000000},
294 {0x0000a624, 0x03814e05, 0x03814e05, 0x03414d05, 0x03414d05, 0x03414d05, 0x03414d05, 0x03014000, 0x03014000},
295 {0x0000a628, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x03804c05, 0x03804c05},
296 {0x0000a62c, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x0701de06, 0x0701de06},
297 {0x0000a630, 0x03418000, 0x03418000, 0x03018000, 0x03018000, 0x02c18000, 0x02c18000, 0x07819c07, 0x07819c07},
298 {0x0000a634, 0x03815004, 0x03815004, 0x03414f04, 0x03414f04, 0x03414e04, 0x03414e04, 0x0701dc07, 0x0701dc07},
299 {0x0000a638, 0x03005302, 0x03005302, 0x02c05202, 0x02c05202, 0x02805202, 0x02805202, 0x0701dc07, 0x0701dc07},
300 {0x0000a63c, 0x04c09302, 0x04c09302, 0x04809202, 0x04809202, 0x04809202, 0x04809202, 0x0701dc07, 0x0701dc07},
301 {0x0000b2dc, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xfffd5aaa, 0xfffd5aaa},
302 {0x0000b2e0, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xfffe9ccc, 0xfffe9ccc},
303 {0x0000b2e4, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xffffe0f0, 0xffffe0f0},
304 {0x0000b2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00},
305 {0x0000c2dc, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xfffd5aaa, 0xfffd5aaa},
306 {0x0000c2e0, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xfffe9ccc, 0xfffe9ccc},
307 {0x0000c2e4, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xffffe0f0, 0xffffe0f0},
308 {0x0000c2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00},
309 {0x00016044, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4},
310 {0x00016048, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x66482401, 0x66482401},
311 {0x00016280, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01808e84, 0x01808e84},
312 {0x00016444, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4},
313 {0x00016448, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x66482401, 0x66482401},
314 {0x00016844, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4},
315 {0x00016848, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x66482401, 0x66482401},
316};
317
318static const u32 ar955x_1p0_mac_core[][2] = {
319 /* Addr allmodes */
320 {0x00000008, 0x00000000},
321 {0x00000030, 0x00020085},
322 {0x00000034, 0x00000005},
323 {0x00000040, 0x00000000},
324 {0x00000044, 0x00000000},
325 {0x00000048, 0x00000008},
326 {0x0000004c, 0x00000010},
327 {0x00000050, 0x00000000},
328 {0x00001040, 0x002ffc0f},
329 {0x00001044, 0x002ffc0f},
330 {0x00001048, 0x002ffc0f},
331 {0x0000104c, 0x002ffc0f},
332 {0x00001050, 0x002ffc0f},
333 {0x00001054, 0x002ffc0f},
334 {0x00001058, 0x002ffc0f},
335 {0x0000105c, 0x002ffc0f},
336 {0x00001060, 0x002ffc0f},
337 {0x00001064, 0x002ffc0f},
338 {0x000010f0, 0x00000100},
339 {0x00001270, 0x00000000},
340 {0x000012b0, 0x00000000},
341 {0x000012f0, 0x00000000},
342 {0x0000143c, 0x00000000},
343 {0x0000147c, 0x00000000},
344 {0x00008000, 0x00000000},
345 {0x00008004, 0x00000000},
346 {0x00008008, 0x00000000},
347 {0x0000800c, 0x00000000},
348 {0x00008018, 0x00000000},
349 {0x00008020, 0x00000000},
350 {0x00008038, 0x00000000},
351 {0x0000803c, 0x00000000},
352 {0x00008040, 0x00000000},
353 {0x00008044, 0x00000000},
354 {0x00008048, 0x00000000},
355 {0x0000804c, 0xffffffff},
356 {0x00008054, 0x00000000},
357 {0x00008058, 0x00000000},
358 {0x0000805c, 0x000fc78f},
359 {0x00008060, 0x0000000f},
360 {0x00008064, 0x00000000},
361 {0x00008070, 0x00000310},
362 {0x00008074, 0x00000020},
363 {0x00008078, 0x00000000},
364 {0x0000809c, 0x0000000f},
365 {0x000080a0, 0x00000000},
366 {0x000080a4, 0x02ff0000},
367 {0x000080a8, 0x0e070605},
368 {0x000080ac, 0x0000000d},
369 {0x000080b0, 0x00000000},
370 {0x000080b4, 0x00000000},
371 {0x000080b8, 0x00000000},
372 {0x000080bc, 0x00000000},
373 {0x000080c0, 0x2a800000},
374 {0x000080c4, 0x06900168},
375 {0x000080c8, 0x13881c22},
376 {0x000080cc, 0x01f40000},
377 {0x000080d0, 0x00252500},
378 {0x000080d4, 0x00a00000},
379 {0x000080d8, 0x00400000},
380 {0x000080dc, 0x00000000},
381 {0x000080e0, 0xffffffff},
382 {0x000080e4, 0x0000ffff},
383 {0x000080e8, 0x3f3f3f3f},
384 {0x000080ec, 0x00000000},
385 {0x000080f0, 0x00000000},
386 {0x000080f4, 0x00000000},
387 {0x000080fc, 0x00020000},
388 {0x00008100, 0x00000000},
389 {0x00008108, 0x00000052},
390 {0x0000810c, 0x00000000},
391 {0x00008110, 0x00000000},
392 {0x00008114, 0x000007ff},
393 {0x00008118, 0x000000aa},
394 {0x0000811c, 0x00003210},
395 {0x00008124, 0x00000000},
396 {0x00008128, 0x00000000},
397 {0x0000812c, 0x00000000},
398 {0x00008130, 0x00000000},
399 {0x00008134, 0x00000000},
400 {0x00008138, 0x00000000},
401 {0x0000813c, 0x0000ffff},
402 {0x00008140, 0x000000fe},
403 {0x00008144, 0xffffffff},
404 {0x00008168, 0x00000000},
405 {0x0000816c, 0x00000000},
406 {0x000081c0, 0x00000000},
407 {0x000081c4, 0x33332210},
408 {0x000081ec, 0x00000000},
409 {0x000081f0, 0x00000000},
410 {0x000081f4, 0x00000000},
411 {0x000081f8, 0x00000000},
412 {0x000081fc, 0x00000000},
413 {0x00008240, 0x00100000},
414 {0x00008244, 0x0010f400},
415 {0x00008248, 0x00000800},
416 {0x0000824c, 0x0001e800},
417 {0x00008250, 0x00000000},
418 {0x00008254, 0x00000000},
419 {0x00008258, 0x00000000},
420 {0x0000825c, 0x40000000},
421 {0x00008260, 0x00080922},
422 {0x00008264, 0x9d400010},
423 {0x00008268, 0xffffffff},
424 {0x0000826c, 0x0000ffff},
425 {0x00008270, 0x00000000},
426 {0x00008274, 0x40000000},
427 {0x00008278, 0x003e4180},
428 {0x0000827c, 0x00000004},
429 {0x00008284, 0x0000002c},
430 {0x00008288, 0x0000002c},
431 {0x0000828c, 0x000000ff},
432 {0x00008294, 0x00000000},
433 {0x00008298, 0x00000000},
434 {0x0000829c, 0x00000000},
435 {0x00008300, 0x00001d40},
436 {0x00008314, 0x00000000},
437 {0x0000831c, 0x0000010d},
438 {0x00008328, 0x00000000},
439 {0x0000832c, 0x0000001f},
440 {0x00008330, 0x00000302},
441 {0x00008334, 0x00000700},
442 {0x00008338, 0xffff0000},
443 {0x0000833c, 0x02400000},
444 {0x00008340, 0x000107ff},
445 {0x00008344, 0xaa48107b},
446 {0x00008348, 0x008f0000},
447 {0x0000835c, 0x00000000},
448 {0x00008360, 0xffffffff},
449 {0x00008364, 0xffffffff},
450 {0x00008368, 0x00000000},
451 {0x00008370, 0x00000000},
452 {0x00008374, 0x000000ff},
453 {0x00008378, 0x00000000},
454 {0x0000837c, 0x00000000},
455 {0x00008380, 0xffffffff},
456 {0x00008384, 0xffffffff},
457 {0x00008390, 0xffffffff},
458 {0x00008394, 0xffffffff},
459 {0x00008398, 0x00000000},
460 {0x0000839c, 0x00000000},
461 {0x000083a0, 0x00000000},
462 {0x000083a4, 0x0000fa14},
463 {0x000083a8, 0x000f0c00},
464 {0x000083ac, 0x33332210},
465 {0x000083b0, 0x33332210},
466 {0x000083b4, 0x33332210},
467 {0x000083b8, 0x33332210},
468 {0x000083bc, 0x00000000},
469 {0x000083c0, 0x00000000},
470 {0x000083c4, 0x00000000},
471 {0x000083c8, 0x00000000},
472 {0x000083cc, 0x00000200},
473 {0x000083d0, 0x8c7901ff},
474};
475
476static const u32 ar955x_1p0_common_rx_gain_table[][2] = {
477 /* Addr allmodes */
478 {0x0000a000, 0x00010000},
479 {0x0000a004, 0x00030002},
480 {0x0000a008, 0x00050004},
481 {0x0000a00c, 0x00810080},
482 {0x0000a010, 0x00830082},
483 {0x0000a014, 0x01810180},
484 {0x0000a018, 0x01830182},
485 {0x0000a01c, 0x01850184},
486 {0x0000a020, 0x01890188},
487 {0x0000a024, 0x018b018a},
488 {0x0000a028, 0x018d018c},
489 {0x0000a02c, 0x01910190},
490 {0x0000a030, 0x01930192},
491 {0x0000a034, 0x01950194},
492 {0x0000a038, 0x038a0196},
493 {0x0000a03c, 0x038c038b},
494 {0x0000a040, 0x0390038d},
495 {0x0000a044, 0x03920391},
496 {0x0000a048, 0x03940393},
497 {0x0000a04c, 0x03960395},
498 {0x0000a050, 0x00000000},
499 {0x0000a054, 0x00000000},
500 {0x0000a058, 0x00000000},
501 {0x0000a05c, 0x00000000},
502 {0x0000a060, 0x00000000},
503 {0x0000a064, 0x00000000},
504 {0x0000a068, 0x00000000},
505 {0x0000a06c, 0x00000000},
506 {0x0000a070, 0x00000000},
507 {0x0000a074, 0x00000000},
508 {0x0000a078, 0x00000000},
509 {0x0000a07c, 0x00000000},
510 {0x0000a080, 0x22222229},
511 {0x0000a084, 0x1d1d1d1d},
512 {0x0000a088, 0x1d1d1d1d},
513 {0x0000a08c, 0x1d1d1d1d},
514 {0x0000a090, 0x171d1d1d},
515 {0x0000a094, 0x11111717},
516 {0x0000a098, 0x00030311},
517 {0x0000a09c, 0x00000000},
518 {0x0000a0a0, 0x00000000},
519 {0x0000a0a4, 0x00000000},
520 {0x0000a0a8, 0x00000000},
521 {0x0000a0ac, 0x00000000},
522 {0x0000a0b0, 0x00000000},
523 {0x0000a0b4, 0x00000000},
524 {0x0000a0b8, 0x00000000},
525 {0x0000a0bc, 0x00000000},
526 {0x0000a0c0, 0x001f0000},
527 {0x0000a0c4, 0x01000101},
528 {0x0000a0c8, 0x011e011f},
529 {0x0000a0cc, 0x011c011d},
530 {0x0000a0d0, 0x02030204},
531 {0x0000a0d4, 0x02010202},
532 {0x0000a0d8, 0x021f0200},
533 {0x0000a0dc, 0x0302021e},
534 {0x0000a0e0, 0x03000301},
535 {0x0000a0e4, 0x031e031f},
536 {0x0000a0e8, 0x0402031d},
537 {0x0000a0ec, 0x04000401},
538 {0x0000a0f0, 0x041e041f},
539 {0x0000a0f4, 0x0502041d},
540 {0x0000a0f8, 0x05000501},
541 {0x0000a0fc, 0x051e051f},
542 {0x0000a100, 0x06010602},
543 {0x0000a104, 0x061f0600},
544 {0x0000a108, 0x061d061e},
545 {0x0000a10c, 0x07020703},
546 {0x0000a110, 0x07000701},
547 {0x0000a114, 0x00000000},
548 {0x0000a118, 0x00000000},
549 {0x0000a11c, 0x00000000},
550 {0x0000a120, 0x00000000},
551 {0x0000a124, 0x00000000},
552 {0x0000a128, 0x00000000},
553 {0x0000a12c, 0x00000000},
554 {0x0000a130, 0x00000000},
555 {0x0000a134, 0x00000000},
556 {0x0000a138, 0x00000000},
557 {0x0000a13c, 0x00000000},
558 {0x0000a140, 0x001f0000},
559 {0x0000a144, 0x01000101},
560 {0x0000a148, 0x011e011f},
561 {0x0000a14c, 0x011c011d},
562 {0x0000a150, 0x02030204},
563 {0x0000a154, 0x02010202},
564 {0x0000a158, 0x021f0200},
565 {0x0000a15c, 0x0302021e},
566 {0x0000a160, 0x03000301},
567 {0x0000a164, 0x031e031f},
568 {0x0000a168, 0x0402031d},
569 {0x0000a16c, 0x04000401},
570 {0x0000a170, 0x041e041f},
571 {0x0000a174, 0x0502041d},
572 {0x0000a178, 0x05000501},
573 {0x0000a17c, 0x051e051f},
574 {0x0000a180, 0x06010602},
575 {0x0000a184, 0x061f0600},
576 {0x0000a188, 0x061d061e},
577 {0x0000a18c, 0x07020703},
578 {0x0000a190, 0x07000701},
579 {0x0000a194, 0x00000000},
580 {0x0000a198, 0x00000000},
581 {0x0000a19c, 0x00000000},
582 {0x0000a1a0, 0x00000000},
583 {0x0000a1a4, 0x00000000},
584 {0x0000a1a8, 0x00000000},
585 {0x0000a1ac, 0x00000000},
586 {0x0000a1b0, 0x00000000},
587 {0x0000a1b4, 0x00000000},
588 {0x0000a1b8, 0x00000000},
589 {0x0000a1bc, 0x00000000},
590 {0x0000a1c0, 0x00000000},
591 {0x0000a1c4, 0x00000000},
592 {0x0000a1c8, 0x00000000},
593 {0x0000a1cc, 0x00000000},
594 {0x0000a1d0, 0x00000000},
595 {0x0000a1d4, 0x00000000},
596 {0x0000a1d8, 0x00000000},
597 {0x0000a1dc, 0x00000000},
598 {0x0000a1e0, 0x00000000},
599 {0x0000a1e4, 0x00000000},
600 {0x0000a1e8, 0x00000000},
601 {0x0000a1ec, 0x00000000},
602 {0x0000a1f0, 0x00000396},
603 {0x0000a1f4, 0x00000396},
604 {0x0000a1f8, 0x00000396},
605 {0x0000a1fc, 0x00000196},
606 {0x0000b000, 0x00010000},
607 {0x0000b004, 0x00030002},
608 {0x0000b008, 0x00050004},
609 {0x0000b00c, 0x00810080},
610 {0x0000b010, 0x00830082},
611 {0x0000b014, 0x01810180},
612 {0x0000b018, 0x01830182},
613 {0x0000b01c, 0x01850184},
614 {0x0000b020, 0x02810280},
615 {0x0000b024, 0x02830282},
616 {0x0000b028, 0x02850284},
617 {0x0000b02c, 0x02890288},
618 {0x0000b030, 0x028b028a},
619 {0x0000b034, 0x0388028c},
620 {0x0000b038, 0x038a0389},
621 {0x0000b03c, 0x038c038b},
622 {0x0000b040, 0x0390038d},
623 {0x0000b044, 0x03920391},
624 {0x0000b048, 0x03940393},
625 {0x0000b04c, 0x03960395},
626 {0x0000b050, 0x00000000},
627 {0x0000b054, 0x00000000},
628 {0x0000b058, 0x00000000},
629 {0x0000b05c, 0x00000000},
630 {0x0000b060, 0x00000000},
631 {0x0000b064, 0x00000000},
632 {0x0000b068, 0x00000000},
633 {0x0000b06c, 0x00000000},
634 {0x0000b070, 0x00000000},
635 {0x0000b074, 0x00000000},
636 {0x0000b078, 0x00000000},
637 {0x0000b07c, 0x00000000},
638 {0x0000b080, 0x23232323},
639 {0x0000b084, 0x21232323},
640 {0x0000b088, 0x19191c1e},
641 {0x0000b08c, 0x12141417},
642 {0x0000b090, 0x07070e0e},
643 {0x0000b094, 0x03030305},
644 {0x0000b098, 0x00000003},
645 {0x0000b09c, 0x00000000},
646 {0x0000b0a0, 0x00000000},
647 {0x0000b0a4, 0x00000000},
648 {0x0000b0a8, 0x00000000},
649 {0x0000b0ac, 0x00000000},
650 {0x0000b0b0, 0x00000000},
651 {0x0000b0b4, 0x00000000},
652 {0x0000b0b8, 0x00000000},
653 {0x0000b0bc, 0x00000000},
654 {0x0000b0c0, 0x003f0020},
655 {0x0000b0c4, 0x00400041},
656 {0x0000b0c8, 0x0140005f},
657 {0x0000b0cc, 0x0160015f},
658 {0x0000b0d0, 0x017e017f},
659 {0x0000b0d4, 0x02410242},
660 {0x0000b0d8, 0x025f0240},
661 {0x0000b0dc, 0x027f0260},
662 {0x0000b0e0, 0x0341027e},
663 {0x0000b0e4, 0x035f0340},
664 {0x0000b0e8, 0x037f0360},
665 {0x0000b0ec, 0x04400441},
666 {0x0000b0f0, 0x0460045f},
667 {0x0000b0f4, 0x0541047f},
668 {0x0000b0f8, 0x055f0540},
669 {0x0000b0fc, 0x057f0560},
670 {0x0000b100, 0x06400641},
671 {0x0000b104, 0x0660065f},
672 {0x0000b108, 0x067e067f},
673 {0x0000b10c, 0x07410742},
674 {0x0000b110, 0x075f0740},
675 {0x0000b114, 0x077f0760},
676 {0x0000b118, 0x07800781},
677 {0x0000b11c, 0x07a0079f},
678 {0x0000b120, 0x07c107bf},
679 {0x0000b124, 0x000007c0},
680 {0x0000b128, 0x00000000},
681 {0x0000b12c, 0x00000000},
682 {0x0000b130, 0x00000000},
683 {0x0000b134, 0x00000000},
684 {0x0000b138, 0x00000000},
685 {0x0000b13c, 0x00000000},
686 {0x0000b140, 0x003f0020},
687 {0x0000b144, 0x00400041},
688 {0x0000b148, 0x0140005f},
689 {0x0000b14c, 0x0160015f},
690 {0x0000b150, 0x017e017f},
691 {0x0000b154, 0x02410242},
692 {0x0000b158, 0x025f0240},
693 {0x0000b15c, 0x027f0260},
694 {0x0000b160, 0x0341027e},
695 {0x0000b164, 0x035f0340},
696 {0x0000b168, 0x037f0360},
697 {0x0000b16c, 0x04400441},
698 {0x0000b170, 0x0460045f},
699 {0x0000b174, 0x0541047f},
700 {0x0000b178, 0x055f0540},
701 {0x0000b17c, 0x057f0560},
702 {0x0000b180, 0x06400641},
703 {0x0000b184, 0x0660065f},
704 {0x0000b188, 0x067e067f},
705 {0x0000b18c, 0x07410742},
706 {0x0000b190, 0x075f0740},
707 {0x0000b194, 0x077f0760},
708 {0x0000b198, 0x07800781},
709 {0x0000b19c, 0x07a0079f},
710 {0x0000b1a0, 0x07c107bf},
711 {0x0000b1a4, 0x000007c0},
712 {0x0000b1a8, 0x00000000},
713 {0x0000b1ac, 0x00000000},
714 {0x0000b1b0, 0x00000000},
715 {0x0000b1b4, 0x00000000},
716 {0x0000b1b8, 0x00000000},
717 {0x0000b1bc, 0x00000000},
718 {0x0000b1c0, 0x00000000},
719 {0x0000b1c4, 0x00000000},
720 {0x0000b1c8, 0x00000000},
721 {0x0000b1cc, 0x00000000},
722 {0x0000b1d0, 0x00000000},
723 {0x0000b1d4, 0x00000000},
724 {0x0000b1d8, 0x00000000},
725 {0x0000b1dc, 0x00000000},
726 {0x0000b1e0, 0x00000000},
727 {0x0000b1e4, 0x00000000},
728 {0x0000b1e8, 0x00000000},
729 {0x0000b1ec, 0x00000000},
730 {0x0000b1f0, 0x00000396},
731 {0x0000b1f4, 0x00000396},
732 {0x0000b1f8, 0x00000396},
733 {0x0000b1fc, 0x00000196},
734};
735
736static const u32 ar955x_1p0_baseband_core[][2] = {
737 /* Addr allmodes */
738 {0x00009800, 0xafe68e30},
739 {0x00009804, 0xfd14e000},
740 {0x00009808, 0x9c0a9f6b},
741 {0x0000980c, 0x04900000},
742 {0x00009814, 0x0280c00a},
743 {0x00009818, 0x00000000},
744 {0x0000981c, 0x00020028},
745 {0x00009834, 0x6400a190},
746 {0x00009838, 0x0108ecff},
747 {0x0000983c, 0x14000600},
748 {0x00009880, 0x201fff00},
749 {0x00009884, 0x00001042},
750 {0x000098a4, 0x00200400},
751 {0x000098b0, 0x32840bbe},
752 {0x000098bc, 0x00000002},
753 {0x000098d0, 0x004b6a8e},
754 {0x000098d4, 0x00000820},
755 {0x000098dc, 0x00000000},
756 {0x000098f0, 0x00000000},
757 {0x000098f4, 0x00000000},
758 {0x00009c04, 0xff55ff55},
759 {0x00009c08, 0x0320ff55},
760 {0x00009c0c, 0x00000000},
761 {0x00009c10, 0x00000000},
762 {0x00009c14, 0x00046384},
763 {0x00009c18, 0x05b6b440},
764 {0x00009c1c, 0x00b6b440},
765 {0x00009d00, 0xc080a333},
766 {0x00009d04, 0x40206c10},
767 {0x00009d08, 0x009c4060},
768 {0x00009d0c, 0x9883800a},
769 {0x00009d10, 0x01834061},
770 {0x00009d14, 0x00c0040b},
771 {0x00009d18, 0x00000000},
772 {0x00009e08, 0x0038230c},
773 {0x00009e24, 0x990bb515},
774 {0x00009e28, 0x0c6f0000},
775 {0x00009e30, 0x06336f77},
776 {0x00009e34, 0x6af6532f},
777 {0x00009e38, 0x0cc80c00},
778 {0x00009e40, 0x0d261820},
779 {0x00009e4c, 0x00001004},
780 {0x00009e50, 0x00ff03f1},
781 {0x00009fc0, 0x813e4788},
782 {0x00009fc4, 0x0001efb5},
783 {0x00009fcc, 0x40000014},
784 {0x00009fd0, 0x01193b93},
785 {0x0000a20c, 0x00000000},
786 {0x0000a220, 0x00000000},
787 {0x0000a224, 0x00000000},
788 {0x0000a228, 0x10002310},
789 {0x0000a23c, 0x00000000},
790 {0x0000a244, 0x0c000000},
791 {0x0000a248, 0x00000140},
792 {0x0000a2a0, 0x00000007},
793 {0x0000a2c0, 0x00000007},
794 {0x0000a2c8, 0x00000000},
795 {0x0000a2d4, 0x00000000},
796 {0x0000a2ec, 0x00000000},
797 {0x0000a2f0, 0x00000000},
798 {0x0000a2f4, 0x00000000},
799 {0x0000a2f8, 0x00000000},
800 {0x0000a344, 0x00000000},
801 {0x0000a34c, 0x00000000},
802 {0x0000a350, 0x0000a000},
803 {0x0000a364, 0x00000000},
804 {0x0000a370, 0x00000000},
805 {0x0000a390, 0x00000001},
806 {0x0000a394, 0x00000444},
807 {0x0000a398, 0x1f020503},
808 {0x0000a39c, 0x29180c03},
809 {0x0000a3a0, 0x9a8b6844},
810 {0x0000a3a4, 0x00000000},
811 {0x0000a3a8, 0xaaaaaaaa},
812 {0x0000a3ac, 0x3c466478},
813 {0x0000a3c0, 0x20202020},
814 {0x0000a3c4, 0x22222220},
815 {0x0000a3c8, 0x20200020},
816 {0x0000a3cc, 0x20202020},
817 {0x0000a3d0, 0x20202020},
818 {0x0000a3d4, 0x20202020},
819 {0x0000a3d8, 0x20202020},
820 {0x0000a3dc, 0x20202020},
821 {0x0000a3e0, 0x20202020},
822 {0x0000a3e4, 0x20202020},
823 {0x0000a3e8, 0x20202020},
824 {0x0000a3ec, 0x20202020},
825 {0x0000a3f0, 0x00000000},
826 {0x0000a3f4, 0x00000000},
827 {0x0000a3f8, 0x0c9bd380},
828 {0x0000a3fc, 0x000f0f01},
829 {0x0000a400, 0x8fa91f01},
830 {0x0000a404, 0x00000000},
831 {0x0000a408, 0x0e79e5c6},
832 {0x0000a40c, 0x00820820},
833 {0x0000a414, 0x1ce739ce},
834 {0x0000a418, 0x2d001dce},
835 {0x0000a41c, 0x1ce739ce},
836 {0x0000a420, 0x000001ce},
837 {0x0000a424, 0x1ce739ce},
838 {0x0000a428, 0x000001ce},
839 {0x0000a42c, 0x1ce739ce},
840 {0x0000a430, 0x1ce739ce},
841 {0x0000a434, 0x00000000},
842 {0x0000a438, 0x00001801},
843 {0x0000a43c, 0x00100000},
844 {0x0000a444, 0x00000000},
845 {0x0000a448, 0x05000080},
846 {0x0000a44c, 0x00000001},
847 {0x0000a450, 0x00010000},
848 {0x0000a458, 0x00000000},
849 {0x0000a644, 0x3fad9d74},
850 {0x0000a648, 0x0048060a},
851 {0x0000a64c, 0x00003c37},
852 {0x0000a670, 0x03020100},
853 {0x0000a674, 0x09080504},
854 {0x0000a678, 0x0d0c0b0a},
855 {0x0000a67c, 0x13121110},
856 {0x0000a680, 0x31301514},
857 {0x0000a684, 0x35343332},
858 {0x0000a688, 0x00000036},
859 {0x0000a690, 0x00000838},
860 {0x0000a7cc, 0x00000000},
861 {0x0000a7d0, 0x00000000},
862 {0x0000a7d4, 0x00000004},
863 {0x0000a7dc, 0x00000000},
864 {0x0000a8d0, 0x004b6a8e},
865 {0x0000a8d4, 0x00000820},
866 {0x0000a8dc, 0x00000000},
867 {0x0000a8f0, 0x00000000},
868 {0x0000a8f4, 0x00000000},
869 {0x0000b2d0, 0x00000080},
870 {0x0000b2d4, 0x00000000},
871 {0x0000b2ec, 0x00000000},
872 {0x0000b2f0, 0x00000000},
873 {0x0000b2f4, 0x00000000},
874 {0x0000b2f8, 0x00000000},
875 {0x0000b408, 0x0e79e5c0},
876 {0x0000b40c, 0x00820820},
877 {0x0000b420, 0x00000000},
878 {0x0000b8d0, 0x004b6a8e},
879 {0x0000b8d4, 0x00000820},
880 {0x0000b8dc, 0x00000000},
881 {0x0000b8f0, 0x00000000},
882 {0x0000b8f4, 0x00000000},
883 {0x0000c2d0, 0x00000080},
884 {0x0000c2d4, 0x00000000},
885 {0x0000c2ec, 0x00000000},
886 {0x0000c2f0, 0x00000000},
887 {0x0000c2f4, 0x00000000},
888 {0x0000c2f8, 0x00000000},
889 {0x0000c408, 0x0e79e5c0},
890 {0x0000c40c, 0x00820820},
891 {0x0000c420, 0x00000000},
892};
893
894static const u32 ar955x_1p0_common_wo_xlna_rx_gain_table[][2] = {
895 /* Addr allmodes */
896 {0x0000a000, 0x00010000},
897 {0x0000a004, 0x00030002},
898 {0x0000a008, 0x00050004},
899 {0x0000a00c, 0x00810080},
900 {0x0000a010, 0x00830082},
901 {0x0000a014, 0x01810180},
902 {0x0000a018, 0x01830182},
903 {0x0000a01c, 0x01850184},
904 {0x0000a020, 0x01890188},
905 {0x0000a024, 0x018b018a},
906 {0x0000a028, 0x018d018c},
907 {0x0000a02c, 0x03820190},
908 {0x0000a030, 0x03840383},
909 {0x0000a034, 0x03880385},
910 {0x0000a038, 0x038a0389},
911 {0x0000a03c, 0x038c038b},
912 {0x0000a040, 0x0390038d},
913 {0x0000a044, 0x03920391},
914 {0x0000a048, 0x03940393},
915 {0x0000a04c, 0x03960395},
916 {0x0000a050, 0x00000000},
917 {0x0000a054, 0x00000000},
918 {0x0000a058, 0x00000000},
919 {0x0000a05c, 0x00000000},
920 {0x0000a060, 0x00000000},
921 {0x0000a064, 0x00000000},
922 {0x0000a068, 0x00000000},
923 {0x0000a06c, 0x00000000},
924 {0x0000a070, 0x00000000},
925 {0x0000a074, 0x00000000},
926 {0x0000a078, 0x00000000},
927 {0x0000a07c, 0x00000000},
928 {0x0000a080, 0x29292929},
929 {0x0000a084, 0x29292929},
930 {0x0000a088, 0x29292929},
931 {0x0000a08c, 0x29292929},
932 {0x0000a090, 0x22292929},
933 {0x0000a094, 0x1d1d2222},
934 {0x0000a098, 0x0c111117},
935 {0x0000a09c, 0x00030303},
936 {0x0000a0a0, 0x00000000},
937 {0x0000a0a4, 0x00000000},
938 {0x0000a0a8, 0x00000000},
939 {0x0000a0ac, 0x00000000},
940 {0x0000a0b0, 0x00000000},
941 {0x0000a0b4, 0x00000000},
942 {0x0000a0b8, 0x00000000},
943 {0x0000a0bc, 0x00000000},
944 {0x0000a0c0, 0x001f0000},
945 {0x0000a0c4, 0x01000101},
946 {0x0000a0c8, 0x011e011f},
947 {0x0000a0cc, 0x011c011d},
948 {0x0000a0d0, 0x02030204},
949 {0x0000a0d4, 0x02010202},
950 {0x0000a0d8, 0x021f0200},
951 {0x0000a0dc, 0x0302021e},
952 {0x0000a0e0, 0x03000301},
953 {0x0000a0e4, 0x031e031f},
954 {0x0000a0e8, 0x0402031d},
955 {0x0000a0ec, 0x04000401},
956 {0x0000a0f0, 0x041e041f},
957 {0x0000a0f4, 0x0502041d},
958 {0x0000a0f8, 0x05000501},
959 {0x0000a0fc, 0x051e051f},
960 {0x0000a100, 0x06010602},
961 {0x0000a104, 0x061f0600},
962 {0x0000a108, 0x061d061e},
963 {0x0000a10c, 0x07020703},
964 {0x0000a110, 0x07000701},
965 {0x0000a114, 0x00000000},
966 {0x0000a118, 0x00000000},
967 {0x0000a11c, 0x00000000},
968 {0x0000a120, 0x00000000},
969 {0x0000a124, 0x00000000},
970 {0x0000a128, 0x00000000},
971 {0x0000a12c, 0x00000000},
972 {0x0000a130, 0x00000000},
973 {0x0000a134, 0x00000000},
974 {0x0000a138, 0x00000000},
975 {0x0000a13c, 0x00000000},
976 {0x0000a140, 0x001f0000},
977 {0x0000a144, 0x01000101},
978 {0x0000a148, 0x011e011f},
979 {0x0000a14c, 0x011c011d},
980 {0x0000a150, 0x02030204},
981 {0x0000a154, 0x02010202},
982 {0x0000a158, 0x021f0200},
983 {0x0000a15c, 0x0302021e},
984 {0x0000a160, 0x03000301},
985 {0x0000a164, 0x031e031f},
986 {0x0000a168, 0x0402031d},
987 {0x0000a16c, 0x04000401},
988 {0x0000a170, 0x041e041f},
989 {0x0000a174, 0x0502041d},
990 {0x0000a178, 0x05000501},
991 {0x0000a17c, 0x051e051f},
992 {0x0000a180, 0x06010602},
993 {0x0000a184, 0x061f0600},
994 {0x0000a188, 0x061d061e},
995 {0x0000a18c, 0x07020703},
996 {0x0000a190, 0x07000701},
997 {0x0000a194, 0x00000000},
998 {0x0000a198, 0x00000000},
999 {0x0000a19c, 0x00000000},
1000 {0x0000a1a0, 0x00000000},
1001 {0x0000a1a4, 0x00000000},
1002 {0x0000a1a8, 0x00000000},
1003 {0x0000a1ac, 0x00000000},
1004 {0x0000a1b0, 0x00000000},
1005 {0x0000a1b4, 0x00000000},
1006 {0x0000a1b8, 0x00000000},
1007 {0x0000a1bc, 0x00000000},
1008 {0x0000a1c0, 0x00000000},
1009 {0x0000a1c4, 0x00000000},
1010 {0x0000a1c8, 0x00000000},
1011 {0x0000a1cc, 0x00000000},
1012 {0x0000a1d0, 0x00000000},
1013 {0x0000a1d4, 0x00000000},
1014 {0x0000a1d8, 0x00000000},
1015 {0x0000a1dc, 0x00000000},
1016 {0x0000a1e0, 0x00000000},
1017 {0x0000a1e4, 0x00000000},
1018 {0x0000a1e8, 0x00000000},
1019 {0x0000a1ec, 0x00000000},
1020 {0x0000a1f0, 0x00000396},
1021 {0x0000a1f4, 0x00000396},
1022 {0x0000a1f8, 0x00000396},
1023 {0x0000a1fc, 0x00000196},
1024 {0x0000b000, 0x00010000},
1025 {0x0000b004, 0x00030002},
1026 {0x0000b008, 0x00050004},
1027 {0x0000b00c, 0x00810080},
1028 {0x0000b010, 0x00830082},
1029 {0x0000b014, 0x01810180},
1030 {0x0000b018, 0x01830182},
1031 {0x0000b01c, 0x01850184},
1032 {0x0000b020, 0x02810280},
1033 {0x0000b024, 0x02830282},
1034 {0x0000b028, 0x02850284},
1035 {0x0000b02c, 0x02890288},
1036 {0x0000b030, 0x028b028a},
1037 {0x0000b034, 0x0388028c},
1038 {0x0000b038, 0x038a0389},
1039 {0x0000b03c, 0x038c038b},
1040 {0x0000b040, 0x0390038d},
1041 {0x0000b044, 0x03920391},
1042 {0x0000b048, 0x03940393},
1043 {0x0000b04c, 0x03960395},
1044 {0x0000b050, 0x00000000},
1045 {0x0000b054, 0x00000000},
1046 {0x0000b058, 0x00000000},
1047 {0x0000b05c, 0x00000000},
1048 {0x0000b060, 0x00000000},
1049 {0x0000b064, 0x00000000},
1050 {0x0000b068, 0x00000000},
1051 {0x0000b06c, 0x00000000},
1052 {0x0000b070, 0x00000000},
1053 {0x0000b074, 0x00000000},
1054 {0x0000b078, 0x00000000},
1055 {0x0000b07c, 0x00000000},
1056 {0x0000b080, 0x32323232},
1057 {0x0000b084, 0x2f2f3232},
1058 {0x0000b088, 0x23282a2d},
1059 {0x0000b08c, 0x1c1e2123},
1060 {0x0000b090, 0x14171919},
1061 {0x0000b094, 0x0e0e1214},
1062 {0x0000b098, 0x03050707},
1063 {0x0000b09c, 0x00030303},
1064 {0x0000b0a0, 0x00000000},
1065 {0x0000b0a4, 0x00000000},
1066 {0x0000b0a8, 0x00000000},
1067 {0x0000b0ac, 0x00000000},
1068 {0x0000b0b0, 0x00000000},
1069 {0x0000b0b4, 0x00000000},
1070 {0x0000b0b8, 0x00000000},
1071 {0x0000b0bc, 0x00000000},
1072 {0x0000b0c0, 0x003f0020},
1073 {0x0000b0c4, 0x00400041},
1074 {0x0000b0c8, 0x0140005f},
1075 {0x0000b0cc, 0x0160015f},
1076 {0x0000b0d0, 0x017e017f},
1077 {0x0000b0d4, 0x02410242},
1078 {0x0000b0d8, 0x025f0240},
1079 {0x0000b0dc, 0x027f0260},
1080 {0x0000b0e0, 0x0341027e},
1081 {0x0000b0e4, 0x035f0340},
1082 {0x0000b0e8, 0x037f0360},
1083 {0x0000b0ec, 0x04400441},
1084 {0x0000b0f0, 0x0460045f},
1085 {0x0000b0f4, 0x0541047f},
1086 {0x0000b0f8, 0x055f0540},
1087 {0x0000b0fc, 0x057f0560},
1088 {0x0000b100, 0x06400641},
1089 {0x0000b104, 0x0660065f},
1090 {0x0000b108, 0x067e067f},
1091 {0x0000b10c, 0x07410742},
1092 {0x0000b110, 0x075f0740},
1093 {0x0000b114, 0x077f0760},
1094 {0x0000b118, 0x07800781},
1095 {0x0000b11c, 0x07a0079f},
1096 {0x0000b120, 0x07c107bf},
1097 {0x0000b124, 0x000007c0},
1098 {0x0000b128, 0x00000000},
1099 {0x0000b12c, 0x00000000},
1100 {0x0000b130, 0x00000000},
1101 {0x0000b134, 0x00000000},
1102 {0x0000b138, 0x00000000},
1103 {0x0000b13c, 0x00000000},
1104 {0x0000b140, 0x003f0020},
1105 {0x0000b144, 0x00400041},
1106 {0x0000b148, 0x0140005f},
1107 {0x0000b14c, 0x0160015f},
1108 {0x0000b150, 0x017e017f},
1109 {0x0000b154, 0x02410242},
1110 {0x0000b158, 0x025f0240},
1111 {0x0000b15c, 0x027f0260},
1112 {0x0000b160, 0x0341027e},
1113 {0x0000b164, 0x035f0340},
1114 {0x0000b168, 0x037f0360},
1115 {0x0000b16c, 0x04400441},
1116 {0x0000b170, 0x0460045f},
1117 {0x0000b174, 0x0541047f},
1118 {0x0000b178, 0x055f0540},
1119 {0x0000b17c, 0x057f0560},
1120 {0x0000b180, 0x06400641},
1121 {0x0000b184, 0x0660065f},
1122 {0x0000b188, 0x067e067f},
1123 {0x0000b18c, 0x07410742},
1124 {0x0000b190, 0x075f0740},
1125 {0x0000b194, 0x077f0760},
1126 {0x0000b198, 0x07800781},
1127 {0x0000b19c, 0x07a0079f},
1128 {0x0000b1a0, 0x07c107bf},
1129 {0x0000b1a4, 0x000007c0},
1130 {0x0000b1a8, 0x00000000},
1131 {0x0000b1ac, 0x00000000},
1132 {0x0000b1b0, 0x00000000},
1133 {0x0000b1b4, 0x00000000},
1134 {0x0000b1b8, 0x00000000},
1135 {0x0000b1bc, 0x00000000},
1136 {0x0000b1c0, 0x00000000},
1137 {0x0000b1c4, 0x00000000},
1138 {0x0000b1c8, 0x00000000},
1139 {0x0000b1cc, 0x00000000},
1140 {0x0000b1d0, 0x00000000},
1141 {0x0000b1d4, 0x00000000},
1142 {0x0000b1d8, 0x00000000},
1143 {0x0000b1dc, 0x00000000},
1144 {0x0000b1e0, 0x00000000},
1145 {0x0000b1e4, 0x00000000},
1146 {0x0000b1e8, 0x00000000},
1147 {0x0000b1ec, 0x00000000},
1148 {0x0000b1f0, 0x00000396},
1149 {0x0000b1f4, 0x00000396},
1150 {0x0000b1f8, 0x00000396},
1151 {0x0000b1fc, 0x00000196},
1152};
1153
1154static const u32 ar955x_1p0_soc_preamble[][2] = {
1155 /* Addr allmodes */
1156 {0x00007000, 0x00000000},
1157 {0x00007004, 0x00000000},
1158 {0x00007008, 0x00000000},
1159 {0x0000700c, 0x00000000},
1160 {0x0000701c, 0x00000000},
1161 {0x00007020, 0x00000000},
1162 {0x00007024, 0x00000000},
1163 {0x00007028, 0x00000000},
1164 {0x0000702c, 0x00000000},
1165 {0x00007030, 0x00000000},
1166 {0x00007034, 0x00000002},
1167 {0x00007038, 0x000004c2},
1168 {0x00007048, 0x00000000},
1169};
1170
1171static const u32 ar955x_1p0_common_wo_xlna_rx_gain_bounds[][5] = {
1172 /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
1173 {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
1174 {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
1175};
1176
1177static const u32 ar955x_1p0_mac_postamble[][5] = {
1178 /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
1179 {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
1180 {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
1181 {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
1182 {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
1183 {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
1184 {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
1185 {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
1186 {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
1187};
1188
1189static const u32 ar955x_1p0_common_rx_gain_bounds[][5] = {
1190 /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
1191 {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
1192 {0x00009e48, 0x5030201a, 0x5030201a, 0x50302018, 0x50302018},
1193};
1194
1195static const u32 ar955x_1p0_modes_no_xpa_tx_gain_table[][9] = {
1196 /* Addr 5G_HT20_L 5G_HT40_L 5G_HT20_M 5G_HT40_M 5G_HT20_H 5G_HT40_H 2G_HT40 2G_HT20 */
1197 {0x0000a2dc, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0xfffe5aaa, 0xfffe5aaa},
1198 {0x0000a2e0, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0xfffe9ccc, 0xfffe9ccc},
1199 {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0xffffe0f0, 0xffffe0f0},
1200 {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffef00, 0xffffef00},
1201 {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d8, 0x000050d8, 0x000050d8, 0x000050d8, 0x000050d7, 0x000050d7},
1202 {0x0000a500, 0x00002220, 0x00002220, 0x00002220, 0x00002220, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
1203 {0x0000a504, 0x04002222, 0x04002222, 0x04002222, 0x04002222, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
1204 {0x0000a508, 0x09002421, 0x09002421, 0x09002421, 0x09002421, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
1205 {0x0000a50c, 0x0d002621, 0x0d002621, 0x0d002621, 0x0d002621, 0x0d002621, 0x0d002621, 0x0b000006, 0x0b000006},
1206 {0x0000a510, 0x13004620, 0x13004620, 0x13004620, 0x13004620, 0x13004620, 0x13004620, 0x0f00000a, 0x0f00000a},
1207 {0x0000a514, 0x19004a20, 0x19004a20, 0x19004a20, 0x19004a20, 0x19004a20, 0x19004a20, 0x1300000c, 0x1300000c},
1208 {0x0000a518, 0x1d004e20, 0x1d004e20, 0x1d004e20, 0x1d004e20, 0x1d004e20, 0x1d004e20, 0x1700000e, 0x1700000e},
1209 {0x0000a51c, 0x21005420, 0x21005420, 0x21005420, 0x21005420, 0x21005420, 0x21005420, 0x1b000012, 0x1b000012},
1210 {0x0000a520, 0x26005e20, 0x26005e20, 0x26005e20, 0x26005e20, 0x26005e20, 0x26005e20, 0x1f00004a, 0x1f00004a},
1211 {0x0000a524, 0x2b005e40, 0x2b005e40, 0x2b005e40, 0x2b005e40, 0x2b005e40, 0x2b005e40, 0x23000244, 0x23000244},
1212 {0x0000a528, 0x2f005e42, 0x2f005e42, 0x2f005e42, 0x2f005e42, 0x2f005e42, 0x2f005e42, 0x2700022b, 0x2700022b},
1213 {0x0000a52c, 0x33005e44, 0x33005e44, 0x33005e44, 0x33005e44, 0x33005e44, 0x33005e44, 0x2b000625, 0x2b000625},
1214 {0x0000a530, 0x38005e65, 0x38005e65, 0x38005e65, 0x38005e65, 0x38005e65, 0x38005e65, 0x2f001006, 0x2f001006},
1215 {0x0000a534, 0x3c005e69, 0x3c005e69, 0x3c005e69, 0x3c005e69, 0x3c005e69, 0x3c005e69, 0x330008a0, 0x330008a0},
1216 {0x0000a538, 0x40005e6b, 0x40005e6b, 0x40005e6b, 0x40005e6b, 0x40005e6b, 0x40005e6b, 0x37000a2a, 0x37000a2a},
1217 {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x44005e6d, 0x44005e6d, 0x44005e6d, 0x44005e6d, 0x3b001c23, 0x3b001c23},
1218 {0x0000a540, 0x49005e72, 0x49005e72, 0x49005e72, 0x49005e72, 0x49005e72, 0x49005e72, 0x3f0014a0, 0x3f0014a0},
1219 {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x4e005eb2, 0x4e005eb2, 0x4e005eb2, 0x4e005eb2, 0x43001882, 0x43001882},
1220 {0x0000a548, 0x53005f12, 0x53005f12, 0x53005f12, 0x53005f12, 0x53005f12, 0x53005f12, 0x47001ca2, 0x47001ca2},
1221 {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x59025eb2, 0x59025eb2, 0x59025eb2, 0x59025eb2, 0x4b001ec3, 0x4b001ec3},
1222 {0x0000a550, 0x5e025f12, 0x5e025f12, 0x5e025f12, 0x5e025f12, 0x5e025f12, 0x5e025f12, 0x4f00148c, 0x4f00148c},
1223 {0x0000a554, 0x61027f12, 0x61027f12, 0x61027f12, 0x61027f12, 0x61027f12, 0x61027f12, 0x53001c6e, 0x53001c6e},
1224 {0x0000a558, 0x6702bf12, 0x6702bf12, 0x6702bf12, 0x6702bf12, 0x6702bf12, 0x6702bf12, 0x57001c92, 0x57001c92},
1225 {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x6b02bf14, 0x6b02bf14, 0x6b02bf14, 0x6b02bf14, 0x5c001af6, 0x5c001af6},
1226 {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6},
1227 {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6},
1228 {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6},
1229 {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6},
1230 {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6},
1231 {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6},
1232 {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6},
1233 {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6},
1234 {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
1235 {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
1236 {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
1237 {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
1238 {0x0000a610, 0x00804000, 0x00804000, 0x00804000, 0x00804000, 0x00804000, 0x00804000, 0x04005001, 0x04005001},
1239 {0x0000a614, 0x00804201, 0x00804201, 0x00804201, 0x00804201, 0x00804201, 0x00804201, 0x03808e02, 0x03808e02},
1240 {0x0000a618, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802, 0x0300c000, 0x0300c000},
1241 {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x03808e02, 0x03808e02},
1242 {0x0000a620, 0x04c15104, 0x04c15104, 0x04c15104, 0x04c15104, 0x04c15104, 0x04c15104, 0x03410c03, 0x03410c03},
1243 {0x0000a624, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04014c03, 0x04014c03},
1244 {0x0000a628, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x05818d04, 0x05818d04},
1245 {0x0000a62c, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x0801cd04, 0x0801cd04},
1246 {0x0000a630, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x0801e007, 0x0801e007},
1247 {0x0000a634, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x0801e007, 0x0801e007},
1248 {0x0000a638, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x0801e007, 0x0801e007},
1249 {0x0000a63c, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x0801e007, 0x0801e007},
1250 {0x0000b2dc, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0xfffe5aaa, 0xfffe5aaa},
1251 {0x0000b2e0, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0xfffe9ccc, 0xfffe9ccc},
1252 {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0xffffe0f0, 0xffffe0f0},
1253 {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffef00, 0xffffef00},
1254 {0x0000c2dc, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0xfffe5aaa, 0xfffe5aaa},
1255 {0x0000c2e0, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0xfffe9ccc, 0xfffe9ccc},
1256 {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0xffffe0f0, 0xffffe0f0},
1257 {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffef00, 0xffffef00},
1258 {0x00016044, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x054922d4, 0x054922d4},
1259 {0x00016048, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401},
1260 {0x00016444, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x054922d4, 0x054922d4},
1261 {0x00016448, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401},
1262 {0x00016844, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x054922d4, 0x054922d4},
1263 {0x00016848, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401},
1264};
1265
1266static const u32 ar955x_1p0_soc_postamble[][5] = {
1267 /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
1268 {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023},
1269};
1270
1271static const u32 ar955x_1p0_modes_fast_clock[][3] = {
1272 /* Addr 5G_HT20 5G_HT40 */
1273 {0x00001030, 0x00000268, 0x000004d0},
1274 {0x00001070, 0x0000018c, 0x00000318},
1275 {0x000010b0, 0x00000fd0, 0x00001fa0},
1276 {0x00008014, 0x044c044c, 0x08980898},
1277 {0x0000801c, 0x148ec02b, 0x148ec057},
1278 {0x00008318, 0x000044c0, 0x00008980},
1279 {0x00009e00, 0x0372131c, 0x0372131c},
1280 {0x0000a230, 0x0000000b, 0x00000016},
1281 {0x0000a254, 0x00000898, 0x00001130},
1282};
1283
1284#endif /* INITVALS_955X_1P0_H */
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index fe39eb4c42a1..79840d6deef2 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -481,6 +481,7 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc);
481void ath9k_btcoex_timer_pause(struct ath_softc *sc); 481void ath9k_btcoex_timer_pause(struct ath_softc *sc);
482void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status); 482void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status);
483u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen); 483u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen);
484void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc);
484#else 485#else
485static inline int ath9k_init_btcoex(struct ath_softc *sc) 486static inline int ath9k_init_btcoex(struct ath_softc *sc)
486{ 487{
@@ -504,6 +505,9 @@ static inline u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc,
504{ 505{
505 return 0; 506 return 0;
506} 507}
508static inline void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
509{
510}
507#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ 511#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
508 512
509/********************/ 513/********************/
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index 9ae6a4d97691..bacdb8fb4ef4 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -194,6 +194,14 @@ static void ath_btcoex_period_timer(unsigned long data)
194 struct ath_mci_profile *mci = &btcoex->mci; 194 struct ath_mci_profile *mci = &btcoex->mci;
195 u32 timer_period; 195 u32 timer_period;
196 bool is_btscan; 196 bool is_btscan;
197 unsigned long flags;
198
199 spin_lock_irqsave(&sc->sc_pm_lock, flags);
200 if (sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP) {
201 spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
202 goto skip_hw_wakeup;
203 }
204 spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
197 205
198 ath9k_ps_wakeup(sc); 206 ath9k_ps_wakeup(sc);
199 if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) 207 if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
@@ -232,6 +240,7 @@ static void ath_btcoex_period_timer(unsigned long data)
232 } 240 }
233 241
234 ath9k_ps_restore(sc); 242 ath9k_ps_restore(sc);
243skip_hw_wakeup:
235 timer_period = btcoex->btcoex_period; 244 timer_period = btcoex->btcoex_period;
236 mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period)); 245 mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period));
237} 246}
@@ -305,7 +314,8 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc)
305 314
306 btcoex->bt_priority_cnt = 0; 315 btcoex->bt_priority_cnt = 0;
307 btcoex->bt_priority_time = jiffies; 316 btcoex->bt_priority_time = jiffies;
308 btcoex->op_flags &= ~(BT_OP_PRIORITY_DETECTED | BT_OP_SCAN); 317 clear_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags);
318 clear_bit(BT_OP_SCAN, &btcoex->op_flags);
309 319
310 mod_timer(&btcoex->period_timer, jiffies); 320 mod_timer(&btcoex->period_timer, jiffies);
311} 321}
@@ -327,6 +337,13 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc)
327 btcoex->hw_timer_enabled = false; 337 btcoex->hw_timer_enabled = false;
328} 338}
329 339
340void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
341{
342 struct ath_btcoex *btcoex = &sc->btcoex;
343
344 ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
345}
346
330u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) 347u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen)
331{ 348{
332 struct ath_btcoex *btcoex = &sc->btcoex; 349 struct ath_btcoex *btcoex = &sc->btcoex;
@@ -376,9 +393,9 @@ void ath9k_stop_btcoex(struct ath_softc *sc)
376 393
377 if (ah->btcoex_hw.enabled && 394 if (ah->btcoex_hw.enabled &&
378 ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) { 395 ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
379 ath9k_hw_btcoex_disable(ah);
380 if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE) 396 if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
381 ath9k_btcoex_timer_pause(sc); 397 ath9k_btcoex_timer_pause(sc);
398 ath9k_hw_btcoex_disable(ah);
382 if (AR_SREV_9462(ah)) 399 if (AR_SREV_9462(ah))
383 ath_mci_flush_profile(&sc->btcoex.mci); 400 ath_mci_flush_profile(&sc->btcoex.mci);
384 } 401 }
@@ -386,11 +403,13 @@ void ath9k_stop_btcoex(struct ath_softc *sc)
386 403
387void ath9k_deinit_btcoex(struct ath_softc *sc) 404void ath9k_deinit_btcoex(struct ath_softc *sc)
388{ 405{
406 struct ath_hw *ah = sc->sc_ah;
407
389 if ((sc->btcoex.no_stomp_timer) && 408 if ((sc->btcoex.no_stomp_timer) &&
390 ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_3WIRE) 409 ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_3WIRE)
391 ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); 410 ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
392 411
393 if (AR_SREV_9462(sc->sc_ah)) 412 if (ath9k_hw_mci_is_enabled(ah))
394 ath_mci_cleanup(sc); 413 ath_mci_cleanup(sc);
395} 414}
396 415
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index ebfb2a3c645c..c1659d079513 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -342,6 +342,9 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
342 val = REG_READ(ah, AR_SREV); 342 val = REG_READ(ah, AR_SREV);
343 ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); 343 ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
344 return; 344 return;
345 case AR9300_DEVID_QCA955X:
346 ah->hw_version.macVersion = AR_SREV_VERSION_9550;
347 return;
345 } 348 }
346 349
347 val = REG_READ(ah, AR_SREV) & AR_SREV_ID; 350 val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
@@ -646,6 +649,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
646 case AR_SREV_VERSION_9485: 649 case AR_SREV_VERSION_9485:
647 case AR_SREV_VERSION_9340: 650 case AR_SREV_VERSION_9340:
648 case AR_SREV_VERSION_9462: 651 case AR_SREV_VERSION_9462:
652 case AR_SREV_VERSION_9550:
649 break; 653 break;
650 default: 654 default:
651 ath_err(common, 655 ath_err(common,
@@ -655,7 +659,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
655 } 659 }
656 660
657 if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) || 661 if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) ||
658 AR_SREV_9330(ah)) 662 AR_SREV_9330(ah) || AR_SREV_9550(ah))
659 ah->is_pciexpress = false; 663 ah->is_pciexpress = false;
660 664
661 ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); 665 ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
@@ -727,6 +731,7 @@ int ath9k_hw_init(struct ath_hw *ah)
727 case AR9300_DEVID_AR9485_PCIE: 731 case AR9300_DEVID_AR9485_PCIE:
728 case AR9300_DEVID_AR9330: 732 case AR9300_DEVID_AR9330:
729 case AR9300_DEVID_AR9340: 733 case AR9300_DEVID_AR9340:
734 case AR9300_DEVID_QCA955X:
730 case AR9300_DEVID_AR9580: 735 case AR9300_DEVID_AR9580:
731 case AR9300_DEVID_AR9462: 736 case AR9300_DEVID_AR9462:
732 break; 737 break;
@@ -865,7 +870,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
865 /* program BB PLL phase_shift */ 870 /* program BB PLL phase_shift */
866 REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, 871 REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
867 AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1); 872 AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1);
868 } else if (AR_SREV_9340(ah)) { 873 } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) {
869 u32 regval, pll2_divint, pll2_divfrac, refdiv; 874 u32 regval, pll2_divint, pll2_divfrac, refdiv;
870 875
871 REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); 876 REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
@@ -879,9 +884,15 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
879 pll2_divfrac = 0x1eb85; 884 pll2_divfrac = 0x1eb85;
880 refdiv = 3; 885 refdiv = 3;
881 } else { 886 } else {
882 pll2_divint = 88; 887 if (AR_SREV_9340(ah)) {
883 pll2_divfrac = 0; 888 pll2_divint = 88;
884 refdiv = 5; 889 pll2_divfrac = 0;
890 refdiv = 5;
891 } else {
892 pll2_divint = 0x11;
893 pll2_divfrac = 0x26666;
894 refdiv = 1;
895 }
885 } 896 }
886 897
887 regval = REG_READ(ah, AR_PHY_PLL_MODE); 898 regval = REG_READ(ah, AR_PHY_PLL_MODE);
@@ -894,8 +905,12 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
894 udelay(100); 905 udelay(100);
895 906
896 regval = REG_READ(ah, AR_PHY_PLL_MODE); 907 regval = REG_READ(ah, AR_PHY_PLL_MODE);
897 regval = (regval & 0x80071fff) | (0x1 << 30) | (0x1 << 13) | 908 if (AR_SREV_9340(ah))
898 (0x4 << 26) | (0x18 << 19); 909 regval = (regval & 0x80071fff) | (0x1 << 30) |
910 (0x1 << 13) | (0x4 << 26) | (0x18 << 19);
911 else
912 regval = (regval & 0x80071fff) | (0x3 << 30) |
913 (0x1 << 13) | (0x4 << 26) | (0x60 << 19);
899 REG_WRITE(ah, AR_PHY_PLL_MODE, regval); 914 REG_WRITE(ah, AR_PHY_PLL_MODE, regval);
900 REG_WRITE(ah, AR_PHY_PLL_MODE, 915 REG_WRITE(ah, AR_PHY_PLL_MODE,
901 REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff); 916 REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff);
@@ -906,7 +921,8 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
906 921
907 REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); 922 REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
908 923
909 if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) 924 if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) ||
925 AR_SREV_9550(ah))
910 udelay(1000); 926 udelay(1000);
911 927
912 /* Switch the core clock for ar9271 to 117Mhz */ 928 /* Switch the core clock for ar9271 to 117Mhz */
@@ -919,7 +935,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
919 935
920 REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); 936 REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
921 937
922 if (AR_SREV_9340(ah)) { 938 if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) {
923 if (ah->is_clk_25mhz) { 939 if (ah->is_clk_25mhz) {
924 REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); 940 REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1);
925 REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); 941 REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7);
@@ -943,7 +959,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
943 AR_IMR_RXORN | 959 AR_IMR_RXORN |
944 AR_IMR_BCNMISC; 960 AR_IMR_BCNMISC;
945 961
946 if (AR_SREV_9340(ah)) 962 if (AR_SREV_9340(ah) || AR_SREV_9550(ah))
947 sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; 963 sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
948 964
949 if (AR_SREV_9300_20_OR_LATER(ah)) { 965 if (AR_SREV_9300_20_OR_LATER(ah)) {
@@ -1949,9 +1965,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1949 if (!ath9k_hw_init_cal(ah, chan)) 1965 if (!ath9k_hw_init_cal(ah, chan))
1950 return -EIO; 1966 return -EIO;
1951 1967
1952 ath9k_hw_loadnf(ah, chan);
1953 ath9k_hw_start_nfcal(ah, true);
1954
1955 if (ath9k_hw_mci_is_enabled(ah) && ar9003_mci_end_reset(ah, chan, caldata)) 1968 if (ath9k_hw_mci_is_enabled(ah) && ar9003_mci_end_reset(ah, chan, caldata))
1956 return -EIO; 1969 return -EIO;
1957 1970
@@ -1987,7 +2000,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1987 REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); 2000 REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
1988 } 2001 }
1989#ifdef __BIG_ENDIAN 2002#ifdef __BIG_ENDIAN
1990 else if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) 2003 else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) ||
2004 AR_SREV_9550(ah))
1991 REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); 2005 REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0);
1992 else 2006 else
1993 REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); 2007 REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
@@ -2000,6 +2014,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
2000 if (ath9k_hw_mci_is_enabled(ah)) 2014 if (ath9k_hw_mci_is_enabled(ah))
2001 ar9003_mci_check_bt(ah); 2015 ar9003_mci_check_bt(ah);
2002 2016
2017 ath9k_hw_loadnf(ah, chan);
2018 ath9k_hw_start_nfcal(ah, true);
2019
2003 if (AR_SREV_9300_20_OR_LATER(ah)) { 2020 if (AR_SREV_9300_20_OR_LATER(ah)) {
2004 ar9003_hw_bb_watchdog_config(ah); 2021 ar9003_hw_bb_watchdog_config(ah);
2005 2022
@@ -3137,6 +3154,7 @@ static struct {
3137 { AR_SREV_VERSION_9340, "9340" }, 3154 { AR_SREV_VERSION_9340, "9340" },
3138 { AR_SREV_VERSION_9485, "9485" }, 3155 { AR_SREV_VERSION_9485, "9485" },
3139 { AR_SREV_VERSION_9462, "9462" }, 3156 { AR_SREV_VERSION_9462, "9462" },
3157 { AR_SREV_VERSION_9550, "9550" },
3140}; 3158};
3141 3159
3142/* For devices with external radios */ 3160/* For devices with external radios */
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 94096607cbdd..26da1732978d 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -48,6 +48,7 @@
48#define AR9300_DEVID_AR9580 0x0033 48#define AR9300_DEVID_AR9580 0x0033
49#define AR9300_DEVID_AR9462 0x0034 49#define AR9300_DEVID_AR9462 0x0034
50#define AR9300_DEVID_AR9330 0x0035 50#define AR9300_DEVID_AR9330 0x0035
51#define AR9300_DEVID_QCA955X 0x0038
51 52
52#define AR5416_AR9100_DEVID 0x000b 53#define AR5416_AR9100_DEVID 0x000b
53 54
@@ -818,6 +819,7 @@ struct ath_hw {
818 struct ar5416IniArray iniModesFastClock; 819 struct ar5416IniArray iniModesFastClock;
819 struct ar5416IniArray iniAdditional; 820 struct ar5416IniArray iniAdditional;
820 struct ar5416IniArray iniModesRxGain; 821 struct ar5416IniArray iniModesRxGain;
822 struct ar5416IniArray ini_modes_rx_gain_bounds;
821 struct ar5416IniArray iniModesTxGain; 823 struct ar5416IniArray iniModesTxGain;
822 struct ar5416IniArray iniCckfirNormal; 824 struct ar5416IniArray iniCckfirNormal;
823 struct ar5416IniArray iniCckfirJapan2484; 825 struct ar5416IniArray iniCckfirJapan2484;
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 04ef775ccee1..7990cd55599c 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -810,7 +810,7 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah)
810 return; 810 return;
811 } 811 }
812 812
813 if (AR_SREV_9340(ah)) 813 if (AR_SREV_9340(ah) || AR_SREV_9550(ah))
814 sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; 814 sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
815 815
816 async_mask = AR_INTR_MAC_IRQ; 816 async_mask = AR_INTR_MAC_IRQ;
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 21c955609e6c..0eba36dca6f8 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -646,6 +646,7 @@ enum ath9k_rx_filter {
646 ATH9K_RX_FILTER_PHYRADAR = 0x00002000, 646 ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
647 ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000, 647 ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000,
648 ATH9K_RX_FILTER_CONTROL_WRAPPER = 0x00080000, 648 ATH9K_RX_FILTER_CONTROL_WRAPPER = 0x00080000,
649 ATH9K_RX_FILTER_4ADDRESS = 0x00100000,
649}; 650};
650 651
651#define ATH9K_RATESERIES_RTS_CTS 0x0001 652#define ATH9K_RATESERIES_RTS_CTS 0x0001
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index e4e73f061a22..248e5b24acfa 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -130,6 +130,8 @@ void ath9k_ps_restore(struct ath_softc *sc)
130 PS_WAIT_FOR_PSPOLL_DATA | 130 PS_WAIT_FOR_PSPOLL_DATA |
131 PS_WAIT_FOR_TX_ACK))) { 131 PS_WAIT_FOR_TX_ACK))) {
132 mode = ATH9K_PM_NETWORK_SLEEP; 132 mode = ATH9K_PM_NETWORK_SLEEP;
133 if (ath9k_hw_btcoex_is_enabled(sc->sc_ah))
134 ath9k_btcoex_stop_gen_timer(sc);
133 } else { 135 } else {
134 goto unlock; 136 goto unlock;
135 } 137 }
@@ -169,7 +171,8 @@ static void ath_restart_work(struct ath_softc *sc)
169 171
170 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); 172 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
171 173
172 if (AR_SREV_9485(sc->sc_ah) || AR_SREV_9340(sc->sc_ah)) 174 if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9485(sc->sc_ah) ||
175 AR_SREV_9550(sc->sc_ah))
173 ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, 176 ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
174 msecs_to_jiffies(ATH_PLL_WORK_INTERVAL)); 177 msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
175 178
@@ -666,8 +669,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
666 669
667 spin_unlock_bh(&sc->sc_pcu_lock); 670 spin_unlock_bh(&sc->sc_pcu_lock);
668 671
669 ath9k_start_btcoex(sc);
670
671 if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en) 672 if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en)
672 common->bus_ops->extn_synch_en(common); 673 common->bus_ops->extn_synch_en(common);
673 674
@@ -774,8 +775,6 @@ static void ath9k_stop(struct ieee80211_hw *hw)
774 /* Ensure HW is awake when we try to shut it down. */ 775 /* Ensure HW is awake when we try to shut it down. */
775 ath9k_ps_wakeup(sc); 776 ath9k_ps_wakeup(sc);
776 777
777 ath9k_stop_btcoex(sc);
778
779 spin_lock_bh(&sc->sc_pcu_lock); 778 spin_lock_bh(&sc->sc_pcu_lock);
780 779
781 /* prevent tasklets to enable interrupts once we disable them */ 780 /* prevent tasklets to enable interrupts once we disable them */
@@ -1139,14 +1138,17 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
1139 1138
1140 if (changed & IEEE80211_CONF_CHANGE_IDLE) { 1139 if (changed & IEEE80211_CONF_CHANGE_IDLE) {
1141 sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); 1140 sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
1142 if (sc->ps_idle) 1141 if (sc->ps_idle) {
1143 ath_cancel_work(sc); 1142 ath_cancel_work(sc);
1144 else 1143 ath9k_stop_btcoex(sc);
1144 } else {
1145 ath9k_start_btcoex(sc);
1145 /* 1146 /*
1146 * The chip needs a reset to properly wake up from 1147 * The chip needs a reset to properly wake up from
1147 * full sleep 1148 * full sleep
1148 */ 1149 */
1149 reset_channel = ah->chip_fullsleep; 1150 reset_channel = ah->chip_fullsleep;
1151 }
1150 } 1152 }
1151 1153
1152 /* 1154 /*
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c
index 64cc782587d8..87acff7fdaae 100644
--- a/drivers/net/wireless/ath/ath9k/mci.c
+++ b/drivers/net/wireless/ath/ath9k/mci.c
@@ -174,8 +174,8 @@ skip_tuning:
174 btcoex->btcoex_period >>= 1; 174 btcoex->btcoex_period >>= 1;
175 } 175 }
176 176
177 ath9k_hw_btcoex_disable(sc->sc_ah);
178 ath9k_btcoex_timer_pause(sc); 177 ath9k_btcoex_timer_pause(sc);
178 ath9k_hw_btcoex_disable(sc->sc_ah);
179 179
180 if (IS_CHAN_5GHZ(sc->sc_ah->curchan)) 180 if (IS_CHAN_5GHZ(sc->sc_ah->curchan))
181 return; 181 return;
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 6a7dd26f2a13..11f3703a420a 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -430,6 +430,9 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
430 rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; 430 rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;
431 } 431 }
432 432
433 if (AR_SREV_9550(sc->sc_ah))
434 rfilt |= ATH9K_RX_FILTER_4ADDRESS;
435
433 return rfilt; 436 return rfilt;
434 437
435} 438}
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 5046b282a93c..6592c07ac646 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -798,6 +798,7 @@
798#define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */ 798#define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */
799#define AR_SREV_VERSION_9462 0x280 799#define AR_SREV_VERSION_9462 0x280
800#define AR_SREV_REVISION_9462_20 2 800#define AR_SREV_REVISION_9462_20 2
801#define AR_SREV_VERSION_9550 0x400
801 802
802#define AR_SREV_5416(_ah) \ 803#define AR_SREV_5416(_ah) \
803 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ 804 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
@@ -905,6 +906,9 @@
905 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ 906 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
906 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20)) 907 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20))
907 908
909#define AR_SREV_9550(_ah) \
910 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9550))
911
908#define AR_SREV_9580(_ah) \ 912#define AR_SREV_9580(_ah) \
909 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \ 913 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \
910 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10)) 914 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10))
@@ -1643,11 +1647,11 @@ enum {
1643 1647
1644#define AR_TPC 0x80e8 1648#define AR_TPC 0x80e8
1645#define AR_TPC_ACK 0x0000003f 1649#define AR_TPC_ACK 0x0000003f
1646#define AR_TPC_ACK_S 0x00 1650#define AR_TPC_ACK_S 0
1647#define AR_TPC_CTS 0x00003f00 1651#define AR_TPC_CTS 0x00003f00
1648#define AR_TPC_CTS_S 0x08 1652#define AR_TPC_CTS_S 8
1649#define AR_TPC_CHIRP 0x003f0000 1653#define AR_TPC_CHIRP 0x003f0000
1650#define AR_TPC_CHIRP_S 0x16 1654#define AR_TPC_CHIRP_S 16
1651 1655
1652#define AR_QUIET1 0x80fc 1656#define AR_QUIET1 0x80fc
1653#define AR_QUIET1_NEXT_QUIET_S 0 1657#define AR_QUIET1_NEXT_QUIET_S 0
@@ -2077,12 +2081,6 @@ enum {
2077 AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET| \ 2081 AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET| \
2078 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING | \ 2082 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING | \
2079 AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING| \ 2083 AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING| \
2080 AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \
2081 AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL | \
2082 AR_MCI_INTERRUPT_RX_MSG_LNA_INFO | \
2083 AR_MCI_INTERRUPT_RX_MSG_CONT_NACK | \
2084 AR_MCI_INTERRUPT_RX_MSG_CONT_INFO | \
2085 AR_MCI_INTERRUPT_RX_MSG_CONT_RST | \
2086 AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) 2084 AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)
2087 2085
2088#define AR_MCI_CPU_INT 0x1840 2086#define AR_MCI_CPU_INT 0x1840
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index 0cea20e3e250..376be11161c0 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -289,6 +289,7 @@ struct ar9170 {
289 unsigned int mem_block_size; 289 unsigned int mem_block_size;
290 unsigned int rx_size; 290 unsigned int rx_size;
291 unsigned int tx_seq_table; 291 unsigned int tx_seq_table;
292 bool ba_filter;
292 } fw; 293 } fw;
293 294
294 /* interface configuration combinations */ 295 /* interface configuration combinations */
@@ -425,6 +426,10 @@ struct ar9170 {
425 struct sk_buff *rx_failover; 426 struct sk_buff *rx_failover;
426 int rx_failover_missing; 427 int rx_failover_missing;
427 428
429 /* FIFO for collecting outstanding BlockAckRequest */
430 struct list_head bar_list[__AR9170_NUM_TXQ];
431 spinlock_t bar_list_lock[__AR9170_NUM_TXQ];
432
428#ifdef CONFIG_CARL9170_WPC 433#ifdef CONFIG_CARL9170_WPC
429 struct { 434 struct {
430 bool pbc_state; 435 bool pbc_state;
@@ -468,6 +473,12 @@ enum carl9170_ps_off_override_reasons {
468 PS_OFF_BCN = BIT(1), 473 PS_OFF_BCN = BIT(1),
469}; 474};
470 475
476struct carl9170_bar_list_entry {
477 struct list_head list;
478 struct rcu_head head;
479 struct sk_buff *skb;
480};
481
471struct carl9170_ba_stats { 482struct carl9170_ba_stats {
472 u8 ampdu_len; 483 u8 ampdu_len;
473 u8 ampdu_ack_len; 484 u8 ampdu_ack_len;
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c
index 5c73c03872f3..c5ca6f1f5836 100644
--- a/drivers/net/wireless/ath/carl9170/fw.c
+++ b/drivers/net/wireless/ath/carl9170/fw.c
@@ -307,6 +307,9 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
307 if (SUPP(CARL9170FW_WOL)) 307 if (SUPP(CARL9170FW_WOL))
308 device_set_wakeup_enable(&ar->udev->dev, true); 308 device_set_wakeup_enable(&ar->udev->dev, true);
309 309
310 if (SUPP(CARL9170FW_RX_BA_FILTER))
311 ar->fw.ba_filter = true;
312
310 if_comb_types = BIT(NL80211_IFTYPE_STATION) | 313 if_comb_types = BIT(NL80211_IFTYPE_STATION) |
311 BIT(NL80211_IFTYPE_P2P_CLIENT); 314 BIT(NL80211_IFTYPE_P2P_CLIENT);
312 315
diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h
index 6d9c0891ce7f..66848d47c88e 100644
--- a/drivers/net/wireless/ath/carl9170/fwdesc.h
+++ b/drivers/net/wireless/ath/carl9170/fwdesc.h
@@ -78,6 +78,9 @@ enum carl9170fw_feature_list {
78 /* HW (ANI, CCA, MIB) tally counters */ 78 /* HW (ANI, CCA, MIB) tally counters */
79 CARL9170FW_HW_COUNTERS, 79 CARL9170FW_HW_COUNTERS,
80 80
81 /* Firmware will pass BA when BARs are queued */
82 CARL9170FW_RX_BA_FILTER,
83
81 /* KEEP LAST */ 84 /* KEEP LAST */
82 __CARL9170FW_FEATURE_NUM 85 __CARL9170FW_FEATURE_NUM
83}; 86};
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 8d2523b3f722..858e58dfc4dc 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -949,6 +949,9 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw,
949 if (ar->fw.rx_filter && changed_flags & ar->rx_filter_caps) { 949 if (ar->fw.rx_filter && changed_flags & ar->rx_filter_caps) {
950 u32 rx_filter = 0; 950 u32 rx_filter = 0;
951 951
952 if (!ar->fw.ba_filter)
953 rx_filter |= CARL9170_RX_FILTER_CTL_OTHER;
954
952 if (!(*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))) 955 if (!(*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)))
953 rx_filter |= CARL9170_RX_FILTER_BAD; 956 rx_filter |= CARL9170_RX_FILTER_BAD;
954 957
@@ -1753,6 +1756,9 @@ void *carl9170_alloc(size_t priv_size)
1753 for (i = 0; i < ar->hw->queues; i++) { 1756 for (i = 0; i < ar->hw->queues; i++) {
1754 skb_queue_head_init(&ar->tx_status[i]); 1757 skb_queue_head_init(&ar->tx_status[i]);
1755 skb_queue_head_init(&ar->tx_pending[i]); 1758 skb_queue_head_init(&ar->tx_pending[i]);
1759
1760 INIT_LIST_HEAD(&ar->bar_list[i]);
1761 spin_lock_init(&ar->bar_list_lock[i]);
1756 } 1762 }
1757 INIT_WORK(&ar->ps_work, carl9170_ps_work); 1763 INIT_WORK(&ar->ps_work, carl9170_ps_work);
1758 INIT_WORK(&ar->ping_work, carl9170_ping_work); 1764 INIT_WORK(&ar->ping_work, carl9170_ping_work);
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index 7a8e90eaad83..6f6a34155667 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -576,6 +576,53 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len)
576 } 576 }
577} 577}
578 578
579static void carl9170_ba_check(struct ar9170 *ar, void *data, unsigned int len)
580{
581 struct ieee80211_bar *bar = (void *) data;
582 struct carl9170_bar_list_entry *entry;
583 unsigned int queue;
584
585 if (likely(!ieee80211_is_back(bar->frame_control)))
586 return;
587
588 if (len <= sizeof(*bar) + FCS_LEN)
589 return;
590
591 queue = TID_TO_WME_AC(((le16_to_cpu(bar->control) &
592 IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
593 IEEE80211_BAR_CTRL_TID_INFO_SHIFT) & 7);
594
595 rcu_read_lock();
596 list_for_each_entry_rcu(entry, &ar->bar_list[queue], list) {
597 struct sk_buff *entry_skb = entry->skb;
598 struct _carl9170_tx_superframe *super = (void *)entry_skb->data;
599 struct ieee80211_bar *entry_bar = (void *)super->frame_data;
600
601#define TID_CHECK(a, b) ( \
602 ((a) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK)) == \
603 ((b) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK))) \
604
605 if (bar->start_seq_num == entry_bar->start_seq_num &&
606 TID_CHECK(bar->control, entry_bar->control) &&
607 compare_ether_addr(bar->ra, entry_bar->ta) == 0 &&
608 compare_ether_addr(bar->ta, entry_bar->ra) == 0) {
609 struct ieee80211_tx_info *tx_info;
610
611 tx_info = IEEE80211_SKB_CB(entry_skb);
612 tx_info->flags |= IEEE80211_TX_STAT_ACK;
613
614 spin_lock_bh(&ar->bar_list_lock[queue]);
615 list_del_rcu(&entry->list);
616 spin_unlock_bh(&ar->bar_list_lock[queue]);
617 kfree_rcu(entry, head);
618 break;
619 }
620 }
621 rcu_read_unlock();
622
623#undef TID_CHECK
624}
625
579static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms) 626static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms)
580{ 627{
581 __le16 fc; 628 __le16 fc;
@@ -738,6 +785,8 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
738 785
739 carl9170_ps_beacon(ar, buf, mpdu_len); 786 carl9170_ps_beacon(ar, buf, mpdu_len);
740 787
788 carl9170_ba_check(ar, buf, mpdu_len);
789
741 skb = carl9170_rx_copy_data(buf, mpdu_len); 790 skb = carl9170_rx_copy_data(buf, mpdu_len);
742 if (!skb) 791 if (!skb)
743 goto drop; 792 goto drop;
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index aed305177af6..6a8681407a1d 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -277,11 +277,11 @@ static void carl9170_tx_release(struct kref *ref)
277 return; 277 return;
278 278
279 BUILD_BUG_ON( 279 BUILD_BUG_ON(
280 offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23); 280 offsetof(struct ieee80211_tx_info, status.ack_signal) != 20);
281 281
282 memset(&txinfo->status.ampdu_ack_len, 0, 282 memset(&txinfo->status.ack_signal, 0,
283 sizeof(struct ieee80211_tx_info) - 283 sizeof(struct ieee80211_tx_info) -
284 offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); 284 offsetof(struct ieee80211_tx_info, status.ack_signal));
285 285
286 if (atomic_read(&ar->tx_total_queued)) 286 if (atomic_read(&ar->tx_total_queued))
287 ar->tx_schedule = true; 287 ar->tx_schedule = true;
@@ -436,6 +436,45 @@ out_rcu:
436 rcu_read_unlock(); 436 rcu_read_unlock();
437} 437}
438 438
439static void carl9170_tx_bar_status(struct ar9170 *ar, struct sk_buff *skb,
440 struct ieee80211_tx_info *tx_info)
441{
442 struct _carl9170_tx_superframe *super = (void *) skb->data;
443 struct ieee80211_bar *bar = (void *) super->frame_data;
444
445 /*
446 * Unlike all other frames, the status report for BARs does
447 * not directly come from the hardware as it is incapable of
448 * matching a BA to a previously send BAR.
449 * Instead the RX-path will scan for incoming BAs and set the
450 * IEEE80211_TX_STAT_ACK if it sees one that was likely
451 * caused by a BAR from us.
452 */
453
454 if (unlikely(ieee80211_is_back_req(bar->frame_control)) &&
455 !(tx_info->flags & IEEE80211_TX_STAT_ACK)) {
456 struct carl9170_bar_list_entry *entry;
457 int queue = skb_get_queue_mapping(skb);
458
459 rcu_read_lock();
460 list_for_each_entry_rcu(entry, &ar->bar_list[queue], list) {
461 if (entry->skb == skb) {
462 spin_lock_bh(&ar->bar_list_lock[queue]);
463 list_del_rcu(&entry->list);
464 spin_unlock_bh(&ar->bar_list_lock[queue]);
465 kfree_rcu(entry, head);
466 goto out;
467 }
468 }
469
470 WARN(1, "bar not found in %d - ra:%pM ta:%pM c:%x ssn:%x\n",
471 queue, bar->ra, bar->ta, bar->control,
472 bar->start_seq_num);
473out:
474 rcu_read_unlock();
475 }
476}
477
439void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, 478void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
440 const bool success) 479 const bool success)
441{ 480{
@@ -445,6 +484,8 @@ void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
445 484
446 txinfo = IEEE80211_SKB_CB(skb); 485 txinfo = IEEE80211_SKB_CB(skb);
447 486
487 carl9170_tx_bar_status(ar, skb, txinfo);
488
448 if (success) 489 if (success)
449 txinfo->flags |= IEEE80211_TX_STAT_ACK; 490 txinfo->flags |= IEEE80211_TX_STAT_ACK;
450 else 491 else
@@ -1265,6 +1306,26 @@ out_rcu:
1265 return false; 1306 return false;
1266} 1307}
1267 1308
1309static void carl9170_bar_check(struct ar9170 *ar, struct sk_buff *skb)
1310{
1311 struct _carl9170_tx_superframe *super = (void *) skb->data;
1312 struct ieee80211_bar *bar = (void *) super->frame_data;
1313
1314 if (unlikely(ieee80211_is_back_req(bar->frame_control)) &&
1315 skb->len >= sizeof(struct ieee80211_bar)) {
1316 struct carl9170_bar_list_entry *entry;
1317 unsigned int queue = skb_get_queue_mapping(skb);
1318
1319 entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
1320 if (!WARN_ON_ONCE(!entry)) {
1321 entry->skb = skb;
1322 spin_lock_bh(&ar->bar_list_lock[queue]);
1323 list_add_tail_rcu(&entry->list, &ar->bar_list[queue]);
1324 spin_unlock_bh(&ar->bar_list_lock[queue]);
1325 }
1326 }
1327}
1328
1268static void carl9170_tx(struct ar9170 *ar) 1329static void carl9170_tx(struct ar9170 *ar)
1269{ 1330{
1270 struct sk_buff *skb; 1331 struct sk_buff *skb;
@@ -1287,6 +1348,8 @@ static void carl9170_tx(struct ar9170 *ar)
1287 if (unlikely(carl9170_tx_ps_drop(ar, skb))) 1348 if (unlikely(carl9170_tx_ps_drop(ar, skb)))
1288 continue; 1349 continue;
1289 1350
1351 carl9170_bar_check(ar, skb);
1352
1290 atomic_inc(&ar->tx_total_pending); 1353 atomic_inc(&ar->tx_total_pending);
1291 1354
1292 q = __carl9170_get_queue(ar, i); 1355 q = __carl9170_get_queue(ar, i);
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h
index e651db856344..2ec3e9191e4d 100644
--- a/drivers/net/wireless/ath/carl9170/version.h
+++ b/drivers/net/wireless/ath/carl9170/version.h
@@ -1,7 +1,7 @@
1#ifndef __CARL9170_SHARED_VERSION_H 1#ifndef __CARL9170_SHARED_VERSION_H
2#define __CARL9170_SHARED_VERSION_H 2#define __CARL9170_SHARED_VERSION_H
3#define CARL9170FW_VERSION_YEAR 11 3#define CARL9170FW_VERSION_YEAR 12
4#define CARL9170FW_VERSION_MONTH 8 4#define CARL9170FW_VERSION_MONTH 7
5#define CARL9170FW_VERSION_DAY 15 5#define CARL9170FW_VERSION_DAY 7
6#define CARL9170FW_VERSION_GIT "1.9.4" 6#define CARL9170FW_VERSION_GIT "1.9.6"
7#endif /* __CARL9170_SHARED_VERSION_H */ 7#endif /* __CARL9170_SHARED_VERSION_H */
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 108118820b36..b92bb9c92ad1 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -1369,7 +1369,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
1369 i << 2); 1369 i << 2);
1370 b43_nphy_poll_rssi(dev, 2, results[i], 8); 1370 b43_nphy_poll_rssi(dev, 2, results[i], 8);
1371 } 1371 }
1372 for (i = 0; i < 4; i++) { 1372 for (i = 0; i < 4; i += 2) {
1373 s32 curr; 1373 s32 curr;
1374 s32 mind = 40; 1374 s32 mind = 40;
1375 s32 minpoll = 249; 1375 s32 minpoll = 249;
@@ -1415,14 +1415,15 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
1415 b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 1, i); 1415 b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 1, i);
1416 b43_nphy_poll_rssi(dev, i, poll_results, 8); 1416 b43_nphy_poll_rssi(dev, i, poll_results, 8);
1417 for (j = 0; j < 4; j++) { 1417 for (j = 0; j < 4; j++) {
1418 if (j / 2 == core) 1418 if (j / 2 == core) {
1419 offset[j] = 232 - poll_results[j]; 1419 offset[j] = 232 - poll_results[j];
1420 if (offset[j] < 0) 1420 if (offset[j] < 0)
1421 offset[j] = -(abs(offset[j] + 4) / 8); 1421 offset[j] = -(abs(offset[j] + 4) / 8);
1422 else 1422 else
1423 offset[j] = (offset[j] + 4) / 8; 1423 offset[j] = (offset[j] + 4) / 8;
1424 b43_nphy_scale_offset_rssi(dev, 0, 1424 b43_nphy_scale_offset_rssi(dev, 0,
1425 offset[2 * core], core + 1, j % 2, i); 1425 offset[2 * core], core + 1, j % 2, i);
1426 }
1426 } 1427 }
1427 } 1428 }
1428 } 1429 }
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
index 3c6f9b1e8d05..8c9345dd37d2 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
@@ -318,10 +318,6 @@
318#define IS_SIM(chippkg) \ 318#define IS_SIM(chippkg) \
319 ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) 319 ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
320 320
321#define PCIE(sih) (ai_get_buscoretype(sih) == PCIE_CORE_ID)
322
323#define PCI_FORCEHT(sih) (PCIE(sih) && (ai_get_chip_id(sih) == BCM4716_CHIP_ID))
324
325#ifdef DEBUG 321#ifdef DEBUG
326#define SI_MSG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) 322#define SI_MSG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__)
327#else 323#else
@@ -473,9 +469,6 @@ ai_buscore_setup(struct si_info *sii, struct bcma_device *cc)
473 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; 469 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
474 } 470 }
475 471
476 /* figure out buscore */
477 sii->buscore = ai_findcore(&sii->pub, PCIE_CORE_ID, 0);
478
479 return true; 472 return true;
480} 473}
481 474
@@ -483,11 +476,7 @@ static struct si_info *ai_doattach(struct si_info *sii,
483 struct bcma_bus *pbus) 476 struct bcma_bus *pbus)
484{ 477{
485 struct si_pub *sih = &sii->pub; 478 struct si_pub *sih = &sii->pub;
486 u32 w, savewin;
487 struct bcma_device *cc; 479 struct bcma_device *cc;
488 struct ssb_sprom *sprom = &pbus->sprom;
489
490 savewin = 0;
491 480
492 sii->icbus = pbus; 481 sii->icbus = pbus;
493 sii->pcibus = pbus->host_pci; 482 sii->pcibus = pbus->host_pci;
@@ -510,47 +499,7 @@ static struct si_info *ai_doattach(struct si_info *sii,
510 499
511 /* PMU specific initializations */ 500 /* PMU specific initializations */
512 if (ai_get_cccaps(sih) & CC_CAP_PMU) { 501 if (ai_get_cccaps(sih) & CC_CAP_PMU) {
513 si_pmu_init(sih);
514 (void)si_pmu_measure_alpclk(sih); 502 (void)si_pmu_measure_alpclk(sih);
515 si_pmu_res_init(sih);
516 }
517
518 /* setup the GPIO based LED powersave register */
519 w = (sprom->leddc_on_time << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
520 (sprom->leddc_off_time << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT);
521 if (w == 0)
522 w = DEFAULT_GPIOTIMERVAL;
523 ai_cc_reg(sih, offsetof(struct chipcregs, gpiotimerval),
524 ~0, w);
525
526 if (ai_get_chip_id(sih) == BCM43224_CHIP_ID) {
527 /*
528 * enable 12 mA drive strenth for 43224 and
529 * set chipControl register bit 15
530 */
531 if (ai_get_chiprev(sih) == 0) {
532 SI_MSG("Applying 43224A0 WARs\n");
533 ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol),
534 CCTRL43224_GPIO_TOGGLE,
535 CCTRL43224_GPIO_TOGGLE);
536 si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE,
537 CCTRL_43224A0_12MA_LED_DRIVE);
538 }
539 if (ai_get_chiprev(sih) >= 1) {
540 SI_MSG("Applying 43224B0+ WARs\n");
541 si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE,
542 CCTRL_43224B0_12MA_LED_DRIVE);
543 }
544 }
545
546 if (ai_get_chip_id(sih) == BCM4313_CHIP_ID) {
547 /*
548 * enable 12 mA drive strenth for 4313 and
549 * set chipControl register bit 1
550 */
551 SI_MSG("Applying 4313 WARs\n");
552 si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE,
553 CCTRL_4313_12MA_LED_DRIVE);
554 } 503 }
555 504
556 return sii; 505 return sii;
@@ -589,7 +538,7 @@ void ai_detach(struct si_pub *sih)
589 struct si_pub *si_local = NULL; 538 struct si_pub *si_local = NULL;
590 memcpy(&si_local, &sih, sizeof(struct si_pub **)); 539 memcpy(&si_local, &sih, sizeof(struct si_pub **));
591 540
592 sii = (struct si_info *)sih; 541 sii = container_of(sih, struct si_info, pub);
593 542
594 if (sii == NULL) 543 if (sii == NULL)
595 return; 544 return;
@@ -597,27 +546,6 @@ void ai_detach(struct si_pub *sih)
597 kfree(sii); 546 kfree(sii);
598} 547}
599 548
600/* return index of coreid or BADIDX if not found */
601struct bcma_device *ai_findcore(struct si_pub *sih, u16 coreid, u16 coreunit)
602{
603 struct bcma_device *core;
604 struct si_info *sii;
605 uint found;
606
607 sii = (struct si_info *)sih;
608
609 found = 0;
610
611 list_for_each_entry(core, &sii->icbus->cores, list)
612 if (core->id.id == coreid) {
613 if (found == coreunit)
614 return core;
615 found++;
616 }
617
618 return NULL;
619}
620
621/* 549/*
622 * read/modify chipcommon core register. 550 * read/modify chipcommon core register.
623 */ 551 */
@@ -627,7 +555,7 @@ uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val)
627 u32 w; 555 u32 w;
628 struct si_info *sii; 556 struct si_info *sii;
629 557
630 sii = (struct si_info *)sih; 558 sii = container_of(sih, struct si_info, pub);
631 cc = sii->icbus->drv_cc.core; 559 cc = sii->icbus->drv_cc.core;
632 560
633 /* mask and set */ 561 /* mask and set */
@@ -693,12 +621,13 @@ ai_clkctl_setdelay(struct si_pub *sih, struct bcma_device *cc)
693/* initialize power control delay registers */ 621/* initialize power control delay registers */
694void ai_clkctl_init(struct si_pub *sih) 622void ai_clkctl_init(struct si_pub *sih)
695{ 623{
624 struct si_info *sii = container_of(sih, struct si_info, pub);
696 struct bcma_device *cc; 625 struct bcma_device *cc;
697 626
698 if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL)) 627 if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL))
699 return; 628 return;
700 629
701 cc = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); 630 cc = sii->icbus->drv_cc.core;
702 if (cc == NULL) 631 if (cc == NULL)
703 return; 632 return;
704 633
@@ -720,7 +649,7 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih)
720 uint slowminfreq; 649 uint slowminfreq;
721 u16 fpdelay; 650 u16 fpdelay;
722 651
723 sii = (struct si_info *)sih; 652 sii = container_of(sih, struct si_info, pub);
724 if (ai_get_cccaps(sih) & CC_CAP_PMU) { 653 if (ai_get_cccaps(sih) & CC_CAP_PMU) {
725 fpdelay = si_pmu_fast_pwrup_delay(sih); 654 fpdelay = si_pmu_fast_pwrup_delay(sih);
726 return fpdelay; 655 return fpdelay;
@@ -730,7 +659,7 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih)
730 return 0; 659 return 0;
731 660
732 fpdelay = 0; 661 fpdelay = 0;
733 cc = ai_findcore(sih, CC_CORE_ID, 0); 662 cc = sii->icbus->drv_cc.core;
734 if (cc) { 663 if (cc) {
735 slowminfreq = ai_slowclk_freq(sih, false, cc); 664 slowminfreq = ai_slowclk_freq(sih, false, cc);
736 fpdelay = (((bcma_read32(cc, CHIPCREGOFFS(pll_on_delay)) + 2) 665 fpdelay = (((bcma_read32(cc, CHIPCREGOFFS(pll_on_delay)) + 2)
@@ -752,12 +681,9 @@ bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode)
752 struct si_info *sii; 681 struct si_info *sii;
753 struct bcma_device *cc; 682 struct bcma_device *cc;
754 683
755 sii = (struct si_info *)sih; 684 sii = container_of(sih, struct si_info, pub);
756
757 if (PCI_FORCEHT(sih))
758 return mode == BCMA_CLKMODE_FAST;
759 685
760 cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0); 686 cc = sii->icbus->drv_cc.core;
761 bcma_core_set_clockmode(cc, mode); 687 bcma_core_set_clockmode(cc, mode);
762 return mode == BCMA_CLKMODE_FAST; 688 return mode == BCMA_CLKMODE_FAST;
763} 689}
@@ -765,16 +691,10 @@ bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode)
765void ai_pci_up(struct si_pub *sih) 691void ai_pci_up(struct si_pub *sih)
766{ 692{
767 struct si_info *sii; 693 struct si_info *sii;
768 struct bcma_device *cc;
769 694
770 sii = (struct si_info *)sih; 695 sii = container_of(sih, struct si_info, pub);
771 696
772 if (PCI_FORCEHT(sih)) { 697 if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
773 cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0);
774 bcma_core_set_clockmode(cc, BCMA_CLKMODE_FAST);
775 }
776
777 if (PCIE(sih))
778 bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, true); 698 bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, true);
779} 699}
780 700
@@ -782,26 +702,20 @@ void ai_pci_up(struct si_pub *sih)
782void ai_pci_down(struct si_pub *sih) 702void ai_pci_down(struct si_pub *sih)
783{ 703{
784 struct si_info *sii; 704 struct si_info *sii;
785 struct bcma_device *cc;
786 705
787 sii = (struct si_info *)sih; 706 sii = container_of(sih, struct si_info, pub);
788 707
789 /* release FORCEHT since chip is going to "down" state */ 708 if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
790 if (PCI_FORCEHT(sih)) {
791 cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0);
792 bcma_core_set_clockmode(cc, BCMA_CLKMODE_DYNAMIC);
793 }
794
795 if (PCIE(sih))
796 bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, false); 709 bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, false);
797} 710}
798 711
799/* Enable BT-COEX & Ex-PA for 4313 */ 712/* Enable BT-COEX & Ex-PA for 4313 */
800void ai_epa_4313war(struct si_pub *sih) 713void ai_epa_4313war(struct si_pub *sih)
801{ 714{
715 struct si_info *sii = container_of(sih, struct si_info, pub);
802 struct bcma_device *cc; 716 struct bcma_device *cc;
803 717
804 cc = ai_findcore(sih, CC_CORE_ID, 0); 718 cc = sii->icbus->drv_cc.core;
805 719
806 /* EPA Fix */ 720 /* EPA Fix */
807 bcma_set32(cc, CHIPCREGOFFS(gpiocontrol), GPIO_CTRL_EPA_EN_MASK); 721 bcma_set32(cc, CHIPCREGOFFS(gpiocontrol), GPIO_CTRL_EPA_EN_MASK);
@@ -813,7 +727,7 @@ bool ai_deviceremoved(struct si_pub *sih)
813 u32 w; 727 u32 w;
814 struct si_info *sii; 728 struct si_info *sii;
815 729
816 sii = (struct si_info *)sih; 730 sii = container_of(sih, struct si_info, pub);
817 731
818 if (sii->icbus->hosttype != BCMA_HOSTTYPE_PCI) 732 if (sii->icbus->hosttype != BCMA_HOSTTYPE_PCI)
819 return false; 733 return false;
@@ -824,15 +738,3 @@ bool ai_deviceremoved(struct si_pub *sih)
824 738
825 return false; 739 return false;
826} 740}
827
828uint ai_get_buscoretype(struct si_pub *sih)
829{
830 struct si_info *sii = (struct si_info *)sih;
831 return sii->buscore->id.id;
832}
833
834uint ai_get_buscorerev(struct si_pub *sih)
835{
836 struct si_info *sii = (struct si_info *)sih;
837 return sii->buscore->id.rev;
838}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h
index d6fa9829af9a..89562c1fbf49 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h
@@ -88,16 +88,6 @@
88#define CLKD_OTP 0x000f0000 88#define CLKD_OTP 0x000f0000
89#define CLKD_OTP_SHIFT 16 89#define CLKD_OTP_SHIFT 16
90 90
91/* Package IDs */
92#define BCM4717_PKG_ID 9 /* 4717 package id */
93#define BCM4718_PKG_ID 10 /* 4718 package id */
94#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */
95
96/* these are router chips */
97#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */
98#define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */
99#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */
100
101/* dynamic clock control defines */ 91/* dynamic clock control defines */
102#define LPOMINFREQ 25000 /* low power oscillator min */ 92#define LPOMINFREQ 25000 /* low power oscillator min */
103#define LPOMAXFREQ 43000 /* low power oscillator max */ 93#define LPOMAXFREQ 43000 /* low power oscillator max */
@@ -168,7 +158,6 @@ struct si_info {
168 struct si_pub pub; /* back plane public state (must be first) */ 158 struct si_pub pub; /* back plane public state (must be first) */
169 struct bcma_bus *icbus; /* handle to soc interconnect bus */ 159 struct bcma_bus *icbus; /* handle to soc interconnect bus */
170 struct pci_dev *pcibus; /* handle to pci bus */ 160 struct pci_dev *pcibus; /* handle to pci bus */
171 struct bcma_device *buscore;
172 161
173 u32 chipst; /* chip status */ 162 u32 chipst; /* chip status */
174}; 163};
@@ -183,8 +172,6 @@ struct si_info {
183 172
184 173
185/* AMBA Interconnect exported externs */ 174/* AMBA Interconnect exported externs */
186extern struct bcma_device *ai_findcore(struct si_pub *sih,
187 u16 coreid, u16 coreunit);
188extern u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val); 175extern u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val);
189 176
190/* === exported functions === */ 177/* === exported functions === */
@@ -202,9 +189,6 @@ extern void ai_pci_up(struct si_pub *sih);
202/* Enable Ex-PA for 4313 */ 189/* Enable Ex-PA for 4313 */
203extern void ai_epa_4313war(struct si_pub *sih); 190extern void ai_epa_4313war(struct si_pub *sih);
204 191
205extern uint ai_get_buscoretype(struct si_pub *sih);
206extern uint ai_get_buscorerev(struct si_pub *sih);
207
208static inline u32 ai_get_cccaps(struct si_pub *sih) 192static inline u32 ai_get_cccaps(struct si_pub *sih)
209{ 193{
210 return sih->cccaps; 194 return sih->cccaps;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index 2d365d3486df..9a4c63f927cb 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -763,20 +763,17 @@ void brcms_c_regd_init(struct brcms_c_info *wlc)
763 int band_idx, i; 763 int band_idx, i;
764 764
765 /* Disable any channels not supported by the phy */ 765 /* Disable any channels not supported by the phy */
766 for (band_idx = 0; band_idx < IEEE80211_NUM_BANDS; band_idx++) { 766 for (band_idx = 0; band_idx < wlc->pub->_nbands; band_idx++) {
767 if (band_idx == IEEE80211_BAND_2GHZ) 767 band = wlc->bandstate[band_idx];
768 band = wlc->bandstate[BAND_2G_INDEX];
769 else
770 band = wlc->bandstate[BAND_5G_INDEX];
771
772 /* skip if band not initialized */
773 if (band->pi == NULL)
774 continue;
775 768
776 wlc_phy_chanspec_band_validch(band->pi, band->bandtype, 769 wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
777 &sup_chan); 770 &sup_chan);
778 771
779 sband = wiphy->bands[band_idx]; 772 if (band_idx == BAND_2G_INDEX)
773 sband = wiphy->bands[IEEE80211_BAND_2GHZ];
774 else
775 sband = wiphy->bands[IEEE80211_BAND_5GHZ];
776
780 for (i = 0; i < sband->n_channels; i++) { 777 for (i = 0; i < sband->n_channels; i++) {
781 ch = &sband->channels[i]; 778 ch = &sband->channels[i];
782 if (!isset(sup_chan.vec, ch->hw_value)) 779 if (!isset(sup_chan.vec, ch->hw_value))
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c
index 7516639412ec..5e53305bd9a9 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/dma.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c
@@ -573,6 +573,7 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
573 struct dma_info *di; 573 struct dma_info *di;
574 u8 rev = core->id.rev; 574 u8 rev = core->id.rev;
575 uint size; 575 uint size;
576 struct si_info *sii = container_of(sih, struct si_info, pub);
576 577
577 /* allocate private info structure */ 578 /* allocate private info structure */
578 di = kzalloc(sizeof(struct dma_info), GFP_ATOMIC); 579 di = kzalloc(sizeof(struct dma_info), GFP_ATOMIC);
@@ -633,16 +634,20 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
633 */ 634 */
634 di->ddoffsetlow = 0; 635 di->ddoffsetlow = 0;
635 di->dataoffsetlow = 0; 636 di->dataoffsetlow = 0;
636 /* add offset for pcie with DMA64 bus */ 637 /* for pci bus, add offset */
637 di->ddoffsetlow = 0; 638 if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) {
638 di->ddoffsethigh = SI_PCIE_DMA_H32; 639 /* add offset for pcie with DMA64 bus */
640 di->ddoffsetlow = 0;
641 di->ddoffsethigh = SI_PCIE_DMA_H32;
642 }
639 di->dataoffsetlow = di->ddoffsetlow; 643 di->dataoffsetlow = di->ddoffsetlow;
640 di->dataoffsethigh = di->ddoffsethigh; 644 di->dataoffsethigh = di->ddoffsethigh;
645
641 /* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */ 646 /* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */
642 if ((core->id.id == SDIOD_CORE_ID) 647 if ((core->id.id == BCMA_CORE_SDIO_DEV)
643 && ((rev > 0) && (rev <= 2))) 648 && ((rev > 0) && (rev <= 2)))
644 di->addrext = false; 649 di->addrext = false;
645 else if ((core->id.id == I2S_CORE_ID) && 650 else if ((core->id.id == BCMA_CORE_I2S) &&
646 ((rev == 0) || (rev == 1))) 651 ((rev == 0) || (rev == 1)))
647 di->addrext = false; 652 di->addrext = false;
648 else 653 else
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index 2d5a40412690..2b57f57a7927 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -319,8 +319,7 @@ static void brcms_ops_stop(struct ieee80211_hw *hw)
319 return; 319 return;
320 320
321 spin_lock_bh(&wl->lock); 321 spin_lock_bh(&wl->lock);
322 status = brcms_c_chipmatch(wl->wlc->hw->vendorid, 322 status = brcms_c_chipmatch(wl->wlc->hw->d11core);
323 wl->wlc->hw->deviceid);
324 spin_unlock_bh(&wl->lock); 323 spin_unlock_bh(&wl->lock);
325 if (!status) { 324 if (!status) {
326 wiphy_err(wl->wiphy, 325 wiphy_err(wl->wiphy,
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index bb00b6528d8f..cb73f2250b11 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -269,7 +269,7 @@ struct brcms_c_bit_desc {
269 */ 269 */
270 270
271/* Starting corerev for the fifo size table */ 271/* Starting corerev for the fifo size table */
272#define XMTFIFOTBL_STARTREV 20 272#define XMTFIFOTBL_STARTREV 17
273 273
274struct d11init { 274struct d11init {
275 __le16 addr; 275 __le16 addr;
@@ -333,6 +333,12 @@ const u8 wlc_prio2prec_map[] = {
333}; 333};
334 334
335static const u16 xmtfifo_sz[][NFIFO] = { 335static const u16 xmtfifo_sz[][NFIFO] = {
336 /* corerev 17: 5120, 49152, 49152, 5376, 4352, 1280 */
337 {20, 192, 192, 21, 17, 5},
338 /* corerev 18: */
339 {0, 0, 0, 0, 0, 0},
340 /* corerev 19: */
341 {0, 0, 0, 0, 0, 0},
336 /* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */ 342 /* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */
337 {20, 192, 192, 21, 17, 5}, 343 {20, 192, 192, 21, 17, 5},
338 /* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */ 344 /* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */
@@ -343,6 +349,14 @@ static const u16 xmtfifo_sz[][NFIFO] = {
343 {20, 192, 192, 21, 17, 5}, 349 {20, 192, 192, 21, 17, 5},
344 /* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */ 350 /* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */
345 {9, 58, 22, 14, 14, 5}, 351 {9, 58, 22, 14, 14, 5},
352 /* corerev 25: */
353 {0, 0, 0, 0, 0, 0},
354 /* corerev 26: */
355 {0, 0, 0, 0, 0, 0},
356 /* corerev 27: */
357 {0, 0, 0, 0, 0, 0},
358 /* corerev 28: 2304, 14848, 5632, 3584, 3584, 1280 */
359 {9, 58, 22, 14, 14, 5},
346}; 360};
347 361
348#ifdef DEBUG 362#ifdef DEBUG
@@ -1942,7 +1956,8 @@ static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw)
1942 * accesses phyreg throughput mac. This can be skipped since 1956 * accesses phyreg throughput mac. This can be skipped since
1943 * only mac reg is accessed below 1957 * only mac reg is accessed below
1944 */ 1958 */
1945 flags |= SICF_PCLKE; 1959 if (D11REV_GE(wlc_hw->corerev, 18))
1960 flags |= SICF_PCLKE;
1946 1961
1947 /* 1962 /*
1948 * TODO: test suspend/resume 1963 * TODO: test suspend/resume
@@ -2023,7 +2038,8 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
2023 * phyreg throughput mac, AND phy_reset is skipped at early stage when 2038 * phyreg throughput mac, AND phy_reset is skipped at early stage when
2024 * band->pi is invalid. need to enable PHY CLK 2039 * band->pi is invalid. need to enable PHY CLK
2025 */ 2040 */
2026 flags |= SICF_PCLKE; 2041 if (D11REV_GE(wlc_hw->corerev, 18))
2042 flags |= SICF_PCLKE;
2027 2043
2028 /* 2044 /*
2029 * reset the core 2045 * reset the core
@@ -2126,8 +2142,8 @@ void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode)
2126{ 2142{
2127 struct bcma_device *core = wlc_hw->d11core; 2143 struct bcma_device *core = wlc_hw->d11core;
2128 2144
2129 if ((ai_get_chip_id(wlc_hw->sih) == BCM43224_CHIP_ID) || 2145 if ((ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM43224) ||
2130 (ai_get_chip_id(wlc_hw->sih) == BCM43225_CHIP_ID)) { 2146 (ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM43225)) {
2131 if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */ 2147 if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */
2132 bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x2082); 2148 bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x2082);
2133 bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0x8); 2149 bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0x8);
@@ -2791,7 +2807,7 @@ void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
2791 tmp = 0; 2807 tmp = 0;
2792 2808
2793 if (on) { 2809 if (on) {
2794 if ((ai_get_chip_id(wlc_hw->sih) == BCM4313_CHIP_ID)) { 2810 if ((ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM4313)) {
2795 bcma_set32(core, D11REGOFFS(clk_ctl_st), 2811 bcma_set32(core, D11REGOFFS(clk_ctl_st),
2796 CCS_ERSRC_REQ_HT | 2812 CCS_ERSRC_REQ_HT |
2797 CCS_ERSRC_REQ_D11PLL | 2813 CCS_ERSRC_REQ_D11PLL |
@@ -4218,9 +4234,8 @@ static void brcms_c_radio_timer(void *arg)
4218} 4234}
4219 4235
4220/* common low-level watchdog code */ 4236/* common low-level watchdog code */
4221static void brcms_b_watchdog(void *arg) 4237static void brcms_b_watchdog(struct brcms_c_info *wlc)
4222{ 4238{
4223 struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
4224 struct brcms_hardware *wlc_hw = wlc->hw; 4239 struct brcms_hardware *wlc_hw = wlc->hw;
4225 4240
4226 BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); 4241 BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
@@ -4241,10 +4256,8 @@ static void brcms_b_watchdog(void *arg)
4241} 4256}
4242 4257
4243/* common watchdog code */ 4258/* common watchdog code */
4244static void brcms_c_watchdog(void *arg) 4259static void brcms_c_watchdog(struct brcms_c_info *wlc)
4245{ 4260{
4246 struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
4247
4248 BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); 4261 BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
4249 4262
4250 if (!wlc->pub->up) 4263 if (!wlc->pub->up)
@@ -4284,7 +4297,9 @@ static void brcms_c_watchdog(void *arg)
4284 4297
4285static void brcms_c_watchdog_by_timer(void *arg) 4298static void brcms_c_watchdog_by_timer(void *arg)
4286{ 4299{
4287 brcms_c_watchdog(arg); 4300 struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
4301
4302 brcms_c_watchdog(wlc);
4288} 4303}
4289 4304
4290static bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit) 4305static bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit)
@@ -4454,11 +4469,9 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
4454 } 4469 }
4455 4470
4456 /* verify again the device is supported */ 4471 /* verify again the device is supported */
4457 if (core->bus->hosttype == BCMA_HOSTTYPE_PCI && 4472 if (!brcms_c_chipmatch(core)) {
4458 !brcms_c_chipmatch(pcidev->vendor, pcidev->device)) { 4473 wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported device\n",
4459 wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported " 4474 unit);
4460 "vendor/device (0x%x/0x%x)\n",
4461 unit, pcidev->vendor, pcidev->device);
4462 err = 12; 4475 err = 12;
4463 goto fail; 4476 goto fail;
4464 } 4477 }
@@ -4528,7 +4541,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
4528 else 4541 else
4529 wlc_hw->_nbands = 1; 4542 wlc_hw->_nbands = 1;
4530 4543
4531 if ((ai_get_chip_id(wlc_hw->sih) == BCM43225_CHIP_ID)) 4544 if ((ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM43225))
4532 wlc_hw->_nbands = 1; 4545 wlc_hw->_nbands = 1;
4533 4546
4534 /* BMAC_NOTE: remove init of pub values when brcms_c_attach() 4547 /* BMAC_NOTE: remove init of pub values when brcms_c_attach()
@@ -4595,8 +4608,12 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
4595 wlc_hw->machwcap_backup = wlc_hw->machwcap; 4608 wlc_hw->machwcap_backup = wlc_hw->machwcap;
4596 4609
4597 /* init tx fifo size */ 4610 /* init tx fifo size */
4611 WARN_ON((wlc_hw->corerev - XMTFIFOTBL_STARTREV) < 0 ||
4612 (wlc_hw->corerev - XMTFIFOTBL_STARTREV) >
4613 ARRAY_SIZE(xmtfifo_sz));
4598 wlc_hw->xmtfifo_sz = 4614 wlc_hw->xmtfifo_sz =
4599 xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)]; 4615 xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)];
4616 WARN_ON(!wlc_hw->xmtfifo_sz[0]);
4600 4617
4601 /* Get a phy for this band */ 4618 /* Get a phy for this band */
4602 wlc_hw->band->pi = 4619 wlc_hw->band->pi =
@@ -5036,7 +5053,7 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw)
5036 wlc_hw->wlc->pub->hw_up = true; 5053 wlc_hw->wlc->pub->hw_up = true;
5037 5054
5038 if ((wlc_hw->boardflags & BFL_FEM) 5055 if ((wlc_hw->boardflags & BFL_FEM)
5039 && (ai_get_chip_id(wlc_hw->sih) == BCM4313_CHIP_ID)) { 5056 && (ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM4313)) {
5040 if (! 5057 if (!
5041 (wlc_hw->boardrev >= 0x1250 5058 (wlc_hw->boardrev >= 0x1250
5042 && (wlc_hw->boardflags & BFL_FEM_BT))) 5059 && (wlc_hw->boardflags & BFL_FEM_BT)))
@@ -5130,7 +5147,7 @@ int brcms_c_up(struct brcms_c_info *wlc)
5130 } 5147 }
5131 5148
5132 if ((wlc->pub->boardflags & BFL_FEM) 5149 if ((wlc->pub->boardflags & BFL_FEM)
5133 && (ai_get_chip_id(wlc->hw->sih) == BCM4313_CHIP_ID)) { 5150 && (ai_get_chip_id(wlc->hw->sih) == BCMA_CHIP_ID_BCM4313)) {
5134 if (wlc->pub->boardrev >= 0x1250 5151 if (wlc->pub->boardrev >= 0x1250
5135 && (wlc->pub->boardflags & BFL_FEM_BT)) 5152 && (wlc->pub->boardflags & BFL_FEM_BT))
5136 brcms_b_mhf(wlc->hw, MHF5, MHF5_4313_GPIOCTRL, 5153 brcms_b_mhf(wlc->hw, MHF5, MHF5_4313_GPIOCTRL,
@@ -5767,8 +5784,12 @@ void brcms_c_print_txstatus(struct tx_status *txs)
5767 (txs->ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT); 5784 (txs->ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT);
5768} 5785}
5769 5786
5770bool brcms_c_chipmatch(u16 vendor, u16 device) 5787static bool brcms_c_chipmatch_pci(struct bcma_device *core)
5771{ 5788{
5789 struct pci_dev *pcidev = core->bus->host_pci;
5790 u16 vendor = pcidev->vendor;
5791 u16 device = pcidev->device;
5792
5772 if (vendor != PCI_VENDOR_ID_BROADCOM) { 5793 if (vendor != PCI_VENDOR_ID_BROADCOM) {
5773 pr_err("unknown vendor id %04x\n", vendor); 5794 pr_err("unknown vendor id %04x\n", vendor);
5774 return false; 5795 return false;
@@ -5787,6 +5808,30 @@ bool brcms_c_chipmatch(u16 vendor, u16 device)
5787 return false; 5808 return false;
5788} 5809}
5789 5810
5811static bool brcms_c_chipmatch_soc(struct bcma_device *core)
5812{
5813 struct bcma_chipinfo *chipinfo = &core->bus->chipinfo;
5814
5815 if (chipinfo->id == BCMA_CHIP_ID_BCM4716)
5816 return true;
5817
5818 pr_err("unknown chip id %04x\n", chipinfo->id);
5819 return false;
5820}
5821
5822bool brcms_c_chipmatch(struct bcma_device *core)
5823{
5824 switch (core->bus->hosttype) {
5825 case BCMA_HOSTTYPE_PCI:
5826 return brcms_c_chipmatch_pci(core);
5827 case BCMA_HOSTTYPE_SOC:
5828 return brcms_c_chipmatch_soc(core);
5829 default:
5830 pr_err("unknown host type: %i\n", core->bus->hosttype);
5831 return false;
5832 }
5833}
5834
5790#if defined(DEBUG) 5835#if defined(DEBUG)
5791void brcms_c_print_txdesc(struct d11txh *txh) 5836void brcms_c_print_txdesc(struct d11txh *txh)
5792{ 5837{
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
index 264f8c4c703d..91937c5025ce 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
@@ -198,6 +198,8 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
198 198
199void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) 199void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
200{ 200{
201 struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub);
202
201 if ((D11REV_GE(pi->sh->corerev, 24)) || 203 if ((D11REV_GE(pi->sh->corerev, 24)) ||
202 (D11REV_IS(pi->sh->corerev, 22) 204 (D11REV_IS(pi->sh->corerev, 22)
203 && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { 205 && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
@@ -209,7 +211,8 @@ void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
209 bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val); 211 bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val);
210 } 212 }
211 213
212 if (++pi->phy_wreg >= pi->phy_wreg_limit) { 214 if ((sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) &&
215 (++pi->phy_wreg >= pi->phy_wreg_limit)) {
213 (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); 216 (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
214 pi->phy_wreg = 0; 217 pi->phy_wreg = 0;
215 } 218 }
@@ -292,10 +295,13 @@ void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
292 bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr); 295 bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
293 bcma_write16(pi->d11core, D11REGOFFS(phyregdata), val); 296 bcma_write16(pi->d11core, D11REGOFFS(phyregdata), val);
294 if (addr == 0x72) 297 if (addr == 0x72)
295 (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion)); 298 (void)bcma_read16(pi->d11core, D11REGOFFS(phyregdata));
296#else 299#else
300 struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub);
301
297 bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16)); 302 bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16));
298 if (++pi->phy_wreg >= pi->phy_wreg_limit) { 303 if ((sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) &&
304 (++pi->phy_wreg >= pi->phy_wreg_limit)) {
299 pi->phy_wreg = 0; 305 pi->phy_wreg = 0;
300 (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion)); 306 (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion));
301 } 307 }
@@ -837,7 +843,7 @@ wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset,
837 pi->tbl_data_hi = tblDataHi; 843 pi->tbl_data_hi = tblDataHi;
838 pi->tbl_data_lo = tblDataLo; 844 pi->tbl_data_lo = tblDataLo;
839 845
840 if (pi->sh->chip == BCM43224_CHIP_ID && 846 if (pi->sh->chip == BCMA_CHIP_ID_BCM43224 &&
841 pi->sh->chiprev == 1) { 847 pi->sh->chiprev == 1) {
842 pi->tbl_addr = tblAddr; 848 pi->tbl_addr = tblAddr;
843 pi->tbl_save_id = tbl_id; 849 pi->tbl_save_id = tbl_id;
@@ -847,7 +853,7 @@ wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset,
847 853
848void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val) 854void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val)
849{ 855{
850 if ((pi->sh->chip == BCM43224_CHIP_ID) && 856 if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) &&
851 (pi->sh->chiprev == 1) && 857 (pi->sh->chiprev == 1) &&
852 (pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) { 858 (pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
853 read_phy_reg(pi, pi->tbl_data_lo); 859 read_phy_reg(pi, pi->tbl_data_lo);
@@ -881,7 +887,7 @@ wlc_phy_write_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info,
881 887
882 for (idx = 0; idx < ptbl_info->tbl_len; idx++) { 888 for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
883 889
884 if ((pi->sh->chip == BCM43224_CHIP_ID) && 890 if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) &&
885 (pi->sh->chiprev == 1) && 891 (pi->sh->chiprev == 1) &&
886 (tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) { 892 (tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
887 read_phy_reg(pi, tblDataLo); 893 read_phy_reg(pi, tblDataLo);
@@ -918,7 +924,7 @@ wlc_phy_read_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info,
918 924
919 for (idx = 0; idx < ptbl_info->tbl_len; idx++) { 925 for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
920 926
921 if ((pi->sh->chip == BCM43224_CHIP_ID) && 927 if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) &&
922 (pi->sh->chiprev == 1)) { 928 (pi->sh->chiprev == 1)) {
923 (void)read_phy_reg(pi, tblDataLo); 929 (void)read_phy_reg(pi, tblDataLo);
924 930
@@ -2894,7 +2900,7 @@ const u8 *wlc_phy_get_ofdm_rate_lookup(void)
2894 2900
2895void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode) 2901void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode)
2896{ 2902{
2897 if ((pi->sh->chip == BCM4313_CHIP_ID) && 2903 if ((pi->sh->chip == BCMA_CHIP_ID_BCM4313) &&
2898 (pi->sh->boardflags & BFL_FEM)) { 2904 (pi->sh->boardflags & BFL_FEM)) {
2899 if (mode) { 2905 if (mode) {
2900 u16 txant = 0; 2906 u16 txant = 0;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
index 366718146418..65db9b7458dc 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
@@ -17893,6 +17893,8 @@ static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi)
17893 nphy_tpc_txgain_ipa_2g_2057rev7; 17893 nphy_tpc_txgain_ipa_2g_2057rev7;
17894 } else if (NREV_IS(pi->pubpi.phy_rev, 6)) { 17894 } else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
17895 tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6; 17895 tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6;
17896 if (pi->sh->chip == BCMA_CHIP_ID_BCM47162)
17897 tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
17896 } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { 17898 } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
17897 tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5; 17899 tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
17898 } else { 17900 } else {
@@ -19254,8 +19256,14 @@ static void wlc_phy_spurwar_nphy(struct brcms_phy *pi)
19254 case 38: 19256 case 38:
19255 case 102: 19257 case 102:
19256 case 118: 19258 case 118:
19257 nphy_adj_tone_id_buf[0] = 0; 19259 if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) &&
19258 nphy_adj_noise_var_buf[0] = 0x0; 19260 (pi->sh->chippkg == BCMA_PKG_ID_BCM4717)) {
19261 nphy_adj_tone_id_buf[0] = 32;
19262 nphy_adj_noise_var_buf[0] = 0x21f;
19263 } else {
19264 nphy_adj_tone_id_buf[0] = 0;
19265 nphy_adj_noise_var_buf[0] = 0x0;
19266 }
19259 break; 19267 break;
19260 case 134: 19268 case 134:
19261 nphy_adj_tone_id_buf[0] = 32; 19269 nphy_adj_tone_id_buf[0] = 32;
@@ -19309,8 +19317,8 @@ void wlc_phy_init_nphy(struct brcms_phy *pi)
19309 pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC; 19317 pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
19310 19318
19311 if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) && 19319 if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) &&
19312 ((pi->sh->chippkg == BCM4717_PKG_ID) || 19320 ((pi->sh->chippkg == BCMA_PKG_ID_BCM4717) ||
19313 (pi->sh->chippkg == BCM4718_PKG_ID))) { 19321 (pi->sh->chippkg == BCMA_PKG_ID_BCM4718))) {
19314 if ((pi->sh->boardflags & BFL_EXTLNA) && 19322 if ((pi->sh->boardflags & BFL_EXTLNA) &&
19315 (CHSPEC_IS2G(pi->radio_chanspec))) 19323 (CHSPEC_IS2G(pi->radio_chanspec)))
19316 ai_cc_reg(pi->sh->sih, 19324 ai_cc_reg(pi->sh->sih,
@@ -19318,6 +19326,10 @@ void wlc_phy_init_nphy(struct brcms_phy *pi)
19318 0x40, 0x40); 19326 0x40, 0x40);
19319 } 19327 }
19320 19328
19329 if ((!PHY_IPA(pi)) && (pi->sh->chip == BCMA_CHIP_ID_BCM5357))
19330 si_pmu_chipcontrol(pi->sh->sih, 1, CCTRL5357_EXTPA,
19331 CCTRL5357_EXTPA);
19332
19321 if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) && 19333 if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
19322 CHSPEC_IS40(pi->radio_chanspec)) { 19334 CHSPEC_IS40(pi->radio_chanspec)) {
19323 19335
@@ -20695,12 +20707,22 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
20695 write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | 20707 write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 |
20696 RADIO_2056_SYN, 0x1f); 20708 RADIO_2056_SYN, 0x1f);
20697 20709
20698 write_radio_reg(pi, 20710 if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) ||
20699 RADIO_2056_SYN_PLL_LOOPFILTER4 | 20711 (pi->sh->chip == BCMA_CHIP_ID_BCM47162)) {
20700 RADIO_2056_SYN, 0xb); 20712 write_radio_reg(pi,
20701 write_radio_reg(pi, 20713 RADIO_2056_SYN_PLL_LOOPFILTER4 |
20702 RADIO_2056_SYN_PLL_CP2 | 20714 RADIO_2056_SYN, 0x14);
20703 RADIO_2056_SYN, 0x14); 20715 write_radio_reg(pi,
20716 RADIO_2056_SYN_PLL_CP2 |
20717 RADIO_2056_SYN, 0x00);
20718 } else {
20719 write_radio_reg(pi,
20720 RADIO_2056_SYN_PLL_LOOPFILTER4 |
20721 RADIO_2056_SYN, 0xb);
20722 write_radio_reg(pi,
20723 RADIO_2056_SYN_PLL_CP2 |
20724 RADIO_2056_SYN, 0x14);
20725 }
20704 } 20726 }
20705 } 20727 }
20706 20728
@@ -20747,24 +20769,30 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
20747 WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, 20769 WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
20748 PADG_IDAC, 0xcc); 20770 PADG_IDAC, 0xcc);
20749 20771
20750 bias = 0x25; 20772 if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) ||
20751 cascbias = 0x20; 20773 (pi->sh->chip == BCMA_CHIP_ID_BCM47162)) {
20774 bias = 0x40;
20775 cascbias = 0x45;
20776 pag_boost_tune = 0x5;
20777 pgag_boost_tune = 0x33;
20778 padg_boost_tune = 0x77;
20779 mixg_boost_tune = 0x55;
20780 } else {
20781 bias = 0x25;
20782 cascbias = 0x20;
20752 20783
20753 if ((pi->sh->chip == 20784 if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224 ||
20754 BCM43224_CHIP_ID) 20785 pi->sh->chip == BCMA_CHIP_ID_BCM43225) &&
20755 || (pi->sh->chip == 20786 pi->sh->chippkg == BCMA_PKG_ID_BCM43224_FAB_SMIC) {
20756 BCM43225_CHIP_ID)) {
20757 if (pi->sh->chippkg ==
20758 BCM43224_FAB_SMIC) {
20759 bias = 0x2a; 20787 bias = 0x2a;
20760 cascbias = 0x38; 20788 cascbias = 0x38;
20761 } 20789 }
20762 }
20763 20790
20764 pag_boost_tune = 0x4; 20791 pag_boost_tune = 0x4;
20765 pgag_boost_tune = 0x03; 20792 pgag_boost_tune = 0x03;
20766 padg_boost_tune = 0x77; 20793 padg_boost_tune = 0x77;
20767 mixg_boost_tune = 0x65; 20794 mixg_boost_tune = 0x65;
20795 }
20768 20796
20769 WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, 20797 WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
20770 INTPAG_IMAIN_STAT, bias); 20798 INTPAG_IMAIN_STAT, bias);
@@ -20863,11 +20891,10 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
20863 20891
20864 cascbias = 0x30; 20892 cascbias = 0x30;
20865 20893
20866 if ((pi->sh->chip == BCM43224_CHIP_ID) || 20894 if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224 ||
20867 (pi->sh->chip == BCM43225_CHIP_ID)) { 20895 pi->sh->chip == BCMA_CHIP_ID_BCM43225) &&
20868 if (pi->sh->chippkg == BCM43224_FAB_SMIC) 20896 pi->sh->chippkg == BCMA_PKG_ID_BCM43224_FAB_SMIC)
20869 cascbias = 0x35; 20897 cascbias = 0x35;
20870 }
20871 20898
20872 pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias; 20899 pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias;
20873 20900
@@ -21106,6 +21133,7 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
21106 const struct nphy_sfo_cfg *ci) 21133 const struct nphy_sfo_cfg *ci)
21107{ 21134{
21108 u16 val; 21135 u16 val;
21136 struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub);
21109 21137
21110 val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; 21138 val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
21111 if (CHSPEC_IS5G(chanspec) && !val) { 21139 if (CHSPEC_IS5G(chanspec) && !val) {
@@ -21178,22 +21206,32 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
21178 } else if (NREV_GE(pi->pubpi.phy_rev, 7)) { 21206 } else if (NREV_GE(pi->pubpi.phy_rev, 7)) {
21179 if (val == 54) 21207 if (val == 54)
21180 spuravoid = 1; 21208 spuravoid = 1;
21181 } else { 21209 } else if (pi->nphy_aband_spurwar_en &&
21182 if (pi->nphy_aband_spurwar_en && 21210 ((val == 38) || (val == 102) || (val == 118))) {
21183 ((val == 38) || (val == 102) 21211 if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716)
21184 || (val == 118))) 21212 && (pi->sh->chippkg == BCMA_PKG_ID_BCM4717)) {
21213 spuravoid = 0;
21214 } else {
21185 spuravoid = 1; 21215 spuravoid = 1;
21216 }
21186 } 21217 }
21187 21218
21188 if (pi->phy_spuravoid == SPURAVOID_FORCEON) 21219 if (pi->phy_spuravoid == SPURAVOID_FORCEON)
21189 spuravoid = 1; 21220 spuravoid = 1;
21190 21221
21191 wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false); 21222 if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) ||
21192 si_pmu_spuravoid_pllupdate(pi->sh->sih, spuravoid); 21223 (pi->sh->chip == BCMA_CHIP_ID_BCM43225)) {
21193 wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true); 21224 bcma_pmu_spuravoid_pllupdate(&sii->icbus->drv_cc,
21225 spuravoid);
21226 } else {
21227 wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false);
21228 bcma_pmu_spuravoid_pllupdate(&sii->icbus->drv_cc,
21229 spuravoid);
21230 wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true);
21231 }
21194 21232
21195 if ((pi->sh->chip == BCM43224_CHIP_ID) || 21233 if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) ||
21196 (pi->sh->chip == BCM43225_CHIP_ID)) { 21234 (pi->sh->chip == BCMA_CHIP_ID_BCM43225)) {
21197 if (spuravoid == 1) { 21235 if (spuravoid == 1) {
21198 bcma_write16(pi->d11core, 21236 bcma_write16(pi->d11core,
21199 D11REGOFFS(tsf_clk_frac_l), 21237 D11REGOFFS(tsf_clk_frac_l),
@@ -21209,7 +21247,9 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
21209 } 21247 }
21210 } 21248 }
21211 21249
21212 wlapi_bmac_core_phypll_reset(pi->sh->physhim); 21250 if (!((pi->sh->chip == BCMA_CHIP_ID_BCM4716) ||
21251 (pi->sh->chip == BCMA_CHIP_ID_BCM47162)))
21252 wlapi_bmac_core_phypll_reset(pi->sh->physhim);
21213 21253
21214 mod_phy_reg(pi, 0x01, (0x1 << 15), 21254 mod_phy_reg(pi, 0x01, (0x1 << 15),
21215 ((spuravoid > 0) ? (0x1 << 15) : 0)); 21255 ((spuravoid > 0) ? (0x1 << 15) : 0));
@@ -22171,9 +22211,15 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi)
22171 wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16, 22211 wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
22172 &auxADC_rssi_ctrlH_save); 22212 &auxADC_rssi_ctrlH_save);
22173 22213
22174 radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1]) 22214 if (pi->sh->chip == BCMA_CHIP_ID_BCM5357) {
22175 + 82 * (auxADC_Vl) - 28861 + 22215 radio_temp[0] = (193 * (radio_temp[1] + radio_temp2[1])
22176 128) / 256; 22216 + 88 * (auxADC_Vl) - 27111 +
22217 128) / 256;
22218 } else {
22219 radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1])
22220 + 82 * (auxADC_Vl) - 28861 +
22221 128) / 256;
22222 }
22177 22223
22178 offset = (s16) pi->phy_tempsense_offset; 22224 offset = (s16) pi->phy_tempsense_offset;
22179 22225
@@ -24923,14 +24969,16 @@ wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains,
24923 if (txgains->useindex) { 24969 if (txgains->useindex) {
24924 phy_a4 = 15 - ((txgains->index) >> 3); 24970 phy_a4 = 15 - ((txgains->index) >> 3);
24925 if (CHSPEC_IS2G(pi->radio_chanspec)) { 24971 if (CHSPEC_IS2G(pi->radio_chanspec)) {
24926 if (NREV_GE(pi->pubpi.phy_rev, 6)) 24972 if (NREV_GE(pi->pubpi.phy_rev, 6) &&
24973 pi->sh->chip == BCMA_CHIP_ID_BCM47162) {
24974 phy_a5 = 0x10f7 | (phy_a4 << 8);
24975 } else if (NREV_GE(pi->pubpi.phy_rev, 6)) {
24927 phy_a5 = 0x00f7 | (phy_a4 << 8); 24976 phy_a5 = 0x00f7 | (phy_a4 << 8);
24928 24977 } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
24929 else
24930 if (NREV_IS(pi->pubpi.phy_rev, 5))
24931 phy_a5 = 0x10f7 | (phy_a4 << 8); 24978 phy_a5 = 0x10f7 | (phy_a4 << 8);
24932 else 24979 } else {
24933 phy_a5 = 0x50f7 | (phy_a4 << 8); 24980 phy_a5 = 0x50f7 | (phy_a4 << 8);
24981 }
24934 } else { 24982 } else {
24935 phy_a5 = 0x70f7 | (phy_a4 << 8); 24983 phy_a5 = 0x70f7 | (phy_a4 << 8);
24936 } 24984 }
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pmu.c b/drivers/net/wireless/brcm80211/brcmsmac/pmu.c
index 4931d29d077b..7e9df566c733 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/pmu.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.c
@@ -74,16 +74,6 @@
74 * PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary 74 * PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary
75 * number to differentiate different PLLs controlled by the same PMU rev. 75 * number to differentiate different PLLs controlled by the same PMU rev.
76 */ 76 */
77/* pllcontrol registers:
78 * ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>,
79 * p1div, p2div, _bypass_sdmod
80 */
81#define PMU1_PLL0_PLLCTL0 0
82#define PMU1_PLL0_PLLCTL1 1
83#define PMU1_PLL0_PLLCTL2 2
84#define PMU1_PLL0_PLLCTL3 3
85#define PMU1_PLL0_PLLCTL4 4
86#define PMU1_PLL0_PLLCTL5 5
87 77
88/* pmu XtalFreqRatio */ 78/* pmu XtalFreqRatio */
89#define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF 79#define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF
@@ -108,118 +98,14 @@
108#define RES4313_HT_AVAIL_RSRC 14 98#define RES4313_HT_AVAIL_RSRC 14
109#define RES4313_MACPHY_CLK_AVAIL_RSRC 15 99#define RES4313_MACPHY_CLK_AVAIL_RSRC 15
110 100
111/* Determine min/max rsrc masks. Value 0 leaves hardware at default. */
112static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax)
113{
114 u32 min_mask = 0, max_mask = 0;
115 uint rsrcs;
116
117 /* # resources */
118 rsrcs = (ai_get_pmucaps(sih) & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
119
120 /* determine min/max rsrc masks */
121 switch (ai_get_chip_id(sih)) {
122 case BCM43224_CHIP_ID:
123 case BCM43225_CHIP_ID:
124 /* ??? */
125 break;
126
127 case BCM4313_CHIP_ID:
128 min_mask = PMURES_BIT(RES4313_BB_PU_RSRC) |
129 PMURES_BIT(RES4313_XTAL_PU_RSRC) |
130 PMURES_BIT(RES4313_ALP_AVAIL_RSRC) |
131 PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC);
132 max_mask = 0xffff;
133 break;
134 default:
135 break;
136 }
137
138 *pmin = min_mask;
139 *pmax = max_mask;
140}
141
142void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid)
143{
144 u32 tmp = 0;
145 struct bcma_device *core;
146
147 /* switch to chipc */
148 core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
149
150 switch (ai_get_chip_id(sih)) {
151 case BCM43224_CHIP_ID:
152 case BCM43225_CHIP_ID:
153 if (spuravoid == 1) {
154 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
155 PMU1_PLL0_PLLCTL0);
156 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
157 0x11500010);
158 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
159 PMU1_PLL0_PLLCTL1);
160 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
161 0x000C0C06);
162 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
163 PMU1_PLL0_PLLCTL2);
164 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
165 0x0F600a08);
166 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
167 PMU1_PLL0_PLLCTL3);
168 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
169 0x00000000);
170 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
171 PMU1_PLL0_PLLCTL4);
172 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
173 0x2001E920);
174 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
175 PMU1_PLL0_PLLCTL5);
176 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
177 0x88888815);
178 } else {
179 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
180 PMU1_PLL0_PLLCTL0);
181 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
182 0x11100010);
183 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
184 PMU1_PLL0_PLLCTL1);
185 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
186 0x000c0c06);
187 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
188 PMU1_PLL0_PLLCTL2);
189 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
190 0x03000a08);
191 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
192 PMU1_PLL0_PLLCTL3);
193 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
194 0x00000000);
195 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
196 PMU1_PLL0_PLLCTL4);
197 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
198 0x200005c0);
199 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
200 PMU1_PLL0_PLLCTL5);
201 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
202 0x88888815);
203 }
204 tmp = 1 << 10;
205 break;
206
207 default:
208 /* bail out */
209 return;
210 }
211
212 bcma_set32(core, CHIPCREGOFFS(pmucontrol), tmp);
213}
214
215u16 si_pmu_fast_pwrup_delay(struct si_pub *sih) 101u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
216{ 102{
217 uint delay = PMU_MAX_TRANSITION_DLY; 103 uint delay = PMU_MAX_TRANSITION_DLY;
218 104
219 switch (ai_get_chip_id(sih)) { 105 switch (ai_get_chip_id(sih)) {
220 case BCM43224_CHIP_ID: 106 case BCMA_CHIP_ID_BCM43224:
221 case BCM43225_CHIP_ID: 107 case BCMA_CHIP_ID_BCM43225:
222 case BCM4313_CHIP_ID: 108 case BCMA_CHIP_ID_BCM4313:
223 delay = 3700; 109 delay = 3700;
224 break; 110 break;
225 default: 111 default:
@@ -270,9 +156,9 @@ u32 si_pmu_alp_clock(struct si_pub *sih)
270 return clock; 156 return clock;
271 157
272 switch (ai_get_chip_id(sih)) { 158 switch (ai_get_chip_id(sih)) {
273 case BCM43224_CHIP_ID: 159 case BCMA_CHIP_ID_BCM43224:
274 case BCM43225_CHIP_ID: 160 case BCMA_CHIP_ID_BCM43225:
275 case BCM4313_CHIP_ID: 161 case BCMA_CHIP_ID_BCM4313:
276 /* always 20Mhz */ 162 /* always 20Mhz */
277 clock = 20000 * 1000; 163 clock = 20000 * 1000;
278 break; 164 break;
@@ -283,51 +169,9 @@ u32 si_pmu_alp_clock(struct si_pub *sih)
283 return clock; 169 return clock;
284} 170}
285 171
286/* initialize PMU */
287void si_pmu_init(struct si_pub *sih)
288{
289 struct bcma_device *core;
290
291 /* select chipc */
292 core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
293
294 if (ai_get_pmurev(sih) == 1)
295 bcma_mask32(core, CHIPCREGOFFS(pmucontrol),
296 ~PCTL_NOILP_ON_WAIT);
297 else if (ai_get_pmurev(sih) >= 2)
298 bcma_set32(core, CHIPCREGOFFS(pmucontrol), PCTL_NOILP_ON_WAIT);
299}
300
301/* initialize PMU resources */
302void si_pmu_res_init(struct si_pub *sih)
303{
304 struct bcma_device *core;
305 u32 min_mask = 0, max_mask = 0;
306
307 /* select to chipc */
308 core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
309
310 /* Determine min/max rsrc masks */
311 si_pmu_res_masks(sih, &min_mask, &max_mask);
312
313 /* It is required to program max_mask first and then min_mask */
314
315 /* Program max resource mask */
316
317 if (max_mask)
318 bcma_write32(core, CHIPCREGOFFS(max_res_mask), max_mask);
319
320 /* Program min resource mask */
321
322 if (min_mask)
323 bcma_write32(core, CHIPCREGOFFS(min_res_mask), min_mask);
324
325 /* Add some delay; allow resources to come up and settle. */
326 mdelay(2);
327}
328
329u32 si_pmu_measure_alpclk(struct si_pub *sih) 172u32 si_pmu_measure_alpclk(struct si_pub *sih)
330{ 173{
174 struct si_info *sii = container_of(sih, struct si_info, pub);
331 struct bcma_device *core; 175 struct bcma_device *core;
332 u32 alp_khz; 176 u32 alp_khz;
333 177
@@ -335,7 +179,7 @@ u32 si_pmu_measure_alpclk(struct si_pub *sih)
335 return 0; 179 return 0;
336 180
337 /* Remember original core before switch to chipc */ 181 /* Remember original core before switch to chipc */
338 core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); 182 core = sii->icbus->drv_cc.core;
339 183
340 if (bcma_read32(core, CHIPCREGOFFS(pmustatus)) & PST_EXTLPOAVAIL) { 184 if (bcma_read32(core, CHIPCREGOFFS(pmustatus)) & PST_EXTLPOAVAIL) {
341 u32 ilp_ctr, alp_hz; 185 u32 ilp_ctr, alp_hz;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h
index 3e39c5e0f9ff..f7cff873578b 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h
@@ -26,10 +26,7 @@ extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
26extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); 26extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
27extern u32 si_pmu_alp_clock(struct si_pub *sih); 27extern u32 si_pmu_alp_clock(struct si_pub *sih);
28extern void si_pmu_pllupd(struct si_pub *sih); 28extern void si_pmu_pllupd(struct si_pub *sih);
29extern void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid);
30extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); 29extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
31extern void si_pmu_init(struct si_pub *sih);
32extern void si_pmu_res_init(struct si_pub *sih);
33extern u32 si_pmu_measure_alpclk(struct si_pub *sih); 30extern u32 si_pmu_measure_alpclk(struct si_pub *sih);
34 31
35#endif /* _BRCM_PMU_H_ */ 32#endif /* _BRCM_PMU_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
index aa5d67f8d874..5855f4fd16dc 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
@@ -311,7 +311,7 @@ extern uint brcms_c_detach(struct brcms_c_info *wlc);
311extern int brcms_c_up(struct brcms_c_info *wlc); 311extern int brcms_c_up(struct brcms_c_info *wlc);
312extern uint brcms_c_down(struct brcms_c_info *wlc); 312extern uint brcms_c_down(struct brcms_c_info *wlc);
313 313
314extern bool brcms_c_chipmatch(u16 vendor, u16 device); 314extern bool brcms_c_chipmatch(struct bcma_device *core);
315extern void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx); 315extern void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx);
316extern void brcms_c_reset(struct brcms_c_info *wlc); 316extern void brcms_c_reset(struct brcms_c_info *wlc);
317 317
diff --git a/drivers/net/wireless/brcm80211/include/soc.h b/drivers/net/wireless/brcm80211/include/soc.h
index 4e9b7e4827ea..123cfa854a0d 100644
--- a/drivers/net/wireless/brcm80211/include/soc.h
+++ b/drivers/net/wireless/brcm80211/include/soc.h
@@ -19,68 +19,6 @@
19 19
20#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */ 20#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */
21 21
22/* core codes */
23#define NODEV_CORE_ID 0x700 /* Invalid coreid */
24#define CC_CORE_ID 0x800 /* chipcommon core */
25#define ILINE20_CORE_ID 0x801 /* iline20 core */
26#define SRAM_CORE_ID 0x802 /* sram core */
27#define SDRAM_CORE_ID 0x803 /* sdram core */
28#define PCI_CORE_ID 0x804 /* pci core */
29#define MIPS_CORE_ID 0x805 /* mips core */
30#define ENET_CORE_ID 0x806 /* enet mac core */
31#define CODEC_CORE_ID 0x807 /* v90 codec core */
32#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */
33#define ADSL_CORE_ID 0x809 /* ADSL core */
34#define ILINE100_CORE_ID 0x80a /* iline100 core */
35#define IPSEC_CORE_ID 0x80b /* ipsec core */
36#define UTOPIA_CORE_ID 0x80c /* utopia core */
37#define PCMCIA_CORE_ID 0x80d /* pcmcia core */
38#define SOCRAM_CORE_ID 0x80e /* internal memory core */
39#define MEMC_CORE_ID 0x80f /* memc sdram core */
40#define OFDM_CORE_ID 0x810 /* OFDM phy core */
41#define EXTIF_CORE_ID 0x811 /* external interface core */
42#define D11_CORE_ID 0x812 /* 802.11 MAC core */
43#define APHY_CORE_ID 0x813 /* 802.11a phy core */
44#define BPHY_CORE_ID 0x814 /* 802.11b phy core */
45#define GPHY_CORE_ID 0x815 /* 802.11g phy core */
46#define MIPS33_CORE_ID 0x816 /* mips3302 core */
47#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */
48#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */
49#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */
50#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */
51#define SDIOH_CORE_ID 0x81b /* sdio host core */
52#define ROBO_CORE_ID 0x81c /* roboswitch core */
53#define ATA100_CORE_ID 0x81d /* parallel ATA core */
54#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */
55#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */
56#define PCIE_CORE_ID 0x820 /* pci express core */
57#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */
58#define SRAMC_CORE_ID 0x822 /* SRAM controller core */
59#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */
60#define ARM11_CORE_ID 0x824 /* ARM 1176 core */
61#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */
62#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */
63#define PMU_CORE_ID 0x827 /* PMU core */
64#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */
65#define SDIOD_CORE_ID 0x829 /* SDIO device core */
66#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */
67#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */
68#define MIPS74K_CORE_ID 0x82c /* mips 74k core */
69#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */
70#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */
71#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */
72#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */
73#define SC_CORE_ID 0x831 /* shared common core */
74#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */
75#define SPIH_CORE_ID 0x833 /* SPI host core */
76#define I2S_CORE_ID 0x834 /* I2S core */
77#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */
78#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */
79#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */
80#define DEF_AI_COMP 0xfff /* Default component, in ai chips it
81 * maps all unused address ranges
82 */
83
84/* Common core control flags */ 22/* Common core control flags */
85#define SICF_BIST_EN 0x8000 23#define SICF_BIST_EN 0x8000
86#define SICF_PME_EN 0x4000 24#define SICF_PME_EN 0x4000
diff --git a/drivers/net/wireless/iwlegacy/3945-rs.c b/drivers/net/wireless/iwlegacy/3945-rs.c
index 4b10157d8686..d4fd29ad90dc 100644
--- a/drivers/net/wireless/iwlegacy/3945-rs.c
+++ b/drivers/net/wireless/iwlegacy/3945-rs.c
@@ -946,7 +946,7 @@ il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
946 case IEEE80211_BAND_5GHZ: 946 case IEEE80211_BAND_5GHZ:
947 rs_sta->expected_tpt = il3945_expected_tpt_a; 947 rs_sta->expected_tpt = il3945_expected_tpt_a;
948 break; 948 break;
949 case IEEE80211_NUM_BANDS: 949 default:
950 BUG(); 950 BUG();
951 break; 951 break;
952 } 952 }
diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h
index 64811cd91635..97bea16f3592 100644
--- a/drivers/net/wireless/iwlwifi/dvm/commands.h
+++ b/drivers/net/wireless/iwlwifi/dvm/commands.h
@@ -190,6 +190,44 @@ enum {
190 REPLY_MAX = 0xff 190 REPLY_MAX = 0xff
191}; 191};
192 192
193/*
194 * Minimum number of queues. MAX_NUM is defined in hw specific files.
195 * Set the minimum to accommodate
196 * - 4 standard TX queues
197 * - the command queue
198 * - 4 PAN TX queues
199 * - the PAN multicast queue, and
200 * - the AUX (TX during scan dwell) queue.
201 */
202#define IWL_MIN_NUM_QUEUES 11
203
204/*
205 * Command queue depends on iPAN support.
206 */
207#define IWL_DEFAULT_CMD_QUEUE_NUM 4
208#define IWL_IPAN_CMD_QUEUE_NUM 9
209
210#define IWL_TX_FIFO_BK 0 /* shared */
211#define IWL_TX_FIFO_BE 1
212#define IWL_TX_FIFO_VI 2 /* shared */
213#define IWL_TX_FIFO_VO 3
214#define IWL_TX_FIFO_BK_IPAN IWL_TX_FIFO_BK
215#define IWL_TX_FIFO_BE_IPAN 4
216#define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI
217#define IWL_TX_FIFO_VO_IPAN 5
218/* re-uses the VO FIFO, uCode will properly flush/schedule */
219#define IWL_TX_FIFO_AUX 5
220#define IWL_TX_FIFO_UNUSED 255
221
222#define IWLAGN_CMD_FIFO_NUM 7
223
224/*
225 * This queue number is required for proper operation
226 * because the ucode will stop/start the scheduler as
227 * required.
228 */
229#define IWL_IPAN_MCAST_QUEUE 8
230
193/****************************************************************************** 231/******************************************************************************
194 * (0) 232 * (0)
195 * Commonly used structures and definitions: 233 * Commonly used structures and definitions:
@@ -755,8 +793,6 @@ struct iwl_qosparam_cmd {
755#define IWLAGN_BROADCAST_ID 15 793#define IWLAGN_BROADCAST_ID 15
756#define IWLAGN_STATION_COUNT 16 794#define IWLAGN_STATION_COUNT 16
757 795
758#define IWL_INVALID_STATION 255
759#define IWL_MAX_TID_COUNT 8
760#define IWL_TID_NON_QOS IWL_MAX_TID_COUNT 796#define IWL_TID_NON_QOS IWL_MAX_TID_COUNT
761 797
762#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) 798#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2)
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
index b0eff1c340c7..46782f1102ac 100644
--- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
@@ -83,7 +83,7 @@ static ssize_t iwl_dbgfs_##name##_write(struct file *file, \
83#define DEBUGFS_READ_FILE_OPS(name) \ 83#define DEBUGFS_READ_FILE_OPS(name) \
84 DEBUGFS_READ_FUNC(name); \ 84 DEBUGFS_READ_FUNC(name); \
85static const struct file_operations iwl_dbgfs_##name##_ops = { \ 85static const struct file_operations iwl_dbgfs_##name##_ops = { \
86 .read = iwl_dbgfs_##name##_read, \ 86 .read = iwl_dbgfs_##name##_read, \
87 .open = simple_open, \ 87 .open = simple_open, \
88 .llseek = generic_file_llseek, \ 88 .llseek = generic_file_llseek, \
89}; 89};
@@ -2255,6 +2255,10 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file,
2255 char buf[8]; 2255 char buf[8];
2256 int buf_size; 2256 int buf_size;
2257 2257
2258 /* check that the interface is up */
2259 if (!iwl_is_ready(priv))
2260 return -EAGAIN;
2261
2258 memset(buf, 0, sizeof(buf)); 2262 memset(buf, 0, sizeof(buf));
2259 buf_size = min(count, sizeof(buf) - 1); 2263 buf_size = min(count, sizeof(buf) - 1);
2260 if (copy_from_user(buf, user_buf, buf_size)) 2264 if (copy_from_user(buf, user_buf, buf_size))
diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h
index 54cf085ddc89..054f728f6266 100644
--- a/drivers/net/wireless/iwlwifi/dvm/dev.h
+++ b/drivers/net/wireless/iwlwifi/dvm/dev.h
@@ -90,22 +90,6 @@
90 90
91#define IWL_NUM_SCAN_RATES (2) 91#define IWL_NUM_SCAN_RATES (2)
92 92
93/*
94 * Minimum number of queues. MAX_NUM is defined in hw specific files.
95 * Set the minimum to accommodate
96 * - 4 standard TX queues
97 * - the command queue
98 * - 4 PAN TX queues
99 * - the PAN multicast queue, and
100 * - the AUX (TX during scan dwell) queue.
101 */
102#define IWL_MIN_NUM_QUEUES 11
103
104/*
105 * Command queue depends on iPAN support.
106 */
107#define IWL_DEFAULT_CMD_QUEUE_NUM 4
108#define IWL_IPAN_CMD_QUEUE_NUM 9
109 93
110#define IEEE80211_DATA_LEN 2304 94#define IEEE80211_DATA_LEN 2304
111#define IEEE80211_4ADDR_LEN 30 95#define IEEE80211_4ADDR_LEN 30
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
index abfd7916bde6..612f05d757db 100644
--- a/drivers/net/wireless/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/iwlwifi/dvm/main.c
@@ -518,49 +518,6 @@ static void iwl_bg_tx_flush(struct work_struct *work)
518 * queue/FIFO/AC mapping definitions 518 * queue/FIFO/AC mapping definitions
519 */ 519 */
520 520
521#define IWL_TX_FIFO_BK 0 /* shared */
522#define IWL_TX_FIFO_BE 1
523#define IWL_TX_FIFO_VI 2 /* shared */
524#define IWL_TX_FIFO_VO 3
525#define IWL_TX_FIFO_BK_IPAN IWL_TX_FIFO_BK
526#define IWL_TX_FIFO_BE_IPAN 4
527#define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI
528#define IWL_TX_FIFO_VO_IPAN 5
529/* re-uses the VO FIFO, uCode will properly flush/schedule */
530#define IWL_TX_FIFO_AUX 5
531#define IWL_TX_FIFO_UNUSED -1
532
533#define IWLAGN_CMD_FIFO_NUM 7
534
535/*
536 * This queue number is required for proper operation
537 * because the ucode will stop/start the scheduler as
538 * required.
539 */
540#define IWL_IPAN_MCAST_QUEUE 8
541
542static const u8 iwlagn_default_queue_to_tx_fifo[] = {
543 IWL_TX_FIFO_VO,
544 IWL_TX_FIFO_VI,
545 IWL_TX_FIFO_BE,
546 IWL_TX_FIFO_BK,
547 IWLAGN_CMD_FIFO_NUM,
548};
549
550static const u8 iwlagn_ipan_queue_to_tx_fifo[] = {
551 IWL_TX_FIFO_VO,
552 IWL_TX_FIFO_VI,
553 IWL_TX_FIFO_BE,
554 IWL_TX_FIFO_BK,
555 IWL_TX_FIFO_BK_IPAN,
556 IWL_TX_FIFO_BE_IPAN,
557 IWL_TX_FIFO_VI_IPAN,
558 IWL_TX_FIFO_VO_IPAN,
559 IWL_TX_FIFO_BE_IPAN,
560 IWLAGN_CMD_FIFO_NUM,
561 IWL_TX_FIFO_AUX,
562};
563
564static const u8 iwlagn_bss_ac_to_fifo[] = { 521static const u8 iwlagn_bss_ac_to_fifo[] = {
565 IWL_TX_FIFO_VO, 522 IWL_TX_FIFO_VO,
566 IWL_TX_FIFO_VI, 523 IWL_TX_FIFO_VI,
@@ -1350,6 +1307,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
1350 else 1307 else
1351 trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED; 1308 trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED;
1352 trans_cfg.command_names = iwl_dvm_cmd_strings; 1309 trans_cfg.command_names = iwl_dvm_cmd_strings;
1310 trans_cfg.cmd_fifo = IWLAGN_CMD_FIFO_NUM;
1353 1311
1354 WARN_ON(sizeof(priv->transport_queue_stop) * BITS_PER_BYTE < 1312 WARN_ON(sizeof(priv->transport_queue_stop) * BITS_PER_BYTE <
1355 priv->cfg->base_params->num_of_queues); 1313 priv->cfg->base_params->num_of_queues);
@@ -1363,15 +1321,9 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
1363 if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) { 1321 if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
1364 priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; 1322 priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
1365 trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; 1323 trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
1366 trans_cfg.queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo;
1367 trans_cfg.n_queue_to_fifo =
1368 ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo);
1369 } else { 1324 } else {
1370 priv->sta_key_max_num = STA_KEY_MAX_NUM; 1325 priv->sta_key_max_num = STA_KEY_MAX_NUM;
1371 trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; 1326 trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
1372 trans_cfg.queue_to_fifo = iwlagn_default_queue_to_tx_fifo;
1373 trans_cfg.n_queue_to_fifo =
1374 ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo);
1375 } 1327 }
1376 1328
1377 /* Configure transport layer */ 1329 /* Configure transport layer */
@@ -1460,9 +1412,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
1460 ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P; 1412 ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
1461 priv->sta_key_max_num = STA_KEY_MAX_NUM; 1413 priv->sta_key_max_num = STA_KEY_MAX_NUM;
1462 trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; 1414 trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
1463 trans_cfg.queue_to_fifo = iwlagn_default_queue_to_tx_fifo;
1464 trans_cfg.n_queue_to_fifo =
1465 ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo);
1466 1415
1467 /* Configure transport layer again*/ 1416 /* Configure transport layer again*/
1468 iwl_trans_configure(priv->trans, &trans_cfg); 1417 iwl_trans_configure(priv->trans, &trans_cfg);
@@ -1480,9 +1429,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
1480 atomic_set(&priv->queue_stop_count[i], 0); 1429 atomic_set(&priv->queue_stop_count[i], 0);
1481 } 1430 }
1482 1431
1483 WARN_ON(trans_cfg.queue_to_fifo[trans_cfg.cmd_queue] !=
1484 IWLAGN_CMD_FIFO_NUM);
1485
1486 if (iwl_init_drv(priv)) 1432 if (iwl_init_drv(priv))
1487 goto out_free_eeprom; 1433 goto out_free_eeprom;
1488 1434
diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c
index 6633074258c7..e3467fa86899 100644
--- a/drivers/net/wireless/iwlwifi/dvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/dvm/scan.c
@@ -396,15 +396,21 @@ static u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
396static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time) 396static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time)
397{ 397{
398 struct iwl_rxon_context *ctx; 398 struct iwl_rxon_context *ctx;
399 int limits[NUM_IWL_RXON_CTX] = {};
400 int n_active = 0;
401 u16 limit;
402
403 BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
399 404
400 /* 405 /*
401 * If we're associated, we clamp the dwell time 98% 406 * If we're associated, we clamp the dwell time 98%
402 * of the smallest beacon interval (minus 2 * channel 407 * of the beacon interval (minus 2 * channel tune time)
403 * tune time) 408 * If both contexts are active, we have to restrict to
409 * 1/2 of the minimum of them, because they might be in
410 * lock-step with the time inbetween only half of what
411 * time we'd have in each of them.
404 */ 412 */
405 for_each_context(priv, ctx) { 413 for_each_context(priv, ctx) {
406 u16 value;
407
408 switch (ctx->staging.dev_type) { 414 switch (ctx->staging.dev_type) {
409 case RXON_DEV_TYPE_P2P: 415 case RXON_DEV_TYPE_P2P:
410 /* no timing constraints */ 416 /* no timing constraints */
@@ -424,14 +430,25 @@ static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time)
424 break; 430 break;
425 } 431 }
426 432
427 value = ctx->beacon_int; 433 limits[n_active++] = ctx->beacon_int ?: IWL_PASSIVE_DWELL_BASE;
428 if (!value)
429 value = IWL_PASSIVE_DWELL_BASE;
430 value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
431 dwell_time = min(value, dwell_time);
432 } 434 }
433 435
434 return dwell_time; 436 switch (n_active) {
437 case 0:
438 return dwell_time;
439 case 2:
440 limit = (limits[1] * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
441 limit /= 2;
442 dwell_time = min(limit, dwell_time);
443 /* fall through to limit further */
444 case 1:
445 limit = (limits[0] * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
446 limit /= n_active;
447 return min(limit, dwell_time);
448 default:
449 WARN_ON_ONCE(1);
450 return dwell_time;
451 }
435} 452}
436 453
437static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, 454static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c
index b3a314ba48c7..6d8d6dd7943f 100644
--- a/drivers/net/wireless/iwlwifi/dvm/ucode.c
+++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c
@@ -226,13 +226,50 @@ int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
226 return ret; 226 return ret;
227} 227}
228 228
229static const u8 iwlagn_default_queue_to_tx_fifo[] = {
230 IWL_TX_FIFO_VO,
231 IWL_TX_FIFO_VI,
232 IWL_TX_FIFO_BE,
233 IWL_TX_FIFO_BK,
234};
235
236static const u8 iwlagn_ipan_queue_to_tx_fifo[] = {
237 IWL_TX_FIFO_VO,
238 IWL_TX_FIFO_VI,
239 IWL_TX_FIFO_BE,
240 IWL_TX_FIFO_BK,
241 IWL_TX_FIFO_BK_IPAN,
242 IWL_TX_FIFO_BE_IPAN,
243 IWL_TX_FIFO_VI_IPAN,
244 IWL_TX_FIFO_VO_IPAN,
245 IWL_TX_FIFO_BE_IPAN,
246 IWL_TX_FIFO_UNUSED,
247 IWL_TX_FIFO_AUX,
248};
229 249
230static int iwl_alive_notify(struct iwl_priv *priv) 250static int iwl_alive_notify(struct iwl_priv *priv)
231{ 251{
252 const u8 *queue_to_txf;
253 u8 n_queues;
232 int ret; 254 int ret;
255 int i;
233 256
234 iwl_trans_fw_alive(priv->trans); 257 iwl_trans_fw_alive(priv->trans);
235 258
259 if (priv->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN &&
260 priv->eeprom_data->sku & EEPROM_SKU_CAP_IPAN_ENABLE) {
261 n_queues = ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo);
262 queue_to_txf = iwlagn_ipan_queue_to_tx_fifo;
263 } else {
264 n_queues = ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo);
265 queue_to_txf = iwlagn_default_queue_to_tx_fifo;
266 }
267
268 for (i = 0; i < n_queues; i++)
269 if (queue_to_txf[i] != IWL_TX_FIFO_UNUSED)
270 iwl_trans_ac_txq_enable(priv->trans, i,
271 queue_to_txf[i]);
272
236 priv->passive_no_rx = false; 273 priv->passive_no_rx = false;
237 priv->transport_queue_stop = 0; 274 priv->transport_queue_stop = 0;
238 275
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.c b/drivers/net/wireless/iwlwifi/iwl-debug.c
index 0f8fcd1d4fe2..87535a67de76 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.c
@@ -61,6 +61,9 @@
61 * 61 *
62 *****************************************************************************/ 62 *****************************************************************************/
63 63
64#define DEBUG
65
66#include <linux/device.h>
64#include <linux/interrupt.h> 67#include <linux/interrupt.h>
65#include <linux/export.h> 68#include <linux/export.h>
66#include "iwl-debug.h" 69#include "iwl-debug.h"
@@ -124,7 +127,7 @@ void __iwl_dbg(struct device *dev,
124#ifdef CONFIG_IWLWIFI_DEBUG 127#ifdef CONFIG_IWLWIFI_DEBUG
125 if (iwl_have_debug_level(level) && 128 if (iwl_have_debug_level(level) &&
126 (!limit || net_ratelimit())) 129 (!limit || net_ratelimit()))
127 dev_err(dev, "%c %s %pV", in_interrupt() ? 'I' : 'U', 130 dev_dbg(dev, "%c %s %pV", in_interrupt() ? 'I' : 'U',
128 function, &vaf); 131 function, &vaf);
129#endif 132#endif
130 trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf); 133 trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf);
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
index 65364793021f..06ca505bb2cc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h
+++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
@@ -176,7 +176,7 @@ TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
176#undef TRACE_SYSTEM 176#undef TRACE_SYSTEM
177#define TRACE_SYSTEM iwlwifi_msg 177#define TRACE_SYSTEM iwlwifi_msg
178 178
179#define MAX_MSG_LEN 100 179#define MAX_MSG_LEN 110
180 180
181DECLARE_EVENT_CLASS(iwlwifi_msg_event, 181DECLARE_EVENT_CLASS(iwlwifi_msg_event,
182 TP_PROTO(struct va_format *vaf), 182 TP_PROTO(struct va_format *vaf),
@@ -189,7 +189,7 @@ DECLARE_EVENT_CLASS(iwlwifi_msg_event,
189 MAX_MSG_LEN, vaf->fmt, 189 MAX_MSG_LEN, vaf->fmt,
190 *vaf->va) >= MAX_MSG_LEN); 190 *vaf->va) >= MAX_MSG_LEN);
191 ), 191 ),
192 TP_printk("%s", (char *)__get_dynamic_array(msg)) 192 TP_printk("%s", __get_str(msg))
193); 193);
194 194
195DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_err, 195DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_err,
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index a175997e7829..cc41cfaedfbd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -1013,6 +1013,7 @@ struct iwl_mod_params iwlwifi_mod_params = {
1013 .power_level = IWL_POWER_INDEX_1, 1013 .power_level = IWL_POWER_INDEX_1,
1014 .bt_ch_announce = true, 1014 .bt_ch_announce = true,
1015 .auto_agg = true, 1015 .auto_agg = true,
1016 .wd_disable = true,
1016 /* the rest are 0 by default */ 1017 /* the rest are 0 by default */
1017}; 1018};
1018EXPORT_SYMBOL_GPL(iwlwifi_mod_params); 1019EXPORT_SYMBOL_GPL(iwlwifi_mod_params);
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 00efde8e5536..867d8e194da4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -290,16 +290,17 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r)
290 * currently supports 290 * currently supports
291 */ 291 */
292#define IWL_MAX_HW_QUEUES 32 292#define IWL_MAX_HW_QUEUES 32
293#define IWL_INVALID_STATION 255
294#define IWL_MAX_TID_COUNT 8
295#define IWL_FRAME_LIMIT 64
293 296
294/** 297/**
295 * struct iwl_trans_config - transport configuration 298 * struct iwl_trans_config - transport configuration
296 * 299 *
297 * @op_mode: pointer to the upper layer. 300 * @op_mode: pointer to the upper layer.
298 * @queue_to_fifo: queue to FIFO mapping to set up by
299 * default
300 * @n_queue_to_fifo: number of queues to set up
301 * @cmd_queue: the index of the command queue. 301 * @cmd_queue: the index of the command queue.
302 * Must be set before start_fw. 302 * Must be set before start_fw.
303 * @cmd_fifo: the fifo for host commands
303 * @no_reclaim_cmds: Some devices erroneously don't set the 304 * @no_reclaim_cmds: Some devices erroneously don't set the
304 * SEQ_RX_FRAME bit on some notifications, this is the 305 * SEQ_RX_FRAME bit on some notifications, this is the
305 * list of such notifications to filter. Max length is 306 * list of such notifications to filter. Max length is
@@ -314,10 +315,9 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r)
314 */ 315 */
315struct iwl_trans_config { 316struct iwl_trans_config {
316 struct iwl_op_mode *op_mode; 317 struct iwl_op_mode *op_mode;
317 const u8 *queue_to_fifo;
318 u8 n_queue_to_fifo;
319 318
320 u8 cmd_queue; 319 u8 cmd_queue;
320 u8 cmd_fifo;
321 const u8 *no_reclaim_cmds; 321 const u8 *no_reclaim_cmds;
322 int n_no_reclaim_cmds; 322 int n_no_reclaim_cmds;
323 323
@@ -355,9 +355,9 @@ struct iwl_trans;
355 * Must be atomic 355 * Must be atomic
356 * @reclaim: free packet until ssn. Returns a list of freed packets. 356 * @reclaim: free packet until ssn. Returns a list of freed packets.
357 * Must be atomic 357 * Must be atomic
358 * @txq_enable: setup a tx queue for AMPDU - will be called once the HW is 358 * @txq_enable: setup a queue. To setup an AC queue, use the
359 * ready and a successful ADDBA response has been received. 359 * iwl_trans_ac_txq_enable wrapper. fw_alive must have been called before
360 * May sleep 360 * this one. The op_mode must not configure the HCMD queue. May sleep.
361 * @txq_disable: de-configure a Tx queue to send AMPDUs 361 * @txq_disable: de-configure a Tx queue to send AMPDUs
362 * Must be atomic 362 * Must be atomic
363 * @wait_tx_queue_empty: wait until all tx queues are empty 363 * @wait_tx_queue_empty: wait until all tx queues are empty
@@ -497,9 +497,9 @@ static inline void iwl_trans_fw_alive(struct iwl_trans *trans)
497{ 497{
498 might_sleep(); 498 might_sleep();
499 499
500 trans->ops->fw_alive(trans);
501
502 trans->state = IWL_TRANS_FW_ALIVE; 500 trans->state = IWL_TRANS_FW_ALIVE;
501
502 trans->ops->fw_alive(trans);
503} 503}
504 504
505static inline int iwl_trans_start_fw(struct iwl_trans *trans, 505static inline int iwl_trans_start_fw(struct iwl_trans *trans,
@@ -593,6 +593,13 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue,
593 frame_limit, ssn); 593 frame_limit, ssn);
594} 594}
595 595
596static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue,
597 int fifo)
598{
599 iwl_trans_txq_enable(trans, queue, fifo, IWL_INVALID_STATION,
600 IWL_MAX_TID_COUNT, IWL_FRAME_LIMIT, 0);
601}
602
596static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) 603static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans)
597{ 604{
598 WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, 605 WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index 5024fb662bf6..d9694c58208c 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -269,10 +269,9 @@ struct iwl_trans_pcie {
269 wait_queue_head_t ucode_write_waitq; 269 wait_queue_head_t ucode_write_waitq;
270 unsigned long status; 270 unsigned long status;
271 u8 cmd_queue; 271 u8 cmd_queue;
272 u8 cmd_fifo;
272 u8 n_no_reclaim_cmds; 273 u8 n_no_reclaim_cmds;
273 u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; 274 u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS];
274 u8 setup_q_to_fifo[IWL_MAX_HW_QUEUES];
275 u8 n_q_to_fifo;
276 275
277 bool rx_buf_size_8k; 276 bool rx_buf_size_8k;
278 u32 rx_page_order; 277 u32 rx_page_order;
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index be143eb4aa4f..39a6ca1f009c 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -879,9 +879,6 @@ static irqreturn_t iwl_isr(int irq, void *data)
879 879
880 lockdep_assert_held(&trans_pcie->irq_lock); 880 lockdep_assert_held(&trans_pcie->irq_lock);
881 881
882 if (!trans)
883 return IRQ_NONE;
884
885 trace_iwlwifi_dev_irq(trans->dev); 882 trace_iwlwifi_dev_irq(trans->dev);
886 883
887 /* Disable (but don't clear!) interrupts here to avoid 884 /* Disable (but don't clear!) interrupts here to avoid
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index d1950838f17f..09795afccb23 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -1059,7 +1059,7 @@ static void iwl_tx_start(struct iwl_trans *trans)
1059{ 1059{
1060 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1060 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
1061 u32 a; 1061 u32 a;
1062 int i, chan; 1062 int chan;
1063 u32 reg_val; 1063 u32 reg_val;
1064 1064
1065 /* make sure all queue are not stopped/used */ 1065 /* make sure all queue are not stopped/used */
@@ -1091,12 +1091,8 @@ static void iwl_tx_start(struct iwl_trans *trans)
1091 */ 1091 */
1092 iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); 1092 iwl_write_prph(trans, SCD_CHAINEXT_EN, 0);
1093 1093
1094 for (i = 0; i < trans_pcie->n_q_to_fifo; i++) { 1094 iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue,
1095 int fifo = trans_pcie->setup_q_to_fifo[i]; 1095 trans_pcie->cmd_fifo);
1096
1097 iwl_trans_pcie_txq_enable(trans, i, fifo, IWL_INVALID_STATION,
1098 IWL_TID_NON_QOS, SCD_FRAME_LIMIT, 0);
1099 }
1100 1096
1101 /* Activate all Tx DMA/FIFO channels */ 1097 /* Activate all Tx DMA/FIFO channels */
1102 iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); 1098 iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7));
@@ -1145,7 +1141,7 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
1145 FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000); 1141 FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000);
1146 if (ret < 0) 1142 if (ret < 0)
1147 IWL_ERR(trans, 1143 IWL_ERR(trans,
1148 "Failing on timeout while stopping DMA channel %d [0x%08x]", 1144 "Failing on timeout while stopping DMA channel %d [0x%08x]\n",
1149 ch, 1145 ch,
1150 iwl_read_direct32(trans, 1146 iwl_read_direct32(trans,
1151 FH_TSSR_TX_STATUS_REG)); 1147 FH_TSSR_TX_STATUS_REG));
@@ -1153,7 +1149,8 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
1153 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); 1149 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
1154 1150
1155 if (!trans_pcie->txq) { 1151 if (!trans_pcie->txq) {
1156 IWL_WARN(trans, "Stopping tx queues that aren't allocated..."); 1152 IWL_WARN(trans,
1153 "Stopping tx queues that aren't allocated...\n");
1157 return 0; 1154 return 0;
1158 } 1155 }
1159 1156
@@ -1430,7 +1427,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
1430 1427
1431 err = iwl_prepare_card_hw(trans); 1428 err = iwl_prepare_card_hw(trans);
1432 if (err) { 1429 if (err) {
1433 IWL_ERR(trans, "Error while preparing HW: %d", err); 1430 IWL_ERR(trans, "Error while preparing HW: %d\n", err);
1434 goto err_free_irq; 1431 goto err_free_irq;
1435 } 1432 }
1436 1433
@@ -1528,6 +1525,7 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans,
1528 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1525 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
1529 1526
1530 trans_pcie->cmd_queue = trans_cfg->cmd_queue; 1527 trans_pcie->cmd_queue = trans_cfg->cmd_queue;
1528 trans_pcie->cmd_fifo = trans_cfg->cmd_fifo;
1531 if (WARN_ON(trans_cfg->n_no_reclaim_cmds > MAX_NO_RECLAIM_CMDS)) 1529 if (WARN_ON(trans_cfg->n_no_reclaim_cmds > MAX_NO_RECLAIM_CMDS))
1532 trans_pcie->n_no_reclaim_cmds = 0; 1530 trans_pcie->n_no_reclaim_cmds = 0;
1533 else 1531 else
@@ -1536,17 +1534,6 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans,
1536 memcpy(trans_pcie->no_reclaim_cmds, trans_cfg->no_reclaim_cmds, 1534 memcpy(trans_pcie->no_reclaim_cmds, trans_cfg->no_reclaim_cmds,
1537 trans_pcie->n_no_reclaim_cmds * sizeof(u8)); 1535 trans_pcie->n_no_reclaim_cmds * sizeof(u8));
1538 1536
1539 trans_pcie->n_q_to_fifo = trans_cfg->n_queue_to_fifo;
1540
1541 if (WARN_ON(trans_pcie->n_q_to_fifo > IWL_MAX_HW_QUEUES))
1542 trans_pcie->n_q_to_fifo = IWL_MAX_HW_QUEUES;
1543
1544 /* at least the command queue must be mapped */
1545 WARN_ON(!trans_pcie->n_q_to_fifo);
1546
1547 memcpy(trans_pcie->setup_q_to_fifo, trans_cfg->queue_to_fifo,
1548 trans_pcie->n_q_to_fifo * sizeof(u8));
1549
1550 trans_pcie->rx_buf_size_8k = trans_cfg->rx_buf_size_8k; 1537 trans_pcie->rx_buf_size_8k = trans_cfg->rx_buf_size_8k;
1551 if (trans_pcie->rx_buf_size_8k) 1538 if (trans_pcie->rx_buf_size_8k)
1552 trans_pcie->rx_page_order = get_order(8 * 1024); 1539 trans_pcie->rx_page_order = get_order(8 * 1024);
@@ -2141,13 +2128,14 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
2141 2128
2142 err = pci_request_regions(pdev, DRV_NAME); 2129 err = pci_request_regions(pdev, DRV_NAME);
2143 if (err) { 2130 if (err) {
2144 dev_printk(KERN_ERR, &pdev->dev, "pci_request_regions failed"); 2131 dev_printk(KERN_ERR, &pdev->dev,
2132 "pci_request_regions failed\n");
2145 goto out_pci_disable_device; 2133 goto out_pci_disable_device;
2146 } 2134 }
2147 2135
2148 trans_pcie->hw_base = pci_ioremap_bar(pdev, 0); 2136 trans_pcie->hw_base = pci_ioremap_bar(pdev, 0);
2149 if (!trans_pcie->hw_base) { 2137 if (!trans_pcie->hw_base) {
2150 dev_printk(KERN_ERR, &pdev->dev, "pci_ioremap_bar failed"); 2138 dev_printk(KERN_ERR, &pdev->dev, "pci_ioremap_bar failed\n");
2151 err = -ENODEV; 2139 err = -ENODEV;
2152 goto out_pci_release_regions; 2140 goto out_pci_release_regions;
2153 } 2141 }
@@ -2168,7 +2156,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
2168 err = pci_enable_msi(pdev); 2156 err = pci_enable_msi(pdev);
2169 if (err) 2157 if (err)
2170 dev_printk(KERN_ERR, &pdev->dev, 2158 dev_printk(KERN_ERR, &pdev->dev,
2171 "pci_enable_msi failed(0X%x)", err); 2159 "pci_enable_msi failed(0X%x)\n", err);
2172 2160
2173 trans->dev = &pdev->dev; 2161 trans->dev = &pdev->dev;
2174 trans_pcie->irq = pdev->irq; 2162 trans_pcie->irq = pdev->irq;
diff --git a/drivers/net/wireless/iwmc3200wifi/Kconfig b/drivers/net/wireless/iwmc3200wifi/Kconfig
deleted file mode 100644
index 7107ce53d4d4..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/Kconfig
+++ /dev/null
@@ -1,39 +0,0 @@
1config IWM
2 tristate "Intel Wireless Multicomm 3200 WiFi driver (EXPERIMENTAL)"
3 depends on MMC && EXPERIMENTAL
4 depends on CFG80211
5 select FW_LOADER
6 select IWMC3200TOP
7 help
8 The Intel Wireless Multicomm 3200 hardware is a combo
9 card with GPS, Bluetooth, WiMax and 802.11 radios. It
10 runs over SDIO and is typically found on Moorestown
11 based platform. This driver takes care of the 802.11
12 part, which is a fullmac one.
13
14 If you choose to build it as a module, it'll be called
15 iwmc3200wifi.ko.
16
17config IWM_DEBUG
18 bool "Enable full debugging output in iwmc3200wifi"
19 depends on IWM && DEBUG_FS
20 help
21 This option will enable debug tracing and setting for iwm
22
23 You can set the debug level and module through debugfs. By
24 default all modules are set to the IWL_DL_ERR level.
25 To see the list of debug modules and levels, see iwm/debug.h
26
27 For example, if you want the full MLME debug output:
28 echo 0xff > /sys/kernel/debug/iwm/phyN/debug/mlme
29
30 Or, if you want the full debug, for all modules:
31 echo 0xff > /sys/kernel/debug/iwm/phyN/debug/level
32 echo 0xff > /sys/kernel/debug/iwm/phyN/debug/modules
33
34config IWM_TRACING
35 bool "Enable event tracing for iwmc3200wifi"
36 depends on IWM && EVENT_TRACING
37 help
38 Say Y here to trace all the commands and responses between
39 the driver and firmware (including TX/RX frames) with ftrace.
diff --git a/drivers/net/wireless/iwmc3200wifi/Makefile b/drivers/net/wireless/iwmc3200wifi/Makefile
deleted file mode 100644
index cdc7e07ba113..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
1obj-$(CONFIG_IWM) := iwmc3200wifi.o
2iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o
3iwmc3200wifi-objs += commands.o cfg80211.o eeprom.o
4
5iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o
6iwmc3200wifi-$(CONFIG_IWM_TRACING) += trace.o
7
8CFLAGS_trace.o := -I$(src)
9
10ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/iwmc3200wifi/bus.h b/drivers/net/wireless/iwmc3200wifi/bus.h
deleted file mode 100644
index 62edd5888a7b..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/bus.h
+++ /dev/null
@@ -1,57 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 */
23
24#ifndef __IWM_BUS_H__
25#define __IWM_BUS_H__
26
27#include "iwm.h"
28
29struct iwm_if_ops {
30 int (*enable)(struct iwm_priv *iwm);
31 int (*disable)(struct iwm_priv *iwm);
32 int (*send_chunk)(struct iwm_priv *iwm, u8* buf, int count);
33
34 void (*debugfs_init)(struct iwm_priv *iwm, struct dentry *parent_dir);
35 void (*debugfs_exit)(struct iwm_priv *iwm);
36
37 const char *umac_name;
38 const char *calib_lmac_name;
39 const char *lmac_name;
40};
41
42static inline int iwm_bus_send_chunk(struct iwm_priv *iwm, u8 *buf, int count)
43{
44 return iwm->bus_ops->send_chunk(iwm, buf, count);
45}
46
47static inline int iwm_bus_enable(struct iwm_priv *iwm)
48{
49 return iwm->bus_ops->enable(iwm);
50}
51
52static inline int iwm_bus_disable(struct iwm_priv *iwm)
53{
54 return iwm->bus_ops->disable(iwm);
55}
56
57#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
deleted file mode 100644
index 48e8218fd23b..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c
+++ /dev/null
@@ -1,882 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 */
23
24#include <linux/kernel.h>
25#include <linux/netdevice.h>
26#include <linux/sched.h>
27#include <linux/etherdevice.h>
28#include <linux/wireless.h>
29#include <linux/ieee80211.h>
30#include <linux/slab.h>
31#include <net/cfg80211.h>
32
33#include "iwm.h"
34#include "commands.h"
35#include "cfg80211.h"
36#include "debug.h"
37
38#define RATETAB_ENT(_rate, _rateid, _flags) \
39 { \
40 .bitrate = (_rate), \
41 .hw_value = (_rateid), \
42 .flags = (_flags), \
43 }
44
45#define CHAN2G(_channel, _freq, _flags) { \
46 .band = IEEE80211_BAND_2GHZ, \
47 .center_freq = (_freq), \
48 .hw_value = (_channel), \
49 .flags = (_flags), \
50 .max_antenna_gain = 0, \
51 .max_power = 30, \
52}
53
54#define CHAN5G(_channel, _flags) { \
55 .band = IEEE80211_BAND_5GHZ, \
56 .center_freq = 5000 + (5 * (_channel)), \
57 .hw_value = (_channel), \
58 .flags = (_flags), \
59 .max_antenna_gain = 0, \
60 .max_power = 30, \
61}
62
63static struct ieee80211_rate iwm_rates[] = {
64 RATETAB_ENT(10, 0x1, 0),
65 RATETAB_ENT(20, 0x2, 0),
66 RATETAB_ENT(55, 0x4, 0),
67 RATETAB_ENT(110, 0x8, 0),
68 RATETAB_ENT(60, 0x10, 0),
69 RATETAB_ENT(90, 0x20, 0),
70 RATETAB_ENT(120, 0x40, 0),
71 RATETAB_ENT(180, 0x80, 0),
72 RATETAB_ENT(240, 0x100, 0),
73 RATETAB_ENT(360, 0x200, 0),
74 RATETAB_ENT(480, 0x400, 0),
75 RATETAB_ENT(540, 0x800, 0),
76};
77
78#define iwm_a_rates (iwm_rates + 4)
79#define iwm_a_rates_size 8
80#define iwm_g_rates (iwm_rates + 0)
81#define iwm_g_rates_size 12
82
83static struct ieee80211_channel iwm_2ghz_channels[] = {
84 CHAN2G(1, 2412, 0),
85 CHAN2G(2, 2417, 0),
86 CHAN2G(3, 2422, 0),
87 CHAN2G(4, 2427, 0),
88 CHAN2G(5, 2432, 0),
89 CHAN2G(6, 2437, 0),
90 CHAN2G(7, 2442, 0),
91 CHAN2G(8, 2447, 0),
92 CHAN2G(9, 2452, 0),
93 CHAN2G(10, 2457, 0),
94 CHAN2G(11, 2462, 0),
95 CHAN2G(12, 2467, 0),
96 CHAN2G(13, 2472, 0),
97 CHAN2G(14, 2484, 0),
98};
99
100static struct ieee80211_channel iwm_5ghz_a_channels[] = {
101 CHAN5G(34, 0), CHAN5G(36, 0),
102 CHAN5G(38, 0), CHAN5G(40, 0),
103 CHAN5G(42, 0), CHAN5G(44, 0),
104 CHAN5G(46, 0), CHAN5G(48, 0),
105 CHAN5G(52, 0), CHAN5G(56, 0),
106 CHAN5G(60, 0), CHAN5G(64, 0),
107 CHAN5G(100, 0), CHAN5G(104, 0),
108 CHAN5G(108, 0), CHAN5G(112, 0),
109 CHAN5G(116, 0), CHAN5G(120, 0),
110 CHAN5G(124, 0), CHAN5G(128, 0),
111 CHAN5G(132, 0), CHAN5G(136, 0),
112 CHAN5G(140, 0), CHAN5G(149, 0),
113 CHAN5G(153, 0), CHAN5G(157, 0),
114 CHAN5G(161, 0), CHAN5G(165, 0),
115 CHAN5G(184, 0), CHAN5G(188, 0),
116 CHAN5G(192, 0), CHAN5G(196, 0),
117 CHAN5G(200, 0), CHAN5G(204, 0),
118 CHAN5G(208, 0), CHAN5G(212, 0),
119 CHAN5G(216, 0),
120};
121
122static struct ieee80211_supported_band iwm_band_2ghz = {
123 .channels = iwm_2ghz_channels,
124 .n_channels = ARRAY_SIZE(iwm_2ghz_channels),
125 .bitrates = iwm_g_rates,
126 .n_bitrates = iwm_g_rates_size,
127};
128
129static struct ieee80211_supported_band iwm_band_5ghz = {
130 .channels = iwm_5ghz_a_channels,
131 .n_channels = ARRAY_SIZE(iwm_5ghz_a_channels),
132 .bitrates = iwm_a_rates,
133 .n_bitrates = iwm_a_rates_size,
134};
135
136static int iwm_key_init(struct iwm_key *key, u8 key_index,
137 const u8 *mac_addr, struct key_params *params)
138{
139 key->hdr.key_idx = key_index;
140 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
141 key->hdr.multicast = 1;
142 memset(key->hdr.mac, 0xff, ETH_ALEN);
143 } else {
144 key->hdr.multicast = 0;
145 memcpy(key->hdr.mac, mac_addr, ETH_ALEN);
146 }
147
148 if (params) {
149 if (params->key_len > WLAN_MAX_KEY_LEN ||
150 params->seq_len > IW_ENCODE_SEQ_MAX_SIZE)
151 return -EINVAL;
152
153 key->cipher = params->cipher;
154 key->key_len = params->key_len;
155 key->seq_len = params->seq_len;
156 memcpy(key->key, params->key, key->key_len);
157 memcpy(key->seq, params->seq, key->seq_len);
158 }
159
160 return 0;
161}
162
163static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
164 u8 key_index, bool pairwise, const u8 *mac_addr,
165 struct key_params *params)
166{
167 struct iwm_priv *iwm = ndev_to_iwm(ndev);
168 struct iwm_key *key;
169 int ret;
170
171 IWM_DBG_WEXT(iwm, DBG, "Adding key for %pM\n", mac_addr);
172
173 if (key_index >= IWM_NUM_KEYS)
174 return -ENOENT;
175
176 key = &iwm->keys[key_index];
177 memset(key, 0, sizeof(struct iwm_key));
178 ret = iwm_key_init(key, key_index, mac_addr, params);
179 if (ret < 0) {
180 IWM_ERR(iwm, "Invalid key_params\n");
181 return ret;
182 }
183
184 return iwm_set_key(iwm, 0, key);
185}
186
187static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
188 u8 key_index, bool pairwise, const u8 *mac_addr,
189 void *cookie,
190 void (*callback)(void *cookie,
191 struct key_params*))
192{
193 struct iwm_priv *iwm = ndev_to_iwm(ndev);
194 struct iwm_key *key;
195 struct key_params params;
196
197 IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index);
198
199 if (key_index >= IWM_NUM_KEYS)
200 return -ENOENT;
201
202 memset(&params, 0, sizeof(params));
203
204 key = &iwm->keys[key_index];
205 params.cipher = key->cipher;
206 params.key_len = key->key_len;
207 params.seq_len = key->seq_len;
208 params.seq = key->seq;
209 params.key = key->key;
210
211 callback(cookie, &params);
212
213 return key->key_len ? 0 : -ENOENT;
214}
215
216
217static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
218 u8 key_index, bool pairwise, const u8 *mac_addr)
219{
220 struct iwm_priv *iwm = ndev_to_iwm(ndev);
221 struct iwm_key *key;
222
223 if (key_index >= IWM_NUM_KEYS)
224 return -ENOENT;
225
226 key = &iwm->keys[key_index];
227 if (!iwm->keys[key_index].key_len) {
228 IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index);
229 return 0;
230 }
231
232 if (key_index == iwm->default_key)
233 iwm->default_key = -1;
234
235 return iwm_set_key(iwm, 1, key);
236}
237
238static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
239 struct net_device *ndev,
240 u8 key_index, bool unicast,
241 bool multicast)
242{
243 struct iwm_priv *iwm = ndev_to_iwm(ndev);
244
245 IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index);
246
247 if (key_index >= IWM_NUM_KEYS)
248 return -ENOENT;
249
250 if (!iwm->keys[key_index].key_len) {
251 IWM_ERR(iwm, "Key %d not used\n", key_index);
252 return -EINVAL;
253 }
254
255 iwm->default_key = key_index;
256
257 return iwm_set_tx_key(iwm, key_index);
258}
259
260static int iwm_cfg80211_get_station(struct wiphy *wiphy,
261 struct net_device *ndev,
262 u8 *mac, struct station_info *sinfo)
263{
264 struct iwm_priv *iwm = ndev_to_iwm(ndev);
265
266 if (memcmp(mac, iwm->bssid, ETH_ALEN))
267 return -ENOENT;
268
269 sinfo->filled |= STATION_INFO_TX_BITRATE;
270 sinfo->txrate.legacy = iwm->rate * 10;
271
272 if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
273 sinfo->filled |= STATION_INFO_SIGNAL;
274 sinfo->signal = iwm->wstats.qual.level;
275 }
276
277 return 0;
278}
279
280
281int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
282{
283 struct wiphy *wiphy = iwm_to_wiphy(iwm);
284 struct iwm_bss_info *bss;
285 struct iwm_umac_notif_bss_info *umac_bss;
286 struct ieee80211_mgmt *mgmt;
287 struct ieee80211_channel *channel;
288 struct ieee80211_supported_band *band;
289 s32 signal;
290 int freq;
291
292 list_for_each_entry(bss, &iwm->bss_list, node) {
293 umac_bss = bss->bss;
294 mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
295
296 if (umac_bss->band == UMAC_BAND_2GHZ)
297 band = wiphy->bands[IEEE80211_BAND_2GHZ];
298 else if (umac_bss->band == UMAC_BAND_5GHZ)
299 band = wiphy->bands[IEEE80211_BAND_5GHZ];
300 else {
301 IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
302 return -EINVAL;
303 }
304
305 freq = ieee80211_channel_to_frequency(umac_bss->channel,
306 band->band);
307 channel = ieee80211_get_channel(wiphy, freq);
308 signal = umac_bss->rssi * 100;
309
310 if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
311 le16_to_cpu(umac_bss->frame_len),
312 signal, GFP_KERNEL))
313 return -EINVAL;
314 }
315
316 return 0;
317}
318
319static int iwm_cfg80211_change_iface(struct wiphy *wiphy,
320 struct net_device *ndev,
321 enum nl80211_iftype type, u32 *flags,
322 struct vif_params *params)
323{
324 struct wireless_dev *wdev;
325 struct iwm_priv *iwm;
326 u32 old_mode;
327
328 wdev = ndev->ieee80211_ptr;
329 iwm = ndev_to_iwm(ndev);
330 old_mode = iwm->conf.mode;
331
332 switch (type) {
333 case NL80211_IFTYPE_STATION:
334 iwm->conf.mode = UMAC_MODE_BSS;
335 break;
336 case NL80211_IFTYPE_ADHOC:
337 iwm->conf.mode = UMAC_MODE_IBSS;
338 break;
339 default:
340 return -EOPNOTSUPP;
341 }
342
343 wdev->iftype = type;
344
345 if ((old_mode == iwm->conf.mode) || !iwm->umac_profile)
346 return 0;
347
348 iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
349
350 if (iwm->umac_profile_active)
351 iwm_invalidate_mlme_profile(iwm);
352
353 return 0;
354}
355
356static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
357 struct cfg80211_scan_request *request)
358{
359 struct iwm_priv *iwm = ndev_to_iwm(ndev);
360 int ret;
361
362 if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
363 IWM_ERR(iwm, "Scan while device is not ready\n");
364 return -EIO;
365 }
366
367 if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) {
368 IWM_ERR(iwm, "Scanning already\n");
369 return -EAGAIN;
370 }
371
372 if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) {
373 IWM_ERR(iwm, "Scanning being aborted\n");
374 return -EAGAIN;
375 }
376
377 set_bit(IWM_STATUS_SCANNING, &iwm->status);
378
379 ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids);
380 if (ret) {
381 clear_bit(IWM_STATUS_SCANNING, &iwm->status);
382 return ret;
383 }
384
385 iwm->scan_request = request;
386 return 0;
387}
388
389static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
390{
391 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
392
393 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
394 (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
395 int ret;
396
397 iwm->conf.rts_threshold = wiphy->rts_threshold;
398
399 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
400 CFG_RTS_THRESHOLD,
401 iwm->conf.rts_threshold);
402 if (ret < 0)
403 return ret;
404 }
405
406 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
407 (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
408 int ret;
409
410 iwm->conf.frag_threshold = wiphy->frag_threshold;
411
412 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
413 CFG_FRAG_THRESHOLD,
414 iwm->conf.frag_threshold);
415 if (ret < 0)
416 return ret;
417 }
418
419 return 0;
420}
421
422static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
423 struct cfg80211_ibss_params *params)
424{
425 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
426 struct ieee80211_channel *chan = params->channel;
427
428 if (!test_bit(IWM_STATUS_READY, &iwm->status))
429 return -EIO;
430
431 /* UMAC doesn't support creating or joining an IBSS network
432 * with specified bssid. */
433 if (params->bssid)
434 return -EOPNOTSUPP;
435
436 iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
437 iwm->umac_profile->ibss.band = chan->band;
438 iwm->umac_profile->ibss.channel = iwm->channel;
439 iwm->umac_profile->ssid.ssid_len = params->ssid_len;
440 memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
441
442 return iwm_send_mlme_profile(iwm);
443}
444
445static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
446{
447 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
448
449 if (iwm->umac_profile_active)
450 return iwm_invalidate_mlme_profile(iwm);
451
452 return 0;
453}
454
455static int iwm_set_auth_type(struct iwm_priv *iwm,
456 enum nl80211_auth_type sme_auth_type)
457{
458 u8 *auth_type = &iwm->umac_profile->sec.auth_type;
459
460 switch (sme_auth_type) {
461 case NL80211_AUTHTYPE_AUTOMATIC:
462 case NL80211_AUTHTYPE_OPEN_SYSTEM:
463 IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n");
464 *auth_type = UMAC_AUTH_TYPE_OPEN;
465 break;
466 case NL80211_AUTHTYPE_SHARED_KEY:
467 if (iwm->umac_profile->sec.flags &
468 (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
469 IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n");
470 *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
471 } else {
472 IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n");
473 *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
474 }
475
476 break;
477 default:
478 IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type);
479 return -ENOTSUPP;
480 }
481
482 return 0;
483}
484
485static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
486{
487 IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version);
488
489 if (!wpa_version) {
490 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
491 return 0;
492 }
493
494 if (wpa_version & NL80211_WPA_VERSION_1)
495 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK;
496
497 if (wpa_version & NL80211_WPA_VERSION_2)
498 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
499
500 return 0;
501}
502
503static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast)
504{
505 u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
506 &iwm->umac_profile->sec.mcast_cipher;
507
508 if (!cipher) {
509 *profile_cipher = UMAC_CIPHER_TYPE_NONE;
510 return 0;
511 }
512
513 IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm',
514 cipher);
515
516 switch (cipher) {
517 case IW_AUTH_CIPHER_NONE:
518 *profile_cipher = UMAC_CIPHER_TYPE_NONE;
519 break;
520 case WLAN_CIPHER_SUITE_WEP40:
521 *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
522 break;
523 case WLAN_CIPHER_SUITE_WEP104:
524 *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
525 break;
526 case WLAN_CIPHER_SUITE_TKIP:
527 *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
528 break;
529 case WLAN_CIPHER_SUITE_CCMP:
530 *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
531 break;
532 default:
533 IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
534 return -ENOTSUPP;
535 }
536
537 return 0;
538}
539
540static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt)
541{
542 u8 *auth_type = &iwm->umac_profile->sec.auth_type;
543
544 IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
545
546 if (key_mgt == WLAN_AKM_SUITE_8021X)
547 *auth_type = UMAC_AUTH_TYPE_8021X;
548 else if (key_mgt == WLAN_AKM_SUITE_PSK) {
549 if (iwm->umac_profile->sec.flags &
550 (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
551 *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
552 else
553 *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
554 } else {
555 IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
556 return -EINVAL;
557 }
558
559 return 0;
560}
561
562
563static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
564 struct cfg80211_connect_params *sme)
565{
566 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
567 struct ieee80211_channel *chan = sme->channel;
568 struct key_params key_param;
569 int ret;
570
571 if (!test_bit(IWM_STATUS_READY, &iwm->status))
572 return -EIO;
573
574 if (!sme->ssid)
575 return -EINVAL;
576
577 if (iwm->umac_profile_active) {
578 ret = iwm_invalidate_mlme_profile(iwm);
579 if (ret) {
580 IWM_ERR(iwm, "Couldn't invalidate profile\n");
581 return ret;
582 }
583 }
584
585 if (chan)
586 iwm->channel =
587 ieee80211_frequency_to_channel(chan->center_freq);
588
589 iwm->umac_profile->ssid.ssid_len = sme->ssid_len;
590 memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len);
591
592 if (sme->bssid) {
593 IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid);
594 memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN);
595 iwm->umac_profile->bss_num = 1;
596 } else {
597 memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
598 iwm->umac_profile->bss_num = 0;
599 }
600
601 ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
602 if (ret < 0)
603 return ret;
604
605 ret = iwm_set_auth_type(iwm, sme->auth_type);
606 if (ret < 0)
607 return ret;
608
609 if (sme->crypto.n_ciphers_pairwise) {
610 ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0],
611 true);
612 if (ret < 0)
613 return ret;
614 }
615
616 ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false);
617 if (ret < 0)
618 return ret;
619
620 if (sme->crypto.n_akm_suites) {
621 ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]);
622 if (ret < 0)
623 return ret;
624 }
625
626 /*
627 * We save the WEP key in case we want to do shared authentication.
628 * We have to do it so because UMAC will assert whenever it gets a
629 * key before a profile.
630 */
631 if (sme->key) {
632 key_param.key = kmemdup(sme->key, sme->key_len, GFP_KERNEL);
633 if (key_param.key == NULL)
634 return -ENOMEM;
635 key_param.key_len = sme->key_len;
636 key_param.seq_len = 0;
637 key_param.cipher = sme->crypto.ciphers_pairwise[0];
638
639 ret = iwm_key_init(&iwm->keys[sme->key_idx], sme->key_idx,
640 NULL, &key_param);
641 kfree(key_param.key);
642 if (ret < 0) {
643 IWM_ERR(iwm, "Invalid key_params\n");
644 return ret;
645 }
646
647 iwm->default_key = sme->key_idx;
648 }
649
650 /* WPA and open AUTH type from wpa_s means WPS (a.k.a. WSC) */
651 if ((iwm->umac_profile->sec.flags &
652 (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) &&
653 iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN) {
654 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WSC_ON_MSK;
655 }
656
657 ret = iwm_send_mlme_profile(iwm);
658
659 if (iwm->umac_profile->sec.auth_type != UMAC_AUTH_TYPE_LEGACY_PSK ||
660 sme->key == NULL)
661 return ret;
662
663 /*
664 * We want to do shared auth.
665 * We need to actually set the key we previously cached,
666 * and then tell the UMAC it's the default one.
667 * That will trigger the auth+assoc UMAC machinery, and again,
668 * this must be done after setting the profile.
669 */
670 ret = iwm_set_key(iwm, 0, &iwm->keys[sme->key_idx]);
671 if (ret < 0)
672 return ret;
673
674 return iwm_set_tx_key(iwm, iwm->default_key);
675}
676
677static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
678 u16 reason_code)
679{
680 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
681
682 IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
683
684 if (iwm->umac_profile_active)
685 iwm_invalidate_mlme_profile(iwm);
686
687 return 0;
688}
689
690static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
691 enum nl80211_tx_power_setting type, int mbm)
692{
693 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
694 int ret;
695
696 switch (type) {
697 case NL80211_TX_POWER_AUTOMATIC:
698 return 0;
699 case NL80211_TX_POWER_FIXED:
700 if (mbm < 0 || (mbm % 100))
701 return -EOPNOTSUPP;
702
703 if (!test_bit(IWM_STATUS_READY, &iwm->status))
704 return 0;
705
706 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
707 CFG_TX_PWR_LIMIT_USR,
708 MBM_TO_DBM(mbm) * 2);
709 if (ret < 0)
710 return ret;
711
712 return iwm_tx_power_trigger(iwm);
713 default:
714 IWM_ERR(iwm, "Unsupported power type: %d\n", type);
715 return -EOPNOTSUPP;
716 }
717
718 return 0;
719}
720
721static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
722{
723 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
724
725 *dbm = iwm->txpower >> 1;
726
727 return 0;
728}
729
730static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
731 struct net_device *dev,
732 bool enabled, int timeout)
733{
734 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
735 u32 power_index;
736
737 if (enabled)
738 power_index = IWM_POWER_INDEX_DEFAULT;
739 else
740 power_index = IWM_POWER_INDEX_MIN;
741
742 if (power_index == iwm->conf.power_index)
743 return 0;
744
745 iwm->conf.power_index = power_index;
746
747 return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
748 CFG_POWER_INDEX, iwm->conf.power_index);
749}
750
751static int iwm_cfg80211_set_pmksa(struct wiphy *wiphy,
752 struct net_device *netdev,
753 struct cfg80211_pmksa *pmksa)
754{
755 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
756
757 return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_ADD);
758}
759
760static int iwm_cfg80211_del_pmksa(struct wiphy *wiphy,
761 struct net_device *netdev,
762 struct cfg80211_pmksa *pmksa)
763{
764 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
765
766 return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_DEL);
767}
768
769static int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy,
770 struct net_device *netdev)
771{
772 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
773 struct cfg80211_pmksa pmksa;
774
775 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
776
777 return iwm_send_pmkid_update(iwm, &pmksa, IWM_CMD_PMKID_FLUSH);
778}
779
780
781static struct cfg80211_ops iwm_cfg80211_ops = {
782 .change_virtual_intf = iwm_cfg80211_change_iface,
783 .add_key = iwm_cfg80211_add_key,
784 .get_key = iwm_cfg80211_get_key,
785 .del_key = iwm_cfg80211_del_key,
786 .set_default_key = iwm_cfg80211_set_default_key,
787 .get_station = iwm_cfg80211_get_station,
788 .scan = iwm_cfg80211_scan,
789 .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
790 .connect = iwm_cfg80211_connect,
791 .disconnect = iwm_cfg80211_disconnect,
792 .join_ibss = iwm_cfg80211_join_ibss,
793 .leave_ibss = iwm_cfg80211_leave_ibss,
794 .set_tx_power = iwm_cfg80211_set_txpower,
795 .get_tx_power = iwm_cfg80211_get_txpower,
796 .set_power_mgmt = iwm_cfg80211_set_power_mgmt,
797 .set_pmksa = iwm_cfg80211_set_pmksa,
798 .del_pmksa = iwm_cfg80211_del_pmksa,
799 .flush_pmksa = iwm_cfg80211_flush_pmksa,
800};
801
802static const u32 cipher_suites[] = {
803 WLAN_CIPHER_SUITE_WEP40,
804 WLAN_CIPHER_SUITE_WEP104,
805 WLAN_CIPHER_SUITE_TKIP,
806 WLAN_CIPHER_SUITE_CCMP,
807};
808
809struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
810{
811 int ret = 0;
812 struct wireless_dev *wdev;
813
814 /*
815 * We're trying to have the following memory
816 * layout:
817 *
818 * +-------------------------+
819 * | struct wiphy |
820 * +-------------------------+
821 * | struct iwm_priv |
822 * +-------------------------+
823 * | bus private data |
824 * | (e.g. iwm_priv_sdio) |
825 * +-------------------------+
826 *
827 */
828
829 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
830 if (!wdev) {
831 dev_err(dev, "Couldn't allocate wireless device\n");
832 return ERR_PTR(-ENOMEM);
833 }
834
835 wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
836 sizeof(struct iwm_priv) + sizeof_bus);
837 if (!wdev->wiphy) {
838 dev_err(dev, "Couldn't allocate wiphy device\n");
839 ret = -ENOMEM;
840 goto out_err_new;
841 }
842
843 set_wiphy_dev(wdev->wiphy, dev);
844 wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
845 wdev->wiphy->max_num_pmkids = UMAC_MAX_NUM_PMKIDS;
846 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
847 BIT(NL80211_IFTYPE_ADHOC);
848 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
849 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
850 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
851
852 wdev->wiphy->cipher_suites = cipher_suites;
853 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
854
855 ret = wiphy_register(wdev->wiphy);
856 if (ret < 0) {
857 dev_err(dev, "Couldn't register wiphy device\n");
858 goto out_err_register;
859 }
860
861 return wdev;
862
863 out_err_register:
864 wiphy_free(wdev->wiphy);
865
866 out_err_new:
867 kfree(wdev);
868
869 return ERR_PTR(ret);
870}
871
872void iwm_wdev_free(struct iwm_priv *iwm)
873{
874 struct wireless_dev *wdev = iwm_to_wdev(iwm);
875
876 if (!wdev)
877 return;
878
879 wiphy_unregister(wdev->wiphy);
880 wiphy_free(wdev->wiphy);
881 kfree(wdev);
882}
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.h b/drivers/net/wireless/iwmc3200wifi/cfg80211.h
deleted file mode 100644
index 56a34145acbf..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/cfg80211.h
+++ /dev/null
@@ -1,31 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 */
23
24#ifndef __IWM_CFG80211_H__
25#define __IWM_CFG80211_H__
26
27int iwm_cfg80211_inform_bss(struct iwm_priv *iwm);
28struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev);
29void iwm_wdev_free(struct iwm_priv *iwm);
30
31#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c
deleted file mode 100644
index bd75078c454b..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/commands.c
+++ /dev/null
@@ -1,1002 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#include <linux/kernel.h>
40#include <linux/wireless.h>
41#include <linux/etherdevice.h>
42#include <linux/ieee80211.h>
43#include <linux/sched.h>
44#include <linux/slab.h>
45#include <linux/moduleparam.h>
46
47#include "iwm.h"
48#include "bus.h"
49#include "hal.h"
50#include "umac.h"
51#include "commands.h"
52#include "debug.h"
53
54static int iwm_send_lmac_ptrough_cmd(struct iwm_priv *iwm,
55 u8 lmac_cmd_id,
56 const void *lmac_payload,
57 u16 lmac_payload_size,
58 u8 resp)
59{
60 struct iwm_udma_wifi_cmd udma_cmd = UDMA_LMAC_INIT;
61 struct iwm_umac_cmd umac_cmd;
62 struct iwm_lmac_cmd lmac_cmd;
63
64 lmac_cmd.id = lmac_cmd_id;
65
66 umac_cmd.id = UMAC_CMD_OPCODE_WIFI_PASS_THROUGH;
67 umac_cmd.resp = resp;
68
69 return iwm_hal_send_host_cmd(iwm, &udma_cmd, &umac_cmd, &lmac_cmd,
70 lmac_payload, lmac_payload_size);
71}
72
73int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size,
74 bool resp)
75{
76 struct iwm_umac_wifi_if *hdr = (struct iwm_umac_wifi_if *)payload;
77 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
78 struct iwm_umac_cmd umac_cmd;
79 int ret;
80 u8 oid = hdr->oid;
81
82 if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
83 IWM_ERR(iwm, "Interface is not ready yet");
84 return -EAGAIN;
85 }
86
87 umac_cmd.id = UMAC_CMD_OPCODE_WIFI_IF_WRAPPER;
88 umac_cmd.resp = resp;
89
90 ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd,
91 payload, payload_size);
92
93 if (resp) {
94 ret = wait_event_interruptible_timeout(iwm->wifi_ntfy_queue,
95 test_and_clear_bit(oid, &iwm->wifi_ntfy[0]),
96 3 * HZ);
97
98 return ret ? 0 : -EBUSY;
99 }
100
101 return ret;
102}
103
104static int modparam_wiwi = COEX_MODE_CM;
105module_param_named(wiwi, modparam_wiwi, int, 0644);
106MODULE_PARM_DESC(wiwi, "Wifi-WiMAX coexistence: 1=SA, 2=XOR, 3=CM (default)");
107
108static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] =
109{
110 {4, 3, 0, COEX_UNASSOC_IDLE_FLAGS},
111 {4, 3, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
112 {4, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
113 {4, 3, 0, COEX_CALIBRATION_FLAGS},
114 {4, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS},
115 {4, 3, 0, COEX_CONNECTION_ESTAB_FLAGS},
116 {4, 3, 0, COEX_ASSOCIATED_IDLE_FLAGS},
117 {4, 3, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
118 {4, 3, 0, COEX_ASSOC_AUTO_SCAN_FLAGS},
119 {4, 3, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS},
120 {6, 3, 0, COEX_XOR_RF_ON_FLAGS},
121 {4, 3, 0, COEX_RF_OFF_FLAGS},
122 {6, 6, 0, COEX_STAND_ALONE_DEBUG_FLAGS},
123 {4, 3, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS},
124 {4, 3, 0, COEX_RSRVD1_FLAGS},
125 {4, 3, 0, COEX_RSRVD2_FLAGS}
126};
127
128static struct coex_event iwm_sta_cm_prio_tbl[COEX_EVENTS_NUM] =
129{
130 {1, 1, 0, COEX_UNASSOC_IDLE_FLAGS},
131 {4, 4, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
132 {3, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
133 {6, 6, 0, COEX_CALIBRATION_FLAGS},
134 {3, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS},
135 {6, 5, 0, COEX_CONNECTION_ESTAB_FLAGS},
136 {4, 4, 0, COEX_ASSOCIATED_IDLE_FLAGS},
137 {4, 4, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
138 {4, 4, 0, COEX_ASSOC_AUTO_SCAN_FLAGS},
139 {4, 4, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS},
140 {1, 1, 0, COEX_RF_ON_FLAGS},
141 {1, 1, 0, COEX_RF_OFF_FLAGS},
142 {7, 7, 0, COEX_STAND_ALONE_DEBUG_FLAGS},
143 {5, 4, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS},
144 {1, 1, 0, COEX_RSRVD1_FLAGS},
145 {1, 1, 0, COEX_RSRVD2_FLAGS}
146};
147
148int iwm_send_prio_table(struct iwm_priv *iwm)
149{
150 struct iwm_coex_prio_table_cmd coex_table_cmd;
151 u32 coex_enabled, mode_enabled;
152
153 memset(&coex_table_cmd, 0, sizeof(struct iwm_coex_prio_table_cmd));
154
155 coex_table_cmd.flags = COEX_FLAGS_STA_TABLE_VALID_MSK;
156
157 switch (modparam_wiwi) {
158 case COEX_MODE_XOR:
159 case COEX_MODE_CM:
160 coex_enabled = 1;
161 break;
162 default:
163 coex_enabled = 0;
164 break;
165 }
166
167 switch (iwm->conf.mode) {
168 case UMAC_MODE_BSS:
169 case UMAC_MODE_IBSS:
170 mode_enabled = 1;
171 break;
172 default:
173 mode_enabled = 0;
174 break;
175 }
176
177 if (coex_enabled && mode_enabled) {
178 coex_table_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK |
179 COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK |
180 COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK;
181
182 switch (modparam_wiwi) {
183 case COEX_MODE_XOR:
184 memcpy(coex_table_cmd.sta_prio, iwm_sta_xor_prio_tbl,
185 sizeof(iwm_sta_xor_prio_tbl));
186 break;
187 case COEX_MODE_CM:
188 memcpy(coex_table_cmd.sta_prio, iwm_sta_cm_prio_tbl,
189 sizeof(iwm_sta_cm_prio_tbl));
190 break;
191 default:
192 IWM_ERR(iwm, "Invalid coex_mode 0x%x\n",
193 modparam_wiwi);
194 break;
195 }
196 } else
197 IWM_WARN(iwm, "coexistense disabled\n");
198
199 return iwm_send_lmac_ptrough_cmd(iwm, COEX_PRIORITY_TABLE_CMD,
200 &coex_table_cmd,
201 sizeof(struct iwm_coex_prio_table_cmd), 0);
202}
203
204int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested)
205{
206 struct iwm_lmac_cal_cfg_cmd cal_cfg_cmd;
207
208 memset(&cal_cfg_cmd, 0, sizeof(struct iwm_lmac_cal_cfg_cmd));
209
210 cal_cfg_cmd.ucode_cfg.init.enable = cpu_to_le32(calib_requested);
211 cal_cfg_cmd.ucode_cfg.init.start = cpu_to_le32(calib_requested);
212 cal_cfg_cmd.ucode_cfg.init.send_res = cpu_to_le32(calib_requested);
213 cal_cfg_cmd.ucode_cfg.flags =
214 cpu_to_le32(CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK);
215
216 return iwm_send_lmac_ptrough_cmd(iwm, CALIBRATION_CFG_CMD, &cal_cfg_cmd,
217 sizeof(struct iwm_lmac_cal_cfg_cmd), 1);
218}
219
220int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested)
221{
222 struct iwm_lmac_cal_cfg_cmd cal_cfg_cmd;
223
224 memset(&cal_cfg_cmd, 0, sizeof(struct iwm_lmac_cal_cfg_cmd));
225
226 cal_cfg_cmd.ucode_cfg.periodic.enable = cpu_to_le32(calib_requested);
227 cal_cfg_cmd.ucode_cfg.periodic.start = cpu_to_le32(calib_requested);
228
229 return iwm_send_lmac_ptrough_cmd(iwm, CALIBRATION_CFG_CMD, &cal_cfg_cmd,
230 sizeof(struct iwm_lmac_cal_cfg_cmd), 0);
231}
232
233int iwm_store_rxiq_calib_result(struct iwm_priv *iwm)
234{
235 struct iwm_calib_rxiq *rxiq;
236 u8 *eeprom_rxiq = iwm_eeprom_access(iwm, IWM_EEPROM_CALIB_RXIQ);
237 int grplen = sizeof(struct iwm_calib_rxiq_group);
238
239 rxiq = kzalloc(sizeof(struct iwm_calib_rxiq), GFP_KERNEL);
240 if (!rxiq) {
241 IWM_ERR(iwm, "Couldn't alloc memory for RX IQ\n");
242 return -ENOMEM;
243 }
244
245 eeprom_rxiq = iwm_eeprom_access(iwm, IWM_EEPROM_CALIB_RXIQ);
246 if (IS_ERR(eeprom_rxiq)) {
247 IWM_ERR(iwm, "Couldn't access EEPROM RX IQ entry\n");
248 kfree(rxiq);
249 return PTR_ERR(eeprom_rxiq);
250 }
251
252 iwm->calib_res[SHILOH_PHY_CALIBRATE_RX_IQ_CMD].buf = (u8 *)rxiq;
253 iwm->calib_res[SHILOH_PHY_CALIBRATE_RX_IQ_CMD].size = sizeof(*rxiq);
254
255 rxiq->hdr.opcode = SHILOH_PHY_CALIBRATE_RX_IQ_CMD;
256 rxiq->hdr.first_grp = 0;
257 rxiq->hdr.grp_num = 1;
258 rxiq->hdr.all_data_valid = 1;
259
260 memcpy(&rxiq->group[0], eeprom_rxiq, 4 * grplen);
261 memcpy(&rxiq->group[4], eeprom_rxiq + 6 * grplen, grplen);
262
263 return 0;
264}
265
266int iwm_send_calib_results(struct iwm_priv *iwm)
267{
268 int i, ret = 0;
269
270 for (i = PHY_CALIBRATE_OPCODES_NUM; i < CALIBRATION_CMD_NUM; i++) {
271 if (test_bit(i - PHY_CALIBRATE_OPCODES_NUM,
272 &iwm->calib_done_map)) {
273 IWM_DBG_CMD(iwm, DBG,
274 "Send calibration %d result\n", i);
275 ret |= iwm_send_lmac_ptrough_cmd(iwm,
276 REPLY_PHY_CALIBRATION_CMD,
277 iwm->calib_res[i].buf,
278 iwm->calib_res[i].size, 0);
279
280 kfree(iwm->calib_res[i].buf);
281 iwm->calib_res[i].buf = NULL;
282 iwm->calib_res[i].size = 0;
283 }
284 }
285
286 return ret;
287}
288
289int iwm_send_ct_kill_cfg(struct iwm_priv *iwm, u8 entry, u8 exit)
290{
291 struct iwm_ct_kill_cfg_cmd cmd;
292
293 cmd.entry_threshold = entry;
294 cmd.exit_threshold = exit;
295
296 return iwm_send_lmac_ptrough_cmd(iwm, REPLY_CT_KILL_CONFIG_CMD, &cmd,
297 sizeof(struct iwm_ct_kill_cfg_cmd), 0);
298}
299
300int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp)
301{
302 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
303 struct iwm_umac_cmd umac_cmd;
304 struct iwm_umac_cmd_reset reset;
305
306 reset.flags = reset_flags;
307
308 umac_cmd.id = UMAC_CMD_OPCODE_RESET;
309 umac_cmd.resp = resp;
310
311 return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &reset,
312 sizeof(struct iwm_umac_cmd_reset));
313}
314
315int iwm_umac_set_config_fix(struct iwm_priv *iwm, u16 tbl, u16 key, u32 value)
316{
317 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
318 struct iwm_umac_cmd umac_cmd;
319 struct iwm_umac_cmd_set_param_fix param;
320
321 if ((tbl != UMAC_PARAM_TBL_CFG_FIX) &&
322 (tbl != UMAC_PARAM_TBL_FA_CFG_FIX))
323 return -EINVAL;
324
325 umac_cmd.id = UMAC_CMD_OPCODE_SET_PARAM_FIX;
326 umac_cmd.resp = 0;
327
328 param.tbl = cpu_to_le16(tbl);
329 param.key = cpu_to_le16(key);
330 param.value = cpu_to_le32(value);
331
332 return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &param,
333 sizeof(struct iwm_umac_cmd_set_param_fix));
334}
335
336int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key,
337 void *payload, u16 payload_size)
338{
339 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
340 struct iwm_umac_cmd umac_cmd;
341 struct iwm_umac_cmd_set_param_var *param_hdr;
342 u8 *param;
343 int ret;
344
345 param = kzalloc(payload_size +
346 sizeof(struct iwm_umac_cmd_set_param_var), GFP_KERNEL);
347 if (!param) {
348 IWM_ERR(iwm, "Couldn't allocate param\n");
349 return -ENOMEM;
350 }
351
352 param_hdr = (struct iwm_umac_cmd_set_param_var *)param;
353
354 umac_cmd.id = UMAC_CMD_OPCODE_SET_PARAM_VAR;
355 umac_cmd.resp = 0;
356
357 param_hdr->tbl = cpu_to_le16(UMAC_PARAM_TBL_CFG_VAR);
358 param_hdr->key = cpu_to_le16(key);
359 param_hdr->len = cpu_to_le16(payload_size);
360 memcpy(param + sizeof(struct iwm_umac_cmd_set_param_var),
361 payload, payload_size);
362
363 ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, param,
364 sizeof(struct iwm_umac_cmd_set_param_var) +
365 payload_size);
366 kfree(param);
367
368 return ret;
369}
370
371int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags)
372{
373 int ret;
374
375 /* Use UMAC default values */
376 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
377 CFG_POWER_INDEX, iwm->conf.power_index);
378 if (ret < 0)
379 return ret;
380
381 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
382 CFG_FRAG_THRESHOLD,
383 iwm->conf.frag_threshold);
384 if (ret < 0)
385 return ret;
386
387 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
388 CFG_RTS_THRESHOLD,
389 iwm->conf.rts_threshold);
390 if (ret < 0)
391 return ret;
392
393 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
394 CFG_CTS_TO_SELF, iwm->conf.cts_to_self);
395 if (ret < 0)
396 return ret;
397
398 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
399 CFG_WIRELESS_MODE,
400 iwm->conf.wireless_mode);
401 if (ret < 0)
402 return ret;
403
404 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
405 CFG_COEX_MODE, modparam_wiwi);
406 if (ret < 0)
407 return ret;
408
409 /*
410 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
411 CFG_ASSOCIATION_TIMEOUT,
412 iwm->conf.assoc_timeout);
413 if (ret < 0)
414 return ret;
415
416 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
417 CFG_ROAM_TIMEOUT,
418 iwm->conf.roam_timeout);
419 if (ret < 0)
420 return ret;
421
422 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
423 CFG_WIRELESS_MODE,
424 WIRELESS_MODE_11A | WIRELESS_MODE_11G);
425 if (ret < 0)
426 return ret;
427 */
428
429 ret = iwm_umac_set_config_var(iwm, CFG_NET_ADDR,
430 iwm_to_ndev(iwm)->dev_addr, ETH_ALEN);
431 if (ret < 0)
432 return ret;
433
434 /* UMAC PM static configurations */
435 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
436 CFG_PM_LEGACY_RX_TIMEOUT, 0x12C);
437 if (ret < 0)
438 return ret;
439
440 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
441 CFG_PM_LEGACY_TX_TIMEOUT, 0x15E);
442 if (ret < 0)
443 return ret;
444
445 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
446 CFG_PM_CTRL_FLAGS, 0x1);
447 if (ret < 0)
448 return ret;
449
450 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
451 CFG_PM_KEEP_ALIVE_IN_BEACONS, 0x80);
452 if (ret < 0)
453 return ret;
454
455 /* reset UMAC */
456 ret = iwm_send_umac_reset(iwm, reset_flags, 1);
457 if (ret < 0)
458 return ret;
459
460 ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_RESET, IWM_SRC_UMAC,
461 WAIT_NOTIF_TIMEOUT);
462 if (ret) {
463 IWM_ERR(iwm, "Wait for UMAC RESET timeout\n");
464 return ret;
465 }
466
467 return ret;
468}
469
470int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id)
471{
472 struct iwm_udma_wifi_cmd udma_cmd;
473 struct iwm_umac_cmd umac_cmd;
474 struct iwm_tx_info *tx_info = skb_to_tx_info(skb);
475
476 udma_cmd.eop = 1; /* always set eop for non-concatenated Tx */
477 udma_cmd.credit_group = pool_id;
478 udma_cmd.ra_tid = tx_info->sta << 4 | tx_info->tid;
479 udma_cmd.lmac_offset = 0;
480
481 umac_cmd.id = REPLY_TX;
482 umac_cmd.color = tx_info->color;
483 umac_cmd.resp = 0;
484
485 return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd,
486 skb->data, skb->len);
487}
488
489static int iwm_target_read(struct iwm_priv *iwm, __le32 address,
490 u8 *response, u32 resp_size)
491{
492 struct iwm_udma_nonwifi_cmd target_cmd;
493 struct iwm_nonwifi_cmd *cmd;
494 u16 seq_num;
495 int ret = 0;
496
497 target_cmd.opcode = UMAC_HDI_OUT_OPCODE_READ;
498 target_cmd.addr = address;
499 target_cmd.op1_sz = cpu_to_le32(resp_size);
500 target_cmd.op2 = 0;
501 target_cmd.handle_by_hw = 0;
502 target_cmd.resp = 1;
503 target_cmd.eop = 1;
504
505 ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL);
506 if (ret < 0) {
507 IWM_ERR(iwm, "Couldn't send READ command\n");
508 return ret;
509 }
510
511 /* When succeeding, the send_target routine returns the seq number */
512 seq_num = ret;
513
514 ret = wait_event_interruptible_timeout(iwm->nonwifi_queue,
515 (cmd = iwm_get_pending_nonwifi_cmd(iwm, seq_num,
516 UMAC_HDI_OUT_OPCODE_READ)) != NULL,
517 2 * HZ);
518
519 if (!ret) {
520 IWM_ERR(iwm, "Didn't receive a target READ answer\n");
521 return ret;
522 }
523
524 memcpy(response, cmd->buf.hdr + sizeof(struct iwm_udma_in_hdr),
525 resp_size);
526
527 kfree(cmd);
528
529 return 0;
530}
531
532int iwm_read_mac(struct iwm_priv *iwm, u8 *mac)
533{
534 int ret;
535 u8 mac_align[ALIGN(ETH_ALEN, 8)];
536
537 ret = iwm_target_read(iwm, cpu_to_le32(WICO_MAC_ADDRESS_ADDR),
538 mac_align, sizeof(mac_align));
539 if (ret)
540 return ret;
541
542 if (is_valid_ether_addr(mac_align))
543 memcpy(mac, mac_align, ETH_ALEN);
544 else {
545 IWM_ERR(iwm, "Invalid EEPROM MAC\n");
546 memcpy(mac, iwm->conf.mac_addr, ETH_ALEN);
547 get_random_bytes(&mac[3], 3);
548 }
549
550 return 0;
551}
552
553static int iwm_check_profile(struct iwm_priv *iwm)
554{
555 if (!iwm->umac_profile_active)
556 return -EAGAIN;
557
558 if (iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_40 &&
559 iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_104 &&
560 iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_TKIP &&
561 iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_CCMP) {
562 IWM_ERR(iwm, "Wrong unicast cipher: 0x%x\n",
563 iwm->umac_profile->sec.ucast_cipher);
564 return -EAGAIN;
565 }
566
567 if (iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_WEP_40 &&
568 iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_WEP_104 &&
569 iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_TKIP &&
570 iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_CCMP) {
571 IWM_ERR(iwm, "Wrong multicast cipher: 0x%x\n",
572 iwm->umac_profile->sec.mcast_cipher);
573 return -EAGAIN;
574 }
575
576 if ((iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_40 ||
577 iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_104) &&
578 (iwm->umac_profile->sec.ucast_cipher !=
579 iwm->umac_profile->sec.mcast_cipher)) {
580 IWM_ERR(iwm, "Unicast and multicast ciphers differ for WEP\n");
581 }
582
583 return 0;
584}
585
586int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx)
587{
588 struct iwm_umac_tx_key_id tx_key_id;
589 int ret;
590
591 ret = iwm_check_profile(iwm);
592 if (ret < 0)
593 return ret;
594
595 /* UMAC only allows to set default key for WEP and auth type is
596 * NOT 802.1X or RSNA. */
597 if ((iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_40 &&
598 iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_104) ||
599 iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_8021X ||
600 iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_RSNA_PSK)
601 return 0;
602
603 tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID;
604 tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) -
605 sizeof(struct iwm_umac_wifi_if));
606
607 tx_key_id.key_idx = key_idx;
608
609 return iwm_send_wifi_if_cmd(iwm, &tx_key_id, sizeof(tx_key_id), 1);
610}
611
612int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key)
613{
614 int ret = 0;
615 u8 cmd[64], *sta_addr, *key_data, key_len;
616 s8 key_idx;
617 u16 cmd_size = 0;
618 struct iwm_umac_key_hdr *key_hdr = &key->hdr;
619 struct iwm_umac_key_wep40 *wep40 = (struct iwm_umac_key_wep40 *)cmd;
620 struct iwm_umac_key_wep104 *wep104 = (struct iwm_umac_key_wep104 *)cmd;
621 struct iwm_umac_key_tkip *tkip = (struct iwm_umac_key_tkip *)cmd;
622 struct iwm_umac_key_ccmp *ccmp = (struct iwm_umac_key_ccmp *)cmd;
623
624 if (!remove) {
625 ret = iwm_check_profile(iwm);
626 if (ret < 0)
627 return ret;
628 }
629
630 sta_addr = key->hdr.mac;
631 key_data = key->key;
632 key_len = key->key_len;
633 key_idx = key->hdr.key_idx;
634
635 if (!remove) {
636 u8 auth_type = iwm->umac_profile->sec.auth_type;
637
638 IWM_DBG_WEXT(iwm, DBG, "key_idx:%d\n", key_idx);
639 IWM_DBG_WEXT(iwm, DBG, "key_len:%d\n", key_len);
640 IWM_DBG_WEXT(iwm, DBG, "MAC:%pM, idx:%d, multicast:%d\n",
641 key_hdr->mac, key_hdr->key_idx, key_hdr->multicast);
642
643 IWM_DBG_WEXT(iwm, DBG, "profile: mcast:0x%x, ucast:0x%x\n",
644 iwm->umac_profile->sec.mcast_cipher,
645 iwm->umac_profile->sec.ucast_cipher);
646 IWM_DBG_WEXT(iwm, DBG, "profile: auth_type:0x%x, flags:0x%x\n",
647 iwm->umac_profile->sec.auth_type,
648 iwm->umac_profile->sec.flags);
649
650 switch (key->cipher) {
651 case WLAN_CIPHER_SUITE_WEP40:
652 wep40->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP40_KEY;
653 wep40->hdr.buf_size =
654 cpu_to_le16(sizeof(struct iwm_umac_key_wep40) -
655 sizeof(struct iwm_umac_wifi_if));
656
657 memcpy(&wep40->key_hdr, key_hdr,
658 sizeof(struct iwm_umac_key_hdr));
659 memcpy(wep40->key, key_data, key_len);
660 wep40->static_key =
661 !!((auth_type != UMAC_AUTH_TYPE_8021X) &&
662 (auth_type != UMAC_AUTH_TYPE_RSNA_PSK));
663
664 cmd_size = sizeof(struct iwm_umac_key_wep40);
665 break;
666
667 case WLAN_CIPHER_SUITE_WEP104:
668 wep104->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP104_KEY;
669 wep104->hdr.buf_size =
670 cpu_to_le16(sizeof(struct iwm_umac_key_wep104) -
671 sizeof(struct iwm_umac_wifi_if));
672
673 memcpy(&wep104->key_hdr, key_hdr,
674 sizeof(struct iwm_umac_key_hdr));
675 memcpy(wep104->key, key_data, key_len);
676 wep104->static_key =
677 !!((auth_type != UMAC_AUTH_TYPE_8021X) &&
678 (auth_type != UMAC_AUTH_TYPE_RSNA_PSK));
679
680 cmd_size = sizeof(struct iwm_umac_key_wep104);
681 break;
682
683 case WLAN_CIPHER_SUITE_CCMP:
684 key_hdr->key_idx++;
685 ccmp->hdr.oid = UMAC_WIFI_IF_CMD_ADD_CCMP_KEY;
686 ccmp->hdr.buf_size =
687 cpu_to_le16(sizeof(struct iwm_umac_key_ccmp) -
688 sizeof(struct iwm_umac_wifi_if));
689
690 memcpy(&ccmp->key_hdr, key_hdr,
691 sizeof(struct iwm_umac_key_hdr));
692
693 memcpy(ccmp->key, key_data, key_len);
694
695 if (key->seq_len)
696 memcpy(ccmp->iv_count, key->seq, key->seq_len);
697
698 cmd_size = sizeof(struct iwm_umac_key_ccmp);
699 break;
700
701 case WLAN_CIPHER_SUITE_TKIP:
702 key_hdr->key_idx++;
703 tkip->hdr.oid = UMAC_WIFI_IF_CMD_ADD_TKIP_KEY;
704 tkip->hdr.buf_size =
705 cpu_to_le16(sizeof(struct iwm_umac_key_tkip) -
706 sizeof(struct iwm_umac_wifi_if));
707
708 memcpy(&tkip->key_hdr, key_hdr,
709 sizeof(struct iwm_umac_key_hdr));
710
711 memcpy(tkip->tkip_key, key_data, IWM_TKIP_KEY_SIZE);
712 memcpy(tkip->mic_tx_key, key_data + IWM_TKIP_KEY_SIZE,
713 IWM_TKIP_MIC_SIZE);
714 memcpy(tkip->mic_rx_key,
715 key_data + IWM_TKIP_KEY_SIZE + IWM_TKIP_MIC_SIZE,
716 IWM_TKIP_MIC_SIZE);
717
718 if (key->seq_len)
719 memcpy(ccmp->iv_count, key->seq, key->seq_len);
720
721 cmd_size = sizeof(struct iwm_umac_key_tkip);
722 break;
723
724 default:
725 return -ENOTSUPP;
726 }
727
728 if ((key->cipher == WLAN_CIPHER_SUITE_TKIP) ||
729 (key->cipher == WLAN_CIPHER_SUITE_CCMP))
730 /*
731 * UGLY_UGLY_UGLY
732 * Copied HACK from the MWG driver.
733 * Without it, the key is set before the second
734 * EAPOL frame is sent, and the latter is thus
735 * encrypted.
736 */
737 schedule_timeout_interruptible(usecs_to_jiffies(300));
738
739 ret = iwm_send_wifi_if_cmd(iwm, cmd, cmd_size, 1);
740 } else {
741 struct iwm_umac_key_remove key_remove;
742
743 IWM_DBG_WEXT(iwm, ERR, "Removing key_idx:%d\n", key_idx);
744
745 key_remove.hdr.oid = UMAC_WIFI_IF_CMD_REMOVE_KEY;
746 key_remove.hdr.buf_size =
747 cpu_to_le16(sizeof(struct iwm_umac_key_remove) -
748 sizeof(struct iwm_umac_wifi_if));
749 memcpy(&key_remove.key_hdr, key_hdr,
750 sizeof(struct iwm_umac_key_hdr));
751
752 ret = iwm_send_wifi_if_cmd(iwm, &key_remove,
753 sizeof(struct iwm_umac_key_remove),
754 1);
755 if (ret)
756 return ret;
757
758 iwm->keys[key_idx].key_len = 0;
759 }
760
761 return ret;
762}
763
764
765int iwm_send_mlme_profile(struct iwm_priv *iwm)
766{
767 int ret;
768 struct iwm_umac_profile profile;
769
770 memcpy(&profile, iwm->umac_profile, sizeof(profile));
771
772 profile.hdr.oid = UMAC_WIFI_IF_CMD_SET_PROFILE;
773 profile.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_profile) -
774 sizeof(struct iwm_umac_wifi_if));
775
776 ret = iwm_send_wifi_if_cmd(iwm, &profile, sizeof(profile), 1);
777 if (ret) {
778 IWM_ERR(iwm, "Send profile command failed\n");
779 return ret;
780 }
781
782 set_bit(IWM_STATUS_SME_CONNECTING, &iwm->status);
783 return 0;
784}
785
786int __iwm_invalidate_mlme_profile(struct iwm_priv *iwm)
787{
788 struct iwm_umac_invalidate_profile invalid;
789
790 invalid.hdr.oid = UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE;
791 invalid.hdr.buf_size =
792 cpu_to_le16(sizeof(struct iwm_umac_invalidate_profile) -
793 sizeof(struct iwm_umac_wifi_if));
794
795 invalid.reason = WLAN_REASON_UNSPECIFIED;
796
797 return iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1);
798}
799
800int iwm_invalidate_mlme_profile(struct iwm_priv *iwm)
801{
802 int ret;
803
804 ret = __iwm_invalidate_mlme_profile(iwm);
805 if (ret)
806 return ret;
807
808 ret = wait_event_interruptible_timeout(iwm->mlme_queue,
809 (iwm->umac_profile_active == 0), 5 * HZ);
810
811 return ret ? 0 : -EBUSY;
812}
813
814int iwm_tx_power_trigger(struct iwm_priv *iwm)
815{
816 struct iwm_umac_pwr_trigger pwr_trigger;
817
818 pwr_trigger.hdr.oid = UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER;
819 pwr_trigger.hdr.buf_size =
820 cpu_to_le16(sizeof(struct iwm_umac_pwr_trigger) -
821 sizeof(struct iwm_umac_wifi_if));
822
823
824 return iwm_send_wifi_if_cmd(iwm, &pwr_trigger, sizeof(pwr_trigger), 1);
825}
826
827int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags)
828{
829 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
830 struct iwm_umac_cmd umac_cmd;
831 struct iwm_umac_cmd_stats_req stats_req;
832
833 stats_req.flags = cpu_to_le32(flags);
834
835 umac_cmd.id = UMAC_CMD_OPCODE_STATISTIC_REQUEST;
836 umac_cmd.resp = 0;
837
838 return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &stats_req,
839 sizeof(struct iwm_umac_cmd_stats_req));
840}
841
842int iwm_send_umac_channel_list(struct iwm_priv *iwm)
843{
844 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
845 struct iwm_umac_cmd umac_cmd;
846 struct iwm_umac_cmd_get_channel_list *ch_list;
847 int size = sizeof(struct iwm_umac_cmd_get_channel_list) +
848 sizeof(struct iwm_umac_channel_info) * 4;
849 int ret;
850
851 ch_list = kzalloc(size, GFP_KERNEL);
852 if (!ch_list) {
853 IWM_ERR(iwm, "Couldn't allocate channel list cmd\n");
854 return -ENOMEM;
855 }
856
857 ch_list->ch[0].band = UMAC_BAND_2GHZ;
858 ch_list->ch[0].type = UMAC_CHANNEL_WIDTH_20MHZ;
859 ch_list->ch[0].flags = UMAC_CHANNEL_FLAG_VALID;
860
861 ch_list->ch[1].band = UMAC_BAND_5GHZ;
862 ch_list->ch[1].type = UMAC_CHANNEL_WIDTH_20MHZ;
863 ch_list->ch[1].flags = UMAC_CHANNEL_FLAG_VALID;
864
865 ch_list->ch[2].band = UMAC_BAND_2GHZ;
866 ch_list->ch[2].type = UMAC_CHANNEL_WIDTH_20MHZ;
867 ch_list->ch[2].flags = UMAC_CHANNEL_FLAG_VALID | UMAC_CHANNEL_FLAG_IBSS;
868
869 ch_list->ch[3].band = UMAC_BAND_5GHZ;
870 ch_list->ch[3].type = UMAC_CHANNEL_WIDTH_20MHZ;
871 ch_list->ch[3].flags = UMAC_CHANNEL_FLAG_VALID | UMAC_CHANNEL_FLAG_IBSS;
872
873 ch_list->count = cpu_to_le16(4);
874
875 umac_cmd.id = UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST;
876 umac_cmd.resp = 1;
877
878 ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, ch_list, size);
879
880 kfree(ch_list);
881
882 return ret;
883}
884
885int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids,
886 int ssid_num)
887{
888 struct iwm_umac_cmd_scan_request req;
889 int i, ret;
890
891 memset(&req, 0, sizeof(struct iwm_umac_cmd_scan_request));
892
893 req.hdr.oid = UMAC_WIFI_IF_CMD_SCAN_REQUEST;
894 req.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_cmd_scan_request)
895 - sizeof(struct iwm_umac_wifi_if));
896 req.type = UMAC_WIFI_IF_SCAN_TYPE_USER;
897 req.timeout = 2;
898 req.seq_num = iwm->scan_id;
899 req.ssid_num = min(ssid_num, UMAC_WIFI_IF_PROBE_OPTION_MAX);
900
901 for (i = 0; i < req.ssid_num; i++) {
902 memcpy(req.ssids[i].ssid, ssids[i].ssid, ssids[i].ssid_len);
903 req.ssids[i].ssid_len = ssids[i].ssid_len;
904 }
905
906 ret = iwm_send_wifi_if_cmd(iwm, &req, sizeof(req), 0);
907 if (ret) {
908 IWM_ERR(iwm, "Couldn't send scan request\n");
909 return ret;
910 }
911
912 iwm->scan_id = (iwm->scan_id + 1) % IWM_SCAN_ID_MAX;
913
914 return 0;
915}
916
917int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len)
918{
919 struct cfg80211_ssid one_ssid;
920
921 if (test_and_set_bit(IWM_STATUS_SCANNING, &iwm->status))
922 return 0;
923
924 one_ssid.ssid_len = min(ssid_len, IEEE80211_MAX_SSID_LEN);
925 memcpy(&one_ssid.ssid, ssid, one_ssid.ssid_len);
926
927 return iwm_scan_ssids(iwm, &one_ssid, 1);
928}
929
930int iwm_target_reset(struct iwm_priv *iwm)
931{
932 struct iwm_udma_nonwifi_cmd target_cmd;
933
934 target_cmd.opcode = UMAC_HDI_OUT_OPCODE_REBOOT;
935 target_cmd.addr = 0;
936 target_cmd.op1_sz = 0;
937 target_cmd.op2 = 0;
938 target_cmd.handle_by_hw = 0;
939 target_cmd.resp = 0;
940 target_cmd.eop = 1;
941
942 return iwm_hal_send_target_cmd(iwm, &target_cmd, NULL);
943}
944
945int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm,
946 struct iwm_umac_notif_stop_resume_tx *ntf)
947{
948 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
949 struct iwm_umac_cmd umac_cmd;
950 struct iwm_umac_cmd_stop_resume_tx stp_res_cmd;
951 struct iwm_sta_info *sta_info;
952 u8 sta_id = STA_ID_N_COLOR_ID(ntf->sta_id);
953 int i;
954
955 sta_info = &iwm->sta_table[sta_id];
956 if (!sta_info->valid) {
957 IWM_ERR(iwm, "Invalid STA: %d\n", sta_id);
958 return -EINVAL;
959 }
960
961 umac_cmd.id = UMAC_CMD_OPCODE_STOP_RESUME_STA_TX;
962 umac_cmd.resp = 0;
963
964 stp_res_cmd.flags = ntf->flags;
965 stp_res_cmd.sta_id = ntf->sta_id;
966 stp_res_cmd.stop_resume_tid_msk = ntf->stop_resume_tid_msk;
967 for (i = 0; i < IWM_UMAC_TID_NR; i++)
968 stp_res_cmd.last_seq_num[i] =
969 sta_info->tid_info[i].last_seq_num;
970
971 return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &stp_res_cmd,
972 sizeof(struct iwm_umac_cmd_stop_resume_tx));
973
974}
975
976int iwm_send_pmkid_update(struct iwm_priv *iwm,
977 struct cfg80211_pmksa *pmksa, u32 command)
978{
979 struct iwm_umac_pmkid_update update;
980 int ret;
981
982 memset(&update, 0, sizeof(struct iwm_umac_pmkid_update));
983
984 update.hdr.oid = UMAC_WIFI_IF_CMD_PMKID_UPDATE;
985 update.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_pmkid_update) -
986 sizeof(struct iwm_umac_wifi_if));
987
988 update.command = cpu_to_le32(command);
989 if (pmksa->bssid)
990 memcpy(&update.bssid, pmksa->bssid, ETH_ALEN);
991 if (pmksa->pmkid)
992 memcpy(&update.pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
993
994 ret = iwm_send_wifi_if_cmd(iwm, &update,
995 sizeof(struct iwm_umac_pmkid_update), 0);
996 if (ret) {
997 IWM_ERR(iwm, "PMKID update command failed\n");
998 return ret;
999 }
1000
1001 return 0;
1002}
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h
deleted file mode 100644
index 6421689f5e8e..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/commands.h
+++ /dev/null
@@ -1,509 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef __IWM_COMMANDS_H__
40#define __IWM_COMMANDS_H__
41
42#include <linux/ieee80211.h>
43
44#define IWM_BARKER_REBOOT_NOTIFICATION 0xF
45#define IWM_ACK_BARKER_NOTIFICATION 0x10
46
47/* UMAC commands */
48#define UMAC_RST_CTRL_FLG_LARC_CLK_EN 0x0001
49#define UMAC_RST_CTRL_FLG_LARC_RESET 0x0002
50#define UMAC_RST_CTRL_FLG_FUNC_RESET 0x0004
51#define UMAC_RST_CTRL_FLG_DEV_RESET 0x0008
52#define UMAC_RST_CTRL_FLG_WIFI_CORE_EN 0x0010
53#define UMAC_RST_CTRL_FLG_WIFI_LINK_EN 0x0040
54#define UMAC_RST_CTRL_FLG_WIFI_MLME_EN 0x0080
55#define UMAC_RST_CTRL_FLG_NVM_RELOAD 0x0100
56
57struct iwm_umac_cmd_reset {
58 __le32 flags;
59} __packed;
60
61#define UMAC_PARAM_TBL_ORD_FIX 0x0
62#define UMAC_PARAM_TBL_ORD_VAR 0x1
63#define UMAC_PARAM_TBL_CFG_FIX 0x2
64#define UMAC_PARAM_TBL_CFG_VAR 0x3
65#define UMAC_PARAM_TBL_BSS_TRK 0x4
66#define UMAC_PARAM_TBL_FA_CFG_FIX 0x5
67#define UMAC_PARAM_TBL_STA 0x6
68#define UMAC_PARAM_TBL_CHN 0x7
69#define UMAC_PARAM_TBL_STATISTICS 0x8
70
71/* fast access table */
72enum {
73 CFG_FRAG_THRESHOLD = 0,
74 CFG_FRAME_RETRY_LIMIT,
75 CFG_OS_QUEUE_UTIL_TH,
76 CFG_RX_FILTER,
77 /* <-- LAST --> */
78 FAST_ACCESS_CFG_TBL_FIX_LAST
79};
80
81/* fixed size table */
82enum {
83 CFG_POWER_INDEX = 0,
84 CFG_PM_LEGACY_RX_TIMEOUT,
85 CFG_PM_LEGACY_TX_TIMEOUT,
86 CFG_PM_CTRL_FLAGS,
87 CFG_PM_KEEP_ALIVE_IN_BEACONS,
88 CFG_BT_ON_THRESHOLD,
89 CFG_RTS_THRESHOLD,
90 CFG_CTS_TO_SELF,
91 CFG_COEX_MODE,
92 CFG_WIRELESS_MODE,
93 CFG_ASSOCIATION_TIMEOUT,
94 CFG_ROAM_TIMEOUT,
95 CFG_CAPABILITY_SUPPORTED_RATES,
96 CFG_SCAN_ALLOWED_UNASSOC_FLAGS,
97 CFG_SCAN_ALLOWED_MAIN_ASSOC_FLAGS,
98 CFG_SCAN_ALLOWED_PAN_ASSOC_FLAGS,
99 CFG_SCAN_INTERNAL_PERIODIC_ENABLED,
100 CFG_SCAN_IMM_INTERNAL_PERIODIC_SCAN_ON_INIT,
101 CFG_SCAN_DEFAULT_PERIODIC_FREQ_SEC,
102 CFG_SCAN_NUM_PASSIVE_CHAN_PER_PARTIAL_SCAN,
103 CFG_TLC_SUPPORTED_TX_HT_RATES,
104 CFG_TLC_SUPPORTED_TX_RATES,
105 CFG_TLC_SPATIAL_STREAM_SUPPORTED,
106 CFG_TLC_RETRY_PER_RATE,
107 CFG_TLC_RETRY_PER_HT_RATE,
108 CFG_TLC_FIXED_MCS,
109 CFG_TLC_CONTROL_FLAGS,
110 CFG_TLC_SR_MIN_FAIL,
111 CFG_TLC_SR_MIN_PASS,
112 CFG_TLC_HT_STAY_IN_COL_PASS_THRESH,
113 CFG_TLC_HT_STAY_IN_COL_FAIL_THRESH,
114 CFG_TLC_LEGACY_STAY_IN_COL_PASS_THRESH,
115 CFG_TLC_LEGACY_STAY_IN_COL_FAIL_THRESH,
116 CFG_TLC_HT_FLUSH_STATS_PACKETS,
117 CFG_TLC_LEGACY_FLUSH_STATS_PACKETS,
118 CFG_TLC_LEGACY_FLUSH_STATS_MS,
119 CFG_TLC_HT_FLUSH_STATS_MS,
120 CFG_TLC_STAY_IN_COL_TIME_OUT,
121 CFG_TLC_AGG_SHORT_LIM,
122 CFG_TLC_AGG_LONG_LIM,
123 CFG_TLC_HT_SR_NO_DECREASE,
124 CFG_TLC_LEGACY_SR_NO_DECREASE,
125 CFG_TLC_SR_FORCE_DECREASE,
126 CFG_TLC_SR_ALLOW_INCREASE,
127 CFG_TLC_AGG_SET_LONG,
128 CFG_TLC_AUTO_AGGREGATION,
129 CFG_TLC_AGG_THRESHOLD,
130 CFG_TLC_TID_LOAD_THRESHOLD,
131 CFG_TLC_BLOCK_ACK_TIMEOUT,
132 CFG_TLC_NO_BA_COUNTED_AS_ONE,
133 CFG_TLC_NUM_BA_STREAMS_ALLOWED,
134 CFG_TLC_NUM_BA_STREAMS_PRESENT,
135 CFG_TLC_RENEW_ADDBA_DELAY,
136 CFG_TLC_NUM_OF_MULTISEC_TO_COUN_LOAD,
137 CFG_TLC_IS_STABLE_IN_HT,
138 CFG_TLC_SR_SIC_1ST_FAIL,
139 CFG_TLC_SR_SIC_1ST_PASS,
140 CFG_TLC_SR_SIC_TOTAL_FAIL,
141 CFG_TLC_SR_SIC_TOTAL_PASS,
142 CFG_RLC_CHAIN_CTRL,
143 CFG_TRK_TABLE_OP_MODE,
144 CFG_TRK_TABLE_RSSI_THRESHOLD,
145 CFG_TX_PWR_TARGET, /* Used By xVT */
146 CFG_TX_PWR_LIMIT_USR,
147 CFG_TX_PWR_LIMIT_BSS, /* 11d limit */
148 CFG_TX_PWR_LIMIT_BSS_CONSTRAINT, /* 11h constraint */
149 CFG_TX_PWR_MODE,
150 CFG_MLME_DBG_NOTIF_BLOCK,
151 CFG_BT_OFF_BECONS_INTERVALS,
152 CFG_BT_FRAG_DURATION,
153 CFG_ACTIVE_CHAINS,
154 CFG_CALIB_CTRL,
155 CFG_CAPABILITY_SUPPORTED_HT_RATES,
156 CFG_HT_MAC_PARAM_INFO,
157 CFG_MIMO_PS_MODE,
158 CFG_HT_DEFAULT_CAPABILIES_INFO,
159 CFG_LED_SC_RESOLUTION_FACTOR,
160 CFG_PTAM_ENERGY_CCK_DET_DEFAULT,
161 CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_DEFAULT,
162 CFG_PTAM_CORR40_4_TH_ADD_MIN_DEFAULT,
163 CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_DEFAULT,
164 CFG_PTAM_CORR32_4_TH_ADD_MIN_DEFAULT,
165 CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_DEFAULT,
166 CFG_PTAM_CORR32_1_TH_ADD_MIN_DEFAULT,
167 CFG_PTAM_ENERGY_CCK_DET_MIN_VAL,
168 CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_MIN_VAL,
169 CFG_PTAM_CORR40_4_TH_ADD_MIN_MIN_VAL,
170 CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_MIN_VAL,
171 CFG_PTAM_CORR32_4_TH_ADD_MIN_MIN_VAL,
172 CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_MIN_VAL,
173 CFG_PTAM_CORR32_1_TH_ADD_MIN_MIN_VAL,
174 CFG_PTAM_ENERGY_CCK_DET_MAX_VAL,
175 CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_MAX_VAL,
176 CFG_PTAM_CORR40_4_TH_ADD_MIN_MAX_VAL,
177 CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_MAX_VAL,
178 CFG_PTAM_CORR32_4_TH_ADD_MIN_MAX_VAL,
179 CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_MAX_VAL,
180 CFG_PTAM_CORR32_1_TH_ADD_MIN_MAX_VAL,
181 CFG_PTAM_ENERGY_CCK_DET_STEP_VAL,
182 CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_STEP_VAL,
183 CFG_PTAM_CORR40_4_TH_ADD_MIN_STEP_VAL,
184 CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_STEP_VAL,
185 CFG_PTAM_CORR32_4_TH_ADD_MIN_STEP_VAL,
186 CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_STEP_VAL,
187 CFG_PTAM_CORR32_1_TH_ADD_MIN_STEP_VAL,
188 CFG_PTAM_LINK_SENS_FA_OFDM_MAX,
189 CFG_PTAM_LINK_SENS_FA_OFDM_MIN,
190 CFG_PTAM_LINK_SENS_FA_CCK_MAX,
191 CFG_PTAM_LINK_SENS_FA_CCK_MIN,
192 CFG_PTAM_LINK_SENS_NRG_DIFF,
193 CFG_PTAM_LINK_SENS_NRG_MARGIN,
194 CFG_PTAM_LINK_SENS_MAX_NUMBER_OF_TIMES_IN_CCK_NO_FA,
195 CFG_PTAM_LINK_SENS_AUTO_CORR_MAX_TH_CCK,
196 CFG_AGG_MGG_TID_LOAD_ADDBA_THRESHOLD,
197 CFG_AGG_MGG_TID_LOAD_DELBA_THRESHOLD,
198 CFG_AGG_MGG_ADDBA_BUF_SIZE,
199 CFG_AGG_MGG_ADDBA_INACTIVE_TIMEOUT,
200 CFG_AGG_MGG_ADDBA_DEBUG_FLAGS,
201 CFG_SCAN_PERIODIC_RSSI_HIGH_THRESHOLD,
202 CFG_SCAN_PERIODIC_COEF_RSSI_HIGH,
203 CFG_11D_ENABLED,
204 CFG_11H_FEATURE_FLAGS,
205
206 /* <-- LAST --> */
207 CFG_TBL_FIX_LAST
208};
209
210/* variable size table */
211enum {
212 CFG_NET_ADDR = 0,
213 CFG_LED_PATTERN_TABLE,
214
215 /* <-- LAST --> */
216 CFG_TBL_VAR_LAST
217};
218
219struct iwm_umac_cmd_set_param_fix {
220 __le16 tbl;
221 __le16 key;
222 __le32 value;
223} __packed;
224
225struct iwm_umac_cmd_set_param_var {
226 __le16 tbl;
227 __le16 key;
228 __le16 len;
229 __le16 reserved;
230} __packed;
231
232struct iwm_umac_cmd_get_param {
233 __le16 tbl;
234 __le16 key;
235} __packed;
236
237struct iwm_umac_cmd_get_param_resp {
238 __le16 tbl;
239 __le16 key;
240 __le16 len;
241 __le16 reserved;
242} __packed;
243
244struct iwm_umac_cmd_eeprom_proxy_hdr {
245 __le32 type;
246 __le32 offset;
247 __le32 len;
248} __packed;
249
250struct iwm_umac_cmd_eeprom_proxy {
251 struct iwm_umac_cmd_eeprom_proxy_hdr hdr;
252 u8 buf[0];
253} __packed;
254
255#define IWM_UMAC_CMD_EEPROM_TYPE_READ 0x1
256#define IWM_UMAC_CMD_EEPROM_TYPE_WRITE 0x2
257
258#define UMAC_CHANNEL_FLAG_VALID BIT(0)
259#define UMAC_CHANNEL_FLAG_IBSS BIT(1)
260#define UMAC_CHANNEL_FLAG_ACTIVE BIT(3)
261#define UMAC_CHANNEL_FLAG_RADAR BIT(4)
262#define UMAC_CHANNEL_FLAG_DFS BIT(7)
263
264struct iwm_umac_channel_info {
265 u8 band;
266 u8 type;
267 u8 reserved;
268 u8 flags;
269 __le32 channels_mask;
270} __packed;
271
272struct iwm_umac_cmd_get_channel_list {
273 __le16 count;
274 __le16 reserved;
275 struct iwm_umac_channel_info ch[0];
276} __packed;
277
278
279/* UMAC WiFi interface commands */
280
281/* Coexistence mode */
282#define COEX_MODE_SA 0x1
283#define COEX_MODE_XOR 0x2
284#define COEX_MODE_CM 0x3
285#define COEX_MODE_MAX 0x4
286
287/* Wireless mode */
288#define WIRELESS_MODE_11A 0x1
289#define WIRELESS_MODE_11G 0x2
290#define WIRELESS_MODE_11N 0x4
291
292#define UMAC_PROFILE_EX_IE_REQUIRED 0x1
293#define UMAC_PROFILE_QOS_ALLOWED 0x2
294
295/* Scanning */
296#define UMAC_WIFI_IF_PROBE_OPTION_MAX 10
297
298#define UMAC_WIFI_IF_SCAN_TYPE_USER 0x0
299#define UMAC_WIFI_IF_SCAN_TYPE_UMAC_RESERVED 0x1
300#define UMAC_WIFI_IF_SCAN_TYPE_HOST_PERIODIC 0x2
301#define UMAC_WIFI_IF_SCAN_TYPE_MAX 0x3
302
303struct iwm_umac_ssid {
304 u8 ssid_len;
305 u8 ssid[IEEE80211_MAX_SSID_LEN];
306 u8 reserved[3];
307} __packed;
308
309struct iwm_umac_cmd_scan_request {
310 struct iwm_umac_wifi_if hdr;
311 __le32 type; /* UMAC_WIFI_IF_SCAN_TYPE_* */
312 u8 ssid_num;
313 u8 seq_num;
314 u8 timeout; /* In seconds */
315 u8 reserved;
316 struct iwm_umac_ssid ssids[UMAC_WIFI_IF_PROBE_OPTION_MAX];
317} __packed;
318
319#define UMAC_CIPHER_TYPE_NONE 0xFF
320#define UMAC_CIPHER_TYPE_USE_GROUPCAST 0x00
321#define UMAC_CIPHER_TYPE_WEP_40 0x01
322#define UMAC_CIPHER_TYPE_WEP_104 0x02
323#define UMAC_CIPHER_TYPE_TKIP 0x04
324#define UMAC_CIPHER_TYPE_CCMP 0x08
325
326/* Supported authentication types - bitmap */
327#define UMAC_AUTH_TYPE_OPEN 0x00
328#define UMAC_AUTH_TYPE_LEGACY_PSK 0x01
329#define UMAC_AUTH_TYPE_8021X 0x02
330#define UMAC_AUTH_TYPE_RSNA_PSK 0x04
331
332/* iwm_umac_security.flag is WPA supported -- bits[0:0] */
333#define UMAC_SEC_FLG_WPA_ON_POS 0
334#define UMAC_SEC_FLG_WPA_ON_SEED 1
335#define UMAC_SEC_FLG_WPA_ON_MSK (UMAC_SEC_FLG_WPA_ON_SEED << \
336 UMAC_SEC_FLG_WPA_ON_POS)
337
338/* iwm_umac_security.flag is WPA2 supported -- bits [1:1] */
339#define UMAC_SEC_FLG_RSNA_ON_POS 1
340#define UMAC_SEC_FLG_RSNA_ON_SEED 1
341#define UMAC_SEC_FLG_RSNA_ON_MSK (UMAC_SEC_FLG_RSNA_ON_SEED << \
342 UMAC_SEC_FLG_RSNA_ON_POS)
343
344/* iwm_umac_security.flag is WSC mode on -- bits [2:2] */
345#define UMAC_SEC_FLG_WSC_ON_POS 2
346#define UMAC_SEC_FLG_WSC_ON_SEED 1
347#define UMAC_SEC_FLG_WSC_ON_MSK (UMAC_SEC_FLG_WSC_ON_SEED << \
348 UMAC_SEC_FLG_WSC_ON_POS)
349
350
351/* Legacy profile can use only WEP40 and WEP104 for encryption and
352 * OPEN or PSK for authentication */
353#define UMAC_SEC_FLG_LEGACY_PROFILE 0
354
355struct iwm_umac_security {
356 u8 auth_type;
357 u8 ucast_cipher;
358 u8 mcast_cipher;
359 u8 flags;
360} __packed;
361
362struct iwm_umac_ibss {
363 u8 beacon_interval; /* in millisecond */
364 u8 atim; /* in millisecond */
365 s8 join_only;
366 u8 band;
367 u8 channel;
368 u8 reserved[3];
369} __packed;
370
371#define UMAC_MODE_BSS 0
372#define UMAC_MODE_IBSS 1
373
374#define UMAC_BSSID_MAX 4
375
376struct iwm_umac_profile {
377 struct iwm_umac_wifi_if hdr;
378 __le32 mode;
379 struct iwm_umac_ssid ssid;
380 u8 bssid[UMAC_BSSID_MAX][ETH_ALEN];
381 struct iwm_umac_security sec;
382 struct iwm_umac_ibss ibss;
383 __le32 channel_2ghz;
384 __le32 channel_5ghz;
385 __le16 flags;
386 u8 wireless_mode;
387 u8 bss_num;
388} __packed;
389
390struct iwm_umac_invalidate_profile {
391 struct iwm_umac_wifi_if hdr;
392 u8 reason;
393 u8 reserved[3];
394} __packed;
395
396/* Encryption key commands */
397struct iwm_umac_key_wep40 {
398 struct iwm_umac_wifi_if hdr;
399 struct iwm_umac_key_hdr key_hdr;
400 u8 key[WLAN_KEY_LEN_WEP40];
401 u8 static_key;
402 u8 reserved[2];
403} __packed;
404
405struct iwm_umac_key_wep104 {
406 struct iwm_umac_wifi_if hdr;
407 struct iwm_umac_key_hdr key_hdr;
408 u8 key[WLAN_KEY_LEN_WEP104];
409 u8 static_key;
410 u8 reserved[2];
411} __packed;
412
413#define IWM_TKIP_KEY_SIZE 16
414#define IWM_TKIP_MIC_SIZE 8
415struct iwm_umac_key_tkip {
416 struct iwm_umac_wifi_if hdr;
417 struct iwm_umac_key_hdr key_hdr;
418 u8 iv_count[6];
419 u8 reserved[2];
420 u8 tkip_key[IWM_TKIP_KEY_SIZE];
421 u8 mic_rx_key[IWM_TKIP_MIC_SIZE];
422 u8 mic_tx_key[IWM_TKIP_MIC_SIZE];
423} __packed;
424
425struct iwm_umac_key_ccmp {
426 struct iwm_umac_wifi_if hdr;
427 struct iwm_umac_key_hdr key_hdr;
428 u8 iv_count[6];
429 u8 reserved[2];
430 u8 key[WLAN_KEY_LEN_CCMP];
431} __packed;
432
433struct iwm_umac_key_remove {
434 struct iwm_umac_wifi_if hdr;
435 struct iwm_umac_key_hdr key_hdr;
436} __packed;
437
438struct iwm_umac_tx_key_id {
439 struct iwm_umac_wifi_if hdr;
440 u8 key_idx;
441 u8 reserved[3];
442} __packed;
443
444struct iwm_umac_pwr_trigger {
445 struct iwm_umac_wifi_if hdr;
446 __le32 reseved;
447} __packed;
448
449struct iwm_umac_cmd_stats_req {
450 __le32 flags;
451} __packed;
452
453struct iwm_umac_cmd_stop_resume_tx {
454 u8 flags;
455 u8 sta_id;
456 __le16 stop_resume_tid_msk;
457 __le16 last_seq_num[IWM_UMAC_TID_NR];
458 u16 reserved;
459} __packed;
460
461#define IWM_CMD_PMKID_ADD 1
462#define IWM_CMD_PMKID_DEL 2
463#define IWM_CMD_PMKID_FLUSH 3
464
465struct iwm_umac_pmkid_update {
466 struct iwm_umac_wifi_if hdr;
467 __le32 command;
468 u8 bssid[ETH_ALEN];
469 __le16 reserved;
470 u8 pmkid[WLAN_PMKID_LEN];
471} __packed;
472
473/* LMAC commands */
474int iwm_read_mac(struct iwm_priv *iwm, u8 *mac);
475int iwm_send_prio_table(struct iwm_priv *iwm);
476int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested);
477int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested);
478int iwm_send_calib_results(struct iwm_priv *iwm);
479int iwm_store_rxiq_calib_result(struct iwm_priv *iwm);
480int iwm_send_ct_kill_cfg(struct iwm_priv *iwm, u8 entry, u8 exit);
481
482/* UMAC commands */
483int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size,
484 bool resp);
485int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp);
486int iwm_umac_set_config_fix(struct iwm_priv *iwm, u16 tbl, u16 key, u32 value);
487int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key,
488 void *payload, u16 payload_size);
489int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags);
490int iwm_send_mlme_profile(struct iwm_priv *iwm);
491int __iwm_invalidate_mlme_profile(struct iwm_priv *iwm);
492int iwm_invalidate_mlme_profile(struct iwm_priv *iwm);
493int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id);
494int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx);
495int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key);
496int iwm_tx_power_trigger(struct iwm_priv *iwm);
497int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags);
498int iwm_send_umac_channel_list(struct iwm_priv *iwm);
499int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids,
500 int ssid_num);
501int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len);
502int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm,
503 struct iwm_umac_notif_stop_resume_tx *ntf);
504int iwm_send_pmkid_update(struct iwm_priv *iwm,
505 struct cfg80211_pmksa *pmksa, u32 command);
506
507/* UDMA commands */
508int iwm_target_reset(struct iwm_priv *iwm);
509#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/debug.h b/drivers/net/wireless/iwmc3200wifi/debug.h
deleted file mode 100644
index a0c13a49ab3c..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/debug.h
+++ /dev/null
@@ -1,123 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 */
23
24#ifndef __IWM_DEBUG_H__
25#define __IWM_DEBUG_H__
26
27#define IWM_ERR(p, f, a...) dev_err(iwm_to_dev(p), f, ## a)
28#define IWM_WARN(p, f, a...) dev_warn(iwm_to_dev(p), f, ## a)
29#define IWM_INFO(p, f, a...) dev_info(iwm_to_dev(p), f, ## a)
30#define IWM_CRIT(p, f, a...) dev_crit(iwm_to_dev(p), f, ## a)
31
32#ifdef CONFIG_IWM_DEBUG
33
34#define IWM_DEBUG_MODULE(i, level, module, f, a...) \
35do { \
36 if (unlikely(i->dbg.dbg_module[IWM_DM_##module] >= (IWM_DL_##level)))\
37 dev_printk(KERN_INFO, (iwm_to_dev(i)), \
38 "%s " f, __func__ , ## a); \
39} while (0)
40
41#define IWM_HEXDUMP(i, level, module, pref, buf, len) \
42do { \
43 if (unlikely(i->dbg.dbg_module[IWM_DM_##module] >= (IWM_DL_##level)))\
44 print_hex_dump(KERN_INFO, pref, DUMP_PREFIX_OFFSET, \
45 16, 1, buf, len, 1); \
46} while (0)
47
48#else
49
50#define IWM_DEBUG_MODULE(i, level, module, f, a...)
51#define IWM_HEXDUMP(i, level, module, pref, buf, len)
52
53#endif /* CONFIG_IWM_DEBUG */
54
55/* Debug modules */
56enum iwm_debug_module_id {
57 IWM_DM_BOOT = 0,
58 IWM_DM_FW,
59 IWM_DM_SDIO,
60 IWM_DM_NTF,
61 IWM_DM_RX,
62 IWM_DM_TX,
63 IWM_DM_MLME,
64 IWM_DM_CMD,
65 IWM_DM_WEXT,
66 __IWM_DM_NR,
67};
68#define IWM_DM_DEFAULT 0
69
70#define IWM_DBG_BOOT(i, l, f, a...) IWM_DEBUG_MODULE(i, l, BOOT, f, ## a)
71#define IWM_DBG_FW(i, l, f, a...) IWM_DEBUG_MODULE(i, l, FW, f, ## a)
72#define IWM_DBG_SDIO(i, l, f, a...) IWM_DEBUG_MODULE(i, l, SDIO, f, ## a)
73#define IWM_DBG_NTF(i, l, f, a...) IWM_DEBUG_MODULE(i, l, NTF, f, ## a)
74#define IWM_DBG_RX(i, l, f, a...) IWM_DEBUG_MODULE(i, l, RX, f, ## a)
75#define IWM_DBG_TX(i, l, f, a...) IWM_DEBUG_MODULE(i, l, TX, f, ## a)
76#define IWM_DBG_MLME(i, l, f, a...) IWM_DEBUG_MODULE(i, l, MLME, f, ## a)
77#define IWM_DBG_CMD(i, l, f, a...) IWM_DEBUG_MODULE(i, l, CMD, f, ## a)
78#define IWM_DBG_WEXT(i, l, f, a...) IWM_DEBUG_MODULE(i, l, WEXT, f, ## a)
79
80/* Debug levels */
81enum iwm_debug_level {
82 IWM_DL_NONE = 0,
83 IWM_DL_ERR,
84 IWM_DL_WARN,
85 IWM_DL_INFO,
86 IWM_DL_DBG,
87};
88#define IWM_DL_DEFAULT IWM_DL_ERR
89
90struct iwm_debugfs {
91 struct iwm_priv *iwm;
92 struct dentry *rootdir;
93 struct dentry *devdir;
94 struct dentry *dbgdir;
95 struct dentry *txdir;
96 struct dentry *rxdir;
97 struct dentry *busdir;
98
99 u32 dbg_level;
100 struct dentry *dbg_level_dentry;
101
102 unsigned long dbg_modules;
103 struct dentry *dbg_modules_dentry;
104
105 u8 dbg_module[__IWM_DM_NR];
106 struct dentry *dbg_module_dentries[__IWM_DM_NR];
107
108 struct dentry *txq_dentry;
109 struct dentry *tx_credit_dentry;
110 struct dentry *rx_ticket_dentry;
111
112 struct dentry *fw_err_dentry;
113};
114
115#ifdef CONFIG_IWM_DEBUG
116void iwm_debugfs_init(struct iwm_priv *iwm);
117void iwm_debugfs_exit(struct iwm_priv *iwm);
118#else
119static inline void iwm_debugfs_init(struct iwm_priv *iwm) {}
120static inline void iwm_debugfs_exit(struct iwm_priv *iwm) {}
121#endif
122
123#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c
deleted file mode 100644
index b6199d124bb9..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/debugfs.c
+++ /dev/null
@@ -1,488 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 */
23
24#include <linux/slab.h>
25#include <linux/kernel.h>
26#include <linux/bitops.h>
27#include <linux/debugfs.h>
28#include <linux/export.h>
29
30#include "iwm.h"
31#include "bus.h"
32#include "rx.h"
33#include "debug.h"
34
35static struct {
36 u8 id;
37 char *name;
38} iwm_debug_module[__IWM_DM_NR] = {
39 {IWM_DM_BOOT, "boot"},
40 {IWM_DM_FW, "fw"},
41 {IWM_DM_SDIO, "sdio"},
42 {IWM_DM_NTF, "ntf"},
43 {IWM_DM_RX, "rx"},
44 {IWM_DM_TX, "tx"},
45 {IWM_DM_MLME, "mlme"},
46 {IWM_DM_CMD, "cmd"},
47 {IWM_DM_WEXT, "wext"},
48};
49
50#define add_dbg_module(dbg, name, id, initlevel) \
51do { \
52 dbg.dbg_module[id] = (initlevel); \
53 dbg.dbg_module_dentries[id] = \
54 debugfs_create_x8(name, 0600, \
55 dbg.dbgdir, \
56 &(dbg.dbg_module[id])); \
57} while (0)
58
59static int iwm_debugfs_u32_read(void *data, u64 *val)
60{
61 struct iwm_priv *iwm = data;
62
63 *val = iwm->dbg.dbg_level;
64 return 0;
65}
66
67static int iwm_debugfs_dbg_level_write(void *data, u64 val)
68{
69 struct iwm_priv *iwm = data;
70 int i;
71
72 iwm->dbg.dbg_level = val;
73
74 for (i = 0; i < __IWM_DM_NR; i++)
75 iwm->dbg.dbg_module[i] = val;
76
77 return 0;
78}
79DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_level,
80 iwm_debugfs_u32_read, iwm_debugfs_dbg_level_write,
81 "%llu\n");
82
83static int iwm_debugfs_dbg_modules_write(void *data, u64 val)
84{
85 struct iwm_priv *iwm = data;
86 int i, bit;
87
88 iwm->dbg.dbg_modules = val;
89
90 for (i = 0; i < __IWM_DM_NR; i++)
91 iwm->dbg.dbg_module[i] = 0;
92
93 for_each_set_bit(bit, &iwm->dbg.dbg_modules, __IWM_DM_NR)
94 iwm->dbg.dbg_module[bit] = iwm->dbg.dbg_level;
95
96 return 0;
97}
98DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_modules,
99 iwm_debugfs_u32_read, iwm_debugfs_dbg_modules_write,
100 "%llu\n");
101
102
103static ssize_t iwm_debugfs_txq_read(struct file *filp, char __user *buffer,
104 size_t count, loff_t *ppos)
105{
106 struct iwm_priv *iwm = filp->private_data;
107 char *buf;
108 int i, buf_len = 4096;
109 size_t len = 0;
110 ssize_t ret;
111
112 if (*ppos != 0)
113 return 0;
114 if (count < sizeof(buf))
115 return -ENOSPC;
116
117 buf = kzalloc(buf_len, GFP_KERNEL);
118 if (!buf)
119 return -ENOMEM;
120
121 for (i = 0; i < IWM_TX_QUEUES; i++) {
122 struct iwm_tx_queue *txq = &iwm->txq[i];
123 struct sk_buff *skb;
124 int j;
125 unsigned long flags;
126
127 spin_lock_irqsave(&txq->queue.lock, flags);
128
129 skb = (struct sk_buff *)&txq->queue;
130
131 len += snprintf(buf + len, buf_len - len, "TXQ #%d\n", i);
132 len += snprintf(buf + len, buf_len - len, "\tStopped: %d\n",
133 __netif_subqueue_stopped(iwm_to_ndev(iwm),
134 txq->id));
135 len += snprintf(buf + len, buf_len - len, "\tConcat count:%d\n",
136 txq->concat_count);
137 len += snprintf(buf + len, buf_len - len, "\tQueue len: %d\n",
138 skb_queue_len(&txq->queue));
139 for (j = 0; j < skb_queue_len(&txq->queue); j++) {
140 struct iwm_tx_info *tx_info;
141
142 skb = skb->next;
143 tx_info = skb_to_tx_info(skb);
144
145 len += snprintf(buf + len, buf_len - len,
146 "\tSKB #%d\n", j);
147 len += snprintf(buf + len, buf_len - len,
148 "\t\tsta: %d\n", tx_info->sta);
149 len += snprintf(buf + len, buf_len - len,
150 "\t\tcolor: %d\n", tx_info->color);
151 len += snprintf(buf + len, buf_len - len,
152 "\t\ttid: %d\n", tx_info->tid);
153 }
154
155 spin_unlock_irqrestore(&txq->queue.lock, flags);
156
157 spin_lock_irqsave(&txq->stopped_queue.lock, flags);
158
159 len += snprintf(buf + len, buf_len - len,
160 "\tStopped Queue len: %d\n",
161 skb_queue_len(&txq->stopped_queue));
162 for (j = 0; j < skb_queue_len(&txq->stopped_queue); j++) {
163 struct iwm_tx_info *tx_info;
164
165 skb = skb->next;
166 tx_info = skb_to_tx_info(skb);
167
168 len += snprintf(buf + len, buf_len - len,
169 "\tSKB #%d\n", j);
170 len += snprintf(buf + len, buf_len - len,
171 "\t\tsta: %d\n", tx_info->sta);
172 len += snprintf(buf + len, buf_len - len,
173 "\t\tcolor: %d\n", tx_info->color);
174 len += snprintf(buf + len, buf_len - len,
175 "\t\ttid: %d\n", tx_info->tid);
176 }
177
178 spin_unlock_irqrestore(&txq->stopped_queue.lock, flags);
179 }
180
181 ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
182 kfree(buf);
183
184 return ret;
185}
186
187static ssize_t iwm_debugfs_tx_credit_read(struct file *filp,
188 char __user *buffer,
189 size_t count, loff_t *ppos)
190{
191 struct iwm_priv *iwm = filp->private_data;
192 struct iwm_tx_credit *credit = &iwm->tx_credit;
193 char *buf;
194 int i, buf_len = 4096;
195 size_t len = 0;
196 ssize_t ret;
197
198 if (*ppos != 0)
199 return 0;
200 if (count < sizeof(buf))
201 return -ENOSPC;
202
203 buf = kzalloc(buf_len, GFP_KERNEL);
204 if (!buf)
205 return -ENOMEM;
206
207 len += snprintf(buf + len, buf_len - len,
208 "NR pools: %d\n", credit->pool_nr);
209 len += snprintf(buf + len, buf_len - len,
210 "pools map: 0x%lx\n", credit->full_pools_map);
211
212 len += snprintf(buf + len, buf_len - len, "\n### POOLS ###\n");
213 for (i = 0; i < IWM_MACS_OUT_GROUPS; i++) {
214 len += snprintf(buf + len, buf_len - len,
215 "pools entry #%d\n", i);
216 len += snprintf(buf + len, buf_len - len,
217 "\tid: %d\n",
218 credit->pools[i].id);
219 len += snprintf(buf + len, buf_len - len,
220 "\tsid: %d\n",
221 credit->pools[i].sid);
222 len += snprintf(buf + len, buf_len - len,
223 "\tmin_pages: %d\n",
224 credit->pools[i].min_pages);
225 len += snprintf(buf + len, buf_len - len,
226 "\tmax_pages: %d\n",
227 credit->pools[i].max_pages);
228 len += snprintf(buf + len, buf_len - len,
229 "\talloc_pages: %d\n",
230 credit->pools[i].alloc_pages);
231 len += snprintf(buf + len, buf_len - len,
232 "\tfreed_pages: %d\n",
233 credit->pools[i].total_freed_pages);
234 }
235
236 len += snprintf(buf + len, buf_len - len, "\n### SPOOLS ###\n");
237 for (i = 0; i < IWM_MACS_OUT_SGROUPS; i++) {
238 len += snprintf(buf + len, buf_len - len,
239 "spools entry #%d\n", i);
240 len += snprintf(buf + len, buf_len - len,
241 "\tid: %d\n",
242 credit->spools[i].id);
243 len += snprintf(buf + len, buf_len - len,
244 "\tmax_pages: %d\n",
245 credit->spools[i].max_pages);
246 len += snprintf(buf + len, buf_len - len,
247 "\talloc_pages: %d\n",
248 credit->spools[i].alloc_pages);
249
250 }
251
252 ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
253 kfree(buf);
254
255 return ret;
256}
257
258static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp,
259 char __user *buffer,
260 size_t count, loff_t *ppos)
261{
262 struct iwm_priv *iwm = filp->private_data;
263 struct iwm_rx_ticket_node *ticket;
264 char *buf;
265 int buf_len = 4096, i;
266 size_t len = 0;
267 ssize_t ret;
268
269 if (*ppos != 0)
270 return 0;
271 if (count < sizeof(buf))
272 return -ENOSPC;
273
274 buf = kzalloc(buf_len, GFP_KERNEL);
275 if (!buf)
276 return -ENOMEM;
277
278 spin_lock(&iwm->ticket_lock);
279 list_for_each_entry(ticket, &iwm->rx_tickets, node) {
280 len += snprintf(buf + len, buf_len - len, "Ticket #%d\n",
281 ticket->ticket->id);
282 len += snprintf(buf + len, buf_len - len, "\taction: 0x%x\n",
283 ticket->ticket->action);
284 len += snprintf(buf + len, buf_len - len, "\tflags: 0x%x\n",
285 ticket->ticket->flags);
286 }
287 spin_unlock(&iwm->ticket_lock);
288
289 for (i = 0; i < IWM_RX_ID_HASH; i++) {
290 struct iwm_rx_packet *packet;
291 struct list_head *pkt_list = &iwm->rx_packets[i];
292
293 if (!list_empty(pkt_list)) {
294 len += snprintf(buf + len, buf_len - len,
295 "Packet hash #%d\n", i);
296 spin_lock(&iwm->packet_lock[i]);
297 list_for_each_entry(packet, pkt_list, node) {
298 len += snprintf(buf + len, buf_len - len,
299 "\tPacket id: %d\n",
300 packet->id);
301 len += snprintf(buf + len, buf_len - len,
302 "\tPacket length: %lu\n",
303 packet->pkt_size);
304 }
305 spin_unlock(&iwm->packet_lock[i]);
306 }
307 }
308
309 ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
310 kfree(buf);
311
312 return ret;
313}
314
315static ssize_t iwm_debugfs_fw_err_read(struct file *filp,
316 char __user *buffer,
317 size_t count, loff_t *ppos)
318{
319
320 struct iwm_priv *iwm = filp->private_data;
321 char buf[512];
322 int buf_len = 512;
323 size_t len = 0;
324
325 if (*ppos != 0)
326 return 0;
327 if (count < sizeof(buf))
328 return -ENOSPC;
329
330 if (!iwm->last_fw_err)
331 return -ENOMEM;
332
333 if (iwm->last_fw_err->line_num == 0)
334 goto out;
335
336 len += snprintf(buf + len, buf_len - len, "%cMAC FW ERROR:\n",
337 (le32_to_cpu(iwm->last_fw_err->category) == UMAC_SYS_ERR_CAT_LMAC)
338 ? 'L' : 'U');
339 len += snprintf(buf + len, buf_len - len,
340 "\tCategory: %d\n",
341 le32_to_cpu(iwm->last_fw_err->category));
342
343 len += snprintf(buf + len, buf_len - len,
344 "\tStatus: 0x%x\n",
345 le32_to_cpu(iwm->last_fw_err->status));
346
347 len += snprintf(buf + len, buf_len - len,
348 "\tPC: 0x%x\n",
349 le32_to_cpu(iwm->last_fw_err->pc));
350
351 len += snprintf(buf + len, buf_len - len,
352 "\tblink1: %d\n",
353 le32_to_cpu(iwm->last_fw_err->blink1));
354
355 len += snprintf(buf + len, buf_len - len,
356 "\tblink2: %d\n",
357 le32_to_cpu(iwm->last_fw_err->blink2));
358
359 len += snprintf(buf + len, buf_len - len,
360 "\tilink1: %d\n",
361 le32_to_cpu(iwm->last_fw_err->ilink1));
362
363 len += snprintf(buf + len, buf_len - len,
364 "\tilink2: %d\n",
365 le32_to_cpu(iwm->last_fw_err->ilink2));
366
367 len += snprintf(buf + len, buf_len - len,
368 "\tData1: 0x%x\n",
369 le32_to_cpu(iwm->last_fw_err->data1));
370
371 len += snprintf(buf + len, buf_len - len,
372 "\tData2: 0x%x\n",
373 le32_to_cpu(iwm->last_fw_err->data2));
374
375 len += snprintf(buf + len, buf_len - len,
376 "\tLine number: %d\n",
377 le32_to_cpu(iwm->last_fw_err->line_num));
378
379 len += snprintf(buf + len, buf_len - len,
380 "\tUMAC status: 0x%x\n",
381 le32_to_cpu(iwm->last_fw_err->umac_status));
382
383 len += snprintf(buf + len, buf_len - len,
384 "\tLMAC status: 0x%x\n",
385 le32_to_cpu(iwm->last_fw_err->lmac_status));
386
387 len += snprintf(buf + len, buf_len - len,
388 "\tSDIO status: 0x%x\n",
389 le32_to_cpu(iwm->last_fw_err->sdio_status));
390
391out:
392
393 return simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
394}
395
396static const struct file_operations iwm_debugfs_txq_fops = {
397 .owner = THIS_MODULE,
398 .open = simple_open,
399 .read = iwm_debugfs_txq_read,
400 .llseek = default_llseek,
401};
402
403static const struct file_operations iwm_debugfs_tx_credit_fops = {
404 .owner = THIS_MODULE,
405 .open = simple_open,
406 .read = iwm_debugfs_tx_credit_read,
407 .llseek = default_llseek,
408};
409
410static const struct file_operations iwm_debugfs_rx_ticket_fops = {
411 .owner = THIS_MODULE,
412 .open = simple_open,
413 .read = iwm_debugfs_rx_ticket_read,
414 .llseek = default_llseek,
415};
416
417static const struct file_operations iwm_debugfs_fw_err_fops = {
418 .owner = THIS_MODULE,
419 .open = simple_open,
420 .read = iwm_debugfs_fw_err_read,
421 .llseek = default_llseek,
422};
423
424void iwm_debugfs_init(struct iwm_priv *iwm)
425{
426 int i;
427
428 iwm->dbg.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
429 iwm->dbg.devdir = debugfs_create_dir(wiphy_name(iwm_to_wiphy(iwm)),
430 iwm->dbg.rootdir);
431 iwm->dbg.dbgdir = debugfs_create_dir("debug", iwm->dbg.devdir);
432 iwm->dbg.rxdir = debugfs_create_dir("rx", iwm->dbg.devdir);
433 iwm->dbg.txdir = debugfs_create_dir("tx", iwm->dbg.devdir);
434 iwm->dbg.busdir = debugfs_create_dir("bus", iwm->dbg.devdir);
435 if (iwm->bus_ops->debugfs_init)
436 iwm->bus_ops->debugfs_init(iwm, iwm->dbg.busdir);
437
438 iwm->dbg.dbg_level = IWM_DL_NONE;
439 iwm->dbg.dbg_level_dentry =
440 debugfs_create_file("level", 0200, iwm->dbg.dbgdir, iwm,
441 &fops_iwm_dbg_level);
442
443 iwm->dbg.dbg_modules = IWM_DM_DEFAULT;
444 iwm->dbg.dbg_modules_dentry =
445 debugfs_create_file("modules", 0200, iwm->dbg.dbgdir, iwm,
446 &fops_iwm_dbg_modules);
447
448 for (i = 0; i < __IWM_DM_NR; i++)
449 add_dbg_module(iwm->dbg, iwm_debug_module[i].name,
450 iwm_debug_module[i].id, IWM_DL_DEFAULT);
451
452 iwm->dbg.txq_dentry = debugfs_create_file("queues", 0200,
453 iwm->dbg.txdir, iwm,
454 &iwm_debugfs_txq_fops);
455 iwm->dbg.tx_credit_dentry = debugfs_create_file("credits", 0200,
456 iwm->dbg.txdir, iwm,
457 &iwm_debugfs_tx_credit_fops);
458 iwm->dbg.rx_ticket_dentry = debugfs_create_file("tickets", 0200,
459 iwm->dbg.rxdir, iwm,
460 &iwm_debugfs_rx_ticket_fops);
461 iwm->dbg.fw_err_dentry = debugfs_create_file("last_fw_err", 0200,
462 iwm->dbg.dbgdir, iwm,
463 &iwm_debugfs_fw_err_fops);
464}
465
466void iwm_debugfs_exit(struct iwm_priv *iwm)
467{
468 int i;
469
470 for (i = 0; i < __IWM_DM_NR; i++)
471 debugfs_remove(iwm->dbg.dbg_module_dentries[i]);
472
473 debugfs_remove(iwm->dbg.dbg_modules_dentry);
474 debugfs_remove(iwm->dbg.dbg_level_dentry);
475 debugfs_remove(iwm->dbg.txq_dentry);
476 debugfs_remove(iwm->dbg.tx_credit_dentry);
477 debugfs_remove(iwm->dbg.rx_ticket_dentry);
478 debugfs_remove(iwm->dbg.fw_err_dentry);
479 if (iwm->bus_ops->debugfs_exit)
480 iwm->bus_ops->debugfs_exit(iwm);
481
482 debugfs_remove(iwm->dbg.busdir);
483 debugfs_remove(iwm->dbg.dbgdir);
484 debugfs_remove(iwm->dbg.txdir);
485 debugfs_remove(iwm->dbg.rxdir);
486 debugfs_remove(iwm->dbg.devdir);
487 debugfs_remove(iwm->dbg.rootdir);
488}
diff --git a/drivers/net/wireless/iwmc3200wifi/eeprom.c b/drivers/net/wireless/iwmc3200wifi/eeprom.c
deleted file mode 100644
index e80e776b74f7..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/eeprom.c
+++ /dev/null
@@ -1,234 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#include <linux/kernel.h>
40#include <linux/slab.h>
41
42#include "iwm.h"
43#include "umac.h"
44#include "commands.h"
45#include "eeprom.h"
46
47static struct iwm_eeprom_entry eeprom_map[] = {
48 [IWM_EEPROM_SIG] =
49 {"Signature", IWM_EEPROM_SIG_OFF, IWM_EEPROM_SIG_LEN},
50
51 [IWM_EEPROM_VERSION] =
52 {"Version", IWM_EEPROM_VERSION_OFF, IWM_EEPROM_VERSION_LEN},
53
54 [IWM_EEPROM_OEM_HW_VERSION] =
55 {"OEM HW version", IWM_EEPROM_OEM_HW_VERSION_OFF,
56 IWM_EEPROM_OEM_HW_VERSION_LEN},
57
58 [IWM_EEPROM_MAC_VERSION] =
59 {"MAC version", IWM_EEPROM_MAC_VERSION_OFF, IWM_EEPROM_MAC_VERSION_LEN},
60
61 [IWM_EEPROM_CARD_ID] =
62 {"Card ID", IWM_EEPROM_CARD_ID_OFF, IWM_EEPROM_CARD_ID_LEN},
63
64 [IWM_EEPROM_RADIO_CONF] =
65 {"Radio config", IWM_EEPROM_RADIO_CONF_OFF, IWM_EEPROM_RADIO_CONF_LEN},
66
67 [IWM_EEPROM_SKU_CAP] =
68 {"SKU capabilities", IWM_EEPROM_SKU_CAP_OFF, IWM_EEPROM_SKU_CAP_LEN},
69
70 [IWM_EEPROM_FAT_CHANNELS_CAP] =
71 {"HT channels capabilities", IWM_EEPROM_FAT_CHANNELS_CAP_OFF,
72 IWM_EEPROM_FAT_CHANNELS_CAP_LEN},
73
74 [IWM_EEPROM_CALIB_RXIQ_OFFSET] =
75 {"RX IQ offset", IWM_EEPROM_CALIB_RXIQ_OFF, IWM_EEPROM_INDIRECT_LEN},
76
77 [IWM_EEPROM_CALIB_RXIQ] =
78 {"Calib RX IQ", 0, IWM_EEPROM_CALIB_RXIQ_LEN},
79};
80
81
82static int iwm_eeprom_read(struct iwm_priv *iwm, u8 eeprom_id)
83{
84 int ret;
85 u32 entry_size, chunk_size, data_offset = 0, addr_offset = 0;
86 u32 addr;
87 struct iwm_udma_wifi_cmd udma_cmd;
88 struct iwm_umac_cmd umac_cmd;
89 struct iwm_umac_cmd_eeprom_proxy eeprom_cmd;
90
91 if (eeprom_id > (IWM_EEPROM_LAST - 1))
92 return -EINVAL;
93
94 entry_size = eeprom_map[eeprom_id].length;
95
96 if (eeprom_id >= IWM_EEPROM_INDIRECT_DATA) {
97 /* indirect data */
98 u32 off_id = eeprom_id - IWM_EEPROM_INDIRECT_DATA +
99 IWM_EEPROM_INDIRECT_OFFSET;
100
101 eeprom_map[eeprom_id].offset =
102 *(u16 *)(iwm->eeprom + eeprom_map[off_id].offset) << 1;
103 }
104
105 addr = eeprom_map[eeprom_id].offset;
106
107 udma_cmd.eop = 1;
108 udma_cmd.credit_group = 0x4;
109 udma_cmd.ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD;
110 udma_cmd.lmac_offset = 0;
111
112 umac_cmd.id = UMAC_CMD_OPCODE_EEPROM_PROXY;
113 umac_cmd.resp = 1;
114
115 while (entry_size > 0) {
116 chunk_size = min_t(u32, entry_size, IWM_MAX_EEPROM_DATA_LEN);
117
118 eeprom_cmd.hdr.type =
119 cpu_to_le32(IWM_UMAC_CMD_EEPROM_TYPE_READ);
120 eeprom_cmd.hdr.offset = cpu_to_le32(addr + addr_offset);
121 eeprom_cmd.hdr.len = cpu_to_le32(chunk_size);
122
123 ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd,
124 &umac_cmd, &eeprom_cmd,
125 sizeof(struct iwm_umac_cmd_eeprom_proxy));
126 if (ret < 0) {
127 IWM_ERR(iwm, "Couldn't read eeprom\n");
128 return ret;
129 }
130
131 ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_EEPROM_PROXY,
132 IWM_SRC_UMAC, 2*HZ);
133 if (ret < 0) {
134 IWM_ERR(iwm, "Did not get any eeprom answer\n");
135 return ret;
136 }
137
138 data_offset += chunk_size;
139 addr_offset += chunk_size;
140 entry_size -= chunk_size;
141 }
142
143 return 0;
144}
145
146u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id)
147{
148 if (!iwm->eeprom)
149 return ERR_PTR(-ENODEV);
150
151 return iwm->eeprom + eeprom_map[eeprom_id].offset;
152}
153
154int iwm_eeprom_fat_channels(struct iwm_priv *iwm)
155{
156 struct wiphy *wiphy = iwm_to_wiphy(iwm);
157 struct ieee80211_supported_band *band;
158 u16 *channels, i;
159
160 channels = (u16 *)iwm_eeprom_access(iwm, IWM_EEPROM_FAT_CHANNELS_CAP);
161 if (IS_ERR(channels))
162 return PTR_ERR(channels);
163
164 band = wiphy->bands[IEEE80211_BAND_2GHZ];
165 band->ht_cap.ht_supported = true;
166
167 for (i = 0; i < IWM_EEPROM_FAT_CHANNELS_24; i++)
168 if (!(channels[i] & IWM_EEPROM_FAT_CHANNEL_ENABLED))
169 band->ht_cap.ht_supported = false;
170
171 band = wiphy->bands[IEEE80211_BAND_5GHZ];
172 band->ht_cap.ht_supported = true;
173 for (i = IWM_EEPROM_FAT_CHANNELS_24; i < IWM_EEPROM_FAT_CHANNELS; i++)
174 if (!(channels[i] & IWM_EEPROM_FAT_CHANNEL_ENABLED))
175 band->ht_cap.ht_supported = false;
176
177 return 0;
178}
179
180u32 iwm_eeprom_wireless_mode(struct iwm_priv *iwm)
181{
182 u16 sku_cap;
183 u32 wireless_mode = 0;
184
185 sku_cap = *((u16 *)iwm_eeprom_access(iwm, IWM_EEPROM_SKU_CAP));
186
187 if (sku_cap & IWM_EEPROM_SKU_CAP_BAND_24GHZ)
188 wireless_mode |= WIRELESS_MODE_11G;
189
190 if (sku_cap & IWM_EEPROM_SKU_CAP_BAND_52GHZ)
191 wireless_mode |= WIRELESS_MODE_11A;
192
193 if (sku_cap & IWM_EEPROM_SKU_CAP_11N_ENABLE)
194 wireless_mode |= WIRELESS_MODE_11N;
195
196 return wireless_mode;
197}
198
199
200int iwm_eeprom_init(struct iwm_priv *iwm)
201{
202 int i, ret = 0;
203 char name[32];
204
205 iwm->eeprom = kzalloc(IWM_EEPROM_LEN, GFP_KERNEL);
206 if (!iwm->eeprom)
207 return -ENOMEM;
208
209 for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) {
210 ret = iwm_eeprom_read(iwm, i);
211 if (ret < 0) {
212 IWM_ERR(iwm, "Couldn't read eeprom entry #%d: %s\n",
213 i, eeprom_map[i].name);
214 break;
215 }
216 }
217
218 IWM_DBG_BOOT(iwm, DBG, "EEPROM dump:\n");
219 for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) {
220 memset(name, 0, 32);
221 sprintf(name, "%s: ", eeprom_map[i].name);
222
223 IWM_HEXDUMP(iwm, DBG, BOOT, name,
224 iwm->eeprom + eeprom_map[i].offset,
225 eeprom_map[i].length);
226 }
227
228 return ret;
229}
230
231void iwm_eeprom_exit(struct iwm_priv *iwm)
232{
233 kfree(iwm->eeprom);
234}
diff --git a/drivers/net/wireless/iwmc3200wifi/eeprom.h b/drivers/net/wireless/iwmc3200wifi/eeprom.h
deleted file mode 100644
index 4e3a3fdab0d3..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/eeprom.h
+++ /dev/null
@@ -1,127 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef __IWM_EEPROM_H__
40#define __IWM_EEPROM_H__
41
42enum {
43 IWM_EEPROM_SIG = 0,
44 IWM_EEPROM_FIRST = IWM_EEPROM_SIG,
45 IWM_EEPROM_VERSION,
46 IWM_EEPROM_OEM_HW_VERSION,
47 IWM_EEPROM_MAC_VERSION,
48 IWM_EEPROM_CARD_ID,
49 IWM_EEPROM_RADIO_CONF,
50 IWM_EEPROM_SKU_CAP,
51 IWM_EEPROM_FAT_CHANNELS_CAP,
52
53 IWM_EEPROM_INDIRECT_OFFSET,
54 IWM_EEPROM_CALIB_RXIQ_OFFSET = IWM_EEPROM_INDIRECT_OFFSET,
55
56 IWM_EEPROM_INDIRECT_DATA,
57 IWM_EEPROM_CALIB_RXIQ = IWM_EEPROM_INDIRECT_DATA,
58
59 IWM_EEPROM_LAST,
60};
61
62#define IWM_EEPROM_SIG_OFF 0x00
63#define IWM_EEPROM_VERSION_OFF (0x54 << 1)
64#define IWM_EEPROM_OEM_HW_VERSION_OFF (0x56 << 1)
65#define IWM_EEPROM_MAC_VERSION_OFF (0x30 << 1)
66#define IWM_EEPROM_CARD_ID_OFF (0x5d << 1)
67#define IWM_EEPROM_RADIO_CONF_OFF (0x58 << 1)
68#define IWM_EEPROM_SKU_CAP_OFF (0x55 << 1)
69#define IWM_EEPROM_CALIB_CONFIG_OFF (0x7c << 1)
70#define IWM_EEPROM_FAT_CHANNELS_CAP_OFF (0xde << 1)
71
72#define IWM_EEPROM_SIG_LEN 4
73#define IWM_EEPROM_VERSION_LEN 2
74#define IWM_EEPROM_OEM_HW_VERSION_LEN 2
75#define IWM_EEPROM_MAC_VERSION_LEN 1
76#define IWM_EEPROM_CARD_ID_LEN 2
77#define IWM_EEPROM_RADIO_CONF_LEN 2
78#define IWM_EEPROM_SKU_CAP_LEN 2
79#define IWM_EEPROM_FAT_CHANNELS_CAP_LEN 40
80#define IWM_EEPROM_INDIRECT_LEN 2
81
82#define IWM_MAX_EEPROM_DATA_LEN 240
83#define IWM_EEPROM_LEN 0x800
84
85#define IWM_EEPROM_MIN_ALLOWED_VERSION 0x0610
86#define IWM_EEPROM_MAX_ALLOWED_VERSION 0x0700
87#define IWM_EEPROM_CURRENT_VERSION 0x0612
88
89#define IWM_EEPROM_SKU_CAP_BAND_24GHZ (1 << 4)
90#define IWM_EEPROM_SKU_CAP_BAND_52GHZ (1 << 5)
91#define IWM_EEPROM_SKU_CAP_11N_ENABLE (1 << 6)
92
93#define IWM_EEPROM_FAT_CHANNELS 20
94/* 2.4 gHz FAT primary channels: 1, 2, 3, 4, 5, 6, 7, 8, 9 */
95#define IWM_EEPROM_FAT_CHANNELS_24 9
96/* 5.2 gHz FAT primary channels: 36,44,52,60,100,108,116,124,132,149,157 */
97#define IWM_EEPROM_FAT_CHANNELS_52 11
98
99#define IWM_EEPROM_FAT_CHANNEL_ENABLED (1 << 0)
100
101enum {
102 IWM_EEPROM_CALIB_CAL_HDR,
103 IWM_EEPROM_CALIB_TX_POWER,
104 IWM_EEPROM_CALIB_XTAL,
105 IWM_EEPROM_CALIB_TEMPERATURE,
106 IWM_EEPROM_CALIB_RX_BB_FILTER,
107 IWM_EEPROM_CALIB_RX_IQ,
108 IWM_EEPROM_CALIB_MAX,
109};
110
111#define IWM_EEPROM_CALIB_RXIQ_OFF (IWM_EEPROM_CALIB_CONFIG_OFF + \
112 (IWM_EEPROM_CALIB_RX_IQ << 1))
113#define IWM_EEPROM_CALIB_RXIQ_LEN sizeof(struct iwm_lmac_calib_rxiq)
114
115struct iwm_eeprom_entry {
116 char *name;
117 u32 offset;
118 u32 length;
119};
120
121int iwm_eeprom_init(struct iwm_priv *iwm);
122void iwm_eeprom_exit(struct iwm_priv *iwm);
123u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id);
124int iwm_eeprom_fat_channels(struct iwm_priv *iwm);
125u32 iwm_eeprom_wireless_mode(struct iwm_priv *iwm);
126
127#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c
deleted file mode 100644
index 6f1afe6bbc8c..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/fw.c
+++ /dev/null
@@ -1,416 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#include <linux/kernel.h>
40#include <linux/firmware.h>
41
42#include "iwm.h"
43#include "bus.h"
44#include "hal.h"
45#include "umac.h"
46#include "debug.h"
47#include "fw.h"
48#include "commands.h"
49
50static const char fw_barker[] = "*WESTOPFORNOONE*";
51
52/*
53 * @op_code: Op code we're looking for.
54 * @index: There can be several instances of the same opcode within
55 * the firmware. Index specifies which one we're looking for.
56 */
57static int iwm_fw_op_offset(struct iwm_priv *iwm, const struct firmware *fw,
58 u16 op_code, u32 index)
59{
60 int offset = -EINVAL, fw_offset;
61 u32 op_index = 0;
62 const u8 *fw_ptr;
63 struct iwm_fw_hdr_rec *rec;
64
65 fw_offset = 0;
66 fw_ptr = fw->data;
67
68 /* We first need to look for the firmware barker */
69 if (memcmp(fw_ptr, fw_barker, IWM_HDR_BARKER_LEN)) {
70 IWM_ERR(iwm, "No barker string in this FW\n");
71 return -EINVAL;
72 }
73
74 if (fw->size < IWM_HDR_LEN) {
75 IWM_ERR(iwm, "FW is too small (%zu)\n", fw->size);
76 return -EINVAL;
77 }
78
79 fw_offset += IWM_HDR_BARKER_LEN;
80
81 while (fw_offset < fw->size) {
82 rec = (struct iwm_fw_hdr_rec *)(fw_ptr + fw_offset);
83
84 IWM_DBG_FW(iwm, DBG, "FW: op_code: 0x%x, len: %d @ 0x%x\n",
85 rec->op_code, rec->len, fw_offset);
86
87 if (rec->op_code == IWM_HDR_REC_OP_INVALID) {
88 IWM_DBG_FW(iwm, DBG, "Reached INVALID op code\n");
89 break;
90 }
91
92 if (rec->op_code == op_code) {
93 if (op_index == index) {
94 fw_offset += sizeof(struct iwm_fw_hdr_rec);
95 offset = fw_offset;
96 goto out;
97 }
98 op_index++;
99 }
100
101 fw_offset += sizeof(struct iwm_fw_hdr_rec) + rec->len;
102 }
103
104 out:
105 return offset;
106}
107
108static int iwm_load_firmware_chunk(struct iwm_priv *iwm,
109 const struct firmware *fw,
110 struct iwm_fw_img_desc *img_desc)
111{
112 struct iwm_udma_nonwifi_cmd target_cmd;
113 u32 chunk_size;
114 const u8 *chunk_ptr;
115 int ret = 0;
116
117 IWM_DBG_FW(iwm, INFO, "Loading FW chunk: %d bytes @ 0x%x\n",
118 img_desc->length, img_desc->address);
119
120 target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE;
121 target_cmd.handle_by_hw = 1;
122 target_cmd.op2 = 0;
123 target_cmd.resp = 0;
124 target_cmd.eop = 1;
125
126 chunk_size = img_desc->length;
127 chunk_ptr = fw->data + img_desc->offset;
128
129 while (chunk_size > 0) {
130 u32 tmp_chunk_size;
131
132 tmp_chunk_size = min_t(u32, chunk_size,
133 IWM_MAX_NONWIFI_CMD_BUFF_SIZE);
134
135 target_cmd.addr = cpu_to_le32(img_desc->address +
136 (chunk_ptr - fw->data - img_desc->offset));
137 target_cmd.op1_sz = cpu_to_le32(tmp_chunk_size);
138
139 IWM_DBG_FW(iwm, DBG, "\t%d bytes @ 0x%x\n",
140 tmp_chunk_size, target_cmd.addr);
141
142 ret = iwm_hal_send_target_cmd(iwm, &target_cmd, chunk_ptr);
143 if (ret < 0) {
144 IWM_ERR(iwm, "Couldn't load FW chunk\n");
145 break;
146 }
147
148 chunk_size -= tmp_chunk_size;
149 chunk_ptr += tmp_chunk_size;
150 }
151
152 return ret;
153}
154/*
155 * To load a fw image to the target, we basically go through the
156 * fw, looking for OP_MEM_DESC records. Once we found one, we
157 * pass it to iwm_load_firmware_chunk().
158 * The OP_MEM_DESC records contain the actuall memory chunk to be
159 * sent, but also the destination address.
160 */
161static int iwm_load_img(struct iwm_priv *iwm, const char *img_name)
162{
163 const struct firmware *fw;
164 struct iwm_fw_img_desc *img_desc;
165 struct iwm_fw_img_ver *ver;
166 int ret = 0, fw_offset;
167 u32 opcode_idx = 0, build_date;
168 char *build_tag;
169
170 ret = request_firmware(&fw, img_name, iwm_to_dev(iwm));
171 if (ret) {
172 IWM_ERR(iwm, "Request firmware failed");
173 return ret;
174 }
175
176 IWM_DBG_FW(iwm, INFO, "Start to load FW %s\n", img_name);
177
178 while (1) {
179 fw_offset = iwm_fw_op_offset(iwm, fw,
180 IWM_HDR_REC_OP_MEM_DESC,
181 opcode_idx);
182 if (fw_offset < 0)
183 break;
184
185 img_desc = (struct iwm_fw_img_desc *)(fw->data + fw_offset);
186 ret = iwm_load_firmware_chunk(iwm, fw, img_desc);
187 if (ret < 0)
188 goto err_release_fw;
189 opcode_idx++;
190 }
191
192 /* Read firmware version */
193 fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_SW_VER, 0);
194 if (fw_offset < 0)
195 goto err_release_fw;
196
197 ver = (struct iwm_fw_img_ver *)(fw->data + fw_offset);
198
199 /* Read build tag */
200 fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_BUILD_TAG, 0);
201 if (fw_offset < 0)
202 goto err_release_fw;
203
204 build_tag = (char *)(fw->data + fw_offset);
205
206 /* Read build date */
207 fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_BUILD_DATE, 0);
208 if (fw_offset < 0)
209 goto err_release_fw;
210
211 build_date = *(u32 *)(fw->data + fw_offset);
212
213 IWM_INFO(iwm, "%s:\n", img_name);
214 IWM_INFO(iwm, "\tVersion: %02X.%02X\n", ver->major, ver->minor);
215 IWM_INFO(iwm, "\tBuild tag: %s\n", build_tag);
216 IWM_INFO(iwm, "\tBuild date: %x-%x-%x\n",
217 IWM_BUILD_YEAR(build_date), IWM_BUILD_MONTH(build_date),
218 IWM_BUILD_DAY(build_date));
219
220 if (!strcmp(img_name, iwm->bus_ops->umac_name))
221 sprintf(iwm->umac_version, "%02X.%02X",
222 ver->major, ver->minor);
223
224 if (!strcmp(img_name, iwm->bus_ops->lmac_name))
225 sprintf(iwm->lmac_version, "%02X.%02X",
226 ver->major, ver->minor);
227
228 err_release_fw:
229 release_firmware(fw);
230
231 return ret;
232}
233
234static int iwm_load_umac(struct iwm_priv *iwm)
235{
236 struct iwm_udma_nonwifi_cmd target_cmd;
237 int ret;
238
239 ret = iwm_load_img(iwm, iwm->bus_ops->umac_name);
240 if (ret < 0)
241 return ret;
242
243 /* We've loaded the UMAC, we can tell the target to jump there */
244 target_cmd.opcode = UMAC_HDI_OUT_OPCODE_JUMP;
245 target_cmd.addr = cpu_to_le32(UMAC_MU_FW_INST_DATA_12_ADDR);
246 target_cmd.op1_sz = 0;
247 target_cmd.op2 = 0;
248 target_cmd.handle_by_hw = 0;
249 target_cmd.resp = 1 ;
250 target_cmd.eop = 1;
251
252 ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL);
253 if (ret < 0)
254 IWM_ERR(iwm, "Couldn't send JMP command\n");
255
256 return ret;
257}
258
259static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name)
260{
261 int ret;
262
263 ret = iwm_load_img(iwm, img_name);
264 if (ret < 0)
265 return ret;
266
267 return iwm_send_umac_reset(iwm,
268 cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_CLK_EN), 0);
269}
270
271static int iwm_init_calib(struct iwm_priv *iwm, unsigned long cfg_bitmap,
272 unsigned long expected_bitmap, u8 rx_iq_cmd)
273{
274 /* Read RX IQ calibration result from EEPROM */
275 if (test_bit(rx_iq_cmd, &cfg_bitmap)) {
276 iwm_store_rxiq_calib_result(iwm);
277 set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map);
278 }
279
280 iwm_send_prio_table(iwm);
281 iwm_send_init_calib_cfg(iwm, cfg_bitmap);
282
283 while (iwm->calib_done_map != expected_bitmap) {
284 if (iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION,
285 IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT)) {
286 IWM_DBG_FW(iwm, DBG, "Initial calibration timeout\n");
287 return -ETIMEDOUT;
288 }
289
290 IWM_DBG_FW(iwm, DBG, "Got calibration result. calib_done_map: "
291 "0x%lx, expected calibrations: 0x%lx\n",
292 iwm->calib_done_map, expected_bitmap);
293 }
294
295 return 0;
296}
297
298/*
299 * We currently have to load 3 FWs:
300 * 1) The UMAC (Upper MAC).
301 * 2) The calibration LMAC (Lower MAC).
302 * We then send the calibration init command, so that the device can
303 * run a first calibration round.
304 * 3) The operational LMAC, which replaces the calibration one when it's
305 * done with the first calibration round.
306 *
307 * Once those 3 FWs have been loaded, we send the periodic calibration
308 * command, and then the device is available for regular 802.11 operations.
309 */
310int iwm_load_fw(struct iwm_priv *iwm)
311{
312 unsigned long init_calib_map, periodic_calib_map;
313 unsigned long expected_calib_map;
314 int ret;
315
316 /* We first start downloading the UMAC */
317 ret = iwm_load_umac(iwm);
318 if (ret < 0) {
319 IWM_ERR(iwm, "UMAC loading failed\n");
320 return ret;
321 }
322
323 /* Handle UMAC_ALIVE notification */
324 ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_ALIVE, IWM_SRC_UMAC,
325 WAIT_NOTIF_TIMEOUT);
326 if (ret) {
327 IWM_ERR(iwm, "Handle UMAC_ALIVE failed: %d\n", ret);
328 return ret;
329 }
330
331 /* UMAC is alive, we can download the calibration LMAC */
332 ret = iwm_load_lmac(iwm, iwm->bus_ops->calib_lmac_name);
333 if (ret) {
334 IWM_ERR(iwm, "Calibration LMAC loading failed\n");
335 return ret;
336 }
337
338 /* Handle UMAC_INIT_COMPLETE notification */
339 ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_INIT_COMPLETE,
340 IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
341 if (ret) {
342 IWM_ERR(iwm, "Handle INIT_COMPLETE failed for calibration "
343 "LMAC: %d\n", ret);
344 return ret;
345 }
346
347 /* Read EEPROM data */
348 ret = iwm_eeprom_init(iwm);
349 if (ret < 0) {
350 IWM_ERR(iwm, "Couldn't init eeprom array\n");
351 return ret;
352 }
353
354 init_calib_map = iwm->conf.calib_map & IWM_CALIB_MAP_INIT_MSK;
355 expected_calib_map = iwm->conf.expected_calib_map &
356 IWM_CALIB_MAP_INIT_MSK;
357 periodic_calib_map = IWM_CALIB_MAP_PER_LMAC(iwm->conf.calib_map);
358
359 ret = iwm_init_calib(iwm, init_calib_map, expected_calib_map,
360 CALIB_CFG_RX_IQ_IDX);
361 if (ret < 0) {
362 /* Let's try the old way */
363 ret = iwm_init_calib(iwm, expected_calib_map,
364 expected_calib_map,
365 PHY_CALIBRATE_RX_IQ_CMD);
366 if (ret < 0) {
367 IWM_ERR(iwm, "Calibration result timeout\n");
368 goto out;
369 }
370 }
371
372 /* Handle LMAC CALIBRATION_COMPLETE notification */
373 ret = iwm_notif_handle(iwm, CALIBRATION_COMPLETE_NOTIFICATION,
374 IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT);
375 if (ret) {
376 IWM_ERR(iwm, "Wait for CALIBRATION_COMPLETE timeout\n");
377 goto out;
378 }
379
380 IWM_INFO(iwm, "LMAC calibration done: 0x%lx\n", iwm->calib_done_map);
381
382 iwm_send_umac_reset(iwm, cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_RESET), 1);
383
384 ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_RESET, IWM_SRC_UMAC,
385 WAIT_NOTIF_TIMEOUT);
386 if (ret) {
387 IWM_ERR(iwm, "Wait for UMAC RESET timeout\n");
388 goto out;
389 }
390
391 /* Download the operational LMAC */
392 ret = iwm_load_lmac(iwm, iwm->bus_ops->lmac_name);
393 if (ret) {
394 IWM_ERR(iwm, "LMAC loading failed\n");
395 goto out;
396 }
397
398 ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_INIT_COMPLETE,
399 IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
400 if (ret) {
401 IWM_ERR(iwm, "Handle INIT_COMPLETE failed for LMAC: %d\n", ret);
402 goto out;
403 }
404
405 iwm_send_prio_table(iwm);
406 iwm_send_calib_results(iwm);
407 iwm_send_periodic_calib_cfg(iwm, periodic_calib_map);
408 iwm_send_ct_kill_cfg(iwm, iwm->conf.ct_kill_entry,
409 iwm->conf.ct_kill_exit);
410
411 return 0;
412
413 out:
414 iwm_eeprom_exit(iwm);
415 return ret;
416}
diff --git a/drivers/net/wireless/iwmc3200wifi/fw.h b/drivers/net/wireless/iwmc3200wifi/fw.h
deleted file mode 100644
index c70a3b40dad3..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/fw.h
+++ /dev/null
@@ -1,100 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef __IWM_FW_H__
40#define __IWM_FW_H__
41
42/**
43 * struct iwm_fw_hdr_rec - An iwm firmware image is a
44 * concatenation of various records. Each of them is
45 * defined by an ID (aka op code), a length, and the
46 * actual data.
47 * @op_code: The record ID, see IWM_HDR_REC_OP_*
48 *
49 * @len: The record payload length
50 *
51 * @buf: The record payload
52 */
53struct iwm_fw_hdr_rec {
54 u16 op_code;
55 u16 len;
56 u8 buf[0];
57};
58
59/* Header's definitions */
60#define IWM_HDR_LEN (512)
61#define IWM_HDR_BARKER_LEN (16)
62
63/* Header's opcodes */
64#define IWM_HDR_REC_OP_INVALID (0x00)
65#define IWM_HDR_REC_OP_BUILD_DATE (0x01)
66#define IWM_HDR_REC_OP_BUILD_TAG (0x02)
67#define IWM_HDR_REC_OP_SW_VER (0x03)
68#define IWM_HDR_REC_OP_HW_SKU (0x04)
69#define IWM_HDR_REC_OP_BUILD_OPT (0x05)
70#define IWM_HDR_REC_OP_MEM_DESC (0x06)
71#define IWM_HDR_REC_USERDEFS (0x07)
72
73/* Header's records length (in bytes) */
74#define IWM_HDR_REC_LEN_BUILD_DATE (4)
75#define IWM_HDR_REC_LEN_BUILD_TAG (64)
76#define IWM_HDR_REC_LEN_SW_VER (4)
77#define IWM_HDR_REC_LEN_HW_SKU (4)
78#define IWM_HDR_REC_LEN_BUILD_OPT (4)
79#define IWM_HDR_REC_LEN_MEM_DESC (12)
80#define IWM_HDR_REC_LEN_USERDEF (64)
81
82#define IWM_BUILD_YEAR(date) ((date >> 16) & 0xffff)
83#define IWM_BUILD_MONTH(date) ((date >> 8) & 0xff)
84#define IWM_BUILD_DAY(date) (date & 0xff)
85
86struct iwm_fw_img_desc {
87 u32 offset;
88 u32 address;
89 u32 length;
90};
91
92struct iwm_fw_img_ver {
93 u8 minor;
94 u8 major;
95 u16 reserved;
96};
97
98int iwm_load_fw(struct iwm_priv *iwm);
99
100#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/hal.c b/drivers/net/wireless/iwmc3200wifi/hal.c
deleted file mode 100644
index 1cabcb39643f..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/hal.c
+++ /dev/null
@@ -1,470 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39/*
40 * Hardware Abstraction Layer for iwm.
41 *
42 * This file mostly defines an abstraction API for
43 * sending various commands to the target.
44 *
45 * We have 2 types of commands: wifi and non-wifi ones.
46 *
47 * - wifi commands:
48 * They are used for sending LMAC and UMAC commands,
49 * and thus are the most commonly used ones.
50 * There are 2 different wifi command types, the regular
51 * one and the LMAC one. The former is used to send
52 * UMAC commands (see UMAC_CMD_OPCODE_* from umac.h)
53 * while the latter is used for sending commands to the
54 * LMAC. If you look at LMAC commands you'll se that they
55 * are actually regular iwlwifi target commands encapsulated
56 * into a special UMAC command called UMAC passthrough.
57 * This is due to the fact the host talks exclusively
58 * to the UMAC and so there needs to be a special UMAC
59 * command for talking to the LMAC.
60 * This is how a wifi command is laid out:
61 * ------------------------
62 * | iwm_udma_out_wifi_hdr |
63 * ------------------------
64 * | SW meta_data (32 bits) |
65 * ------------------------
66 * | iwm_dev_cmd_hdr |
67 * ------------------------
68 * | payload |
69 * | .... |
70 *
71 * - non-wifi, or general commands:
72 * Those commands are handled by the device's bootrom,
73 * and are typically sent when the UMAC and the LMAC
74 * are not yet available.
75 * * This is how a non-wifi command is laid out:
76 * ---------------------------
77 * | iwm_udma_out_nonwifi_hdr |
78 * ---------------------------
79 * | payload |
80 * | .... |
81
82 *
83 * All the commands start with a UDMA header, which is
84 * basically a 32 bits field. The 4 LSB there define
85 * an opcode that allows the target to differentiate
86 * between wifi (opcode is 0xf) and non-wifi commands
87 * (opcode is [0..0xe]).
88 *
89 * When a command (wifi or non-wifi) is supposed to receive
90 * an answer, we queue the command buffer. When we do receive
91 * a command response from the UMAC, we go through the list
92 * of pending command, and pass both the command and the answer
93 * to the rx handler. Each command is sent with a unique
94 * sequence id, and the answer is sent with the same one. This
95 * is how we're supposed to match an answer with its command.
96 * See rx.c:iwm_rx_handle_[non]wifi() and iwm_get_pending_[non]wifi()
97 * for the implementation details.
98 */
99#include <linux/kernel.h>
100#include <linux/netdevice.h>
101#include <linux/slab.h>
102
103#include "iwm.h"
104#include "bus.h"
105#include "hal.h"
106#include "umac.h"
107#include "debug.h"
108#include "trace.h"
109
110static int iwm_nonwifi_cmd_init(struct iwm_priv *iwm,
111 struct iwm_nonwifi_cmd *cmd,
112 struct iwm_udma_nonwifi_cmd *udma_cmd)
113{
114 INIT_LIST_HEAD(&cmd->pending);
115
116 spin_lock(&iwm->cmd_lock);
117
118 cmd->resp_received = 0;
119
120 cmd->seq_num = iwm->nonwifi_seq_num;
121 udma_cmd->seq_num = cpu_to_le16(cmd->seq_num);
122
123 iwm->nonwifi_seq_num++;
124 iwm->nonwifi_seq_num %= UMAC_NONWIFI_SEQ_NUM_MAX;
125
126 if (udma_cmd->resp)
127 list_add_tail(&cmd->pending, &iwm->nonwifi_pending_cmd);
128
129 spin_unlock(&iwm->cmd_lock);
130
131 cmd->buf.start = cmd->buf.payload;
132 cmd->buf.len = 0;
133
134 memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd));
135
136 return cmd->seq_num;
137}
138
139u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm)
140{
141 u16 seq_num = iwm->wifi_seq_num;
142
143 iwm->wifi_seq_num++;
144 iwm->wifi_seq_num %= UMAC_WIFI_SEQ_NUM_MAX;
145
146 return seq_num;
147}
148
149static void iwm_wifi_cmd_init(struct iwm_priv *iwm,
150 struct iwm_wifi_cmd *cmd,
151 struct iwm_udma_wifi_cmd *udma_cmd,
152 struct iwm_umac_cmd *umac_cmd,
153 struct iwm_lmac_cmd *lmac_cmd,
154 u16 payload_size)
155{
156 INIT_LIST_HEAD(&cmd->pending);
157
158 spin_lock(&iwm->cmd_lock);
159
160 cmd->seq_num = iwm_alloc_wifi_cmd_seq(iwm);
161 umac_cmd->seq_num = cpu_to_le16(cmd->seq_num);
162
163 if (umac_cmd->resp)
164 list_add_tail(&cmd->pending, &iwm->wifi_pending_cmd);
165
166 spin_unlock(&iwm->cmd_lock);
167
168 cmd->buf.start = cmd->buf.payload;
169 cmd->buf.len = 0;
170
171 if (lmac_cmd) {
172 cmd->buf.start -= sizeof(struct iwm_lmac_hdr);
173
174 lmac_cmd->seq_num = cpu_to_le16(cmd->seq_num);
175 lmac_cmd->count = cpu_to_le16(payload_size);
176
177 memcpy(&cmd->lmac_cmd, lmac_cmd, sizeof(*lmac_cmd));
178
179 umac_cmd->count = cpu_to_le16(sizeof(struct iwm_lmac_hdr));
180 } else
181 umac_cmd->count = 0;
182
183 umac_cmd->count = cpu_to_le16(payload_size +
184 le16_to_cpu(umac_cmd->count));
185 udma_cmd->count = cpu_to_le16(sizeof(struct iwm_umac_fw_cmd_hdr) +
186 le16_to_cpu(umac_cmd->count));
187
188 memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd));
189 memcpy(&cmd->umac_cmd, umac_cmd, sizeof(*umac_cmd));
190}
191
192void iwm_cmd_flush(struct iwm_priv *iwm)
193{
194 struct iwm_wifi_cmd *wcmd, *wnext;
195 struct iwm_nonwifi_cmd *nwcmd, *nwnext;
196
197 list_for_each_entry_safe(wcmd, wnext, &iwm->wifi_pending_cmd, pending) {
198 list_del(&wcmd->pending);
199 kfree(wcmd);
200 }
201
202 list_for_each_entry_safe(nwcmd, nwnext, &iwm->nonwifi_pending_cmd,
203 pending) {
204 list_del(&nwcmd->pending);
205 kfree(nwcmd);
206 }
207}
208
209struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, u16 seq_num)
210{
211 struct iwm_wifi_cmd *cmd;
212
213 list_for_each_entry(cmd, &iwm->wifi_pending_cmd, pending)
214 if (cmd->seq_num == seq_num) {
215 list_del(&cmd->pending);
216 return cmd;
217 }
218
219 return NULL;
220}
221
222struct iwm_nonwifi_cmd *iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm,
223 u8 seq_num, u8 cmd_opcode)
224{
225 struct iwm_nonwifi_cmd *cmd;
226
227 list_for_each_entry(cmd, &iwm->nonwifi_pending_cmd, pending)
228 if ((cmd->seq_num == seq_num) &&
229 (cmd->udma_cmd.opcode == cmd_opcode) &&
230 (cmd->resp_received)) {
231 list_del(&cmd->pending);
232 return cmd;
233 }
234
235 return NULL;
236}
237
238static void iwm_build_udma_nonwifi_hdr(struct iwm_priv *iwm,
239 struct iwm_udma_out_nonwifi_hdr *hdr,
240 struct iwm_udma_nonwifi_cmd *cmd)
241{
242 memset(hdr, 0, sizeof(*hdr));
243
244 SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE, cmd->opcode);
245 SET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_RESP, cmd->resp);
246 SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, 1);
247 SET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW,
248 cmd->handle_by_hw);
249 SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_SIGNATURE, UMAC_HDI_OUT_SIGNATURE);
250 SET_VAL32(hdr->cmd, UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM,
251 le16_to_cpu(cmd->seq_num));
252
253 hdr->addr = cmd->addr;
254 hdr->op1_sz = cmd->op1_sz;
255 hdr->op2 = cmd->op2;
256}
257
258static int iwm_send_udma_nonwifi_cmd(struct iwm_priv *iwm,
259 struct iwm_nonwifi_cmd *cmd)
260{
261 struct iwm_udma_out_nonwifi_hdr *udma_hdr;
262 struct iwm_nonwifi_cmd_buff *buf;
263 struct iwm_udma_nonwifi_cmd *udma_cmd = &cmd->udma_cmd;
264
265 buf = &cmd->buf;
266
267 buf->start -= sizeof(struct iwm_umac_nonwifi_out_hdr);
268 buf->len += sizeof(struct iwm_umac_nonwifi_out_hdr);
269
270 udma_hdr = (struct iwm_udma_out_nonwifi_hdr *)(buf->start);
271
272 iwm_build_udma_nonwifi_hdr(iwm, udma_hdr, udma_cmd);
273
274 IWM_DBG_CMD(iwm, DBG,
275 "Send UDMA nonwifi cmd: opcode = 0x%x, resp = 0x%x, "
276 "hw = 0x%x, seqnum = %d, addr = 0x%x, op1_sz = 0x%x, "
277 "op2 = 0x%x\n", udma_cmd->opcode, udma_cmd->resp,
278 udma_cmd->handle_by_hw, cmd->seq_num, udma_cmd->addr,
279 udma_cmd->op1_sz, udma_cmd->op2);
280
281 trace_iwm_tx_nonwifi_cmd(iwm, udma_hdr);
282 return iwm_bus_send_chunk(iwm, buf->start, buf->len);
283}
284
285void iwm_udma_wifi_hdr_set_eop(struct iwm_priv *iwm, u8 *buf, u8 eop)
286{
287 struct iwm_udma_out_wifi_hdr *hdr = (struct iwm_udma_out_wifi_hdr *)buf;
288
289 SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, eop);
290}
291
292void iwm_build_udma_wifi_hdr(struct iwm_priv *iwm,
293 struct iwm_udma_out_wifi_hdr *hdr,
294 struct iwm_udma_wifi_cmd *cmd)
295{
296 memset(hdr, 0, sizeof(*hdr));
297
298 SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE, UMAC_HDI_OUT_OPCODE_WIFI);
299 SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, cmd->eop);
300 SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_SIGNATURE, UMAC_HDI_OUT_SIGNATURE);
301
302 SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_BYTE_COUNT,
303 le16_to_cpu(cmd->count));
304 SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_CREDIT_GRP, cmd->credit_group);
305 SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_RATID, cmd->ra_tid);
306 SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_LMAC_OFFSET, cmd->lmac_offset);
307}
308
309void iwm_build_umac_hdr(struct iwm_priv *iwm,
310 struct iwm_umac_fw_cmd_hdr *hdr,
311 struct iwm_umac_cmd *cmd)
312{
313 memset(hdr, 0, sizeof(*hdr));
314
315 SET_VAL32(hdr->meta_data, UMAC_FW_CMD_BYTE_COUNT,
316 le16_to_cpu(cmd->count));
317 SET_VAL32(hdr->meta_data, UMAC_FW_CMD_TX_STA_COLOR, cmd->color);
318 SET_VAL8(hdr->cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ, cmd->resp);
319
320 hdr->cmd.cmd = cmd->id;
321 hdr->cmd.seq_num = cmd->seq_num;
322}
323
324static int iwm_send_udma_wifi_cmd(struct iwm_priv *iwm,
325 struct iwm_wifi_cmd *cmd)
326{
327 struct iwm_umac_wifi_out_hdr *umac_hdr;
328 struct iwm_wifi_cmd_buff *buf;
329 struct iwm_udma_wifi_cmd *udma_cmd = &cmd->udma_cmd;
330 struct iwm_umac_cmd *umac_cmd = &cmd->umac_cmd;
331 int ret;
332
333 buf = &cmd->buf;
334
335 buf->start -= sizeof(struct iwm_umac_wifi_out_hdr);
336 buf->len += sizeof(struct iwm_umac_wifi_out_hdr);
337
338 umac_hdr = (struct iwm_umac_wifi_out_hdr *)(buf->start);
339
340 iwm_build_udma_wifi_hdr(iwm, &umac_hdr->hw_hdr, udma_cmd);
341 iwm_build_umac_hdr(iwm, &umac_hdr->sw_hdr, umac_cmd);
342
343 IWM_DBG_CMD(iwm, DBG,
344 "Send UDMA wifi cmd: opcode = 0x%x, UMAC opcode = 0x%x, "
345 "eop = 0x%x, count = 0x%x, credit_group = 0x%x, "
346 "ra_tid = 0x%x, lmac_offset = 0x%x, seqnum = %d\n",
347 UMAC_HDI_OUT_OPCODE_WIFI, umac_cmd->id,
348 udma_cmd->eop, udma_cmd->count, udma_cmd->credit_group,
349 udma_cmd->ra_tid, udma_cmd->lmac_offset, cmd->seq_num);
350
351 if (umac_cmd->id == UMAC_CMD_OPCODE_WIFI_PASS_THROUGH)
352 IWM_DBG_CMD(iwm, DBG, "\tLMAC opcode: 0x%x\n",
353 cmd->lmac_cmd.id);
354
355 ret = iwm_tx_credit_alloc(iwm, udma_cmd->credit_group, buf->len);
356
357 /* We keep sending UMAC reset regardless of the command credits.
358 * The UMAC is supposed to be reset anyway and the Tx credits are
359 * reinitialized afterwards. If we are lucky, the reset could
360 * still be done even though we have run out of credits for the
361 * command pool at this moment.*/
362 if (ret && (umac_cmd->id != UMAC_CMD_OPCODE_RESET)) {
363 IWM_DBG_TX(iwm, DBG, "Failed to alloc tx credit for cmd %d\n",
364 umac_cmd->id);
365 return ret;
366 }
367
368 trace_iwm_tx_wifi_cmd(iwm, umac_hdr);
369 return iwm_bus_send_chunk(iwm, buf->start, buf->len);
370}
371
372/* target_cmd a.k.a udma_nonwifi_cmd can be sent when UMAC is not available */
373int iwm_hal_send_target_cmd(struct iwm_priv *iwm,
374 struct iwm_udma_nonwifi_cmd *udma_cmd,
375 const void *payload)
376{
377 struct iwm_nonwifi_cmd *cmd;
378 int ret, seq_num;
379
380 cmd = kzalloc(sizeof(struct iwm_nonwifi_cmd), GFP_KERNEL);
381 if (!cmd) {
382 IWM_ERR(iwm, "Couldn't alloc memory for hal cmd\n");
383 return -ENOMEM;
384 }
385
386 seq_num = iwm_nonwifi_cmd_init(iwm, cmd, udma_cmd);
387
388 if (cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE ||
389 cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT) {
390 cmd->buf.len = le32_to_cpu(cmd->udma_cmd.op1_sz);
391 memcpy(&cmd->buf.payload, payload, cmd->buf.len);
392 }
393
394 ret = iwm_send_udma_nonwifi_cmd(iwm, cmd);
395
396 if (!udma_cmd->resp)
397 kfree(cmd);
398
399 if (ret < 0)
400 return ret;
401
402 return seq_num;
403}
404
405static void iwm_build_lmac_hdr(struct iwm_priv *iwm, struct iwm_lmac_hdr *hdr,
406 struct iwm_lmac_cmd *cmd)
407{
408 memset(hdr, 0, sizeof(*hdr));
409
410 hdr->id = cmd->id;
411 hdr->flags = 0; /* Is this ever used? */
412 hdr->seq_num = cmd->seq_num;
413}
414
415/*
416 * iwm_hal_send_host_cmd(): sends commands to the UMAC or the LMAC.
417 * Sending command to the LMAC is equivalent to sending a
418 * regular UMAC command with the LMAC passthrough or the LMAC
419 * wrapper UMAC command IDs.
420 */
421int iwm_hal_send_host_cmd(struct iwm_priv *iwm,
422 struct iwm_udma_wifi_cmd *udma_cmd,
423 struct iwm_umac_cmd *umac_cmd,
424 struct iwm_lmac_cmd *lmac_cmd,
425 const void *payload, u16 payload_size)
426{
427 struct iwm_wifi_cmd *cmd;
428 struct iwm_lmac_hdr *hdr;
429 int lmac_hdr_len = 0;
430 int ret;
431
432 cmd = kzalloc(sizeof(struct iwm_wifi_cmd), GFP_KERNEL);
433 if (!cmd) {
434 IWM_ERR(iwm, "Couldn't alloc memory for wifi hal cmd\n");
435 return -ENOMEM;
436 }
437
438 iwm_wifi_cmd_init(iwm, cmd, udma_cmd, umac_cmd, lmac_cmd, payload_size);
439
440 if (lmac_cmd) {
441 hdr = (struct iwm_lmac_hdr *)(cmd->buf.start);
442
443 iwm_build_lmac_hdr(iwm, hdr, &cmd->lmac_cmd);
444 lmac_hdr_len = sizeof(struct iwm_lmac_hdr);
445 }
446
447 memcpy(cmd->buf.payload, payload, payload_size);
448 cmd->buf.len = le16_to_cpu(umac_cmd->count);
449
450 ret = iwm_send_udma_wifi_cmd(iwm, cmd);
451
452 /* We free the cmd if we're not expecting any response */
453 if (!umac_cmd->resp)
454 kfree(cmd);
455 return ret;
456}
457
458/*
459 * iwm_hal_send_umac_cmd(): This is a special case for
460 * iwm_hal_send_host_cmd() to send direct UMAC cmd (without
461 * LMAC involved).
462 */
463int iwm_hal_send_umac_cmd(struct iwm_priv *iwm,
464 struct iwm_udma_wifi_cmd *udma_cmd,
465 struct iwm_umac_cmd *umac_cmd,
466 const void *payload, u16 payload_size)
467{
468 return iwm_hal_send_host_cmd(iwm, udma_cmd, umac_cmd, NULL,
469 payload, payload_size);
470}
diff --git a/drivers/net/wireless/iwmc3200wifi/hal.h b/drivers/net/wireless/iwmc3200wifi/hal.h
deleted file mode 100644
index c20936d9b6b7..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/hal.h
+++ /dev/null
@@ -1,237 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef _IWM_HAL_H_
40#define _IWM_HAL_H_
41
42#include "umac.h"
43
44#define GET_VAL8(s, name) ((s >> name##_POS) & name##_SEED)
45#define GET_VAL16(s, name) ((le16_to_cpu(s) >> name##_POS) & name##_SEED)
46#define GET_VAL32(s, name) ((le32_to_cpu(s) >> name##_POS) & name##_SEED)
47
48#define SET_VAL8(s, name, val) \
49do { \
50 s = (s & ~(name##_SEED << name##_POS)) | \
51 ((val & name##_SEED) << name##_POS); \
52} while (0)
53
54#define SET_VAL16(s, name, val) \
55do { \
56 s = cpu_to_le16((le16_to_cpu(s) & ~(name##_SEED << name##_POS)) | \
57 ((val & name##_SEED) << name##_POS)); \
58} while (0)
59
60#define SET_VAL32(s, name, val) \
61do { \
62 s = cpu_to_le32((le32_to_cpu(s) & ~(name##_SEED << name##_POS)) | \
63 ((val & name##_SEED) << name##_POS)); \
64} while (0)
65
66
67#define UDMA_UMAC_INIT { .eop = 1, \
68 .credit_group = 0x4, \
69 .ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD, \
70 .lmac_offset = 0 }
71#define UDMA_LMAC_INIT { .eop = 1, \
72 .credit_group = 0x4, \
73 .ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD, \
74 .lmac_offset = 4 }
75
76
77/* UDMA IN OP CODE -- cmd bits [3:0] */
78#define UDMA_HDI_IN_NW_CMD_OPCODE_POS 0
79#define UDMA_HDI_IN_NW_CMD_OPCODE_SEED 0xF
80
81#define UDMA_IN_OPCODE_GENERAL_RESP 0x0
82#define UDMA_IN_OPCODE_READ_RESP 0x1
83#define UDMA_IN_OPCODE_WRITE_RESP 0x2
84#define UDMA_IN_OPCODE_PERS_WRITE_RESP 0x5
85#define UDMA_IN_OPCODE_PERS_READ_RESP 0x6
86#define UDMA_IN_OPCODE_RD_MDFY_WR_RESP 0x7
87#define UDMA_IN_OPCODE_EP_MNGMT_MSG 0x8
88#define UDMA_IN_OPCODE_CRDT_CHNG_MSG 0x9
89#define UDMA_IN_OPCODE_CNTRL_DATABASE_MSG 0xA
90#define UDMA_IN_OPCODE_SW_MSG 0xB
91#define UDMA_IN_OPCODE_WIFI 0xF
92#define UDMA_IN_OPCODE_WIFI_LMAC 0x1F
93#define UDMA_IN_OPCODE_WIFI_UMAC 0x2F
94
95/* HW API: udma_hdi_nonwifi API (OUT and IN) */
96
97/* iwm_udma_nonwifi_cmd request response -- bits [9:9] */
98#define UDMA_HDI_OUT_NW_CMD_RESP_POS 9
99#define UDMA_HDI_OUT_NW_CMD_RESP_SEED 0x1
100
101/* iwm_udma_nonwifi_cmd handle by HW -- bits [11:11] */
102#define UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW_POS 11
103#define UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW_SEED 0x1
104
105/* iwm_udma_nonwifi_cmd sequence-number -- bits [12:15] */
106#define UDMA_HDI_OUT_NW_CMD_SEQ_NUM_POS 12
107#define UDMA_HDI_OUT_NW_CMD_SEQ_NUM_SEED 0xF
108
109/* UDMA IN Non-WIFI HW sequence number -- bits [12:15] */
110#define UDMA_IN_NW_HW_SEQ_NUM_POS 12
111#define UDMA_IN_NW_HW_SEQ_NUM_SEED 0xF
112
113/* UDMA IN Non-WIFI HW signature -- bits [16:31] */
114#define UDMA_IN_NW_HW_SIG_POS 16
115#define UDMA_IN_NW_HW_SIG_SEED 0xFFFF
116
117/* fixed signature */
118#define UDMA_IN_NW_HW_SIG 0xCBBC
119
120/* UDMA IN Non-WIFI HW block length -- bits [32:35] */
121#define UDMA_IN_NW_HW_LENGTH_SEED 0xF
122#define UDMA_IN_NW_HW_LENGTH_POS 32
123
124/* End of HW API: udma_hdi_nonwifi API (OUT and IN) */
125
126#define IWM_SDIO_FW_MAX_CHUNK_SIZE 2032
127#define IWM_MAX_WIFI_HEADERS_SIZE 32
128#define IWM_MAX_NONWIFI_HEADERS_SIZE 16
129#define IWM_MAX_NONWIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \
130 IWM_MAX_NONWIFI_HEADERS_SIZE)
131#define IWM_MAX_WIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \
132 IWM_MAX_WIFI_HEADERS_SIZE)
133
134#define IWM_HAL_CONCATENATE_BUF_SIZE (32 * 1024)
135
136struct iwm_wifi_cmd_buff {
137 u16 len;
138 u8 *start;
139 u8 hdr[IWM_MAX_WIFI_HEADERS_SIZE];
140 u8 payload[IWM_MAX_WIFI_CMD_BUFF_SIZE];
141};
142
143struct iwm_nonwifi_cmd_buff {
144 u16 len;
145 u8 *start;
146 u8 hdr[IWM_MAX_NONWIFI_HEADERS_SIZE];
147 u8 payload[IWM_MAX_NONWIFI_CMD_BUFF_SIZE];
148};
149
150struct iwm_udma_nonwifi_cmd {
151 u8 opcode;
152 u8 eop;
153 u8 resp;
154 u8 handle_by_hw;
155 __le32 addr;
156 __le32 op1_sz;
157 __le32 op2;
158 __le16 seq_num;
159};
160
161struct iwm_udma_wifi_cmd {
162 __le16 count;
163 u8 eop;
164 u8 credit_group;
165 u8 ra_tid;
166 u8 lmac_offset;
167};
168
169struct iwm_umac_cmd {
170 u8 id;
171 __le16 count;
172 u8 resp;
173 __le16 seq_num;
174 u8 color;
175};
176
177struct iwm_lmac_cmd {
178 u8 id;
179 __le16 count;
180 u8 resp;
181 __le16 seq_num;
182};
183
184struct iwm_nonwifi_cmd {
185 u16 seq_num;
186 bool resp_received;
187 struct list_head pending;
188 struct iwm_udma_nonwifi_cmd udma_cmd;
189 struct iwm_umac_cmd umac_cmd;
190 struct iwm_lmac_cmd lmac_cmd;
191 struct iwm_nonwifi_cmd_buff buf;
192 u32 flags;
193};
194
195struct iwm_wifi_cmd {
196 u16 seq_num;
197 struct list_head pending;
198 struct iwm_udma_wifi_cmd udma_cmd;
199 struct iwm_umac_cmd umac_cmd;
200 struct iwm_lmac_cmd lmac_cmd;
201 struct iwm_wifi_cmd_buff buf;
202 u32 flags;
203};
204
205void iwm_cmd_flush(struct iwm_priv *iwm);
206
207struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm,
208 u16 seq_num);
209struct iwm_nonwifi_cmd *iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm,
210 u8 seq_num, u8 cmd_opcode);
211
212
213int iwm_hal_send_target_cmd(struct iwm_priv *iwm,
214 struct iwm_udma_nonwifi_cmd *ucmd,
215 const void *payload);
216
217int iwm_hal_send_host_cmd(struct iwm_priv *iwm,
218 struct iwm_udma_wifi_cmd *udma_cmd,
219 struct iwm_umac_cmd *umac_cmd,
220 struct iwm_lmac_cmd *lmac_cmd,
221 const void *payload, u16 payload_size);
222
223int iwm_hal_send_umac_cmd(struct iwm_priv *iwm,
224 struct iwm_udma_wifi_cmd *udma_cmd,
225 struct iwm_umac_cmd *umac_cmd,
226 const void *payload, u16 payload_size);
227
228u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm);
229
230void iwm_udma_wifi_hdr_set_eop(struct iwm_priv *iwm, u8 *buf, u8 eop);
231void iwm_build_udma_wifi_hdr(struct iwm_priv *iwm,
232 struct iwm_udma_out_wifi_hdr *hdr,
233 struct iwm_udma_wifi_cmd *cmd);
234void iwm_build_umac_hdr(struct iwm_priv *iwm,
235 struct iwm_umac_fw_cmd_hdr *hdr,
236 struct iwm_umac_cmd *cmd);
237#endif /* _IWM_HAL_H_ */
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h
deleted file mode 100644
index 51d7efa15ae6..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/iwm.h
+++ /dev/null
@@ -1,367 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef __IWM_H__
40#define __IWM_H__
41
42#include <linux/netdevice.h>
43#include <linux/wireless.h>
44#include <net/cfg80211.h>
45
46#include "debug.h"
47#include "hal.h"
48#include "umac.h"
49#include "lmac.h"
50#include "eeprom.h"
51#include "trace.h"
52
53#define IWM_COPYRIGHT "Copyright(c) 2009 Intel Corporation"
54#define IWM_AUTHOR "<ilw@linux.intel.com>"
55
56#define IWM_SRC_LMAC UMAC_HDI_IN_SOURCE_FHRX
57#define IWM_SRC_UDMA UMAC_HDI_IN_SOURCE_UDMA
58#define IWM_SRC_UMAC UMAC_HDI_IN_SOURCE_FW
59#define IWM_SRC_NUM 3
60
61#define IWM_POWER_INDEX_MIN 0
62#define IWM_POWER_INDEX_MAX 5
63#define IWM_POWER_INDEX_DEFAULT 3
64
65struct iwm_conf {
66 u32 sdio_ior_timeout;
67 unsigned long calib_map;
68 unsigned long expected_calib_map;
69 u8 ct_kill_entry;
70 u8 ct_kill_exit;
71 bool reset_on_fatal_err;
72 bool auto_connect;
73 bool wimax_not_present;
74 bool enable_qos;
75 u32 mode;
76
77 u32 power_index;
78 u32 frag_threshold;
79 u32 rts_threshold;
80 bool cts_to_self;
81
82 u32 assoc_timeout;
83 u32 roam_timeout;
84 u32 wireless_mode;
85
86 u8 ibss_band;
87 u8 ibss_channel;
88
89 u8 mac_addr[ETH_ALEN];
90};
91
92enum {
93 COEX_MODE_SA = 1,
94 COEX_MODE_XOR,
95 COEX_MODE_CM,
96 COEX_MODE_MAX,
97};
98
99struct iwm_if_ops;
100struct iwm_wifi_cmd;
101
102struct pool_entry {
103 int id; /* group id */
104 int sid; /* super group id */
105 int min_pages; /* min capacity in pages */
106 int max_pages; /* max capacity in pages */
107 int alloc_pages; /* allocated # of pages. incresed by driver */
108 int total_freed_pages; /* total freed # of pages. incresed by UMAC */
109};
110
111struct spool_entry {
112 int id;
113 int max_pages;
114 int alloc_pages;
115};
116
117struct iwm_tx_credit {
118 spinlock_t lock;
119 int pool_nr;
120 unsigned long full_pools_map; /* bitmap for # of filled tx pools */
121 struct pool_entry pools[IWM_MACS_OUT_GROUPS];
122 struct spool_entry spools[IWM_MACS_OUT_SGROUPS];
123};
124
125struct iwm_notif {
126 struct list_head pending;
127 u32 cmd_id;
128 void *cmd;
129 u8 src;
130 void *buf;
131 unsigned long buf_size;
132};
133
134struct iwm_tid_info {
135 __le16 last_seq_num;
136 bool stopped;
137 struct mutex mutex;
138};
139
140struct iwm_sta_info {
141 u8 addr[ETH_ALEN];
142 bool valid;
143 bool qos;
144 u8 color;
145 struct iwm_tid_info tid_info[IWM_UMAC_TID_NR];
146};
147
148struct iwm_tx_info {
149 u8 sta;
150 u8 color;
151 u8 tid;
152};
153
154struct iwm_rx_info {
155 unsigned long rx_size;
156 unsigned long rx_buf_size;
157};
158
159#define IWM_NUM_KEYS 4
160
161struct iwm_umac_key_hdr {
162 u8 mac[ETH_ALEN];
163 u8 key_idx;
164 u8 multicast; /* BCast encrypt & BCast decrypt of frames FROM mac */
165} __packed;
166
167struct iwm_key {
168 struct iwm_umac_key_hdr hdr;
169 u32 cipher;
170 u8 key[WLAN_MAX_KEY_LEN];
171 u8 seq[IW_ENCODE_SEQ_MAX_SIZE];
172 int key_len;
173 int seq_len;
174};
175
176#define IWM_RX_ID_HASH 0xff
177#define IWM_RX_ID_GET_HASH(id) ((id) % IWM_RX_ID_HASH)
178
179#define IWM_STA_TABLE_NUM 16
180#define IWM_TX_LIST_SIZE 64
181#define IWM_RX_LIST_SIZE 256
182
183#define IWM_SCAN_ID_MAX 0xff
184
185#define IWM_STATUS_READY 0
186#define IWM_STATUS_SCANNING 1
187#define IWM_STATUS_SCAN_ABORTING 2
188#define IWM_STATUS_SME_CONNECTING 3
189#define IWM_STATUS_ASSOCIATED 4
190#define IWM_STATUS_RESETTING 5
191
192struct iwm_tx_queue {
193 int id;
194 struct sk_buff_head queue;
195 struct sk_buff_head stopped_queue;
196 spinlock_t lock;
197 struct workqueue_struct *wq;
198 struct work_struct worker;
199 u8 concat_buf[IWM_HAL_CONCATENATE_BUF_SIZE];
200 int concat_count;
201 u8 *concat_ptr;
202};
203
204/* Queues 0 ~ 3 for AC data, 5 for iPAN */
205#define IWM_TX_QUEUES 5
206#define IWM_TX_DATA_QUEUES 4
207#define IWM_TX_CMD_QUEUE 4
208
209struct iwm_bss_info {
210 struct list_head node;
211 struct cfg80211_bss *cfg_bss;
212 struct iwm_umac_notif_bss_info *bss;
213};
214
215typedef int (*iwm_handler)(struct iwm_priv *priv, u8 *buf,
216 unsigned long buf_size, struct iwm_wifi_cmd *cmd);
217
218#define IWM_WATCHDOG_PERIOD (6 * HZ)
219
220struct iwm_priv {
221 struct wireless_dev *wdev;
222 struct iwm_if_ops *bus_ops;
223
224 struct iwm_conf conf;
225
226 unsigned long status;
227
228 struct list_head pending_notif;
229 wait_queue_head_t notif_queue;
230
231 wait_queue_head_t nonwifi_queue;
232
233 unsigned long calib_done_map;
234 struct {
235 u8 *buf;
236 u32 size;
237 } calib_res[CALIBRATION_CMD_NUM];
238
239 struct iwm_umac_profile *umac_profile;
240 bool umac_profile_active;
241
242 u8 bssid[ETH_ALEN];
243 u8 channel;
244 u16 rate;
245 u32 txpower;
246
247 struct iwm_sta_info sta_table[IWM_STA_TABLE_NUM];
248 struct list_head bss_list;
249
250 void (*nonwifi_rx_handlers[UMAC_HDI_IN_OPCODE_NONWIFI_MAX])
251 (struct iwm_priv *priv, u8 *buf, unsigned long buf_size);
252
253 const iwm_handler *umac_handlers;
254 const iwm_handler *lmac_handlers;
255 DECLARE_BITMAP(lmac_handler_map, LMAC_COMMAND_ID_NUM);
256 DECLARE_BITMAP(umac_handler_map, LMAC_COMMAND_ID_NUM);
257 DECLARE_BITMAP(udma_handler_map, LMAC_COMMAND_ID_NUM);
258
259 struct list_head wifi_pending_cmd;
260 struct list_head nonwifi_pending_cmd;
261 u16 wifi_seq_num;
262 u8 nonwifi_seq_num;
263 spinlock_t cmd_lock;
264
265 u32 core_enabled;
266
267 u8 scan_id;
268 struct cfg80211_scan_request *scan_request;
269
270 struct sk_buff_head rx_list;
271 struct list_head rx_tickets;
272 spinlock_t ticket_lock;
273 struct list_head rx_packets[IWM_RX_ID_HASH];
274 spinlock_t packet_lock[IWM_RX_ID_HASH];
275 struct workqueue_struct *rx_wq;
276 struct work_struct rx_worker;
277
278 struct iwm_tx_credit tx_credit;
279 struct iwm_tx_queue txq[IWM_TX_QUEUES];
280
281 struct iwm_key keys[IWM_NUM_KEYS];
282 s8 default_key;
283
284 DECLARE_BITMAP(wifi_ntfy, WIFI_IF_NTFY_MAX);
285 wait_queue_head_t wifi_ntfy_queue;
286
287 wait_queue_head_t mlme_queue;
288
289 struct iw_statistics wstats;
290 struct delayed_work stats_request;
291 struct delayed_work disconnect;
292 struct delayed_work ct_kill_delay;
293
294 struct iwm_debugfs dbg;
295
296 u8 *eeprom;
297 struct timer_list watchdog;
298 struct work_struct reset_worker;
299 struct work_struct auth_retry_worker;
300 struct mutex mutex;
301
302 u8 *req_ie;
303 int req_ie_len;
304 u8 *resp_ie;
305 int resp_ie_len;
306
307 struct iwm_fw_error_hdr *last_fw_err;
308 char umac_version[8];
309 char lmac_version[8];
310
311 char private[0] __attribute__((__aligned__(NETDEV_ALIGN)));
312};
313
314static inline void *iwm_private(struct iwm_priv *iwm)
315{
316 BUG_ON(!iwm);
317 return &iwm->private;
318}
319
320#define hw_to_iwm(h) (h->iwm)
321#define iwm_to_dev(i) (wiphy_dev(i->wdev->wiphy))
322#define iwm_to_wiphy(i) (i->wdev->wiphy)
323#define wiphy_to_iwm(w) (struct iwm_priv *)(wiphy_priv(w))
324#define iwm_to_wdev(i) (i->wdev)
325#define wdev_to_iwm(w) (struct iwm_priv *)(wdev_priv(w))
326#define iwm_to_ndev(i) (i->wdev->netdev)
327#define ndev_to_iwm(n) (wdev_to_iwm(n->ieee80211_ptr))
328#define skb_to_rx_info(s) ((struct iwm_rx_info *)(s->cb))
329#define skb_to_tx_info(s) ((struct iwm_tx_info *)s->cb)
330
331void *iwm_if_alloc(int sizeof_bus, struct device *dev,
332 struct iwm_if_ops *if_ops);
333void iwm_if_free(struct iwm_priv *iwm);
334int iwm_if_add(struct iwm_priv *iwm);
335void iwm_if_remove(struct iwm_priv *iwm);
336int iwm_mode_to_nl80211_iftype(int mode);
337int iwm_priv_init(struct iwm_priv *iwm);
338void iwm_priv_deinit(struct iwm_priv *iwm);
339void iwm_reset(struct iwm_priv *iwm);
340void iwm_resetting(struct iwm_priv *iwm);
341void iwm_tx_credit_init_pools(struct iwm_priv *iwm,
342 struct iwm_umac_notif_alive *alive);
343int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb);
344int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd,
345 u8 cmd_id, u8 source, u8 *buf, unsigned long buf_size);
346int iwm_notif_handle(struct iwm_priv *iwm, u32 cmd, u8 source, long timeout);
347void iwm_init_default_profile(struct iwm_priv *iwm,
348 struct iwm_umac_profile *profile);
349void iwm_link_on(struct iwm_priv *iwm);
350void iwm_link_off(struct iwm_priv *iwm);
351int iwm_up(struct iwm_priv *iwm);
352int iwm_down(struct iwm_priv *iwm);
353
354/* TX API */
355int iwm_tid_to_queue(u16 tid);
356void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages);
357void iwm_tx_worker(struct work_struct *work);
358int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
359
360/* RX API */
361void iwm_rx_setup_handlers(struct iwm_priv *iwm);
362int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size);
363int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size,
364 struct iwm_wifi_cmd *cmd);
365void iwm_rx_free(struct iwm_priv *iwm);
366
367#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/lmac.h b/drivers/net/wireless/iwmc3200wifi/lmac.h
deleted file mode 100644
index 5ddcdf8c70c0..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/lmac.h
+++ /dev/null
@@ -1,484 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef __IWM_LMAC_H__
40#define __IWM_LMAC_H__
41
42struct iwm_lmac_hdr {
43 u8 id;
44 u8 flags;
45 __le16 seq_num;
46} __packed;
47
48/* LMAC commands */
49#define CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK 0x1
50
51struct iwm_lmac_cal_cfg_elt {
52 __le32 enable; /* 1 means LMAC needs to do something */
53 __le32 start; /* 1 to start calibration, 0 to stop */
54 __le32 send_res; /* 1 for sending back results */
55 __le32 apply_res; /* 1 for applying calibration results to HW */
56 __le32 reserved;
57} __packed;
58
59struct iwm_lmac_cal_cfg_status {
60 struct iwm_lmac_cal_cfg_elt init;
61 struct iwm_lmac_cal_cfg_elt periodic;
62 __le32 flags; /* CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK */
63} __packed;
64
65struct iwm_lmac_cal_cfg_cmd {
66 struct iwm_lmac_cal_cfg_status ucode_cfg;
67 struct iwm_lmac_cal_cfg_status driver_cfg;
68 __le32 reserved;
69} __packed;
70
71struct iwm_lmac_cal_cfg_resp {
72 __le32 status;
73} __packed;
74
75#define IWM_CARD_STATE_SW_HW_ENABLED 0x00
76#define IWM_CARD_STATE_HW_DISABLED 0x01
77#define IWM_CARD_STATE_SW_DISABLED 0x02
78#define IWM_CARD_STATE_CTKILL_DISABLED 0x04
79#define IWM_CARD_STATE_IS_RXON 0x10
80
81struct iwm_lmac_card_state {
82 __le32 flags;
83} __packed;
84
85/**
86 * COEX_PRIORITY_TABLE_CMD
87 *
88 * Priority entry for each state
89 * Will keep two tables, for STA and WIPAN
90 */
91enum {
92 /* UN-ASSOCIATION PART */
93 COEX_UNASSOC_IDLE = 0,
94 COEX_UNASSOC_MANUAL_SCAN,
95 COEX_UNASSOC_AUTO_SCAN,
96
97 /* CALIBRATION */
98 COEX_CALIBRATION,
99 COEX_PERIODIC_CALIBRATION,
100
101 /* CONNECTION */
102 COEX_CONNECTION_ESTAB,
103
104 /* ASSOCIATION PART */
105 COEX_ASSOCIATED_IDLE,
106 COEX_ASSOC_MANUAL_SCAN,
107 COEX_ASSOC_AUTO_SCAN,
108 COEX_ASSOC_ACTIVE_LEVEL,
109
110 /* RF ON/OFF */
111 COEX_RF_ON,
112 COEX_RF_OFF,
113 COEX_STAND_ALONE_DEBUG,
114
115 /* IPNN */
116 COEX_IPAN_ASSOC_LEVEL,
117
118 /* RESERVED */
119 COEX_RSRVD1,
120 COEX_RSRVD2,
121
122 COEX_EVENTS_NUM
123};
124
125#define COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK 0x1
126#define COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK 0x2
127#define COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK 0x4
128
129struct coex_event {
130 u8 req_prio;
131 u8 win_med_prio;
132 u8 reserved;
133 u8 flags;
134} __packed;
135
136#define COEX_FLAGS_STA_TABLE_VALID_MSK 0x1
137#define COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK 0x4
138#define COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK 0x8
139#define COEX_FLAGS_COEX_ENABLE_MSK 0x80
140
141struct iwm_coex_prio_table_cmd {
142 u8 flags;
143 u8 reserved[3];
144 struct coex_event sta_prio[COEX_EVENTS_NUM];
145} __packed;
146
147/* Coexistence definitions
148 *
149 * Constants to fill in the Priorities' Tables
150 * RP - Requested Priority
151 * WP - Win Medium Priority: priority assigned when the contention has been won
152 * FLAGS - Combination of COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK and
153 * COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK
154 */
155
156#define COEX_UNASSOC_IDLE_FLAGS 0
157#define COEX_UNASSOC_MANUAL_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
158 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
159#define COEX_UNASSOC_AUTO_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
160 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
161#define COEX_CALIBRATION_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
162 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
163#define COEX_PERIODIC_CALIBRATION_FLAGS 0
164/* COEX_CONNECTION_ESTAB: we need DELAY_MEDIUM_FREE_NTFY to let WiMAX
165 * disconnect from network. */
166#define COEX_CONNECTION_ESTAB_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
167 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \
168 COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK)
169#define COEX_ASSOCIATED_IDLE_FLAGS 0
170#define COEX_ASSOC_MANUAL_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
171 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
172#define COEX_ASSOC_AUTO_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
173 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
174#define COEX_ASSOC_ACTIVE_LEVEL_FLAGS 0
175#define COEX_RF_ON_FLAGS 0
176#define COEX_RF_OFF_FLAGS 0
177#define COEX_STAND_ALONE_DEBUG_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
178 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
179#define COEX_IPAN_ASSOC_LEVEL_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
180 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \
181 COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK)
182#define COEX_RSRVD1_FLAGS 0
183#define COEX_RSRVD2_FLAGS 0
184/* XOR_RF_ON is the event wrapping all radio ownership. We need
185 * DELAY_MEDIUM_FREE_NTFY to let WiMAX disconnect from network. */
186#define COEX_XOR_RF_ON_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
187 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \
188 COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK)
189
190/* CT kill config command */
191struct iwm_ct_kill_cfg_cmd {
192 u32 exit_threshold;
193 u32 reserved;
194 u32 entry_threshold;
195} __packed;
196
197
198/* LMAC OP CODES */
199#define REPLY_PAD 0x0
200#define REPLY_ALIVE 0x1
201#define REPLY_ERROR 0x2
202#define REPLY_ECHO 0x3
203#define REPLY_HALT 0x6
204
205/* RXON state commands */
206#define REPLY_RX_ON 0x10
207#define REPLY_RX_ON_ASSOC 0x11
208#define REPLY_RX_OFF 0x12
209#define REPLY_QOS_PARAM 0x13
210#define REPLY_RX_ON_TIMING 0x14
211#define REPLY_INTERNAL_QOS_PARAM 0x15
212#define REPLY_RX_INT_TIMEOUT_CNFG 0x16
213#define REPLY_NULL 0x17
214
215/* Multi-Station support */
216#define REPLY_ADD_STA 0x18
217#define REPLY_REMOVE_STA 0x19
218#define REPLY_RESET_ALL_STA 0x1a
219
220/* RX, TX */
221#define REPLY_ALM_RX 0x1b
222#define REPLY_TX 0x1c
223#define REPLY_TXFIFO_FLUSH 0x1e
224
225/* MISC commands */
226#define REPLY_MGMT_MCAST_KEY 0x1f
227#define REPLY_WEPKEY 0x20
228#define REPLY_INIT_IV 0x21
229#define REPLY_WRITE_MIB 0x22
230#define REPLY_READ_MIB 0x23
231#define REPLY_RADIO_FE 0x24
232#define REPLY_TXFIFO_CFG 0x25
233#define REPLY_WRITE_READ 0x26
234#define REPLY_INSTALL_SEC_KEY 0x27
235
236
237#define REPLY_RATE_SCALE 0x47
238#define REPLY_LEDS_CMD 0x48
239#define REPLY_TX_LINK_QUALITY_CMD 0x4e
240#define REPLY_ANA_MIB_OVERRIDE_CMD 0x4f
241#define REPLY_WRITE2REG_CMD 0x50
242
243/* winfi-wifi coexistence */
244#define COEX_PRIORITY_TABLE_CMD 0x5a
245#define COEX_MEDIUM_NOTIFICATION 0x5b
246#define COEX_EVENT_CMD 0x5c
247
248/* more Protocol and Protocol-test commands */
249#define REPLY_MAX_SLEEP_TIME_CMD 0x61
250#define CALIBRATION_CFG_CMD 0x65
251#define CALIBRATION_RES_NOTIFICATION 0x66
252#define CALIBRATION_COMPLETE_NOTIFICATION 0x67
253
254/* Measurements */
255#define REPLY_QUIET_CMD 0x71
256#define REPLY_CHANNEL_SWITCH 0x72
257#define CHANNEL_SWITCH_NOTIFICATION 0x73
258
259#define REPLY_SPECTRUM_MEASUREMENT_CMD 0x74
260#define SPECTRUM_MEASURE_NOTIFICATION 0x75
261#define REPLY_MEASUREMENT_ABORT_CMD 0x76
262
263/* Power Management */
264#define POWER_TABLE_CMD 0x77
265#define SAVE_RESTORE_ADDRESS_CMD 0x78
266#define REPLY_WATERMARK_CMD 0x79
267#define PM_DEBUG_STATISTIC_NOTIFIC 0x7B
268#define PD_FLUSH_N_NOTIFICATION 0x7C
269
270/* Scan commands and notifications */
271#define REPLY_SCAN_REQUEST_CMD 0x80
272#define REPLY_SCAN_ABORT_CMD 0x81
273#define SCAN_START_NOTIFICATION 0x82
274#define SCAN_RESULTS_NOTIFICATION 0x83
275#define SCAN_COMPLETE_NOTIFICATION 0x84
276
277/* Continuous TX commands */
278#define REPLY_CONT_TX_CMD 0x85
279#define END_OF_CONT_TX_NOTIFICATION 0x86
280
281/* Timer/Eeprom commands */
282#define TIMER_CMD 0x87
283#define EEPROM_WRITE_CMD 0x88
284
285/* PAPD commands */
286#define FEEDBACK_REQUEST_NOTIFICATION 0x8b
287#define REPLY_CW_CMD 0x8c
288
289/* IBSS/AP commands Continue */
290#define BEACON_NOTIFICATION 0x90
291#define REPLY_TX_BEACON 0x91
292#define REPLY_REQUEST_ATIM 0x93
293#define WHO_IS_AWAKE_NOTIFICATION 0x94
294#define TX_PWR_DBM_LIMIT_CMD 0x95
295#define QUIET_NOTIFICATION 0x96
296#define TX_PWR_TABLE_CMD 0x97
297#define TX_ANT_CONFIGURATION_CMD 0x98
298#define MEASURE_ABORT_NOTIFICATION 0x99
299#define REPLY_CALIBRATION_TUNE 0x9a
300
301/* bt config command */
302#define REPLY_BT_CONFIG 0x9b
303#define REPLY_STATISTICS_CMD 0x9c
304#define STATISTICS_NOTIFICATION 0x9d
305
306/* RF-KILL commands and notifications */
307#define REPLY_CARD_STATE_CMD 0xa0
308#define CARD_STATE_NOTIFICATION 0xa1
309
310/* Missed beacons notification */
311#define MISSED_BEACONS_NOTIFICATION 0xa2
312#define MISSED_BEACONS_NOTIFICATION_TH_CMD 0xa3
313
314#define REPLY_CT_KILL_CONFIG_CMD 0xa4
315
316/* HD commands and notifications */
317#define REPLY_HD_PARAMS_CMD 0xa6
318#define HD_PARAMS_NOTIFICATION 0xa7
319#define SENSITIVITY_CMD 0xa8
320#define U_APSD_PARAMS_CMD 0xa9
321#define NOISY_PLATFORM_CMD 0xaa
322#define ILLEGAL_CMD 0xac
323#define REPLY_PHY_CALIBRATION_CMD 0xb0
324#define REPLAY_RX_GAIN_CALIB_CMD 0xb1
325
326/* WiPAN commands */
327#define REPLY_WIPAN_PARAMS_CMD 0xb2
328#define REPLY_WIPAN_RX_ON_CMD 0xb3
329#define REPLY_WIPAN_RX_ON_TIMING 0xb4
330#define REPLY_WIPAN_TX_PWR_TABLE_CMD 0xb5
331#define REPLY_WIPAN_RXON_ASSOC_CMD 0xb6
332#define REPLY_WIPAN_QOS_PARAM 0xb7
333#define WIPAN_REPLY_WEPKEY 0xb8
334
335/* BeamForming commands */
336#define BEAMFORMER_CFG_CMD 0xba
337#define BEAMFORMEE_NOTIFICATION 0xbb
338
339/* TGn new Commands */
340#define REPLY_RX_PHY_CMD 0xc0
341#define REPLY_RX_MPDU_CMD 0xc1
342#define REPLY_MULTICAST_HASH 0xc2
343#define REPLY_KDR_RX 0xc3
344#define REPLY_RX_DSP_EXT_INFO 0xc4
345#define REPLY_COMPRESSED_BA 0xc5
346
347/* PNC commands */
348#define PNC_CONFIG_CMD 0xc8
349#define PNC_UPDATE_TABLE_CMD 0xc9
350#define XVT_GENERAL_CTRL_CMD 0xca
351#define REPLY_LEGACY_RADIO_FE 0xdd
352
353/* WoWLAN commands */
354#define WOWLAN_PATTERNS 0xe0
355#define WOWLAN_WAKEUP_FILTER 0xe1
356#define WOWLAN_TSC_RSC_PARAM 0xe2
357#define WOWLAN_TKIP_PARAM 0xe3
358#define WOWLAN_KEK_KCK_MATERIAL 0xe4
359#define WOWLAN_GET_STATUSES 0xe5
360#define WOWLAN_TX_POWER_PER_DB 0xe6
361#define REPLY_WOWLAN_GET_STATUSES WOWLAN_GET_STATUSES
362
363#define REPLY_DEBUG_CMD 0xf0
364#define REPLY_DSP_DEBUG_CMD 0xf1
365#define REPLY_DEBUG_MONITOR_CMD 0xf2
366#define REPLY_DEBUG_XVT_CMD 0xf3
367#define REPLY_DEBUG_DC_CALIB 0xf4
368#define REPLY_DYNAMIC_BP 0xf5
369
370/* General purpose Commands */
371#define REPLY_GP1_CMD 0xfa
372#define REPLY_GP2_CMD 0xfb
373#define REPLY_GP3_CMD 0xfc
374#define REPLY_GP4_CMD 0xfd
375#define REPLY_REPLAY_WRAPPER 0xfe
376#define REPLY_FRAME_DURATION_CALC_CMD 0xff
377
378#define LMAC_COMMAND_ID_MAX 0xff
379#define LMAC_COMMAND_ID_NUM (LMAC_COMMAND_ID_MAX + 1)
380
381
382/* Calibration */
383
384enum {
385 PHY_CALIBRATE_DC_CMD = 0,
386 PHY_CALIBRATE_LO_CMD = 1,
387 PHY_CALIBRATE_RX_BB_CMD = 2,
388 PHY_CALIBRATE_TX_IQ_CMD = 3,
389 PHY_CALIBRATE_RX_IQ_CMD = 4,
390 PHY_CALIBRATION_NOISE_CMD = 5,
391 PHY_CALIBRATE_AGC_TABLE_CMD = 6,
392 PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 7,
393 PHY_CALIBRATE_OPCODES_NUM,
394 SHILOH_PHY_CALIBRATE_DC_CMD = 8,
395 SHILOH_PHY_CALIBRATE_LO_CMD = 9,
396 SHILOH_PHY_CALIBRATE_RX_BB_CMD = 10,
397 SHILOH_PHY_CALIBRATE_TX_IQ_CMD = 11,
398 SHILOH_PHY_CALIBRATE_RX_IQ_CMD = 12,
399 SHILOH_PHY_CALIBRATION_NOISE_CMD = 13,
400 SHILOH_PHY_CALIBRATE_AGC_TABLE_CMD = 14,
401 SHILOH_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
402 SHILOH_PHY_CALIBRATE_BASE_BAND_CMD = 16,
403 SHILOH_PHY_CALIBRATE_TXIQ_PERIODIC_CMD = 17,
404 CALIBRATION_CMD_NUM,
405};
406
407enum {
408 CALIB_CFG_RX_BB_IDX = 0,
409 CALIB_CFG_DC_IDX = 1,
410 CALIB_CFG_LO_IDX = 2,
411 CALIB_CFG_TX_IQ_IDX = 3,
412 CALIB_CFG_RX_IQ_IDX = 4,
413 CALIB_CFG_NOISE_IDX = 5,
414 CALIB_CFG_CRYSTAL_IDX = 6,
415 CALIB_CFG_TEMPERATURE_IDX = 7,
416 CALIB_CFG_PAPD_IDX = 8,
417 CALIB_CFG_LAST_IDX = CALIB_CFG_PAPD_IDX,
418 CALIB_CFG_MODULE_NUM,
419};
420
421#define IWM_CALIB_MAP_INIT_MSK 0xFFFF
422#define IWM_CALIB_MAP_PER_LMAC(m) ((m & 0xFF0000) >> 16)
423#define IWM_CALIB_MAP_PER_UMAC(m) ((m & 0xFF000000) >> 24)
424#define IWM_CALIB_OPCODE_TO_INDEX(op) (op - PHY_CALIBRATE_OPCODES_NUM)
425
426struct iwm_lmac_calib_hdr {
427 u8 opcode;
428 u8 first_grp;
429 u8 grp_num;
430 u8 all_data_valid;
431} __packed;
432
433#define IWM_LMAC_CALIB_FREQ_GROUPS_NR 7
434#define IWM_CALIB_FREQ_GROUPS_NR 5
435#define IWM_CALIB_DC_MODES_NR 12
436
437struct iwm_calib_rxiq_entry {
438 u16 ptam_postdist_ars;
439 u16 ptam_postdist_arc;
440} __packed;
441
442struct iwm_calib_rxiq_group {
443 struct iwm_calib_rxiq_entry mode[IWM_CALIB_DC_MODES_NR];
444} __packed;
445
446struct iwm_lmac_calib_rxiq {
447 struct iwm_calib_rxiq_group group[IWM_LMAC_CALIB_FREQ_GROUPS_NR];
448} __packed;
449
450struct iwm_calib_rxiq {
451 struct iwm_lmac_calib_hdr hdr;
452 struct iwm_calib_rxiq_group group[IWM_CALIB_FREQ_GROUPS_NR];
453} __packed;
454
455#define LMAC_STA_ID_SEED 0x0f
456#define LMAC_STA_ID_POS 0
457
458#define LMAC_STA_COLOR_SEED 0x7
459#define LMAC_STA_COLOR_POS 4
460
461struct iwm_lmac_power_report {
462 u8 pa_status;
463 u8 pa_integ_res_A[3];
464 u8 pa_integ_res_B[3];
465 u8 pa_integ_res_C[3];
466} __packed;
467
468struct iwm_lmac_tx_resp {
469 u8 frame_cnt; /* 1-no aggregation, greater then 1 - aggregation */
470 u8 bt_kill_cnt;
471 __le16 retry_cnt;
472 __le32 initial_tx_rate;
473 __le16 wireless_media_time;
474 struct iwm_lmac_power_report power_report;
475 __le32 tfd_info;
476 __le16 seq_ctl;
477 __le16 byte_cnt;
478 u8 tlc_rate_info;
479 u8 ra_tid;
480 __le16 frame_ctl;
481 __le32 status;
482} __packed;
483
484#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c
deleted file mode 100644
index 1f868b166d10..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/main.c
+++ /dev/null
@@ -1,847 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#include <linux/kernel.h>
40#include <linux/netdevice.h>
41#include <linux/sched.h>
42#include <linux/ieee80211.h>
43#include <linux/wireless.h>
44#include <linux/slab.h>
45#include <linux/moduleparam.h>
46
47#include "iwm.h"
48#include "debug.h"
49#include "bus.h"
50#include "umac.h"
51#include "commands.h"
52#include "hal.h"
53#include "fw.h"
54#include "rx.h"
55
56static struct iwm_conf def_iwm_conf = {
57
58 .sdio_ior_timeout = 5000,
59 .calib_map = BIT(CALIB_CFG_DC_IDX) |
60 BIT(CALIB_CFG_LO_IDX) |
61 BIT(CALIB_CFG_TX_IQ_IDX) |
62 BIT(CALIB_CFG_RX_IQ_IDX) |
63 BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD),
64 .expected_calib_map = BIT(PHY_CALIBRATE_DC_CMD) |
65 BIT(PHY_CALIBRATE_LO_CMD) |
66 BIT(PHY_CALIBRATE_TX_IQ_CMD) |
67 BIT(PHY_CALIBRATE_RX_IQ_CMD) |
68 BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD),
69 .ct_kill_entry = 110,
70 .ct_kill_exit = 110,
71 .reset_on_fatal_err = 1,
72 .auto_connect = 1,
73 .enable_qos = 1,
74 .mode = UMAC_MODE_BSS,
75
76 /* UMAC configuration */
77 .power_index = 0,
78 .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD,
79 .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD,
80 .cts_to_self = 0,
81
82 .assoc_timeout = 2,
83 .roam_timeout = 10,
84 .wireless_mode = WIRELESS_MODE_11A | WIRELESS_MODE_11G |
85 WIRELESS_MODE_11N,
86
87 /* IBSS */
88 .ibss_band = UMAC_BAND_2GHZ,
89 .ibss_channel = 1,
90
91 .mac_addr = {0x00, 0x02, 0xb3, 0x01, 0x02, 0x03},
92};
93
94static bool modparam_reset;
95module_param_named(reset, modparam_reset, bool, 0644);
96MODULE_PARM_DESC(reset, "reset on firmware errors (default 0 [not reset])");
97
98static bool modparam_wimax_enable = true;
99module_param_named(wimax_enable, modparam_wimax_enable, bool, 0644);
100MODULE_PARM_DESC(wimax_enable, "Enable wimax core (default 1 [wimax enabled])");
101
102int iwm_mode_to_nl80211_iftype(int mode)
103{
104 switch (mode) {
105 case UMAC_MODE_BSS:
106 return NL80211_IFTYPE_STATION;
107 case UMAC_MODE_IBSS:
108 return NL80211_IFTYPE_ADHOC;
109 default:
110 return NL80211_IFTYPE_UNSPECIFIED;
111 }
112
113 return 0;
114}
115
116static void iwm_statistics_request(struct work_struct *work)
117{
118 struct iwm_priv *iwm =
119 container_of(work, struct iwm_priv, stats_request.work);
120
121 iwm_send_umac_stats_req(iwm, 0);
122}
123
124static void iwm_disconnect_work(struct work_struct *work)
125{
126 struct iwm_priv *iwm =
127 container_of(work, struct iwm_priv, disconnect.work);
128
129 if (iwm->umac_profile_active)
130 iwm_invalidate_mlme_profile(iwm);
131
132 clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
133 iwm->umac_profile_active = false;
134 memset(iwm->bssid, 0, ETH_ALEN);
135 iwm->channel = 0;
136
137 iwm_link_off(iwm);
138
139 wake_up_interruptible(&iwm->mlme_queue);
140
141 cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, GFP_KERNEL);
142}
143
144static void iwm_ct_kill_work(struct work_struct *work)
145{
146 struct iwm_priv *iwm =
147 container_of(work, struct iwm_priv, ct_kill_delay.work);
148 struct wiphy *wiphy = iwm_to_wiphy(iwm);
149
150 IWM_INFO(iwm, "CT kill delay timeout\n");
151
152 wiphy_rfkill_set_hw_state(wiphy, false);
153}
154
155static int __iwm_up(struct iwm_priv *iwm);
156static int __iwm_down(struct iwm_priv *iwm);
157
158static void iwm_reset_worker(struct work_struct *work)
159{
160 struct iwm_priv *iwm;
161 struct iwm_umac_profile *profile = NULL;
162 int uninitialized_var(ret), retry = 0;
163
164 iwm = container_of(work, struct iwm_priv, reset_worker);
165
166 /*
167 * XXX: The iwm->mutex is introduced purely for this reset work,
168 * because the other users for iwm_up and iwm_down are only netdev
169 * ndo_open and ndo_stop which are already protected by rtnl.
170 * Please remove iwm->mutex together if iwm_reset_worker() is not
171 * required in the future.
172 */
173 if (!mutex_trylock(&iwm->mutex)) {
174 IWM_WARN(iwm, "We are in the middle of interface bringing "
175 "UP/DOWN. Skip driver resetting.\n");
176 return;
177 }
178
179 if (iwm->umac_profile_active) {
180 profile = kmalloc(sizeof(struct iwm_umac_profile), GFP_KERNEL);
181 if (profile)
182 memcpy(profile, iwm->umac_profile, sizeof(*profile));
183 else
184 IWM_ERR(iwm, "Couldn't alloc memory for profile\n");
185 }
186
187 __iwm_down(iwm);
188
189 while (retry++ < 3) {
190 ret = __iwm_up(iwm);
191 if (!ret)
192 break;
193
194 schedule_timeout_uninterruptible(10 * HZ);
195 }
196
197 if (ret) {
198 IWM_WARN(iwm, "iwm_up() failed: %d\n", ret);
199
200 kfree(profile);
201 goto out;
202 }
203
204 if (profile) {
205 IWM_DBG_MLME(iwm, DBG, "Resend UMAC profile\n");
206 memcpy(iwm->umac_profile, profile, sizeof(*profile));
207 iwm_send_mlme_profile(iwm);
208 kfree(profile);
209 } else
210 clear_bit(IWM_STATUS_RESETTING, &iwm->status);
211
212 out:
213 mutex_unlock(&iwm->mutex);
214}
215
216static void iwm_auth_retry_worker(struct work_struct *work)
217{
218 struct iwm_priv *iwm;
219 int i, ret;
220
221 iwm = container_of(work, struct iwm_priv, auth_retry_worker);
222 if (iwm->umac_profile_active) {
223 ret = iwm_invalidate_mlme_profile(iwm);
224 if (ret < 0)
225 return;
226 }
227
228 iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
229
230 ret = iwm_send_mlme_profile(iwm);
231 if (ret < 0)
232 return;
233
234 for (i = 0; i < IWM_NUM_KEYS; i++)
235 if (iwm->keys[i].key_len)
236 iwm_set_key(iwm, 0, &iwm->keys[i]);
237
238 iwm_set_tx_key(iwm, iwm->default_key);
239}
240
241
242
243static void iwm_watchdog(unsigned long data)
244{
245 struct iwm_priv *iwm = (struct iwm_priv *)data;
246
247 IWM_WARN(iwm, "Watchdog expired: UMAC stalls!\n");
248
249 if (modparam_reset)
250 iwm_resetting(iwm);
251}
252
253int iwm_priv_init(struct iwm_priv *iwm)
254{
255 int i, j;
256 char name[32];
257
258 iwm->status = 0;
259 INIT_LIST_HEAD(&iwm->pending_notif);
260 init_waitqueue_head(&iwm->notif_queue);
261 init_waitqueue_head(&iwm->nonwifi_queue);
262 init_waitqueue_head(&iwm->wifi_ntfy_queue);
263 init_waitqueue_head(&iwm->mlme_queue);
264 memcpy(&iwm->conf, &def_iwm_conf, sizeof(struct iwm_conf));
265 spin_lock_init(&iwm->tx_credit.lock);
266 INIT_LIST_HEAD(&iwm->wifi_pending_cmd);
267 INIT_LIST_HEAD(&iwm->nonwifi_pending_cmd);
268 iwm->wifi_seq_num = UMAC_WIFI_SEQ_NUM_BASE;
269 iwm->nonwifi_seq_num = UMAC_NONWIFI_SEQ_NUM_BASE;
270 spin_lock_init(&iwm->cmd_lock);
271 iwm->scan_id = 1;
272 INIT_DELAYED_WORK(&iwm->stats_request, iwm_statistics_request);
273 INIT_DELAYED_WORK(&iwm->disconnect, iwm_disconnect_work);
274 INIT_DELAYED_WORK(&iwm->ct_kill_delay, iwm_ct_kill_work);
275 INIT_WORK(&iwm->reset_worker, iwm_reset_worker);
276 INIT_WORK(&iwm->auth_retry_worker, iwm_auth_retry_worker);
277 INIT_LIST_HEAD(&iwm->bss_list);
278
279 skb_queue_head_init(&iwm->rx_list);
280 INIT_LIST_HEAD(&iwm->rx_tickets);
281 spin_lock_init(&iwm->ticket_lock);
282 for (i = 0; i < IWM_RX_ID_HASH; i++) {
283 INIT_LIST_HEAD(&iwm->rx_packets[i]);
284 spin_lock_init(&iwm->packet_lock[i]);
285 }
286
287 INIT_WORK(&iwm->rx_worker, iwm_rx_worker);
288
289 iwm->rx_wq = create_singlethread_workqueue(KBUILD_MODNAME "_rx");
290 if (!iwm->rx_wq)
291 return -EAGAIN;
292
293 for (i = 0; i < IWM_TX_QUEUES; i++) {
294 INIT_WORK(&iwm->txq[i].worker, iwm_tx_worker);
295 snprintf(name, 32, KBUILD_MODNAME "_tx_%d", i);
296 iwm->txq[i].id = i;
297 iwm->txq[i].wq = create_singlethread_workqueue(name);
298 if (!iwm->txq[i].wq)
299 return -EAGAIN;
300
301 skb_queue_head_init(&iwm->txq[i].queue);
302 skb_queue_head_init(&iwm->txq[i].stopped_queue);
303 spin_lock_init(&iwm->txq[i].lock);
304 }
305
306 for (i = 0; i < IWM_NUM_KEYS; i++)
307 memset(&iwm->keys[i], 0, sizeof(struct iwm_key));
308
309 iwm->default_key = -1;
310
311 for (i = 0; i < IWM_STA_TABLE_NUM; i++)
312 for (j = 0; j < IWM_UMAC_TID_NR; j++) {
313 mutex_init(&iwm->sta_table[i].tid_info[j].mutex);
314 iwm->sta_table[i].tid_info[j].stopped = false;
315 }
316
317 init_timer(&iwm->watchdog);
318 iwm->watchdog.function = iwm_watchdog;
319 iwm->watchdog.data = (unsigned long)iwm;
320 mutex_init(&iwm->mutex);
321
322 iwm->last_fw_err = kzalloc(sizeof(struct iwm_fw_error_hdr),
323 GFP_KERNEL);
324 if (iwm->last_fw_err == NULL)
325 return -ENOMEM;
326
327 return 0;
328}
329
330void iwm_priv_deinit(struct iwm_priv *iwm)
331{
332 int i;
333
334 for (i = 0; i < IWM_TX_QUEUES; i++)
335 destroy_workqueue(iwm->txq[i].wq);
336
337 destroy_workqueue(iwm->rx_wq);
338 kfree(iwm->last_fw_err);
339}
340
341/*
342 * We reset all the structures, and we reset the UMAC.
343 * After calling this routine, you're expected to reload
344 * the firmware.
345 */
346void iwm_reset(struct iwm_priv *iwm)
347{
348 struct iwm_notif *notif, *next;
349
350 if (test_bit(IWM_STATUS_READY, &iwm->status))
351 iwm_target_reset(iwm);
352
353 if (test_bit(IWM_STATUS_RESETTING, &iwm->status)) {
354 iwm->status = 0;
355 set_bit(IWM_STATUS_RESETTING, &iwm->status);
356 } else
357 iwm->status = 0;
358 iwm->scan_id = 1;
359
360 list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) {
361 list_del(&notif->pending);
362 kfree(notif->buf);
363 kfree(notif);
364 }
365
366 iwm_cmd_flush(iwm);
367
368 flush_workqueue(iwm->rx_wq);
369
370 iwm_link_off(iwm);
371}
372
373void iwm_resetting(struct iwm_priv *iwm)
374{
375 set_bit(IWM_STATUS_RESETTING, &iwm->status);
376
377 schedule_work(&iwm->reset_worker);
378}
379
380/*
381 * Notification code:
382 *
383 * We're faced with the following issue: Any host command can
384 * have an answer or not, and if there's an answer to expect,
385 * it can be treated synchronously or asynchronously.
386 * To work around the synchronous answer case, we implemented
387 * our notification mechanism.
388 * When a code path needs to wait for a command response
389 * synchronously, it calls notif_handle(), which waits for the
390 * right notification to show up, and then process it. Before
391 * starting to wait, it registered as a waiter for this specific
392 * answer (by toggling a bit in on of the handler_map), so that
393 * the rx code knows that it needs to send a notification to the
394 * waiting processes. It does so by calling iwm_notif_send(),
395 * which adds the notification to the pending notifications list,
396 * and then wakes the waiting processes up.
397 */
398int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd,
399 u8 cmd_id, u8 source, u8 *buf, unsigned long buf_size)
400{
401 struct iwm_notif *notif;
402
403 notif = kzalloc(sizeof(struct iwm_notif), GFP_KERNEL);
404 if (!notif) {
405 IWM_ERR(iwm, "Couldn't alloc memory for notification\n");
406 return -ENOMEM;
407 }
408
409 INIT_LIST_HEAD(&notif->pending);
410 notif->cmd = cmd;
411 notif->cmd_id = cmd_id;
412 notif->src = source;
413 notif->buf = kzalloc(buf_size, GFP_KERNEL);
414 if (!notif->buf) {
415 IWM_ERR(iwm, "Couldn't alloc notification buffer\n");
416 kfree(notif);
417 return -ENOMEM;
418 }
419 notif->buf_size = buf_size;
420 memcpy(notif->buf, buf, buf_size);
421 list_add_tail(&notif->pending, &iwm->pending_notif);
422
423 wake_up_interruptible(&iwm->notif_queue);
424
425 return 0;
426}
427
428static struct iwm_notif *iwm_notif_find(struct iwm_priv *iwm, u32 cmd,
429 u8 source)
430{
431 struct iwm_notif *notif;
432
433 list_for_each_entry(notif, &iwm->pending_notif, pending) {
434 if ((notif->cmd_id == cmd) && (notif->src == source)) {
435 list_del(&notif->pending);
436 return notif;
437 }
438 }
439
440 return NULL;
441}
442
443static struct iwm_notif *iwm_notif_wait(struct iwm_priv *iwm, u32 cmd,
444 u8 source, long timeout)
445{
446 int ret;
447 struct iwm_notif *notif;
448 unsigned long *map = NULL;
449
450 switch (source) {
451 case IWM_SRC_LMAC:
452 map = &iwm->lmac_handler_map[0];
453 break;
454 case IWM_SRC_UMAC:
455 map = &iwm->umac_handler_map[0];
456 break;
457 case IWM_SRC_UDMA:
458 map = &iwm->udma_handler_map[0];
459 break;
460 }
461
462 set_bit(cmd, map);
463
464 ret = wait_event_interruptible_timeout(iwm->notif_queue,
465 ((notif = iwm_notif_find(iwm, cmd, source)) != NULL),
466 timeout);
467 clear_bit(cmd, map);
468
469 if (!ret)
470 return NULL;
471
472 return notif;
473}
474
475int iwm_notif_handle(struct iwm_priv *iwm, u32 cmd, u8 source, long timeout)
476{
477 int ret;
478 struct iwm_notif *notif;
479
480 notif = iwm_notif_wait(iwm, cmd, source, timeout);
481 if (!notif)
482 return -ETIME;
483
484 ret = iwm_rx_handle_resp(iwm, notif->buf, notif->buf_size, notif->cmd);
485 kfree(notif->buf);
486 kfree(notif);
487
488 return ret;
489}
490
491static int iwm_config_boot_params(struct iwm_priv *iwm)
492{
493 struct iwm_udma_nonwifi_cmd target_cmd;
494 int ret;
495
496 /* check Wimax is off and config debug monitor */
497 if (!modparam_wimax_enable) {
498 u32 data1 = 0x1f;
499 u32 addr1 = 0x606BE258;
500
501 u32 data2_set = 0x0;
502 u32 data2_clr = 0x1;
503 u32 addr2 = 0x606BE100;
504
505 u32 data3 = 0x1;
506 u32 addr3 = 0x606BEC00;
507
508 target_cmd.resp = 0;
509 target_cmd.handle_by_hw = 0;
510 target_cmd.eop = 1;
511
512 target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE;
513 target_cmd.addr = cpu_to_le32(addr1);
514 target_cmd.op1_sz = cpu_to_le32(sizeof(u32));
515 target_cmd.op2 = 0;
516
517 ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data1);
518 if (ret < 0) {
519 IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n");
520 return ret;
521 }
522
523 target_cmd.opcode = UMAC_HDI_OUT_OPCODE_READ_MODIFY_WRITE;
524 target_cmd.addr = cpu_to_le32(addr2);
525 target_cmd.op1_sz = cpu_to_le32(data2_set);
526 target_cmd.op2 = cpu_to_le32(data2_clr);
527
528 ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data1);
529 if (ret < 0) {
530 IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n");
531 return ret;
532 }
533
534 target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE;
535 target_cmd.addr = cpu_to_le32(addr3);
536 target_cmd.op1_sz = cpu_to_le32(sizeof(u32));
537 target_cmd.op2 = 0;
538
539 ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data3);
540 if (ret < 0) {
541 IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n");
542 return ret;
543 }
544 }
545
546 return 0;
547}
548
549void iwm_init_default_profile(struct iwm_priv *iwm,
550 struct iwm_umac_profile *profile)
551{
552 memset(profile, 0, sizeof(struct iwm_umac_profile));
553
554 profile->sec.auth_type = UMAC_AUTH_TYPE_OPEN;
555 profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
556 profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_NONE;
557 profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_NONE;
558
559 if (iwm->conf.enable_qos)
560 profile->flags |= cpu_to_le16(UMAC_PROFILE_QOS_ALLOWED);
561
562 profile->wireless_mode = iwm->conf.wireless_mode;
563 profile->mode = cpu_to_le32(iwm->conf.mode);
564
565 profile->ibss.atim = 0;
566 profile->ibss.beacon_interval = 100;
567 profile->ibss.join_only = 0;
568 profile->ibss.band = iwm->conf.ibss_band;
569 profile->ibss.channel = iwm->conf.ibss_channel;
570}
571
572void iwm_link_on(struct iwm_priv *iwm)
573{
574 netif_carrier_on(iwm_to_ndev(iwm));
575 netif_tx_wake_all_queues(iwm_to_ndev(iwm));
576
577 iwm_send_umac_stats_req(iwm, 0);
578}
579
580void iwm_link_off(struct iwm_priv *iwm)
581{
582 struct iw_statistics *wstats = &iwm->wstats;
583 int i;
584
585 netif_tx_stop_all_queues(iwm_to_ndev(iwm));
586 netif_carrier_off(iwm_to_ndev(iwm));
587
588 for (i = 0; i < IWM_TX_QUEUES; i++) {
589 skb_queue_purge(&iwm->txq[i].queue);
590 skb_queue_purge(&iwm->txq[i].stopped_queue);
591
592 iwm->txq[i].concat_count = 0;
593 iwm->txq[i].concat_ptr = iwm->txq[i].concat_buf;
594
595 flush_workqueue(iwm->txq[i].wq);
596 }
597
598 iwm_rx_free(iwm);
599
600 cancel_delayed_work_sync(&iwm->stats_request);
601 memset(wstats, 0, sizeof(struct iw_statistics));
602 wstats->qual.updated = IW_QUAL_ALL_INVALID;
603
604 kfree(iwm->req_ie);
605 iwm->req_ie = NULL;
606 iwm->req_ie_len = 0;
607 kfree(iwm->resp_ie);
608 iwm->resp_ie = NULL;
609 iwm->resp_ie_len = 0;
610
611 del_timer_sync(&iwm->watchdog);
612}
613
614static void iwm_bss_list_clean(struct iwm_priv *iwm)
615{
616 struct iwm_bss_info *bss, *next;
617
618 list_for_each_entry_safe(bss, next, &iwm->bss_list, node) {
619 list_del(&bss->node);
620 kfree(bss->bss);
621 kfree(bss);
622 }
623}
624
625static int iwm_channels_init(struct iwm_priv *iwm)
626{
627 int ret;
628
629 ret = iwm_send_umac_channel_list(iwm);
630 if (ret) {
631 IWM_ERR(iwm, "Send channel list failed\n");
632 return ret;
633 }
634
635 ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST,
636 IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
637 if (ret) {
638 IWM_ERR(iwm, "Didn't get a channel list notification\n");
639 return ret;
640 }
641
642 return 0;
643}
644
645static int __iwm_up(struct iwm_priv *iwm)
646{
647 int ret;
648 struct iwm_notif *notif_reboot, *notif_ack = NULL;
649 struct wiphy *wiphy = iwm_to_wiphy(iwm);
650 u32 wireless_mode;
651
652 ret = iwm_bus_enable(iwm);
653 if (ret) {
654 IWM_ERR(iwm, "Couldn't enable function\n");
655 return ret;
656 }
657
658 iwm_rx_setup_handlers(iwm);
659
660 /* Wait for initial BARKER_REBOOT from hardware */
661 notif_reboot = iwm_notif_wait(iwm, IWM_BARKER_REBOOT_NOTIFICATION,
662 IWM_SRC_UDMA, 2 * HZ);
663 if (!notif_reboot) {
664 IWM_ERR(iwm, "Wait for REBOOT_BARKER timeout\n");
665 goto err_disable;
666 }
667
668 /* We send the barker back */
669 ret = iwm_bus_send_chunk(iwm, notif_reboot->buf, 16);
670 if (ret) {
671 IWM_ERR(iwm, "REBOOT barker response failed\n");
672 kfree(notif_reboot);
673 goto err_disable;
674 }
675
676 kfree(notif_reboot->buf);
677 kfree(notif_reboot);
678
679 /* Wait for ACK_BARKER from hardware */
680 notif_ack = iwm_notif_wait(iwm, IWM_ACK_BARKER_NOTIFICATION,
681 IWM_SRC_UDMA, 2 * HZ);
682 if (!notif_ack) {
683 IWM_ERR(iwm, "Wait for ACK_BARKER timeout\n");
684 goto err_disable;
685 }
686
687 kfree(notif_ack->buf);
688 kfree(notif_ack);
689
690 /* We start to config static boot parameters */
691 ret = iwm_config_boot_params(iwm);
692 if (ret) {
693 IWM_ERR(iwm, "Config boot parameters failed\n");
694 goto err_disable;
695 }
696
697 ret = iwm_read_mac(iwm, iwm_to_ndev(iwm)->dev_addr);
698 if (ret) {
699 IWM_ERR(iwm, "MAC reading failed\n");
700 goto err_disable;
701 }
702 memcpy(iwm_to_ndev(iwm)->perm_addr, iwm_to_ndev(iwm)->dev_addr,
703 ETH_ALEN);
704
705 /* We can load the FWs */
706 ret = iwm_load_fw(iwm);
707 if (ret) {
708 IWM_ERR(iwm, "FW loading failed\n");
709 goto err_disable;
710 }
711
712 ret = iwm_eeprom_fat_channels(iwm);
713 if (ret) {
714 IWM_ERR(iwm, "Couldnt read HT channels EEPROM entries\n");
715 goto err_fw;
716 }
717
718 /*
719 * Read our SKU capabilities.
720 * If it's valid, we AND the configured wireless mode with the
721 * device EEPROM value as the current profile wireless mode.
722 */
723 wireless_mode = iwm_eeprom_wireless_mode(iwm);
724 if (wireless_mode) {
725 iwm->conf.wireless_mode &= wireless_mode;
726 if (iwm->umac_profile)
727 iwm->umac_profile->wireless_mode =
728 iwm->conf.wireless_mode;
729 } else
730 IWM_ERR(iwm, "Wrong SKU capabilities: 0x%x\n",
731 *((u16 *)iwm_eeprom_access(iwm, IWM_EEPROM_SKU_CAP)));
732
733 snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "L%s_U%s",
734 iwm->lmac_version, iwm->umac_version);
735
736 /* We configure the UMAC and enable the wifi module */
737 ret = iwm_send_umac_config(iwm,
738 cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_CORE_EN) |
739 cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_LINK_EN) |
740 cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_MLME_EN));
741 if (ret) {
742 IWM_ERR(iwm, "UMAC config failed\n");
743 goto err_fw;
744 }
745
746 ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS,
747 IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
748 if (ret) {
749 IWM_ERR(iwm, "Didn't get a wifi core status notification\n");
750 goto err_fw;
751 }
752
753 if (iwm->core_enabled != (UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN |
754 UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN)) {
755 IWM_DBG_BOOT(iwm, DBG, "Not all cores enabled:0x%x\n",
756 iwm->core_enabled);
757 ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS,
758 IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
759 if (ret) {
760 IWM_ERR(iwm, "Didn't get a core status notification\n");
761 goto err_fw;
762 }
763
764 if (iwm->core_enabled != (UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN |
765 UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN)) {
766 IWM_ERR(iwm, "Not all cores enabled: 0x%x\n",
767 iwm->core_enabled);
768 goto err_fw;
769 } else {
770 IWM_INFO(iwm, "All cores enabled\n");
771 }
772 }
773
774 ret = iwm_channels_init(iwm);
775 if (ret < 0) {
776 IWM_ERR(iwm, "Couldn't init channels\n");
777 goto err_fw;
778 }
779
780 /* Set the READY bit to indicate interface is brought up successfully */
781 set_bit(IWM_STATUS_READY, &iwm->status);
782
783 return 0;
784
785 err_fw:
786 iwm_eeprom_exit(iwm);
787
788 err_disable:
789 ret = iwm_bus_disable(iwm);
790 if (ret < 0)
791 IWM_ERR(iwm, "Couldn't disable function\n");
792
793 return -EIO;
794}
795
796int iwm_up(struct iwm_priv *iwm)
797{
798 int ret;
799
800 mutex_lock(&iwm->mutex);
801 ret = __iwm_up(iwm);
802 mutex_unlock(&iwm->mutex);
803
804 return ret;
805}
806
807static int __iwm_down(struct iwm_priv *iwm)
808{
809 int ret;
810
811 /* The interface is already down */
812 if (!test_bit(IWM_STATUS_READY, &iwm->status))
813 return 0;
814
815 if (iwm->scan_request) {
816 cfg80211_scan_done(iwm->scan_request, true);
817 iwm->scan_request = NULL;
818 }
819
820 clear_bit(IWM_STATUS_READY, &iwm->status);
821
822 iwm_eeprom_exit(iwm);
823 iwm_bss_list_clean(iwm);
824 iwm_init_default_profile(iwm, iwm->umac_profile);
825 iwm->umac_profile_active = false;
826 iwm->default_key = -1;
827 iwm->core_enabled = 0;
828
829 ret = iwm_bus_disable(iwm);
830 if (ret < 0) {
831 IWM_ERR(iwm, "Couldn't disable function\n");
832 return ret;
833 }
834
835 return 0;
836}
837
838int iwm_down(struct iwm_priv *iwm)
839{
840 int ret;
841
842 mutex_lock(&iwm->mutex);
843 ret = __iwm_down(iwm);
844 mutex_unlock(&iwm->mutex);
845
846 return ret;
847}
diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c
deleted file mode 100644
index 5091d77e02ce..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/netdev.c
+++ /dev/null
@@ -1,191 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 */
23
24/*
25 * This is the netdev related hooks for iwm.
26 *
27 * Some interesting code paths:
28 *
29 * iwm_open() (Called at netdev interface bringup time)
30 * -> iwm_up() (main.c)
31 * -> iwm_bus_enable()
32 * -> if_sdio_enable() (In case of an SDIO bus)
33 * -> sdio_enable_func()
34 * -> iwm_notif_wait(BARKER_REBOOT) (wait for reboot barker)
35 * -> iwm_notif_wait(ACK_BARKER) (wait for ACK barker)
36 * -> iwm_load_fw() (fw.c)
37 * -> iwm_load_umac()
38 * -> iwm_load_lmac() (Calibration LMAC)
39 * -> iwm_load_lmac() (Operational LMAC)
40 * -> iwm_send_umac_config()
41 *
42 * iwm_stop() (Called at netdev interface bringdown time)
43 * -> iwm_down()
44 * -> iwm_bus_disable()
45 * -> if_sdio_disable() (In case of an SDIO bus)
46 * -> sdio_disable_func()
47 */
48#include <linux/netdevice.h>
49#include <linux/slab.h>
50
51#include "iwm.h"
52#include "commands.h"
53#include "cfg80211.h"
54#include "debug.h"
55
56static int iwm_open(struct net_device *ndev)
57{
58 struct iwm_priv *iwm = ndev_to_iwm(ndev);
59
60 return iwm_up(iwm);
61}
62
63static int iwm_stop(struct net_device *ndev)
64{
65 struct iwm_priv *iwm = ndev_to_iwm(ndev);
66
67 return iwm_down(iwm);
68}
69
70/*
71 * iwm AC to queue mapping
72 *
73 * AC_VO -> queue 3
74 * AC_VI -> queue 2
75 * AC_BE -> queue 1
76 * AC_BK -> queue 0
77 */
78static const u16 iwm_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
79
80int iwm_tid_to_queue(u16 tid)
81{
82 if (tid > IWM_UMAC_TID_NR - 2)
83 return -EINVAL;
84
85 return iwm_1d_to_queue[tid];
86}
87
88static u16 iwm_select_queue(struct net_device *dev, struct sk_buff *skb)
89{
90 skb->priority = cfg80211_classify8021d(skb);
91
92 return iwm_1d_to_queue[skb->priority];
93}
94
95static const struct net_device_ops iwm_netdev_ops = {
96 .ndo_open = iwm_open,
97 .ndo_stop = iwm_stop,
98 .ndo_start_xmit = iwm_xmit_frame,
99 .ndo_select_queue = iwm_select_queue,
100};
101
102void *iwm_if_alloc(int sizeof_bus, struct device *dev,
103 struct iwm_if_ops *if_ops)
104{
105 struct net_device *ndev;
106 struct wireless_dev *wdev;
107 struct iwm_priv *iwm;
108 int ret = 0;
109
110 wdev = iwm_wdev_alloc(sizeof_bus, dev);
111 if (IS_ERR(wdev))
112 return wdev;
113
114 iwm = wdev_to_iwm(wdev);
115 iwm->bus_ops = if_ops;
116 iwm->wdev = wdev;
117
118 ret = iwm_priv_init(iwm);
119 if (ret) {
120 dev_err(dev, "failed to init iwm_priv\n");
121 goto out_wdev;
122 }
123
124 wdev->iftype = iwm_mode_to_nl80211_iftype(iwm->conf.mode);
125
126 ndev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES);
127 if (!ndev) {
128 dev_err(dev, "no memory for network device instance\n");
129 ret = -ENOMEM;
130 goto out_priv;
131 }
132
133 ndev->netdev_ops = &iwm_netdev_ops;
134 ndev->ieee80211_ptr = wdev;
135 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
136 wdev->netdev = ndev;
137
138 iwm->umac_profile = kmalloc(sizeof(struct iwm_umac_profile),
139 GFP_KERNEL);
140 if (!iwm->umac_profile) {
141 dev_err(dev, "Couldn't alloc memory for profile\n");
142 ret = -ENOMEM;
143 goto out_profile;
144 }
145
146 iwm_init_default_profile(iwm, iwm->umac_profile);
147
148 return iwm;
149
150 out_profile:
151 free_netdev(ndev);
152
153 out_priv:
154 iwm_priv_deinit(iwm);
155
156 out_wdev:
157 iwm_wdev_free(iwm);
158 return ERR_PTR(ret);
159}
160
161void iwm_if_free(struct iwm_priv *iwm)
162{
163 if (!iwm_to_ndev(iwm))
164 return;
165
166 cancel_delayed_work_sync(&iwm->ct_kill_delay);
167 free_netdev(iwm_to_ndev(iwm));
168 iwm_priv_deinit(iwm);
169 kfree(iwm->umac_profile);
170 iwm->umac_profile = NULL;
171 iwm_wdev_free(iwm);
172}
173
174int iwm_if_add(struct iwm_priv *iwm)
175{
176 struct net_device *ndev = iwm_to_ndev(iwm);
177 int ret;
178
179 ret = register_netdev(ndev);
180 if (ret < 0) {
181 dev_err(&ndev->dev, "Failed to register netdev: %d\n", ret);
182 return ret;
183 }
184
185 return 0;
186}
187
188void iwm_if_remove(struct iwm_priv *iwm)
189{
190 unregister_netdev(iwm_to_ndev(iwm));
191}
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
deleted file mode 100644
index 7d708f4395f3..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/rx.c
+++ /dev/null
@@ -1,1701 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#include <linux/kernel.h>
40#include <linux/netdevice.h>
41#include <linux/sched.h>
42#include <linux/etherdevice.h>
43#include <linux/wireless.h>
44#include <linux/ieee80211.h>
45#include <linux/if_arp.h>
46#include <linux/list.h>
47#include <linux/slab.h>
48#include <net/iw_handler.h>
49
50#include "iwm.h"
51#include "debug.h"
52#include "hal.h"
53#include "umac.h"
54#include "lmac.h"
55#include "commands.h"
56#include "rx.h"
57#include "cfg80211.h"
58#include "eeprom.h"
59
60static int iwm_rx_check_udma_hdr(struct iwm_udma_in_hdr *hdr)
61{
62 if ((le32_to_cpu(hdr->cmd) == UMAC_PAD_TERMINAL) ||
63 (le32_to_cpu(hdr->size) == UMAC_PAD_TERMINAL))
64 return -EINVAL;
65
66 return 0;
67}
68
69static inline int iwm_rx_resp_size(struct iwm_udma_in_hdr *hdr)
70{
71 return ALIGN(le32_to_cpu(hdr->size) + sizeof(struct iwm_udma_in_hdr),
72 16);
73}
74
75/*
76 * Notification handlers:
77 *
78 * For every possible notification we can receive from the
79 * target, we have a handler.
80 * When we get a target notification, and there is no one
81 * waiting for it, it's just processed through the rx code
82 * path:
83 *
84 * iwm_rx_handle()
85 * -> iwm_rx_handle_umac()
86 * -> iwm_rx_handle_wifi()
87 * -> iwm_rx_handle_resp()
88 * -> iwm_ntf_*()
89 *
90 * OR
91 *
92 * -> iwm_rx_handle_non_wifi()
93 *
94 * If there are processes waiting for this notification, then
95 * iwm_rx_handle_wifi() just wakes those processes up and they
96 * grab the pending notification.
97 */
98static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf,
99 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
100{
101 struct iwm_umac_notif_error *error;
102 struct iwm_fw_error_hdr *fw_err;
103
104 error = (struct iwm_umac_notif_error *)buf;
105 fw_err = &error->err;
106
107 memcpy(iwm->last_fw_err, fw_err, sizeof(struct iwm_fw_error_hdr));
108
109 IWM_ERR(iwm, "%cMAC FW ERROR:\n",
110 (le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U');
111 IWM_ERR(iwm, "\tCategory: %d\n", le32_to_cpu(fw_err->category));
112 IWM_ERR(iwm, "\tStatus: 0x%x\n", le32_to_cpu(fw_err->status));
113 IWM_ERR(iwm, "\tPC: 0x%x\n", le32_to_cpu(fw_err->pc));
114 IWM_ERR(iwm, "\tblink1: %d\n", le32_to_cpu(fw_err->blink1));
115 IWM_ERR(iwm, "\tblink2: %d\n", le32_to_cpu(fw_err->blink2));
116 IWM_ERR(iwm, "\tilink1: %d\n", le32_to_cpu(fw_err->ilink1));
117 IWM_ERR(iwm, "\tilink2: %d\n", le32_to_cpu(fw_err->ilink2));
118 IWM_ERR(iwm, "\tData1: 0x%x\n", le32_to_cpu(fw_err->data1));
119 IWM_ERR(iwm, "\tData2: 0x%x\n", le32_to_cpu(fw_err->data2));
120 IWM_ERR(iwm, "\tLine number: %d\n", le32_to_cpu(fw_err->line_num));
121 IWM_ERR(iwm, "\tUMAC status: 0x%x\n", le32_to_cpu(fw_err->umac_status));
122 IWM_ERR(iwm, "\tLMAC status: 0x%x\n", le32_to_cpu(fw_err->lmac_status));
123 IWM_ERR(iwm, "\tSDIO status: 0x%x\n", le32_to_cpu(fw_err->sdio_status));
124
125 iwm_resetting(iwm);
126
127 return 0;
128}
129
130static int iwm_ntf_umac_alive(struct iwm_priv *iwm, u8 *buf,
131 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
132{
133 struct iwm_umac_notif_alive *alive_resp =
134 (struct iwm_umac_notif_alive *)(buf);
135 u16 status = le16_to_cpu(alive_resp->status);
136
137 if (status == UMAC_NTFY_ALIVE_STATUS_ERR) {
138 IWM_ERR(iwm, "Receive error UMAC_ALIVE\n");
139 return -EIO;
140 }
141
142 iwm_tx_credit_init_pools(iwm, alive_resp);
143
144 return 0;
145}
146
147static int iwm_ntf_init_complete(struct iwm_priv *iwm, u8 *buf,
148 unsigned long buf_size,
149 struct iwm_wifi_cmd *cmd)
150{
151 struct wiphy *wiphy = iwm_to_wiphy(iwm);
152 struct iwm_umac_notif_init_complete *init_complete =
153 (struct iwm_umac_notif_init_complete *)(buf);
154 u16 status = le16_to_cpu(init_complete->status);
155 bool blocked = (status == UMAC_NTFY_INIT_COMPLETE_STATUS_ERR);
156
157 if (blocked)
158 IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is on (radio off)\n");
159 else
160 IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is off (radio on)\n");
161
162 wiphy_rfkill_set_hw_state(wiphy, blocked);
163
164 return 0;
165}
166
167static int iwm_ntf_tx_credit_update(struct iwm_priv *iwm, u8 *buf,
168 unsigned long buf_size,
169 struct iwm_wifi_cmd *cmd)
170{
171 int pool_nr, total_freed_pages;
172 unsigned long pool_map;
173 int i, id;
174 struct iwm_umac_notif_page_dealloc *dealloc =
175 (struct iwm_umac_notif_page_dealloc *)buf;
176
177 pool_nr = GET_VAL32(dealloc->changes, UMAC_DEALLOC_NTFY_CHANGES_CNT);
178 pool_map = GET_VAL32(dealloc->changes, UMAC_DEALLOC_NTFY_CHANGES_MSK);
179
180 IWM_DBG_TX(iwm, DBG, "UMAC dealloc notification: pool nr %d, "
181 "update map 0x%lx\n", pool_nr, pool_map);
182
183 spin_lock(&iwm->tx_credit.lock);
184
185 for (i = 0; i < pool_nr; i++) {
186 id = GET_VAL32(dealloc->grp_info[i],
187 UMAC_DEALLOC_NTFY_GROUP_NUM);
188 if (test_bit(id, &pool_map)) {
189 total_freed_pages = GET_VAL32(dealloc->grp_info[i],
190 UMAC_DEALLOC_NTFY_PAGE_CNT);
191 iwm_tx_credit_inc(iwm, id, total_freed_pages);
192 }
193 }
194
195 spin_unlock(&iwm->tx_credit.lock);
196
197 return 0;
198}
199
200static int iwm_ntf_umac_reset(struct iwm_priv *iwm, u8 *buf,
201 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
202{
203 IWM_DBG_NTF(iwm, DBG, "UMAC RESET done\n");
204
205 return 0;
206}
207
208static int iwm_ntf_lmac_version(struct iwm_priv *iwm, u8 *buf,
209 unsigned long buf_size,
210 struct iwm_wifi_cmd *cmd)
211{
212 IWM_DBG_NTF(iwm, INFO, "LMAC Version: %x.%x\n", buf[9], buf[8]);
213
214 return 0;
215}
216
217static int iwm_ntf_tx(struct iwm_priv *iwm, u8 *buf,
218 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
219{
220 struct iwm_lmac_tx_resp *tx_resp;
221 struct iwm_umac_wifi_in_hdr *hdr;
222
223 tx_resp = (struct iwm_lmac_tx_resp *)
224 (buf + sizeof(struct iwm_umac_wifi_in_hdr));
225 hdr = (struct iwm_umac_wifi_in_hdr *)buf;
226
227 IWM_DBG_TX(iwm, DBG, "REPLY_TX, buf size: %lu\n", buf_size);
228
229 IWM_DBG_TX(iwm, DBG, "Seqnum: %d\n",
230 le16_to_cpu(hdr->sw_hdr.cmd.seq_num));
231 IWM_DBG_TX(iwm, DBG, "\tFrame cnt: %d\n", tx_resp->frame_cnt);
232 IWM_DBG_TX(iwm, DBG, "\tRetry cnt: %d\n",
233 le16_to_cpu(tx_resp->retry_cnt));
234 IWM_DBG_TX(iwm, DBG, "\tSeq ctl: %d\n", le16_to_cpu(tx_resp->seq_ctl));
235 IWM_DBG_TX(iwm, DBG, "\tByte cnt: %d\n",
236 le16_to_cpu(tx_resp->byte_cnt));
237 IWM_DBG_TX(iwm, DBG, "\tStatus: 0x%x\n", le32_to_cpu(tx_resp->status));
238
239 return 0;
240}
241
242
243static int iwm_ntf_calib_res(struct iwm_priv *iwm, u8 *buf,
244 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
245{
246 u8 opcode;
247 u8 *calib_buf;
248 struct iwm_lmac_calib_hdr *hdr = (struct iwm_lmac_calib_hdr *)
249 (buf + sizeof(struct iwm_umac_wifi_in_hdr));
250
251 opcode = hdr->opcode;
252
253 BUG_ON(opcode >= CALIBRATION_CMD_NUM ||
254 opcode < PHY_CALIBRATE_OPCODES_NUM);
255
256 IWM_DBG_NTF(iwm, DBG, "Store calibration result for opcode: %d\n",
257 opcode);
258
259 buf_size -= sizeof(struct iwm_umac_wifi_in_hdr);
260 calib_buf = iwm->calib_res[opcode].buf;
261
262 if (!calib_buf || (iwm->calib_res[opcode].size < buf_size)) {
263 kfree(calib_buf);
264 calib_buf = kzalloc(buf_size, GFP_KERNEL);
265 if (!calib_buf) {
266 IWM_ERR(iwm, "Memory allocation failed: calib_res\n");
267 return -ENOMEM;
268 }
269 iwm->calib_res[opcode].buf = calib_buf;
270 iwm->calib_res[opcode].size = buf_size;
271 }
272
273 memcpy(calib_buf, hdr, buf_size);
274 set_bit(opcode - PHY_CALIBRATE_OPCODES_NUM, &iwm->calib_done_map);
275
276 return 0;
277}
278
279static int iwm_ntf_calib_complete(struct iwm_priv *iwm, u8 *buf,
280 unsigned long buf_size,
281 struct iwm_wifi_cmd *cmd)
282{
283 IWM_DBG_NTF(iwm, DBG, "Calibration completed\n");
284
285 return 0;
286}
287
288static int iwm_ntf_calib_cfg(struct iwm_priv *iwm, u8 *buf,
289 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
290{
291 struct iwm_lmac_cal_cfg_resp *cal_resp;
292
293 cal_resp = (struct iwm_lmac_cal_cfg_resp *)
294 (buf + sizeof(struct iwm_umac_wifi_in_hdr));
295
296 IWM_DBG_NTF(iwm, DBG, "Calibration CFG command status: %d\n",
297 le32_to_cpu(cal_resp->status));
298
299 return 0;
300}
301
302static int iwm_ntf_wifi_status(struct iwm_priv *iwm, u8 *buf,
303 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
304{
305 struct iwm_umac_notif_wifi_status *status =
306 (struct iwm_umac_notif_wifi_status *)buf;
307
308 iwm->core_enabled |= le16_to_cpu(status->status);
309
310 return 0;
311}
312
313static struct iwm_rx_ticket_node *
314iwm_rx_ticket_node_alloc(struct iwm_priv *iwm, struct iwm_rx_ticket *ticket)
315{
316 struct iwm_rx_ticket_node *ticket_node;
317
318 ticket_node = kzalloc(sizeof(struct iwm_rx_ticket_node), GFP_KERNEL);
319 if (!ticket_node) {
320 IWM_ERR(iwm, "Couldn't allocate ticket node\n");
321 return ERR_PTR(-ENOMEM);
322 }
323
324 ticket_node->ticket = kmemdup(ticket, sizeof(struct iwm_rx_ticket),
325 GFP_KERNEL);
326 if (!ticket_node->ticket) {
327 IWM_ERR(iwm, "Couldn't allocate RX ticket\n");
328 kfree(ticket_node);
329 return ERR_PTR(-ENOMEM);
330 }
331
332 INIT_LIST_HEAD(&ticket_node->node);
333
334 return ticket_node;
335}
336
337static void iwm_rx_ticket_node_free(struct iwm_rx_ticket_node *ticket_node)
338{
339 kfree(ticket_node->ticket);
340 kfree(ticket_node);
341}
342
343static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id)
344{
345 u8 id_hash = IWM_RX_ID_GET_HASH(id);
346 struct iwm_rx_packet *packet;
347
348 spin_lock(&iwm->packet_lock[id_hash]);
349 list_for_each_entry(packet, &iwm->rx_packets[id_hash], node)
350 if (packet->id == id) {
351 list_del(&packet->node);
352 spin_unlock(&iwm->packet_lock[id_hash]);
353 return packet;
354 }
355
356 spin_unlock(&iwm->packet_lock[id_hash]);
357 return NULL;
358}
359
360static struct iwm_rx_packet *iwm_rx_packet_alloc(struct iwm_priv *iwm, u8 *buf,
361 u32 size, u16 id)
362{
363 struct iwm_rx_packet *packet;
364
365 packet = kzalloc(sizeof(struct iwm_rx_packet), GFP_KERNEL);
366 if (!packet) {
367 IWM_ERR(iwm, "Couldn't allocate packet\n");
368 return ERR_PTR(-ENOMEM);
369 }
370
371 packet->skb = dev_alloc_skb(size);
372 if (!packet->skb) {
373 IWM_ERR(iwm, "Couldn't allocate packet SKB\n");
374 kfree(packet);
375 return ERR_PTR(-ENOMEM);
376 }
377
378 packet->pkt_size = size;
379
380 skb_put(packet->skb, size);
381 memcpy(packet->skb->data, buf, size);
382 INIT_LIST_HEAD(&packet->node);
383 packet->id = id;
384
385 return packet;
386}
387
388void iwm_rx_free(struct iwm_priv *iwm)
389{
390 struct iwm_rx_ticket_node *ticket, *nt;
391 struct iwm_rx_packet *packet, *np;
392 int i;
393
394 spin_lock(&iwm->ticket_lock);
395 list_for_each_entry_safe(ticket, nt, &iwm->rx_tickets, node) {
396 list_del(&ticket->node);
397 iwm_rx_ticket_node_free(ticket);
398 }
399 spin_unlock(&iwm->ticket_lock);
400
401 for (i = 0; i < IWM_RX_ID_HASH; i++) {
402 spin_lock(&iwm->packet_lock[i]);
403 list_for_each_entry_safe(packet, np, &iwm->rx_packets[i],
404 node) {
405 list_del(&packet->node);
406 kfree_skb(packet->skb);
407 kfree(packet);
408 }
409 spin_unlock(&iwm->packet_lock[i]);
410 }
411}
412
413static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf,
414 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
415{
416 struct iwm_umac_notif_rx_ticket *ntf_rx_ticket =
417 (struct iwm_umac_notif_rx_ticket *)buf;
418 struct iwm_rx_ticket *ticket =
419 (struct iwm_rx_ticket *)ntf_rx_ticket->tickets;
420 int i, schedule_rx = 0;
421
422 for (i = 0; i < ntf_rx_ticket->num_tickets; i++) {
423 struct iwm_rx_ticket_node *ticket_node;
424
425 switch (le16_to_cpu(ticket->action)) {
426 case IWM_RX_TICKET_RELEASE:
427 case IWM_RX_TICKET_DROP:
428 /* We can push the packet to the stack */
429 ticket_node = iwm_rx_ticket_node_alloc(iwm, ticket);
430 if (IS_ERR(ticket_node))
431 return PTR_ERR(ticket_node);
432
433 IWM_DBG_RX(iwm, DBG, "TICKET %s(%d)\n",
434 __le16_to_cpu(ticket->action) ==
435 IWM_RX_TICKET_RELEASE ?
436 "RELEASE" : "DROP",
437 ticket->id);
438 spin_lock(&iwm->ticket_lock);
439 list_add_tail(&ticket_node->node, &iwm->rx_tickets);
440 spin_unlock(&iwm->ticket_lock);
441
442 /*
443 * We received an Rx ticket, most likely there's
444 * a packet pending for it, it's not worth going
445 * through the packet hash list to double check.
446 * Let's just fire the rx worker..
447 */
448 schedule_rx = 1;
449
450 break;
451
452 default:
453 IWM_ERR(iwm, "Invalid RX ticket action: 0x%x\n",
454 ticket->action);
455 }
456
457 ticket++;
458 }
459
460 if (schedule_rx)
461 queue_work(iwm->rx_wq, &iwm->rx_worker);
462
463 return 0;
464}
465
466static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf,
467 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
468{
469 struct iwm_umac_wifi_in_hdr *wifi_hdr;
470 struct iwm_rx_packet *packet;
471 u16 id, buf_offset;
472 u32 packet_size;
473 u8 id_hash;
474
475 IWM_DBG_RX(iwm, DBG, "\n");
476
477 wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
478 id = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num);
479 buf_offset = sizeof(struct iwm_umac_wifi_in_hdr);
480 packet_size = buf_size - sizeof(struct iwm_umac_wifi_in_hdr);
481
482 IWM_DBG_RX(iwm, DBG, "CMD:0x%x, seqnum: %d, packet size: %d\n",
483 wifi_hdr->sw_hdr.cmd.cmd, id, packet_size);
484 IWM_DBG_RX(iwm, DBG, "Packet id: %d\n", id);
485 IWM_HEXDUMP(iwm, DBG, RX, "PACKET: ", buf + buf_offset, packet_size);
486
487 packet = iwm_rx_packet_alloc(iwm, buf + buf_offset, packet_size, id);
488 if (IS_ERR(packet))
489 return PTR_ERR(packet);
490
491 id_hash = IWM_RX_ID_GET_HASH(id);
492 spin_lock(&iwm->packet_lock[id_hash]);
493 list_add_tail(&packet->node, &iwm->rx_packets[id_hash]);
494 spin_unlock(&iwm->packet_lock[id_hash]);
495
496 /* We might (unlikely) have received the packet _after_ the ticket */
497 queue_work(iwm->rx_wq, &iwm->rx_worker);
498
499 return 0;
500}
501
502/* MLME handlers */
503static int iwm_mlme_assoc_start(struct iwm_priv *iwm, u8 *buf,
504 unsigned long buf_size,
505 struct iwm_wifi_cmd *cmd)
506{
507 struct iwm_umac_notif_assoc_start *start;
508
509 start = (struct iwm_umac_notif_assoc_start *)buf;
510
511 IWM_DBG_MLME(iwm, INFO, "Association with %pM Started, reason: %d\n",
512 start->bssid, le32_to_cpu(start->roam_reason));
513
514 wake_up_interruptible(&iwm->mlme_queue);
515
516 return 0;
517}
518
519static u8 iwm_is_open_wep_profile(struct iwm_priv *iwm)
520{
521 if ((iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_40 ||
522 iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_104) &&
523 (iwm->umac_profile->sec.ucast_cipher ==
524 iwm->umac_profile->sec.mcast_cipher) &&
525 (iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN))
526 return 1;
527
528 return 0;
529}
530
531static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
532 unsigned long buf_size,
533 struct iwm_wifi_cmd *cmd)
534{
535 struct wiphy *wiphy = iwm_to_wiphy(iwm);
536 struct ieee80211_channel *chan;
537 struct iwm_umac_notif_assoc_complete *complete =
538 (struct iwm_umac_notif_assoc_complete *)buf;
539
540 IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n",
541 complete->bssid, complete->status);
542
543 switch (le32_to_cpu(complete->status)) {
544 case UMAC_ASSOC_COMPLETE_SUCCESS:
545 chan = ieee80211_get_channel(wiphy,
546 ieee80211_channel_to_frequency(complete->channel,
547 complete->band == UMAC_BAND_2GHZ ?
548 IEEE80211_BAND_2GHZ :
549 IEEE80211_BAND_5GHZ));
550 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
551 /* Associated to a unallowed channel, disassociate. */
552 __iwm_invalidate_mlme_profile(iwm);
553 IWM_WARN(iwm, "Couldn't associate with %pM due to "
554 "channel %d is disabled. Check your local "
555 "regulatory setting.\n",
556 complete->bssid, complete->channel);
557 goto failure;
558 }
559
560 set_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
561 memcpy(iwm->bssid, complete->bssid, ETH_ALEN);
562 iwm->channel = complete->channel;
563
564 /* Internal roaming state, avoid notifying SME. */
565 if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status)
566 && iwm->conf.mode == UMAC_MODE_BSS) {
567 cancel_delayed_work(&iwm->disconnect);
568 cfg80211_roamed(iwm_to_ndev(iwm), NULL,
569 complete->bssid,
570 iwm->req_ie, iwm->req_ie_len,
571 iwm->resp_ie, iwm->resp_ie_len,
572 GFP_KERNEL);
573 break;
574 }
575
576 iwm_link_on(iwm);
577
578 if (iwm->conf.mode == UMAC_MODE_IBSS)
579 goto ibss;
580
581 if (!test_bit(IWM_STATUS_RESETTING, &iwm->status))
582 cfg80211_connect_result(iwm_to_ndev(iwm),
583 complete->bssid,
584 iwm->req_ie, iwm->req_ie_len,
585 iwm->resp_ie, iwm->resp_ie_len,
586 WLAN_STATUS_SUCCESS,
587 GFP_KERNEL);
588 else
589 cfg80211_roamed(iwm_to_ndev(iwm), NULL,
590 complete->bssid,
591 iwm->req_ie, iwm->req_ie_len,
592 iwm->resp_ie, iwm->resp_ie_len,
593 GFP_KERNEL);
594 break;
595 case UMAC_ASSOC_COMPLETE_FAILURE:
596 failure:
597 clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
598 memset(iwm->bssid, 0, ETH_ALEN);
599 iwm->channel = 0;
600
601 /* Internal roaming state, avoid notifying SME. */
602 if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status)
603 && iwm->conf.mode == UMAC_MODE_BSS) {
604 cancel_delayed_work(&iwm->disconnect);
605 break;
606 }
607
608 iwm_link_off(iwm);
609
610 if (iwm->conf.mode == UMAC_MODE_IBSS)
611 goto ibss;
612
613 if (!test_bit(IWM_STATUS_RESETTING, &iwm->status))
614 if (!iwm_is_open_wep_profile(iwm)) {
615 cfg80211_connect_result(iwm_to_ndev(iwm),
616 complete->bssid,
617 NULL, 0, NULL, 0,
618 WLAN_STATUS_UNSPECIFIED_FAILURE,
619 GFP_KERNEL);
620 } else {
621 /* Let's try shared WEP auth */
622 IWM_ERR(iwm, "Trying WEP shared auth\n");
623 schedule_work(&iwm->auth_retry_worker);
624 }
625 else
626 cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0,
627 GFP_KERNEL);
628 break;
629 default:
630 break;
631 }
632
633 clear_bit(IWM_STATUS_RESETTING, &iwm->status);
634 return 0;
635
636 ibss:
637 cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL);
638 clear_bit(IWM_STATUS_RESETTING, &iwm->status);
639 return 0;
640}
641
642static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf,
643 unsigned long buf_size,
644 struct iwm_wifi_cmd *cmd)
645{
646 struct iwm_umac_notif_profile_invalidate *invalid;
647 u32 reason;
648
649 invalid = (struct iwm_umac_notif_profile_invalidate *)buf;
650 reason = le32_to_cpu(invalid->reason);
651
652 IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n", reason);
653
654 if (reason != UMAC_PROFILE_INVALID_REQUEST &&
655 test_bit(IWM_STATUS_SME_CONNECTING, &iwm->status))
656 cfg80211_connect_result(iwm_to_ndev(iwm), NULL, NULL, 0, NULL,
657 0, WLAN_STATUS_UNSPECIFIED_FAILURE,
658 GFP_KERNEL);
659
660 clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status);
661 clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
662
663 iwm->umac_profile_active = false;
664 memset(iwm->bssid, 0, ETH_ALEN);
665 iwm->channel = 0;
666
667 iwm_link_off(iwm);
668
669 wake_up_interruptible(&iwm->mlme_queue);
670
671 return 0;
672}
673
674#define IWM_DISCONNECT_INTERVAL (5 * HZ)
675
676static int iwm_mlme_connection_terminated(struct iwm_priv *iwm, u8 *buf,
677 unsigned long buf_size,
678 struct iwm_wifi_cmd *cmd)
679{
680 IWM_DBG_MLME(iwm, DBG, "Connection terminated\n");
681
682 schedule_delayed_work(&iwm->disconnect, IWM_DISCONNECT_INTERVAL);
683
684 return 0;
685}
686
687static int iwm_mlme_scan_complete(struct iwm_priv *iwm, u8 *buf,
688 unsigned long buf_size,
689 struct iwm_wifi_cmd *cmd)
690{
691 int ret;
692 struct iwm_umac_notif_scan_complete *scan_complete =
693 (struct iwm_umac_notif_scan_complete *)buf;
694 u32 result = le32_to_cpu(scan_complete->result);
695
696 IWM_DBG_MLME(iwm, INFO, "type:0x%x result:0x%x seq:%d\n",
697 le32_to_cpu(scan_complete->type),
698 le32_to_cpu(scan_complete->result),
699 scan_complete->seq_num);
700
701 if (!test_and_clear_bit(IWM_STATUS_SCANNING, &iwm->status)) {
702 IWM_ERR(iwm, "Scan complete while device not scanning\n");
703 return -EIO;
704 }
705 if (!iwm->scan_request)
706 return 0;
707
708 ret = iwm_cfg80211_inform_bss(iwm);
709
710 cfg80211_scan_done(iwm->scan_request,
711 (result & UMAC_SCAN_RESULT_ABORTED) ? 1 : !!ret);
712 iwm->scan_request = NULL;
713
714 return ret;
715}
716
717static int iwm_mlme_update_sta_table(struct iwm_priv *iwm, u8 *buf,
718 unsigned long buf_size,
719 struct iwm_wifi_cmd *cmd)
720{
721 struct iwm_umac_notif_sta_info *umac_sta =
722 (struct iwm_umac_notif_sta_info *)buf;
723 struct iwm_sta_info *sta;
724 int i;
725
726 switch (le32_to_cpu(umac_sta->opcode)) {
727 case UMAC_OPCODE_ADD_MODIFY:
728 sta = &iwm->sta_table[GET_VAL8(umac_sta->sta_id, LMAC_STA_ID)];
729
730 IWM_DBG_MLME(iwm, INFO, "%s STA: ID = %d, Color = %d, "
731 "addr = %pM, qos = %d\n",
732 sta->valid ? "Modify" : "Add",
733 GET_VAL8(umac_sta->sta_id, LMAC_STA_ID),
734 GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR),
735 umac_sta->mac_addr,
736 umac_sta->flags & UMAC_STA_FLAG_QOS);
737
738 sta->valid = true;
739 sta->qos = umac_sta->flags & UMAC_STA_FLAG_QOS;
740 sta->color = GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR);
741 memcpy(sta->addr, umac_sta->mac_addr, ETH_ALEN);
742 break;
743 case UMAC_OPCODE_REMOVE:
744 IWM_DBG_MLME(iwm, INFO, "Remove STA: ID = %d, Color = %d, "
745 "addr = %pM\n",
746 GET_VAL8(umac_sta->sta_id, LMAC_STA_ID),
747 GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR),
748 umac_sta->mac_addr);
749
750 sta = &iwm->sta_table[GET_VAL8(umac_sta->sta_id, LMAC_STA_ID)];
751
752 if (!memcmp(sta->addr, umac_sta->mac_addr, ETH_ALEN))
753 sta->valid = false;
754
755 break;
756 case UMAC_OPCODE_CLEAR_ALL:
757 for (i = 0; i < IWM_STA_TABLE_NUM; i++)
758 iwm->sta_table[i].valid = false;
759
760 break;
761 default:
762 break;
763 }
764
765 return 0;
766}
767
768static int iwm_mlme_medium_lost(struct iwm_priv *iwm, u8 *buf,
769 unsigned long buf_size,
770 struct iwm_wifi_cmd *cmd)
771{
772 struct wiphy *wiphy = iwm_to_wiphy(iwm);
773
774 IWM_DBG_NTF(iwm, DBG, "WiFi/WiMax coexistence radio is OFF\n");
775
776 wiphy_rfkill_set_hw_state(wiphy, true);
777
778 return 0;
779}
780
781static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf,
782 unsigned long buf_size,
783 struct iwm_wifi_cmd *cmd)
784{
785 struct wiphy *wiphy = iwm_to_wiphy(iwm);
786 struct ieee80211_mgmt *mgmt;
787 struct iwm_umac_notif_bss_info *umac_bss =
788 (struct iwm_umac_notif_bss_info *)buf;
789 struct ieee80211_channel *channel;
790 struct ieee80211_supported_band *band;
791 struct iwm_bss_info *bss;
792 s32 signal;
793 int freq;
794 u16 frame_len = le16_to_cpu(umac_bss->frame_len);
795 size_t bss_len = sizeof(struct iwm_umac_notif_bss_info) + frame_len;
796
797 mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
798
799 IWM_DBG_MLME(iwm, DBG, "New BSS info entry: %pM\n", mgmt->bssid);
800 IWM_DBG_MLME(iwm, DBG, "\tType: 0x%x\n", le32_to_cpu(umac_bss->type));
801 IWM_DBG_MLME(iwm, DBG, "\tTimestamp: %d\n",
802 le32_to_cpu(umac_bss->timestamp));
803 IWM_DBG_MLME(iwm, DBG, "\tTable Index: %d\n",
804 le16_to_cpu(umac_bss->table_idx));
805 IWM_DBG_MLME(iwm, DBG, "\tBand: %d\n", umac_bss->band);
806 IWM_DBG_MLME(iwm, DBG, "\tChannel: %d\n", umac_bss->channel);
807 IWM_DBG_MLME(iwm, DBG, "\tRSSI: %d\n", umac_bss->rssi);
808 IWM_DBG_MLME(iwm, DBG, "\tFrame Length: %d\n", frame_len);
809
810 list_for_each_entry(bss, &iwm->bss_list, node)
811 if (bss->bss->table_idx == umac_bss->table_idx)
812 break;
813
814 if (&bss->node != &iwm->bss_list) {
815 /* Remove the old BSS entry, we will add it back later. */
816 list_del(&bss->node);
817 kfree(bss->bss);
818 } else {
819 /* New BSS entry */
820
821 bss = kzalloc(sizeof(struct iwm_bss_info), GFP_KERNEL);
822 if (!bss) {
823 IWM_ERR(iwm, "Couldn't allocate bss_info\n");
824 return -ENOMEM;
825 }
826 }
827
828 bss->bss = kzalloc(bss_len, GFP_KERNEL);
829 if (!bss->bss) {
830 kfree(bss);
831 IWM_ERR(iwm, "Couldn't allocate bss\n");
832 return -ENOMEM;
833 }
834
835 INIT_LIST_HEAD(&bss->node);
836 memcpy(bss->bss, umac_bss, bss_len);
837
838 if (umac_bss->band == UMAC_BAND_2GHZ)
839 band = wiphy->bands[IEEE80211_BAND_2GHZ];
840 else if (umac_bss->band == UMAC_BAND_5GHZ)
841 band = wiphy->bands[IEEE80211_BAND_5GHZ];
842 else {
843 IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
844 goto err;
845 }
846
847 freq = ieee80211_channel_to_frequency(umac_bss->channel, band->band);
848 channel = ieee80211_get_channel(wiphy, freq);
849 signal = umac_bss->rssi * 100;
850
851 bss->cfg_bss = cfg80211_inform_bss_frame(wiphy, channel,
852 mgmt, frame_len,
853 signal, GFP_KERNEL);
854 if (!bss->cfg_bss)
855 goto err;
856
857 list_add_tail(&bss->node, &iwm->bss_list);
858
859 return 0;
860 err:
861 kfree(bss->bss);
862 kfree(bss);
863
864 return -EINVAL;
865}
866
867static int iwm_mlme_remove_bss(struct iwm_priv *iwm, u8 *buf,
868 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
869{
870 struct iwm_umac_notif_bss_removed *bss_rm =
871 (struct iwm_umac_notif_bss_removed *)buf;
872 struct iwm_bss_info *bss, *next;
873 u16 table_idx;
874 int i;
875
876 for (i = 0; i < le32_to_cpu(bss_rm->count); i++) {
877 table_idx = le16_to_cpu(bss_rm->entries[i]) &
878 IWM_BSS_REMOVE_INDEX_MSK;
879 list_for_each_entry_safe(bss, next, &iwm->bss_list, node)
880 if (bss->bss->table_idx == cpu_to_le16(table_idx)) {
881 struct ieee80211_mgmt *mgmt;
882
883 mgmt = (struct ieee80211_mgmt *)
884 (bss->bss->frame_buf);
885 IWM_DBG_MLME(iwm, ERR, "BSS removed: %pM\n",
886 mgmt->bssid);
887 list_del(&bss->node);
888 kfree(bss->bss);
889 kfree(bss);
890 }
891 }
892
893 return 0;
894}
895
896static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf,
897 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
898{
899 struct iwm_umac_notif_mgt_frame *mgt_frame =
900 (struct iwm_umac_notif_mgt_frame *)buf;
901 struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame;
902
903 IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame,
904 le16_to_cpu(mgt_frame->len));
905
906 if (ieee80211_is_assoc_req(mgt->frame_control)) {
907 iwm->req_ie_len = le16_to_cpu(mgt_frame->len)
908 - offsetof(struct ieee80211_mgmt,
909 u.assoc_req.variable);
910 kfree(iwm->req_ie);
911 iwm->req_ie = kmemdup(mgt->u.assoc_req.variable,
912 iwm->req_ie_len, GFP_KERNEL);
913 } else if (ieee80211_is_reassoc_req(mgt->frame_control)) {
914 iwm->req_ie_len = le16_to_cpu(mgt_frame->len)
915 - offsetof(struct ieee80211_mgmt,
916 u.reassoc_req.variable);
917 kfree(iwm->req_ie);
918 iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable,
919 iwm->req_ie_len, GFP_KERNEL);
920 } else if (ieee80211_is_assoc_resp(mgt->frame_control)) {
921 iwm->resp_ie_len = le16_to_cpu(mgt_frame->len)
922 - offsetof(struct ieee80211_mgmt,
923 u.assoc_resp.variable);
924 kfree(iwm->resp_ie);
925 iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable,
926 iwm->resp_ie_len, GFP_KERNEL);
927 } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) {
928 iwm->resp_ie_len = le16_to_cpu(mgt_frame->len)
929 - offsetof(struct ieee80211_mgmt,
930 u.reassoc_resp.variable);
931 kfree(iwm->resp_ie);
932 iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable,
933 iwm->resp_ie_len, GFP_KERNEL);
934 } else {
935 IWM_ERR(iwm, "Unsupported management frame: 0x%x",
936 le16_to_cpu(mgt->frame_control));
937 return 0;
938 }
939
940 return 0;
941}
942
943static int iwm_ntf_mlme(struct iwm_priv *iwm, u8 *buf,
944 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
945{
946 struct iwm_umac_notif_wifi_if *notif =
947 (struct iwm_umac_notif_wifi_if *)buf;
948
949 switch (notif->status) {
950 case WIFI_IF_NTFY_ASSOC_START:
951 return iwm_mlme_assoc_start(iwm, buf, buf_size, cmd);
952 case WIFI_IF_NTFY_ASSOC_COMPLETE:
953 return iwm_mlme_assoc_complete(iwm, buf, buf_size, cmd);
954 case WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE:
955 return iwm_mlme_profile_invalidate(iwm, buf, buf_size, cmd);
956 case WIFI_IF_NTFY_CONNECTION_TERMINATED:
957 return iwm_mlme_connection_terminated(iwm, buf, buf_size, cmd);
958 case WIFI_IF_NTFY_SCAN_COMPLETE:
959 return iwm_mlme_scan_complete(iwm, buf, buf_size, cmd);
960 case WIFI_IF_NTFY_STA_TABLE_CHANGE:
961 return iwm_mlme_update_sta_table(iwm, buf, buf_size, cmd);
962 case WIFI_IF_NTFY_EXTENDED_IE_REQUIRED:
963 IWM_DBG_MLME(iwm, DBG, "Extended IE required\n");
964 break;
965 case WIFI_IF_NTFY_RADIO_PREEMPTION:
966 return iwm_mlme_medium_lost(iwm, buf, buf_size, cmd);
967 case WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED:
968 return iwm_mlme_update_bss_table(iwm, buf, buf_size, cmd);
969 case WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED:
970 return iwm_mlme_remove_bss(iwm, buf, buf_size, cmd);
971 break;
972 case WIFI_IF_NTFY_MGMT_FRAME:
973 return iwm_mlme_mgt_frame(iwm, buf, buf_size, cmd);
974 case WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_START:
975 case WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_COMPLETE:
976 case WIFI_DBG_IF_NTFY_SCAN_CHANNEL_START:
977 case WIFI_DBG_IF_NTFY_SCAN_CHANNEL_RESULT:
978 case WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_START:
979 case WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_COMPLETE:
980 case WIFI_DBG_IF_NTFY_CNCT_ATC_START:
981 case WIFI_DBG_IF_NTFY_COEX_NOTIFICATION:
982 case WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP:
983 case WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP:
984 IWM_DBG_MLME(iwm, DBG, "MLME debug notification: 0x%x\n",
985 notif->status);
986 break;
987 default:
988 IWM_ERR(iwm, "Unhandled notification: 0x%x\n", notif->status);
989 break;
990 }
991
992 return 0;
993}
994
995#define IWM_STATS_UPDATE_INTERVAL (2 * HZ)
996
997static int iwm_ntf_statistics(struct iwm_priv *iwm, u8 *buf,
998 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
999{
1000 struct iwm_umac_notif_stats *stats = (struct iwm_umac_notif_stats *)buf;
1001 struct iw_statistics *wstats = &iwm->wstats;
1002 u16 max_rate = 0;
1003 int i;
1004
1005 IWM_DBG_MLME(iwm, DBG, "Statistics notification received\n");
1006
1007 if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
1008 for (i = 0; i < UMAC_NTF_RATE_SAMPLE_NR; i++) {
1009 max_rate = max_t(u16, max_rate,
1010 max(le16_to_cpu(stats->tx_rate[i]),
1011 le16_to_cpu(stats->rx_rate[i])));
1012 }
1013 /* UMAC passes rate info multiplies by 2 */
1014 iwm->rate = max_rate >> 1;
1015 }
1016 iwm->txpower = le32_to_cpu(stats->tx_power);
1017
1018 wstats->status = 0;
1019
1020 wstats->discard.nwid = le32_to_cpu(stats->rx_drop_other_bssid);
1021 wstats->discard.code = le32_to_cpu(stats->rx_drop_decode);
1022 wstats->discard.fragment = le32_to_cpu(stats->rx_drop_reassembly);
1023 wstats->discard.retries = le32_to_cpu(stats->tx_drop_max_retry);
1024
1025 wstats->miss.beacon = le32_to_cpu(stats->missed_beacons);
1026
1027 /* according to cfg80211 */
1028 if (stats->rssi_dbm < -110)
1029 wstats->qual.qual = 0;
1030 else if (stats->rssi_dbm > -40)
1031 wstats->qual.qual = 70;
1032 else
1033 wstats->qual.qual = stats->rssi_dbm + 110;
1034
1035 wstats->qual.level = stats->rssi_dbm;
1036 wstats->qual.noise = stats->noise_dbm;
1037 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1038
1039 schedule_delayed_work(&iwm->stats_request, IWM_STATS_UPDATE_INTERVAL);
1040
1041 mod_timer(&iwm->watchdog, round_jiffies(jiffies + IWM_WATCHDOG_PERIOD));
1042
1043 return 0;
1044}
1045
1046static int iwm_ntf_eeprom_proxy(struct iwm_priv *iwm, u8 *buf,
1047 unsigned long buf_size,
1048 struct iwm_wifi_cmd *cmd)
1049{
1050 struct iwm_umac_cmd_eeprom_proxy *eeprom_proxy =
1051 (struct iwm_umac_cmd_eeprom_proxy *)
1052 (buf + sizeof(struct iwm_umac_wifi_in_hdr));
1053 struct iwm_umac_cmd_eeprom_proxy_hdr *hdr = &eeprom_proxy->hdr;
1054 u32 hdr_offset = le32_to_cpu(hdr->offset);
1055 u32 hdr_len = le32_to_cpu(hdr->len);
1056 u32 hdr_type = le32_to_cpu(hdr->type);
1057
1058 IWM_DBG_NTF(iwm, DBG, "type: 0x%x, len: %d, offset: 0x%x\n",
1059 hdr_type, hdr_len, hdr_offset);
1060
1061 if ((hdr_offset + hdr_len) > IWM_EEPROM_LEN)
1062 return -EINVAL;
1063
1064 switch (hdr_type) {
1065 case IWM_UMAC_CMD_EEPROM_TYPE_READ:
1066 memcpy(iwm->eeprom + hdr_offset, eeprom_proxy->buf, hdr_len);
1067 break;
1068 case IWM_UMAC_CMD_EEPROM_TYPE_WRITE:
1069 default:
1070 return -ENOTSUPP;
1071 }
1072
1073 return 0;
1074}
1075
1076static int iwm_ntf_channel_info_list(struct iwm_priv *iwm, u8 *buf,
1077 unsigned long buf_size,
1078 struct iwm_wifi_cmd *cmd)
1079{
1080 struct iwm_umac_cmd_get_channel_list *ch_list =
1081 (struct iwm_umac_cmd_get_channel_list *)
1082 (buf + sizeof(struct iwm_umac_wifi_in_hdr));
1083 struct wiphy *wiphy = iwm_to_wiphy(iwm);
1084 struct ieee80211_supported_band *band;
1085 int i;
1086
1087 band = wiphy->bands[IEEE80211_BAND_2GHZ];
1088
1089 for (i = 0; i < band->n_channels; i++) {
1090 unsigned long ch_mask_0 =
1091 le32_to_cpu(ch_list->ch[0].channels_mask);
1092 unsigned long ch_mask_2 =
1093 le32_to_cpu(ch_list->ch[2].channels_mask);
1094
1095 if (!test_bit(i, &ch_mask_0))
1096 band->channels[i].flags |= IEEE80211_CHAN_DISABLED;
1097
1098 if (!test_bit(i, &ch_mask_2))
1099 band->channels[i].flags |= IEEE80211_CHAN_NO_IBSS;
1100 }
1101
1102 band = wiphy->bands[IEEE80211_BAND_5GHZ];
1103
1104 for (i = 0; i < min(band->n_channels, 32); i++) {
1105 unsigned long ch_mask_1 =
1106 le32_to_cpu(ch_list->ch[1].channels_mask);
1107 unsigned long ch_mask_3 =
1108 le32_to_cpu(ch_list->ch[3].channels_mask);
1109
1110 if (!test_bit(i, &ch_mask_1))
1111 band->channels[i].flags |= IEEE80211_CHAN_DISABLED;
1112
1113 if (!test_bit(i, &ch_mask_3))
1114 band->channels[i].flags |= IEEE80211_CHAN_NO_IBSS;
1115 }
1116
1117 return 0;
1118}
1119
1120static int iwm_ntf_stop_resume_tx(struct iwm_priv *iwm, u8 *buf,
1121 unsigned long buf_size,
1122 struct iwm_wifi_cmd *cmd)
1123{
1124 struct iwm_umac_notif_stop_resume_tx *stp_res_tx =
1125 (struct iwm_umac_notif_stop_resume_tx *)buf;
1126 struct iwm_sta_info *sta_info;
1127 struct iwm_tid_info *tid_info;
1128 u8 sta_id = STA_ID_N_COLOR_ID(stp_res_tx->sta_id);
1129 u16 tid_msk = le16_to_cpu(stp_res_tx->stop_resume_tid_msk);
1130 int bit, ret = 0;
1131 bool stop = false;
1132
1133 IWM_DBG_NTF(iwm, DBG, "stop/resume notification:\n"
1134 "\tflags: 0x%x\n"
1135 "\tSTA id: %d\n"
1136 "\tTID bitmask: 0x%x\n",
1137 stp_res_tx->flags, stp_res_tx->sta_id,
1138 stp_res_tx->stop_resume_tid_msk);
1139
1140 if (stp_res_tx->flags & UMAC_STOP_TX_FLAG)
1141 stop = true;
1142
1143 sta_info = &iwm->sta_table[sta_id];
1144 if (!sta_info->valid) {
1145 IWM_ERR(iwm, "Stoping an invalid STA: %d %d\n",
1146 sta_id, stp_res_tx->sta_id);
1147 return -EINVAL;
1148 }
1149
1150 for_each_set_bit(bit, (unsigned long *)&tid_msk, IWM_UMAC_TID_NR) {
1151 tid_info = &sta_info->tid_info[bit];
1152
1153 mutex_lock(&tid_info->mutex);
1154 tid_info->stopped = stop;
1155 mutex_unlock(&tid_info->mutex);
1156
1157 if (!stop) {
1158 struct iwm_tx_queue *txq;
1159 int queue = iwm_tid_to_queue(bit);
1160
1161 if (queue < 0)
1162 continue;
1163
1164 txq = &iwm->txq[queue];
1165 /*
1166 * If we resume, we have to move our SKBs
1167 * back to the tx queue and queue some work.
1168 */
1169 spin_lock_bh(&txq->lock);
1170 skb_queue_splice_init(&txq->queue, &txq->stopped_queue);
1171 spin_unlock_bh(&txq->lock);
1172
1173 queue_work(txq->wq, &txq->worker);
1174 }
1175
1176 }
1177
1178 /* We send an ACK only for the stop case */
1179 if (stop)
1180 ret = iwm_send_umac_stop_resume_tx(iwm, stp_res_tx);
1181
1182 return ret;
1183}
1184
1185static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf,
1186 unsigned long buf_size,
1187 struct iwm_wifi_cmd *cmd)
1188{
1189 struct iwm_umac_wifi_if *hdr;
1190
1191 if (cmd == NULL) {
1192 IWM_ERR(iwm, "Couldn't find expected wifi command\n");
1193 return -EINVAL;
1194 }
1195
1196 hdr = (struct iwm_umac_wifi_if *)cmd->buf.payload;
1197
1198 IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: "
1199 "oid is 0x%x\n", hdr->oid);
1200
1201 set_bit(hdr->oid, &iwm->wifi_ntfy[0]);
1202 wake_up_interruptible(&iwm->wifi_ntfy_queue);
1203
1204 switch (hdr->oid) {
1205 case UMAC_WIFI_IF_CMD_SET_PROFILE:
1206 iwm->umac_profile_active = true;
1207 break;
1208 default:
1209 break;
1210 }
1211
1212 return 0;
1213}
1214
1215#define CT_KILL_DELAY (30 * HZ)
1216static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf,
1217 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
1218{
1219 struct wiphy *wiphy = iwm_to_wiphy(iwm);
1220 struct iwm_lmac_card_state *state = (struct iwm_lmac_card_state *)
1221 (buf + sizeof(struct iwm_umac_wifi_in_hdr));
1222 u32 flags = le32_to_cpu(state->flags);
1223
1224 IWM_INFO(iwm, "HW RF Kill %s, CT Kill %s\n",
1225 flags & IWM_CARD_STATE_HW_DISABLED ? "ON" : "OFF",
1226 flags & IWM_CARD_STATE_CTKILL_DISABLED ? "ON" : "OFF");
1227
1228 if (flags & IWM_CARD_STATE_CTKILL_DISABLED) {
1229 /*
1230 * We got a CTKILL event: We bring the interface down in
1231 * oder to cool the device down, and try to bring it up
1232 * 30 seconds later. If it's still too hot, we'll go through
1233 * this code path again.
1234 */
1235 cancel_delayed_work_sync(&iwm->ct_kill_delay);
1236 schedule_delayed_work(&iwm->ct_kill_delay, CT_KILL_DELAY);
1237 }
1238
1239 wiphy_rfkill_set_hw_state(wiphy, flags &
1240 (IWM_CARD_STATE_HW_DISABLED |
1241 IWM_CARD_STATE_CTKILL_DISABLED));
1242
1243 return 0;
1244}
1245
1246static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf,
1247 unsigned long buf_size)
1248{
1249 struct iwm_umac_wifi_in_hdr *wifi_hdr;
1250 struct iwm_wifi_cmd *cmd;
1251 u8 source, cmd_id;
1252 u16 seq_num;
1253 u32 count;
1254
1255 wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
1256 cmd_id = wifi_hdr->sw_hdr.cmd.cmd;
1257 source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
1258 if (source >= IWM_SRC_NUM) {
1259 IWM_CRIT(iwm, "invalid source %d\n", source);
1260 return -EINVAL;
1261 }
1262
1263 if (cmd_id == REPLY_RX_MPDU_CMD)
1264 trace_iwm_rx_packet(iwm, buf, buf_size);
1265 else if ((cmd_id == UMAC_NOTIFY_OPCODE_RX_TICKET) &&
1266 (source == UMAC_HDI_IN_SOURCE_FW))
1267 trace_iwm_rx_ticket(iwm, buf, buf_size);
1268 else
1269 trace_iwm_rx_wifi_cmd(iwm, wifi_hdr);
1270
1271 count = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT);
1272 count += sizeof(struct iwm_umac_wifi_in_hdr) -
1273 sizeof(struct iwm_dev_cmd_hdr);
1274 if (count > buf_size) {
1275 IWM_CRIT(iwm, "count %d, buf size:%ld\n", count, buf_size);
1276 return -EINVAL;
1277 }
1278
1279 seq_num = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num);
1280
1281 IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x, seqnum: %d\n",
1282 cmd_id, source, seq_num);
1283
1284 /*
1285 * If this is a response to a previously sent command, there must
1286 * be a pending command for this sequence number.
1287 */
1288 cmd = iwm_get_pending_wifi_cmd(iwm, seq_num);
1289
1290 /* Notify the caller only for sync commands. */
1291 switch (source) {
1292 case UMAC_HDI_IN_SOURCE_FHRX:
1293 if (iwm->lmac_handlers[cmd_id] &&
1294 test_bit(cmd_id, &iwm->lmac_handler_map[0]))
1295 return iwm_notif_send(iwm, cmd, cmd_id, source,
1296 buf, count);
1297 break;
1298 case UMAC_HDI_IN_SOURCE_FW:
1299 if (iwm->umac_handlers[cmd_id] &&
1300 test_bit(cmd_id, &iwm->umac_handler_map[0]))
1301 return iwm_notif_send(iwm, cmd, cmd_id, source,
1302 buf, count);
1303 break;
1304 case UMAC_HDI_IN_SOURCE_UDMA:
1305 break;
1306 }
1307
1308 return iwm_rx_handle_resp(iwm, buf, count, cmd);
1309}
1310
1311int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size,
1312 struct iwm_wifi_cmd *cmd)
1313{
1314 u8 source, cmd_id;
1315 struct iwm_umac_wifi_in_hdr *wifi_hdr;
1316 int ret = 0;
1317
1318 wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
1319 cmd_id = wifi_hdr->sw_hdr.cmd.cmd;
1320
1321 source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
1322
1323 IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x\n", cmd_id, source);
1324
1325 switch (source) {
1326 case UMAC_HDI_IN_SOURCE_FHRX:
1327 if (iwm->lmac_handlers[cmd_id])
1328 ret = iwm->lmac_handlers[cmd_id]
1329 (iwm, buf, buf_size, cmd);
1330 break;
1331 case UMAC_HDI_IN_SOURCE_FW:
1332 if (iwm->umac_handlers[cmd_id])
1333 ret = iwm->umac_handlers[cmd_id]
1334 (iwm, buf, buf_size, cmd);
1335 break;
1336 case UMAC_HDI_IN_SOURCE_UDMA:
1337 ret = -EINVAL;
1338 break;
1339 }
1340
1341 kfree(cmd);
1342
1343 return ret;
1344}
1345
1346static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf,
1347 unsigned long buf_size)
1348{
1349 u8 seq_num;
1350 struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf;
1351 struct iwm_nonwifi_cmd *cmd;
1352
1353 trace_iwm_rx_nonwifi_cmd(iwm, buf, buf_size);
1354 seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM);
1355
1356 /*
1357 * We received a non wifi answer.
1358 * Let's check if there's a pending command for it, and if so
1359 * replace the command payload with the buffer, and then wake the
1360 * callers up.
1361 * That means we only support synchronised non wifi command response
1362 * schemes.
1363 */
1364 list_for_each_entry(cmd, &iwm->nonwifi_pending_cmd, pending)
1365 if (cmd->seq_num == seq_num) {
1366 cmd->resp_received = true;
1367 cmd->buf.len = buf_size;
1368 memcpy(cmd->buf.hdr, buf, buf_size);
1369 wake_up_interruptible(&iwm->nonwifi_queue);
1370 }
1371
1372 return 0;
1373}
1374
1375static int iwm_rx_handle_umac(struct iwm_priv *iwm, u8 *buf,
1376 unsigned long buf_size)
1377{
1378 int ret = 0;
1379 u8 op_code;
1380 unsigned long buf_offset = 0;
1381 struct iwm_udma_in_hdr *hdr;
1382
1383 /*
1384 * To allow for a more efficient bus usage, UMAC
1385 * messages are encapsulated into UDMA ones. This
1386 * way we can have several UMAC messages in one bus
1387 * transfer.
1388 * A UDMA frame size is always aligned on 16 bytes,
1389 * and a UDMA frame must not start with a UMAC_PAD_TERMINAL
1390 * word. This is how we parse a bus frame into several
1391 * UDMA ones.
1392 */
1393 while (buf_offset < buf_size) {
1394
1395 hdr = (struct iwm_udma_in_hdr *)(buf + buf_offset);
1396
1397 if (iwm_rx_check_udma_hdr(hdr) < 0) {
1398 IWM_DBG_RX(iwm, DBG, "End of frame\n");
1399 break;
1400 }
1401
1402 op_code = GET_VAL32(hdr->cmd, UMAC_HDI_IN_CMD_OPCODE);
1403
1404 IWM_DBG_RX(iwm, DBG, "Op code: 0x%x\n", op_code);
1405
1406 if (op_code == UMAC_HDI_IN_OPCODE_WIFI) {
1407 ret |= iwm_rx_handle_wifi(iwm, buf + buf_offset,
1408 buf_size - buf_offset);
1409 } else if (op_code < UMAC_HDI_IN_OPCODE_NONWIFI_MAX) {
1410 if (GET_VAL32(hdr->cmd,
1411 UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG) !=
1412 UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG) {
1413 IWM_ERR(iwm, "Incorrect hw signature\n");
1414 return -EINVAL;
1415 }
1416 ret |= iwm_rx_handle_nonwifi(iwm, buf + buf_offset,
1417 buf_size - buf_offset);
1418 } else {
1419 IWM_ERR(iwm, "Invalid RX opcode: 0x%x\n", op_code);
1420 ret |= -EINVAL;
1421 }
1422
1423 buf_offset += iwm_rx_resp_size(hdr);
1424 }
1425
1426 return ret;
1427}
1428
1429int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size)
1430{
1431 struct iwm_udma_in_hdr *hdr;
1432
1433 hdr = (struct iwm_udma_in_hdr *)buf;
1434
1435 switch (le32_to_cpu(hdr->cmd)) {
1436 case UMAC_REBOOT_BARKER:
1437 if (test_bit(IWM_STATUS_READY, &iwm->status)) {
1438 IWM_ERR(iwm, "Unexpected BARKER\n");
1439
1440 schedule_work(&iwm->reset_worker);
1441
1442 return 0;
1443 }
1444
1445 return iwm_notif_send(iwm, NULL, IWM_BARKER_REBOOT_NOTIFICATION,
1446 IWM_SRC_UDMA, buf, buf_size);
1447 case UMAC_ACK_BARKER:
1448 return iwm_notif_send(iwm, NULL, IWM_ACK_BARKER_NOTIFICATION,
1449 IWM_SRC_UDMA, NULL, 0);
1450 default:
1451 IWM_DBG_RX(iwm, DBG, "Received cmd: 0x%x\n", hdr->cmd);
1452 return iwm_rx_handle_umac(iwm, buf, buf_size);
1453 }
1454
1455 return 0;
1456}
1457
1458static const iwm_handler iwm_umac_handlers[] =
1459{
1460 [UMAC_NOTIFY_OPCODE_ERROR] = iwm_ntf_error,
1461 [UMAC_NOTIFY_OPCODE_ALIVE] = iwm_ntf_umac_alive,
1462 [UMAC_NOTIFY_OPCODE_INIT_COMPLETE] = iwm_ntf_init_complete,
1463 [UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS] = iwm_ntf_wifi_status,
1464 [UMAC_NOTIFY_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_mlme,
1465 [UMAC_NOTIFY_OPCODE_PAGE_DEALLOC] = iwm_ntf_tx_credit_update,
1466 [UMAC_NOTIFY_OPCODE_RX_TICKET] = iwm_ntf_rx_ticket,
1467 [UMAC_CMD_OPCODE_RESET] = iwm_ntf_umac_reset,
1468 [UMAC_NOTIFY_OPCODE_STATS] = iwm_ntf_statistics,
1469 [UMAC_CMD_OPCODE_EEPROM_PROXY] = iwm_ntf_eeprom_proxy,
1470 [UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST] = iwm_ntf_channel_info_list,
1471 [UMAC_CMD_OPCODE_STOP_RESUME_STA_TX] = iwm_ntf_stop_resume_tx,
1472 [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet,
1473 [UMAC_CMD_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_wifi_if_wrapper,
1474};
1475
1476static const iwm_handler iwm_lmac_handlers[] =
1477{
1478 [REPLY_TX] = iwm_ntf_tx,
1479 [REPLY_ALIVE] = iwm_ntf_lmac_version,
1480 [CALIBRATION_RES_NOTIFICATION] = iwm_ntf_calib_res,
1481 [CALIBRATION_COMPLETE_NOTIFICATION] = iwm_ntf_calib_complete,
1482 [CALIBRATION_CFG_CMD] = iwm_ntf_calib_cfg,
1483 [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet,
1484 [CARD_STATE_NOTIFICATION] = iwm_ntf_card_state,
1485};
1486
1487void iwm_rx_setup_handlers(struct iwm_priv *iwm)
1488{
1489 iwm->umac_handlers = (iwm_handler *) iwm_umac_handlers;
1490 iwm->lmac_handlers = (iwm_handler *) iwm_lmac_handlers;
1491}
1492
1493static void iwm_remove_iv(struct sk_buff *skb, u32 hdr_total_len)
1494{
1495 struct ieee80211_hdr *hdr;
1496 unsigned int hdr_len;
1497
1498 hdr = (struct ieee80211_hdr *)skb->data;
1499
1500 if (!ieee80211_has_protected(hdr->frame_control))
1501 return;
1502
1503 hdr_len = ieee80211_hdrlen(hdr->frame_control);
1504 if (hdr_total_len <= hdr_len)
1505 return;
1506
1507 memmove(skb->data + (hdr_total_len - hdr_len), skb->data, hdr_len);
1508 skb_pull(skb, (hdr_total_len - hdr_len));
1509}
1510
1511static void iwm_rx_adjust_packet(struct iwm_priv *iwm,
1512 struct iwm_rx_packet *packet,
1513 struct iwm_rx_ticket_node *ticket_node)
1514{
1515 u32 payload_offset = 0, payload_len;
1516 struct iwm_rx_ticket *ticket = ticket_node->ticket;
1517 struct iwm_rx_mpdu_hdr *mpdu_hdr;
1518 struct ieee80211_hdr *hdr;
1519
1520 mpdu_hdr = (struct iwm_rx_mpdu_hdr *)packet->skb->data;
1521 payload_offset += sizeof(struct iwm_rx_mpdu_hdr);
1522 /* Padding is 0 or 2 bytes */
1523 payload_len = le16_to_cpu(mpdu_hdr->len) +
1524 (le16_to_cpu(ticket->flags) & IWM_RX_TICKET_PAD_SIZE_MSK);
1525 payload_len -= ticket->tail_len;
1526
1527 IWM_DBG_RX(iwm, DBG, "Packet adjusted, len:%d, offset:%d, "
1528 "ticket offset:%d ticket tail len:%d\n",
1529 payload_len, payload_offset, ticket->payload_offset,
1530 ticket->tail_len);
1531
1532 IWM_HEXDUMP(iwm, DBG, RX, "RAW: ", packet->skb->data, packet->skb->len);
1533
1534 skb_pull(packet->skb, payload_offset);
1535 skb_trim(packet->skb, payload_len);
1536
1537 iwm_remove_iv(packet->skb, ticket->payload_offset);
1538
1539 hdr = (struct ieee80211_hdr *) packet->skb->data;
1540 if (ieee80211_is_data_qos(hdr->frame_control)) {
1541 /* UMAC handed QOS_DATA frame with 2 padding bytes appended
1542 * to the qos_ctl field in IEEE 802.11 headers. */
1543 memmove(packet->skb->data + IEEE80211_QOS_CTL_LEN + 2,
1544 packet->skb->data,
1545 ieee80211_hdrlen(hdr->frame_control) -
1546 IEEE80211_QOS_CTL_LEN);
1547 hdr = (struct ieee80211_hdr *) skb_pull(packet->skb,
1548 IEEE80211_QOS_CTL_LEN + 2);
1549 hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
1550 }
1551
1552 IWM_HEXDUMP(iwm, DBG, RX, "ADJUSTED: ",
1553 packet->skb->data, packet->skb->len);
1554}
1555
1556static void classify8023(struct sk_buff *skb)
1557{
1558 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1559
1560 if (ieee80211_is_data_qos(hdr->frame_control)) {
1561 u8 *qc = ieee80211_get_qos_ctl(hdr);
1562 /* frame has qos control */
1563 skb->priority = *qc & IEEE80211_QOS_CTL_TID_MASK;
1564 } else {
1565 skb->priority = 0;
1566 }
1567}
1568
1569static void iwm_rx_process_amsdu(struct iwm_priv *iwm, struct sk_buff *skb)
1570{
1571 struct wireless_dev *wdev = iwm_to_wdev(iwm);
1572 struct net_device *ndev = iwm_to_ndev(iwm);
1573 struct sk_buff_head list;
1574 struct sk_buff *frame;
1575
1576 IWM_HEXDUMP(iwm, DBG, RX, "A-MSDU: ", skb->data, skb->len);
1577
1578 __skb_queue_head_init(&list);
1579 ieee80211_amsdu_to_8023s(skb, &list, ndev->dev_addr, wdev->iftype, 0,
1580 true);
1581
1582 while ((frame = __skb_dequeue(&list))) {
1583 ndev->stats.rx_packets++;
1584 ndev->stats.rx_bytes += frame->len;
1585
1586 frame->protocol = eth_type_trans(frame, ndev);
1587 frame->ip_summed = CHECKSUM_NONE;
1588 memset(frame->cb, 0, sizeof(frame->cb));
1589
1590 if (netif_rx_ni(frame) == NET_RX_DROP) {
1591 IWM_ERR(iwm, "Packet dropped\n");
1592 ndev->stats.rx_dropped++;
1593 }
1594 }
1595}
1596
1597static void iwm_rx_process_packet(struct iwm_priv *iwm,
1598 struct iwm_rx_packet *packet,
1599 struct iwm_rx_ticket_node *ticket_node)
1600{
1601 int ret;
1602 struct sk_buff *skb = packet->skb;
1603 struct wireless_dev *wdev = iwm_to_wdev(iwm);
1604 struct net_device *ndev = iwm_to_ndev(iwm);
1605
1606 IWM_DBG_RX(iwm, DBG, "Processing packet ID %d\n", packet->id);
1607
1608 switch (le16_to_cpu(ticket_node->ticket->action)) {
1609 case IWM_RX_TICKET_RELEASE:
1610 IWM_DBG_RX(iwm, DBG, "RELEASE packet\n");
1611
1612 iwm_rx_adjust_packet(iwm, packet, ticket_node);
1613 skb->dev = iwm_to_ndev(iwm);
1614 classify8023(skb);
1615
1616 if (le16_to_cpu(ticket_node->ticket->flags) &
1617 IWM_RX_TICKET_AMSDU_MSK) {
1618 iwm_rx_process_amsdu(iwm, skb);
1619 break;
1620 }
1621
1622 ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype);
1623 if (ret < 0) {
1624 IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - "
1625 "%d\n", ret);
1626 kfree_skb(packet->skb);
1627 break;
1628 }
1629
1630 IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len);
1631
1632 ndev->stats.rx_packets++;
1633 ndev->stats.rx_bytes += skb->len;
1634
1635 skb->protocol = eth_type_trans(skb, ndev);
1636 skb->ip_summed = CHECKSUM_NONE;
1637 memset(skb->cb, 0, sizeof(skb->cb));
1638
1639 if (netif_rx_ni(skb) == NET_RX_DROP) {
1640 IWM_ERR(iwm, "Packet dropped\n");
1641 ndev->stats.rx_dropped++;
1642 }
1643 break;
1644 case IWM_RX_TICKET_DROP:
1645 IWM_DBG_RX(iwm, DBG, "DROP packet: 0x%x\n",
1646 le16_to_cpu(ticket_node->ticket->flags));
1647 kfree_skb(packet->skb);
1648 break;
1649 default:
1650 IWM_ERR(iwm, "Unknown ticket action: %d\n",
1651 le16_to_cpu(ticket_node->ticket->action));
1652 kfree_skb(packet->skb);
1653 }
1654
1655 kfree(packet);
1656 iwm_rx_ticket_node_free(ticket_node);
1657}
1658
1659/*
1660 * Rx data processing:
1661 *
1662 * We're receiving Rx packet from the LMAC, and Rx ticket from
1663 * the UMAC.
1664 * To forward a target data packet upstream (i.e. to the
1665 * kernel network stack), we must have received an Rx ticket
1666 * that tells us we're allowed to release this packet (ticket
1667 * action is IWM_RX_TICKET_RELEASE). The Rx ticket also indicates,
1668 * among other things, where valid data actually starts in the Rx
1669 * packet.
1670 */
1671void iwm_rx_worker(struct work_struct *work)
1672{
1673 struct iwm_priv *iwm;
1674 struct iwm_rx_ticket_node *ticket, *next;
1675
1676 iwm = container_of(work, struct iwm_priv, rx_worker);
1677
1678 /*
1679 * We go through the tickets list and if there is a pending
1680 * packet for it, we push it upstream.
1681 * We stop whenever a ticket is missing its packet, as we're
1682 * supposed to send the packets in order.
1683 */
1684 spin_lock(&iwm->ticket_lock);
1685 list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) {
1686 struct iwm_rx_packet *packet =
1687 iwm_rx_packet_get(iwm, le16_to_cpu(ticket->ticket->id));
1688
1689 if (!packet) {
1690 IWM_DBG_RX(iwm, DBG, "Skip rx_work: Wait for ticket %d "
1691 "to be handled first\n",
1692 le16_to_cpu(ticket->ticket->id));
1693 break;
1694 }
1695
1696 list_del(&ticket->node);
1697 iwm_rx_process_packet(iwm, packet, ticket);
1698 }
1699 spin_unlock(&iwm->ticket_lock);
1700}
1701
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.h b/drivers/net/wireless/iwmc3200wifi/rx.h
deleted file mode 100644
index da0db91cee59..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/rx.h
+++ /dev/null
@@ -1,60 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef __IWM_RX_H__
40#define __IWM_RX_H__
41
42#include <linux/skbuff.h>
43
44#include "umac.h"
45
46struct iwm_rx_ticket_node {
47 struct list_head node;
48 struct iwm_rx_ticket *ticket;
49};
50
51struct iwm_rx_packet {
52 struct list_head node;
53 u16 id;
54 struct sk_buff *skb;
55 unsigned long pkt_size;
56};
57
58void iwm_rx_worker(struct work_struct *work);
59
60#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c
deleted file mode 100644
index 0042f204b07f..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/sdio.c
+++ /dev/null
@@ -1,509 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39/*
40 * This is the SDIO bus specific hooks for iwm.
41 * It also is the module's entry point.
42 *
43 * Interesting code paths:
44 * iwm_sdio_probe() (Called by an SDIO bus scan)
45 * -> iwm_if_alloc() (netdev.c)
46 * -> iwm_wdev_alloc() (cfg80211.c, allocates and register our wiphy)
47 * -> wiphy_new()
48 * -> wiphy_register()
49 * -> alloc_netdev_mq()
50 * -> register_netdev()
51 *
52 * iwm_sdio_remove()
53 * -> iwm_if_free() (netdev.c)
54 * -> unregister_netdev()
55 * -> iwm_wdev_free() (cfg80211.c)
56 * -> wiphy_unregister()
57 * -> wiphy_free()
58 *
59 * iwm_sdio_isr() (called in process context from the SDIO core code)
60 * -> queue_work(.., isr_worker)
61 * -- [async] --> iwm_sdio_isr_worker()
62 * -> iwm_rx_handle()
63 */
64
65#include <linux/kernel.h>
66#include <linux/module.h>
67#include <linux/slab.h>
68#include <linux/netdevice.h>
69#include <linux/debugfs.h>
70#include <linux/mmc/sdio_ids.h>
71#include <linux/mmc/sdio.h>
72#include <linux/mmc/sdio_func.h>
73
74#include "iwm.h"
75#include "debug.h"
76#include "bus.h"
77#include "sdio.h"
78
79static void iwm_sdio_isr_worker(struct work_struct *work)
80{
81 struct iwm_sdio_priv *hw;
82 struct iwm_priv *iwm;
83 struct iwm_rx_info *rx_info;
84 struct sk_buff *skb;
85 u8 *rx_buf;
86 unsigned long rx_size;
87
88 hw = container_of(work, struct iwm_sdio_priv, isr_worker);
89 iwm = hw_to_iwm(hw);
90
91 while (!skb_queue_empty(&iwm->rx_list)) {
92 skb = skb_dequeue(&iwm->rx_list);
93 rx_info = skb_to_rx_info(skb);
94 rx_size = rx_info->rx_size;
95 rx_buf = skb->data;
96
97 IWM_HEXDUMP(iwm, DBG, SDIO, "RX: ", rx_buf, rx_size);
98 if (iwm_rx_handle(iwm, rx_buf, rx_size) < 0)
99 IWM_WARN(iwm, "RX error\n");
100
101 kfree_skb(skb);
102 }
103}
104
105static void iwm_sdio_isr(struct sdio_func *func)
106{
107 struct iwm_priv *iwm;
108 struct iwm_sdio_priv *hw;
109 struct iwm_rx_info *rx_info;
110 struct sk_buff *skb;
111 unsigned long buf_size, read_size;
112 int ret;
113 u8 val;
114
115 hw = sdio_get_drvdata(func);
116 iwm = hw_to_iwm(hw);
117
118 buf_size = hw->blk_size;
119
120 /* We're checking the status */
121 val = sdio_readb(func, IWM_SDIO_INTR_STATUS_ADDR, &ret);
122 if (val == 0 || ret < 0) {
123 IWM_ERR(iwm, "Wrong INTR_STATUS\n");
124 return;
125 }
126
127 /* See if we have free buffers */
128 if (skb_queue_len(&iwm->rx_list) > IWM_RX_LIST_SIZE) {
129 IWM_ERR(iwm, "No buffer for more Rx frames\n");
130 return;
131 }
132
133 /* We first read the transaction size */
134 read_size = sdio_readb(func, IWM_SDIO_INTR_GET_SIZE_ADDR + 1, &ret);
135 read_size = read_size << 8;
136
137 if (ret < 0) {
138 IWM_ERR(iwm, "Couldn't read the xfer size\n");
139 return;
140 }
141
142 /* We need to clear the INT register */
143 sdio_writeb(func, 1, IWM_SDIO_INTR_CLEAR_ADDR, &ret);
144 if (ret < 0) {
145 IWM_ERR(iwm, "Couldn't clear the INT register\n");
146 return;
147 }
148
149 while (buf_size < read_size)
150 buf_size <<= 1;
151
152 skb = dev_alloc_skb(buf_size);
153 if (!skb) {
154 IWM_ERR(iwm, "Couldn't alloc RX skb\n");
155 return;
156 }
157 rx_info = skb_to_rx_info(skb);
158 rx_info->rx_size = read_size;
159 rx_info->rx_buf_size = buf_size;
160
161 /* Now we can read the actual buffer */
162 ret = sdio_memcpy_fromio(func, skb_put(skb, read_size),
163 IWM_SDIO_DATA_ADDR, read_size);
164
165 /* The skb is put on a driver's specific Rx SKB list */
166 skb_queue_tail(&iwm->rx_list, skb);
167
168 /* We can now schedule the actual worker */
169 queue_work(hw->isr_wq, &hw->isr_worker);
170}
171
172static void iwm_sdio_rx_free(struct iwm_sdio_priv *hw)
173{
174 struct iwm_priv *iwm = hw_to_iwm(hw);
175
176 flush_workqueue(hw->isr_wq);
177
178 skb_queue_purge(&iwm->rx_list);
179}
180
181/* Bus ops */
182static int if_sdio_enable(struct iwm_priv *iwm)
183{
184 struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
185 int ret;
186
187 sdio_claim_host(hw->func);
188
189 ret = sdio_enable_func(hw->func);
190 if (ret) {
191 IWM_ERR(iwm, "Couldn't enable the device: is TOP driver "
192 "loaded and functional?\n");
193 goto release_host;
194 }
195
196 iwm_reset(iwm);
197
198 ret = sdio_claim_irq(hw->func, iwm_sdio_isr);
199 if (ret) {
200 IWM_ERR(iwm, "Failed to claim irq: %d\n", ret);
201 goto release_host;
202 }
203
204 sdio_writeb(hw->func, 1, IWM_SDIO_INTR_ENABLE_ADDR, &ret);
205 if (ret < 0) {
206 IWM_ERR(iwm, "Couldn't enable INTR: %d\n", ret);
207 goto release_irq;
208 }
209
210 sdio_release_host(hw->func);
211
212 IWM_DBG_SDIO(iwm, INFO, "IWM SDIO enable\n");
213
214 return 0;
215
216 release_irq:
217 sdio_release_irq(hw->func);
218 release_host:
219 sdio_release_host(hw->func);
220
221 return ret;
222}
223
224static int if_sdio_disable(struct iwm_priv *iwm)
225{
226 struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
227 int ret;
228
229 sdio_claim_host(hw->func);
230 sdio_writeb(hw->func, 0, IWM_SDIO_INTR_ENABLE_ADDR, &ret);
231 if (ret < 0)
232 IWM_WARN(iwm, "Couldn't disable INTR: %d\n", ret);
233
234 sdio_release_irq(hw->func);
235 sdio_disable_func(hw->func);
236 sdio_release_host(hw->func);
237
238 iwm_sdio_rx_free(hw);
239
240 iwm_reset(iwm);
241
242 IWM_DBG_SDIO(iwm, INFO, "IWM SDIO disable\n");
243
244 return 0;
245}
246
247static int if_sdio_send_chunk(struct iwm_priv *iwm, u8 *buf, int count)
248{
249 struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
250 int aligned_count = ALIGN(count, hw->blk_size);
251 int ret;
252
253 if ((unsigned long)buf & 0x3) {
254 IWM_ERR(iwm, "buf <%p> is not dword aligned\n", buf);
255 /* TODO: Is this a hardware limitation? use get_unligned */
256 return -EINVAL;
257 }
258
259 sdio_claim_host(hw->func);
260 ret = sdio_memcpy_toio(hw->func, IWM_SDIO_DATA_ADDR, buf,
261 aligned_count);
262 sdio_release_host(hw->func);
263
264 return ret;
265}
266
267static ssize_t iwm_debugfs_sdio_read(struct file *filp, char __user *buffer,
268 size_t count, loff_t *ppos)
269{
270 struct iwm_priv *iwm = filp->private_data;
271 struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
272 char *buf;
273 u8 cccr;
274 int buf_len = 4096, ret;
275 size_t len = 0;
276
277 if (*ppos != 0)
278 return 0;
279 if (count < sizeof(buf))
280 return -ENOSPC;
281
282 buf = kzalloc(buf_len, GFP_KERNEL);
283 if (!buf)
284 return -ENOMEM;
285
286 sdio_claim_host(hw->func);
287
288 cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IOEx, &ret);
289 if (ret) {
290 IWM_ERR(iwm, "Could not read SDIO_CCCR_IOEx\n");
291 goto err;
292 }
293 len += snprintf(buf + len, buf_len - len, "CCCR_IOEx: 0x%x\n", cccr);
294
295 cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IORx, &ret);
296 if (ret) {
297 IWM_ERR(iwm, "Could not read SDIO_CCCR_IORx\n");
298 goto err;
299 }
300 len += snprintf(buf + len, buf_len - len, "CCCR_IORx: 0x%x\n", cccr);
301
302
303 cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IENx, &ret);
304 if (ret) {
305 IWM_ERR(iwm, "Could not read SDIO_CCCR_IENx\n");
306 goto err;
307 }
308 len += snprintf(buf + len, buf_len - len, "CCCR_IENx: 0x%x\n", cccr);
309
310
311 cccr = sdio_f0_readb(hw->func, SDIO_CCCR_INTx, &ret);
312 if (ret) {
313 IWM_ERR(iwm, "Could not read SDIO_CCCR_INTx\n");
314 goto err;
315 }
316 len += snprintf(buf + len, buf_len - len, "CCCR_INTx: 0x%x\n", cccr);
317
318
319 cccr = sdio_f0_readb(hw->func, SDIO_CCCR_ABORT, &ret);
320 if (ret) {
321 IWM_ERR(iwm, "Could not read SDIO_CCCR_ABORTx\n");
322 goto err;
323 }
324 len += snprintf(buf + len, buf_len - len, "CCCR_ABORT: 0x%x\n", cccr);
325
326 cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IF, &ret);
327 if (ret) {
328 IWM_ERR(iwm, "Could not read SDIO_CCCR_IF\n");
329 goto err;
330 }
331 len += snprintf(buf + len, buf_len - len, "CCCR_IF: 0x%x\n", cccr);
332
333
334 cccr = sdio_f0_readb(hw->func, SDIO_CCCR_CAPS, &ret);
335 if (ret) {
336 IWM_ERR(iwm, "Could not read SDIO_CCCR_CAPS\n");
337 goto err;
338 }
339 len += snprintf(buf + len, buf_len - len, "CCCR_CAPS: 0x%x\n", cccr);
340
341 cccr = sdio_f0_readb(hw->func, SDIO_CCCR_CIS, &ret);
342 if (ret) {
343 IWM_ERR(iwm, "Could not read SDIO_CCCR_CIS\n");
344 goto err;
345 }
346 len += snprintf(buf + len, buf_len - len, "CCCR_CIS: 0x%x\n", cccr);
347
348 ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
349err:
350 sdio_release_host(hw->func);
351
352 kfree(buf);
353
354 return ret;
355}
356
357static const struct file_operations iwm_debugfs_sdio_fops = {
358 .owner = THIS_MODULE,
359 .open = simple_open,
360 .read = iwm_debugfs_sdio_read,
361 .llseek = default_llseek,
362};
363
364static void if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir)
365{
366 struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
367
368 hw->cccr_dentry = debugfs_create_file("cccr", 0200,
369 parent_dir, iwm,
370 &iwm_debugfs_sdio_fops);
371}
372
373static void if_sdio_debugfs_exit(struct iwm_priv *iwm)
374{
375 struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
376
377 debugfs_remove(hw->cccr_dentry);
378}
379
380static struct iwm_if_ops if_sdio_ops = {
381 .enable = if_sdio_enable,
382 .disable = if_sdio_disable,
383 .send_chunk = if_sdio_send_chunk,
384 .debugfs_init = if_sdio_debugfs_init,
385 .debugfs_exit = if_sdio_debugfs_exit,
386 .umac_name = "iwmc3200wifi-umac-sdio.bin",
387 .calib_lmac_name = "iwmc3200wifi-calib-sdio.bin",
388 .lmac_name = "iwmc3200wifi-lmac-sdio.bin",
389};
390MODULE_FIRMWARE("iwmc3200wifi-umac-sdio.bin");
391MODULE_FIRMWARE("iwmc3200wifi-calib-sdio.bin");
392MODULE_FIRMWARE("iwmc3200wifi-lmac-sdio.bin");
393
394static int iwm_sdio_probe(struct sdio_func *func,
395 const struct sdio_device_id *id)
396{
397 struct iwm_priv *iwm;
398 struct iwm_sdio_priv *hw;
399 struct device *dev = &func->dev;
400 int ret;
401
402 /* check if TOP has already initialized the card */
403 sdio_claim_host(func);
404 ret = sdio_enable_func(func);
405 if (ret) {
406 dev_err(dev, "wait for TOP to enable the device\n");
407 sdio_release_host(func);
408 return ret;
409 }
410
411 ret = sdio_set_block_size(func, IWM_SDIO_BLK_SIZE);
412
413 sdio_disable_func(func);
414 sdio_release_host(func);
415
416 if (ret < 0) {
417 dev_err(dev, "Failed to set block size: %d\n", ret);
418 return ret;
419 }
420
421 iwm = iwm_if_alloc(sizeof(struct iwm_sdio_priv), dev, &if_sdio_ops);
422 if (IS_ERR(iwm)) {
423 dev_err(dev, "allocate SDIO interface failed\n");
424 return PTR_ERR(iwm);
425 }
426
427 hw = iwm_private(iwm);
428 hw->iwm = iwm;
429
430 iwm_debugfs_init(iwm);
431
432 sdio_set_drvdata(func, hw);
433
434 hw->func = func;
435 hw->blk_size = IWM_SDIO_BLK_SIZE;
436
437 hw->isr_wq = create_singlethread_workqueue(KBUILD_MODNAME "_sdio");
438 if (!hw->isr_wq) {
439 ret = -ENOMEM;
440 goto debugfs_exit;
441 }
442
443 INIT_WORK(&hw->isr_worker, iwm_sdio_isr_worker);
444
445 ret = iwm_if_add(iwm);
446 if (ret) {
447 dev_err(dev, "add SDIO interface failed\n");
448 goto destroy_wq;
449 }
450
451 dev_info(dev, "IWM SDIO probe\n");
452
453 return 0;
454
455 destroy_wq:
456 destroy_workqueue(hw->isr_wq);
457 debugfs_exit:
458 iwm_debugfs_exit(iwm);
459 iwm_if_free(iwm);
460 return ret;
461}
462
463static void iwm_sdio_remove(struct sdio_func *func)
464{
465 struct iwm_sdio_priv *hw = sdio_get_drvdata(func);
466 struct iwm_priv *iwm = hw_to_iwm(hw);
467 struct device *dev = &func->dev;
468
469 iwm_if_remove(iwm);
470 destroy_workqueue(hw->isr_wq);
471 iwm_debugfs_exit(iwm);
472 iwm_if_free(iwm);
473
474 sdio_set_drvdata(func, NULL);
475
476 dev_info(dev, "IWM SDIO remove\n");
477}
478
479static const struct sdio_device_id iwm_sdio_ids[] = {
480 /* Global/AGN SKU */
481 { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 0x1403) },
482 /* BGN SKU */
483 { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 0x1408) },
484 { /* end: all zeroes */ },
485};
486MODULE_DEVICE_TABLE(sdio, iwm_sdio_ids);
487
488static struct sdio_driver iwm_sdio_driver = {
489 .name = "iwm_sdio",
490 .id_table = iwm_sdio_ids,
491 .probe = iwm_sdio_probe,
492 .remove = iwm_sdio_remove,
493};
494
495static int __init iwm_sdio_init_module(void)
496{
497 return sdio_register_driver(&iwm_sdio_driver);
498}
499
500static void __exit iwm_sdio_exit_module(void)
501{
502 sdio_unregister_driver(&iwm_sdio_driver);
503}
504
505module_init(iwm_sdio_init_module);
506module_exit(iwm_sdio_exit_module);
507
508MODULE_LICENSE("GPL");
509MODULE_AUTHOR(IWM_COPYRIGHT " " IWM_AUTHOR);
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.h b/drivers/net/wireless/iwmc3200wifi/sdio.h
deleted file mode 100644
index aab6b6892e45..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/sdio.h
+++ /dev/null
@@ -1,64 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef __IWM_SDIO_H__
40#define __IWM_SDIO_H__
41
42#define IWM_SDIO_DATA_ADDR 0x0
43#define IWM_SDIO_INTR_ENABLE_ADDR 0x14
44#define IWM_SDIO_INTR_STATUS_ADDR 0x13
45#define IWM_SDIO_INTR_CLEAR_ADDR 0x13
46#define IWM_SDIO_INTR_GET_SIZE_ADDR 0x2C
47
48#define IWM_SDIO_BLK_SIZE 256
49
50#define iwm_to_if_sdio(i) (struct iwm_sdio_priv *)(iwm->private)
51
52struct iwm_sdio_priv {
53 struct sdio_func *func;
54 struct iwm_priv *iwm;
55
56 struct workqueue_struct *isr_wq;
57 struct work_struct isr_worker;
58
59 struct dentry *cccr_dentry;
60
61 unsigned int blk_size;
62};
63
64#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/trace.c b/drivers/net/wireless/iwmc3200wifi/trace.c
deleted file mode 100644
index 904d36f22311..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/trace.c
+++ /dev/null
@@ -1,3 +0,0 @@
1#include "iwm.h"
2#define CREATE_TRACE_POINTS
3#include "trace.h"
diff --git a/drivers/net/wireless/iwmc3200wifi/trace.h b/drivers/net/wireless/iwmc3200wifi/trace.h
deleted file mode 100644
index f5f7070b7e22..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/trace.h
+++ /dev/null
@@ -1,283 +0,0 @@
1#if !defined(__IWM_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
2#define __IWM_TRACE_H__
3
4#include <linux/tracepoint.h>
5
6#if !defined(CONFIG_IWM_TRACING)
7#undef TRACE_EVENT
8#define TRACE_EVENT(name, proto, ...) \
9static inline void trace_ ## name(proto) {}
10#endif
11
12#undef TRACE_SYSTEM
13#define TRACE_SYSTEM iwm
14
15#define IWM_ENTRY __array(char, ndev_name, 16)
16#define IWM_ASSIGN strlcpy(__entry->ndev_name, iwm_to_ndev(iwm)->name, 16)
17#define IWM_PR_FMT "%s"
18#define IWM_PR_ARG __entry->ndev_name
19
20TRACE_EVENT(iwm_tx_nonwifi_cmd,
21 TP_PROTO(struct iwm_priv *iwm, struct iwm_udma_out_nonwifi_hdr *hdr),
22
23 TP_ARGS(iwm, hdr),
24
25 TP_STRUCT__entry(
26 IWM_ENTRY
27 __field(u8, opcode)
28 __field(u8, resp)
29 __field(u8, eot)
30 __field(u8, hw)
31 __field(u16, seq)
32 __field(u32, addr)
33 __field(u32, op1)
34 __field(u32, op2)
35 ),
36
37 TP_fast_assign(
38 IWM_ASSIGN;
39 __entry->opcode = GET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE);
40 __entry->resp = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_RESP);
41 __entry->eot = GET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT);
42 __entry->hw = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW);
43 __entry->seq = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM);
44 __entry->addr = le32_to_cpu(hdr->addr);
45 __entry->op1 = le32_to_cpu(hdr->op1_sz);
46 __entry->op2 = le32_to_cpu(hdr->op2);
47 ),
48
49 TP_printk(
50 IWM_PR_FMT " Tx TARGET CMD: opcode 0x%x, resp %d, eot %d, "
51 "hw %d, seq 0x%x, addr 0x%x, op1 0x%x, op2 0x%x",
52 IWM_PR_ARG, __entry->opcode, __entry->resp, __entry->eot,
53 __entry->hw, __entry->seq, __entry->addr, __entry->op1,
54 __entry->op2
55 )
56);
57
58TRACE_EVENT(iwm_tx_wifi_cmd,
59 TP_PROTO(struct iwm_priv *iwm, struct iwm_umac_wifi_out_hdr *hdr),
60
61 TP_ARGS(iwm, hdr),
62
63 TP_STRUCT__entry(
64 IWM_ENTRY
65 __field(u8, opcode)
66 __field(u8, lmac)
67 __field(u8, resp)
68 __field(u8, eot)
69 __field(u8, ra_tid)
70 __field(u8, credit_group)
71 __field(u8, color)
72 __field(u16, seq)
73 ),
74
75 TP_fast_assign(
76 IWM_ASSIGN;
77 __entry->opcode = hdr->sw_hdr.cmd.cmd;
78 __entry->lmac = 0;
79 __entry->seq = __le16_to_cpu(hdr->sw_hdr.cmd.seq_num);
80 __entry->resp = GET_VAL8(hdr->sw_hdr.cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ);
81 __entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR);
82 __entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT);
83 __entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID);
84 __entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP);
85 if (__entry->opcode == UMAC_CMD_OPCODE_WIFI_PASS_THROUGH ||
86 __entry->opcode == UMAC_CMD_OPCODE_WIFI_IF_WRAPPER) {
87 __entry->lmac = 1;
88 __entry->opcode = ((struct iwm_lmac_hdr *)(hdr + 1))->id;
89 }
90 ),
91
92 TP_printk(
93 IWM_PR_FMT " Tx %cMAC CMD: opcode 0x%x, resp %d, eot %d, "
94 "seq 0x%x, sta_color 0x%x, ra_tid 0x%x, credit_group 0x%x",
95 IWM_PR_ARG, __entry->lmac ? 'L' : 'U', __entry->opcode,
96 __entry->resp, __entry->eot, __entry->seq, __entry->color,
97 __entry->ra_tid, __entry->credit_group
98 )
99);
100
101TRACE_EVENT(iwm_tx_packets,
102 TP_PROTO(struct iwm_priv *iwm, u8 *buf, int len),
103
104 TP_ARGS(iwm, buf, len),
105
106 TP_STRUCT__entry(
107 IWM_ENTRY
108 __field(u8, eot)
109 __field(u8, ra_tid)
110 __field(u8, credit_group)
111 __field(u8, color)
112 __field(u16, seq)
113 __field(u8, npkt)
114 __field(u32, bytes)
115 ),
116
117 TP_fast_assign(
118 struct iwm_umac_wifi_out_hdr *hdr =
119 (struct iwm_umac_wifi_out_hdr *)buf;
120
121 IWM_ASSIGN;
122 __entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT);
123 __entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID);
124 __entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP);
125 __entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR);
126 __entry->seq = __le16_to_cpu(hdr->sw_hdr.cmd.seq_num);
127 __entry->npkt = 1;
128 __entry->bytes = len;
129
130 if (!__entry->eot) {
131 int count;
132 u8 *ptr = buf;
133
134 __entry->npkt = 0;
135 while (ptr < buf + len) {
136 count = GET_VAL32(hdr->sw_hdr.meta_data,
137 UMAC_FW_CMD_BYTE_COUNT);
138 ptr += ALIGN(sizeof(*hdr) + count, 16);
139 hdr = (struct iwm_umac_wifi_out_hdr *)ptr;
140 __entry->npkt++;
141 }
142 }
143 ),
144
145 TP_printk(
146 IWM_PR_FMT " Tx %spacket: eot %d, seq 0x%x, sta_color 0x%x, "
147 "ra_tid 0x%x, credit_group 0x%x, embedded_packets %d, %d bytes",
148 IWM_PR_ARG, !__entry->eot ? "concatenated " : "",
149 __entry->eot, __entry->seq, __entry->color, __entry->ra_tid,
150 __entry->credit_group, __entry->npkt, __entry->bytes
151 )
152);
153
154TRACE_EVENT(iwm_rx_nonwifi_cmd,
155 TP_PROTO(struct iwm_priv *iwm, void *buf, int len),
156
157 TP_ARGS(iwm, buf, len),
158
159 TP_STRUCT__entry(
160 IWM_ENTRY
161 __field(u8, opcode)
162 __field(u16, seq)
163 __field(u32, len)
164 ),
165
166 TP_fast_assign(
167 struct iwm_udma_in_hdr *hdr = buf;
168
169 IWM_ASSIGN;
170 __entry->opcode = GET_VAL32(hdr->cmd, UDMA_HDI_IN_NW_CMD_OPCODE);
171 __entry->seq = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM);
172 __entry->len = len;
173 ),
174
175 TP_printk(
176 IWM_PR_FMT " Rx TARGET RESP: opcode 0x%x, seq 0x%x, len 0x%x",
177 IWM_PR_ARG, __entry->opcode, __entry->seq, __entry->len
178 )
179);
180
181TRACE_EVENT(iwm_rx_wifi_cmd,
182 TP_PROTO(struct iwm_priv *iwm, struct iwm_umac_wifi_in_hdr *hdr),
183
184 TP_ARGS(iwm, hdr),
185
186 TP_STRUCT__entry(
187 IWM_ENTRY
188 __field(u8, cmd)
189 __field(u8, source)
190 __field(u16, seq)
191 __field(u32, count)
192 ),
193
194 TP_fast_assign(
195 IWM_ASSIGN;
196 __entry->cmd = hdr->sw_hdr.cmd.cmd;
197 __entry->source = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
198 __entry->count = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT);
199 __entry->seq = le16_to_cpu(hdr->sw_hdr.cmd.seq_num);
200 ),
201
202 TP_printk(
203 IWM_PR_FMT " Rx %s RESP: cmd 0x%x, seq 0x%x, count 0x%x",
204 IWM_PR_ARG, __entry->source == UMAC_HDI_IN_SOURCE_FHRX ? "LMAC" :
205 __entry->source == UMAC_HDI_IN_SOURCE_FW ? "UMAC" : "UDMA",
206 __entry->cmd, __entry->seq, __entry->count
207 )
208);
209
210#define iwm_ticket_action_symbol \
211 { IWM_RX_TICKET_DROP, "DROP" }, \
212 { IWM_RX_TICKET_RELEASE, "RELEASE" }, \
213 { IWM_RX_TICKET_SNIFFER, "SNIFFER" }, \
214 { IWM_RX_TICKET_ENQUEUE, "ENQUEUE" }
215
216TRACE_EVENT(iwm_rx_ticket,
217 TP_PROTO(struct iwm_priv *iwm, void *buf, int len),
218
219 TP_ARGS(iwm, buf, len),
220
221 TP_STRUCT__entry(
222 IWM_ENTRY
223 __field(u8, action)
224 __field(u8, reason)
225 __field(u16, id)
226 __field(u16, flags)
227 ),
228
229 TP_fast_assign(
230 struct iwm_rx_ticket *ticket =
231 ((struct iwm_umac_notif_rx_ticket *)buf)->tickets;
232
233 IWM_ASSIGN;
234 __entry->id = le16_to_cpu(ticket->id);
235 __entry->action = le16_to_cpu(ticket->action);
236 __entry->flags = le16_to_cpu(ticket->flags);
237 __entry->reason = (__entry->flags & IWM_RX_TICKET_DROP_REASON_MSK) >> IWM_RX_TICKET_DROP_REASON_POS;
238 ),
239
240 TP_printk(
241 IWM_PR_FMT " Rx ticket: id 0x%x, action %s, %s 0x%x%s",
242 IWM_PR_ARG, __entry->id,
243 __print_symbolic(__entry->action, iwm_ticket_action_symbol),
244 __entry->reason ? "reason" : "flags",
245 __entry->reason ? __entry->reason : __entry->flags,
246 __entry->flags & IWM_RX_TICKET_AMSDU_MSK ? ", AMSDU frame" : ""
247 )
248);
249
250TRACE_EVENT(iwm_rx_packet,
251 TP_PROTO(struct iwm_priv *iwm, void *buf, int len),
252
253 TP_ARGS(iwm, buf, len),
254
255 TP_STRUCT__entry(
256 IWM_ENTRY
257 __field(u8, source)
258 __field(u16, id)
259 __field(u32, len)
260 ),
261
262 TP_fast_assign(
263 struct iwm_umac_wifi_in_hdr *hdr = buf;
264
265 IWM_ASSIGN;
266 __entry->source = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
267 __entry->id = le16_to_cpu(hdr->sw_hdr.cmd.seq_num);
268 __entry->len = len - sizeof(*hdr);
269 ),
270
271 TP_printk(
272 IWM_PR_FMT " Rx %s packet: id 0x%x, %d bytes",
273 IWM_PR_ARG, __entry->source == UMAC_HDI_IN_SOURCE_FHRX ?
274 "LMAC" : "UMAC", __entry->id, __entry->len
275 )
276);
277#endif
278
279#undef TRACE_INCLUDE_PATH
280#define TRACE_INCLUDE_PATH .
281#undef TRACE_INCLUDE_FILE
282#define TRACE_INCLUDE_FILE trace
283#include <trace/define_trace.h>
diff --git a/drivers/net/wireless/iwmc3200wifi/tx.c b/drivers/net/wireless/iwmc3200wifi/tx.c
deleted file mode 100644
index be98074c0608..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/tx.c
+++ /dev/null
@@ -1,529 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39/*
40 * iwm Tx theory of operation:
41 *
42 * 1) We receive a 802.3 frame from the stack
43 * 2) We convert it to a 802.11 frame [iwm_xmit_frame]
44 * 3) We queue it to its corresponding tx queue [iwm_xmit_frame]
45 * 4) We schedule the tx worker. There is one worker per tx
46 * queue. [iwm_xmit_frame]
47 * 5) The tx worker is scheduled
48 * 6) We go through every queued skb on the tx queue, and for each
49 * and every one of them: [iwm_tx_worker]
50 * a) We check if we have enough Tx credits (see below for a Tx
51 * credits description) for the frame length. [iwm_tx_worker]
52 * b) If we do, we aggregate the Tx frame into a UDMA one, by
53 * concatenating one REPLY_TX command per Tx frame. [iwm_tx_worker]
54 * c) When we run out of credits, or when we reach the maximum
55 * concatenation size, we actually send the concatenated UDMA
56 * frame. [iwm_tx_worker]
57 *
58 * When we run out of Tx credits, the skbs are filling the tx queue,
59 * and eventually we will stop the netdev queue. [iwm_tx_worker]
60 * The tx queue is emptied as we're getting new tx credits, by
61 * scheduling the tx_worker. [iwm_tx_credit_inc]
62 * The netdev queue is started again when we have enough tx credits,
63 * and when our tx queue has some reasonable amout of space available
64 * (i.e. half of the max size). [iwm_tx_worker]
65 */
66
67#include <linux/slab.h>
68#include <linux/skbuff.h>
69#include <linux/netdevice.h>
70#include <linux/ieee80211.h>
71
72#include "iwm.h"
73#include "debug.h"
74#include "commands.h"
75#include "hal.h"
76#include "umac.h"
77#include "bus.h"
78
79#define IWM_UMAC_PAGE_ALLOC_WRAP 0xffff
80
81#define BYTES_TO_PAGES(n) (1 + ((n) >> ilog2(IWM_UMAC_PAGE_SIZE)) - \
82 (((n) & (IWM_UMAC_PAGE_SIZE - 1)) == 0))
83
84#define pool_id_to_queue(id) ((id < IWM_TX_CMD_QUEUE) ? id : id - 1)
85#define queue_to_pool_id(q) ((q < IWM_TX_CMD_QUEUE) ? q : q + 1)
86
87/* require to hold tx_credit lock */
88static int iwm_tx_credit_get(struct iwm_tx_credit *tx_credit, int id)
89{
90 struct pool_entry *pool = &tx_credit->pools[id];
91 struct spool_entry *spool = &tx_credit->spools[pool->sid];
92 int spool_pages;
93
94 /* number of pages can be taken from spool by this pool */
95 spool_pages = spool->max_pages - spool->alloc_pages +
96 max(pool->min_pages - pool->alloc_pages, 0);
97
98 return min(pool->max_pages - pool->alloc_pages, spool_pages);
99}
100
101static bool iwm_tx_credit_ok(struct iwm_priv *iwm, int id, int nb)
102{
103 u32 npages = BYTES_TO_PAGES(nb);
104
105 if (npages <= iwm_tx_credit_get(&iwm->tx_credit, id))
106 return 1;
107
108 set_bit(id, &iwm->tx_credit.full_pools_map);
109
110 IWM_DBG_TX(iwm, DBG, "LINK: stop txq[%d], available credit: %d\n",
111 pool_id_to_queue(id),
112 iwm_tx_credit_get(&iwm->tx_credit, id));
113
114 return 0;
115}
116
117void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages)
118{
119 struct pool_entry *pool;
120 struct spool_entry *spool;
121 int freed_pages;
122 int queue;
123
124 BUG_ON(id >= IWM_MACS_OUT_GROUPS);
125
126 pool = &iwm->tx_credit.pools[id];
127 spool = &iwm->tx_credit.spools[pool->sid];
128
129 freed_pages = total_freed_pages - pool->total_freed_pages;
130 IWM_DBG_TX(iwm, DBG, "Free %d pages for pool[%d]\n", freed_pages, id);
131
132 if (!freed_pages) {
133 IWM_DBG_TX(iwm, DBG, "No pages are freed by UMAC\n");
134 return;
135 } else if (freed_pages < 0)
136 freed_pages += IWM_UMAC_PAGE_ALLOC_WRAP + 1;
137
138 if (pool->alloc_pages > pool->min_pages) {
139 int spool_pages = pool->alloc_pages - pool->min_pages;
140 spool_pages = min(spool_pages, freed_pages);
141 spool->alloc_pages -= spool_pages;
142 }
143
144 pool->alloc_pages -= freed_pages;
145 pool->total_freed_pages = total_freed_pages;
146
147 IWM_DBG_TX(iwm, DBG, "Pool[%d] pages alloc: %d, total_freed: %d, "
148 "Spool[%d] pages alloc: %d\n", id, pool->alloc_pages,
149 pool->total_freed_pages, pool->sid, spool->alloc_pages);
150
151 if (test_bit(id, &iwm->tx_credit.full_pools_map) &&
152 (pool->alloc_pages < pool->max_pages / 2)) {
153 clear_bit(id, &iwm->tx_credit.full_pools_map);
154
155 queue = pool_id_to_queue(id);
156
157 IWM_DBG_TX(iwm, DBG, "LINK: start txq[%d], available "
158 "credit: %d\n", queue,
159 iwm_tx_credit_get(&iwm->tx_credit, id));
160 queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker);
161 }
162}
163
164static void iwm_tx_credit_dec(struct iwm_priv *iwm, int id, int alloc_pages)
165{
166 struct pool_entry *pool;
167 struct spool_entry *spool;
168 int spool_pages;
169
170 IWM_DBG_TX(iwm, DBG, "Allocate %d pages for pool[%d]\n",
171 alloc_pages, id);
172
173 BUG_ON(id >= IWM_MACS_OUT_GROUPS);
174
175 pool = &iwm->tx_credit.pools[id];
176 spool = &iwm->tx_credit.spools[pool->sid];
177
178 spool_pages = pool->alloc_pages + alloc_pages - pool->min_pages;
179
180 if (pool->alloc_pages >= pool->min_pages)
181 spool->alloc_pages += alloc_pages;
182 else if (spool_pages > 0)
183 spool->alloc_pages += spool_pages;
184
185 pool->alloc_pages += alloc_pages;
186
187 IWM_DBG_TX(iwm, DBG, "Pool[%d] pages alloc: %d, total_freed: %d, "
188 "Spool[%d] pages alloc: %d\n", id, pool->alloc_pages,
189 pool->total_freed_pages, pool->sid, spool->alloc_pages);
190}
191
192int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb)
193{
194 u32 npages = BYTES_TO_PAGES(nb);
195 int ret = 0;
196
197 spin_lock(&iwm->tx_credit.lock);
198
199 if (!iwm_tx_credit_ok(iwm, id, nb)) {
200 IWM_DBG_TX(iwm, DBG, "No credit available for pool[%d]\n", id);
201 ret = -ENOSPC;
202 goto out;
203 }
204
205 iwm_tx_credit_dec(iwm, id, npages);
206
207 out:
208 spin_unlock(&iwm->tx_credit.lock);
209 return ret;
210}
211
212/*
213 * Since we're on an SDIO or USB bus, we are not sharing memory
214 * for storing to be transmitted frames. The host needs to push
215 * them upstream. As a consequence there needs to be a way for
216 * the target to let us know if it can actually take more TX frames
217 * or not. This is what Tx credits are for.
218 *
219 * For each Tx HW queue, we have a Tx pool, and then we have one
220 * unique super pool (spool), which is actually a global pool of
221 * all the UMAC pages.
222 * For each Tx pool we have a min_pages, a max_pages fields, and a
223 * alloc_pages fields. The alloc_pages tracks the number of pages
224 * currently allocated from the tx pool.
225 * Here are the rules to check if given a tx frame we have enough
226 * tx credits for it:
227 * 1) We translate the frame length into a number of UMAC pages.
228 * Let's call them n_pages.
229 * 2) For the corresponding tx pool, we check if n_pages +
230 * pool->alloc_pages is higher than pool->min_pages. min_pages
231 * represent a set of pre-allocated pages on the tx pool. If
232 * that's the case, then we need to allocate those pages from
233 * the spool. We can do so until we reach spool->max_pages.
234 * 3) Each tx pool is not allowed to allocate more than pool->max_pages
235 * from the spool, so once we're over min_pages, we can allocate
236 * pages from the spool, but not more than max_pages.
237 *
238 * When the tx code path needs to send a tx frame, it checks first
239 * if it has enough tx credits, following those rules. [iwm_tx_credit_get]
240 * If it does, it then updates the pool and spool counters and
241 * then send the frame. [iwm_tx_credit_alloc and iwm_tx_credit_dec]
242 * On the other side, when the UMAC is done transmitting frames, it
243 * will send a credit update notification to the host. This is when
244 * the pool and spool counters gets to be decreased. [iwm_tx_credit_inc,
245 * called from rx.c:iwm_ntf_tx_credit_update]
246 *
247 */
248void iwm_tx_credit_init_pools(struct iwm_priv *iwm,
249 struct iwm_umac_notif_alive *alive)
250{
251 int i, sid, pool_pages;
252
253 spin_lock(&iwm->tx_credit.lock);
254
255 iwm->tx_credit.pool_nr = le16_to_cpu(alive->page_grp_count);
256 iwm->tx_credit.full_pools_map = 0;
257 memset(&iwm->tx_credit.spools[0], 0, sizeof(struct spool_entry));
258
259 IWM_DBG_TX(iwm, DBG, "Pools number is %d\n", iwm->tx_credit.pool_nr);
260
261 for (i = 0; i < iwm->tx_credit.pool_nr; i++) {
262 __le32 page_grp_state = alive->page_grp_state[i];
263
264 iwm->tx_credit.pools[i].id = GET_VAL32(page_grp_state,
265 UMAC_ALIVE_PAGE_STS_GRP_NUM);
266 iwm->tx_credit.pools[i].sid = GET_VAL32(page_grp_state,
267 UMAC_ALIVE_PAGE_STS_SGRP_NUM);
268 iwm->tx_credit.pools[i].min_pages = GET_VAL32(page_grp_state,
269 UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE);
270 iwm->tx_credit.pools[i].max_pages = GET_VAL32(page_grp_state,
271 UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE);
272 iwm->tx_credit.pools[i].alloc_pages = 0;
273 iwm->tx_credit.pools[i].total_freed_pages = 0;
274
275 sid = iwm->tx_credit.pools[i].sid;
276 pool_pages = iwm->tx_credit.pools[i].min_pages;
277
278 if (iwm->tx_credit.spools[sid].max_pages == 0) {
279 iwm->tx_credit.spools[sid].id = sid;
280 iwm->tx_credit.spools[sid].max_pages =
281 GET_VAL32(page_grp_state,
282 UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE);
283 iwm->tx_credit.spools[sid].alloc_pages = 0;
284 }
285
286 iwm->tx_credit.spools[sid].alloc_pages += pool_pages;
287
288 IWM_DBG_TX(iwm, DBG, "Pool idx: %d, id: %d, sid: %d, capacity "
289 "min: %d, max: %d, pool alloc: %d, total_free: %d, "
290 "super poll alloc: %d\n",
291 i, iwm->tx_credit.pools[i].id,
292 iwm->tx_credit.pools[i].sid,
293 iwm->tx_credit.pools[i].min_pages,
294 iwm->tx_credit.pools[i].max_pages,
295 iwm->tx_credit.pools[i].alloc_pages,
296 iwm->tx_credit.pools[i].total_freed_pages,
297 iwm->tx_credit.spools[sid].alloc_pages);
298 }
299
300 spin_unlock(&iwm->tx_credit.lock);
301}
302
303#define IWM_UDMA_HDR_LEN sizeof(struct iwm_umac_wifi_out_hdr)
304
305static __le16 iwm_tx_build_packet(struct iwm_priv *iwm, struct sk_buff *skb,
306 int pool_id, u8 *buf)
307{
308 struct iwm_umac_wifi_out_hdr *hdr = (struct iwm_umac_wifi_out_hdr *)buf;
309 struct iwm_udma_wifi_cmd udma_cmd;
310 struct iwm_umac_cmd umac_cmd;
311 struct iwm_tx_info *tx_info = skb_to_tx_info(skb);
312
313 udma_cmd.count = cpu_to_le16(skb->len +
314 sizeof(struct iwm_umac_fw_cmd_hdr));
315 /* set EOP to 0 here. iwm_udma_wifi_hdr_set_eop() will be
316 * called later to set EOP for the last packet. */
317 udma_cmd.eop = 0;
318 udma_cmd.credit_group = pool_id;
319 udma_cmd.ra_tid = tx_info->sta << 4 | tx_info->tid;
320 udma_cmd.lmac_offset = 0;
321
322 umac_cmd.id = REPLY_TX;
323 umac_cmd.count = cpu_to_le16(skb->len);
324 umac_cmd.color = tx_info->color;
325 umac_cmd.resp = 0;
326 umac_cmd.seq_num = cpu_to_le16(iwm_alloc_wifi_cmd_seq(iwm));
327
328 iwm_build_udma_wifi_hdr(iwm, &hdr->hw_hdr, &udma_cmd);
329 iwm_build_umac_hdr(iwm, &hdr->sw_hdr, &umac_cmd);
330
331 memcpy(buf + sizeof(*hdr), skb->data, skb->len);
332
333 return umac_cmd.seq_num;
334}
335
336static int iwm_tx_send_concat_packets(struct iwm_priv *iwm,
337 struct iwm_tx_queue *txq)
338{
339 int ret;
340
341 if (!txq->concat_count)
342 return 0;
343
344 IWM_DBG_TX(iwm, DBG, "Send concatenated Tx: queue %d, %d bytes\n",
345 txq->id, txq->concat_count);
346
347 /* mark EOP for the last packet */
348 iwm_udma_wifi_hdr_set_eop(iwm, txq->concat_ptr, 1);
349
350 trace_iwm_tx_packets(iwm, txq->concat_buf, txq->concat_count);
351 ret = iwm_bus_send_chunk(iwm, txq->concat_buf, txq->concat_count);
352
353 txq->concat_count = 0;
354 txq->concat_ptr = txq->concat_buf;
355
356 return ret;
357}
358
359void iwm_tx_worker(struct work_struct *work)
360{
361 struct iwm_priv *iwm;
362 struct iwm_tx_info *tx_info = NULL;
363 struct sk_buff *skb;
364 struct iwm_tx_queue *txq;
365 struct iwm_sta_info *sta_info;
366 struct iwm_tid_info *tid_info;
367 int cmdlen, ret, pool_id;
368
369 txq = container_of(work, struct iwm_tx_queue, worker);
370 iwm = container_of(txq, struct iwm_priv, txq[txq->id]);
371
372 pool_id = queue_to_pool_id(txq->id);
373
374 while (!test_bit(pool_id, &iwm->tx_credit.full_pools_map) &&
375 !skb_queue_empty(&txq->queue)) {
376
377 spin_lock_bh(&txq->lock);
378 skb = skb_dequeue(&txq->queue);
379 spin_unlock_bh(&txq->lock);
380
381 tx_info = skb_to_tx_info(skb);
382 sta_info = &iwm->sta_table[tx_info->sta];
383 if (!sta_info->valid) {
384 IWM_ERR(iwm, "Trying to send a frame to unknown STA\n");
385 kfree_skb(skb);
386 continue;
387 }
388
389 tid_info = &sta_info->tid_info[tx_info->tid];
390
391 mutex_lock(&tid_info->mutex);
392
393 /*
394 * If the RAxTID is stopped, we queue the skb to the stopped
395 * queue.
396 * Whenever we'll get a UMAC notification to resume the tx flow
397 * for this RAxTID, we'll merge back the stopped queue into the
398 * regular queue. See iwm_ntf_stop_resume_tx() from rx.c.
399 */
400 if (tid_info->stopped) {
401 IWM_DBG_TX(iwm, DBG, "%dx%d stopped\n",
402 tx_info->sta, tx_info->tid);
403 spin_lock_bh(&txq->lock);
404 skb_queue_tail(&txq->stopped_queue, skb);
405 spin_unlock_bh(&txq->lock);
406
407 mutex_unlock(&tid_info->mutex);
408 continue;
409 }
410
411 cmdlen = IWM_UDMA_HDR_LEN + skb->len;
412
413 IWM_DBG_TX(iwm, DBG, "Tx frame on queue %d: skb: 0x%p, sta: "
414 "%d, color: %d\n", txq->id, skb, tx_info->sta,
415 tx_info->color);
416
417 if (txq->concat_count + cmdlen > IWM_HAL_CONCATENATE_BUF_SIZE)
418 iwm_tx_send_concat_packets(iwm, txq);
419
420 ret = iwm_tx_credit_alloc(iwm, pool_id, cmdlen);
421 if (ret) {
422 IWM_DBG_TX(iwm, DBG, "not enough tx_credit for queue "
423 "%d, Tx worker stopped\n", txq->id);
424 spin_lock_bh(&txq->lock);
425 skb_queue_head(&txq->queue, skb);
426 spin_unlock_bh(&txq->lock);
427
428 mutex_unlock(&tid_info->mutex);
429 break;
430 }
431
432 txq->concat_ptr = txq->concat_buf + txq->concat_count;
433 tid_info->last_seq_num =
434 iwm_tx_build_packet(iwm, skb, pool_id, txq->concat_ptr);
435 txq->concat_count += ALIGN(cmdlen, 16);
436
437 mutex_unlock(&tid_info->mutex);
438
439 kfree_skb(skb);
440 }
441
442 iwm_tx_send_concat_packets(iwm, txq);
443
444 if (__netif_subqueue_stopped(iwm_to_ndev(iwm), txq->id) &&
445 !test_bit(pool_id, &iwm->tx_credit.full_pools_map) &&
446 (skb_queue_len(&txq->queue) < IWM_TX_LIST_SIZE / 2)) {
447 IWM_DBG_TX(iwm, DBG, "LINK: start netif_subqueue[%d]", txq->id);
448 netif_wake_subqueue(iwm_to_ndev(iwm), txq->id);
449 }
450}
451
452int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
453{
454 struct iwm_priv *iwm = ndev_to_iwm(netdev);
455 struct wireless_dev *wdev = iwm_to_wdev(iwm);
456 struct iwm_tx_info *tx_info;
457 struct iwm_tx_queue *txq;
458 struct iwm_sta_info *sta_info;
459 u8 *dst_addr, sta_id;
460 u16 queue;
461 int ret;
462
463
464 if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
465 IWM_DBG_TX(iwm, DBG, "LINK: stop netif_all_queues: "
466 "not associated\n");
467 netif_tx_stop_all_queues(netdev);
468 goto drop;
469 }
470
471 queue = skb_get_queue_mapping(skb);
472 BUG_ON(queue >= IWM_TX_DATA_QUEUES); /* no iPAN yet */
473
474 txq = &iwm->txq[queue];
475
476 /* No free space for Tx, tx_worker is too slow */
477 if ((skb_queue_len(&txq->queue) > IWM_TX_LIST_SIZE) ||
478 (skb_queue_len(&txq->stopped_queue) > IWM_TX_LIST_SIZE)) {
479 IWM_DBG_TX(iwm, DBG, "LINK: stop netif_subqueue[%d]\n", queue);
480 netif_stop_subqueue(netdev, queue);
481 return NETDEV_TX_BUSY;
482 }
483
484 ret = ieee80211_data_from_8023(skb, netdev->dev_addr, wdev->iftype,
485 iwm->bssid, 0);
486 if (ret) {
487 IWM_ERR(iwm, "build wifi header failed\n");
488 goto drop;
489 }
490
491 dst_addr = ((struct ieee80211_hdr *)(skb->data))->addr1;
492
493 for (sta_id = 0; sta_id < IWM_STA_TABLE_NUM; sta_id++) {
494 sta_info = &iwm->sta_table[sta_id];
495 if (sta_info->valid &&
496 !memcmp(dst_addr, sta_info->addr, ETH_ALEN))
497 break;
498 }
499
500 if (sta_id == IWM_STA_TABLE_NUM) {
501 IWM_ERR(iwm, "STA %pM not found in sta_table, Tx ignored\n",
502 dst_addr);
503 goto drop;
504 }
505
506 tx_info = skb_to_tx_info(skb);
507 tx_info->sta = sta_id;
508 tx_info->color = sta_info->color;
509 /* UMAC uses TID 8 (vs. 0) for non QoS packets */
510 if (sta_info->qos)
511 tx_info->tid = skb->priority;
512 else
513 tx_info->tid = IWM_UMAC_MGMT_TID;
514
515 spin_lock_bh(&iwm->txq[queue].lock);
516 skb_queue_tail(&iwm->txq[queue].queue, skb);
517 spin_unlock_bh(&iwm->txq[queue].lock);
518
519 queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker);
520
521 netdev->stats.tx_packets++;
522 netdev->stats.tx_bytes += skb->len;
523 return NETDEV_TX_OK;
524
525 drop:
526 netdev->stats.tx_dropped++;
527 dev_kfree_skb_any(skb);
528 return NETDEV_TX_OK;
529}
diff --git a/drivers/net/wireless/iwmc3200wifi/umac.h b/drivers/net/wireless/iwmc3200wifi/umac.h
deleted file mode 100644
index 4a137d334a42..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/umac.h
+++ /dev/null
@@ -1,789 +0,0 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef __IWM_UMAC_H__
40#define __IWM_UMAC_H__
41
42struct iwm_udma_in_hdr {
43 __le32 cmd;
44 __le32 size;
45} __packed;
46
47struct iwm_udma_out_nonwifi_hdr {
48 __le32 cmd;
49 __le32 addr;
50 __le32 op1_sz;
51 __le32 op2;
52} __packed;
53
54struct iwm_udma_out_wifi_hdr {
55 __le32 cmd;
56 __le32 meta_data;
57} __packed;
58
59/* Sequence numbering */
60#define UMAC_WIFI_SEQ_NUM_BASE 1
61#define UMAC_WIFI_SEQ_NUM_MAX 0x4000
62#define UMAC_NONWIFI_SEQ_NUM_BASE 1
63#define UMAC_NONWIFI_SEQ_NUM_MAX 0x10
64
65/* MAC address address */
66#define WICO_MAC_ADDRESS_ADDR 0x604008F8
67
68/* RA / TID */
69#define UMAC_HDI_ACT_TBL_IDX_TID_POS 0
70#define UMAC_HDI_ACT_TBL_IDX_TID_SEED 0xF
71
72#define UMAC_HDI_ACT_TBL_IDX_RA_POS 4
73#define UMAC_HDI_ACT_TBL_IDX_RA_SEED 0xF
74
75#define UMAC_HDI_ACT_TBL_IDX_RA_UMAC 0xF
76#define UMAC_HDI_ACT_TBL_IDX_TID_UMAC 0x9
77#define UMAC_HDI_ACT_TBL_IDX_TID_LMAC 0xA
78
79#define UMAC_HDI_ACT_TBL_IDX_HOST_CMD \
80 ((UMAC_HDI_ACT_TBL_IDX_RA_UMAC << UMAC_HDI_ACT_TBL_IDX_RA_POS) |\
81 (UMAC_HDI_ACT_TBL_IDX_TID_UMAC << UMAC_HDI_ACT_TBL_IDX_TID_POS))
82#define UMAC_HDI_ACT_TBL_IDX_UMAC_CMD \
83 ((UMAC_HDI_ACT_TBL_IDX_RA_UMAC << UMAC_HDI_ACT_TBL_IDX_RA_POS) |\
84 (UMAC_HDI_ACT_TBL_IDX_TID_LMAC << UMAC_HDI_ACT_TBL_IDX_TID_POS))
85
86/* STA ID and color */
87#define STA_ID_SEED (0x0f)
88#define STA_ID_POS (0)
89#define STA_ID_MSK (STA_ID_SEED << STA_ID_POS)
90
91#define STA_COLOR_SEED (0x7)
92#define STA_COLOR_POS (4)
93#define STA_COLOR_MSK (STA_COLOR_SEED << STA_COLOR_POS)
94
95#define STA_ID_N_COLOR_COLOR(id_n_color) \
96 (((id_n_color) & STA_COLOR_MSK) >> STA_COLOR_POS)
97#define STA_ID_N_COLOR_ID(id_n_color) \
98 (((id_n_color) & STA_ID_MSK) >> STA_ID_POS)
99
100/* iwm_umac_notif_alive.page_grp_state Group number -- bits [3:0] */
101#define UMAC_ALIVE_PAGE_STS_GRP_NUM_POS 0
102#define UMAC_ALIVE_PAGE_STS_GRP_NUM_SEED 0xF
103
104/* iwm_umac_notif_alive.page_grp_state Super group number -- bits [7:4] */
105#define UMAC_ALIVE_PAGE_STS_SGRP_NUM_POS 4
106#define UMAC_ALIVE_PAGE_STS_SGRP_NUM_SEED 0xF
107
108/* iwm_umac_notif_alive.page_grp_state Group min size -- bits [15:8] */
109#define UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE_POS 8
110#define UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE_SEED 0xFF
111
112/* iwm_umac_notif_alive.page_grp_state Group max size -- bits [23:16] */
113#define UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE_POS 16
114#define UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE_SEED 0xFF
115
116/* iwm_umac_notif_alive.page_grp_state Super group max size -- bits [31:24] */
117#define UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE_POS 24
118#define UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE_SEED 0xFF
119
120/* Barkers */
121#define UMAC_REBOOT_BARKER 0xdeadbeef
122#define UMAC_ACK_BARKER 0xfeedbabe
123#define UMAC_PAD_TERMINAL 0xadadadad
124
125/* UMAC JMP address */
126#define UMAC_MU_FW_INST_DATA_12_ADDR 0xBF0000
127
128/* iwm_umac_hdi_out_hdr.cmd OP code -- bits [3:0] */
129#define UMAC_HDI_OUT_CMD_OPCODE_POS 0
130#define UMAC_HDI_OUT_CMD_OPCODE_SEED 0xF
131
132/* iwm_umac_hdi_out_hdr.cmd End-Of-Transfer -- bits [10:10] */
133#define UMAC_HDI_OUT_CMD_EOT_POS 10
134#define UMAC_HDI_OUT_CMD_EOT_SEED 0x1
135
136/* iwm_umac_hdi_out_hdr.cmd UTFD only usage -- bits [11:11] */
137#define UMAC_HDI_OUT_CMD_UTFD_ONLY_POS 11
138#define UMAC_HDI_OUT_CMD_UTFD_ONLY_SEED 0x1
139
140/* iwm_umac_hdi_out_hdr.cmd Non-WiFi HW sequence number -- bits [12:15] */
141#define UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM_POS 12
142#define UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM_SEED 0xF
143
144/* iwm_umac_hdi_out_hdr.cmd Signature -- bits [31:16] */
145#define UMAC_HDI_OUT_CMD_SIGNATURE_POS 16
146#define UMAC_HDI_OUT_CMD_SIGNATURE_SEED 0xFFFF
147
148/* iwm_umac_hdi_out_hdr.meta_data Byte count -- bits [11:0] */
149#define UMAC_HDI_OUT_BYTE_COUNT_POS 0
150#define UMAC_HDI_OUT_BYTE_COUNT_SEED 0xFFF
151
152/* iwm_umac_hdi_out_hdr.meta_data Credit group -- bits [15:12] */
153#define UMAC_HDI_OUT_CREDIT_GRP_POS 12
154#define UMAC_HDI_OUT_CREDIT_GRP_SEED 0xF
155
156/* iwm_umac_hdi_out_hdr.meta_data RA/TID -- bits [23:16] */
157#define UMAC_HDI_OUT_RATID_POS 16
158#define UMAC_HDI_OUT_RATID_SEED 0xFF
159
160/* iwm_umac_hdi_out_hdr.meta_data LMAC offset -- bits [31:24] */
161#define UMAC_HDI_OUT_LMAC_OFFSET_POS 24
162#define UMAC_HDI_OUT_LMAC_OFFSET_SEED 0xFF
163
164/* Signature */
165#define UMAC_HDI_OUT_SIGNATURE 0xCBBC
166
167/* buffer alignment */
168#define UMAC_HDI_BUF_ALIGN_MSK 0xF
169
170/* iwm_umac_hdi_in_hdr.cmd OP code -- bits [3:0] */
171#define UMAC_HDI_IN_CMD_OPCODE_POS 0
172#define UMAC_HDI_IN_CMD_OPCODE_SEED 0xF
173
174/* iwm_umac_hdi_in_hdr.cmd Non-WiFi API response -- bits [6:4] */
175#define UMAC_HDI_IN_CMD_NON_WIFI_RESP_POS 4
176#define UMAC_HDI_IN_CMD_NON_WIFI_RESP_SEED 0x7
177
178/* iwm_umac_hdi_in_hdr.cmd WiFi API source -- bits [5:4] */
179#define UMAC_HDI_IN_CMD_SOURCE_POS 4
180#define UMAC_HDI_IN_CMD_SOURCE_SEED 0x3
181
182/* iwm_umac_hdi_in_hdr.cmd WiFi API EOT -- bits [6:6] */
183#define UMAC_HDI_IN_CMD_EOT_POS 6
184#define UMAC_HDI_IN_CMD_EOT_SEED 0x1
185
186/* iwm_umac_hdi_in_hdr.cmd timestamp present -- bits [7:7] */
187#define UMAC_HDI_IN_CMD_TIME_STAMP_PRESENT_POS 7
188#define UMAC_HDI_IN_CMD_TIME_STAMP_PRESENT_SEED 0x1
189
190/* iwm_umac_hdi_in_hdr.cmd WiFi Non-last AMSDU -- bits [8:8] */
191#define UMAC_HDI_IN_CMD_NON_LAST_AMSDU_POS 8
192#define UMAC_HDI_IN_CMD_NON_LAST_AMSDU_SEED 0x1
193
194/* iwm_umac_hdi_in_hdr.cmd WiFi HW sequence number -- bits [31:9] */
195#define UMAC_HDI_IN_CMD_HW_SEQ_NUM_POS 9
196#define UMAC_HDI_IN_CMD_HW_SEQ_NUM_SEED 0x7FFFFF
197
198/* iwm_umac_hdi_in_hdr.cmd Non-WiFi HW sequence number -- bits [12:15] */
199#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM_POS 12
200#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM_SEED 0xF
201
202/* iwm_umac_hdi_in_hdr.cmd Non-WiFi HW signature -- bits [16:31] */
203#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG_POS 16
204#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG_SEED 0xFFFF
205
206/* Fixed Non-WiFi signature */
207#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG 0xCBBC
208
209/* IN NTFY op-codes */
210#define UMAC_NOTIFY_OPCODE_ALIVE 0xA1
211#define UMAC_NOTIFY_OPCODE_INIT_COMPLETE 0xA2
212#define UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS 0xA3
213#define UMAC_NOTIFY_OPCODE_ERROR 0xA4
214#define UMAC_NOTIFY_OPCODE_DEBUG 0xA5
215#define UMAC_NOTIFY_OPCODE_WIFI_IF_WRAPPER 0xB0
216#define UMAC_NOTIFY_OPCODE_STATS 0xB1
217#define UMAC_NOTIFY_OPCODE_PAGE_DEALLOC 0xB3
218#define UMAC_NOTIFY_OPCODE_RX_TICKET 0xB4
219#define UMAC_NOTIFY_OPCODE_MAX (UMAC_NOTIFY_OPCODE_RX_TICKET -\
220 UMAC_NOTIFY_OPCODE_ALIVE + 1)
221#define UMAC_NOTIFY_OPCODE_FIRST (UMAC_NOTIFY_OPCODE_ALIVE)
222
223/* HDI OUT OP CODE */
224#define UMAC_HDI_OUT_OPCODE_PING 0x0
225#define UMAC_HDI_OUT_OPCODE_READ 0x1
226#define UMAC_HDI_OUT_OPCODE_WRITE 0x2
227#define UMAC_HDI_OUT_OPCODE_JUMP 0x3
228#define UMAC_HDI_OUT_OPCODE_REBOOT 0x4
229#define UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT 0x5
230#define UMAC_HDI_OUT_OPCODE_READ_PERSISTENT 0x6
231#define UMAC_HDI_OUT_OPCODE_READ_MODIFY_WRITE 0x7
232/* #define UMAC_HDI_OUT_OPCODE_RESERVED 0x8..0xA */
233#define UMAC_HDI_OUT_OPCODE_WRITE_AUX_REG 0xB
234#define UMAC_HDI_OUT_OPCODE_WIFI 0xF
235
236/* HDI IN OP CODE -- Non WiFi*/
237#define UMAC_HDI_IN_OPCODE_PING 0x0
238#define UMAC_HDI_IN_OPCODE_READ 0x1
239#define UMAC_HDI_IN_OPCODE_WRITE 0x2
240#define UMAC_HDI_IN_OPCODE_WRITE_PERSISTENT 0x5
241#define UMAC_HDI_IN_OPCODE_READ_PERSISTENT 0x6
242#define UMAC_HDI_IN_OPCODE_READ_MODIFY_WRITE 0x7
243#define UMAC_HDI_IN_OPCODE_EP_MGMT 0x8
244#define UMAC_HDI_IN_OPCODE_CREDIT_CHANGE 0x9
245#define UMAC_HDI_IN_OPCODE_CTRL_DATABASE 0xA
246#define UMAC_HDI_IN_OPCODE_WRITE_AUX_REG 0xB
247#define UMAC_HDI_IN_OPCODE_NONWIFI_MAX \
248 (UMAC_HDI_IN_OPCODE_WRITE_AUX_REG + 1)
249#define UMAC_HDI_IN_OPCODE_WIFI 0xF
250
251/* HDI IN SOURCE */
252#define UMAC_HDI_IN_SOURCE_FHRX 0x0
253#define UMAC_HDI_IN_SOURCE_UDMA 0x1
254#define UMAC_HDI_IN_SOURCE_FW 0x2
255#define UMAC_HDI_IN_SOURCE_RESERVED 0x3
256
257/* OUT CMD op-codes */
258#define UMAC_CMD_OPCODE_ECHO 0x01
259#define UMAC_CMD_OPCODE_HALT 0x02
260#define UMAC_CMD_OPCODE_RESET 0x03
261#define UMAC_CMD_OPCODE_BULK_EP_INACT_TIMEOUT 0x09
262#define UMAC_CMD_OPCODE_URB_CANCEL_ACK 0x0A
263#define UMAC_CMD_OPCODE_DCACHE_FLUSH 0x0B
264#define UMAC_CMD_OPCODE_EEPROM_PROXY 0x0C
265#define UMAC_CMD_OPCODE_TX_ECHO 0x0D
266#define UMAC_CMD_OPCODE_DBG_MON 0x0E
267#define UMAC_CMD_OPCODE_INTERNAL_TX 0x0F
268#define UMAC_CMD_OPCODE_SET_PARAM_FIX 0x10
269#define UMAC_CMD_OPCODE_SET_PARAM_VAR 0x11
270#define UMAC_CMD_OPCODE_GET_PARAM 0x12
271#define UMAC_CMD_OPCODE_DBG_EVENT_WRAPPER 0x13
272#define UMAC_CMD_OPCODE_TARGET 0x14
273#define UMAC_CMD_OPCODE_STATISTIC_REQUEST 0x15
274#define UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST 0x16
275#define UMAC_CMD_OPCODE_SET_PARAM_LIST 0x17
276#define UMAC_CMD_OPCODE_GET_PARAM_LIST 0x18
277#define UMAC_CMD_OPCODE_STOP_RESUME_STA_TX 0x19
278#define UMAC_CMD_OPCODE_TEST_BLOCK_ACK 0x1A
279
280#define UMAC_CMD_OPCODE_BASE_WRAPPER 0xFA
281#define UMAC_CMD_OPCODE_LMAC_WRAPPER 0xFB
282#define UMAC_CMD_OPCODE_HW_TEST_WRAPPER 0xFC
283#define UMAC_CMD_OPCODE_WIFI_IF_WRAPPER 0xFD
284#define UMAC_CMD_OPCODE_WIFI_WRAPPER 0xFE
285#define UMAC_CMD_OPCODE_WIFI_PASS_THROUGH 0xFF
286
287/* UMAC WiFi interface op-codes */
288#define UMAC_WIFI_IF_CMD_SET_PROFILE 0x11
289#define UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE 0x12
290#define UMAC_WIFI_IF_CMD_SET_EXCLUDE_LIST 0x13
291#define UMAC_WIFI_IF_CMD_SCAN_REQUEST 0x14
292#define UMAC_WIFI_IF_CMD_SCAN_CONFIG 0x15
293#define UMAC_WIFI_IF_CMD_ADD_WEP40_KEY 0x16
294#define UMAC_WIFI_IF_CMD_ADD_WEP104_KEY 0x17
295#define UMAC_WIFI_IF_CMD_ADD_TKIP_KEY 0x18
296#define UMAC_WIFI_IF_CMD_ADD_CCMP_KEY 0x19
297#define UMAC_WIFI_IF_CMD_REMOVE_KEY 0x1A
298#define UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID 0x1B
299#define UMAC_WIFI_IF_CMD_SET_HOST_EXTENDED_IE 0x1C
300#define UMAC_WIFI_IF_CMD_GET_SUPPORTED_CHANNELS 0x1E
301#define UMAC_WIFI_IF_CMD_PMKID_UPDATE 0x1F
302#define UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER 0x20
303
304/* UMAC WiFi interface ports */
305#define UMAC_WIFI_IF_FLG_PORT_DEF 0x00
306#define UMAC_WIFI_IF_FLG_PORT_PAN 0x01
307#define UMAC_WIFI_IF_FLG_PORT_PAN_INVALID WIFI_IF_FLG_PORT_DEF
308
309/* UMAC WiFi interface actions */
310#define UMAC_WIFI_IF_FLG_ACT_GET 0x10
311#define UMAC_WIFI_IF_FLG_ACT_SET 0x20
312
313/* iwm_umac_fw_cmd_hdr.meta_data byte count -- bits [11:0] */
314#define UMAC_FW_CMD_BYTE_COUNT_POS 0
315#define UMAC_FW_CMD_BYTE_COUNT_SEED 0xFFF
316
317/* iwm_umac_fw_cmd_hdr.meta_data status -- bits [15:12] */
318#define UMAC_FW_CMD_STATUS_POS 12
319#define UMAC_FW_CMD_STATUS_SEED 0xF
320
321/* iwm_umac_fw_cmd_hdr.meta_data full TX command by Driver -- bits [16:16] */
322#define UMAC_FW_CMD_TX_DRV_FULL_CMD_POS 16
323#define UMAC_FW_CMD_TX_DRV_FULL_CMD_SEED 0x1
324
325/* iwm_umac_fw_cmd_hdr.meta_data TX command by FW -- bits [17:17] */
326#define UMAC_FW_CMD_TX_FW_CMD_POS 17
327#define UMAC_FW_CMD_TX_FW_CMD_SEED 0x1
328
329/* iwm_umac_fw_cmd_hdr.meta_data TX plaintext mode -- bits [18:18] */
330#define UMAC_FW_CMD_TX_PLAINTEXT_POS 18
331#define UMAC_FW_CMD_TX_PLAINTEXT_SEED 0x1
332
333/* iwm_umac_fw_cmd_hdr.meta_data STA color -- bits [22:20] */
334#define UMAC_FW_CMD_TX_STA_COLOR_POS 20
335#define UMAC_FW_CMD_TX_STA_COLOR_SEED 0x7
336
337/* iwm_umac_fw_cmd_hdr.meta_data TX life time (TU) -- bits [31:24] */
338#define UMAC_FW_CMD_TX_LIFETIME_TU_POS 24
339#define UMAC_FW_CMD_TX_LIFETIME_TU_SEED 0xFF
340
341/* iwm_dev_cmd_hdr.flags Response required -- bits [5:5] */
342#define UMAC_DEV_CMD_FLAGS_RESP_REQ_POS 5
343#define UMAC_DEV_CMD_FLAGS_RESP_REQ_SEED 0x1
344
345/* iwm_dev_cmd_hdr.flags Aborted command -- bits [6:6] */
346#define UMAC_DEV_CMD_FLAGS_ABORT_POS 6
347#define UMAC_DEV_CMD_FLAGS_ABORT_SEED 0x1
348
349/* iwm_dev_cmd_hdr.flags Internal command -- bits [7:7] */
350#define DEV_CMD_FLAGS_FLD_INTERNAL_POS 7
351#define DEV_CMD_FLAGS_FLD_INTERNAL_SEED 0x1
352
353/* Rx */
354/* Rx actions */
355#define IWM_RX_TICKET_DROP 0x0
356#define IWM_RX_TICKET_RELEASE 0x1
357#define IWM_RX_TICKET_SNIFFER 0x2
358#define IWM_RX_TICKET_ENQUEUE 0x3
359
360/* Rx flags */
361#define IWM_RX_TICKET_PAD_SIZE_MSK 0x2
362#define IWM_RX_TICKET_SPECIAL_SNAP_MSK 0x4
363#define IWM_RX_TICKET_AMSDU_MSK 0x8
364#define IWM_RX_TICKET_DROP_REASON_POS 4
365#define IWM_RX_TICKET_DROP_REASON_MSK (0x1F << IWM_RX_TICKET_DROP_REASON_POS)
366
367#define IWM_RX_DROP_NO_DROP 0x0
368#define IWM_RX_DROP_BAD_CRC 0x1
369/* L2P no address match */
370#define IWM_RX_DROP_LMAC_ADDR_FILTER 0x2
371/* Multicast address not in list */
372#define IWM_RX_DROP_MCAST_ADDR_FILTER 0x3
373/* Control frames are not sent to the driver */
374#define IWM_RX_DROP_CTL_FRAME 0x4
375/* Our frame is back */
376#define IWM_RX_DROP_OUR_TX 0x5
377/* Association class filtering */
378#define IWM_RX_DROP_CLASS_FILTER 0x6
379/* Duplicated frame */
380#define IWM_RX_DROP_DUPLICATE_FILTER 0x7
381/* Decryption error */
382#define IWM_RX_DROP_SEC_ERR 0x8
383/* Unencrypted frame while encryption is on */
384#define IWM_RX_DROP_SEC_NO_ENCRYPTION 0x9
385/* Replay check failure */
386#define IWM_RX_DROP_SEC_REPLAY_ERR 0xa
387/* uCode and FW key color mismatch, check before replay */
388#define IWM_RX_DROP_SEC_KEY_COLOR_MISMATCH 0xb
389#define IWM_RX_DROP_SEC_TKIP_COUNTER_MEASURE 0xc
390/* No fragmentations Db is found */
391#define IWM_RX_DROP_FRAG_NO_RESOURCE 0xd
392/* Fragmention Db has seqCtl mismatch Vs. non-1st frag */
393#define IWM_RX_DROP_FRAG_ERR 0xe
394#define IWM_RX_DROP_FRAG_LOST 0xf
395#define IWM_RX_DROP_FRAG_COMPLETE 0x10
396/* Should be handled by UMAC */
397#define IWM_RX_DROP_MANAGEMENT 0x11
398/* STA not found by UMAC */
399#define IWM_RX_DROP_NO_STATION 0x12
400/* NULL or QoS NULL */
401#define IWM_RX_DROP_NULL_DATA 0x13
402#define IWM_RX_DROP_BA_REORDER_OLD_SEQCTL 0x14
403#define IWM_RX_DROP_BA_REORDER_DUPLICATE 0x15
404
405struct iwm_rx_ticket {
406 __le16 action;
407 __le16 id;
408 __le16 flags;
409 u8 payload_offset; /* includes: MAC header, pad, IV */
410 u8 tail_len; /* includes: MIC, ICV, CRC (w/o STATUS) */
411} __packed;
412
413struct iwm_rx_mpdu_hdr {
414 __le16 len;
415 __le16 reserved;
416} __packed;
417
418/* UMAC SW WIFI API */
419
420struct iwm_dev_cmd_hdr {
421 u8 cmd;
422 u8 flags;
423 __le16 seq_num;
424} __packed;
425
426struct iwm_umac_fw_cmd_hdr {
427 __le32 meta_data;
428 struct iwm_dev_cmd_hdr cmd;
429} __packed;
430
431struct iwm_umac_wifi_out_hdr {
432 struct iwm_udma_out_wifi_hdr hw_hdr;
433 struct iwm_umac_fw_cmd_hdr sw_hdr;
434} __packed;
435
436struct iwm_umac_nonwifi_out_hdr {
437 struct iwm_udma_out_nonwifi_hdr hw_hdr;
438} __packed;
439
440struct iwm_umac_wifi_in_hdr {
441 struct iwm_udma_in_hdr hw_hdr;
442 struct iwm_umac_fw_cmd_hdr sw_hdr;
443} __packed;
444
445struct iwm_umac_nonwifi_in_hdr {
446 struct iwm_udma_in_hdr hw_hdr;
447 __le32 time_stamp;
448} __packed;
449
450#define IWM_UMAC_PAGE_SIZE 0x200
451
452/* Notify structures */
453struct iwm_fw_version {
454 u8 minor;
455 u8 major;
456 __le16 id;
457};
458
459struct iwm_fw_build {
460 u8 type;
461 u8 subtype;
462 u8 platform;
463 u8 opt;
464};
465
466struct iwm_fw_alive_hdr {
467 struct iwm_fw_version ver;
468 struct iwm_fw_build build;
469 __le32 os_build;
470 __le32 log_hdr_addr;
471 __le32 log_buf_addr;
472 __le32 sys_timer_addr;
473};
474
475#define WAIT_NOTIF_TIMEOUT (2 * HZ)
476#define SCAN_COMPLETE_TIMEOUT (3 * HZ)
477
478#define UMAC_NTFY_ALIVE_STATUS_ERR 0xDEAD
479#define UMAC_NTFY_ALIVE_STATUS_OK 0xCAFE
480
481#define UMAC_NTFY_INIT_COMPLETE_STATUS_ERR 0xDEAD
482#define UMAC_NTFY_INIT_COMPLETE_STATUS_OK 0xCAFE
483
484#define UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN 0x40
485#define UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN 0x80
486
487#define IWM_MACS_OUT_GROUPS 6
488#define IWM_MACS_OUT_SGROUPS 1
489
490
491#define WIFI_IF_NTFY_ASSOC_START 0x80
492#define WIFI_IF_NTFY_ASSOC_COMPLETE 0x81
493#define WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE 0x82
494#define WIFI_IF_NTFY_CONNECTION_TERMINATED 0x83
495#define WIFI_IF_NTFY_SCAN_COMPLETE 0x84
496#define WIFI_IF_NTFY_STA_TABLE_CHANGE 0x85
497#define WIFI_IF_NTFY_EXTENDED_IE_REQUIRED 0x86
498#define WIFI_IF_NTFY_RADIO_PREEMPTION 0x87
499#define WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED 0x88
500#define WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED 0x89
501#define WIFI_IF_NTFY_LINK_QUALITY_STATISTICS 0x8A
502#define WIFI_IF_NTFY_MGMT_FRAME 0x8B
503
504/* DEBUG INDICATIONS */
505#define WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_START 0xE0
506#define WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_COMPLETE 0xE1
507#define WIFI_DBG_IF_NTFY_SCAN_CHANNEL_START 0xE2
508#define WIFI_DBG_IF_NTFY_SCAN_CHANNEL_RESULT 0xE3
509#define WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_START 0xE4
510#define WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_COMPLETE 0xE5
511#define WIFI_DBG_IF_NTFY_CNCT_ATC_START 0xE6
512#define WIFI_DBG_IF_NTFY_COEX_NOTIFICATION 0xE7
513#define WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP 0xE8
514#define WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP 0xE9
515
516#define WIFI_IF_NTFY_MAX 0xff
517
518/* Notification structures */
519struct iwm_umac_notif_wifi_if {
520 struct iwm_umac_wifi_in_hdr hdr;
521 u8 status;
522 u8 flags;
523 __le16 buf_size;
524} __packed;
525
526#define UMAC_ROAM_REASON_FIRST_SELECTION 0x1
527#define UMAC_ROAM_REASON_AP_DEAUTH 0x2
528#define UMAC_ROAM_REASON_AP_CONNECT_LOST 0x3
529#define UMAC_ROAM_REASON_RSSI 0x4
530#define UMAC_ROAM_REASON_AP_ASSISTED_ROAM 0x5
531#define UMAC_ROAM_REASON_IBSS_COALESCING 0x6
532
533struct iwm_umac_notif_assoc_start {
534 struct iwm_umac_notif_wifi_if mlme_hdr;
535 __le32 roam_reason;
536 u8 bssid[ETH_ALEN];
537 u8 reserved[2];
538} __packed;
539
540#define UMAC_ASSOC_COMPLETE_SUCCESS 0x0
541#define UMAC_ASSOC_COMPLETE_FAILURE 0x1
542
543struct iwm_umac_notif_assoc_complete {
544 struct iwm_umac_notif_wifi_if mlme_hdr;
545 __le32 status;
546 u8 bssid[ETH_ALEN];
547 u8 band;
548 u8 channel;
549} __packed;
550
551#define UMAC_PROFILE_INVALID_ASSOC_TIMEOUT 0x0
552#define UMAC_PROFILE_INVALID_ROAM_TIMEOUT 0x1
553#define UMAC_PROFILE_INVALID_REQUEST 0x2
554#define UMAC_PROFILE_INVALID_RF_PREEMPTED 0x3
555
556struct iwm_umac_notif_profile_invalidate {
557 struct iwm_umac_notif_wifi_if mlme_hdr;
558 __le32 reason;
559} __packed;
560
561#define UMAC_SCAN_RESULT_SUCCESS 0x0
562#define UMAC_SCAN_RESULT_ABORTED 0x1
563#define UMAC_SCAN_RESULT_REJECTED 0x2
564#define UMAC_SCAN_RESULT_FAILED 0x3
565
566struct iwm_umac_notif_scan_complete {
567 struct iwm_umac_notif_wifi_if mlme_hdr;
568 __le32 type;
569 __le32 result;
570 u8 seq_num;
571} __packed;
572
573#define UMAC_OPCODE_ADD_MODIFY 0x0
574#define UMAC_OPCODE_REMOVE 0x1
575#define UMAC_OPCODE_CLEAR_ALL 0x2
576
577#define UMAC_STA_FLAG_QOS 0x1
578
579struct iwm_umac_notif_sta_info {
580 struct iwm_umac_notif_wifi_if mlme_hdr;
581 __le32 opcode;
582 u8 mac_addr[ETH_ALEN];
583 u8 sta_id; /* bits 0-3: station ID, bits 4-7: station color */
584 u8 flags;
585} __packed;
586
587#define UMAC_BAND_2GHZ 0
588#define UMAC_BAND_5GHZ 1
589
590#define UMAC_CHANNEL_WIDTH_20MHZ 0
591#define UMAC_CHANNEL_WIDTH_40MHZ 1
592
593struct iwm_umac_notif_bss_info {
594 struct iwm_umac_notif_wifi_if mlme_hdr;
595 __le32 type;
596 __le32 timestamp;
597 __le16 table_idx;
598 __le16 frame_len;
599 u8 band;
600 u8 channel;
601 s8 rssi;
602 u8 reserved;
603 u8 frame_buf[1];
604} __packed;
605
606#define IWM_BSS_REMOVE_INDEX_MSK 0x0fff
607#define IWM_BSS_REMOVE_FLAGS_MSK 0xfc00
608
609#define IWM_BSS_REMOVE_FLG_AGE 0x1000
610#define IWM_BSS_REMOVE_FLG_TIMEOUT 0x2000
611#define IWM_BSS_REMOVE_FLG_TABLE_FULL 0x4000
612
613struct iwm_umac_notif_bss_removed {
614 struct iwm_umac_notif_wifi_if mlme_hdr;
615 __le32 count;
616 __le16 entries[0];
617} __packed;
618
619struct iwm_umac_notif_mgt_frame {
620 struct iwm_umac_notif_wifi_if mlme_hdr;
621 __le16 len;
622 u8 frame[1];
623} __packed;
624
625struct iwm_umac_notif_alive {
626 struct iwm_umac_wifi_in_hdr hdr;
627 __le16 status;
628 __le16 reserved1;
629 struct iwm_fw_alive_hdr alive_data;
630 __le16 reserved2;
631 __le16 page_grp_count;
632 __le32 page_grp_state[IWM_MACS_OUT_GROUPS];
633} __packed;
634
635struct iwm_umac_notif_init_complete {
636 struct iwm_umac_wifi_in_hdr hdr;
637 __le16 status;
638 __le16 reserved;
639} __packed;
640
641/* error categories */
642enum {
643 UMAC_SYS_ERR_CAT_NONE = 0,
644 UMAC_SYS_ERR_CAT_BOOT,
645 UMAC_SYS_ERR_CAT_UMAC,
646 UMAC_SYS_ERR_CAT_UAXM,
647 UMAC_SYS_ERR_CAT_LMAC,
648 UMAC_SYS_ERR_CAT_MAX
649};
650
651struct iwm_fw_error_hdr {
652 __le32 category;
653 __le32 status;
654 __le32 pc;
655 __le32 blink1;
656 __le32 blink2;
657 __le32 ilink1;
658 __le32 ilink2;
659 __le32 data1;
660 __le32 data2;
661 __le32 line_num;
662 __le32 umac_status;
663 __le32 lmac_status;
664 __le32 sdio_status;
665 __le32 dbm_sample_ctrl;
666 __le32 dbm_buf_base;
667 __le32 dbm_buf_end;
668 __le32 dbm_buf_write_ptr;
669 __le32 dbm_buf_cycle_cnt;
670} __packed;
671
672struct iwm_umac_notif_error {
673 struct iwm_umac_wifi_in_hdr hdr;
674 struct iwm_fw_error_hdr err;
675} __packed;
676
677#define UMAC_DEALLOC_NTFY_CHANGES_CNT_POS 0
678#define UMAC_DEALLOC_NTFY_CHANGES_CNT_SEED 0xff
679#define UMAC_DEALLOC_NTFY_CHANGES_MSK_POS 8
680#define UMAC_DEALLOC_NTFY_CHANGES_MSK_SEED 0xffffff
681#define UMAC_DEALLOC_NTFY_PAGE_CNT_POS 0
682#define UMAC_DEALLOC_NTFY_PAGE_CNT_SEED 0xffffff
683#define UMAC_DEALLOC_NTFY_GROUP_NUM_POS 24
684#define UMAC_DEALLOC_NTFY_GROUP_NUM_SEED 0xf
685
686struct iwm_umac_notif_page_dealloc {
687 struct iwm_umac_wifi_in_hdr hdr;
688 __le32 changes;
689 __le32 grp_info[IWM_MACS_OUT_GROUPS];
690} __packed;
691
692struct iwm_umac_notif_wifi_status {
693 struct iwm_umac_wifi_in_hdr hdr;
694 __le16 status;
695 __le16 reserved;
696} __packed;
697
698struct iwm_umac_notif_rx_ticket {
699 struct iwm_umac_wifi_in_hdr hdr;
700 u8 num_tickets;
701 u8 reserved[3];
702 struct iwm_rx_ticket tickets[1];
703} __packed;
704
705/* Tx/Rx rates window (number of max of last update window per second) */
706#define UMAC_NTF_RATE_SAMPLE_NR 4
707
708/* Max numbers of bits required to go through all antennae in bitmasks */
709#define UMAC_PHY_NUM_CHAINS 3
710
711#define IWM_UMAC_MGMT_TID 8
712#define IWM_UMAC_TID_NR 9 /* 8 TIDs + MGMT */
713
714struct iwm_umac_notif_stats {
715 struct iwm_umac_wifi_in_hdr hdr;
716 __le32 flags;
717 __le32 timestamp;
718 __le16 tid_load[IWM_UMAC_TID_NR + 1]; /* 1 non-QoS + 1 dword align */
719 __le16 tx_rate[UMAC_NTF_RATE_SAMPLE_NR];
720 __le16 rx_rate[UMAC_NTF_RATE_SAMPLE_NR];
721 __le32 chain_energy[UMAC_PHY_NUM_CHAINS];
722 s32 rssi_dbm;
723 s32 noise_dbm;
724 __le32 supp_rates;
725 __le32 supp_ht_rates;
726 __le32 missed_beacons;
727 __le32 rx_beacons;
728 __le32 rx_dir_pkts;
729 __le32 rx_nondir_pkts;
730 __le32 rx_multicast;
731 __le32 rx_errors;
732 __le32 rx_drop_other_bssid;
733 __le32 rx_drop_decode;
734 __le32 rx_drop_reassembly;
735 __le32 rx_drop_bad_len;
736 __le32 rx_drop_overflow;
737 __le32 rx_drop_crc;
738 __le32 rx_drop_missed;
739 __le32 tx_dir_pkts;
740 __le32 tx_nondir_pkts;
741 __le32 tx_failure;
742 __le32 tx_errors;
743 __le32 tx_drop_max_retry;
744 __le32 tx_err_abort;
745 __le32 tx_err_carrier;
746 __le32 rx_bytes;
747 __le32 tx_bytes;
748 __le32 tx_power;
749 __le32 tx_max_power;
750 __le32 roam_threshold;
751 __le32 ap_assoc_nr;
752 __le32 scan_full;
753 __le32 scan_abort;
754 __le32 ap_nr;
755 __le32 roam_nr;
756 __le32 roam_missed_beacons;
757 __le32 roam_rssi;
758 __le32 roam_unassoc;
759 __le32 roam_deauth;
760 __le32 roam_ap_loadblance;
761} __packed;
762
763#define UMAC_STOP_TX_FLAG 0x1
764#define UMAC_RESUME_TX_FLAG 0x2
765
766#define LAST_SEQ_NUM_INVALID 0xFFFF
767
768struct iwm_umac_notif_stop_resume_tx {
769 struct iwm_umac_wifi_in_hdr hdr;
770 u8 flags; /* UMAC_*_TX_FLAG_* */
771 u8 sta_id;
772 __le16 stop_resume_tid_msk; /* tid bitmask */
773} __packed;
774
775#define UMAC_MAX_NUM_PMKIDS 4
776
777/* WiFi interface wrapper header */
778struct iwm_umac_wifi_if {
779 u8 oid;
780 u8 flags;
781 __le16 buf_size;
782} __packed;
783
784#define IWM_SEQ_NUM_HOST_MSK 0x0000
785#define IWM_SEQ_NUM_UMAC_MSK 0x4000
786#define IWM_SEQ_NUM_LMAC_MSK 0x8000
787#define IWM_SEQ_NUM_MSK 0xC000
788
789#endif
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index 2e2dbfa2ee50..96726f79a1dd 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -68,7 +68,6 @@
68#define CMD_802_11_BEACON_STOP 0x0049 68#define CMD_802_11_BEACON_STOP 0x0049
69#define CMD_802_11_MAC_ADDRESS 0x004d 69#define CMD_802_11_MAC_ADDRESS 0x004d
70#define CMD_802_11_LED_GPIO_CTRL 0x004e 70#define CMD_802_11_LED_GPIO_CTRL 0x004e
71#define CMD_802_11_EEPROM_ACCESS 0x0059
72#define CMD_802_11_BAND_CONFIG 0x0058 71#define CMD_802_11_BAND_CONFIG 0x0058
73#define CMD_GSPI_BUS_CONFIG 0x005a 72#define CMD_GSPI_BUS_CONFIG 0x005a
74#define CMD_802_11D_DOMAIN_INFO 0x005b 73#define CMD_802_11D_DOMAIN_INFO 0x005b
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index f578d0b2172d..200bcc0ead98 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -292,7 +292,7 @@ struct mac80211_hwsim_data {
292 struct list_head list; 292 struct list_head list;
293 struct ieee80211_hw *hw; 293 struct ieee80211_hw *hw;
294 struct device *dev; 294 struct device *dev;
295 struct ieee80211_supported_band bands[2]; 295 struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
296 struct ieee80211_channel channels_2ghz[ARRAY_SIZE(hwsim_channels_2ghz)]; 296 struct ieee80211_channel channels_2ghz[ARRAY_SIZE(hwsim_channels_2ghz)];
297 struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; 297 struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)];
298 struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; 298 struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)];
@@ -1082,6 +1082,8 @@ enum hwsim_testmode_attr {
1082enum hwsim_testmode_cmd { 1082enum hwsim_testmode_cmd {
1083 HWSIM_TM_CMD_SET_PS = 0, 1083 HWSIM_TM_CMD_SET_PS = 0,
1084 HWSIM_TM_CMD_GET_PS = 1, 1084 HWSIM_TM_CMD_GET_PS = 1,
1085 HWSIM_TM_CMD_STOP_QUEUES = 2,
1086 HWSIM_TM_CMD_WAKE_QUEUES = 3,
1085}; 1087};
1086 1088
1087static const struct nla_policy hwsim_testmode_policy[HWSIM_TM_ATTR_MAX + 1] = { 1089static const struct nla_policy hwsim_testmode_policy[HWSIM_TM_ATTR_MAX + 1] = {
@@ -1121,6 +1123,12 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw,
1121 if (nla_put_u32(skb, HWSIM_TM_ATTR_PS, hwsim->ps)) 1123 if (nla_put_u32(skb, HWSIM_TM_ATTR_PS, hwsim->ps))
1122 goto nla_put_failure; 1124 goto nla_put_failure;
1123 return cfg80211_testmode_reply(skb); 1125 return cfg80211_testmode_reply(skb);
1126 case HWSIM_TM_CMD_STOP_QUEUES:
1127 ieee80211_stop_queues(hw);
1128 return 0;
1129 case HWSIM_TM_CMD_WAKE_QUEUES:
1130 ieee80211_wake_queues(hw);
1131 return 0;
1124 default: 1132 default:
1125 return -EOPNOTSUPP; 1133 return -EOPNOTSUPP;
1126 } 1134 }
@@ -1855,7 +1863,7 @@ static int __init init_mac80211_hwsim(void)
1855 sband->n_bitrates = ARRAY_SIZE(hwsim_rates) - 4; 1863 sband->n_bitrates = ARRAY_SIZE(hwsim_rates) - 4;
1856 break; 1864 break;
1857 default: 1865 default:
1858 break; 1866 continue;
1859 } 1867 }
1860 1868
1861 sband->ht_cap.ht_supported = true; 1869 sband->ht_cap.ht_supported = true;
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 3af88b8cfcb7..c7a177c62625 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -914,6 +914,69 @@ static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,
914 return 0; 914 return 0;
915} 915}
916 916
917/* cfg80211 operation handler for change_beacon.
918 * Function retrieves and sets modified management IEs to FW.
919 */
920static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
921 struct net_device *dev,
922 struct cfg80211_beacon_data *data)
923{
924 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
925
926 if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
927 wiphy_err(wiphy, "%s: bss_type mismatched\n", __func__);
928 return -EINVAL;
929 }
930
931 if (!priv->bss_started) {
932 wiphy_err(wiphy, "%s: bss not started\n", __func__);
933 return -EINVAL;
934 }
935
936 if (mwifiex_set_mgmt_ies(priv, data)) {
937 wiphy_err(wiphy, "%s: setting mgmt ies failed\n", __func__);
938 return -EFAULT;
939 }
940
941 return 0;
942}
943
944static int
945mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
946{
947 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
948 struct mwifiex_private *priv = mwifiex_get_priv(adapter,
949 MWIFIEX_BSS_ROLE_ANY);
950 struct mwifiex_ds_ant_cfg ant_cfg;
951
952 if (!tx_ant || !rx_ant)
953 return -EOPNOTSUPP;
954
955 if (adapter->hw_dev_mcs_support != HT_STREAM_2X2) {
956 /* Not a MIMO chip. User should provide specific antenna number
957 * for Tx/Rx path or enable all antennas for diversity
958 */
959 if (tx_ant != rx_ant)
960 return -EOPNOTSUPP;
961
962 if ((tx_ant & (tx_ant - 1)) &&
963 (tx_ant != BIT(adapter->number_of_antenna) - 1))
964 return -EOPNOTSUPP;
965
966 if ((tx_ant == BIT(adapter->number_of_antenna) - 1) &&
967 (priv->adapter->number_of_antenna > 1)) {
968 tx_ant = RF_ANTENNA_AUTO;
969 rx_ant = RF_ANTENNA_AUTO;
970 }
971 }
972
973 ant_cfg.tx_ant = tx_ant;
974 ant_cfg.rx_ant = rx_ant;
975
976 return mwifiex_send_cmd_sync(priv, HostCmd_CMD_RF_ANTENNA,
977 HostCmd_ACT_GEN_SET, 0, &ant_cfg);
978}
979
917/* cfg80211 operation handler for stop ap. 980/* cfg80211 operation handler for stop ap.
918 * Function stops BSS running at uAP interface. 981 * Function stops BSS running at uAP interface.
919 */ 982 */
@@ -947,7 +1010,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
947 1010
948 if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) 1011 if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP)
949 return -1; 1012 return -1;
950 if (mwifiex_set_mgmt_ies(priv, params)) 1013 if (mwifiex_set_mgmt_ies(priv, &params->beacon))
951 return -1; 1014 return -1;
952 1015
953 bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL); 1016 bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);
@@ -1697,7 +1760,9 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
1697 .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask, 1760 .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask,
1698 .start_ap = mwifiex_cfg80211_start_ap, 1761 .start_ap = mwifiex_cfg80211_start_ap,
1699 .stop_ap = mwifiex_cfg80211_stop_ap, 1762 .stop_ap = mwifiex_cfg80211_stop_ap,
1763 .change_beacon = mwifiex_cfg80211_change_beacon,
1700 .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, 1764 .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,
1765 .set_antenna = mwifiex_cfg80211_set_antenna,
1701}; 1766};
1702 1767
1703/* 1768/*
@@ -1744,7 +1809,14 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
1744 1809
1745 memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN); 1810 memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN);
1746 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; 1811 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
1747 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME; 1812 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
1813 WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
1814
1815 wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
1816 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2;
1817
1818 wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
1819 wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
1748 1820
1749 /* Reserve space for mwifiex specific private data for BSS */ 1821 /* Reserve space for mwifiex specific private data for BSS */
1750 wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); 1822 wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index ffb6cdfdb797..14e985d01dee 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -227,6 +227,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
227#define HostCmd_CMD_PMIC_REG_ACCESS 0x00ad 227#define HostCmd_CMD_PMIC_REG_ACCESS 0x00ad
228#define HostCmd_CMD_802_11_RF_CHANNEL 0x001d 228#define HostCmd_CMD_802_11_RF_CHANNEL 0x001d
229#define HostCmd_CMD_RF_TX_PWR 0x001e 229#define HostCmd_CMD_RF_TX_PWR 0x001e
230#define HostCmd_CMD_RF_ANTENNA 0x0020
230#define HostCmd_CMD_802_11_DEAUTHENTICATE 0x0024 231#define HostCmd_CMD_802_11_DEAUTHENTICATE 0x0024
231#define HostCmd_CMD_MAC_CONTROL 0x0028 232#define HostCmd_CMD_MAC_CONTROL 0x0028
232#define HostCmd_CMD_802_11_AD_HOC_START 0x002b 233#define HostCmd_CMD_802_11_AD_HOC_START 0x002b
@@ -322,6 +323,12 @@ enum ENH_PS_MODES {
322 323
323#define HostCmd_BSS_TYPE_MASK 0xf000 324#define HostCmd_BSS_TYPE_MASK 0xf000
324 325
326#define HostCmd_ACT_SET_RX 0x0001
327#define HostCmd_ACT_SET_TX 0x0002
328#define HostCmd_ACT_SET_BOTH 0x0003
329
330#define RF_ANTENNA_AUTO 0xFFFF
331
325#define HostCmd_SET_SEQ_NO_BSS_INFO(seq, num, type) { \ 332#define HostCmd_SET_SEQ_NO_BSS_INFO(seq, num, type) { \
326 (((seq) & 0x00ff) | \ 333 (((seq) & 0x00ff) | \
327 (((num) & 0x000f) << 8)) | \ 334 (((num) & 0x000f) << 8)) | \
@@ -884,6 +891,18 @@ struct host_cmd_ds_rf_tx_pwr {
884 u8 min_power; 891 u8 min_power;
885} __packed; 892} __packed;
886 893
894struct host_cmd_ds_rf_ant_mimo {
895 __le16 action_tx;
896 __le16 tx_ant_mode;
897 __le16 action_rx;
898 __le16 rx_ant_mode;
899};
900
901struct host_cmd_ds_rf_ant_siso {
902 __le16 action;
903 __le16 ant_mode;
904};
905
887struct mwifiex_bcn_param { 906struct mwifiex_bcn_param {
888 u8 bssid[ETH_ALEN]; 907 u8 bssid[ETH_ALEN];
889 u8 rssi; 908 u8 rssi;
@@ -1370,6 +1389,8 @@ struct host_cmd_ds_command {
1370 struct host_cmd_ds_tx_rate_cfg tx_rate_cfg; 1389 struct host_cmd_ds_tx_rate_cfg tx_rate_cfg;
1371 struct host_cmd_ds_txpwr_cfg txp_cfg; 1390 struct host_cmd_ds_txpwr_cfg txp_cfg;
1372 struct host_cmd_ds_rf_tx_pwr txp; 1391 struct host_cmd_ds_rf_tx_pwr txp;
1392 struct host_cmd_ds_rf_ant_mimo ant_mimo;
1393 struct host_cmd_ds_rf_ant_siso ant_siso;
1373 struct host_cmd_ds_802_11_ps_mode_enh psmode_enh; 1394 struct host_cmd_ds_802_11_ps_mode_enh psmode_enh;
1374 struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg; 1395 struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg;
1375 struct host_cmd_ds_802_11_scan scan; 1396 struct host_cmd_ds_802_11_scan scan;
diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c
index 8374e33f195a..1d8dd003e396 100644
--- a/drivers/net/wireless/mwifiex/ie.c
+++ b/drivers/net/wireless/mwifiex/ie.c
@@ -51,8 +51,7 @@ mwifiex_ie_get_autoidx(struct mwifiex_private *priv, u16 subtype_mask,
51 51
52 for (i = 0; i < priv->adapter->max_mgmt_ie_index; i++) { 52 for (i = 0; i < priv->adapter->max_mgmt_ie_index; i++) {
53 mask = le16_to_cpu(priv->mgmt_ie[i].mgmt_subtype_mask); 53 mask = le16_to_cpu(priv->mgmt_ie[i].mgmt_subtype_mask);
54 len = le16_to_cpu(priv->mgmt_ie[i].ie_length) + 54 len = le16_to_cpu(ie->ie_length);
55 le16_to_cpu(ie->ie_length);
56 55
57 if (mask == MWIFIEX_AUTO_IDX_MASK) 56 if (mask == MWIFIEX_AUTO_IDX_MASK)
58 continue; 57 continue;
@@ -108,10 +107,8 @@ mwifiex_update_autoindex_ies(struct mwifiex_private *priv,
108 return -1; 107 return -1;
109 108
110 tmp = (u8 *)&priv->mgmt_ie[index].ie_buffer; 109 tmp = (u8 *)&priv->mgmt_ie[index].ie_buffer;
111 tmp += le16_to_cpu(priv->mgmt_ie[index].ie_length);
112 memcpy(tmp, &ie->ie_buffer, le16_to_cpu(ie->ie_length)); 110 memcpy(tmp, &ie->ie_buffer, le16_to_cpu(ie->ie_length));
113 le16_add_cpu(&priv->mgmt_ie[index].ie_length, 111 priv->mgmt_ie[index].ie_length = ie->ie_length;
114 le16_to_cpu(ie->ie_length));
115 priv->mgmt_ie[index].ie_index = cpu_to_le16(index); 112 priv->mgmt_ie[index].ie_index = cpu_to_le16(index);
116 priv->mgmt_ie[index].mgmt_subtype_mask = 113 priv->mgmt_ie[index].mgmt_subtype_mask =
117 cpu_to_le16(mask); 114 cpu_to_le16(mask);
@@ -217,34 +214,107 @@ mwifiex_update_uap_custom_ie(struct mwifiex_private *priv,
217 return ret; 214 return ret;
218} 215}
219 216
220/* This function parses different IEs- Tail IEs, beacon IEs, probe response IEs, 217/* This function checks if WPS IE is present in passed buffer and copies it to
218 * mwifiex_ie structure.
219 * Function takes pointer to struct mwifiex_ie pointer as argument.
220 * If WPS IE is present memory is allocated for mwifiex_ie pointer and filled
221 * in with WPS IE. Caller should take care of freeing this memory.
222 */
223static int mwifiex_update_wps_ie(const u8 *ies, int ies_len,
224 struct mwifiex_ie **ie_ptr, u16 mask)
225{
226 struct ieee_types_header *wps_ie;
227 struct mwifiex_ie *ie = NULL;
228 const u8 *vendor_ie;
229
230 vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
231 WLAN_OUI_TYPE_MICROSOFT_WPS,
232 ies, ies_len);
233 if (vendor_ie) {
234 ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
235 if (!ie)
236 return -ENOMEM;
237
238 wps_ie = (struct ieee_types_header *)vendor_ie;
239 memcpy(ie->ie_buffer, wps_ie, wps_ie->len + 2);
240 ie->ie_length = cpu_to_le16(wps_ie->len + 2);
241 ie->mgmt_subtype_mask = cpu_to_le16(mask);
242 ie->ie_index = cpu_to_le16(MWIFIEX_AUTO_IDX_MASK);
243 }
244
245 *ie_ptr = ie;
246 return 0;
247}
248
249/* This function parses beacon IEs, probe response IEs, association response IEs
250 * from cfg80211_ap_settings->beacon and sets these IE to FW.
251 */
252static int mwifiex_set_mgmt_beacon_data_ies(struct mwifiex_private *priv,
253 struct cfg80211_beacon_data *data)
254{
255 struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL, *ar_ie = NULL;
256 u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK;
257 u16 ar_idx = MWIFIEX_AUTO_IDX_MASK;
258 int ret = 0;
259
260 if (data->beacon_ies && data->beacon_ies_len)
261 mwifiex_update_wps_ie(data->beacon_ies, data->beacon_ies_len,
262 &beacon_ie, MGMT_MASK_BEACON);
263
264 if (data->proberesp_ies && data->proberesp_ies_len)
265 mwifiex_update_wps_ie(data->proberesp_ies,
266 data->proberesp_ies_len, &pr_ie,
267 MGMT_MASK_PROBE_RESP);
268
269 if (data->assocresp_ies && data->assocresp_ies_len)
270 mwifiex_update_wps_ie(data->assocresp_ies,
271 data->assocresp_ies_len, &ar_ie,
272 MGMT_MASK_ASSOC_RESP |
273 MGMT_MASK_REASSOC_RESP);
274
275 if (beacon_ie || pr_ie || ar_ie) {
276 ret = mwifiex_update_uap_custom_ie(priv, beacon_ie,
277 &beacon_idx, pr_ie,
278 &pr_idx, ar_ie, &ar_idx);
279 if (ret)
280 goto done;
281 }
282
283 priv->beacon_idx = beacon_idx;
284 priv->proberesp_idx = pr_idx;
285 priv->assocresp_idx = ar_idx;
286
287done:
288 kfree(beacon_ie);
289 kfree(pr_ie);
290 kfree(ar_ie);
291
292 return ret;
293}
294
295/* This function parses different IEs-tail IEs, beacon IEs, probe response IEs,
221 * association response IEs from cfg80211_ap_settings function and sets these IE 296 * association response IEs from cfg80211_ap_settings function and sets these IE
222 * to FW. 297 * to FW.
223 */ 298 */
224int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, 299int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
225 struct cfg80211_ap_settings *params) 300 struct cfg80211_beacon_data *info)
226{ 301{
227 struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL; 302 struct mwifiex_ie *gen_ie;
228 struct mwifiex_ie *ar_ie = NULL, *gen_ie = NULL; 303 struct ieee_types_header *rsn_ie, *wpa_ie = NULL;
229 struct ieee_types_header *rsn_ie = NULL, *wpa_ie = NULL; 304 u16 rsn_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
230 u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK;
231 u16 ar_idx = MWIFIEX_AUTO_IDX_MASK, rsn_idx = MWIFIEX_AUTO_IDX_MASK;
232 u16 mask, ie_len = 0;
233 const u8 *vendor_ie; 305 const u8 *vendor_ie;
234 int ret = 0;
235 306
236 if (params->beacon.tail && params->beacon.tail_len) { 307 if (info->tail && info->tail_len) {
237 gen_ie = kzalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); 308 gen_ie = kzalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
238 if (!gen_ie) 309 if (!gen_ie)
239 return -ENOMEM; 310 return -ENOMEM;
240 gen_ie->ie_index = cpu_to_le16(rsn_idx); 311 gen_ie->ie_index = cpu_to_le16(rsn_idx);
241 mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP | 312 gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
242 MGMT_MASK_ASSOC_RESP; 313 MGMT_MASK_PROBE_RESP |
243 gen_ie->mgmt_subtype_mask = cpu_to_le16(mask); 314 MGMT_MASK_ASSOC_RESP);
244 315
245 rsn_ie = (void *)cfg80211_find_ie(WLAN_EID_RSN, 316 rsn_ie = (void *)cfg80211_find_ie(WLAN_EID_RSN,
246 params->beacon.tail, 317 info->tail, info->tail_len);
247 params->beacon.tail_len);
248 if (rsn_ie) { 318 if (rsn_ie) {
249 memcpy(gen_ie->ie_buffer, rsn_ie, rsn_ie->len + 2); 319 memcpy(gen_ie->ie_buffer, rsn_ie, rsn_ie->len + 2);
250 ie_len = rsn_ie->len + 2; 320 ie_len = rsn_ie->len + 2;
@@ -253,8 +323,8 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
253 323
254 vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, 324 vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
255 WLAN_OUI_TYPE_MICROSOFT_WPA, 325 WLAN_OUI_TYPE_MICROSOFT_WPA,
256 params->beacon.tail, 326 info->tail,
257 params->beacon.tail_len); 327 info->tail_len);
258 if (vendor_ie) { 328 if (vendor_ie) {
259 wpa_ie = (struct ieee_types_header *)vendor_ie; 329 wpa_ie = (struct ieee_types_header *)vendor_ie;
260 memcpy(gen_ie->ie_buffer + ie_len, 330 memcpy(gen_ie->ie_buffer + ie_len,
@@ -267,79 +337,16 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
267 if (mwifiex_update_uap_custom_ie(priv, gen_ie, &rsn_idx, 337 if (mwifiex_update_uap_custom_ie(priv, gen_ie, &rsn_idx,
268 NULL, NULL, 338 NULL, NULL,
269 NULL, NULL)) { 339 NULL, NULL)) {
270 ret = -1; 340 kfree(gen_ie);
271 goto done; 341 return -1;
272 } 342 }
273
274 priv->rsn_idx = rsn_idx; 343 priv->rsn_idx = rsn_idx;
275 } 344 }
276 }
277
278 if (params->beacon.beacon_ies && params->beacon.beacon_ies_len) {
279 beacon_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
280 if (!beacon_ie) {
281 ret = -ENOMEM;
282 goto done;
283 }
284
285 beacon_ie->ie_index = cpu_to_le16(beacon_idx);
286 beacon_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON);
287 beacon_ie->ie_length =
288 cpu_to_le16(params->beacon.beacon_ies_len);
289 memcpy(beacon_ie->ie_buffer, params->beacon.beacon_ies,
290 params->beacon.beacon_ies_len);
291 }
292
293 if (params->beacon.proberesp_ies && params->beacon.proberesp_ies_len) {
294 pr_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
295 if (!pr_ie) {
296 ret = -ENOMEM;
297 goto done;
298 }
299
300 pr_ie->ie_index = cpu_to_le16(pr_idx);
301 pr_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_PROBE_RESP);
302 pr_ie->ie_length =
303 cpu_to_le16(params->beacon.proberesp_ies_len);
304 memcpy(pr_ie->ie_buffer, params->beacon.proberesp_ies,
305 params->beacon.proberesp_ies_len);
306 }
307
308 if (params->beacon.assocresp_ies && params->beacon.assocresp_ies_len) {
309 ar_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
310 if (!ar_ie) {
311 ret = -ENOMEM;
312 goto done;
313 }
314 345
315 ar_ie->ie_index = cpu_to_le16(ar_idx); 346 kfree(gen_ie);
316 mask = MGMT_MASK_ASSOC_RESP | MGMT_MASK_REASSOC_RESP;
317 ar_ie->mgmt_subtype_mask = cpu_to_le16(mask);
318 ar_ie->ie_length =
319 cpu_to_le16(params->beacon.assocresp_ies_len);
320 memcpy(ar_ie->ie_buffer, params->beacon.assocresp_ies,
321 params->beacon.assocresp_ies_len);
322 }
323
324 if (beacon_ie || pr_ie || ar_ie) {
325 ret = mwifiex_update_uap_custom_ie(priv, beacon_ie,
326 &beacon_idx, pr_ie,
327 &pr_idx, ar_ie, &ar_idx);
328 if (ret)
329 goto done;
330 } 347 }
331 348
332 priv->beacon_idx = beacon_idx; 349 return mwifiex_set_mgmt_beacon_data_ies(priv, info);
333 priv->proberesp_idx = pr_idx;
334 priv->assocresp_idx = ar_idx;
335
336done:
337 kfree(beacon_ie);
338 kfree(pr_ie);
339 kfree(ar_ie);
340 kfree(gen_ie);
341
342 return ret;
343} 350}
344 351
345/* This function removes management IE set */ 352/* This function removes management IE set */
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index 9f088fb88cb7..e121294cc1ac 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -277,6 +277,11 @@ struct mwifiex_ds_11n_amsdu_aggr_ctrl {
277 u16 curr_buf_size; 277 u16 curr_buf_size;
278}; 278};
279 279
280struct mwifiex_ds_ant_cfg {
281 u32 tx_ant;
282 u32 rx_ant;
283};
284
280#define MWIFIEX_NUM_OF_CMD_BUFFER 20 285#define MWIFIEX_NUM_OF_CMD_BUFFER 20
281#define MWIFIEX_SIZE_OF_CMD_BUFFER 2048 286#define MWIFIEX_SIZE_OF_CMD_BUFFER 2048
282 287
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 7cd95cc99a85..9e636535cbf6 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -1013,7 +1013,7 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev);
1013void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config); 1013void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config);
1014 1014
1015int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, 1015int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
1016 struct cfg80211_ap_settings *params); 1016 struct cfg80211_beacon_data *data);
1017int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); 1017int mwifiex_del_mgmt_ies(struct mwifiex_private *priv);
1018u8 *mwifiex_11d_code_2_region(u8 code); 1018u8 *mwifiex_11d_code_2_region(u8 code);
1019 1019
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index b9cd9ed48c45..225d4c776177 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -277,6 +277,39 @@ static int mwifiex_cmd_rf_tx_power(struct mwifiex_private *priv,
277} 277}
278 278
279/* 279/*
280 * This function prepares command to set rf antenna.
281 */
282static int mwifiex_cmd_rf_antenna(struct mwifiex_private *priv,
283 struct host_cmd_ds_command *cmd,
284 u16 cmd_action,
285 struct mwifiex_ds_ant_cfg *ant_cfg)
286{
287 struct host_cmd_ds_rf_ant_mimo *ant_mimo = &cmd->params.ant_mimo;
288 struct host_cmd_ds_rf_ant_siso *ant_siso = &cmd->params.ant_siso;
289
290 cmd->command = cpu_to_le16(HostCmd_CMD_RF_ANTENNA);
291
292 if (cmd_action != HostCmd_ACT_GEN_SET)
293 return 0;
294
295 if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) {
296 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_mimo) +
297 S_DS_GEN);
298 ant_mimo->action_tx = cpu_to_le16(HostCmd_ACT_SET_TX);
299 ant_mimo->tx_ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant);
300 ant_mimo->action_rx = cpu_to_le16(HostCmd_ACT_SET_RX);
301 ant_mimo->rx_ant_mode = cpu_to_le16((u16)ant_cfg->rx_ant);
302 } else {
303 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_siso) +
304 S_DS_GEN);
305 ant_siso->action = cpu_to_le16(HostCmd_ACT_SET_BOTH);
306 ant_siso->ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant);
307 }
308
309 return 0;
310}
311
312/*
280 * This function prepares command to set Host Sleep configuration. 313 * This function prepares command to set Host Sleep configuration.
281 * 314 *
282 * Preparation includes - 315 * Preparation includes -
@@ -1070,6 +1103,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
1070 ret = mwifiex_cmd_rf_tx_power(priv, cmd_ptr, cmd_action, 1103 ret = mwifiex_cmd_rf_tx_power(priv, cmd_ptr, cmd_action,
1071 data_buf); 1104 data_buf);
1072 break; 1105 break;
1106 case HostCmd_CMD_RF_ANTENNA:
1107 ret = mwifiex_cmd_rf_antenna(priv, cmd_ptr, cmd_action,
1108 data_buf);
1109 break;
1073 case HostCmd_CMD_802_11_PS_MODE_ENH: 1110 case HostCmd_CMD_802_11_PS_MODE_ENH:
1074 ret = mwifiex_cmd_enh_power_mode(priv, cmd_ptr, cmd_action, 1111 ret = mwifiex_cmd_enh_power_mode(priv, cmd_ptr, cmd_action,
1075 (uint16_t)cmd_oid, data_buf); 1112 (uint16_t)cmd_oid, data_buf);
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 78fc352c85c4..97715dfbdf58 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -475,6 +475,33 @@ static int mwifiex_ret_rf_tx_power(struct mwifiex_private *priv,
475} 475}
476 476
477/* 477/*
478 * This function handles the command response of set rf antenna
479 */
480static int mwifiex_ret_rf_antenna(struct mwifiex_private *priv,
481 struct host_cmd_ds_command *resp)
482{
483 struct host_cmd_ds_rf_ant_mimo *ant_mimo = &resp->params.ant_mimo;
484 struct host_cmd_ds_rf_ant_siso *ant_siso = &resp->params.ant_siso;
485 struct mwifiex_adapter *adapter = priv->adapter;
486
487 if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
488 dev_dbg(adapter->dev,
489 "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x"
490 " Rx action = 0x%x, Rx Mode = 0x%04x\n",
491 le16_to_cpu(ant_mimo->action_tx),
492 le16_to_cpu(ant_mimo->tx_ant_mode),
493 le16_to_cpu(ant_mimo->action_rx),
494 le16_to_cpu(ant_mimo->rx_ant_mode));
495 else
496 dev_dbg(adapter->dev,
497 "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n",
498 le16_to_cpu(ant_siso->action),
499 le16_to_cpu(ant_siso->ant_mode));
500
501 return 0;
502}
503
504/*
478 * This function handles the command response of set/get MAC address. 505 * This function handles the command response of set/get MAC address.
479 * 506 *
480 * Handling includes saving the MAC address in driver. 507 * Handling includes saving the MAC address in driver.
@@ -868,6 +895,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
868 case HostCmd_CMD_RF_TX_PWR: 895 case HostCmd_CMD_RF_TX_PWR:
869 ret = mwifiex_ret_rf_tx_power(priv, resp); 896 ret = mwifiex_ret_rf_tx_power(priv, resp);
870 break; 897 break;
898 case HostCmd_CMD_RF_ANTENNA:
899 ret = mwifiex_ret_rf_antenna(priv, resp);
900 break;
871 case HostCmd_CMD_802_11_PS_MODE_ENH: 901 case HostCmd_CMD_802_11_PS_MODE_ENH:
872 ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf); 902 ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf);
873 break; 903 break;
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index 82a1cac920bd..f38786e02623 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -422,11 +422,11 @@ static void p54_rx_frame_sent(struct p54_common *priv, struct sk_buff *skb)
422 * Clear manually, ieee80211_tx_info_clear_status would 422 * Clear manually, ieee80211_tx_info_clear_status would
423 * clear the counts too and we need them. 423 * clear the counts too and we need them.
424 */ 424 */
425 memset(&info->status.ampdu_ack_len, 0, 425 memset(&info->status.ack_signal, 0,
426 sizeof(struct ieee80211_tx_info) - 426 sizeof(struct ieee80211_tx_info) -
427 offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); 427 offsetof(struct ieee80211_tx_info, status.ack_signal));
428 BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, 428 BUILD_BUG_ON(offsetof(struct ieee80211_tx_info,
429 status.ampdu_ack_len) != 23); 429 status.ack_signal) != 20);
430 430
431 if (entry_hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN)) 431 if (entry_hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
432 pad = entry_data->align[0]; 432 pad = entry_data->align[0];
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 068276ee8aff..e76f03c9b468 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1940,10 +1940,8 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
1940 rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); 1940 rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
1941} 1941}
1942 1942
1943#define RT3290_POWER_BOUND 0x27 1943#define POWER_BOUND 0x27
1944#define RT3290_FREQ_OFFSET_BOUND 0x5f 1944#define FREQ_OFFSET_BOUND 0x5f
1945#define RT5390_POWER_BOUND 0x27
1946#define RT5390_FREQ_OFFSET_BOUND 0x5f
1947 1945
1948static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, 1946static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
1949 struct ieee80211_conf *conf, 1947 struct ieee80211_conf *conf,
@@ -1959,16 +1957,15 @@ static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
1959 rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); 1957 rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
1960 1958
1961 rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); 1959 rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
1962 if (info->default_power1 > RT3290_POWER_BOUND) 1960 if (info->default_power1 > POWER_BOUND)
1963 rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT3290_POWER_BOUND); 1961 rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND);
1964 else 1962 else
1965 rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); 1963 rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
1966 rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); 1964 rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
1967 1965
1968 rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); 1966 rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
1969 if (rt2x00dev->freq_offset > RT3290_FREQ_OFFSET_BOUND) 1967 if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND)
1970 rt2x00_set_field8(&rfcsr, RFCSR17_CODE, 1968 rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND);
1971 RT3290_FREQ_OFFSET_BOUND);
1972 else 1969 else
1973 rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); 1970 rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
1974 rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); 1971 rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
@@ -2002,17 +1999,16 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
2002 rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); 1999 rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
2003 2000
2004 rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); 2001 rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
2005 if (info->default_power1 > RT5390_POWER_BOUND) 2002 if (info->default_power1 > POWER_BOUND)
2006 rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT5390_POWER_BOUND); 2003 rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND);
2007 else 2004 else
2008 rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); 2005 rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
2009 rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); 2006 rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
2010 2007
2011 if (rt2x00_rt(rt2x00dev, RT5392)) { 2008 if (rt2x00_rt(rt2x00dev, RT5392)) {
2012 rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); 2009 rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
2013 if (info->default_power1 > RT5390_POWER_BOUND) 2010 if (info->default_power1 > POWER_BOUND)
2014 rt2x00_set_field8(&rfcsr, RFCSR50_TX, 2011 rt2x00_set_field8(&rfcsr, RFCSR50_TX, POWER_BOUND);
2015 RT5390_POWER_BOUND);
2016 else 2012 else
2017 rt2x00_set_field8(&rfcsr, RFCSR50_TX, 2013 rt2x00_set_field8(&rfcsr, RFCSR50_TX,
2018 info->default_power2); 2014 info->default_power2);
@@ -2031,9 +2027,8 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
2031 rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); 2027 rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
2032 2028
2033 rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); 2029 rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
2034 if (rt2x00dev->freq_offset > RT5390_FREQ_OFFSET_BOUND) 2030 if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND)
2035 rt2x00_set_field8(&rfcsr, RFCSR17_CODE, 2031 rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND);
2036 RT5390_FREQ_OFFSET_BOUND);
2037 else 2032 else
2038 rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); 2033 rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
2039 rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); 2034 rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index dd436125fe3d..235376e9cb04 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -986,7 +986,7 @@ static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)
986 int i, count; 986 int i, count;
987 987
988 rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg); 988 rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
989 if ((rt2x00_get_field32(reg, WLAN_EN) == 1)) 989 if (rt2x00_get_field32(reg, WLAN_EN))
990 return 0; 990 return 0;
991 991
992 rt2x00_set_field32(&reg, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff); 992 rt2x00_set_field32(&reg, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);
@@ -1004,9 +1004,9 @@ static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)
1004 */ 1004 */
1005 for (i = 0; i < REGISTER_BUSY_COUNT; i++) { 1005 for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
1006 rt2800_register_read(rt2x00dev, CMB_CTRL, &reg); 1006 rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
1007 if ((rt2x00_get_field32(reg, PLL_LD) == 1) && 1007 if (rt2x00_get_field32(reg, PLL_LD) &&
1008 (rt2x00_get_field32(reg, XTAL_RDY) == 1)) 1008 rt2x00_get_field32(reg, XTAL_RDY))
1009 break; 1009 break;
1010 udelay(REGISTER_BUSY_DELAY); 1010 udelay(REGISTER_BUSY_DELAY);
1011 } 1011 }
1012 1012
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 2fd830103415..f7e74a0a7759 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -774,9 +774,7 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
774bool rt2x00queue_for_each_entry(struct data_queue *queue, 774bool rt2x00queue_for_each_entry(struct data_queue *queue,
775 enum queue_index start, 775 enum queue_index start,
776 enum queue_index end, 776 enum queue_index end,
777 void *data, 777 bool (*fn)(struct queue_entry *entry))
778 bool (*fn)(struct queue_entry *entry,
779 void *data))
780{ 778{
781 unsigned long irqflags; 779 unsigned long irqflags;
782 unsigned int index_start; 780 unsigned int index_start;
@@ -807,17 +805,17 @@ bool rt2x00queue_for_each_entry(struct data_queue *queue,
807 */ 805 */
808 if (index_start < index_end) { 806 if (index_start < index_end) {
809 for (i = index_start; i < index_end; i++) { 807 for (i = index_start; i < index_end; i++) {
810 if (fn(&queue->entries[i], data)) 808 if (fn(&queue->entries[i]))
811 return true; 809 return true;
812 } 810 }
813 } else { 811 } else {
814 for (i = index_start; i < queue->limit; i++) { 812 for (i = index_start; i < queue->limit; i++) {
815 if (fn(&queue->entries[i], data)) 813 if (fn(&queue->entries[i]))
816 return true; 814 return true;
817 } 815 }
818 816
819 for (i = 0; i < index_end; i++) { 817 for (i = 0; i < index_end; i++) {
820 if (fn(&queue->entries[i], data)) 818 if (fn(&queue->entries[i]))
821 return true; 819 return true;
822 } 820 }
823 } 821 }
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 5f1392c72673..9b8c10a86dee 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -584,7 +584,6 @@ struct data_queue_desc {
584 * @queue: Pointer to @data_queue 584 * @queue: Pointer to @data_queue
585 * @start: &enum queue_index Pointer to start index 585 * @start: &enum queue_index Pointer to start index
586 * @end: &enum queue_index Pointer to end index 586 * @end: &enum queue_index Pointer to end index
587 * @data: Data to pass to the callback function
588 * @fn: The function to call for each &struct queue_entry 587 * @fn: The function to call for each &struct queue_entry
589 * 588 *
590 * This will walk through all entries in the queue, in chronological 589 * This will walk through all entries in the queue, in chronological
@@ -597,9 +596,7 @@ struct data_queue_desc {
597bool rt2x00queue_for_each_entry(struct data_queue *queue, 596bool rt2x00queue_for_each_entry(struct data_queue *queue,
598 enum queue_index start, 597 enum queue_index start,
599 enum queue_index end, 598 enum queue_index end,
600 void *data, 599 bool (*fn)(struct queue_entry *entry));
601 bool (*fn)(struct queue_entry *entry,
602 void *data));
603 600
604/** 601/**
605 * rt2x00queue_empty - Check if the queue is empty. 602 * rt2x00queue_empty - Check if the queue is empty.
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 74ecc33fdd90..40ea80725a96 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -285,7 +285,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
285 queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); 285 queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
286} 286}
287 287
288static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data) 288static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry)
289{ 289{
290 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; 290 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
291 struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); 291 struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
@@ -390,7 +390,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
390 queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); 390 queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work);
391} 391}
392 392
393static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data) 393static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry)
394{ 394{
395 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; 395 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
396 struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); 396 struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
@@ -427,18 +427,12 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
427 case QID_AC_BE: 427 case QID_AC_BE:
428 case QID_AC_BK: 428 case QID_AC_BK:
429 if (!rt2x00queue_empty(queue)) 429 if (!rt2x00queue_empty(queue))
430 rt2x00queue_for_each_entry(queue, 430 rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
431 Q_INDEX_DONE,
432 Q_INDEX,
433 NULL,
434 rt2x00usb_kick_tx_entry); 431 rt2x00usb_kick_tx_entry);
435 break; 432 break;
436 case QID_RX: 433 case QID_RX:
437 if (!rt2x00queue_full(queue)) 434 if (!rt2x00queue_full(queue))
438 rt2x00queue_for_each_entry(queue, 435 rt2x00queue_for_each_entry(queue, Q_INDEX, Q_INDEX_DONE,
439 Q_INDEX,
440 Q_INDEX_DONE,
441 NULL,
442 rt2x00usb_kick_rx_entry); 436 rt2x00usb_kick_rx_entry);
443 break; 437 break;
444 default: 438 default:
@@ -447,7 +441,7 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
447} 441}
448EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); 442EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue);
449 443
450static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data) 444static bool rt2x00usb_flush_entry(struct queue_entry *entry)
451{ 445{
452 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; 446 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
453 struct queue_entry_priv_usb *entry_priv = entry->priv_data; 447 struct queue_entry_priv_usb *entry_priv = entry->priv_data;
@@ -474,7 +468,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue, bool drop)
474 unsigned int i; 468 unsigned int i;
475 469
476 if (drop) 470 if (drop)
477 rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL, 471 rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
478 rt2x00usb_flush_entry); 472 rt2x00usb_flush_entry);
479 473
480 /* 474 /*
@@ -565,7 +559,7 @@ void rt2x00usb_clear_entry(struct queue_entry *entry)
565 entry->flags = 0; 559 entry->flags = 0;
566 560
567 if (entry->queue->qid == QID_RX) 561 if (entry->queue->qid == QID_RX)
568 rt2x00usb_kick_rx_entry(entry, NULL); 562 rt2x00usb_kick_rx_entry(entry);
569} 563}
570EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); 564EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);
571 565
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 47ba2e0017f4..3d6c71b7a3c7 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -242,7 +242,7 @@ static struct wlcore_conf wl12xx_conf = {
242 .psm_entry_retries = 8, 242 .psm_entry_retries = 8,
243 .psm_exit_retries = 16, 243 .psm_exit_retries = 16,
244 .psm_entry_nullfunc_retries = 3, 244 .psm_entry_nullfunc_retries = 3,
245 .dynamic_ps_timeout = 200, 245 .dynamic_ps_timeout = 1500,
246 .forced_ps = false, 246 .forced_ps = false,
247 .keep_alive_interval = 55000, 247 .keep_alive_interval = 55000,
248 .max_listen_interval = 20, 248 .max_listen_interval = 20,
@@ -590,13 +590,13 @@ static const int wl12xx_rtable[REG_TABLE_LEN] = {
590}; 590};
591 591
592/* TODO: maybe move to a new header file? */ 592/* TODO: maybe move to a new header file? */
593#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin" 593#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-5-mr.bin"
594#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin" 594#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-5-sr.bin"
595#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin" 595#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-5-plt.bin"
596 596
597#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-4-mr.bin" 597#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-5-mr.bin"
598#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin" 598#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-5-sr.bin"
599#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin" 599#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-5-plt.bin"
600 600
601static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) 601static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
602{ 602{
@@ -637,6 +637,7 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
637 wl->chip.id); 637 wl->chip.id);
638 638
639 wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | 639 wl->quirks |= WLCORE_QUIRK_LEGACY_NVS |
640 WLCORE_QUIRK_DUAL_PROBE_TMPL |
640 WLCORE_QUIRK_TKIP_HEADER_SPACE; 641 WLCORE_QUIRK_TKIP_HEADER_SPACE;
641 wl->sr_fw_name = WL127X_FW_NAME_SINGLE; 642 wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
642 wl->mr_fw_name = WL127X_FW_NAME_MULTI; 643 wl->mr_fw_name = WL127X_FW_NAME_MULTI;
@@ -646,6 +647,9 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
646 /* read data preparation is only needed by wl127x */ 647 /* read data preparation is only needed by wl127x */
647 wl->ops->prepare_read = wl127x_prepare_read; 648 wl->ops->prepare_read = wl127x_prepare_read;
648 649
650 wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, WL127X_IFTYPE_VER,
651 WL127X_MAJOR_VER, WL127X_SUBTYPE_VER,
652 WL127X_MINOR_VER);
649 break; 653 break;
650 654
651 case CHIP_ID_1271_PG20: 655 case CHIP_ID_1271_PG20:
@@ -653,6 +657,7 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
653 wl->chip.id); 657 wl->chip.id);
654 658
655 wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | 659 wl->quirks |= WLCORE_QUIRK_LEGACY_NVS |
660 WLCORE_QUIRK_DUAL_PROBE_TMPL |
656 WLCORE_QUIRK_TKIP_HEADER_SPACE; 661 WLCORE_QUIRK_TKIP_HEADER_SPACE;
657 wl->plt_fw_name = WL127X_PLT_FW_NAME; 662 wl->plt_fw_name = WL127X_PLT_FW_NAME;
658 wl->sr_fw_name = WL127X_FW_NAME_SINGLE; 663 wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
@@ -663,6 +668,9 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
663 /* read data preparation is only needed by wl127x */ 668 /* read data preparation is only needed by wl127x */
664 wl->ops->prepare_read = wl127x_prepare_read; 669 wl->ops->prepare_read = wl127x_prepare_read;
665 670
671 wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, WL127X_IFTYPE_VER,
672 WL127X_MAJOR_VER, WL127X_SUBTYPE_VER,
673 WL127X_MINOR_VER);
666 break; 674 break;
667 675
668 case CHIP_ID_1283_PG20: 676 case CHIP_ID_1283_PG20:
@@ -674,8 +682,12 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
674 682
675 /* wl128x requires TX blocksize alignment */ 683 /* wl128x requires TX blocksize alignment */
676 wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | 684 wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN |
685 WLCORE_QUIRK_DUAL_PROBE_TMPL |
677 WLCORE_QUIRK_TKIP_HEADER_SPACE; 686 WLCORE_QUIRK_TKIP_HEADER_SPACE;
678 687
688 wlcore_set_min_fw_ver(wl, WL128X_CHIP_VER, WL128X_IFTYPE_VER,
689 WL128X_MAJOR_VER, WL128X_SUBTYPE_VER,
690 WL128X_MINOR_VER);
679 break; 691 break;
680 case CHIP_ID_1283_PG10: 692 case CHIP_ID_1283_PG10:
681 default: 693 default:
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h
index de1132410876..26990fb4edea 100644
--- a/drivers/net/wireless/ti/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h
@@ -24,6 +24,20 @@
24 24
25#include "conf.h" 25#include "conf.h"
26 26
27/* minimum FW required for driver for wl127x */
28#define WL127X_CHIP_VER 6
29#define WL127X_IFTYPE_VER 3
30#define WL127X_MAJOR_VER 10
31#define WL127X_SUBTYPE_VER 2
32#define WL127X_MINOR_VER 115
33
34/* minimum FW required for driver for wl128x */
35#define WL128X_CHIP_VER 7
36#define WL128X_IFTYPE_VER 3
37#define WL128X_MAJOR_VER 10
38#define WL128X_SUBTYPE_VER 2
39#define WL128X_MINOR_VER 115
40
27struct wl127x_rx_mem_pool_addr { 41struct wl127x_rx_mem_pool_addr {
28 u32 addr; 42 u32 addr;
29 u32 addr_extra; 43 u32 addr_extra;
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 5e583be8f674..b378b34c4a6a 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -369,7 +369,7 @@ static struct wlcore_conf wl18xx_conf = {
369 .psm_entry_retries = 8, 369 .psm_entry_retries = 8,
370 .psm_exit_retries = 16, 370 .psm_exit_retries = 16,
371 .psm_entry_nullfunc_retries = 3, 371 .psm_entry_nullfunc_retries = 3,
372 .dynamic_ps_timeout = 200, 372 .dynamic_ps_timeout = 1500,
373 .forced_ps = false, 373 .forced_ps = false,
374 .keep_alive_interval = 55000, 374 .keep_alive_interval = 55000,
375 .max_listen_interval = 20, 375 .max_listen_interval = 20,
@@ -609,7 +609,12 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
609 wl->quirks |= WLCORE_QUIRK_NO_ELP | 609 wl->quirks |= WLCORE_QUIRK_NO_ELP |
610 WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | 610 WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN |
611 WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | 611 WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN |
612 WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN |
612 WLCORE_QUIRK_TX_PAD_LAST_FRAME; 613 WLCORE_QUIRK_TX_PAD_LAST_FRAME;
614
615 wlcore_set_min_fw_ver(wl, WL18XX_CHIP_VER, WL18XX_IFTYPE_VER,
616 WL18XX_MAJOR_VER, WL18XX_SUBTYPE_VER,
617 WL18XX_MINOR_VER);
613 break; 618 break;
614 case CHIP_ID_185x_PG10: 619 case CHIP_ID_185x_PG10:
615 wl1271_warning("chip id 0x%x (185x PG10) is deprecated", 620 wl1271_warning("chip id 0x%x (185x PG10) is deprecated",
@@ -1020,14 +1025,24 @@ static u32 wl18xx_sta_get_ap_rate_mask(struct wl1271 *wl,
1020static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, 1025static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
1021 struct wl12xx_vif *wlvif) 1026 struct wl12xx_vif *wlvif)
1022{ 1027{
1023 if ((wlvif->channel_type == NL80211_CHAN_HT40MINUS || 1028 struct wl18xx_priv *priv = wl->priv;
1024 wlvif->channel_type == NL80211_CHAN_HT40PLUS) && 1029
1025 !strcmp(ht_mode_param, "wide")) { 1030 if (wlvif->channel_type == NL80211_CHAN_HT40MINUS ||
1031 wlvif->channel_type == NL80211_CHAN_HT40PLUS) {
1026 wl1271_debug(DEBUG_ACX, "using wide channel rate mask"); 1032 wl1271_debug(DEBUG_ACX, "using wide channel rate mask");
1033
1034 /* sanity check - we don't support this */
1035 if (WARN_ON(wlvif->band != IEEE80211_BAND_5GHZ))
1036 return 0;
1037
1027 return CONF_TX_RATE_USE_WIDE_CHAN; 1038 return CONF_TX_RATE_USE_WIDE_CHAN;
1028 } else if (!strcmp(ht_mode_param, "mimo")) { 1039 } else if (priv->conf.phy.number_of_assembled_ant2_4 >= 2 &&
1040 wlvif->band == IEEE80211_BAND_2GHZ) {
1029 wl1271_debug(DEBUG_ACX, "using MIMO rate mask"); 1041 wl1271_debug(DEBUG_ACX, "using MIMO rate mask");
1030 1042 /*
1043 * we don't care about HT channel here - if a peer doesn't
1044 * support MIMO, we won't enable it in its rates
1045 */
1031 return CONF_TX_MIMO_RATES; 1046 return CONF_TX_MIMO_RATES;
1032 } else { 1047 } else {
1033 return 0; 1048 return 0;
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index bc67a4750615..6452396fa1d4 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -24,6 +24,13 @@
24 24
25#include "conf.h" 25#include "conf.h"
26 26
27/* minimum FW required for driver */
28#define WL18XX_CHIP_VER 8
29#define WL18XX_IFTYPE_VER 2
30#define WL18XX_MAJOR_VER 0
31#define WL18XX_SUBTYPE_VER 0
32#define WL18XX_MINOR_VER 100
33
27#define WL18XX_CMD_MAX_SIZE 740 34#define WL18XX_CMD_MAX_SIZE 740
28 35
29struct wl18xx_priv { 36struct wl18xx_priv {
diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c
index 8965960b841a..375ea574eafb 100644
--- a/drivers/net/wireless/ti/wlcore/boot.c
+++ b/drivers/net/wireless/ti/wlcore/boot.c
@@ -81,6 +81,53 @@ out:
81 return ret; 81 return ret;
82} 82}
83 83
84static int wlcore_validate_fw_ver(struct wl1271 *wl)
85{
86 unsigned int *fw_ver = wl->chip.fw_ver;
87 unsigned int *min_ver = wl->min_fw_ver;
88
89 /* the chip must be exactly equal */
90 if (min_ver[FW_VER_CHIP] != fw_ver[FW_VER_CHIP])
91 goto fail;
92
93 /* always check the next digit if all previous ones are equal */
94
95 if (min_ver[FW_VER_IF_TYPE] < fw_ver[FW_VER_IF_TYPE])
96 goto out;
97 else if (min_ver[FW_VER_IF_TYPE] > fw_ver[FW_VER_IF_TYPE])
98 goto fail;
99
100 if (min_ver[FW_VER_MAJOR] < fw_ver[FW_VER_MAJOR])
101 goto out;
102 else if (min_ver[FW_VER_MAJOR] > fw_ver[FW_VER_MAJOR])
103 goto fail;
104
105 if (min_ver[FW_VER_SUBTYPE] < fw_ver[FW_VER_SUBTYPE])
106 goto out;
107 else if (min_ver[FW_VER_SUBTYPE] > fw_ver[FW_VER_SUBTYPE])
108 goto fail;
109
110 if (min_ver[FW_VER_MINOR] < fw_ver[FW_VER_MINOR])
111 goto out;
112 else if (min_ver[FW_VER_MINOR] > fw_ver[FW_VER_MINOR])
113 goto fail;
114
115out:
116 return 0;
117
118fail:
119 wl1271_error("Your WiFi FW version (%u.%u.%u.%u.%u) is outdated.\n"
120 "Please use at least FW %u.%u.%u.%u.%u.\n"
121 "You can get more information at:\n"
122 "http://wireless.kernel.org/en/users/Drivers/wl12xx",
123 fw_ver[FW_VER_CHIP], fw_ver[FW_VER_IF_TYPE],
124 fw_ver[FW_VER_MAJOR], fw_ver[FW_VER_SUBTYPE],
125 fw_ver[FW_VER_MINOR], min_ver[FW_VER_CHIP],
126 min_ver[FW_VER_IF_TYPE], min_ver[FW_VER_MAJOR],
127 min_ver[FW_VER_SUBTYPE], min_ver[FW_VER_MINOR]);
128 return -EINVAL;
129}
130
84static int wlcore_boot_static_data(struct wl1271 *wl) 131static int wlcore_boot_static_data(struct wl1271 *wl)
85{ 132{
86 struct wl1271_static_data *static_data; 133 struct wl1271_static_data *static_data;
@@ -101,6 +148,10 @@ static int wlcore_boot_static_data(struct wl1271 *wl)
101 if (ret < 0) 148 if (ret < 0)
102 goto out_free; 149 goto out_free;
103 150
151 ret = wlcore_validate_fw_ver(wl);
152 if (ret < 0)
153 goto out_free;
154
104 ret = wlcore_handle_static_data(wl, static_data); 155 ret = wlcore_handle_static_data(wl, static_data);
105 if (ret < 0) 156 if (ret < 0)
106 goto out_free; 157 goto out_free;
@@ -141,7 +192,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
141 partition.mem.start = dest; 192 partition.mem.start = dest;
142 ret = wlcore_set_partition(wl, &partition); 193 ret = wlcore_set_partition(wl, &partition);
143 if (ret < 0) 194 if (ret < 0)
144 return ret; 195 goto out;
145 196
146 /* 10.1 set partition limit and chunk num */ 197 /* 10.1 set partition limit and chunk num */
147 chunk_num = 0; 198 chunk_num = 0;
@@ -157,7 +208,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
157 partition.mem.start = addr; 208 partition.mem.start = addr;
158 ret = wlcore_set_partition(wl, &partition); 209 ret = wlcore_set_partition(wl, &partition);
159 if (ret < 0) 210 if (ret < 0)
160 return ret; 211 goto out;
161 } 212 }
162 213
163 /* 10.3 upload the chunk */ 214 /* 10.3 upload the chunk */
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 56c7a2342fdf..a23949cdaebc 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -39,6 +39,7 @@
39#include "hw_ops.h" 39#include "hw_ops.h"
40 40
41#define WL1271_CMD_FAST_POLL_COUNT 50 41#define WL1271_CMD_FAST_POLL_COUNT 50
42#define WL1271_WAIT_EVENT_FAST_POLL_COUNT 20
42 43
43/* 44/*
44 * send command to firmware 45 * send command to firmware
@@ -138,6 +139,7 @@ static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl,
138 u32 *events_vector; 139 u32 *events_vector;
139 u32 event; 140 u32 event;
140 unsigned long timeout_time; 141 unsigned long timeout_time;
142 u16 poll_count = 0;
141 int ret = 0; 143 int ret = 0;
142 144
143 *timeout = false; 145 *timeout = false;
@@ -156,7 +158,11 @@ static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl,
156 goto out; 158 goto out;
157 } 159 }
158 160
159 msleep(1); 161 poll_count++;
162 if (poll_count < WL1271_WAIT_EVENT_FAST_POLL_COUNT)
163 usleep_range(50, 51);
164 else
165 usleep_range(1000, 5000);
160 166
161 /* read from both event fields */ 167 /* read from both event fields */
162 ret = wlcore_read(wl, wl->mbox_ptr[0], events_vector, 168 ret = wlcore_read(wl, wl->mbox_ptr[0], events_vector,
@@ -1007,12 +1013,14 @@ out:
1007int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, 1013int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
1008 u8 role_id, u8 band, 1014 u8 role_id, u8 band,
1009 const u8 *ssid, size_t ssid_len, 1015 const u8 *ssid, size_t ssid_len,
1010 const u8 *ie, size_t ie_len) 1016 const u8 *ie, size_t ie_len, bool sched_scan)
1011{ 1017{
1012 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); 1018 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
1013 struct sk_buff *skb; 1019 struct sk_buff *skb;
1014 int ret; 1020 int ret;
1015 u32 rate; 1021 u32 rate;
1022 u16 template_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4;
1023 u16 template_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5;
1016 1024
1017 skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len, 1025 skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len,
1018 ie, ie_len); 1026 ie, ie_len);
@@ -1023,14 +1031,20 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
1023 1031
1024 wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); 1032 wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len);
1025 1033
1034 if (!sched_scan &&
1035 (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL)) {
1036 template_id_2_4 = CMD_TEMPL_APP_PROBE_REQ_2_4;
1037 template_id_5 = CMD_TEMPL_APP_PROBE_REQ_5;
1038 }
1039
1026 rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); 1040 rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
1027 if (band == IEEE80211_BAND_2GHZ) 1041 if (band == IEEE80211_BAND_2GHZ)
1028 ret = wl1271_cmd_template_set(wl, role_id, 1042 ret = wl1271_cmd_template_set(wl, role_id,
1029 CMD_TEMPL_CFG_PROBE_REQ_2_4, 1043 template_id_2_4,
1030 skb->data, skb->len, 0, rate); 1044 skb->data, skb->len, 0, rate);
1031 else 1045 else
1032 ret = wl1271_cmd_template_set(wl, role_id, 1046 ret = wl1271_cmd_template_set(wl, role_id,
1033 CMD_TEMPL_CFG_PROBE_REQ_5, 1047 template_id_5,
1034 skb->data, skb->len, 0, rate); 1048 skb->data, skb->len, 0, rate);
1035 1049
1036out: 1050out:
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h
index c8a6510c72cb..d7d9f801e506 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.h
+++ b/drivers/net/wireless/ti/wlcore/cmd.h
@@ -58,7 +58,7 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif,
58int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, 58int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
59 u8 role_id, u8 band, 59 u8 role_id, u8 band,
60 const u8 *ssid, size_t ssid_len, 60 const u8 *ssid, size_t ssid_len,
61 const u8 *ie, size_t ie_len); 61 const u8 *ie, size_t ie_len, bool sched_scan);
62struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, 62struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
63 struct wl12xx_vif *wlvif, 63 struct wl12xx_vif *wlvif,
64 struct sk_buff *skb); 64 struct sk_buff *skb);
@@ -172,8 +172,8 @@ enum cmd_templ {
172 CMD_TEMPL_PS_POLL, 172 CMD_TEMPL_PS_POLL,
173 CMD_TEMPL_KLV, 173 CMD_TEMPL_KLV,
174 CMD_TEMPL_DISCONNECT, 174 CMD_TEMPL_DISCONNECT,
175 CMD_TEMPL_PROBE_REQ_2_4, /* for firmware internal use only */ 175 CMD_TEMPL_APP_PROBE_REQ_2_4,
176 CMD_TEMPL_PROBE_REQ_5, /* for firmware internal use only */ 176 CMD_TEMPL_APP_PROBE_REQ_5,
177 CMD_TEMPL_BAR, /* for firmware internal use only */ 177 CMD_TEMPL_BAR, /* for firmware internal use only */
178 CMD_TEMPL_CTS, /* 178 CMD_TEMPL_CTS, /*
179 * For CTS-to-self (FastCTS) mechanism 179 * For CTS-to-self (FastCTS) mechanism
diff --git a/drivers/net/wireless/ti/wlcore/init.c b/drivers/net/wireless/ti/wlcore/init.c
index 8a8a8971befa..a3c867786df8 100644
--- a/drivers/net/wireless/ti/wlcore/init.c
+++ b/drivers/net/wireless/ti/wlcore/init.c
@@ -54,6 +54,22 @@ int wl1271_init_templates_config(struct wl1271 *wl)
54 if (ret < 0) 54 if (ret < 0)
55 return ret; 55 return ret;
56 56
57 if (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL) {
58 ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
59 CMD_TEMPL_APP_PROBE_REQ_2_4, NULL,
60 WL1271_CMD_TEMPL_MAX_SIZE,
61 0, WL1271_RATE_AUTOMATIC);
62 if (ret < 0)
63 return ret;
64
65 ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
66 CMD_TEMPL_APP_PROBE_REQ_5, NULL,
67 WL1271_CMD_TEMPL_MAX_SIZE,
68 0, WL1271_RATE_AUTOMATIC);
69 if (ret < 0)
70 return ret;
71 }
72
57 ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, 73 ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
58 CMD_TEMPL_NULL_DATA, NULL, 74 CMD_TEMPL_NULL_DATA, NULL,
59 sizeof(struct wl12xx_null_data_template), 75 sizeof(struct wl12xx_null_data_template),
diff --git a/drivers/net/wireless/ti/wlcore/io.c b/drivers/net/wireless/ti/wlcore/io.c
index 9976219c4e49..68e74eefd296 100644
--- a/drivers/net/wireless/ti/wlcore/io.c
+++ b/drivers/net/wireless/ti/wlcore/io.c
@@ -60,6 +60,12 @@ void wlcore_enable_interrupts(struct wl1271 *wl)
60} 60}
61EXPORT_SYMBOL_GPL(wlcore_enable_interrupts); 61EXPORT_SYMBOL_GPL(wlcore_enable_interrupts);
62 62
63void wlcore_synchronize_interrupts(struct wl1271 *wl)
64{
65 synchronize_irq(wl->irq);
66}
67EXPORT_SYMBOL_GPL(wlcore_synchronize_interrupts);
68
63int wlcore_translate_addr(struct wl1271 *wl, int addr) 69int wlcore_translate_addr(struct wl1271 *wl, int addr)
64{ 70{
65 struct wlcore_partition_set *part = &wl->curr_part; 71 struct wlcore_partition_set *part = &wl->curr_part;
diff --git a/drivers/net/wireless/ti/wlcore/io.h b/drivers/net/wireless/ti/wlcore/io.h
index fef80adc8bf5..259149f36fae 100644
--- a/drivers/net/wireless/ti/wlcore/io.h
+++ b/drivers/net/wireless/ti/wlcore/io.h
@@ -47,6 +47,7 @@ struct wl1271;
47void wlcore_disable_interrupts(struct wl1271 *wl); 47void wlcore_disable_interrupts(struct wl1271 *wl);
48void wlcore_disable_interrupts_nosync(struct wl1271 *wl); 48void wlcore_disable_interrupts_nosync(struct wl1271 *wl);
49void wlcore_enable_interrupts(struct wl1271 *wl); 49void wlcore_enable_interrupts(struct wl1271 *wl);
50void wlcore_synchronize_interrupts(struct wl1271 *wl);
50 51
51void wl1271_io_reset(struct wl1271 *wl); 52void wl1271_io_reset(struct wl1271 *wl);
52void wl1271_io_init(struct wl1271 *wl); 53void wl1271_io_init(struct wl1271 *wl);
@@ -59,12 +60,12 @@ static inline int __must_check wlcore_raw_write(struct wl1271 *wl, int addr,
59{ 60{
60 int ret; 61 int ret;
61 62
62 if (test_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags)) 63 if (test_bit(WL1271_FLAG_IO_FAILED, &wl->flags))
63 return -EIO; 64 return -EIO;
64 65
65 ret = wl->if_ops->write(wl->dev, addr, buf, len, fixed); 66 ret = wl->if_ops->write(wl->dev, addr, buf, len, fixed);
66 if (ret) 67 if (ret && wl->state != WL1271_STATE_OFF)
67 set_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags); 68 set_bit(WL1271_FLAG_IO_FAILED, &wl->flags);
68 69
69 return ret; 70 return ret;
70} 71}
@@ -75,12 +76,12 @@ static inline int __must_check wlcore_raw_read(struct wl1271 *wl, int addr,
75{ 76{
76 int ret; 77 int ret;
77 78
78 if (test_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags)) 79 if (test_bit(WL1271_FLAG_IO_FAILED, &wl->flags))
79 return -EIO; 80 return -EIO;
80 81
81 ret = wl->if_ops->read(wl->dev, addr, buf, len, fixed); 82 ret = wl->if_ops->read(wl->dev, addr, buf, len, fixed);
82 if (ret) 83 if (ret && wl->state != WL1271_STATE_OFF)
83 set_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags); 84 set_bit(WL1271_FLAG_IO_FAILED, &wl->flags);
84 85
85 return ret; 86 return ret;
86} 87}
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 2240cca597ac..9f04b64dfa33 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -62,7 +62,7 @@ static bool no_recovery;
62static void __wl1271_op_remove_interface(struct wl1271 *wl, 62static void __wl1271_op_remove_interface(struct wl1271 *wl,
63 struct ieee80211_vif *vif, 63 struct ieee80211_vif *vif,
64 bool reset_tx_queues); 64 bool reset_tx_queues);
65static void wl1271_op_stop(struct ieee80211_hw *hw); 65static void wlcore_op_stop_locked(struct wl1271 *wl);
66static void wl1271_free_ap_keys(struct wl1271 *wl, struct wl12xx_vif *wlvif); 66static void wl1271_free_ap_keys(struct wl1271 *wl, struct wl12xx_vif *wlvif);
67 67
68static int wl12xx_set_authorized(struct wl1271 *wl, 68static int wl12xx_set_authorized(struct wl1271 *wl,
@@ -916,16 +916,16 @@ static void wl1271_recovery_work(struct work_struct *work)
916 if (wl->state != WL1271_STATE_ON || wl->plt) 916 if (wl->state != WL1271_STATE_ON || wl->plt)
917 goto out_unlock; 917 goto out_unlock;
918 918
919 wl12xx_read_fwlog_panic(wl); 919 if (!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) {
920 920 wl12xx_read_fwlog_panic(wl);
921 wlcore_print_recovery(wl); 921 wlcore_print_recovery(wl);
922 }
922 923
923 BUG_ON(bug_on_recovery && 924 BUG_ON(bug_on_recovery &&
924 !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); 925 !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags));
925 926
926 if (no_recovery) { 927 if (no_recovery) {
927 wl1271_info("No recovery (chosen on module load). Fw will remain stuck."); 928 wl1271_info("No recovery (chosen on module load). Fw will remain stuck.");
928 clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
929 goto out_unlock; 929 goto out_unlock;
930 } 930 }
931 931
@@ -956,9 +956,8 @@ static void wl1271_recovery_work(struct work_struct *work)
956 vif = wl12xx_wlvif_to_vif(wlvif); 956 vif = wl12xx_wlvif_to_vif(wlvif);
957 __wl1271_op_remove_interface(wl, vif, false); 957 __wl1271_op_remove_interface(wl, vif, false);
958 } 958 }
959 wl->watchdog_recovery = false; 959
960 mutex_unlock(&wl->mutex); 960 wlcore_op_stop_locked(wl);
961 wl1271_op_stop(wl->hw);
962 961
963 ieee80211_restart_hw(wl->hw); 962 ieee80211_restart_hw(wl->hw);
964 963
@@ -967,9 +966,10 @@ static void wl1271_recovery_work(struct work_struct *work)
967 * to restart the HW. 966 * to restart the HW.
968 */ 967 */
969 wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART); 968 wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART);
970 return; 969
971out_unlock: 970out_unlock:
972 wl->watchdog_recovery = false; 971 wl->watchdog_recovery = false;
972 clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
973 mutex_unlock(&wl->mutex); 973 mutex_unlock(&wl->mutex);
974} 974}
975 975
@@ -1211,7 +1211,9 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
1211 * The workqueue is slow to process the tx_queue and we need stop 1211 * The workqueue is slow to process the tx_queue and we need stop
1212 * the queue here, otherwise the queue will get too long. 1212 * the queue here, otherwise the queue will get too long.
1213 */ 1213 */
1214 if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) { 1214 if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK &&
1215 !wlcore_is_queue_stopped_by_reason(wl, q,
1216 WLCORE_QUEUE_STOP_REASON_WATERMARK)) {
1215 wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q); 1217 wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q);
1216 wlcore_stop_queue_locked(wl, q, 1218 wlcore_stop_queue_locked(wl, q,
1217 WLCORE_QUEUE_STOP_REASON_WATERMARK); 1219 WLCORE_QUEUE_STOP_REASON_WATERMARK);
@@ -1797,33 +1799,15 @@ static int wl1271_op_start(struct ieee80211_hw *hw)
1797 return 0; 1799 return 0;
1798} 1800}
1799 1801
1800static void wl1271_op_stop(struct ieee80211_hw *hw) 1802static void wlcore_op_stop_locked(struct wl1271 *wl)
1801{ 1803{
1802 struct wl1271 *wl = hw->priv;
1803 int i; 1804 int i;
1804 1805
1805 wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
1806
1807 /*
1808 * Interrupts must be disabled before setting the state to OFF.
1809 * Otherwise, the interrupt handler might be called and exit without
1810 * reading the interrupt status.
1811 */
1812 wlcore_disable_interrupts(wl);
1813 mutex_lock(&wl->mutex);
1814 if (wl->state == WL1271_STATE_OFF) { 1806 if (wl->state == WL1271_STATE_OFF) {
1815 if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, 1807 if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS,
1816 &wl->flags)) 1808 &wl->flags))
1817 wlcore_enable_interrupts(wl); 1809 wlcore_enable_interrupts(wl);
1818 1810
1819 mutex_unlock(&wl->mutex);
1820
1821 /*
1822 * This will not necessarily enable interrupts as interrupts
1823 * may have been disabled when op_stop was called. It will,
1824 * however, balance the above call to disable_interrupts().
1825 */
1826 wlcore_enable_interrupts(wl);
1827 return; 1811 return;
1828 } 1812 }
1829 1813
@@ -1832,8 +1816,16 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
1832 * functions don't perform further work. 1816 * functions don't perform further work.
1833 */ 1817 */
1834 wl->state = WL1271_STATE_OFF; 1818 wl->state = WL1271_STATE_OFF;
1819
1820 /*
1821 * Use the nosync variant to disable interrupts, so the mutex could be
1822 * held while doing so without deadlocking.
1823 */
1824 wlcore_disable_interrupts_nosync(wl);
1825
1835 mutex_unlock(&wl->mutex); 1826 mutex_unlock(&wl->mutex);
1836 1827
1828 wlcore_synchronize_interrupts(wl);
1837 wl1271_flush_deferred_work(wl); 1829 wl1271_flush_deferred_work(wl);
1838 cancel_delayed_work_sync(&wl->scan_complete_work); 1830 cancel_delayed_work_sync(&wl->scan_complete_work);
1839 cancel_work_sync(&wl->netstack_work); 1831 cancel_work_sync(&wl->netstack_work);
@@ -1900,6 +1892,17 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
1900 wl->tx_res_if = NULL; 1892 wl->tx_res_if = NULL;
1901 kfree(wl->target_mem_map); 1893 kfree(wl->target_mem_map);
1902 wl->target_mem_map = NULL; 1894 wl->target_mem_map = NULL;
1895}
1896
1897static void wlcore_op_stop(struct ieee80211_hw *hw)
1898{
1899 struct wl1271 *wl = hw->priv;
1900
1901 wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
1902
1903 mutex_lock(&wl->mutex);
1904
1905 wlcore_op_stop_locked(wl);
1903 1906
1904 mutex_unlock(&wl->mutex); 1907 mutex_unlock(&wl->mutex);
1905} 1908}
@@ -4566,7 +4569,7 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw,
4566 4569
4567 mutex_lock(&wl->mutex); 4570 mutex_lock(&wl->mutex);
4568 4571
4569 for (i = 0; i < IEEE80211_NUM_BANDS; i++) 4572 for (i = 0; i < WLCORE_NUM_BANDS; i++)
4570 wlvif->bitrate_masks[i] = 4573 wlvif->bitrate_masks[i] =
4571 wl1271_tx_enabled_rates_get(wl, 4574 wl1271_tx_enabled_rates_get(wl,
4572 mask->control[i].legacy, 4575 mask->control[i].legacy,
@@ -4634,6 +4637,13 @@ out:
4634 mutex_unlock(&wl->mutex); 4637 mutex_unlock(&wl->mutex);
4635} 4638}
4636 4639
4640static void wlcore_op_flush(struct ieee80211_hw *hw, bool drop)
4641{
4642 struct wl1271 *wl = hw->priv;
4643
4644 wl1271_tx_flush(wl);
4645}
4646
4637static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) 4647static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
4638{ 4648{
4639 struct wl1271 *wl = hw->priv; 4649 struct wl1271 *wl = hw->priv;
@@ -4796,7 +4806,7 @@ static struct ieee80211_supported_band wl1271_band_5ghz = {
4796 4806
4797static const struct ieee80211_ops wl1271_ops = { 4807static const struct ieee80211_ops wl1271_ops = {
4798 .start = wl1271_op_start, 4808 .start = wl1271_op_start,
4799 .stop = wl1271_op_stop, 4809 .stop = wlcore_op_stop,
4800 .add_interface = wl1271_op_add_interface, 4810 .add_interface = wl1271_op_add_interface,
4801 .remove_interface = wl1271_op_remove_interface, 4811 .remove_interface = wl1271_op_remove_interface,
4802 .change_interface = wl12xx_op_change_interface, 4812 .change_interface = wl12xx_op_change_interface,
@@ -4824,6 +4834,7 @@ static const struct ieee80211_ops wl1271_ops = {
4824 .tx_frames_pending = wl1271_tx_frames_pending, 4834 .tx_frames_pending = wl1271_tx_frames_pending,
4825 .set_bitrate_mask = wl12xx_set_bitrate_mask, 4835 .set_bitrate_mask = wl12xx_set_bitrate_mask,
4826 .channel_switch = wl12xx_op_channel_switch, 4836 .channel_switch = wl12xx_op_channel_switch,
4837 .flush = wlcore_op_flush,
4827 CFG80211_TESTMODE_CMD(wl1271_tm_cmd) 4838 CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
4828}; 4839};
4829 4840
@@ -5504,6 +5515,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
5504 goto out_free_hw; 5515 goto out_free_hw;
5505 } 5516 }
5506 5517
5518#ifdef CONFIG_PM
5507 ret = enable_irq_wake(wl->irq); 5519 ret = enable_irq_wake(wl->irq);
5508 if (!ret) { 5520 if (!ret) {
5509 wl->irq_wake_enabled = true; 5521 wl->irq_wake_enabled = true;
@@ -5517,6 +5529,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
5517 WL1271_RX_FILTER_MAX_PATTERN_SIZE; 5529 WL1271_RX_FILTER_MAX_PATTERN_SIZE;
5518 } 5530 }
5519 } 5531 }
5532#endif
5520 disable_irq(wl->irq); 5533 disable_irq(wl->irq);
5521 5534
5522 ret = wl12xx_get_hw_info(wl); 5535 ret = wl12xx_get_hw_info(wl);
diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c
index d9daed53ceb7..dbeca1bfbb2c 100644
--- a/drivers/net/wireless/ti/wlcore/scan.c
+++ b/drivers/net/wireless/ti/wlcore/scan.c
@@ -226,7 +226,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif,
226 cmd->params.role_id, band, 226 cmd->params.role_id, band,
227 wl->scan.ssid, wl->scan.ssid_len, 227 wl->scan.ssid, wl->scan.ssid_len,
228 wl->scan.req->ie, 228 wl->scan.req->ie,
229 wl->scan.req->ie_len); 229 wl->scan.req->ie_len, false);
230 if (ret < 0) { 230 if (ret < 0) {
231 wl1271_error("PROBE request template failed"); 231 wl1271_error("PROBE request template failed");
232 goto out; 232 goto out;
@@ -633,7 +633,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
633 633
634 for (j = 0; j < cmd->n_ssids; j++) 634 for (j = 0; j < cmd->n_ssids; j++)
635 if ((req->ssids[i].ssid_len == 635 if ((req->ssids[i].ssid_len ==
636 req->ssids[j].ssid_len) && 636 cmd->ssids[j].len) &&
637 !memcmp(req->ssids[i].ssid, 637 !memcmp(req->ssids[i].ssid,
638 cmd->ssids[j].ssid, 638 cmd->ssids[j].ssid,
639 req->ssids[i].ssid_len)) { 639 req->ssids[i].ssid_len)) {
@@ -722,7 +722,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
722 req->ssids[0].ssid, 722 req->ssids[0].ssid,
723 req->ssids[0].ssid_len, 723 req->ssids[0].ssid_len,
724 ies->ie[band], 724 ies->ie[band],
725 ies->len[band]); 725 ies->len[band], true);
726 if (ret < 0) { 726 if (ret < 0) {
727 wl1271_error("2.4GHz PROBE request template failed"); 727 wl1271_error("2.4GHz PROBE request template failed");
728 goto out; 728 goto out;
@@ -736,7 +736,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
736 req->ssids[0].ssid, 736 req->ssids[0].ssid,
737 req->ssids[0].ssid_len, 737 req->ssids[0].ssid_len,
738 ies->ie[band], 738 ies->ie[band],
739 ies->len[band]); 739 ies->len[band], true);
740 if (ret < 0) { 740 if (ret < 0) {
741 wl1271_error("5GHz PROBE request template failed"); 741 wl1271_error("5GHz PROBE request template failed");
742 goto out; 742 goto out;
@@ -766,7 +766,8 @@ int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif)
766 if (wlvif->bss_type != BSS_TYPE_STA_BSS) 766 if (wlvif->bss_type != BSS_TYPE_STA_BSS)
767 return -EOPNOTSUPP; 767 return -EOPNOTSUPP;
768 768
769 if (test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) 769 if ((wl->quirks & WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN) &&
770 test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags))
770 return -EBUSY; 771 return -EBUSY;
771 772
772 start = kzalloc(sizeof(*start), GFP_KERNEL); 773 start = kzalloc(sizeof(*start), GFP_KERNEL);
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index 204e69fa9327..73ace4b2604e 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -411,9 +411,3 @@ MODULE_PARM_DESC(dump, "Enable sdio read/write dumps.");
411MODULE_LICENSE("GPL"); 411MODULE_LICENSE("GPL");
412MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); 412MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
413MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); 413MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
414MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE);
415MODULE_FIRMWARE(WL127X_FW_NAME_MULTI);
416MODULE_FIRMWARE(WL127X_PLT_FW_NAME);
417MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE);
418MODULE_FIRMWARE(WL128X_FW_NAME_MULTI);
419MODULE_FIRMWARE(WL128X_PLT_FW_NAME);
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c
index 6420abae40ee..8da4ed243ebc 100644
--- a/drivers/net/wireless/ti/wlcore/spi.c
+++ b/drivers/net/wireless/ti/wlcore/spi.c
@@ -435,10 +435,4 @@ module_exit(wl1271_exit);
435MODULE_LICENSE("GPL"); 435MODULE_LICENSE("GPL");
436MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); 436MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
437MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); 437MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
438MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE);
439MODULE_FIRMWARE(WL127X_FW_NAME_MULTI);
440MODULE_FIRMWARE(WL127X_PLT_FW_NAME);
441MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE);
442MODULE_FIRMWARE(WL128X_FW_NAME_MULTI);
443MODULE_FIRMWARE(WL128X_PLT_FW_NAME);
444MODULE_ALIAS("spi:wl1271"); 438MODULE_ALIAS("spi:wl1271");
diff --git a/drivers/net/wireless/ti/wlcore/testmode.c b/drivers/net/wireless/ti/wlcore/testmode.c
index eeb339d61d1e..d6f57e2c03cf 100644
--- a/drivers/net/wireless/ti/wlcore/testmode.c
+++ b/drivers/net/wireless/ti/wlcore/testmode.c
@@ -40,7 +40,7 @@ enum wl1271_tm_commands {
40 WL1271_TM_CMD_CONFIGURE, 40 WL1271_TM_CMD_CONFIGURE,
41 WL1271_TM_CMD_NVS_PUSH, /* Not in use. Keep to not break ABI */ 41 WL1271_TM_CMD_NVS_PUSH, /* Not in use. Keep to not break ABI */
42 WL1271_TM_CMD_SET_PLT_MODE, 42 WL1271_TM_CMD_SET_PLT_MODE,
43 WL1271_TM_CMD_RECOVER, 43 WL1271_TM_CMD_RECOVER, /* Not in use. Keep to not break ABI */
44 WL1271_TM_CMD_GET_MAC, 44 WL1271_TM_CMD_GET_MAC,
45 45
46 __WL1271_TM_CMD_AFTER_LAST 46 __WL1271_TM_CMD_AFTER_LAST
@@ -272,15 +272,6 @@ static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[])
272 return ret; 272 return ret;
273} 273}
274 274
275static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[])
276{
277 wl1271_debug(DEBUG_TESTMODE, "testmode cmd recover");
278
279 wl12xx_queue_recovery_work(wl);
280
281 return 0;
282}
283
284static int wl12xx_tm_cmd_get_mac(struct wl1271 *wl, struct nlattr *tb[]) 275static int wl12xx_tm_cmd_get_mac(struct wl1271 *wl, struct nlattr *tb[])
285{ 276{
286 struct sk_buff *skb; 277 struct sk_buff *skb;
@@ -350,8 +341,6 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
350 return wl1271_tm_cmd_configure(wl, tb); 341 return wl1271_tm_cmd_configure(wl, tb);
351 case WL1271_TM_CMD_SET_PLT_MODE: 342 case WL1271_TM_CMD_SET_PLT_MODE:
352 return wl1271_tm_cmd_set_plt_mode(wl, tb); 343 return wl1271_tm_cmd_set_plt_mode(wl, tb);
353 case WL1271_TM_CMD_RECOVER:
354 return wl1271_tm_cmd_recover(wl, tb);
355 case WL1271_TM_CMD_GET_MAC: 344 case WL1271_TM_CMD_GET_MAC:
356 return wl12xx_tm_cmd_get_mac(wl, tb); 345 return wl12xx_tm_cmd_get_mac(wl, tb);
357 default: 346 default:
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index e796974df59b..27ccc275a1c1 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -304,7 +304,7 @@ struct wl1271 {
304 s8 noise; 304 s8 noise;
305 305
306 /* bands supported by this instance of wl12xx */ 306 /* bands supported by this instance of wl12xx */
307 struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; 307 struct ieee80211_supported_band bands[WLCORE_NUM_BANDS];
308 308
309 /* 309 /*
310 * wowlan trigger was configured during suspend. 310 * wowlan trigger was configured during suspend.
@@ -371,7 +371,7 @@ struct wl1271 {
371 u8 hw_min_ht_rate; 371 u8 hw_min_ht_rate;
372 372
373 /* HW HT (11n) capabilities */ 373 /* HW HT (11n) capabilities */
374 struct ieee80211_sta_ht_cap ht_cap[IEEE80211_NUM_BANDS]; 374 struct ieee80211_sta_ht_cap ht_cap[WLCORE_NUM_BANDS];
375 375
376 /* size of the private FW status data */ 376 /* size of the private FW status data */
377 size_t fw_status_priv_len; 377 size_t fw_status_priv_len;
@@ -390,6 +390,9 @@ struct wl1271 {
390 390
391 /* sleep auth value currently configured to FW */ 391 /* sleep auth value currently configured to FW */
392 int sleep_auth; 392 int sleep_auth;
393
394 /* the minimum FW version required for the driver to work */
395 unsigned int min_fw_ver[NUM_FW_VER];
393}; 396};
394 397
395int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); 398int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
@@ -408,6 +411,18 @@ wlcore_set_ht_cap(struct wl1271 *wl, enum ieee80211_band band,
408 memcpy(&wl->ht_cap[band], ht_cap, sizeof(*ht_cap)); 411 memcpy(&wl->ht_cap[band], ht_cap, sizeof(*ht_cap));
409} 412}
410 413
414static inline void
415wlcore_set_min_fw_ver(struct wl1271 *wl, unsigned int chip,
416 unsigned int iftype, unsigned int major,
417 unsigned int subtype, unsigned int minor)
418{
419 wl->min_fw_ver[FW_VER_CHIP] = chip;
420 wl->min_fw_ver[FW_VER_IF_TYPE] = iftype;
421 wl->min_fw_ver[FW_VER_MAJOR] = major;
422 wl->min_fw_ver[FW_VER_SUBTYPE] = subtype;
423 wl->min_fw_ver[FW_VER_MINOR] = minor;
424}
425
411/* Firmware image load chunk size */ 426/* Firmware image load chunk size */
412#define CHUNK_SIZE 16384 427#define CHUNK_SIZE 16384
413 428
@@ -437,6 +452,12 @@ wlcore_set_ht_cap(struct wl1271 *wl, enum ieee80211_band band,
437/* extra header space is required for TKIP */ 452/* extra header space is required for TKIP */
438#define WLCORE_QUIRK_TKIP_HEADER_SPACE BIT(8) 453#define WLCORE_QUIRK_TKIP_HEADER_SPACE BIT(8)
439 454
455/* Some firmwares not support sched scans while connected */
456#define WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN BIT(9)
457
458/* separate probe response templates for one-shot and sched scans */
459#define WLCORE_QUIRK_DUAL_PROBE_TMPL BIT(10)
460
440/* TODO: move to the lower drivers when all usages are abstracted */ 461/* TODO: move to the lower drivers when all usages are abstracted */
441#define CHIP_ID_1271_PG10 (0x4030101) 462#define CHIP_ID_1271_PG10 (0x4030101)
442#define CHIP_ID_1271_PG20 (0x4030111) 463#define CHIP_ID_1271_PG20 (0x4030111)
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 4273a21cdde1..0187eef4fb07 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -35,15 +35,6 @@
35#include "conf.h" 35#include "conf.h"
36#include "ini.h" 36#include "ini.h"
37 37
38#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin"
39#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin"
40
41#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-4-mr.bin"
42#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin"
43
44#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin"
45#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin"
46
47/* 38/*
48 * wl127x and wl128x are using the same NVS file name. However, the 39 * wl127x and wl128x are using the same NVS file name. However, the
49 * ini parameters between them are different. The driver validates 40 * ini parameters between them are different. The driver validates
@@ -71,6 +62,9 @@
71#define WL12XX_INVALID_ROLE_ID 0xff 62#define WL12XX_INVALID_ROLE_ID 0xff
72#define WL12XX_INVALID_LINK_ID 0xff 63#define WL12XX_INVALID_LINK_ID 0xff
73 64
65/* the driver supports the 2.4Ghz and 5Ghz bands */
66#define WLCORE_NUM_BANDS 2
67
74#define WL12XX_MAX_RATE_POLICIES 16 68#define WL12XX_MAX_RATE_POLICIES 16
75 69
76/* Defined by FW as 0. Will not be freed or allocated. */ 70/* Defined by FW as 0. Will not be freed or allocated. */
@@ -247,7 +241,7 @@ enum wl12xx_flags {
247 WL1271_FLAG_RECOVERY_IN_PROGRESS, 241 WL1271_FLAG_RECOVERY_IN_PROGRESS,
248 WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, 242 WL1271_FLAG_VIF_CHANGE_IN_PROGRESS,
249 WL1271_FLAG_INTENDED_FW_RECOVERY, 243 WL1271_FLAG_INTENDED_FW_RECOVERY,
250 WL1271_FLAG_SDIO_FAILED, 244 WL1271_FLAG_IO_FAILED,
251}; 245};
252 246
253enum wl12xx_vif_flags { 247enum wl12xx_vif_flags {
@@ -369,7 +363,7 @@ struct wl12xx_vif {
369 int channel; 363 int channel;
370 enum nl80211_channel_type channel_type; 364 enum nl80211_channel_type channel_type;
371 365
372 u32 bitrate_masks[IEEE80211_NUM_BANDS]; 366 u32 bitrate_masks[WLCORE_NUM_BANDS];
373 u32 basic_rate_set; 367 u32 basic_rate_set;
374 368
375 /* 369 /*