aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/nfc/nfc-hci.txt33
-rw-r--r--MAINTAINERS8
-rw-r--r--drivers/bcma/bcma_private.h9
-rw-r--r--drivers/bcma/core.c10
-rw-r--r--drivers/bcma/driver_chipcommon.c5
-rw-r--r--drivers/bcma/driver_chipcommon_pmu.c369
-rw-r--r--drivers/bcma/driver_mips.c24
-rw-r--r--drivers/bcma/driver_pci_host.c18
-rw-r--r--drivers/bcma/host_pci.c5
-rw-r--r--drivers/bcma/main.c19
-rw-r--r--drivers/bcma/scan.c24
-rw-r--r--drivers/bcma/sprom.c26
-rw-r--r--drivers/misc/Kconfig1
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/iwmc3200top/Kconfig20
-rw-r--r--drivers/misc/iwmc3200top/Makefile29
-rw-r--r--drivers/misc/iwmc3200top/debugfs.c137
-rw-r--r--drivers/misc/iwmc3200top/debugfs.h58
-rw-r--r--drivers/misc/iwmc3200top/fw-download.c358
-rw-r--r--drivers/misc/iwmc3200top/fw-msg.h113
-rw-r--r--drivers/misc/iwmc3200top/iwmc3200top.h205
-rw-r--r--drivers/misc/iwmc3200top/log.c348
-rw-r--r--drivers/misc/iwmc3200top/log.h171
-rw-r--r--drivers/misc/iwmc3200top/main.c662
-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
-rw-r--r--drivers/nfc/nfcwilink.c7
-rw-r--r--drivers/nfc/pn533.c224
-rw-r--r--drivers/nfc/pn544_hci.c37
-rw-r--r--include/linux/bcma/bcma.h30
-rw-r--r--include/linux/bcma/bcma_driver_chipcommon.h37
-rw-r--r--include/linux/ieee80211.h160
-rw-r--r--include/linux/nfc.h14
-rw-r--r--include/linux/nl80211.h17
-rw-r--r--include/net/cfg80211.h40
-rw-r--r--include/net/mac80211.h44
-rw-r--r--include/net/nfc/hci.h19
-rw-r--r--include/net/nfc/nfc.h2
-rw-r--r--net/mac80211/cfg.c24
-rw-r--r--net/mac80211/debugfs_key.c16
-rw-r--r--net/mac80211/driver-ops.h22
-rw-r--r--net/mac80211/ieee80211_i.h11
-rw-r--r--net/mac80211/iface.c258
-rw-r--r--net/mac80211/main.c17
-rw-r--r--net/mac80211/mesh_plink.c4
-rw-r--r--net/mac80211/mlme.c28
-rw-r--r--net/mac80211/trace.h7
-rw-r--r--net/mac80211/tx.c16
-rw-r--r--net/mac80211/util.c49
-rw-r--r--net/nfc/core.c38
-rw-r--r--net/nfc/hci/command.c26
-rw-r--r--net/nfc/hci/core.c104
-rw-r--r--net/nfc/hci/hci.h12
-rw-r--r--net/nfc/hci/shdlc.c38
-rw-r--r--net/nfc/llcp/llcp.c342
-rw-r--r--net/nfc/llcp/llcp.h5
-rw-r--r--net/nfc/llcp/sock.c31
-rw-r--r--net/nfc/nci/core.c5
-rw-r--r--net/nfc/nci/ntf.c5
-rw-r--r--net/nfc/netlink.c9
-rw-r--r--net/wireless/Makefile2
-rw-r--r--net/wireless/ap.c46
-rw-r--r--net/wireless/chan.c62
-rw-r--r--net/wireless/core.c84
-rw-r--r--net/wireless/core.h64
-rw-r--r--net/wireless/ibss.c11
-rw-r--r--net/wireless/mesh.c30
-rw-r--r--net/wireless/mlme.c17
-rw-r--r--net/wireless/nl80211.c65
-rw-r--r--net/wireless/reg.c5
-rw-r--r--net/wireless/util.c156
-rw-r--r--net/wireless/wext-compat.c9
198 files changed, 4692 insertions, 15819 deletions
diff --git a/Documentation/nfc/nfc-hci.txt b/Documentation/nfc/nfc-hci.txt
index 320f9336c781..89a339c9b079 100644
--- a/Documentation/nfc/nfc-hci.txt
+++ b/Documentation/nfc/nfc-hci.txt
@@ -178,3 +178,36 @@ ANY_GET_PARAMETER to the reader A gate to get information on the target
178that was discovered). 178that was discovered).
179 179
180Typically, such an event will be propagated to NFC Core from MSGRXWQ context. 180Typically, such an event will be propagated to NFC Core from MSGRXWQ context.
181
182Error management
183----------------
184
185Errors that occur synchronously with the execution of an NFC Core request are
186simply returned as the execution result of the request. These are easy.
187
188Errors that occur asynchronously (e.g. in a background protocol handling thread)
189must be reported such that upper layers don't stay ignorant that something
190went wrong below and know that expected events will probably never happen.
191Handling of these errors is done as follows:
192
193- driver (pn544) fails to deliver an incoming frame: it stores the error such
194that any subsequent call to the driver will result in this error. Then it calls
195the standard nfc_shdlc_recv_frame() with a NULL argument to report the problem
196above. shdlc stores a EREMOTEIO sticky status, which will trigger SMW to
197report above in turn.
198
199- SMW is basically a background thread to handle incoming and outgoing shdlc
200frames. This thread will also check the shdlc sticky status and report to HCI
201when it discovers it is not able to run anymore because of an unrecoverable
202error that happened within shdlc or below. If the problem occurs during shdlc
203connection, the error is reported through the connect completion.
204
205- HCI: if an internal HCI error happens (frame is lost), or HCI is reported an
206error from a lower layer, HCI will either complete the currently executing
207command with that error, or notify NFC Core directly if no command is executing.
208
209- NFC Core: when NFC Core is notified of an error from below and polling is
210active, it will send a tag discovered event with an empty tag list to the user
211space to let it know that the poll operation will never be able to detect a tag.
212If polling is not active and the error was sticky, lower levels will return it
213at next invocation.
diff --git a/MAINTAINERS b/MAINTAINERS
index ce7398e1e1ec..b4321fb74698 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3661,14 +3661,6 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi.git
3661S: Supported 3661S: Supported
3662F: drivers/net/wireless/iwlwifi/ 3662F: drivers/net/wireless/iwlwifi/
3663 3663
3664INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi)
3665M: Samuel Ortiz <samuel.ortiz@intel.com>
3666M: Intel Linux Wireless <ilw@linux.intel.com>
3667L: linux-wireless@vger.kernel.org
3668S: Supported
3669W: http://wireless.kernel.org/en/users/Drivers/iwmc3200wifi
3670F: drivers/net/wireless/iwmc3200wifi/
3671
3672INTEL MANAGEMENT ENGINE (mei) 3664INTEL MANAGEMENT ENGINE (mei)
3673M: Tomas Winkler <tomas.winkler@intel.com> 3665M: Tomas Winkler <tomas.winkler@intel.com>
3674L: linux-kernel@vger.kernel.org 3666L: linux-kernel@vger.kernel.org
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index b81755bb4798..f6589eb7c45f 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -10,6 +10,15 @@
10 10
11#define BCMA_CORE_SIZE 0x1000 11#define BCMA_CORE_SIZE 0x1000
12 12
13#define bcma_err(bus, fmt, ...) \
14 pr_err("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
15#define bcma_warn(bus, fmt, ...) \
16 pr_warn("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
17#define bcma_info(bus, fmt, ...) \
18 pr_info("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
19#define bcma_debug(bus, fmt, ...) \
20 pr_debug("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
21
13struct bcma_bus; 22struct bcma_bus;
14 23
15/* main.c */ 24/* main.c */
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c
index bc6e89212ad3..63c8b470536f 100644
--- a/drivers/bcma/core.c
+++ b/drivers/bcma/core.c
@@ -75,7 +75,7 @@ void bcma_core_set_clockmode(struct bcma_device *core,
75 udelay(10); 75 udelay(10);
76 } 76 }
77 if (i) 77 if (i)
78 pr_err("HT force timeout\n"); 78 bcma_err(core->bus, "HT force timeout\n");
79 break; 79 break;
80 case BCMA_CLKMODE_DYNAMIC: 80 case BCMA_CLKMODE_DYNAMIC:
81 bcma_set32(core, BCMA_CLKCTLST, ~BCMA_CLKCTLST_FORCEHT); 81 bcma_set32(core, BCMA_CLKCTLST, ~BCMA_CLKCTLST_FORCEHT);
@@ -102,9 +102,9 @@ void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on)
102 udelay(10); 102 udelay(10);
103 } 103 }
104 if (i) 104 if (i)
105 pr_err("PLL enable timeout\n"); 105 bcma_err(core->bus, "PLL enable timeout\n");
106 } else { 106 } else {
107 pr_warn("Disabling PLL not supported yet!\n"); 107 bcma_warn(core->bus, "Disabling PLL not supported yet!\n");
108 } 108 }
109} 109}
110EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); 110EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
@@ -120,8 +120,8 @@ u32 bcma_core_dma_translation(struct bcma_device *core)
120 else 120 else
121 return BCMA_DMA_TRANSLATION_DMA32_CMT; 121 return BCMA_DMA_TRANSLATION_DMA32_CMT;
122 default: 122 default:
123 pr_err("DMA translation unknown for host %d\n", 123 bcma_err(core->bus, "DMA translation unknown for host %d\n",
124 core->bus->hosttype); 124 core->bus->hosttype);
125 } 125 }
126 return BCMA_DMA_TRANSLATION_NONE; 126 return BCMA_DMA_TRANSLATION_NONE;
127} 127}
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index e9f1b3fd252c..a4c3ebcc4c86 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -44,7 +44,7 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
44 if (cc->capabilities & BCMA_CC_CAP_PMU) 44 if (cc->capabilities & BCMA_CC_CAP_PMU)
45 bcma_pmu_init(cc); 45 bcma_pmu_init(cc);
46 if (cc->capabilities & BCMA_CC_CAP_PCTL) 46 if (cc->capabilities & BCMA_CC_CAP_PCTL)
47 pr_err("Power control not implemented!\n"); 47 bcma_err(cc->core->bus, "Power control not implemented!\n");
48 48
49 if (cc->core->id.rev >= 16) { 49 if (cc->core->id.rev >= 16) {
50 if (cc->core->bus->sprom.leddc_on_time && 50 if (cc->core->bus->sprom.leddc_on_time &&
@@ -137,8 +137,7 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
137 | BCMA_CC_CORECTL_UARTCLKEN); 137 | BCMA_CC_CORECTL_UARTCLKEN);
138 } 138 }
139 } else { 139 } else {
140 pr_err("serial not supported on this device ccrev: 0x%x\n", 140 bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n", ccrev);
141 ccrev);
142 return; 141 return;
143 } 142 }
144 143
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index 61ce4054b3c3..44326178db29 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -3,7 +3,8 @@
3 * ChipCommon Power Management Unit driver 3 * ChipCommon Power Management Unit driver
4 * 4 *
5 * Copyright 2009, Michael Buesch <m@bues.ch> 5 * Copyright 2009, Michael Buesch <m@bues.ch>
6 * Copyright 2007, Broadcom Corporation 6 * Copyright 2007, 2011, Broadcom Corporation
7 * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
7 * 8 *
8 * Licensed under the GNU/GPL. See COPYING for details. 9 * Licensed under the GNU/GPL. See COPYING for details.
9 */ 10 */
@@ -54,39 +55,19 @@ void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
54} 55}
55EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); 56EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset);
56 57
57static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
58{
59 struct bcma_bus *bus = cc->core->bus;
60
61 switch (bus->chipinfo.id) {
62 case 0x4313:
63 case 0x4331:
64 case 43224:
65 case 43225:
66 break;
67 default:
68 pr_err("PLL init unknown for device 0x%04X\n",
69 bus->chipinfo.id);
70 }
71}
72
73static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) 58static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
74{ 59{
75 struct bcma_bus *bus = cc->core->bus; 60 struct bcma_bus *bus = cc->core->bus;
76 u32 min_msk = 0, max_msk = 0; 61 u32 min_msk = 0, max_msk = 0;
77 62
78 switch (bus->chipinfo.id) { 63 switch (bus->chipinfo.id) {
79 case 0x4313: 64 case BCMA_CHIP_ID_BCM4313:
80 min_msk = 0x200D; 65 min_msk = 0x200D;
81 max_msk = 0xFFFF; 66 max_msk = 0xFFFF;
82 break; 67 break;
83 case 0x4331:
84 case 43224:
85 case 43225:
86 break;
87 default: 68 default:
88 pr_err("PMU resource config unknown for device 0x%04X\n", 69 bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n",
89 bus->chipinfo.id); 70 bus->chipinfo.id);
90 } 71 }
91 72
92 /* Set the resource masks. */ 73 /* Set the resource masks. */
@@ -94,22 +75,9 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
94 bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); 75 bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk);
95 if (max_msk) 76 if (max_msk)
96 bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); 77 bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk);
97}
98
99void bcma_pmu_swreg_init(struct bcma_drv_cc *cc)
100{
101 struct bcma_bus *bus = cc->core->bus;
102 78
103 switch (bus->chipinfo.id) { 79 /* Add some delay; allow resources to come up and settle. */
104 case 0x4313: 80 mdelay(2);
105 case 0x4331:
106 case 43224:
107 case 43225:
108 break;
109 default:
110 pr_err("PMU switch/regulators init unknown for device "
111 "0x%04X\n", bus->chipinfo.id);
112 }
113} 81}
114 82
115/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */ 83/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */
@@ -123,8 +91,11 @@ void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable)
123 val |= BCMA_CHIPCTL_4331_EXTPA_EN; 91 val |= BCMA_CHIPCTL_4331_EXTPA_EN;
124 if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11) 92 if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11)
125 val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; 93 val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
94 else if (bus->chipinfo.rev > 0)
95 val |= BCMA_CHIPCTL_4331_EXTPA_EN2;
126 } else { 96 } else {
127 val &= ~BCMA_CHIPCTL_4331_EXTPA_EN; 97 val &= ~BCMA_CHIPCTL_4331_EXTPA_EN;
98 val &= ~BCMA_CHIPCTL_4331_EXTPA_EN2;
128 val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; 99 val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
129 } 100 }
130 bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val); 101 bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val);
@@ -135,28 +106,38 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
135 struct bcma_bus *bus = cc->core->bus; 106 struct bcma_bus *bus = cc->core->bus;
136 107
137 switch (bus->chipinfo.id) { 108 switch (bus->chipinfo.id) {
138 case 0x4313: 109 case BCMA_CHIP_ID_BCM4313:
139 bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7); 110 /* enable 12 mA drive strenth for 4313 and set chipControl
111 register bit 1 */
112 bcma_chipco_chipctl_maskset(cc, 0,
113 BCMA_CCTRL_4313_12MA_LED_DRIVE,
114 BCMA_CCTRL_4313_12MA_LED_DRIVE);
140 break; 115 break;
141 case 0x4331: 116 case BCMA_CHIP_ID_BCM4331:
142 case 43431: 117 case BCMA_CHIP_ID_BCM43431:
143 /* Ext PA lines must be enabled for tx on BCM4331 */ 118 /* Ext PA lines must be enabled for tx on BCM4331 */
144 bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true); 119 bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true);
145 break; 120 break;
146 case 43224: 121 case BCMA_CHIP_ID_BCM43224:
122 case BCMA_CHIP_ID_BCM43421:
123 /* enable 12 mA drive strenth for 43224 and set chipControl
124 register bit 15 */
147 if (bus->chipinfo.rev == 0) { 125 if (bus->chipinfo.rev == 0) {
148 pr_err("Workarounds for 43224 rev 0 not fully " 126 bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL,
149 "implemented\n"); 127 BCMA_CCTRL_43224_GPIO_TOGGLE,
150 bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0); 128 BCMA_CCTRL_43224_GPIO_TOGGLE);
129 bcma_chipco_chipctl_maskset(cc, 0,
130 BCMA_CCTRL_43224A0_12MA_LED_DRIVE,
131 BCMA_CCTRL_43224A0_12MA_LED_DRIVE);
151 } else { 132 } else {
152 bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0); 133 bcma_chipco_chipctl_maskset(cc, 0,
134 BCMA_CCTRL_43224B0_12MA_LED_DRIVE,
135 BCMA_CCTRL_43224B0_12MA_LED_DRIVE);
153 } 136 }
154 break; 137 break;
155 case 43225:
156 break;
157 default: 138 default:
158 pr_err("Workarounds unknown for device 0x%04X\n", 139 bcma_debug(bus, "Workarounds unknown or not needed for device 0x%04X\n",
159 bus->chipinfo.id); 140 bus->chipinfo.id);
160 } 141 }
161} 142}
162 143
@@ -167,8 +148,8 @@ void bcma_pmu_init(struct bcma_drv_cc *cc)
167 pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP); 148 pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP);
168 cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION); 149 cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION);
169 150
170 pr_debug("Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev, 151 bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n",
171 pmucap); 152 cc->pmu.rev, pmucap);
172 153
173 if (cc->pmu.rev == 1) 154 if (cc->pmu.rev == 1)
174 bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, 155 bcma_cc_mask32(cc, BCMA_CC_PMU_CTL,
@@ -177,12 +158,7 @@ void bcma_pmu_init(struct bcma_drv_cc *cc)
177 bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 158 bcma_cc_set32(cc, BCMA_CC_PMU_CTL,
178 BCMA_CC_PMU_CTL_NOILPONW); 159 BCMA_CC_PMU_CTL_NOILPONW);
179 160
180 if (cc->core->id.id == 0x4329 && cc->core->id.rev == 2)
181 pr_err("Fix for 4329b0 bad LPOM state not implemented!\n");
182
183 bcma_pmu_pll_init(cc);
184 bcma_pmu_resources_init(cc); 161 bcma_pmu_resources_init(cc);
185 bcma_pmu_swreg_init(cc);
186 bcma_pmu_workarounds(cc); 162 bcma_pmu_workarounds(cc);
187} 163}
188 164
@@ -191,23 +167,22 @@ u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc)
191 struct bcma_bus *bus = cc->core->bus; 167 struct bcma_bus *bus = cc->core->bus;
192 168
193 switch (bus->chipinfo.id) { 169 switch (bus->chipinfo.id) {
194 case 0x4716: 170 case BCMA_CHIP_ID_BCM4716:
195 case 0x4748: 171 case BCMA_CHIP_ID_BCM4748:
196 case 47162: 172 case BCMA_CHIP_ID_BCM47162:
197 case 0x4313: 173 case BCMA_CHIP_ID_BCM4313:
198 case 0x5357: 174 case BCMA_CHIP_ID_BCM5357:
199 case 0x4749: 175 case BCMA_CHIP_ID_BCM4749:
200 case 53572: 176 case BCMA_CHIP_ID_BCM53572:
201 /* always 20Mhz */ 177 /* always 20Mhz */
202 return 20000 * 1000; 178 return 20000 * 1000;
203 case 0x5356: 179 case BCMA_CHIP_ID_BCM5356:
204 case 0x5300: 180 case BCMA_CHIP_ID_BCM4706:
205 /* always 25Mhz */ 181 /* always 25Mhz */
206 return 25000 * 1000; 182 return 25000 * 1000;
207 default: 183 default:
208 pr_warn("No ALP clock specified for %04X device, " 184 bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
209 "pmu rev. %d, using default %d Hz\n", 185 bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
210 bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
211 } 186 }
212 return BCMA_CC_PMU_ALP_CLOCK; 187 return BCMA_CC_PMU_ALP_CLOCK;
213} 188}
@@ -224,7 +199,8 @@ static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
224 199
225 BUG_ON(!m || m > 4); 200 BUG_ON(!m || m > 4);
226 201
227 if (bus->chipinfo.id == 0x5357 || bus->chipinfo.id == 0x4749) { 202 if (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
203 bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) {
228 /* Detect failure in clock setting */ 204 /* Detect failure in clock setting */
229 tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); 205 tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
230 if (tmp & 0x40000) 206 if (tmp & 0x40000)
@@ -250,33 +226,62 @@ static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
250 return (fc / div) * 1000000; 226 return (fc / div) * 1000000;
251} 227}
252 228
229static u32 bcma_pmu_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
230{
231 u32 tmp, ndiv, p1div, p2div;
232 u32 clock;
233
234 BUG_ON(!m || m > 4);
235
236 /* Get N, P1 and P2 dividers to determine CPU clock */
237 tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PMU6_4706_PROCPLL_OFF);
238 ndiv = (tmp & BCMA_CC_PMU6_4706_PROC_NDIV_INT_MASK)
239 >> BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT;
240 p1div = (tmp & BCMA_CC_PMU6_4706_PROC_P1DIV_MASK)
241 >> BCMA_CC_PMU6_4706_PROC_P1DIV_SHIFT;
242 p2div = (tmp & BCMA_CC_PMU6_4706_PROC_P2DIV_MASK)
243 >> BCMA_CC_PMU6_4706_PROC_P2DIV_SHIFT;
244
245 tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
246 if (tmp & BCMA_CC_CHIPST_4706_PKG_OPTION)
247 /* Low cost bonding: Fixed reference clock 25MHz and m = 4 */
248 clock = (25000000 / 4) * ndiv * p2div / p1div;
249 else
250 /* Fixed reference clock 25MHz and m = 2 */
251 clock = (25000000 / 2) * ndiv * p2div / p1div;
252
253 if (m == BCMA_CC_PMU5_MAINPLL_SSB)
254 clock = clock / 4;
255
256 return clock;
257}
258
253/* query bus clock frequency for PMU-enabled chipcommon */ 259/* query bus clock frequency for PMU-enabled chipcommon */
254u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc) 260u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
255{ 261{
256 struct bcma_bus *bus = cc->core->bus; 262 struct bcma_bus *bus = cc->core->bus;
257 263
258 switch (bus->chipinfo.id) { 264 switch (bus->chipinfo.id) {
259 case 0x4716: 265 case BCMA_CHIP_ID_BCM4716:
260 case 0x4748: 266 case BCMA_CHIP_ID_BCM4748:
261 case 47162: 267 case BCMA_CHIP_ID_BCM47162:
262 return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0, 268 return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
263 BCMA_CC_PMU5_MAINPLL_SSB); 269 BCMA_CC_PMU5_MAINPLL_SSB);
264 case 0x5356: 270 case BCMA_CHIP_ID_BCM5356:
265 return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0, 271 return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
266 BCMA_CC_PMU5_MAINPLL_SSB); 272 BCMA_CC_PMU5_MAINPLL_SSB);
267 case 0x5357: 273 case BCMA_CHIP_ID_BCM5357:
268 case 0x4749: 274 case BCMA_CHIP_ID_BCM4749:
269 return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0, 275 return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
270 BCMA_CC_PMU5_MAINPLL_SSB); 276 BCMA_CC_PMU5_MAINPLL_SSB);
271 case 0x5300: 277 case BCMA_CHIP_ID_BCM4706:
272 return bcma_pmu_clock(cc, BCMA_CC_PMU4706_MAINPLL_PLL0, 278 return bcma_pmu_clock_bcm4706(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
273 BCMA_CC_PMU5_MAINPLL_SSB); 279 BCMA_CC_PMU5_MAINPLL_SSB);
274 case 53572: 280 case BCMA_CHIP_ID_BCM53572:
275 return 75000000; 281 return 75000000;
276 default: 282 default:
277 pr_warn("No backplane clock specified for %04X device, " 283 bcma_warn(bus, "No backplane clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
278 "pmu rev. %d, using default %d Hz\n", 284 bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
279 bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
280 } 285 }
281 return BCMA_CC_PMU_HT_CLOCK; 286 return BCMA_CC_PMU_HT_CLOCK;
282} 287}
@@ -286,17 +291,21 @@ u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc)
286{ 291{
287 struct bcma_bus *bus = cc->core->bus; 292 struct bcma_bus *bus = cc->core->bus;
288 293
289 if (bus->chipinfo.id == 53572) 294 if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53572)
290 return 300000000; 295 return 300000000;
291 296
292 if (cc->pmu.rev >= 5) { 297 if (cc->pmu.rev >= 5) {
293 u32 pll; 298 u32 pll;
294 switch (bus->chipinfo.id) { 299 switch (bus->chipinfo.id) {
295 case 0x5356: 300 case BCMA_CHIP_ID_BCM4706:
301 return bcma_pmu_clock_bcm4706(cc,
302 BCMA_CC_PMU4706_MAINPLL_PLL0,
303 BCMA_CC_PMU5_MAINPLL_CPU);
304 case BCMA_CHIP_ID_BCM5356:
296 pll = BCMA_CC_PMU5356_MAINPLL_PLL0; 305 pll = BCMA_CC_PMU5356_MAINPLL_PLL0;
297 break; 306 break;
298 case 0x5357: 307 case BCMA_CHIP_ID_BCM5357:
299 case 0x4749: 308 case BCMA_CHIP_ID_BCM4749:
300 pll = BCMA_CC_PMU5357_MAINPLL_PLL0; 309 pll = BCMA_CC_PMU5357_MAINPLL_PLL0;
301 break; 310 break;
302 default: 311 default:
@@ -304,10 +313,188 @@ u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc)
304 break; 313 break;
305 } 314 }
306 315
307 /* TODO: if (bus->chipinfo.id == 0x5300)
308 return si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU); */
309 return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU); 316 return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
310 } 317 }
311 318
312 return bcma_pmu_get_clockcontrol(cc); 319 return bcma_pmu_get_clockcontrol(cc);
313} 320}
321
322static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset,
323 u32 value)
324{
325 bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
326 bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value);
327}
328
329void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
330{
331 u32 tmp = 0;
332 u8 phypll_offset = 0;
333 u8 bcm5357_bcm43236_p1div[] = {0x1, 0x5, 0x5};
334 u8 bcm5357_bcm43236_ndiv[] = {0x30, 0xf6, 0xfc};
335 struct bcma_bus *bus = cc->core->bus;
336
337 switch (bus->chipinfo.id) {
338 case BCMA_CHIP_ID_BCM5357:
339 case BCMA_CHIP_ID_BCM4749:
340 case BCMA_CHIP_ID_BCM53572:
341 /* 5357[ab]0, 43236[ab]0, and 6362b0 */
342
343 /* BCM5357 needs to touch PLL1_PLLCTL[02],
344 so offset PLL0_PLLCTL[02] by 6 */
345 phypll_offset = (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
346 bus->chipinfo.id == BCMA_CHIP_ID_BCM4749 ||
347 bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) ? 6 : 0;
348
349 /* RMW only the P1 divider */
350 bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR,
351 BCMA_CC_PMU_PLL_CTL0 + phypll_offset);
352 tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
353 tmp &= (~(BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK));
354 tmp |= (bcm5357_bcm43236_p1div[spuravoid] << BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT);
355 bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp);
356
357 /* RMW only the int feedback divider */
358 bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR,
359 BCMA_CC_PMU_PLL_CTL2 + phypll_offset);
360 tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
361 tmp &= ~(BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK);
362 tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT;
363 bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp);
364
365 tmp = 1 << 10;
366 break;
367
368 case BCMA_CHIP_ID_BCM4331:
369 case BCMA_CHIP_ID_BCM43431:
370 if (spuravoid == 2) {
371 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
372 0x11500014);
373 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
374 0x0FC00a08);
375 } else if (spuravoid == 1) {
376 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
377 0x11500014);
378 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
379 0x0F600a08);
380 } else {
381 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
382 0x11100014);
383 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
384 0x03000a08);
385 }
386 tmp = 1 << 10;
387 break;
388
389 case BCMA_CHIP_ID_BCM43224:
390 case BCMA_CHIP_ID_BCM43225:
391 case BCMA_CHIP_ID_BCM43421:
392 if (spuravoid == 1) {
393 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
394 0x11500010);
395 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
396 0x000C0C06);
397 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
398 0x0F600a08);
399 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
400 0x00000000);
401 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
402 0x2001E920);
403 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
404 0x88888815);
405 } else {
406 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
407 0x11100010);
408 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
409 0x000c0c06);
410 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
411 0x03000a08);
412 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
413 0x00000000);
414 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
415 0x200005c0);
416 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
417 0x88888815);
418 }
419 tmp = 1 << 10;
420 break;
421
422 case BCMA_CHIP_ID_BCM4716:
423 case BCMA_CHIP_ID_BCM4748:
424 case BCMA_CHIP_ID_BCM47162:
425 if (spuravoid == 1) {
426 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
427 0x11500060);
428 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
429 0x080C0C06);
430 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
431 0x0F600000);
432 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
433 0x00000000);
434 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
435 0x2001E924);
436 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
437 0x88888815);
438 } else {
439 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
440 0x11100060);
441 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
442 0x080c0c06);
443 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
444 0x03000000);
445 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
446 0x00000000);
447 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
448 0x200005c0);
449 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
450 0x88888815);
451 }
452
453 tmp = 3 << 9;
454 break;
455
456 case BCMA_CHIP_ID_BCM43227:
457 case BCMA_CHIP_ID_BCM43228:
458 case BCMA_CHIP_ID_BCM43428:
459 /* LCNXN */
460 /* PLL Settings for spur avoidance on/off mode,
461 no on2 support for 43228A0 */
462 if (spuravoid == 1) {
463 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
464 0x01100014);
465 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
466 0x040C0C06);
467 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
468 0x03140A08);
469 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
470 0x00333333);
471 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
472 0x202C2820);
473 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
474 0x88888815);
475 } else {
476 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
477 0x11100014);
478 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
479 0x040c0c06);
480 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
481 0x03000a08);
482 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
483 0x00000000);
484 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
485 0x200005c0);
486 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
487 0x88888815);
488 }
489 tmp = 1 << 10;
490 break;
491 default:
492 bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
493 bus->chipinfo.id);
494 break;
495 }
496
497 tmp |= bcma_cc_read32(cc, BCMA_CC_PMU_CTL);
498 bcma_cc_write32(cc, BCMA_CC_PMU_CTL, tmp);
499}
500EXPORT_SYMBOL_GPL(bcma_pmu_spuravoid_pllupdate);
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c
index c3e9dff4224e..ef34ed25bf00 100644
--- a/drivers/bcma/driver_mips.c
+++ b/drivers/bcma/driver_mips.c
@@ -22,15 +22,15 @@
22/* The 47162a0 hangs when reading MIPS DMP registers registers */ 22/* The 47162a0 hangs when reading MIPS DMP registers registers */
23static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev) 23static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
24{ 24{
25 return dev->bus->chipinfo.id == 47162 && dev->bus->chipinfo.rev == 0 && 25 return dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM47162 &&
26 dev->id.id == BCMA_CORE_MIPS_74K; 26 dev->bus->chipinfo.rev == 0 && dev->id.id == BCMA_CORE_MIPS_74K;
27} 27}
28 28
29/* The 5357b0 hangs when reading USB20H DMP registers */ 29/* The 5357b0 hangs when reading USB20H DMP registers */
30static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev) 30static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
31{ 31{
32 return (dev->bus->chipinfo.id == 0x5357 || 32 return (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
33 dev->bus->chipinfo.id == 0x4749) && 33 dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) &&
34 dev->bus->chipinfo.pkg == 11 && 34 dev->bus->chipinfo.pkg == 11 &&
35 dev->id.id == BCMA_CORE_USB20_HOST; 35 dev->id.id == BCMA_CORE_USB20_HOST;
36} 36}
@@ -143,8 +143,8 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
143 1 << irqflag); 143 1 << irqflag);
144 } 144 }
145 145
146 pr_info("set_irq: core 0x%04x, irq %d => %d\n", 146 bcma_info(bus, "set_irq: core 0x%04x, irq %d => %d\n",
147 dev->id.id, oldirq + 2, irq + 2); 147 dev->id.id, oldirq + 2, irq + 2);
148} 148}
149 149
150static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq) 150static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
@@ -173,7 +173,7 @@ u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
173 if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU) 173 if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
174 return bcma_pmu_get_clockcpu(&bus->drv_cc); 174 return bcma_pmu_get_clockcpu(&bus->drv_cc);
175 175
176 pr_err("No PMU available, need this to get the cpu clock\n"); 176 bcma_err(bus, "No PMU available, need this to get the cpu clock\n");
177 return 0; 177 return 0;
178} 178}
179EXPORT_SYMBOL(bcma_cpu_clock); 179EXPORT_SYMBOL(bcma_cpu_clock);
@@ -185,10 +185,10 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
185 switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) { 185 switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
186 case BCMA_CC_FLASHT_STSER: 186 case BCMA_CC_FLASHT_STSER:
187 case BCMA_CC_FLASHT_ATSER: 187 case BCMA_CC_FLASHT_ATSER:
188 pr_err("Serial flash not supported.\n"); 188 bcma_err(bus, "Serial flash not supported.\n");
189 break; 189 break;
190 case BCMA_CC_FLASHT_PARA: 190 case BCMA_CC_FLASHT_PARA:
191 pr_info("found parallel flash.\n"); 191 bcma_info(bus, "found parallel flash.\n");
192 bus->drv_cc.pflash.window = 0x1c000000; 192 bus->drv_cc.pflash.window = 0x1c000000;
193 bus->drv_cc.pflash.window_size = 0x02000000; 193 bus->drv_cc.pflash.window_size = 0x02000000;
194 194
@@ -199,7 +199,7 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
199 bus->drv_cc.pflash.buswidth = 2; 199 bus->drv_cc.pflash.buswidth = 2;
200 break; 200 break;
201 default: 201 default:
202 pr_err("flash not supported.\n"); 202 bcma_err(bus, "flash not supported.\n");
203 } 203 }
204} 204}
205 205
@@ -209,7 +209,7 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
209 struct bcma_device *core; 209 struct bcma_device *core;
210 bus = mcore->core->bus; 210 bus = mcore->core->bus;
211 211
212 pr_info("Initializing MIPS core...\n"); 212 bcma_info(bus, "Initializing MIPS core...\n");
213 213
214 if (!mcore->setup_done) 214 if (!mcore->setup_done)
215 mcore->assigned_irqs = 1; 215 mcore->assigned_irqs = 1;
@@ -244,7 +244,7 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
244 break; 244 break;
245 } 245 }
246 } 246 }
247 pr_info("IRQ reconfiguration done\n"); 247 bcma_info(bus, "IRQ reconfiguration done\n");
248 bcma_core_mips_dump_irq(bus); 248 bcma_core_mips_dump_irq(bus);
249 249
250 if (mcore->setup_done) 250 if (mcore->setup_done)
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c
index b9a86edfec39..cbae2c231336 100644
--- a/drivers/bcma/driver_pci_host.c
+++ b/drivers/bcma/driver_pci_host.c
@@ -36,7 +36,7 @@ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
36 return false; 36 return false;
37 37
38 if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) { 38 if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
39 pr_info("This PCI core is disabled and not working\n"); 39 bcma_info(bus, "This PCI core is disabled and not working\n");
40 return false; 40 return false;
41 } 41 }
42 42
@@ -215,7 +215,8 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
215 } else { 215 } else {
216 writel(val, mmio); 216 writel(val, mmio);
217 217
218 if (chipid == 0x4716 || chipid == 0x4748) 218 if (chipid == BCMA_CHIP_ID_BCM4716 ||
219 chipid == BCMA_CHIP_ID_BCM4748)
219 readl(mmio); 220 readl(mmio);
220 } 221 }
221 222
@@ -340,6 +341,7 @@ static u8 __devinit bcma_find_pci_capability(struct bcma_drv_pci *pc,
340 */ 341 */
341static void __devinit bcma_core_pci_enable_crs(struct bcma_drv_pci *pc) 342static void __devinit bcma_core_pci_enable_crs(struct bcma_drv_pci *pc)
342{ 343{
344 struct bcma_bus *bus = pc->core->bus;
343 u8 cap_ptr, root_ctrl, root_cap, dev; 345 u8 cap_ptr, root_ctrl, root_cap, dev;
344 u16 val16; 346 u16 val16;
345 int i; 347 int i;
@@ -378,7 +380,8 @@ static void __devinit bcma_core_pci_enable_crs(struct bcma_drv_pci *pc)
378 udelay(10); 380 udelay(10);
379 } 381 }
380 if (val16 == 0x1) 382 if (val16 == 0x1)
381 pr_err("PCI: Broken device in slot %d\n", dev); 383 bcma_err(bus, "PCI: Broken device in slot %d\n",
384 dev);
382 } 385 }
383 } 386 }
384} 387}
@@ -391,11 +394,11 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
391 u32 pci_membase_1G; 394 u32 pci_membase_1G;
392 unsigned long io_map_base; 395 unsigned long io_map_base;
393 396
394 pr_info("PCIEcore in host mode found\n"); 397 bcma_info(bus, "PCIEcore in host mode found\n");
395 398
396 pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL); 399 pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL);
397 if (!pc_host) { 400 if (!pc_host) {
398 pr_err("can not allocate memory"); 401 bcma_err(bus, "can not allocate memory");
399 return; 402 return;
400 } 403 }
401 404
@@ -434,13 +437,14 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
434 * as mips can't generate 64-bit address on the 437 * as mips can't generate 64-bit address on the
435 * backplane. 438 * backplane.
436 */ 439 */
437 if (bus->chipinfo.id == 0x4716 || bus->chipinfo.id == 0x4748) { 440 if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4716 ||
441 bus->chipinfo.id == BCMA_CHIP_ID_BCM4748) {
438 pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; 442 pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
439 pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + 443 pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
440 BCMA_SOC_PCI_MEM_SZ - 1; 444 BCMA_SOC_PCI_MEM_SZ - 1;
441 pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, 445 pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
442 BCMA_CORE_PCI_SBTOPCI_MEM | BCMA_SOC_PCI_MEM); 446 BCMA_CORE_PCI_SBTOPCI_MEM | BCMA_SOC_PCI_MEM);
443 } else if (bus->chipinfo.id == 0x5300) { 447 } else if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
444 tmp = BCMA_CORE_PCI_SBTOPCI_MEM; 448 tmp = BCMA_CORE_PCI_SBTOPCI_MEM;
445 tmp |= BCMA_CORE_PCI_SBTOPCI_PREF; 449 tmp |= BCMA_CORE_PCI_SBTOPCI_PREF;
446 tmp |= BCMA_CORE_PCI_SBTOPCI_BURST; 450 tmp |= BCMA_CORE_PCI_SBTOPCI_BURST;
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index 6c05cf470f96..11b32d2642df 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -18,7 +18,7 @@ static void bcma_host_pci_switch_core(struct bcma_device *core)
18 pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2, 18 pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2,
19 core->wrap); 19 core->wrap);
20 core->bus->mapped_core = core; 20 core->bus->mapped_core = core;
21 pr_debug("Switched to core: 0x%X\n", core->id.id); 21 bcma_debug(core->bus, "Switched to core: 0x%X\n", core->id.id);
22} 22}
23 23
24/* Provides access to the requested core. Returns base offset that has to be 24/* Provides access to the requested core. Returns base offset that has to be
@@ -188,7 +188,7 @@ static int __devinit bcma_host_pci_probe(struct pci_dev *dev,
188 188
189 /* SSB needed additional powering up, do we have any AMBA PCI cards? */ 189 /* SSB needed additional powering up, do we have any AMBA PCI cards? */
190 if (!pci_is_pcie(dev)) 190 if (!pci_is_pcie(dev))
191 pr_err("PCI card detected, report problems.\n"); 191 bcma_err(bus, "PCI card detected, report problems.\n");
192 192
193 /* Map MMIO */ 193 /* Map MMIO */
194 err = -ENOMEM; 194 err = -ENOMEM;
@@ -268,6 +268,7 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
268 268
269static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { 269static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
270 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, 270 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
271 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) },
271 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, 272 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
272 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, 273 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
273 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, 274 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 7e138ec21357..7ff4bac6f9e1 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -118,8 +118,9 @@ static int bcma_register_cores(struct bcma_bus *bus)
118 118
119 err = device_register(&core->dev); 119 err = device_register(&core->dev);
120 if (err) { 120 if (err) {
121 pr_err("Could not register dev for core 0x%03X\n", 121 bcma_err(bus,
122 core->id.id); 122 "Could not register dev for core 0x%03X\n",
123 core->id.id);
123 continue; 124 continue;
124 } 125 }
125 core->dev_registered = true; 126 core->dev_registered = true;
@@ -151,7 +152,7 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
151 /* Scan for devices (cores) */ 152 /* Scan for devices (cores) */
152 err = bcma_bus_scan(bus); 153 err = bcma_bus_scan(bus);
153 if (err) { 154 if (err) {
154 pr_err("Failed to scan: %d\n", err); 155 bcma_err(bus, "Failed to scan: %d\n", err);
155 return -1; 156 return -1;
156 } 157 }
157 158
@@ -179,14 +180,14 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
179 /* Try to get SPROM */ 180 /* Try to get SPROM */
180 err = bcma_sprom_get(bus); 181 err = bcma_sprom_get(bus);
181 if (err == -ENOENT) { 182 if (err == -ENOENT) {
182 pr_err("No SPROM available\n"); 183 bcma_err(bus, "No SPROM available\n");
183 } else if (err) 184 } else if (err)
184 pr_err("Failed to get SPROM: %d\n", err); 185 bcma_err(bus, "Failed to get SPROM: %d\n", err);
185 186
186 /* Register found cores */ 187 /* Register found cores */
187 bcma_register_cores(bus); 188 bcma_register_cores(bus);
188 189
189 pr_info("Bus registered\n"); 190 bcma_info(bus, "Bus registered\n");
190 191
191 return 0; 192 return 0;
192} 193}
@@ -214,7 +215,7 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
214 /* Scan for chip common core */ 215 /* Scan for chip common core */
215 err = bcma_bus_scan_early(bus, &match, core_cc); 216 err = bcma_bus_scan_early(bus, &match, core_cc);
216 if (err) { 217 if (err) {
217 pr_err("Failed to scan for common core: %d\n", err); 218 bcma_err(bus, "Failed to scan for common core: %d\n", err);
218 return -1; 219 return -1;
219 } 220 }
220 221
@@ -226,7 +227,7 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
226 /* Scan for mips core */ 227 /* Scan for mips core */
227 err = bcma_bus_scan_early(bus, &match, core_mips); 228 err = bcma_bus_scan_early(bus, &match, core_mips);
228 if (err) { 229 if (err) {
229 pr_err("Failed to scan for mips core: %d\n", err); 230 bcma_err(bus, "Failed to scan for mips core: %d\n", err);
230 return -1; 231 return -1;
231 } 232 }
232 233
@@ -244,7 +245,7 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
244 bcma_core_mips_init(&bus->drv_mips); 245 bcma_core_mips_init(&bus->drv_mips);
245 } 246 }
246 247
247 pr_info("Early bus registered\n"); 248 bcma_info(bus, "Early bus registered\n");
248 249
249 return 0; 250 return 0;
250} 251}
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index a3420585d942..a0272bbfc4f6 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -340,7 +340,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
340 if (tmp <= 0) { 340 if (tmp <= 0) {
341 return -EILSEQ; 341 return -EILSEQ;
342 } else { 342 } else {
343 pr_info("Bridge found\n"); 343 bcma_info(bus, "Bridge found\n");
344 return -ENXIO; 344 return -ENXIO;
345 } 345 }
346 } 346 }
@@ -427,8 +427,8 @@ void bcma_init_bus(struct bcma_bus *bus)
427 chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; 427 chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
428 chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; 428 chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
429 chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; 429 chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
430 pr_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n", 430 bcma_info(bus, "Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n",
431 chipinfo->id, chipinfo->rev, chipinfo->pkg); 431 chipinfo->id, chipinfo->rev, chipinfo->pkg);
432 432
433 bus->init_done = true; 433 bus->init_done = true;
434} 434}
@@ -482,11 +482,10 @@ int bcma_bus_scan(struct bcma_bus *bus)
482 other_core = bcma_find_core_reverse(bus, core->id.id); 482 other_core = bcma_find_core_reverse(bus, core->id.id);
483 core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1; 483 core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1;
484 484
485 pr_info("Core %d found: %s " 485 bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
486 "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", 486 core->core_index, bcma_device_name(&core->id),
487 core->core_index, bcma_device_name(&core->id), 487 core->id.manuf, core->id.id, core->id.rev,
488 core->id.manuf, core->id.id, core->id.rev, 488 core->id.class);
489 core->id.class);
490 489
491 list_add(&core->list, &bus->cores); 490 list_add(&core->list, &bus->cores);
492 } 491 }
@@ -538,11 +537,10 @@ int __init bcma_bus_scan_early(struct bcma_bus *bus,
538 537
539 core->core_index = core_num++; 538 core->core_index = core_num++;
540 bus->nr_cores++; 539 bus->nr_cores++;
541 pr_info("Core %d found: %s " 540 bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
542 "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", 541 core->core_index, bcma_device_name(&core->id),
543 core->core_index, bcma_device_name(&core->id), 542 core->id.manuf, core->id.id, core->id.rev,
544 core->id.manuf, core->id.id, core->id.rev, 543 core->id.class);
545 core->id.class);
546 544
547 list_add(&core->list, &bus->cores); 545 list_add(&core->list, &bus->cores);
548 err = 0; 546 err = 0;
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index f16f42d36071..26823d97fd9f 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -60,11 +60,11 @@ static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus,
60 if (err) 60 if (err)
61 goto fail; 61 goto fail;
62 62
63 pr_debug("Using SPROM revision %d provided by" 63 bcma_debug(bus, "Using SPROM revision %d provided by platform.\n",
64 " platform.\n", bus->sprom.revision); 64 bus->sprom.revision);
65 return 0; 65 return 0;
66fail: 66fail:
67 pr_warn("Using fallback SPROM failed (err %d)\n", err); 67 bcma_warn(bus, "Using fallback SPROM failed (err %d)\n", err);
68 return err; 68 return err;
69} 69}
70 70
@@ -468,11 +468,11 @@ static bool bcma_sprom_ext_available(struct bcma_bus *bus)
468 /* older chipcommon revisions use chip status register */ 468 /* older chipcommon revisions use chip status register */
469 chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT); 469 chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
470 switch (bus->chipinfo.id) { 470 switch (bus->chipinfo.id) {
471 case 0x4313: 471 case BCMA_CHIP_ID_BCM4313:
472 present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT; 472 present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT;
473 break; 473 break;
474 474
475 case 0x4331: 475 case BCMA_CHIP_ID_BCM4331:
476 present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT; 476 present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT;
477 break; 477 break;
478 478
@@ -494,16 +494,16 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
494 494
495 chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT); 495 chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
496 switch (bus->chipinfo.id) { 496 switch (bus->chipinfo.id) {
497 case 0x4313: 497 case BCMA_CHIP_ID_BCM4313:
498 present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT; 498 present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT;
499 break; 499 break;
500 500
501 case 0x4331: 501 case BCMA_CHIP_ID_BCM4331:
502 present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT; 502 present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT;
503 break; 503 break;
504 504
505 case 43224: 505 case BCMA_CHIP_ID_BCM43224:
506 case 43225: 506 case BCMA_CHIP_ID_BCM43225:
507 /* for these chips OTP is always available */ 507 /* for these chips OTP is always available */
508 present = true; 508 present = true;
509 break; 509 break;
@@ -579,13 +579,15 @@ int bcma_sprom_get(struct bcma_bus *bus)
579 if (!sprom) 579 if (!sprom)
580 return -ENOMEM; 580 return -ENOMEM;
581 581
582 if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431) 582 if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 ||
583 bus->chipinfo.id == BCMA_CHIP_ID_BCM43431)
583 bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); 584 bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
584 585
585 pr_debug("SPROM offset 0x%x\n", offset); 586 bcma_debug(bus, "SPROM offset 0x%x\n", offset);
586 bcma_sprom_read(bus, offset, sprom); 587 bcma_sprom_read(bus, offset, sprom);
587 588
588 if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431) 589 if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 ||
590 bus->chipinfo.id == BCMA_CHIP_ID_BCM43431)
589 bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); 591 bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
590 592
591 err = bcma_sprom_valid(sprom); 593 err = bcma_sprom_valid(sprom);
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 2661f6e366f9..154f3ef07631 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -511,7 +511,6 @@ config USB_SWITCH_FSA9480
511source "drivers/misc/c2port/Kconfig" 511source "drivers/misc/c2port/Kconfig"
512source "drivers/misc/eeprom/Kconfig" 512source "drivers/misc/eeprom/Kconfig"
513source "drivers/misc/cb710/Kconfig" 513source "drivers/misc/cb710/Kconfig"
514source "drivers/misc/iwmc3200top/Kconfig"
515source "drivers/misc/ti-st/Kconfig" 514source "drivers/misc/ti-st/Kconfig"
516source "drivers/misc/lis3lv02d/Kconfig" 515source "drivers/misc/lis3lv02d/Kconfig"
517source "drivers/misc/carma/Kconfig" 516source "drivers/misc/carma/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 456972faaeb3..b88df7a350b8 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -36,7 +36,6 @@ obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o
36obj-$(CONFIG_DS1682) += ds1682.o 36obj-$(CONFIG_DS1682) += ds1682.o
37obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o 37obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o
38obj-$(CONFIG_C2PORT) += c2port/ 38obj-$(CONFIG_C2PORT) += c2port/
39obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/
40obj-$(CONFIG_HMC6352) += hmc6352.o 39obj-$(CONFIG_HMC6352) += hmc6352.o
41obj-y += eeprom/ 40obj-y += eeprom/
42obj-y += cb710/ 41obj-y += cb710/
diff --git a/drivers/misc/iwmc3200top/Kconfig b/drivers/misc/iwmc3200top/Kconfig
deleted file mode 100644
index 9e4b88fb57f1..000000000000
--- a/drivers/misc/iwmc3200top/Kconfig
+++ /dev/null
@@ -1,20 +0,0 @@
1config IWMC3200TOP
2 tristate "Intel Wireless MultiCom Top Driver"
3 depends on MMC && EXPERIMENTAL
4 select FW_LOADER
5 ---help---
6 Intel Wireless MultiCom 3200 Top driver is responsible for
7 for firmware load and enabled coms enumeration
8
9config IWMC3200TOP_DEBUG
10 bool "Enable full debug output of iwmc3200top Driver"
11 depends on IWMC3200TOP
12 ---help---
13 Enable full debug output of iwmc3200top Driver
14
15config IWMC3200TOP_DEBUGFS
16 bool "Enable Debugfs debugging interface for iwmc3200top"
17 depends on IWMC3200TOP
18 ---help---
19 Enable creation of debugfs files for iwmc3200top
20
diff --git a/drivers/misc/iwmc3200top/Makefile b/drivers/misc/iwmc3200top/Makefile
deleted file mode 100644
index fbf53fb4634e..000000000000
--- a/drivers/misc/iwmc3200top/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
1# iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
2# drivers/misc/iwmc3200top/Makefile
3#
4# Copyright (C) 2009 Intel Corporation. All rights reserved.
5#
6# This program is free software; you can redistribute it and/or
7# modify it under the terms of the GNU General Public License version
8# 2 as published by the Free Software Foundation.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18# 02110-1301, USA.
19#
20#
21# Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
22# -
23#
24#
25
26obj-$(CONFIG_IWMC3200TOP) += iwmc3200top.o
27iwmc3200top-objs := main.o fw-download.o
28iwmc3200top-$(CONFIG_IWMC3200TOP_DEBUG) += log.o
29iwmc3200top-$(CONFIG_IWMC3200TOP_DEBUGFS) += debugfs.o
diff --git a/drivers/misc/iwmc3200top/debugfs.c b/drivers/misc/iwmc3200top/debugfs.c
deleted file mode 100644
index 62fbaec48207..000000000000
--- a/drivers/misc/iwmc3200top/debugfs.c
+++ /dev/null
@@ -1,137 +0,0 @@
1/*
2 * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
3 * drivers/misc/iwmc3200top/debufs.c
4 *
5 * Copyright (C) 2009 Intel Corporation. All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301, USA.
20 *
21 *
22 * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
23 * -
24 *
25 */
26
27#include <linux/kernel.h>
28#include <linux/slab.h>
29#include <linux/string.h>
30#include <linux/ctype.h>
31#include <linux/mmc/sdio_func.h>
32#include <linux/mmc/sdio.h>
33#include <linux/debugfs.h>
34
35#include "iwmc3200top.h"
36#include "fw-msg.h"
37#include "log.h"
38#include "debugfs.h"
39
40
41
42/* Constants definition */
43#define HEXADECIMAL_RADIX 16
44
45/* Functions definition */
46
47
48#define DEBUGFS_ADD(name, parent) do { \
49 dbgfs->dbgfs_##parent##_files.file_##name = \
50 debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv, \
51 &iwmct_dbgfs_##name##_ops); \
52} while (0)
53
54#define DEBUGFS_RM(name) do { \
55 debugfs_remove(name); \
56 name = NULL; \
57} while (0)
58
59#define DEBUGFS_READ_FUNC(name) \
60ssize_t iwmct_dbgfs_##name##_read(struct file *file, \
61 char __user *user_buf, \
62 size_t count, loff_t *ppos);
63
64#define DEBUGFS_WRITE_FUNC(name) \
65ssize_t iwmct_dbgfs_##name##_write(struct file *file, \
66 const char __user *user_buf, \
67 size_t count, loff_t *ppos);
68
69#define DEBUGFS_READ_FILE_OPS(name) \
70 DEBUGFS_READ_FUNC(name) \
71 static const struct file_operations iwmct_dbgfs_##name##_ops = { \
72 .read = iwmct_dbgfs_##name##_read, \
73 .open = iwmct_dbgfs_open_file_generic, \
74 .llseek = generic_file_llseek, \
75 };
76
77#define DEBUGFS_WRITE_FILE_OPS(name) \
78 DEBUGFS_WRITE_FUNC(name) \
79 static const struct file_operations iwmct_dbgfs_##name##_ops = { \
80 .write = iwmct_dbgfs_##name##_write, \
81 .open = iwmct_dbgfs_open_file_generic, \
82 .llseek = generic_file_llseek, \
83 };
84
85#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
86 DEBUGFS_READ_FUNC(name) \
87 DEBUGFS_WRITE_FUNC(name) \
88 static const struct file_operations iwmct_dbgfs_##name##_ops = {\
89 .write = iwmct_dbgfs_##name##_write, \
90 .read = iwmct_dbgfs_##name##_read, \
91 .open = iwmct_dbgfs_open_file_generic, \
92 .llseek = generic_file_llseek, \
93 };
94
95
96/* Debugfs file ops definitions */
97
98/*
99 * Create the debugfs files and directories
100 *
101 */
102void iwmct_dbgfs_register(struct iwmct_priv *priv, const char *name)
103{
104 struct iwmct_debugfs *dbgfs;
105
106 dbgfs = kzalloc(sizeof(struct iwmct_debugfs), GFP_KERNEL);
107 if (!dbgfs) {
108 LOG_ERROR(priv, DEBUGFS, "failed to allocate %zd bytes\n",
109 sizeof(struct iwmct_debugfs));
110 return;
111 }
112
113 priv->dbgfs = dbgfs;
114 dbgfs->name = name;
115 dbgfs->dir_drv = debugfs_create_dir(name, NULL);
116 if (!dbgfs->dir_drv) {
117 LOG_ERROR(priv, DEBUGFS, "failed to create debugfs dir\n");
118 return;
119 }
120
121 return;
122}
123
124/**
125 * Remove the debugfs files and directories
126 *
127 */
128void iwmct_dbgfs_unregister(struct iwmct_debugfs *dbgfs)
129{
130 if (!dbgfs)
131 return;
132
133 DEBUGFS_RM(dbgfs->dir_drv);
134 kfree(dbgfs);
135 dbgfs = NULL;
136}
137
diff --git a/drivers/misc/iwmc3200top/debugfs.h b/drivers/misc/iwmc3200top/debugfs.h
deleted file mode 100644
index 71d45759b40f..000000000000
--- a/drivers/misc/iwmc3200top/debugfs.h
+++ /dev/null
@@ -1,58 +0,0 @@
1/*
2 * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
3 * drivers/misc/iwmc3200top/debufs.h
4 *
5 * Copyright (C) 2009 Intel Corporation. All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301, USA.
20 *
21 *
22 * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
23 * -
24 *
25 */
26
27#ifndef __DEBUGFS_H__
28#define __DEBUGFS_H__
29
30
31#ifdef CONFIG_IWMC3200TOP_DEBUGFS
32
33struct iwmct_debugfs {
34 const char *name;
35 struct dentry *dir_drv;
36 struct dir_drv_files {
37 } dbgfs_drv_files;
38};
39
40void iwmct_dbgfs_register(struct iwmct_priv *priv, const char *name);
41void iwmct_dbgfs_unregister(struct iwmct_debugfs *dbgfs);
42
43#else /* CONFIG_IWMC3200TOP_DEBUGFS */
44
45struct iwmct_debugfs;
46
47static inline void
48iwmct_dbgfs_register(struct iwmct_priv *priv, const char *name)
49{}
50
51static inline void
52iwmct_dbgfs_unregister(struct iwmct_debugfs *dbgfs)
53{}
54
55#endif /* CONFIG_IWMC3200TOP_DEBUGFS */
56
57#endif /* __DEBUGFS_H__ */
58
diff --git a/drivers/misc/iwmc3200top/fw-download.c b/drivers/misc/iwmc3200top/fw-download.c
deleted file mode 100644
index e27afde6e99f..000000000000
--- a/drivers/misc/iwmc3200top/fw-download.c
+++ /dev/null
@@ -1,358 +0,0 @@
1/*
2 * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
3 * drivers/misc/iwmc3200top/fw-download.c
4 *
5 * Copyright (C) 2009 Intel Corporation. All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301, USA.
20 *
21 *
22 * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
23 * -
24 *
25 */
26
27#include <linux/firmware.h>
28#include <linux/mmc/sdio_func.h>
29#include <linux/slab.h>
30#include <asm/unaligned.h>
31
32#include "iwmc3200top.h"
33#include "log.h"
34#include "fw-msg.h"
35
36#define CHECKSUM_BYTES_NUM sizeof(u32)
37
38/**
39 init parser struct with file
40 */
41static int iwmct_fw_parser_init(struct iwmct_priv *priv, const u8 *file,
42 size_t file_size, size_t block_size)
43{
44 struct iwmct_parser *parser = &priv->parser;
45 struct iwmct_fw_hdr *fw_hdr = &parser->versions;
46
47 LOG_TRACE(priv, FW_DOWNLOAD, "-->\n");
48
49 LOG_INFO(priv, FW_DOWNLOAD, "file_size=%zd\n", file_size);
50
51 parser->file = file;
52 parser->file_size = file_size;
53 parser->cur_pos = 0;
54 parser->entry_point = 0;
55 parser->buf = kzalloc(block_size, GFP_KERNEL);
56 if (!parser->buf) {
57 LOG_ERROR(priv, FW_DOWNLOAD, "kzalloc error\n");
58 return -ENOMEM;
59 }
60 parser->buf_size = block_size;
61
62 /* extract fw versions */
63 memcpy(fw_hdr, parser->file, sizeof(struct iwmct_fw_hdr));
64 LOG_INFO(priv, FW_DOWNLOAD, "fw versions are:\n"
65 "top %u.%u.%u gps %u.%u.%u bt %u.%u.%u tic %s\n",
66 fw_hdr->top_major, fw_hdr->top_minor, fw_hdr->top_revision,
67 fw_hdr->gps_major, fw_hdr->gps_minor, fw_hdr->gps_revision,
68 fw_hdr->bt_major, fw_hdr->bt_minor, fw_hdr->bt_revision,
69 fw_hdr->tic_name);
70
71 parser->cur_pos += sizeof(struct iwmct_fw_hdr);
72
73 LOG_TRACE(priv, FW_DOWNLOAD, "<--\n");
74 return 0;
75}
76
77static bool iwmct_checksum(struct iwmct_priv *priv)
78{
79 struct iwmct_parser *parser = &priv->parser;
80 __le32 *file = (__le32 *)parser->file;
81 int i, pad, steps;
82 u32 accum = 0;
83 u32 checksum;
84 u32 mask = 0xffffffff;
85
86 pad = (parser->file_size - CHECKSUM_BYTES_NUM) % 4;
87 steps = (parser->file_size - CHECKSUM_BYTES_NUM) / 4;
88
89 LOG_INFO(priv, FW_DOWNLOAD, "pad=%d steps=%d\n", pad, steps);
90
91 for (i = 0; i < steps; i++)
92 accum += le32_to_cpu(file[i]);
93
94 if (pad) {
95 mask <<= 8 * (4 - pad);
96 accum += le32_to_cpu(file[steps]) & mask;
97 }
98
99 checksum = get_unaligned_le32((__le32 *)(parser->file +
100 parser->file_size - CHECKSUM_BYTES_NUM));
101
102 LOG_INFO(priv, FW_DOWNLOAD,
103 "compare checksum accum=0x%x to checksum=0x%x\n",
104 accum, checksum);
105
106 return checksum == accum;
107}
108
109static int iwmct_parse_next_section(struct iwmct_priv *priv, const u8 **p_sec,
110 size_t *sec_size, __le32 *sec_addr)
111{
112 struct iwmct_parser *parser = &priv->parser;
113 struct iwmct_dbg *dbg = &priv->dbg;
114 struct iwmct_fw_sec_hdr *sec_hdr;
115
116 LOG_TRACE(priv, FW_DOWNLOAD, "-->\n");
117
118 while (parser->cur_pos + sizeof(struct iwmct_fw_sec_hdr)
119 <= parser->file_size) {
120
121 sec_hdr = (struct iwmct_fw_sec_hdr *)
122 (parser->file + parser->cur_pos);
123 parser->cur_pos += sizeof(struct iwmct_fw_sec_hdr);
124
125 LOG_INFO(priv, FW_DOWNLOAD,
126 "sec hdr: type=%s addr=0x%x size=%d\n",
127 sec_hdr->type, sec_hdr->target_addr,
128 sec_hdr->data_size);
129
130 if (strcmp(sec_hdr->type, "ENT") == 0)
131 parser->entry_point = le32_to_cpu(sec_hdr->target_addr);
132 else if (strcmp(sec_hdr->type, "LBL") == 0)
133 strcpy(dbg->label_fw, parser->file + parser->cur_pos);
134 else if (((strcmp(sec_hdr->type, "TOP") == 0) &&
135 (priv->barker & BARKER_DNLOAD_TOP_MSK)) ||
136 ((strcmp(sec_hdr->type, "GPS") == 0) &&
137 (priv->barker & BARKER_DNLOAD_GPS_MSK)) ||
138 ((strcmp(sec_hdr->type, "BTH") == 0) &&
139 (priv->barker & BARKER_DNLOAD_BT_MSK))) {
140 *sec_addr = sec_hdr->target_addr;
141 *sec_size = le32_to_cpu(sec_hdr->data_size);
142 *p_sec = parser->file + parser->cur_pos;
143 parser->cur_pos += le32_to_cpu(sec_hdr->data_size);
144 return 1;
145 } else if (strcmp(sec_hdr->type, "LOG") != 0)
146 LOG_WARNING(priv, FW_DOWNLOAD,
147 "skipping section type %s\n",
148 sec_hdr->type);
149
150 parser->cur_pos += le32_to_cpu(sec_hdr->data_size);
151 LOG_INFO(priv, FW_DOWNLOAD,
152 "finished with section cur_pos=%zd\n", parser->cur_pos);
153 }
154
155 LOG_TRACE(priv, INIT, "<--\n");
156 return 0;
157}
158
159static int iwmct_download_section(struct iwmct_priv *priv, const u8 *p_sec,
160 size_t sec_size, __le32 addr)
161{
162 struct iwmct_parser *parser = &priv->parser;
163 struct iwmct_fw_load_hdr *hdr = (struct iwmct_fw_load_hdr *)parser->buf;
164 const u8 *cur_block = p_sec;
165 size_t sent = 0;
166 int cnt = 0;
167 int ret = 0;
168 u32 cmd = 0;
169
170 LOG_TRACE(priv, FW_DOWNLOAD, "-->\n");
171 LOG_INFO(priv, FW_DOWNLOAD, "Download address 0x%x size 0x%zx\n",
172 addr, sec_size);
173
174 while (sent < sec_size) {
175 int i;
176 u32 chksm = 0;
177 u32 reset = atomic_read(&priv->reset);
178 /* actual FW data */
179 u32 data_size = min(parser->buf_size - sizeof(*hdr),
180 sec_size - sent);
181 /* Pad to block size */
182 u32 trans_size = (data_size + sizeof(*hdr) +
183 IWMC_SDIO_BLK_SIZE - 1) &
184 ~(IWMC_SDIO_BLK_SIZE - 1);
185 ++cnt;
186
187 /* in case of reset, interrupt FW DOWNLAOD */
188 if (reset) {
189 LOG_INFO(priv, FW_DOWNLOAD,
190 "Reset detected. Abort FW download!!!");
191 ret = -ECANCELED;
192 goto exit;
193 }
194
195 memset(parser->buf, 0, parser->buf_size);
196 cmd |= IWMC_OPCODE_WRITE << CMD_HDR_OPCODE_POS;
197 cmd |= IWMC_CMD_SIGNATURE << CMD_HDR_SIGNATURE_POS;
198 cmd |= (priv->dbg.direct ? 1 : 0) << CMD_HDR_DIRECT_ACCESS_POS;
199 cmd |= (priv->dbg.checksum ? 1 : 0) << CMD_HDR_USE_CHECKSUM_POS;
200 hdr->data_size = cpu_to_le32(data_size);
201 hdr->target_addr = addr;
202
203 /* checksum is allowed for sizes divisible by 4 */
204 if (data_size & 0x3)
205 cmd &= ~CMD_HDR_USE_CHECKSUM_MSK;
206
207 memcpy(hdr->data, cur_block, data_size);
208
209
210 if (cmd & CMD_HDR_USE_CHECKSUM_MSK) {
211
212 chksm = data_size + le32_to_cpu(addr) + cmd;
213 for (i = 0; i < data_size >> 2; i++)
214 chksm += ((u32 *)cur_block)[i];
215
216 hdr->block_chksm = cpu_to_le32(chksm);
217 LOG_INFO(priv, FW_DOWNLOAD, "Checksum = 0x%X\n",
218 hdr->block_chksm);
219 }
220
221 LOG_INFO(priv, FW_DOWNLOAD, "trans#%d, len=%d, sent=%zd, "
222 "sec_size=%zd, startAddress 0x%X\n",
223 cnt, trans_size, sent, sec_size, addr);
224
225 if (priv->dbg.dump)
226 LOG_HEXDUMP(FW_DOWNLOAD, parser->buf, trans_size);
227
228
229 hdr->cmd = cpu_to_le32(cmd);
230 /* send it down */
231 /* TODO: add more proper sending and error checking */
232 ret = iwmct_tx(priv, parser->buf, trans_size);
233 if (ret != 0) {
234 LOG_INFO(priv, FW_DOWNLOAD,
235 "iwmct_tx returned %d\n", ret);
236 goto exit;
237 }
238
239 addr = cpu_to_le32(le32_to_cpu(addr) + data_size);
240 sent += data_size;
241 cur_block = p_sec + sent;
242
243 if (priv->dbg.blocks && (cnt + 1) >= priv->dbg.blocks) {
244 LOG_INFO(priv, FW_DOWNLOAD,
245 "Block number limit is reached [%d]\n",
246 priv->dbg.blocks);
247 break;
248 }
249 }
250
251 if (sent < sec_size)
252 ret = -EINVAL;
253exit:
254 LOG_TRACE(priv, FW_DOWNLOAD, "<--\n");
255 return ret;
256}
257
258static int iwmct_kick_fw(struct iwmct_priv *priv, bool jump)
259{
260 struct iwmct_parser *parser = &priv->parser;
261 struct iwmct_fw_load_hdr *hdr = (struct iwmct_fw_load_hdr *)parser->buf;
262 int ret;
263 u32 cmd;
264
265 LOG_TRACE(priv, FW_DOWNLOAD, "-->\n");
266
267 memset(parser->buf, 0, parser->buf_size);
268 cmd = IWMC_CMD_SIGNATURE << CMD_HDR_SIGNATURE_POS;
269 if (jump) {
270 cmd |= IWMC_OPCODE_JUMP << CMD_HDR_OPCODE_POS;
271 hdr->target_addr = cpu_to_le32(parser->entry_point);
272 LOG_INFO(priv, FW_DOWNLOAD, "jump address 0x%x\n",
273 parser->entry_point);
274 } else {
275 cmd |= IWMC_OPCODE_LAST_COMMAND << CMD_HDR_OPCODE_POS;
276 LOG_INFO(priv, FW_DOWNLOAD, "last command\n");
277 }
278
279 hdr->cmd = cpu_to_le32(cmd);
280
281 LOG_HEXDUMP(FW_DOWNLOAD, parser->buf, sizeof(*hdr));
282 /* send it down */
283 /* TODO: add more proper sending and error checking */
284 ret = iwmct_tx(priv, parser->buf, IWMC_SDIO_BLK_SIZE);
285 if (ret)
286 LOG_INFO(priv, FW_DOWNLOAD, "iwmct_tx returned %d", ret);
287
288 LOG_TRACE(priv, FW_DOWNLOAD, "<--\n");
289 return 0;
290}
291
292int iwmct_fw_load(struct iwmct_priv *priv)
293{
294 const u8 *fw_name = FW_NAME(FW_API_VER);
295 const struct firmware *raw;
296 const u8 *pdata;
297 size_t len;
298 __le32 addr;
299 int ret;
300
301
302 LOG_INFO(priv, FW_DOWNLOAD, "barker download request 0x%x is:\n",
303 priv->barker);
304 LOG_INFO(priv, FW_DOWNLOAD, "******* Top FW %s requested ********\n",
305 (priv->barker & BARKER_DNLOAD_TOP_MSK) ? "was" : "not");
306 LOG_INFO(priv, FW_DOWNLOAD, "******* GPS FW %s requested ********\n",
307 (priv->barker & BARKER_DNLOAD_GPS_MSK) ? "was" : "not");
308 LOG_INFO(priv, FW_DOWNLOAD, "******* BT FW %s requested ********\n",
309 (priv->barker & BARKER_DNLOAD_BT_MSK) ? "was" : "not");
310
311
312 /* get the firmware */
313 ret = request_firmware(&raw, fw_name, &priv->func->dev);
314 if (ret < 0) {
315 LOG_ERROR(priv, FW_DOWNLOAD, "%s request_firmware failed %d\n",
316 fw_name, ret);
317 goto exit;
318 }
319
320 if (raw->size < sizeof(struct iwmct_fw_sec_hdr)) {
321 LOG_ERROR(priv, FW_DOWNLOAD, "%s smaller then (%zd) (%zd)\n",
322 fw_name, sizeof(struct iwmct_fw_sec_hdr), raw->size);
323 goto exit;
324 }
325
326 LOG_INFO(priv, FW_DOWNLOAD, "Read firmware '%s'\n", fw_name);
327
328 /* clear parser struct */
329 ret = iwmct_fw_parser_init(priv, raw->data, raw->size, priv->trans_len);
330 if (ret < 0) {
331 LOG_ERROR(priv, FW_DOWNLOAD,
332 "iwmct_parser_init failed: Reason %d\n", ret);
333 goto exit;
334 }
335
336 if (!iwmct_checksum(priv)) {
337 LOG_ERROR(priv, FW_DOWNLOAD, "checksum error\n");
338 ret = -EINVAL;
339 goto exit;
340 }
341
342 /* download firmware to device */
343 while (iwmct_parse_next_section(priv, &pdata, &len, &addr)) {
344 ret = iwmct_download_section(priv, pdata, len, addr);
345 if (ret) {
346 LOG_ERROR(priv, FW_DOWNLOAD,
347 "%s download section failed\n", fw_name);
348 goto exit;
349 }
350 }
351
352 ret = iwmct_kick_fw(priv, !!(priv->barker & BARKER_DNLOAD_JUMP_MSK));
353
354exit:
355 kfree(priv->parser.buf);
356 release_firmware(raw);
357 return ret;
358}
diff --git a/drivers/misc/iwmc3200top/fw-msg.h b/drivers/misc/iwmc3200top/fw-msg.h
deleted file mode 100644
index 9e26b75bd482..000000000000
--- a/drivers/misc/iwmc3200top/fw-msg.h
+++ /dev/null
@@ -1,113 +0,0 @@
1/*
2 * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
3 * drivers/misc/iwmc3200top/fw-msg.h
4 *
5 * Copyright (C) 2009 Intel Corporation. All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301, USA.
20 *
21 *
22 * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
23 * -
24 *
25 */
26
27#ifndef __FWMSG_H__
28#define __FWMSG_H__
29
30#define COMM_TYPE_D2H 0xFF
31#define COMM_TYPE_H2D 0xEE
32
33#define COMM_CATEGORY_OPERATIONAL 0x00
34#define COMM_CATEGORY_DEBUG 0x01
35#define COMM_CATEGORY_TESTABILITY 0x02
36#define COMM_CATEGORY_DIAGNOSTICS 0x03
37
38#define OP_DBG_ZSTR_MSG cpu_to_le16(0x1A)
39
40#define FW_LOG_SRC_MAX 32
41#define FW_LOG_SRC_ALL 255
42
43#define FW_STRING_TABLE_ADDR cpu_to_le32(0x0C000000)
44
45#define CMD_DBG_LOG_LEVEL cpu_to_le16(0x0001)
46#define CMD_TST_DEV_RESET cpu_to_le16(0x0060)
47#define CMD_TST_FUNC_RESET cpu_to_le16(0x0062)
48#define CMD_TST_IFACE_RESET cpu_to_le16(0x0064)
49#define CMD_TST_CPU_UTILIZATION cpu_to_le16(0x0065)
50#define CMD_TST_TOP_DEEP_SLEEP cpu_to_le16(0x0080)
51#define CMD_TST_WAKEUP cpu_to_le16(0x0081)
52#define CMD_TST_FUNC_WAKEUP cpu_to_le16(0x0082)
53#define CMD_TST_FUNC_DEEP_SLEEP_REQUEST cpu_to_le16(0x0083)
54#define CMD_TST_GET_MEM_DUMP cpu_to_le16(0x0096)
55
56#define OP_OPR_ALIVE cpu_to_le16(0x0010)
57#define OP_OPR_CMD_ACK cpu_to_le16(0x001F)
58#define OP_OPR_CMD_NACK cpu_to_le16(0x0020)
59#define OP_TST_MEM_DUMP cpu_to_le16(0x0043)
60
61#define CMD_FLAG_PADDING_256 0x80
62
63#define FW_HCMD_BLOCK_SIZE 256
64
65struct msg_hdr {
66 u8 type;
67 u8 category;
68 __le16 opcode;
69 u8 seqnum;
70 u8 flags;
71 __le16 length;
72} __attribute__((__packed__));
73
74struct log_hdr {
75 __le32 timestamp;
76 u8 severity;
77 u8 logsource;
78 __le16 reserved;
79} __attribute__((__packed__));
80
81struct mdump_hdr {
82 u8 dmpid;
83 u8 frag;
84 __le16 size;
85 __le32 addr;
86} __attribute__((__packed__));
87
88struct top_msg {
89 struct msg_hdr hdr;
90 union {
91 /* D2H messages */
92 struct {
93 struct log_hdr log_hdr;
94 u8 data[1];
95 } __attribute__((__packed__)) log;
96
97 struct {
98 struct log_hdr log_hdr;
99 struct mdump_hdr md_hdr;
100 u8 data[1];
101 } __attribute__((__packed__)) mdump;
102
103 /* H2D messages */
104 struct {
105 u8 logsource;
106 u8 sevmask;
107 } __attribute__((__packed__)) logdefs[FW_LOG_SRC_MAX];
108 struct mdump_hdr mdump_req;
109 } u;
110} __attribute__((__packed__));
111
112
113#endif /* __FWMSG_H__ */
diff --git a/drivers/misc/iwmc3200top/iwmc3200top.h b/drivers/misc/iwmc3200top/iwmc3200top.h
deleted file mode 100644
index 620973ed8bf9..000000000000
--- a/drivers/misc/iwmc3200top/iwmc3200top.h
+++ /dev/null
@@ -1,205 +0,0 @@
1/*
2 * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
3 * drivers/misc/iwmc3200top/iwmc3200top.h
4 *
5 * Copyright (C) 2009 Intel Corporation. All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301, USA.
20 *
21 *
22 * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
23 * -
24 *
25 */
26
27#ifndef __IWMC3200TOP_H__
28#define __IWMC3200TOP_H__
29
30#include <linux/workqueue.h>
31
32#define DRV_NAME "iwmc3200top"
33#define FW_API_VER 1
34#define _FW_NAME(api) DRV_NAME "." #api ".fw"
35#define FW_NAME(api) _FW_NAME(api)
36
37#define IWMC_SDIO_BLK_SIZE 256
38#define IWMC_DEFAULT_TR_BLK 64
39#define IWMC_SDIO_DATA_ADDR 0x0
40#define IWMC_SDIO_INTR_ENABLE_ADDR 0x14
41#define IWMC_SDIO_INTR_STATUS_ADDR 0x13
42#define IWMC_SDIO_INTR_CLEAR_ADDR 0x13
43#define IWMC_SDIO_INTR_GET_SIZE_ADDR 0x2C
44
45#define COMM_HUB_HEADER_LENGTH 16
46#define LOGGER_HEADER_LENGTH 10
47
48
49#define BARKER_DNLOAD_BT_POS 0
50#define BARKER_DNLOAD_BT_MSK BIT(BARKER_DNLOAD_BT_POS)
51#define BARKER_DNLOAD_GPS_POS 1
52#define BARKER_DNLOAD_GPS_MSK BIT(BARKER_DNLOAD_GPS_POS)
53#define BARKER_DNLOAD_TOP_POS 2
54#define BARKER_DNLOAD_TOP_MSK BIT(BARKER_DNLOAD_TOP_POS)
55#define BARKER_DNLOAD_RESERVED1_POS 3
56#define BARKER_DNLOAD_RESERVED1_MSK BIT(BARKER_DNLOAD_RESERVED1_POS)
57#define BARKER_DNLOAD_JUMP_POS 4
58#define BARKER_DNLOAD_JUMP_MSK BIT(BARKER_DNLOAD_JUMP_POS)
59#define BARKER_DNLOAD_SYNC_POS 5
60#define BARKER_DNLOAD_SYNC_MSK BIT(BARKER_DNLOAD_SYNC_POS)
61#define BARKER_DNLOAD_RESERVED2_POS 6
62#define BARKER_DNLOAD_RESERVED2_MSK (0x3 << BARKER_DNLOAD_RESERVED2_POS)
63#define BARKER_DNLOAD_BARKER_POS 8
64#define BARKER_DNLOAD_BARKER_MSK (0xffffff << BARKER_DNLOAD_BARKER_POS)
65
66#define IWMC_BARKER_REBOOT (0xdeadbe << BARKER_DNLOAD_BARKER_POS)
67/* whole field barker */
68#define IWMC_BARKER_ACK 0xfeedbabe
69
70#define IWMC_CMD_SIGNATURE 0xcbbc
71
72#define CMD_HDR_OPCODE_POS 0
73#define CMD_HDR_OPCODE_MSK_MSK (0xf << CMD_HDR_OPCODE_MSK_POS)
74#define CMD_HDR_RESPONSE_CODE_POS 4
75#define CMD_HDR_RESPONSE_CODE_MSK (0xf << CMD_HDR_RESPONSE_CODE_POS)
76#define CMD_HDR_USE_CHECKSUM_POS 8
77#define CMD_HDR_USE_CHECKSUM_MSK BIT(CMD_HDR_USE_CHECKSUM_POS)
78#define CMD_HDR_RESPONSE_REQUIRED_POS 9
79#define CMD_HDR_RESPONSE_REQUIRED_MSK BIT(CMD_HDR_RESPONSE_REQUIRED_POS)
80#define CMD_HDR_DIRECT_ACCESS_POS 10
81#define CMD_HDR_DIRECT_ACCESS_MSK BIT(CMD_HDR_DIRECT_ACCESS_POS)
82#define CMD_HDR_RESERVED_POS 11
83#define CMD_HDR_RESERVED_MSK BIT(0x1f << CMD_HDR_RESERVED_POS)
84#define CMD_HDR_SIGNATURE_POS 16
85#define CMD_HDR_SIGNATURE_MSK BIT(0xffff << CMD_HDR_SIGNATURE_POS)
86
87enum {
88 IWMC_OPCODE_PING = 0,
89 IWMC_OPCODE_READ = 1,
90 IWMC_OPCODE_WRITE = 2,
91 IWMC_OPCODE_JUMP = 3,
92 IWMC_OPCODE_REBOOT = 4,
93 IWMC_OPCODE_PERSISTENT_WRITE = 5,
94 IWMC_OPCODE_PERSISTENT_READ = 6,
95 IWMC_OPCODE_READ_MODIFY_WRITE = 7,
96 IWMC_OPCODE_LAST_COMMAND = 15
97};
98
99struct iwmct_fw_load_hdr {
100 __le32 cmd;
101 __le32 target_addr;
102 __le32 data_size;
103 __le32 block_chksm;
104 u8 data[0];
105};
106
107/**
108 * struct iwmct_fw_hdr
109 * holds all sw components versions
110 */
111struct iwmct_fw_hdr {
112 u8 top_major;
113 u8 top_minor;
114 u8 top_revision;
115 u8 gps_major;
116 u8 gps_minor;
117 u8 gps_revision;
118 u8 bt_major;
119 u8 bt_minor;
120 u8 bt_revision;
121 u8 tic_name[31];
122};
123
124/**
125 * struct iwmct_fw_sec_hdr
126 * @type: function type
127 * @data_size: section's data size
128 * @target_addr: download address
129 */
130struct iwmct_fw_sec_hdr {
131 u8 type[4];
132 __le32 data_size;
133 __le32 target_addr;
134};
135
136/**
137 * struct iwmct_parser
138 * @file: fw image
139 * @file_size: fw size
140 * @cur_pos: position in file
141 * @buf: temp buf for download
142 * @buf_size: size of buf
143 * @entry_point: address to jump in fw kick-off
144 */
145struct iwmct_parser {
146 const u8 *file;
147 size_t file_size;
148 size_t cur_pos;
149 u8 *buf;
150 size_t buf_size;
151 u32 entry_point;
152 struct iwmct_fw_hdr versions;
153};
154
155
156struct iwmct_work_struct {
157 struct list_head list;
158 ssize_t iosize;
159};
160
161struct iwmct_dbg {
162 int blocks;
163 bool dump;
164 bool jump;
165 bool direct;
166 bool checksum;
167 bool fw_download;
168 int block_size;
169 int download_trans_blks;
170
171 char label_fw[256];
172};
173
174struct iwmct_debugfs;
175
176struct iwmct_priv {
177 struct sdio_func *func;
178 struct iwmct_debugfs *dbgfs;
179 struct iwmct_parser parser;
180 atomic_t reset;
181 atomic_t dev_sync;
182 u32 trans_len;
183 u32 barker;
184 struct iwmct_dbg dbg;
185
186 /* drivers work items */
187 struct work_struct bus_rescan_worker;
188 struct work_struct isr_worker;
189
190 /* drivers wait queue */
191 wait_queue_head_t wait_q;
192
193 /* rx request list */
194 struct list_head read_req_list;
195};
196
197extern int iwmct_tx(struct iwmct_priv *priv, void *src, int count);
198extern int iwmct_fw_load(struct iwmct_priv *priv);
199
200extern void iwmct_dbg_init_params(struct iwmct_priv *drv);
201extern void iwmct_dbg_init_drv_attrs(struct device_driver *drv);
202extern void iwmct_dbg_remove_drv_attrs(struct device_driver *drv);
203extern int iwmct_send_hcmd(struct iwmct_priv *priv, u8 *cmd, u16 len);
204
205#endif /* __IWMC3200TOP_H__ */
diff --git a/drivers/misc/iwmc3200top/log.c b/drivers/misc/iwmc3200top/log.c
deleted file mode 100644
index a36a55a49cac..000000000000
--- a/drivers/misc/iwmc3200top/log.c
+++ /dev/null
@@ -1,348 +0,0 @@
1/*
2 * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
3 * drivers/misc/iwmc3200top/log.c
4 *
5 * Copyright (C) 2009 Intel Corporation. All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301, USA.
20 *
21 *
22 * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
23 * -
24 *
25 */
26
27#include <linux/kernel.h>
28#include <linux/mmc/sdio_func.h>
29#include <linux/slab.h>
30#include <linux/ctype.h>
31#include "fw-msg.h"
32#include "iwmc3200top.h"
33#include "log.h"
34
35/* Maximal hexadecimal string size of the FW memdump message */
36#define LOG_MSG_SIZE_MAX 12400
37
38/* iwmct_logdefs is a global used by log macros */
39u8 iwmct_logdefs[LOG_SRC_MAX];
40static u8 iwmct_fw_logdefs[FW_LOG_SRC_MAX];
41
42
43static int _log_set_log_filter(u8 *logdefs, int size, u8 src, u8 logmask)
44{
45 int i;
46
47 if (src < size)
48 logdefs[src] = logmask;
49 else if (src == LOG_SRC_ALL)
50 for (i = 0; i < size; i++)
51 logdefs[i] = logmask;
52 else
53 return -1;
54
55 return 0;
56}
57
58
59int iwmct_log_set_filter(u8 src, u8 logmask)
60{
61 return _log_set_log_filter(iwmct_logdefs, LOG_SRC_MAX, src, logmask);
62}
63
64
65int iwmct_log_set_fw_filter(u8 src, u8 logmask)
66{
67 return _log_set_log_filter(iwmct_fw_logdefs,
68 FW_LOG_SRC_MAX, src, logmask);
69}
70
71
72static int log_msg_format_hex(char *str, int slen, u8 *ibuf,
73 int ilen, char *pref)
74{
75 int pos = 0;
76 int i;
77 int len;
78
79 for (pos = 0, i = 0; pos < slen - 2 && pref[i] != '\0'; i++, pos++)
80 str[pos] = pref[i];
81
82 for (i = 0; pos < slen - 2 && i < ilen; pos += len, i++)
83 len = snprintf(&str[pos], slen - pos - 1, " %2.2X", ibuf[i]);
84
85 if (i < ilen)
86 return -1;
87
88 return 0;
89}
90
91/* NOTE: This function is not thread safe.
92 Currently it's called only from sdio rx worker - no race there
93*/
94void iwmct_log_top_message(struct iwmct_priv *priv, u8 *buf, int len)
95{
96 struct top_msg *msg;
97 static char logbuf[LOG_MSG_SIZE_MAX];
98
99 msg = (struct top_msg *)buf;
100
101 if (len < sizeof(msg->hdr) + sizeof(msg->u.log.log_hdr)) {
102 LOG_ERROR(priv, FW_MSG, "Log message from TOP "
103 "is too short %d (expected %zd)\n",
104 len, sizeof(msg->hdr) + sizeof(msg->u.log.log_hdr));
105 return;
106 }
107
108 if (!(iwmct_fw_logdefs[msg->u.log.log_hdr.logsource] &
109 BIT(msg->u.log.log_hdr.severity)) ||
110 !(iwmct_logdefs[LOG_SRC_FW_MSG] & BIT(msg->u.log.log_hdr.severity)))
111 return;
112
113 switch (msg->hdr.category) {
114 case COMM_CATEGORY_TESTABILITY:
115 if (!(iwmct_logdefs[LOG_SRC_TST] &
116 BIT(msg->u.log.log_hdr.severity)))
117 return;
118 if (log_msg_format_hex(logbuf, LOG_MSG_SIZE_MAX, buf,
119 le16_to_cpu(msg->hdr.length) +
120 sizeof(msg->hdr), "<TST>"))
121 LOG_WARNING(priv, TST,
122 "TOP TST message is too long, truncating...");
123 LOG_WARNING(priv, TST, "%s\n", logbuf);
124 break;
125 case COMM_CATEGORY_DEBUG:
126 if (msg->hdr.opcode == OP_DBG_ZSTR_MSG)
127 LOG_INFO(priv, FW_MSG, "%s %s", "<DBG>",
128 ((u8 *)msg) + sizeof(msg->hdr)
129 + sizeof(msg->u.log.log_hdr));
130 else {
131 if (log_msg_format_hex(logbuf, LOG_MSG_SIZE_MAX, buf,
132 le16_to_cpu(msg->hdr.length)
133 + sizeof(msg->hdr),
134 "<DBG>"))
135 LOG_WARNING(priv, FW_MSG,
136 "TOP DBG message is too long,"
137 "truncating...");
138 LOG_WARNING(priv, FW_MSG, "%s\n", logbuf);
139 }
140 break;
141 default:
142 break;
143 }
144}
145
146static int _log_get_filter_str(u8 *logdefs, int logdefsz, char *buf, int size)
147{
148 int i, pos, len;
149 for (i = 0, pos = 0; (pos < size-1) && (i < logdefsz); i++) {
150 len = snprintf(&buf[pos], size - pos - 1, "0x%02X%02X,",
151 i, logdefs[i]);
152 pos += len;
153 }
154 buf[pos-1] = '\n';
155 buf[pos] = '\0';
156
157 if (i < logdefsz)
158 return -1;
159 return 0;
160}
161
162int log_get_filter_str(char *buf, int size)
163{
164 return _log_get_filter_str(iwmct_logdefs, LOG_SRC_MAX, buf, size);
165}
166
167int log_get_fw_filter_str(char *buf, int size)
168{
169 return _log_get_filter_str(iwmct_fw_logdefs, FW_LOG_SRC_MAX, buf, size);
170}
171
172#define HEXADECIMAL_RADIX 16
173#define LOG_SRC_FORMAT 7 /* log level is in format of "0xXXXX," */
174
175ssize_t show_iwmct_log_level(struct device *d,
176 struct device_attribute *attr, char *buf)
177{
178 struct iwmct_priv *priv = dev_get_drvdata(d);
179 char *str_buf;
180 int buf_size;
181 ssize_t ret;
182
183 buf_size = (LOG_SRC_FORMAT * LOG_SRC_MAX) + 1;
184 str_buf = kzalloc(buf_size, GFP_KERNEL);
185 if (!str_buf) {
186 LOG_ERROR(priv, DEBUGFS,
187 "failed to allocate %d bytes\n", buf_size);
188 ret = -ENOMEM;
189 goto exit;
190 }
191
192 if (log_get_filter_str(str_buf, buf_size) < 0) {
193 ret = -EINVAL;
194 goto exit;
195 }
196
197 ret = sprintf(buf, "%s", str_buf);
198
199exit:
200 kfree(str_buf);
201 return ret;
202}
203
204ssize_t store_iwmct_log_level(struct device *d,
205 struct device_attribute *attr,
206 const char *buf, size_t count)
207{
208 struct iwmct_priv *priv = dev_get_drvdata(d);
209 char *token, *str_buf = NULL;
210 long val;
211 ssize_t ret = count;
212 u8 src, mask;
213
214 if (!count)
215 goto exit;
216
217 str_buf = kzalloc(count, GFP_KERNEL);
218 if (!str_buf) {
219 LOG_ERROR(priv, DEBUGFS,
220 "failed to allocate %zd bytes\n", count);
221 ret = -ENOMEM;
222 goto exit;
223 }
224
225 memcpy(str_buf, buf, count);
226
227 while ((token = strsep(&str_buf, ",")) != NULL) {
228 while (isspace(*token))
229 ++token;
230 if (strict_strtol(token, HEXADECIMAL_RADIX, &val)) {
231 LOG_ERROR(priv, DEBUGFS,
232 "failed to convert string to long %s\n",
233 token);
234 ret = -EINVAL;
235 goto exit;
236 }
237
238 mask = val & 0xFF;
239 src = (val & 0XFF00) >> 8;
240 iwmct_log_set_filter(src, mask);
241 }
242
243exit:
244 kfree(str_buf);
245 return ret;
246}
247
248ssize_t show_iwmct_log_level_fw(struct device *d,
249 struct device_attribute *attr, char *buf)
250{
251 struct iwmct_priv *priv = dev_get_drvdata(d);
252 char *str_buf;
253 int buf_size;
254 ssize_t ret;
255
256 buf_size = (LOG_SRC_FORMAT * FW_LOG_SRC_MAX) + 2;
257
258 str_buf = kzalloc(buf_size, GFP_KERNEL);
259 if (!str_buf) {
260 LOG_ERROR(priv, DEBUGFS,
261 "failed to allocate %d bytes\n", buf_size);
262 ret = -ENOMEM;
263 goto exit;
264 }
265
266 if (log_get_fw_filter_str(str_buf, buf_size) < 0) {
267 ret = -EINVAL;
268 goto exit;
269 }
270
271 ret = sprintf(buf, "%s", str_buf);
272
273exit:
274 kfree(str_buf);
275 return ret;
276}
277
278ssize_t store_iwmct_log_level_fw(struct device *d,
279 struct device_attribute *attr,
280 const char *buf, size_t count)
281{
282 struct iwmct_priv *priv = dev_get_drvdata(d);
283 struct top_msg cmd;
284 char *token, *str_buf = NULL;
285 ssize_t ret = count;
286 u16 cmdlen = 0;
287 int i;
288 long val;
289 u8 src, mask;
290
291 if (!count)
292 goto exit;
293
294 str_buf = kzalloc(count, GFP_KERNEL);
295 if (!str_buf) {
296 LOG_ERROR(priv, DEBUGFS,
297 "failed to allocate %zd bytes\n", count);
298 ret = -ENOMEM;
299 goto exit;
300 }
301
302 memcpy(str_buf, buf, count);
303
304 cmd.hdr.type = COMM_TYPE_H2D;
305 cmd.hdr.category = COMM_CATEGORY_DEBUG;
306 cmd.hdr.opcode = CMD_DBG_LOG_LEVEL;
307
308 for (i = 0; ((token = strsep(&str_buf, ",")) != NULL) &&
309 (i < FW_LOG_SRC_MAX); i++) {
310
311 while (isspace(*token))
312 ++token;
313
314 if (strict_strtol(token, HEXADECIMAL_RADIX, &val)) {
315 LOG_ERROR(priv, DEBUGFS,
316 "failed to convert string to long %s\n",
317 token);
318 ret = -EINVAL;
319 goto exit;
320 }
321
322 mask = val & 0xFF; /* LSB */
323 src = (val & 0XFF00) >> 8; /* 2nd least significant byte. */
324 iwmct_log_set_fw_filter(src, mask);
325
326 cmd.u.logdefs[i].logsource = src;
327 cmd.u.logdefs[i].sevmask = mask;
328 }
329
330 cmd.hdr.length = cpu_to_le16(i * sizeof(cmd.u.logdefs[0]));
331 cmdlen = (i * sizeof(cmd.u.logdefs[0]) + sizeof(cmd.hdr));
332
333 ret = iwmct_send_hcmd(priv, (u8 *)&cmd, cmdlen);
334 if (ret) {
335 LOG_ERROR(priv, DEBUGFS,
336 "Failed to send %d bytes of fwcmd, ret=%zd\n",
337 cmdlen, ret);
338 goto exit;
339 } else
340 LOG_INFO(priv, DEBUGFS, "fwcmd sent (%d bytes)\n", cmdlen);
341
342 ret = count;
343
344exit:
345 kfree(str_buf);
346 return ret;
347}
348
diff --git a/drivers/misc/iwmc3200top/log.h b/drivers/misc/iwmc3200top/log.h
deleted file mode 100644
index 4434bb16cea7..000000000000
--- a/drivers/misc/iwmc3200top/log.h
+++ /dev/null
@@ -1,171 +0,0 @@
1/*
2 * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
3 * drivers/misc/iwmc3200top/log.h
4 *
5 * Copyright (C) 2009 Intel Corporation. All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301, USA.
20 *
21 *
22 * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
23 * -
24 *
25 */
26
27#ifndef __LOG_H__
28#define __LOG_H__
29
30
31/* log severity:
32 * The log levels here match FW log levels
33 * so values need to stay as is */
34#define LOG_SEV_CRITICAL 0
35#define LOG_SEV_ERROR 1
36#define LOG_SEV_WARNING 2
37#define LOG_SEV_INFO 3
38#define LOG_SEV_INFOEX 4
39
40/* Log levels not defined for FW */
41#define LOG_SEV_TRACE 5
42#define LOG_SEV_DUMP 6
43
44#define LOG_SEV_FW_FILTER_ALL \
45 (BIT(LOG_SEV_CRITICAL) | \
46 BIT(LOG_SEV_ERROR) | \
47 BIT(LOG_SEV_WARNING) | \
48 BIT(LOG_SEV_INFO) | \
49 BIT(LOG_SEV_INFOEX))
50
51#define LOG_SEV_FILTER_ALL \
52 (BIT(LOG_SEV_CRITICAL) | \
53 BIT(LOG_SEV_ERROR) | \
54 BIT(LOG_SEV_WARNING) | \
55 BIT(LOG_SEV_INFO) | \
56 BIT(LOG_SEV_INFOEX) | \
57 BIT(LOG_SEV_TRACE) | \
58 BIT(LOG_SEV_DUMP))
59
60/* log source */
61#define LOG_SRC_INIT 0
62#define LOG_SRC_DEBUGFS 1
63#define LOG_SRC_FW_DOWNLOAD 2
64#define LOG_SRC_FW_MSG 3
65#define LOG_SRC_TST 4
66#define LOG_SRC_IRQ 5
67
68#define LOG_SRC_MAX 6
69#define LOG_SRC_ALL 0xFF
70
71/**
72 * Default intitialization runtime log level
73 */
74#ifndef LOG_SEV_FILTER_RUNTIME
75#define LOG_SEV_FILTER_RUNTIME \
76 (BIT(LOG_SEV_CRITICAL) | \
77 BIT(LOG_SEV_ERROR) | \
78 BIT(LOG_SEV_WARNING))
79#endif
80
81#ifndef FW_LOG_SEV_FILTER_RUNTIME
82#define FW_LOG_SEV_FILTER_RUNTIME LOG_SEV_FILTER_ALL
83#endif
84
85#ifdef CONFIG_IWMC3200TOP_DEBUG
86/**
87 * Log macros
88 */
89
90#define priv2dev(priv) (&(priv->func)->dev)
91
92#define LOG_CRITICAL(priv, src, fmt, args...) \
93do { \
94 if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_CRITICAL)) \
95 dev_crit(priv2dev(priv), "%s %d: " fmt, \
96 __func__, __LINE__, ##args); \
97} while (0)
98
99#define LOG_ERROR(priv, src, fmt, args...) \
100do { \
101 if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_ERROR)) \
102 dev_err(priv2dev(priv), "%s %d: " fmt, \
103 __func__, __LINE__, ##args); \
104} while (0)
105
106#define LOG_WARNING(priv, src, fmt, args...) \
107do { \
108 if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_WARNING)) \
109 dev_warn(priv2dev(priv), "%s %d: " fmt, \
110 __func__, __LINE__, ##args); \
111} while (0)
112
113#define LOG_INFO(priv, src, fmt, args...) \
114do { \
115 if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_INFO)) \
116 dev_info(priv2dev(priv), "%s %d: " fmt, \
117 __func__, __LINE__, ##args); \
118} while (0)
119
120#define LOG_TRACE(priv, src, fmt, args...) \
121do { \
122 if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_TRACE)) \
123 dev_dbg(priv2dev(priv), "%s %d: " fmt, \
124 __func__, __LINE__, ##args); \
125} while (0)
126
127#define LOG_HEXDUMP(src, ptr, len) \
128do { \
129 if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_DUMP)) \
130 print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, \
131 16, 1, ptr, len, false); \
132} while (0)
133
134void iwmct_log_top_message(struct iwmct_priv *priv, u8 *buf, int len);
135
136extern u8 iwmct_logdefs[];
137
138int iwmct_log_set_filter(u8 src, u8 logmask);
139int iwmct_log_set_fw_filter(u8 src, u8 logmask);
140
141ssize_t show_iwmct_log_level(struct device *d,
142 struct device_attribute *attr, char *buf);
143ssize_t store_iwmct_log_level(struct device *d,
144 struct device_attribute *attr,
145 const char *buf, size_t count);
146ssize_t show_iwmct_log_level_fw(struct device *d,
147 struct device_attribute *attr, char *buf);
148ssize_t store_iwmct_log_level_fw(struct device *d,
149 struct device_attribute *attr,
150 const char *buf, size_t count);
151
152#else
153
154#define LOG_CRITICAL(priv, src, fmt, args...)
155#define LOG_ERROR(priv, src, fmt, args...)
156#define LOG_WARNING(priv, src, fmt, args...)
157#define LOG_INFO(priv, src, fmt, args...)
158#define LOG_TRACE(priv, src, fmt, args...)
159#define LOG_HEXDUMP(src, ptr, len)
160
161static inline void iwmct_log_top_message(struct iwmct_priv *priv,
162 u8 *buf, int len) {}
163static inline int iwmct_log_set_filter(u8 src, u8 logmask) { return 0; }
164static inline int iwmct_log_set_fw_filter(u8 src, u8 logmask) { return 0; }
165
166#endif /* CONFIG_IWMC3200TOP_DEBUG */
167
168int log_get_filter_str(char *buf, int size);
169int log_get_fw_filter_str(char *buf, int size);
170
171#endif /* __LOG_H__ */
diff --git a/drivers/misc/iwmc3200top/main.c b/drivers/misc/iwmc3200top/main.c
deleted file mode 100644
index 701eb600b127..000000000000
--- a/drivers/misc/iwmc3200top/main.c
+++ /dev/null
@@ -1,662 +0,0 @@
1/*
2 * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
3 * drivers/misc/iwmc3200top/main.c
4 *
5 * Copyright (C) 2009 Intel Corporation. All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301, USA.
20 *
21 *
22 * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
23 * -
24 *
25 */
26
27#include <linux/module.h>
28#include <linux/slab.h>
29#include <linux/init.h>
30#include <linux/kernel.h>
31#include <linux/debugfs.h>
32#include <linux/mmc/sdio_ids.h>
33#include <linux/mmc/sdio_func.h>
34#include <linux/mmc/sdio.h>
35
36#include "iwmc3200top.h"
37#include "log.h"
38#include "fw-msg.h"
39#include "debugfs.h"
40
41
42#define DRIVER_DESCRIPTION "Intel(R) IWMC 3200 Top Driver"
43#define DRIVER_COPYRIGHT "Copyright (c) 2008 Intel Corporation."
44
45#define DRIVER_VERSION "0.1.62"
46
47MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
48MODULE_VERSION(DRIVER_VERSION);
49MODULE_LICENSE("GPL");
50MODULE_AUTHOR(DRIVER_COPYRIGHT);
51MODULE_FIRMWARE(FW_NAME(FW_API_VER));
52
53
54static inline int __iwmct_tx(struct iwmct_priv *priv, void *src, int count)
55{
56 return sdio_memcpy_toio(priv->func, IWMC_SDIO_DATA_ADDR, src, count);
57
58}
59int iwmct_tx(struct iwmct_priv *priv, void *src, int count)
60{
61 int ret;
62 sdio_claim_host(priv->func);
63 ret = __iwmct_tx(priv, src, count);
64 sdio_release_host(priv->func);
65 return ret;
66}
67/*
68 * This workers main task is to wait for OP_OPR_ALIVE
69 * from TOP FW until ALIVE_MSG_TIMOUT timeout is elapsed.
70 * When OP_OPR_ALIVE received it will issue
71 * a call to "bus_rescan_devices".
72 */
73static void iwmct_rescan_worker(struct work_struct *ws)
74{
75 struct iwmct_priv *priv;
76 int ret;
77
78 priv = container_of(ws, struct iwmct_priv, bus_rescan_worker);
79
80 LOG_INFO(priv, FW_MSG, "Calling bus_rescan\n");
81
82 ret = bus_rescan_devices(priv->func->dev.bus);
83 if (ret < 0)
84 LOG_INFO(priv, INIT, "bus_rescan_devices FAILED!!!\n");
85}
86
87static void op_top_message(struct iwmct_priv *priv, struct top_msg *msg)
88{
89 switch (msg->hdr.opcode) {
90 case OP_OPR_ALIVE:
91 LOG_INFO(priv, FW_MSG, "Got ALIVE from device, wake rescan\n");
92 schedule_work(&priv->bus_rescan_worker);
93 break;
94 default:
95 LOG_INFO(priv, FW_MSG, "Received msg opcode 0x%X\n",
96 msg->hdr.opcode);
97 break;
98 }
99}
100
101
102static void handle_top_message(struct iwmct_priv *priv, u8 *buf, int len)
103{
104 struct top_msg *msg;
105
106 msg = (struct top_msg *)buf;
107
108 if (msg->hdr.type != COMM_TYPE_D2H) {
109 LOG_ERROR(priv, FW_MSG,
110 "Message from TOP with invalid message type 0x%X\n",
111 msg->hdr.type);
112 return;
113 }
114
115 if (len < sizeof(msg->hdr)) {
116 LOG_ERROR(priv, FW_MSG,
117 "Message from TOP is too short for message header "
118 "received %d bytes, expected at least %zd bytes\n",
119 len, sizeof(msg->hdr));
120 return;
121 }
122
123 if (len < le16_to_cpu(msg->hdr.length) + sizeof(msg->hdr)) {
124 LOG_ERROR(priv, FW_MSG,
125 "Message length (%d bytes) is shorter than "
126 "in header (%d bytes)\n",
127 len, le16_to_cpu(msg->hdr.length));
128 return;
129 }
130
131 switch (msg->hdr.category) {
132 case COMM_CATEGORY_OPERATIONAL:
133 op_top_message(priv, (struct top_msg *)buf);
134 break;
135
136 case COMM_CATEGORY_DEBUG:
137 case COMM_CATEGORY_TESTABILITY:
138 case COMM_CATEGORY_DIAGNOSTICS:
139 iwmct_log_top_message(priv, buf, len);
140 break;
141
142 default:
143 LOG_ERROR(priv, FW_MSG,
144 "Message from TOP with unknown category 0x%X\n",
145 msg->hdr.category);
146 break;
147 }
148}
149
150int iwmct_send_hcmd(struct iwmct_priv *priv, u8 *cmd, u16 len)
151{
152 int ret;
153 u8 *buf;
154
155 LOG_TRACE(priv, FW_MSG, "Sending hcmd:\n");
156
157 /* add padding to 256 for IWMC */
158 ((struct top_msg *)cmd)->hdr.flags |= CMD_FLAG_PADDING_256;
159
160 LOG_HEXDUMP(FW_MSG, cmd, len);
161
162 if (len > FW_HCMD_BLOCK_SIZE) {
163 LOG_ERROR(priv, FW_MSG, "size %d exceeded hcmd max size %d\n",
164 len, FW_HCMD_BLOCK_SIZE);
165 return -1;
166 }
167
168 buf = kzalloc(FW_HCMD_BLOCK_SIZE, GFP_KERNEL);
169 if (!buf) {
170 LOG_ERROR(priv, FW_MSG, "kzalloc error, buf size %d\n",
171 FW_HCMD_BLOCK_SIZE);
172 return -1;
173 }
174
175 memcpy(buf, cmd, len);
176 ret = iwmct_tx(priv, buf, FW_HCMD_BLOCK_SIZE);
177
178 kfree(buf);
179 return ret;
180}
181
182
183static void iwmct_irq_read_worker(struct work_struct *ws)
184{
185 struct iwmct_priv *priv;
186 struct iwmct_work_struct *read_req;
187 __le32 *buf = NULL;
188 int ret;
189 int iosize;
190 u32 barker;
191 bool is_barker;
192
193 priv = container_of(ws, struct iwmct_priv, isr_worker);
194
195 LOG_TRACE(priv, IRQ, "enter iwmct_irq_read_worker %p\n", ws);
196
197 /* --------------------- Handshake with device -------------------- */
198 sdio_claim_host(priv->func);
199
200 /* all list manipulations have to be protected by
201 * sdio_claim_host/sdio_release_host */
202 if (list_empty(&priv->read_req_list)) {
203 LOG_ERROR(priv, IRQ, "read_req_list empty in read worker\n");
204 goto exit_release;
205 }
206
207 read_req = list_entry(priv->read_req_list.next,
208 struct iwmct_work_struct, list);
209
210 list_del(&read_req->list);
211 iosize = read_req->iosize;
212 kfree(read_req);
213
214 buf = kzalloc(iosize, GFP_KERNEL);
215 if (!buf) {
216 LOG_ERROR(priv, IRQ, "kzalloc error, buf size %d\n", iosize);
217 goto exit_release;
218 }
219
220 LOG_INFO(priv, IRQ, "iosize=%d, buf=%p, func=%d\n",
221 iosize, buf, priv->func->num);
222
223 /* read from device */
224 ret = sdio_memcpy_fromio(priv->func, buf, IWMC_SDIO_DATA_ADDR, iosize);
225 if (ret) {
226 LOG_ERROR(priv, IRQ, "error %d reading buffer\n", ret);
227 goto exit_release;
228 }
229
230 LOG_HEXDUMP(IRQ, (u8 *)buf, iosize);
231
232 barker = le32_to_cpu(buf[0]);
233
234 /* Verify whether it's a barker and if not - treat as regular Rx */
235 if (barker == IWMC_BARKER_ACK ||
236 (barker & BARKER_DNLOAD_BARKER_MSK) == IWMC_BARKER_REBOOT) {
237
238 /* Valid Barker is equal on first 4 dwords */
239 is_barker = (buf[1] == buf[0]) &&
240 (buf[2] == buf[0]) &&
241 (buf[3] == buf[0]);
242
243 if (!is_barker) {
244 LOG_WARNING(priv, IRQ,
245 "Potentially inconsistent barker "
246 "%08X_%08X_%08X_%08X\n",
247 le32_to_cpu(buf[0]), le32_to_cpu(buf[1]),
248 le32_to_cpu(buf[2]), le32_to_cpu(buf[3]));
249 }
250 } else {
251 is_barker = false;
252 }
253
254 /* Handle Top CommHub message */
255 if (!is_barker) {
256 sdio_release_host(priv->func);
257 handle_top_message(priv, (u8 *)buf, iosize);
258 goto exit;
259 } else if (barker == IWMC_BARKER_ACK) { /* Handle barkers */
260 if (atomic_read(&priv->dev_sync) == 0) {
261 LOG_ERROR(priv, IRQ,
262 "ACK barker arrived out-of-sync\n");
263 goto exit_release;
264 }
265
266 /* Continuing to FW download (after Sync is completed)*/
267 atomic_set(&priv->dev_sync, 0);
268 LOG_INFO(priv, IRQ, "ACK barker arrived "
269 "- starting FW download\n");
270 } else { /* REBOOT barker */
271 LOG_INFO(priv, IRQ, "Received reboot barker: %x\n", barker);
272 priv->barker = barker;
273
274 if (barker & BARKER_DNLOAD_SYNC_MSK) {
275 /* Send the same barker back */
276 ret = __iwmct_tx(priv, buf, iosize);
277 if (ret) {
278 LOG_ERROR(priv, IRQ,
279 "error %d echoing barker\n", ret);
280 goto exit_release;
281 }
282 LOG_INFO(priv, IRQ, "Echoing barker to device\n");
283 atomic_set(&priv->dev_sync, 1);
284 goto exit_release;
285 }
286
287 /* Continuing to FW download (without Sync) */
288 LOG_INFO(priv, IRQ, "No sync requested "
289 "- starting FW download\n");
290 }
291
292 sdio_release_host(priv->func);
293
294 if (priv->dbg.fw_download)
295 iwmct_fw_load(priv);
296 else
297 LOG_ERROR(priv, IRQ, "FW download not allowed\n");
298
299 goto exit;
300
301exit_release:
302 sdio_release_host(priv->func);
303exit:
304 kfree(buf);
305 LOG_TRACE(priv, IRQ, "exit iwmct_irq_read_worker\n");
306}
307
308static void iwmct_irq(struct sdio_func *func)
309{
310 struct iwmct_priv *priv;
311 int val, ret;
312 int iosize;
313 int addr = IWMC_SDIO_INTR_GET_SIZE_ADDR;
314 struct iwmct_work_struct *read_req;
315
316 priv = sdio_get_drvdata(func);
317
318 LOG_TRACE(priv, IRQ, "enter iwmct_irq\n");
319
320 /* read the function's status register */
321 val = sdio_readb(func, IWMC_SDIO_INTR_STATUS_ADDR, &ret);
322
323 LOG_TRACE(priv, IRQ, "iir value = %d, ret=%d\n", val, ret);
324
325 if (!val) {
326 LOG_ERROR(priv, IRQ, "iir = 0, exiting ISR\n");
327 goto exit_clear_intr;
328 }
329
330
331 /*
332 * read 2 bytes of the transaction size
333 * IMPORTANT: sdio transaction size has to be read before clearing
334 * sdio interrupt!!!
335 */
336 val = sdio_readb(priv->func, addr++, &ret);
337 iosize = val;
338 val = sdio_readb(priv->func, addr++, &ret);
339 iosize += val << 8;
340
341 LOG_INFO(priv, IRQ, "READ size %d\n", iosize);
342
343 if (iosize == 0) {
344 LOG_ERROR(priv, IRQ, "READ size %d, exiting ISR\n", iosize);
345 goto exit_clear_intr;
346 }
347
348 /* allocate a work structure to pass iosize to the worker */
349 read_req = kzalloc(sizeof(struct iwmct_work_struct), GFP_KERNEL);
350 if (!read_req) {
351 LOG_ERROR(priv, IRQ, "failed to allocate read_req, exit ISR\n");
352 goto exit_clear_intr;
353 }
354
355 INIT_LIST_HEAD(&read_req->list);
356 read_req->iosize = iosize;
357
358 list_add_tail(&priv->read_req_list, &read_req->list);
359
360 /* clear the function's interrupt request bit (write 1 to clear) */
361 sdio_writeb(func, 1, IWMC_SDIO_INTR_CLEAR_ADDR, &ret);
362
363 schedule_work(&priv->isr_worker);
364
365 LOG_TRACE(priv, IRQ, "exit iwmct_irq\n");
366
367 return;
368
369exit_clear_intr:
370 /* clear the function's interrupt request bit (write 1 to clear) */
371 sdio_writeb(func, 1, IWMC_SDIO_INTR_CLEAR_ADDR, &ret);
372}
373
374
375static int blocks;
376module_param(blocks, int, 0604);
377MODULE_PARM_DESC(blocks, "max_blocks_to_send");
378
379static bool dump;
380module_param(dump, bool, 0604);
381MODULE_PARM_DESC(dump, "dump_hex_content");
382
383static bool jump = 1;
384module_param(jump, bool, 0604);
385
386static bool direct = 1;
387module_param(direct, bool, 0604);
388
389static bool checksum = 1;
390module_param(checksum, bool, 0604);
391
392static bool fw_download = 1;
393module_param(fw_download, bool, 0604);
394
395static int block_size = IWMC_SDIO_BLK_SIZE;
396module_param(block_size, int, 0404);
397
398static int download_trans_blks = IWMC_DEFAULT_TR_BLK;
399module_param(download_trans_blks, int, 0604);
400
401static bool rubbish_barker;
402module_param(rubbish_barker, bool, 0604);
403
404#ifdef CONFIG_IWMC3200TOP_DEBUG
405static int log_level[LOG_SRC_MAX];
406static unsigned int log_level_argc;
407module_param_array(log_level, int, &log_level_argc, 0604);
408MODULE_PARM_DESC(log_level, "log_level");
409
410static int log_level_fw[FW_LOG_SRC_MAX];
411static unsigned int log_level_fw_argc;
412module_param_array(log_level_fw, int, &log_level_fw_argc, 0604);
413MODULE_PARM_DESC(log_level_fw, "log_level_fw");
414#endif
415
416void iwmct_dbg_init_params(struct iwmct_priv *priv)
417{
418#ifdef CONFIG_IWMC3200TOP_DEBUG
419 int i;
420
421 for (i = 0; i < log_level_argc; i++) {
422 dev_notice(&priv->func->dev, "log_level[%d]=0x%X\n",
423 i, log_level[i]);
424 iwmct_log_set_filter((log_level[i] >> 8) & 0xFF,
425 log_level[i] & 0xFF);
426 }
427 for (i = 0; i < log_level_fw_argc; i++) {
428 dev_notice(&priv->func->dev, "log_level_fw[%d]=0x%X\n",
429 i, log_level_fw[i]);
430 iwmct_log_set_fw_filter((log_level_fw[i] >> 8) & 0xFF,
431 log_level_fw[i] & 0xFF);
432 }
433#endif
434
435 priv->dbg.blocks = blocks;
436 LOG_INFO(priv, INIT, "blocks=%d\n", blocks);
437 priv->dbg.dump = (bool)dump;
438 LOG_INFO(priv, INIT, "dump=%d\n", dump);
439 priv->dbg.jump = (bool)jump;
440 LOG_INFO(priv, INIT, "jump=%d\n", jump);
441 priv->dbg.direct = (bool)direct;
442 LOG_INFO(priv, INIT, "direct=%d\n", direct);
443 priv->dbg.checksum = (bool)checksum;
444 LOG_INFO(priv, INIT, "checksum=%d\n", checksum);
445 priv->dbg.fw_download = (bool)fw_download;
446 LOG_INFO(priv, INIT, "fw_download=%d\n", fw_download);
447 priv->dbg.block_size = block_size;
448 LOG_INFO(priv, INIT, "block_size=%d\n", block_size);
449 priv->dbg.download_trans_blks = download_trans_blks;
450 LOG_INFO(priv, INIT, "download_trans_blks=%d\n", download_trans_blks);
451}
452
453/*****************************************************************************
454 *
455 * sysfs attributes
456 *
457 *****************************************************************************/
458static ssize_t show_iwmct_fw_version(struct device *d,
459 struct device_attribute *attr, char *buf)
460{
461 struct iwmct_priv *priv = dev_get_drvdata(d);
462 return sprintf(buf, "%s\n", priv->dbg.label_fw);
463}
464static DEVICE_ATTR(cc_label_fw, S_IRUGO, show_iwmct_fw_version, NULL);
465
466#ifdef CONFIG_IWMC3200TOP_DEBUG
467static DEVICE_ATTR(log_level, S_IWUSR | S_IRUGO,
468 show_iwmct_log_level, store_iwmct_log_level);
469static DEVICE_ATTR(log_level_fw, S_IWUSR | S_IRUGO,
470 show_iwmct_log_level_fw, store_iwmct_log_level_fw);
471#endif
472
473static struct attribute *iwmct_sysfs_entries[] = {
474 &dev_attr_cc_label_fw.attr,
475#ifdef CONFIG_IWMC3200TOP_DEBUG
476 &dev_attr_log_level.attr,
477 &dev_attr_log_level_fw.attr,
478#endif
479 NULL
480};
481
482static struct attribute_group iwmct_attribute_group = {
483 .name = NULL, /* put in device directory */
484 .attrs = iwmct_sysfs_entries,
485};
486
487
488static int iwmct_probe(struct sdio_func *func,
489 const struct sdio_device_id *id)
490{
491 struct iwmct_priv *priv;
492 int ret;
493 int val = 1;
494 int addr = IWMC_SDIO_INTR_ENABLE_ADDR;
495
496 dev_dbg(&func->dev, "enter iwmct_probe\n");
497
498 dev_dbg(&func->dev, "IRQ polling period id %u msecs, HZ is %d\n",
499 jiffies_to_msecs(2147483647), HZ);
500
501 priv = kzalloc(sizeof(struct iwmct_priv), GFP_KERNEL);
502 if (!priv) {
503 dev_err(&func->dev, "kzalloc error\n");
504 return -ENOMEM;
505 }
506 priv->func = func;
507 sdio_set_drvdata(func, priv);
508
509 INIT_WORK(&priv->bus_rescan_worker, iwmct_rescan_worker);
510 INIT_WORK(&priv->isr_worker, iwmct_irq_read_worker);
511
512 init_waitqueue_head(&priv->wait_q);
513
514 sdio_claim_host(func);
515 /* FIXME: Remove after it is fixed in the Boot ROM upgrade */
516 func->enable_timeout = 10;
517
518 /* In our HW, setting the block size also wakes up the boot rom. */
519 ret = sdio_set_block_size(func, priv->dbg.block_size);
520 if (ret) {
521 LOG_ERROR(priv, INIT,
522 "sdio_set_block_size() failure: %d\n", ret);
523 goto error_sdio_enable;
524 }
525
526 ret = sdio_enable_func(func);
527 if (ret) {
528 LOG_ERROR(priv, INIT, "sdio_enable_func() failure: %d\n", ret);
529 goto error_sdio_enable;
530 }
531
532 /* init reset and dev_sync states */
533 atomic_set(&priv->reset, 0);
534 atomic_set(&priv->dev_sync, 0);
535
536 /* init read req queue */
537 INIT_LIST_HEAD(&priv->read_req_list);
538
539 /* process configurable parameters */
540 iwmct_dbg_init_params(priv);
541 ret = sysfs_create_group(&func->dev.kobj, &iwmct_attribute_group);
542 if (ret) {
543 LOG_ERROR(priv, INIT, "Failed to register attributes and "
544 "initialize module_params\n");
545 goto error_dev_attrs;
546 }
547
548 iwmct_dbgfs_register(priv, DRV_NAME);
549
550 if (!priv->dbg.direct && priv->dbg.download_trans_blks > 8) {
551 LOG_INFO(priv, INIT,
552 "Reducing transaction to 8 blocks = 2K (from %d)\n",
553 priv->dbg.download_trans_blks);
554 priv->dbg.download_trans_blks = 8;
555 }
556 priv->trans_len = priv->dbg.download_trans_blks * priv->dbg.block_size;
557 LOG_INFO(priv, INIT, "Transaction length = %d\n", priv->trans_len);
558
559 ret = sdio_claim_irq(func, iwmct_irq);
560 if (ret) {
561 LOG_ERROR(priv, INIT, "sdio_claim_irq() failure: %d\n", ret);
562 goto error_claim_irq;
563 }
564
565
566 /* Enable function's interrupt */
567 sdio_writeb(priv->func, val, addr, &ret);
568 if (ret) {
569 LOG_ERROR(priv, INIT, "Failure writing to "
570 "Interrupt Enable Register (%d): %d\n", addr, ret);
571 goto error_enable_int;
572 }
573
574 sdio_release_host(func);
575
576 LOG_INFO(priv, INIT, "exit iwmct_probe\n");
577
578 return ret;
579
580error_enable_int:
581 sdio_release_irq(func);
582error_claim_irq:
583 sdio_disable_func(func);
584error_dev_attrs:
585 iwmct_dbgfs_unregister(priv->dbgfs);
586 sysfs_remove_group(&func->dev.kobj, &iwmct_attribute_group);
587error_sdio_enable:
588 sdio_release_host(func);
589 return ret;
590}
591
592static void iwmct_remove(struct sdio_func *func)
593{
594 struct iwmct_work_struct *read_req;
595 struct iwmct_priv *priv = sdio_get_drvdata(func);
596
597 LOG_INFO(priv, INIT, "enter\n");
598
599 sdio_claim_host(func);
600 sdio_release_irq(func);
601 sdio_release_host(func);
602
603 /* Make sure works are finished */
604 flush_work_sync(&priv->bus_rescan_worker);
605 flush_work_sync(&priv->isr_worker);
606
607 sdio_claim_host(func);
608 sdio_disable_func(func);
609 sysfs_remove_group(&func->dev.kobj, &iwmct_attribute_group);
610 iwmct_dbgfs_unregister(priv->dbgfs);
611 sdio_release_host(func);
612
613 /* free read requests */
614 while (!list_empty(&priv->read_req_list)) {
615 read_req = list_entry(priv->read_req_list.next,
616 struct iwmct_work_struct, list);
617
618 list_del(&read_req->list);
619 kfree(read_req);
620 }
621
622 kfree(priv);
623}
624
625
626static const struct sdio_device_id iwmct_ids[] = {
627 /* Intel Wireless MultiCom 3200 Top Driver */
628 { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 0x1404)},
629 { }, /* Terminating entry */
630};
631
632MODULE_DEVICE_TABLE(sdio, iwmct_ids);
633
634static struct sdio_driver iwmct_driver = {
635 .probe = iwmct_probe,
636 .remove = iwmct_remove,
637 .name = DRV_NAME,
638 .id_table = iwmct_ids,
639};
640
641static int __init iwmct_init(void)
642{
643 int rc;
644
645 /* Default log filter settings */
646 iwmct_log_set_filter(LOG_SRC_ALL, LOG_SEV_FILTER_RUNTIME);
647 iwmct_log_set_filter(LOG_SRC_FW_MSG, LOG_SEV_FW_FILTER_ALL);
648 iwmct_log_set_fw_filter(LOG_SRC_ALL, FW_LOG_SEV_FILTER_RUNTIME);
649
650 rc = sdio_register_driver(&iwmct_driver);
651
652 return rc;
653}
654
655static void __exit iwmct_exit(void)
656{
657 sdio_unregister_driver(&iwmct_driver);
658}
659
660module_init(iwmct_init);
661module_exit(iwmct_exit);
662
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 /*
diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c
index 1f74a77d040d..e7fd4938f9bc 100644
--- a/drivers/nfc/nfcwilink.c
+++ b/drivers/nfc/nfcwilink.c
@@ -535,9 +535,10 @@ static int nfcwilink_probe(struct platform_device *pdev)
535 drv->pdev = pdev; 535 drv->pdev = pdev;
536 536
537 protocols = NFC_PROTO_JEWEL_MASK 537 protocols = NFC_PROTO_JEWEL_MASK
538 | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK 538 | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK
539 | NFC_PROTO_ISO14443_MASK 539 | NFC_PROTO_ISO14443_MASK
540 | NFC_PROTO_NFC_DEP_MASK; 540 | NFC_PROTO_ISO14443_B_MASK
541 | NFC_PROTO_NFC_DEP_MASK;
541 542
542 drv->ndev = nci_allocate_device(&nfcwilink_ops, 543 drv->ndev = nci_allocate_device(&nfcwilink_ops,
543 protocols, 544 protocols,
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 9ac829e22e73..d606f52fec84 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -38,9 +38,44 @@
38#define SCM_VENDOR_ID 0x4E6 38#define SCM_VENDOR_ID 0x4E6
39#define SCL3711_PRODUCT_ID 0x5591 39#define SCL3711_PRODUCT_ID 0x5591
40 40
41#define SONY_VENDOR_ID 0x054c
42#define PASORI_PRODUCT_ID 0x02e1
43
44#define PN533_QUIRKS_TYPE_A BIT(0)
45#define PN533_QUIRKS_TYPE_F BIT(1)
46#define PN533_QUIRKS_DEP BIT(2)
47#define PN533_QUIRKS_RAW_EXCHANGE BIT(3)
48
49#define PN533_DEVICE_STD 0x1
50#define PN533_DEVICE_PASORI 0x2
51
52#define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK |\
53 NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK |\
54 NFC_PROTO_NFC_DEP_MASK |\
55 NFC_PROTO_ISO14443_B_MASK)
56
57#define PN533_NO_TYPE_B_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \
58 NFC_PROTO_MIFARE_MASK | \
59 NFC_PROTO_FELICA_MASK | \
60 NFC_PROTO_ISO14443_MASK | \
61 NFC_PROTO_NFC_DEP_MASK)
62
41static const struct usb_device_id pn533_table[] = { 63static const struct usb_device_id pn533_table[] = {
42 { USB_DEVICE(PN533_VENDOR_ID, PN533_PRODUCT_ID) }, 64 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
43 { USB_DEVICE(SCM_VENDOR_ID, SCL3711_PRODUCT_ID) }, 65 .idVendor = PN533_VENDOR_ID,
66 .idProduct = PN533_PRODUCT_ID,
67 .driver_info = PN533_DEVICE_STD,
68 },
69 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
70 .idVendor = SCM_VENDOR_ID,
71 .idProduct = SCL3711_PRODUCT_ID,
72 .driver_info = PN533_DEVICE_STD,
73 },
74 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
75 .idVendor = SONY_VENDOR_ID,
76 .idProduct = PASORI_PRODUCT_ID,
77 .driver_info = PN533_DEVICE_PASORI,
78 },
44 { } 79 { }
45}; 80};
46MODULE_DEVICE_TABLE(usb, pn533_table); 81MODULE_DEVICE_TABLE(usb, pn533_table);
@@ -72,6 +107,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
72#define PN533_CMD_GET_FIRMWARE_VERSION 0x02 107#define PN533_CMD_GET_FIRMWARE_VERSION 0x02
73#define PN533_CMD_RF_CONFIGURATION 0x32 108#define PN533_CMD_RF_CONFIGURATION 0x32
74#define PN533_CMD_IN_DATA_EXCHANGE 0x40 109#define PN533_CMD_IN_DATA_EXCHANGE 0x40
110#define PN533_CMD_IN_COMM_THRU 0x42
75#define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A 111#define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A
76#define PN533_CMD_IN_ATR 0x50 112#define PN533_CMD_IN_ATR 0x50
77#define PN533_CMD_IN_RELEASE 0x52 113#define PN533_CMD_IN_RELEASE 0x52
@@ -109,6 +145,7 @@ struct pn533_fw_version {
109/* PN533_CMD_RF_CONFIGURATION */ 145/* PN533_CMD_RF_CONFIGURATION */
110#define PN533_CFGITEM_TIMING 0x02 146#define PN533_CFGITEM_TIMING 0x02
111#define PN533_CFGITEM_MAX_RETRIES 0x05 147#define PN533_CFGITEM_MAX_RETRIES 0x05
148#define PN533_CFGITEM_PASORI 0x82
112 149
113#define PN533_CONFIG_TIMING_102 0xb 150#define PN533_CONFIG_TIMING_102 0xb
114#define PN533_CONFIG_TIMING_204 0xc 151#define PN533_CONFIG_TIMING_204 0xc
@@ -344,6 +381,8 @@ struct pn533 {
344 u8 tgt_available_prots; 381 u8 tgt_available_prots;
345 u8 tgt_active_prot; 382 u8 tgt_active_prot;
346 u8 tgt_mode; 383 u8 tgt_mode;
384
385 u32 device_type;
347}; 386};
348 387
349struct pn533_frame { 388struct pn533_frame {
@@ -950,7 +989,7 @@ static int pn533_target_found_type_b(struct nfc_target *nfc_tgt, u8 *tgt_data,
950 if (!pn533_target_type_b_is_valid(tgt_type_b, tgt_data_len)) 989 if (!pn533_target_type_b_is_valid(tgt_type_b, tgt_data_len))
951 return -EPROTO; 990 return -EPROTO;
952 991
953 nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_MASK; 992 nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_B_MASK;
954 993
955 return 0; 994 return 0;
956} 995}
@@ -1057,7 +1096,7 @@ static void pn533_poll_create_mod_list(struct pn533 *dev,
1057 if (im_protocols & NFC_PROTO_JEWEL_MASK) 1096 if (im_protocols & NFC_PROTO_JEWEL_MASK)
1058 pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL); 1097 pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL);
1059 1098
1060 if (im_protocols & NFC_PROTO_ISO14443_MASK) 1099 if (im_protocols & NFC_PROTO_ISO14443_B_MASK)
1061 pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B); 1100 pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B);
1062 1101
1063 if (tm_protocols) 1102 if (tm_protocols)
@@ -1768,13 +1807,30 @@ static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb,
1768 } 1807 }
1769 1808
1770 if (target == true) { 1809 if (target == true) {
1771 skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN); 1810 switch (dev->device_type) {
1772 out_frame = (struct pn533_frame *) skb->data; 1811 case PN533_DEVICE_PASORI:
1812 if (dev->tgt_active_prot == NFC_PROTO_FELICA) {
1813 skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1);
1814 out_frame = (struct pn533_frame *) skb->data;
1815 pn533_tx_frame_init(out_frame,
1816 PN533_CMD_IN_COMM_THRU);
1817
1818 break;
1819 }
1820
1821 default:
1822 skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);
1823 out_frame = (struct pn533_frame *) skb->data;
1824 pn533_tx_frame_init(out_frame,
1825 PN533_CMD_IN_DATA_EXCHANGE);
1826 tg = 1;
1827 memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame),
1828 &tg, sizeof(u8));
1829 out_frame->datalen += sizeof(u8);
1830
1831 break;
1832 }
1773 1833
1774 pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE);
1775 tg = 1;
1776 memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8));
1777 out_frame->datalen += sizeof(u8);
1778 } else { 1834 } else {
1779 skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1); 1835 skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1);
1780 out_frame = (struct pn533_frame *) skb->data; 1836 out_frame = (struct pn533_frame *) skb->data;
@@ -2101,7 +2157,28 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
2101 return rc; 2157 return rc;
2102} 2158}
2103 2159
2104struct nfc_ops pn533_nfc_ops = { 2160static int pn533_fw_reset(struct pn533 *dev)
2161{
2162 int rc;
2163 u8 *params;
2164
2165 nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
2166
2167 pn533_tx_frame_init(dev->out_frame, 0x18);
2168
2169 params = PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame);
2170 params[0] = 0x1;
2171 dev->out_frame->datalen += 1;
2172
2173 pn533_tx_frame_finish(dev->out_frame);
2174
2175 rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame,
2176 dev->in_maxlen);
2177
2178 return rc;
2179}
2180
2181static struct nfc_ops pn533_nfc_ops = {
2105 .dev_up = NULL, 2182 .dev_up = NULL,
2106 .dev_down = NULL, 2183 .dev_down = NULL,
2107 .dep_link_up = pn533_dep_link_up, 2184 .dep_link_up = pn533_dep_link_up,
@@ -2114,6 +2191,84 @@ struct nfc_ops pn533_nfc_ops = {
2114 .tm_send = pn533_tm_send, 2191 .tm_send = pn533_tm_send,
2115}; 2192};
2116 2193
2194static int pn533_setup(struct pn533 *dev)
2195{
2196 struct pn533_config_max_retries max_retries;
2197 struct pn533_config_timing timing;
2198 u8 pasori_cfg[3] = {0x08, 0x01, 0x08};
2199 int rc;
2200
2201 switch (dev->device_type) {
2202 case PN533_DEVICE_STD:
2203 max_retries.mx_rty_atr = PN533_CONFIG_MAX_RETRIES_ENDLESS;
2204 max_retries.mx_rty_psl = 2;
2205 max_retries.mx_rty_passive_act =
2206 PN533_CONFIG_MAX_RETRIES_NO_RETRY;
2207
2208 timing.rfu = PN533_CONFIG_TIMING_102;
2209 timing.atr_res_timeout = PN533_CONFIG_TIMING_204;
2210 timing.dep_timeout = PN533_CONFIG_TIMING_409;
2211
2212 break;
2213
2214 case PN533_DEVICE_PASORI:
2215 max_retries.mx_rty_atr = 0x2;
2216 max_retries.mx_rty_psl = 0x1;
2217 max_retries.mx_rty_passive_act =
2218 PN533_CONFIG_MAX_RETRIES_NO_RETRY;
2219
2220 timing.rfu = PN533_CONFIG_TIMING_102;
2221 timing.atr_res_timeout = PN533_CONFIG_TIMING_102;
2222 timing.dep_timeout = PN533_CONFIG_TIMING_204;
2223
2224 break;
2225
2226 default:
2227 nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n",
2228 dev->device_type);
2229 return -EINVAL;
2230 }
2231
2232 rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES,
2233 (u8 *)&max_retries, sizeof(max_retries));
2234 if (rc) {
2235 nfc_dev_err(&dev->interface->dev,
2236 "Error on setting MAX_RETRIES config");
2237 return rc;
2238 }
2239
2240
2241 rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING,
2242 (u8 *)&timing, sizeof(timing));
2243 if (rc) {
2244 nfc_dev_err(&dev->interface->dev,
2245 "Error on setting RF timings");
2246 return rc;
2247 }
2248
2249 switch (dev->device_type) {
2250 case PN533_DEVICE_STD:
2251 break;
2252
2253 case PN533_DEVICE_PASORI:
2254 pn533_fw_reset(dev);
2255
2256 rc = pn533_set_configuration(dev, PN533_CFGITEM_PASORI,
2257 pasori_cfg, 3);
2258 if (rc) {
2259 nfc_dev_err(&dev->interface->dev,
2260 "Error while settings PASORI config");
2261 return rc;
2262 }
2263
2264 pn533_fw_reset(dev);
2265
2266 break;
2267 }
2268
2269 return 0;
2270}
2271
2117static int pn533_probe(struct usb_interface *interface, 2272static int pn533_probe(struct usb_interface *interface,
2118 const struct usb_device_id *id) 2273 const struct usb_device_id *id)
2119{ 2274{
@@ -2121,8 +2276,6 @@ static int pn533_probe(struct usb_interface *interface,
2121 struct pn533 *dev; 2276 struct pn533 *dev;
2122 struct usb_host_interface *iface_desc; 2277 struct usb_host_interface *iface_desc;
2123 struct usb_endpoint_descriptor *endpoint; 2278 struct usb_endpoint_descriptor *endpoint;
2124 struct pn533_config_max_retries max_retries;
2125 struct pn533_config_timing timing;
2126 int in_endpoint = 0; 2279 int in_endpoint = 0;
2127 int out_endpoint = 0; 2280 int out_endpoint = 0;
2128 int rc = -ENOMEM; 2281 int rc = -ENOMEM;
@@ -2208,10 +2361,22 @@ static int pn533_probe(struct usb_interface *interface,
2208 nfc_dev_info(&dev->interface->dev, "NXP PN533 firmware ver %d.%d now" 2361 nfc_dev_info(&dev->interface->dev, "NXP PN533 firmware ver %d.%d now"
2209 " attached", fw_ver->ver, fw_ver->rev); 2362 " attached", fw_ver->ver, fw_ver->rev);
2210 2363
2211 protocols = NFC_PROTO_JEWEL_MASK 2364 dev->device_type = id->driver_info;
2212 | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK 2365 switch (dev->device_type) {
2213 | NFC_PROTO_ISO14443_MASK 2366 case PN533_DEVICE_STD:
2214 | NFC_PROTO_NFC_DEP_MASK; 2367 protocols = PN533_ALL_PROTOCOLS;
2368 break;
2369
2370 case PN533_DEVICE_PASORI:
2371 protocols = PN533_NO_TYPE_B_PROTOCOLS;
2372 break;
2373
2374 default:
2375 nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n",
2376 dev->device_type);
2377 rc = -EINVAL;
2378 goto destroy_wq;
2379 }
2215 2380
2216 dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, 2381 dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols,
2217 PN533_CMD_DATAEXCH_HEAD_LEN, 2382 PN533_CMD_DATAEXCH_HEAD_LEN,
@@ -2226,30 +2391,9 @@ static int pn533_probe(struct usb_interface *interface,
2226 if (rc) 2391 if (rc)
2227 goto free_nfc_dev; 2392 goto free_nfc_dev;
2228 2393
2229 max_retries.mx_rty_atr = PN533_CONFIG_MAX_RETRIES_ENDLESS; 2394 rc = pn533_setup(dev);
2230 max_retries.mx_rty_psl = 2; 2395 if (rc)
2231 max_retries.mx_rty_passive_act = PN533_CONFIG_MAX_RETRIES_NO_RETRY;
2232
2233 rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES,
2234 (u8 *) &max_retries, sizeof(max_retries));
2235
2236 if (rc) {
2237 nfc_dev_err(&dev->interface->dev, "Error on setting MAX_RETRIES"
2238 " config");
2239 goto unregister_nfc_dev;
2240 }
2241
2242 timing.rfu = PN533_CONFIG_TIMING_102;
2243 timing.atr_res_timeout = PN533_CONFIG_TIMING_204;
2244 timing.dep_timeout = PN533_CONFIG_TIMING_409;
2245
2246 rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING,
2247 (u8 *) &timing, sizeof(timing));
2248 if (rc) {
2249 nfc_dev_err(&dev->interface->dev,
2250 "Error on setting RF timings");
2251 goto unregister_nfc_dev; 2396 goto unregister_nfc_dev;
2252 }
2253 2397
2254 return 0; 2398 return 0;
2255 2399
diff --git a/drivers/nfc/pn544_hci.c b/drivers/nfc/pn544_hci.c
index 457eac35dc74..aa71807189ba 100644
--- a/drivers/nfc/pn544_hci.c
+++ b/drivers/nfc/pn544_hci.c
@@ -108,16 +108,22 @@ enum pn544_state {
108 108
109#define PN544_NFC_WI_MGMT_GATE 0xA1 109#define PN544_NFC_WI_MGMT_GATE 0xA1
110 110
111static u8 pn544_custom_gates[] = { 111static struct nfc_hci_gate pn544_gates[] = {
112 PN544_SYS_MGMT_GATE, 112 {NFC_HCI_ADMIN_GATE, NFC_HCI_INVALID_PIPE},
113 PN544_SWP_MGMT_GATE, 113 {NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE},
114 PN544_POLLING_LOOP_MGMT_GATE, 114 {NFC_HCI_ID_MGMT_GATE, NFC_HCI_INVALID_PIPE},
115 PN544_NFC_WI_MGMT_GATE, 115 {NFC_HCI_LINK_MGMT_GATE, NFC_HCI_INVALID_PIPE},
116 PN544_RF_READER_F_GATE, 116 {NFC_HCI_RF_READER_B_GATE, NFC_HCI_INVALID_PIPE},
117 PN544_RF_READER_JEWEL_GATE, 117 {NFC_HCI_RF_READER_A_GATE, NFC_HCI_INVALID_PIPE},
118 PN544_RF_READER_ISO15693_GATE, 118 {PN544_SYS_MGMT_GATE, NFC_HCI_INVALID_PIPE},
119 PN544_RF_READER_NFCIP1_INITIATOR_GATE, 119 {PN544_SWP_MGMT_GATE, NFC_HCI_INVALID_PIPE},
120 PN544_RF_READER_NFCIP1_TARGET_GATE 120 {PN544_POLLING_LOOP_MGMT_GATE, NFC_HCI_INVALID_PIPE},
121 {PN544_NFC_WI_MGMT_GATE, NFC_HCI_INVALID_PIPE},
122 {PN544_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE},
123 {PN544_RF_READER_JEWEL_GATE, NFC_HCI_INVALID_PIPE},
124 {PN544_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE},
125 {PN544_RF_READER_NFCIP1_INITIATOR_GATE, NFC_HCI_INVALID_PIPE},
126 {PN544_RF_READER_NFCIP1_TARGET_GATE, NFC_HCI_INVALID_PIPE}
121}; 127};
122 128
123/* Largest headroom needed for outgoing custom commands */ 129/* Largest headroom needed for outgoing custom commands */
@@ -377,6 +383,9 @@ static int pn544_hci_open(struct nfc_shdlc *shdlc)
377 383
378 r = pn544_hci_enable(info, HCI_MODE); 384 r = pn544_hci_enable(info, HCI_MODE);
379 385
386 if (r == 0)
387 info->state = PN544_ST_READY;
388
380out: 389out:
381 mutex_unlock(&info->info_lock); 390 mutex_unlock(&info->info_lock);
382 return r; 391 return r;
@@ -393,6 +402,8 @@ static void pn544_hci_close(struct nfc_shdlc *shdlc)
393 402
394 pn544_hci_disable(info); 403 pn544_hci_disable(info);
395 404
405 info->state = PN544_ST_COLD;
406
396out: 407out:
397 mutex_unlock(&info->info_lock); 408 mutex_unlock(&info->info_lock);
398} 409}
@@ -844,10 +855,9 @@ static int __devinit pn544_hci_probe(struct i2c_client *client,
844 goto err_rti; 855 goto err_rti;
845 } 856 }
846 857
847 init_data.gate_count = ARRAY_SIZE(pn544_custom_gates); 858 init_data.gate_count = ARRAY_SIZE(pn544_gates);
848 859
849 memcpy(init_data.gates, pn544_custom_gates, 860 memcpy(init_data.gates, pn544_gates, sizeof(pn544_gates));
850 ARRAY_SIZE(pn544_custom_gates));
851 861
852 /* 862 /*
853 * TODO: Session id must include the driver name + some bus addr 863 * TODO: Session id must include the driver name + some bus addr
@@ -859,6 +869,7 @@ static int __devinit pn544_hci_probe(struct i2c_client *client,
859 NFC_PROTO_MIFARE_MASK | 869 NFC_PROTO_MIFARE_MASK |
860 NFC_PROTO_FELICA_MASK | 870 NFC_PROTO_FELICA_MASK |
861 NFC_PROTO_ISO14443_MASK | 871 NFC_PROTO_ISO14443_MASK |
872 NFC_PROTO_ISO14443_B_MASK |
862 NFC_PROTO_NFC_DEP_MASK; 873 NFC_PROTO_NFC_DEP_MASK;
863 874
864 info->shdlc = nfc_shdlc_allocate(&pn544_shdlc_ops, 875 info->shdlc = nfc_shdlc_allocate(&pn544_shdlc_ops,
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 12334f9190cb..03b2f30d2ace 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -137,6 +137,36 @@ struct bcma_host_ops {
137 137
138#define BCMA_MAX_NR_CORES 16 138#define BCMA_MAX_NR_CORES 16
139 139
140/* Chip IDs of PCIe devices */
141#define BCMA_CHIP_ID_BCM4313 0x4313
142#define BCMA_CHIP_ID_BCM43224 43224
143#define BCMA_PKG_ID_BCM43224_FAB_CSM 0x8
144#define BCMA_PKG_ID_BCM43224_FAB_SMIC 0xa
145#define BCMA_CHIP_ID_BCM43225 43225
146#define BCMA_CHIP_ID_BCM43227 43227
147#define BCMA_CHIP_ID_BCM43228 43228
148#define BCMA_CHIP_ID_BCM43421 43421
149#define BCMA_CHIP_ID_BCM43428 43428
150#define BCMA_CHIP_ID_BCM43431 43431
151#define BCMA_CHIP_ID_BCM43460 43460
152#define BCMA_CHIP_ID_BCM4331 0x4331
153#define BCMA_CHIP_ID_BCM6362 0x6362
154#define BCMA_CHIP_ID_BCM4360 0x4360
155#define BCMA_CHIP_ID_BCM4352 0x4352
156
157/* Chip IDs of SoCs */
158#define BCMA_CHIP_ID_BCM4706 0x5300
159#define BCMA_CHIP_ID_BCM4716 0x4716
160#define BCMA_PKG_ID_BCM4716 8
161#define BCMA_PKG_ID_BCM4717 9
162#define BCMA_PKG_ID_BCM4718 10
163#define BCMA_CHIP_ID_BCM47162 47162
164#define BCMA_CHIP_ID_BCM4748 0x4748
165#define BCMA_CHIP_ID_BCM4749 0x4749
166#define BCMA_CHIP_ID_BCM5356 0x5356
167#define BCMA_CHIP_ID_BCM5357 0x5357
168#define BCMA_CHIP_ID_BCM53572 53572
169
140struct bcma_device { 170struct bcma_device {
141 struct bcma_bus *bus; 171 struct bcma_bus *bus;
142 struct bcma_device_id id; 172 struct bcma_device_id id;
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index 8bbfe31fbac8..fbd0d49dc4d2 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -88,6 +88,11 @@
88#define BCMA_CC_CHIPST_4313_OTP_PRESENT 2 88#define BCMA_CC_CHIPST_4313_OTP_PRESENT 2
89#define BCMA_CC_CHIPST_4331_SPROM_PRESENT 2 89#define BCMA_CC_CHIPST_4331_SPROM_PRESENT 2
90#define BCMA_CC_CHIPST_4331_OTP_PRESENT 4 90#define BCMA_CC_CHIPST_4331_OTP_PRESENT 4
91#define BCMA_CC_CHIPST_4706_PKG_OPTION BIT(0) /* 0: full-featured package 1: low-cost package */
92#define BCMA_CC_CHIPST_4706_SFLASH_PRESENT BIT(1) /* 0: parallel, 1: serial flash is present */
93#define BCMA_CC_CHIPST_4706_SFLASH_TYPE BIT(2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */
94#define BCMA_CC_CHIPST_4706_MIPS_BENDIAN BIT(3) /* 0: little, 1: big endian */
95#define BCMA_CC_CHIPST_4706_PCIE1_DISABLE BIT(5) /* PCIE1 enable strap pin */
91#define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */ 96#define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */
92#define BCMA_CC_JCMD_START 0x80000000 97#define BCMA_CC_JCMD_START 0x80000000
93#define BCMA_CC_JCMD_BUSY 0x80000000 98#define BCMA_CC_JCMD_BUSY 0x80000000
@@ -280,6 +285,15 @@
280 285
281/* 4706 PMU */ 286/* 4706 PMU */
282#define BCMA_CC_PMU4706_MAINPLL_PLL0 0 287#define BCMA_CC_PMU4706_MAINPLL_PLL0 0
288#define BCMA_CC_PMU6_4706_PROCPLL_OFF 4 /* The CPU PLL */
289#define BCMA_CC_PMU6_4706_PROC_P2DIV_MASK 0x000f0000
290#define BCMA_CC_PMU6_4706_PROC_P2DIV_SHIFT 16
291#define BCMA_CC_PMU6_4706_PROC_P1DIV_MASK 0x0000f000
292#define BCMA_CC_PMU6_4706_PROC_P1DIV_SHIFT 12
293#define BCMA_CC_PMU6_4706_PROC_NDIV_INT_MASK 0x00000ff8
294#define BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT 3
295#define BCMA_CC_PMU6_4706_PROC_NDIV_MODE_MASK 0x00000007
296#define BCMA_CC_PMU6_4706_PROC_NDIV_MODE_SHIFT 0
283 297
284/* ALP clock on pre-PMU chips */ 298/* ALP clock on pre-PMU chips */
285#define BCMA_CC_PMU_ALP_CLOCK 20000000 299#define BCMA_CC_PMU_ALP_CLOCK 20000000
@@ -308,6 +322,19 @@
308#define BCMA_CC_PPL_PCHI_OFF 5 322#define BCMA_CC_PPL_PCHI_OFF 5
309#define BCMA_CC_PPL_PCHI_MASK 0x0000003f 323#define BCMA_CC_PPL_PCHI_MASK 0x0000003f
310 324
325#define BCMA_CC_PMU_PLL_CTL0 0
326#define BCMA_CC_PMU_PLL_CTL1 1
327#define BCMA_CC_PMU_PLL_CTL2 2
328#define BCMA_CC_PMU_PLL_CTL3 3
329#define BCMA_CC_PMU_PLL_CTL4 4
330#define BCMA_CC_PMU_PLL_CTL5 5
331
332#define BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK 0x00f00000
333#define BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT 20
334
335#define BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK 0x1ff00000
336#define BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT 20
337
311/* BCM4331 ChipControl numbers. */ 338/* BCM4331 ChipControl numbers. */
312#define BCMA_CHIPCTL_4331_BT_COEXIST BIT(0) /* 0 disable */ 339#define BCMA_CHIPCTL_4331_BT_COEXIST BIT(0) /* 0 disable */
313#define BCMA_CHIPCTL_4331_SECI BIT(1) /* 0 SECI is disabled (JATG functional) */ 340#define BCMA_CHIPCTL_4331_SECI BIT(1) /* 0 SECI is disabled (JATG functional) */
@@ -321,9 +348,18 @@
321#define BCMA_CHIPCTL_4331_OVR_PIPEAUXPWRDOWN BIT(9) /* override core control on pipe_AuxPowerDown */ 348#define BCMA_CHIPCTL_4331_OVR_PIPEAUXPWRDOWN BIT(9) /* override core control on pipe_AuxPowerDown */
322#define BCMA_CHIPCTL_4331_PCIE_AUXCLKEN BIT(10) /* pcie_auxclkenable */ 349#define BCMA_CHIPCTL_4331_PCIE_AUXCLKEN BIT(10) /* pcie_auxclkenable */
323#define BCMA_CHIPCTL_4331_PCIE_PIPE_PLLDOWN BIT(11) /* pcie_pipe_pllpowerdown */ 350#define BCMA_CHIPCTL_4331_PCIE_PIPE_PLLDOWN BIT(11) /* pcie_pipe_pllpowerdown */
351#define BCMA_CHIPCTL_4331_EXTPA_EN2 BIT(12) /* 0 ext pa disable, 1 ext pa enabled */
324#define BCMA_CHIPCTL_4331_BT_SHD0_ON_GPIO4 BIT(16) /* enable bt_shd0 at gpio4 */ 352#define BCMA_CHIPCTL_4331_BT_SHD0_ON_GPIO4 BIT(16) /* enable bt_shd0 at gpio4 */
325#define BCMA_CHIPCTL_4331_BT_SHD1_ON_GPIO5 BIT(17) /* enable bt_shd1 at gpio5 */ 353#define BCMA_CHIPCTL_4331_BT_SHD1_ON_GPIO5 BIT(17) /* enable bt_shd1 at gpio5 */
326 354
355/* 43224 chip-specific ChipControl register bits */
356#define BCMA_CCTRL_43224_GPIO_TOGGLE 0x8000 /* gpio[3:0] pins as btcoex or s/w gpio */
357#define BCMA_CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */
358#define BCMA_CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */
359
360/* 4313 Chip specific ChipControl register bits */
361#define BCMA_CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */
362
327/* Data for the PMU, if available. 363/* Data for the PMU, if available.
328 * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) 364 * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
329 */ 365 */
@@ -411,5 +447,6 @@ extern void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
411 u32 offset, u32 mask, u32 set); 447 u32 offset, u32 mask, u32 set);
412extern void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, 448extern void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc,
413 u32 offset, u32 mask, u32 set); 449 u32 offset, u32 mask, u32 set);
450extern void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid);
414 451
415#endif /* LINUX_BCMA_DRIVER_CC_H_ */ 452#endif /* LINUX_BCMA_DRIVER_CC_H_ */
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 318fc1f705b1..e02fc682bb68 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -47,6 +47,7 @@
47#define IEEE80211_FCTL_MOREDATA 0x2000 47#define IEEE80211_FCTL_MOREDATA 0x2000
48#define IEEE80211_FCTL_PROTECTED 0x4000 48#define IEEE80211_FCTL_PROTECTED 0x4000
49#define IEEE80211_FCTL_ORDER 0x8000 49#define IEEE80211_FCTL_ORDER 0x8000
50#define IEEE80211_FCTL_CTL_EXT 0x0f00
50 51
51#define IEEE80211_SCTL_FRAG 0x000F 52#define IEEE80211_SCTL_FRAG 0x000F
52#define IEEE80211_SCTL_SEQ 0xFFF0 53#define IEEE80211_SCTL_SEQ 0xFFF0
@@ -54,6 +55,7 @@
54#define IEEE80211_FTYPE_MGMT 0x0000 55#define IEEE80211_FTYPE_MGMT 0x0000
55#define IEEE80211_FTYPE_CTL 0x0004 56#define IEEE80211_FTYPE_CTL 0x0004
56#define IEEE80211_FTYPE_DATA 0x0008 57#define IEEE80211_FTYPE_DATA 0x0008
58#define IEEE80211_FTYPE_EXT 0x000c
57 59
58/* management */ 60/* management */
59#define IEEE80211_STYPE_ASSOC_REQ 0x0000 61#define IEEE80211_STYPE_ASSOC_REQ 0x0000
@@ -70,6 +72,7 @@
70#define IEEE80211_STYPE_ACTION 0x00D0 72#define IEEE80211_STYPE_ACTION 0x00D0
71 73
72/* control */ 74/* control */
75#define IEEE80211_STYPE_CTL_EXT 0x0060
73#define IEEE80211_STYPE_BACK_REQ 0x0080 76#define IEEE80211_STYPE_BACK_REQ 0x0080
74#define IEEE80211_STYPE_BACK 0x0090 77#define IEEE80211_STYPE_BACK 0x0090
75#define IEEE80211_STYPE_PSPOLL 0x00A0 78#define IEEE80211_STYPE_PSPOLL 0x00A0
@@ -97,6 +100,18 @@
97#define IEEE80211_STYPE_QOS_CFPOLL 0x00E0 100#define IEEE80211_STYPE_QOS_CFPOLL 0x00E0
98#define IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0 101#define IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0
99 102
103/* extension, added by 802.11ad */
104#define IEEE80211_STYPE_DMG_BEACON 0x0000
105
106/* control extension - for IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTL_EXT */
107#define IEEE80211_CTL_EXT_POLL 0x2000
108#define IEEE80211_CTL_EXT_SPR 0x3000
109#define IEEE80211_CTL_EXT_GRANT 0x4000
110#define IEEE80211_CTL_EXT_DMG_CTS 0x5000
111#define IEEE80211_CTL_EXT_DMG_DTS 0x6000
112#define IEEE80211_CTL_EXT_SSW 0x8000
113#define IEEE80211_CTL_EXT_SSW_FBACK 0x9000
114#define IEEE80211_CTL_EXT_SSW_ACK 0xa000
100 115
101/* miscellaneous IEEE 802.11 constants */ 116/* miscellaneous IEEE 802.11 constants */
102#define IEEE80211_MAX_FRAG_THRESHOLD 2352 117#define IEEE80211_MAX_FRAG_THRESHOLD 2352
@@ -1092,6 +1107,73 @@ struct ieee80211_ht_operation {
1092#define WLAN_HT_SMPS_CONTROL_STATIC 1 1107#define WLAN_HT_SMPS_CONTROL_STATIC 1
1093#define WLAN_HT_SMPS_CONTROL_DYNAMIC 3 1108#define WLAN_HT_SMPS_CONTROL_DYNAMIC 3
1094 1109
1110#define VHT_MCS_SUPPORTED_SET_SIZE 8
1111
1112struct ieee80211_vht_capabilities {
1113 __le32 vht_capabilities_info;
1114 u8 vht_supported_mcs_set[VHT_MCS_SUPPORTED_SET_SIZE];
1115} __packed;
1116
1117struct ieee80211_vht_operation {
1118 u8 vht_op_info_chwidth;
1119 u8 vht_op_info_chan_center_freq_seg1_idx;
1120 u8 vht_op_info_chan_center_freq_seg2_idx;
1121 __le16 vht_basic_mcs_set;
1122} __packed;
1123
1124/**
1125 * struct ieee80211_vht_mcs_info - VHT MCS information
1126 * @rx_mcs_map: RX MCS map 2 bits for each stream, total 8 streams
1127 * @rx_highest: Indicates highest long GI VHT PPDU data rate
1128 * STA can receive. Rate expressed in units of 1 Mbps.
1129 * If this field is 0 this value should not be used to
1130 * consider the highest RX data rate supported.
1131 * @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams
1132 * @tx_highest: Indicates highest long GI VHT PPDU data rate
1133 * STA can transmit. Rate expressed in units of 1 Mbps.
1134 * If this field is 0 this value should not be used to
1135 * consider the highest TX data rate supported.
1136 */
1137struct ieee80211_vht_mcs_info {
1138 __le16 rx_mcs_map;
1139 __le16 rx_highest;
1140 __le16 tx_mcs_map;
1141 __le16 tx_highest;
1142} __packed;
1143
1144#define IEEE80211_VHT_MCS_ZERO_TO_SEVEN_SUPPORT 0
1145#define IEEE80211_VHT_MCS_ZERO_TO_EIGHT_SUPPORT 1
1146#define IEEE80211_VHT_MCS_ZERO_TO_NINE_SUPPORT 2
1147#define IEEE80211_VHT_MCS_NOT_SUPPORTED 3
1148
1149/* 802.11ac VHT Capabilities */
1150#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000
1151#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001
1152#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002
1153#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004
1154#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008
1155#define IEEE80211_VHT_CAP_RXLDPC 0x00000010
1156#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020
1157#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040
1158#define IEEE80211_VHT_CAP_TXSTBC 0x00000080
1159#define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100
1160#define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200
1161#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300
1162#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400
1163#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800
1164#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000
1165#define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000
1166#define IEEE80211_VHT_CAP_SOUNDING_DIMENTION_MAX 0x00030000
1167#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000
1168#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000
1169#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000
1170#define IEEE80211_VHT_CAP_HTC_VHT 0x00400000
1171#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT 0x00800000
1172#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000
1173#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000
1174#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000
1175#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000
1176
1095/* Authentication algorithms */ 1177/* Authentication algorithms */
1096#define WLAN_AUTH_OPEN 0 1178#define WLAN_AUTH_OPEN 0
1097#define WLAN_AUTH_SHARED_KEY 1 1179#define WLAN_AUTH_SHARED_KEY 1
@@ -1124,6 +1206,21 @@ struct ieee80211_ht_operation {
1124#define WLAN_CAPABILITY_QOS (1<<9) 1206#define WLAN_CAPABILITY_QOS (1<<9)
1125#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) 1207#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
1126#define WLAN_CAPABILITY_DSSS_OFDM (1<<13) 1208#define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
1209
1210/* DMG (60gHz) 802.11ad */
1211/* type - bits 0..1 */
1212#define WLAN_CAPABILITY_DMG_TYPE_IBSS (1<<0) /* Tx by: STA */
1213#define WLAN_CAPABILITY_DMG_TYPE_PBSS (2<<0) /* Tx by: PCP */
1214#define WLAN_CAPABILITY_DMG_TYPE_AP (3<<0) /* Tx by: AP */
1215
1216#define WLAN_CAPABILITY_DMG_CBAP_ONLY (1<<2)
1217#define WLAN_CAPABILITY_DMG_CBAP_SOURCE (1<<3)
1218#define WLAN_CAPABILITY_DMG_PRIVACY (1<<4)
1219#define WLAN_CAPABILITY_DMG_ECPAC (1<<5)
1220
1221#define WLAN_CAPABILITY_DMG_SPECTRUM_MGMT (1<<8)
1222#define WLAN_CAPABILITY_DMG_RADIO_MEASURE (1<<12)
1223
1127/* measurement */ 1224/* measurement */
1128#define IEEE80211_SPCT_MSR_RPRT_MODE_LATE (1<<0) 1225#define IEEE80211_SPCT_MSR_RPRT_MODE_LATE (1<<0)
1129#define IEEE80211_SPCT_MSR_RPRT_MODE_INCAPABLE (1<<1) 1226#define IEEE80211_SPCT_MSR_RPRT_MODE_INCAPABLE (1<<1)
@@ -1133,7 +1230,6 @@ struct ieee80211_ht_operation {
1133#define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1 1230#define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1
1134#define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2 1231#define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2
1135 1232
1136
1137/* 802.11g ERP information element */ 1233/* 802.11g ERP information element */
1138#define WLAN_ERP_NON_ERP_PRESENT (1<<0) 1234#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
1139#define WLAN_ERP_USE_PROTECTION (1<<1) 1235#define WLAN_ERP_USE_PROTECTION (1<<1)
@@ -1145,6 +1241,16 @@ enum {
1145 WLAN_ERP_PREAMBLE_LONG = 1, 1241 WLAN_ERP_PREAMBLE_LONG = 1,
1146}; 1242};
1147 1243
1244/* Band ID, 802.11ad #8.4.1.45 */
1245enum {
1246 IEEE80211_BANDID_TV_WS = 0, /* TV white spaces */
1247 IEEE80211_BANDID_SUB1 = 1, /* Sub-1 GHz (excluding TV white spaces) */
1248 IEEE80211_BANDID_2G = 2, /* 2.4 GHz */
1249 IEEE80211_BANDID_3G = 3, /* 3.6 GHz */
1250 IEEE80211_BANDID_5G = 4, /* 4.9 and 5 GHz */
1251 IEEE80211_BANDID_60G = 5, /* 60 GHz */
1252};
1253
1148/* Status codes */ 1254/* Status codes */
1149enum ieee80211_statuscode { 1255enum ieee80211_statuscode {
1150 WLAN_STATUS_SUCCESS = 0, 1256 WLAN_STATUS_SUCCESS = 0,
@@ -1196,6 +1302,17 @@ enum ieee80211_statuscode {
1196 WLAN_STATUS_ANTI_CLOG_REQUIRED = 76, 1302 WLAN_STATUS_ANTI_CLOG_REQUIRED = 76,
1197 WLAN_STATUS_FCG_NOT_SUPP = 78, 1303 WLAN_STATUS_FCG_NOT_SUPP = 78,
1198 WLAN_STATUS_STA_NO_TBTT = 78, 1304 WLAN_STATUS_STA_NO_TBTT = 78,
1305 /* 802.11ad */
1306 WLAN_STATUS_REJECTED_WITH_SUGGESTED_CHANGES = 39,
1307 WLAN_STATUS_REJECTED_FOR_DELAY_PERIOD = 47,
1308 WLAN_STATUS_REJECT_WITH_SCHEDULE = 83,
1309 WLAN_STATUS_PENDING_ADMITTING_FST_SESSION = 86,
1310 WLAN_STATUS_PERFORMING_FST_NOW = 87,
1311 WLAN_STATUS_PENDING_GAP_IN_BA_WINDOW = 88,
1312 WLAN_STATUS_REJECT_U_PID_SETTING = 89,
1313 WLAN_STATUS_REJECT_DSE_BAND = 96,
1314 WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL = 99,
1315 WLAN_STATUS_DENIED_DUE_TO_SPECTRUM_MANAGEMENT = 103,
1199}; 1316};
1200 1317
1201 1318
@@ -1352,6 +1469,43 @@ enum ieee80211_eid {
1352 WLAN_EID_DSE_REGISTERED_LOCATION = 58, 1469 WLAN_EID_DSE_REGISTERED_LOCATION = 58,
1353 WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59, 1470 WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59,
1354 WLAN_EID_EXT_CHANSWITCH_ANN = 60, 1471 WLAN_EID_EXT_CHANSWITCH_ANN = 60,
1472
1473 WLAN_EID_VHT_CAPABILITY = 191,
1474 WLAN_EID_VHT_OPERATION = 192,
1475
1476 /* 802.11ad */
1477 WLAN_EID_NON_TX_BSSID_CAP = 83,
1478 WLAN_EID_WAKEUP_SCHEDULE = 143,
1479 WLAN_EID_EXT_SCHEDULE = 144,
1480 WLAN_EID_STA_AVAILABILITY = 145,
1481 WLAN_EID_DMG_TSPEC = 146,
1482 WLAN_EID_DMG_AT = 147,
1483 WLAN_EID_DMG_CAP = 148,
1484 WLAN_EID_DMG_OPERATION = 151,
1485 WLAN_EID_DMG_BSS_PARAM_CHANGE = 152,
1486 WLAN_EID_DMG_BEAM_REFINEMENT = 153,
1487 WLAN_EID_CHANNEL_MEASURE_FEEDBACK = 154,
1488 WLAN_EID_AWAKE_WINDOW = 157,
1489 WLAN_EID_MULTI_BAND = 158,
1490 WLAN_EID_ADDBA_EXT = 159,
1491 WLAN_EID_NEXT_PCP_LIST = 160,
1492 WLAN_EID_PCP_HANDOVER = 161,
1493 WLAN_EID_DMG_LINK_MARGIN = 162,
1494 WLAN_EID_SWITCHING_STREAM = 163,
1495 WLAN_EID_SESSION_TRANSITION = 164,
1496 WLAN_EID_DYN_TONE_PAIRING_REPORT = 165,
1497 WLAN_EID_CLUSTER_REPORT = 166,
1498 WLAN_EID_RELAY_CAP = 167,
1499 WLAN_EID_RELAY_XFER_PARAM_SET = 168,
1500 WLAN_EID_BEAM_LINK_MAINT = 169,
1501 WLAN_EID_MULTIPLE_MAC_ADDR = 170,
1502 WLAN_EID_U_PID = 171,
1503 WLAN_EID_DMG_LINK_ADAPT_ACK = 172,
1504 WLAN_EID_QUIET_PERIOD_REQ = 175,
1505 WLAN_EID_QUIET_PERIOD_RESP = 177,
1506 WLAN_EID_EPAC_POLICY = 182,
1507 WLAN_EID_CLISTER_TIME_OFF = 183,
1508 WLAN_EID_ANTENNA_SECTOR_ID_PATTERN = 190,
1355}; 1509};
1356 1510
1357/* Action category code */ 1511/* Action category code */
@@ -1368,7 +1522,10 @@ enum ieee80211_category {
1368 WLAN_CATEGORY_MESH_ACTION = 13, 1522 WLAN_CATEGORY_MESH_ACTION = 13,
1369 WLAN_CATEGORY_MULTIHOP_ACTION = 14, 1523 WLAN_CATEGORY_MULTIHOP_ACTION = 14,
1370 WLAN_CATEGORY_SELF_PROTECTED = 15, 1524 WLAN_CATEGORY_SELF_PROTECTED = 15,
1525 WLAN_CATEGORY_DMG = 16,
1371 WLAN_CATEGORY_WMM = 17, 1526 WLAN_CATEGORY_WMM = 17,
1527 WLAN_CATEGORY_FST = 18,
1528 WLAN_CATEGORY_UNPROT_DMG = 20,
1372 WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, 1529 WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126,
1373 WLAN_CATEGORY_VENDOR_SPECIFIC = 127, 1530 WLAN_CATEGORY_VENDOR_SPECIFIC = 127,
1374}; 1531};
@@ -1616,6 +1773,7 @@ enum ieee80211_sa_query_action {
1616#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 1773#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
1617#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 1774#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
1618#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 1775#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
1776#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
1619 1777
1620#define WLAN_CIPHER_SUITE_SMS4 0x00147201 1778#define WLAN_CIPHER_SUITE_SMS4 0x00147201
1621 1779
diff --git a/include/linux/nfc.h b/include/linux/nfc.h
index f4e6dd915b1c..6189f27e305b 100644
--- a/include/linux/nfc.h
+++ b/include/linux/nfc.h
@@ -136,8 +136,9 @@ enum nfc_attrs {
136#define NFC_PROTO_FELICA 3 136#define NFC_PROTO_FELICA 3
137#define NFC_PROTO_ISO14443 4 137#define NFC_PROTO_ISO14443 4
138#define NFC_PROTO_NFC_DEP 5 138#define NFC_PROTO_NFC_DEP 5
139#define NFC_PROTO_ISO14443_B 6
139 140
140#define NFC_PROTO_MAX 6 141#define NFC_PROTO_MAX 7
141 142
142/* NFC communication modes */ 143/* NFC communication modes */
143#define NFC_COMM_ACTIVE 0 144#define NFC_COMM_ACTIVE 0
@@ -149,11 +150,12 @@ enum nfc_attrs {
149#define NFC_RF_NONE 2 150#define NFC_RF_NONE 2
150 151
151/* NFC protocols masks used in bitsets */ 152/* NFC protocols masks used in bitsets */
152#define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL) 153#define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL)
153#define NFC_PROTO_MIFARE_MASK (1 << NFC_PROTO_MIFARE) 154#define NFC_PROTO_MIFARE_MASK (1 << NFC_PROTO_MIFARE)
154#define NFC_PROTO_FELICA_MASK (1 << NFC_PROTO_FELICA) 155#define NFC_PROTO_FELICA_MASK (1 << NFC_PROTO_FELICA)
155#define NFC_PROTO_ISO14443_MASK (1 << NFC_PROTO_ISO14443) 156#define NFC_PROTO_ISO14443_MASK (1 << NFC_PROTO_ISO14443)
156#define NFC_PROTO_NFC_DEP_MASK (1 << NFC_PROTO_NFC_DEP) 157#define NFC_PROTO_NFC_DEP_MASK (1 << NFC_PROTO_NFC_DEP)
158#define NFC_PROTO_ISO14443_B_MASK (1 << NFC_PROTO_ISO14443_B)
157 159
158struct sockaddr_nfc { 160struct sockaddr_nfc {
159 sa_family_t sa_family; 161 sa_family_t sa_family;
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index c0fc5d277338..db961a59247f 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1638,12 +1638,20 @@ struct nl80211_sta_flag_update {
1638 * 1638 *
1639 * These attribute types are used with %NL80211_STA_INFO_TXRATE 1639 * These attribute types are used with %NL80211_STA_INFO_TXRATE
1640 * when getting information about the bitrate of a station. 1640 * when getting information about the bitrate of a station.
1641 * There are 2 attributes for bitrate, a legacy one that represents
1642 * a 16-bit value, and new one that represents a 32-bit value.
1643 * If the rate value fits into 16 bit, both attributes are reported
1644 * with the same value. If the rate is too high to fit into 16 bits
1645 * (>6.5535Gbps) only 32-bit attribute is included.
1646 * User space tools encouraged to use the 32-bit attribute and fall
1647 * back to the 16-bit one for compatibility with older kernels.
1641 * 1648 *
1642 * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved 1649 * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
1643 * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s) 1650 * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
1644 * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8) 1651 * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
1645 * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate 1652 * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
1646 * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval 1653 * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
1654 * @NL80211_RATE_INFO_BITRATE32: total bitrate (u32, 100kbit/s)
1647 * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined 1655 * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined
1648 * @__NL80211_RATE_INFO_AFTER_LAST: internal use 1656 * @__NL80211_RATE_INFO_AFTER_LAST: internal use
1649 */ 1657 */
@@ -1653,6 +1661,7 @@ enum nl80211_rate_info {
1653 NL80211_RATE_INFO_MCS, 1661 NL80211_RATE_INFO_MCS,
1654 NL80211_RATE_INFO_40_MHZ_WIDTH, 1662 NL80211_RATE_INFO_40_MHZ_WIDTH,
1655 NL80211_RATE_INFO_SHORT_GI, 1663 NL80211_RATE_INFO_SHORT_GI,
1664 NL80211_RATE_INFO_BITRATE32,
1656 1665
1657 /* keep last */ 1666 /* keep last */
1658 __NL80211_RATE_INFO_AFTER_LAST, 1667 __NL80211_RATE_INFO_AFTER_LAST,
@@ -1813,6 +1822,9 @@ enum nl80211_mpath_info {
1813 * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE 1822 * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE
1814 * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n 1823 * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n
1815 * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n 1824 * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n
1825 * @NL80211_BAND_ATTR_VHT_MCS_SET: 32-byte attribute containing the MCS set as
1826 * defined in 802.11ac
1827 * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE
1816 * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined 1828 * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined
1817 * @__NL80211_BAND_ATTR_AFTER_LAST: internal use 1829 * @__NL80211_BAND_ATTR_AFTER_LAST: internal use
1818 */ 1830 */
@@ -1826,6 +1838,9 @@ enum nl80211_band_attr {
1826 NL80211_BAND_ATTR_HT_AMPDU_FACTOR, 1838 NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
1827 NL80211_BAND_ATTR_HT_AMPDU_DENSITY, 1839 NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
1828 1840
1841 NL80211_BAND_ATTR_VHT_MCS_SET,
1842 NL80211_BAND_ATTR_VHT_CAPA,
1843
1829 /* keep last */ 1844 /* keep last */
1830 __NL80211_BAND_ATTR_AFTER_LAST, 1845 __NL80211_BAND_ATTR_AFTER_LAST,
1831 NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1 1846 NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
@@ -2539,10 +2554,12 @@ enum nl80211_tx_rate_attributes {
2539 * enum nl80211_band - Frequency band 2554 * enum nl80211_band - Frequency band
2540 * @NL80211_BAND_2GHZ: 2.4 GHz ISM band 2555 * @NL80211_BAND_2GHZ: 2.4 GHz ISM band
2541 * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) 2556 * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz)
2557 * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz)
2542 */ 2558 */
2543enum nl80211_band { 2559enum nl80211_band {
2544 NL80211_BAND_2GHZ, 2560 NL80211_BAND_2GHZ,
2545 NL80211_BAND_5GHZ, 2561 NL80211_BAND_5GHZ,
2562 NL80211_BAND_60GHZ,
2546}; 2563};
2547 2564
2548/** 2565/**
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 061c01957e54..51f67a9003a9 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -70,11 +70,13 @@
70 * 70 *
71 * @IEEE80211_BAND_2GHZ: 2.4GHz ISM band 71 * @IEEE80211_BAND_2GHZ: 2.4GHz ISM band
72 * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7) 72 * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7)
73 * @IEEE80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz)
73 * @IEEE80211_NUM_BANDS: number of defined bands 74 * @IEEE80211_NUM_BANDS: number of defined bands
74 */ 75 */
75enum ieee80211_band { 76enum ieee80211_band {
76 IEEE80211_BAND_2GHZ = NL80211_BAND_2GHZ, 77 IEEE80211_BAND_2GHZ = NL80211_BAND_2GHZ,
77 IEEE80211_BAND_5GHZ = NL80211_BAND_5GHZ, 78 IEEE80211_BAND_5GHZ = NL80211_BAND_5GHZ,
79 IEEE80211_BAND_60GHZ = NL80211_BAND_60GHZ,
78 80
79 /* keep last */ 81 /* keep last */
80 IEEE80211_NUM_BANDS 82 IEEE80211_NUM_BANDS
@@ -211,6 +213,22 @@ struct ieee80211_sta_ht_cap {
211}; 213};
212 214
213/** 215/**
216 * struct ieee80211_sta_vht_cap - STA's VHT capabilities
217 *
218 * This structure describes most essential parameters needed
219 * to describe 802.11ac VHT capabilities for an STA.
220 *
221 * @vht_supported: is VHT supported by the STA
222 * @cap: VHT capabilities map as described in 802.11ac spec
223 * @vht_mcs: Supported VHT MCS rates
224 */
225struct ieee80211_sta_vht_cap {
226 bool vht_supported;
227 u32 cap; /* use IEEE80211_VHT_CAP_ */
228 struct ieee80211_vht_mcs_info vht_mcs;
229};
230
231/**
214 * struct ieee80211_supported_band - frequency band definition 232 * struct ieee80211_supported_band - frequency band definition
215 * 233 *
216 * This structure describes a frequency band a wiphy 234 * This structure describes a frequency band a wiphy
@@ -233,6 +251,7 @@ struct ieee80211_supported_band {
233 int n_channels; 251 int n_channels;
234 int n_bitrates; 252 int n_bitrates;
235 struct ieee80211_sta_ht_cap ht_cap; 253 struct ieee80211_sta_ht_cap ht_cap;
254 struct ieee80211_sta_vht_cap vht_cap;
236}; 255};
237 256
238/* 257/*
@@ -561,11 +580,13 @@ enum station_info_flags {
561 * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled 580 * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
562 * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission 581 * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
563 * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval 582 * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
583 * @RATE_INFO_FLAGS_60G: 60gHz MCS
564 */ 584 */
565enum rate_info_flags { 585enum rate_info_flags {
566 RATE_INFO_FLAGS_MCS = 1<<0, 586 RATE_INFO_FLAGS_MCS = 1<<0,
567 RATE_INFO_FLAGS_40_MHZ_WIDTH = 1<<1, 587 RATE_INFO_FLAGS_40_MHZ_WIDTH = 1<<1,
568 RATE_INFO_FLAGS_SHORT_GI = 1<<2, 588 RATE_INFO_FLAGS_SHORT_GI = 1<<2,
589 RATE_INFO_FLAGS_60G = 1<<3,
569}; 590};
570 591
571/** 592/**
@@ -1482,9 +1503,8 @@ struct cfg80211_gtk_rekey_data {
1482 * interfaces are active this callback should reject the configuration. 1503 * interfaces are active this callback should reject the configuration.
1483 * If no interfaces are active or the device is down, the channel should 1504 * If no interfaces are active or the device is down, the channel should
1484 * be stored for when a monitor interface becomes active. 1505 * be stored for when a monitor interface becomes active.
1485 * @get_channel: Get the current operating channel, should return %NULL if 1506 * @set_monitor_enabled: Notify driver that there are only monitor
1486 * there's no single defined operating channel if for example the 1507 * interfaces running.
1487 * device implements channel hopping for multi-channel virtual interfaces.
1488 * 1508 *
1489 * @scan: Request to do a scan. If returning zero, the scan request is given 1509 * @scan: Request to do a scan. If returning zero, the scan request is given
1490 * the driver, and will be valid until passed to cfg80211_scan_done(). 1510 * the driver, and will be valid until passed to cfg80211_scan_done().
@@ -1791,15 +1811,14 @@ struct cfg80211_ops {
1791 struct net_device *dev, 1811 struct net_device *dev,
1792 u16 noack_map); 1812 u16 noack_map);
1793 1813
1794 struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy,
1795 enum nl80211_channel_type *type);
1796
1797 int (*get_et_sset_count)(struct wiphy *wiphy, 1814 int (*get_et_sset_count)(struct wiphy *wiphy,
1798 struct net_device *dev, int sset); 1815 struct net_device *dev, int sset);
1799 void (*get_et_stats)(struct wiphy *wiphy, struct net_device *dev, 1816 void (*get_et_stats)(struct wiphy *wiphy, struct net_device *dev,
1800 struct ethtool_stats *stats, u64 *data); 1817 struct ethtool_stats *stats, u64 *data);
1801 void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev, 1818 void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev,
1802 u32 sset, u8 *data); 1819 u32 sset, u8 *data);
1820
1821 void (*set_monitor_enabled)(struct wiphy *wiphy, bool enabled);
1803}; 1822};
1804 1823
1805/* 1824/*
@@ -2153,7 +2172,9 @@ struct wiphy {
2153 char fw_version[ETHTOOL_BUSINFO_LEN]; 2172 char fw_version[ETHTOOL_BUSINFO_LEN];
2154 u32 hw_version; 2173 u32 hw_version;
2155 2174
2175#ifdef CONFIG_PM
2156 struct wiphy_wowlan_support wowlan; 2176 struct wiphy_wowlan_support wowlan;
2177#endif
2157 2178
2158 u16 max_remain_on_channel_duration; 2179 u16 max_remain_on_channel_duration;
2159 2180
@@ -2389,6 +2410,11 @@ struct wireless_dev {
2389 struct ieee80211_channel *preset_chan; 2410 struct ieee80211_channel *preset_chan;
2390 enum nl80211_channel_type preset_chantype; 2411 enum nl80211_channel_type preset_chantype;
2391 2412
2413 /* for AP and mesh channel tracking */
2414 struct ieee80211_channel *channel;
2415
2416 bool ibss_fixed;
2417
2392 bool ps; 2418 bool ps;
2393 int ps_timeout; 2419 int ps_timeout;
2394 2420
@@ -3463,7 +3489,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
3463 * 3489 *
3464 * return 0 if MCS index >= 32 3490 * return 0 if MCS index >= 32
3465 */ 3491 */
3466u16 cfg80211_calculate_bitrate(struct rate_info *rate); 3492u32 cfg80211_calculate_bitrate(struct rate_info *rate);
3467 3493
3468/* Logging, debugging and troubleshooting/diagnostic helpers. */ 3494/* Logging, debugging and troubleshooting/diagnostic helpers. */
3469 3495
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 670a58ba8a41..e3fa90ce9ecb 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -475,7 +475,7 @@ enum mac80211_rate_control_flags {
475#define IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE 24 475#define IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE 24
476 476
477/* maximum number of rate stages */ 477/* maximum number of rate stages */
478#define IEEE80211_TX_MAX_RATES 5 478#define IEEE80211_TX_MAX_RATES 4
479 479
480/** 480/**
481 * struct ieee80211_tx_rate - rate selection/status 481 * struct ieee80211_tx_rate - rate selection/status
@@ -563,11 +563,11 @@ struct ieee80211_tx_info {
563 } control; 563 } control;
564 struct { 564 struct {
565 struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES]; 565 struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
566 u8 ampdu_ack_len;
567 int ack_signal; 566 int ack_signal;
567 u8 ampdu_ack_len;
568 u8 ampdu_len; 568 u8 ampdu_len;
569 u8 antenna; 569 u8 antenna;
570 /* 14 bytes free */ 570 /* 21 bytes free */
571 } status; 571 } status;
572 struct { 572 struct {
573 struct ieee80211_tx_rate driver_rates[ 573 struct ieee80211_tx_rate driver_rates[
@@ -634,7 +634,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
634 info->status.rates[i].count = 0; 634 info->status.rates[i].count = 0;
635 635
636 BUILD_BUG_ON( 636 BUILD_BUG_ON(
637 offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23); 637 offsetof(struct ieee80211_tx_info, status.ack_signal) != 20);
638 memset(&info->status.ampdu_ack_len, 0, 638 memset(&info->status.ampdu_ack_len, 0,
639 sizeof(struct ieee80211_tx_info) - 639 sizeof(struct ieee80211_tx_info) -
640 offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); 640 offsetof(struct ieee80211_tx_info, status.ampdu_ack_len));
@@ -1896,19 +1896,6 @@ enum ieee80211_rate_control_changed {
1896 * The low-level driver should send the frame out based on 1896 * The low-level driver should send the frame out based on
1897 * configuration in the TX control data. This handler should, 1897 * configuration in the TX control data. This handler should,
1898 * preferably, never fail and stop queues appropriately. 1898 * preferably, never fail and stop queues appropriately.
1899 * This must be implemented if @tx_frags is not.
1900 * Must be atomic.
1901 *
1902 * @tx_frags: Called to transmit multiple fragments of a single MSDU.
1903 * This handler must consume all fragments, sending out some of
1904 * them only is useless and it can't ask for some of them to be
1905 * queued again. If the frame is not fragmented the queue has a
1906 * single SKB only. To avoid issues with the networking stack
1907 * when TX status is reported the frames should be removed from
1908 * the skb queue.
1909 * If this is used, the tx_info @vif and @sta pointers will be
1910 * invalid -- you must not use them in that case.
1911 * This must be implemented if @tx isn't.
1912 * Must be atomic. 1899 * Must be atomic.
1913 * 1900 *
1914 * @start: Called before the first netdevice attached to the hardware 1901 * @start: Called before the first netdevice attached to the hardware
@@ -2257,11 +2244,21 @@ enum ieee80211_rate_control_changed {
2257 * @get_rssi: Get current signal strength in dBm, the function is optional 2244 * @get_rssi: Get current signal strength in dBm, the function is optional
2258 * and can sleep. 2245 * and can sleep.
2259 * 2246 *
2247 * @mgd_prepare_tx: Prepare for transmitting a management frame for association
2248 * before associated. In multi-channel scenarios, a virtual interface is
2249 * bound to a channel before it is associated, but as it isn't associated
2250 * yet it need not necessarily be given airtime, in particular since any
2251 * transmission to a P2P GO needs to be synchronized against the GO's
2252 * powersave state. mac80211 will call this function before transmitting a
2253 * management frame prior to having successfully associated to allow the
2254 * driver to give it channel time for the transmission, to get a response
2255 * and to be able to synchronize with the GO.
2256 * The callback will be called before each transmission and upon return
2257 * mac80211 will transmit the frame right away.
2258 * The callback is optional and can (should!) sleep.
2260 */ 2259 */
2261struct ieee80211_ops { 2260struct ieee80211_ops {
2262 void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); 2261 void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
2263 void (*tx_frags)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2264 struct ieee80211_sta *sta, struct sk_buff_head *skbs);
2265 int (*start)(struct ieee80211_hw *hw); 2262 int (*start)(struct ieee80211_hw *hw);
2266 void (*stop)(struct ieee80211_hw *hw); 2263 void (*stop)(struct ieee80211_hw *hw);
2267#ifdef CONFIG_PM 2264#ifdef CONFIG_PM
@@ -2398,6 +2395,9 @@ struct ieee80211_ops {
2398 u32 sset, u8 *data); 2395 u32 sset, u8 *data);
2399 int (*get_rssi)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 2396 int (*get_rssi)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2400 struct ieee80211_sta *sta, s8 *rssi_dbm); 2397 struct ieee80211_sta *sta, s8 *rssi_dbm);
2398
2399 void (*mgd_prepare_tx)(struct ieee80211_hw *hw,
2400 struct ieee80211_vif *vif);
2401}; 2401};
2402 2402
2403/** 2403/**
@@ -3832,12 +3832,6 @@ void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
3832 3832
3833void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif); 3833void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif);
3834 3834
3835int ieee80211_add_srates_ie(struct ieee80211_vif *vif,
3836 struct sk_buff *skb, bool need_basic);
3837
3838int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif,
3839 struct sk_buff *skb, bool need_basic);
3840
3841/** 3835/**
3842 * ieee80211_ave_rssi - report the average rssi for the specified interface 3836 * ieee80211_ave_rssi - report the average rssi for the specified interface
3843 * 3837 *
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
index e30e6a869714..f5169b04f082 100644
--- a/include/net/nfc/hci.h
+++ b/include/net/nfc/hci.h
@@ -44,10 +44,20 @@ struct nfc_hci_ops {
44 struct nfc_target *target); 44 struct nfc_target *target);
45}; 45};
46 46
47#define NFC_HCI_MAX_CUSTOM_GATES 15 47/* Pipes */
48#define NFC_HCI_INVALID_PIPE 0x80
49#define NFC_HCI_LINK_MGMT_PIPE 0x00
50#define NFC_HCI_ADMIN_PIPE 0x01
51
52struct nfc_hci_gate {
53 u8 gate;
54 u8 pipe;
55};
56
57#define NFC_HCI_MAX_CUSTOM_GATES 50
48struct nfc_hci_init_data { 58struct nfc_hci_init_data {
49 u8 gate_count; 59 u8 gate_count;
50 u8 gates[NFC_HCI_MAX_CUSTOM_GATES]; 60 struct nfc_hci_gate gates[NFC_HCI_MAX_CUSTOM_GATES];
51 char session_id[9]; 61 char session_id[9];
52}; 62};
53 63
@@ -112,6 +122,8 @@ void nfc_hci_unregister_device(struct nfc_hci_dev *hdev);
112void nfc_hci_set_clientdata(struct nfc_hci_dev *hdev, void *clientdata); 122void nfc_hci_set_clientdata(struct nfc_hci_dev *hdev, void *clientdata);
113void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev); 123void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev);
114 124
125void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err);
126
115/* Host IDs */ 127/* Host IDs */
116#define NFC_HCI_HOST_CONTROLLER_ID 0x00 128#define NFC_HCI_HOST_CONTROLLER_ID 0x00
117#define NFC_HCI_TERMINAL_HOST_ID 0x01 129#define NFC_HCI_TERMINAL_HOST_ID 0x01
@@ -180,7 +192,8 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event,
180void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb); 192void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb);
181 193
182/* connecting to gates and sending hci instructions */ 194/* connecting to gates and sending hci instructions */
183int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate); 195int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate,
196 u8 pipe);
184int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate); 197int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate);
185int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev); 198int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev);
186int nfc_hci_get_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx, 199int nfc_hci_get_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx,
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index 180964b954ab..6431f5e39022 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -204,4 +204,6 @@ int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode,
204int nfc_tm_deactivated(struct nfc_dev *dev); 204int nfc_tm_deactivated(struct nfc_dev *dev);
205int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb); 205int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb);
206 206
207void nfc_driver_failure(struct nfc_dev *dev, int err);
208
207#endif /* __NET_NFC_H */ 209#endif /* __NET_NFC_H */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index c2a2dcbfdf01..ccbe2413142a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2668,8 +2668,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
2668 tf->u.setup_req.capability = 2668 tf->u.setup_req.capability =
2669 cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); 2669 cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
2670 2670
2671 ieee80211_add_srates_ie(&sdata->vif, skb, false); 2671 ieee80211_add_srates_ie(sdata, skb, false);
2672 ieee80211_add_ext_srates_ie(&sdata->vif, skb, false); 2672 ieee80211_add_ext_srates_ie(sdata, skb, false);
2673 ieee80211_tdls_add_ext_capab(skb); 2673 ieee80211_tdls_add_ext_capab(skb);
2674 break; 2674 break;
2675 case WLAN_TDLS_SETUP_RESPONSE: 2675 case WLAN_TDLS_SETUP_RESPONSE:
@@ -2682,8 +2682,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
2682 tf->u.setup_resp.capability = 2682 tf->u.setup_resp.capability =
2683 cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); 2683 cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
2684 2684
2685 ieee80211_add_srates_ie(&sdata->vif, skb, false); 2685 ieee80211_add_srates_ie(sdata, skb, false);
2686 ieee80211_add_ext_srates_ie(&sdata->vif, skb, false); 2686 ieee80211_add_ext_srates_ie(sdata, skb, false);
2687 ieee80211_tdls_add_ext_capab(skb); 2687 ieee80211_tdls_add_ext_capab(skb);
2688 break; 2688 break;
2689 case WLAN_TDLS_SETUP_CONFIRM: 2689 case WLAN_TDLS_SETUP_CONFIRM:
@@ -2743,8 +2743,8 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
2743 mgmt->u.action.u.tdls_discover_resp.capability = 2743 mgmt->u.action.u.tdls_discover_resp.capability =
2744 cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); 2744 cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
2745 2745
2746 ieee80211_add_srates_ie(&sdata->vif, skb, false); 2746 ieee80211_add_srates_ie(sdata, skb, false);
2747 ieee80211_add_ext_srates_ie(&sdata->vif, skb, false); 2747 ieee80211_add_ext_srates_ie(sdata, skb, false);
2748 ieee80211_tdls_add_ext_capab(skb); 2748 ieee80211_tdls_add_ext_capab(skb);
2749 break; 2749 break;
2750 default: 2750 default:
@@ -2980,14 +2980,14 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
2980 return 0; 2980 return 0;
2981} 2981}
2982 2982
2983static struct ieee80211_channel * 2983static void ieee80211_set_monitor_enabled(struct wiphy *wiphy, bool enabled)
2984ieee80211_wiphy_get_channel(struct wiphy *wiphy,
2985 enum nl80211_channel_type *type)
2986{ 2984{
2987 struct ieee80211_local *local = wiphy_priv(wiphy); 2985 struct ieee80211_local *local = wiphy_priv(wiphy);
2988 2986
2989 *type = local->_oper_channel_type; 2987 if (enabled)
2990 return local->oper_channel; 2988 WARN_ON(ieee80211_add_virtual_monitor(local));
2989 else
2990 ieee80211_del_virtual_monitor(local);
2991} 2991}
2992 2992
2993#ifdef CONFIG_PM 2993#ifdef CONFIG_PM
@@ -3063,8 +3063,8 @@ struct cfg80211_ops mac80211_config_ops = {
3063 .tdls_oper = ieee80211_tdls_oper, 3063 .tdls_oper = ieee80211_tdls_oper,
3064 .tdls_mgmt = ieee80211_tdls_mgmt, 3064 .tdls_mgmt = ieee80211_tdls_mgmt,
3065 .probe_client = ieee80211_probe_client, 3065 .probe_client = ieee80211_probe_client,
3066 .get_channel = ieee80211_wiphy_get_channel,
3067 .set_noack_map = ieee80211_set_noack_map, 3066 .set_noack_map = ieee80211_set_noack_map,
3067 .set_monitor_enabled = ieee80211_set_monitor_enabled,
3068#ifdef CONFIG_PM 3068#ifdef CONFIG_PM
3069 .set_wakeup = ieee80211_set_wakeup, 3069 .set_wakeup = ieee80211_set_wakeup,
3070#endif 3070#endif
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 7932767bb482..090d08ff22c4 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -283,6 +283,11 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
283 283
284 lockdep_assert_held(&sdata->local->key_mtx); 284 lockdep_assert_held(&sdata->local->key_mtx);
285 285
286 if (sdata->debugfs.default_unicast_key) {
287 debugfs_remove(sdata->debugfs.default_unicast_key);
288 sdata->debugfs.default_unicast_key = NULL;
289 }
290
286 if (sdata->default_unicast_key) { 291 if (sdata->default_unicast_key) {
287 key = key_mtx_dereference(sdata->local, 292 key = key_mtx_dereference(sdata->local,
288 sdata->default_unicast_key); 293 sdata->default_unicast_key);
@@ -290,9 +295,11 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
290 sdata->debugfs.default_unicast_key = 295 sdata->debugfs.default_unicast_key =
291 debugfs_create_symlink("default_unicast_key", 296 debugfs_create_symlink("default_unicast_key",
292 sdata->debugfs.dir, buf); 297 sdata->debugfs.dir, buf);
293 } else { 298 }
294 debugfs_remove(sdata->debugfs.default_unicast_key); 299
295 sdata->debugfs.default_unicast_key = NULL; 300 if (sdata->debugfs.default_multicast_key) {
301 debugfs_remove(sdata->debugfs.default_multicast_key);
302 sdata->debugfs.default_multicast_key = NULL;
296 } 303 }
297 304
298 if (sdata->default_multicast_key) { 305 if (sdata->default_multicast_key) {
@@ -302,9 +309,6 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
302 sdata->debugfs.default_multicast_key = 309 sdata->debugfs.default_multicast_key =
303 debugfs_create_symlink("default_multicast_key", 310 debugfs_create_symlink("default_multicast_key",
304 sdata->debugfs.dir, buf); 311 sdata->debugfs.dir, buf);
305 } else {
306 debugfs_remove(sdata->debugfs.default_multicast_key);
307 sdata->debugfs.default_multicast_key = NULL;
308 } 312 }
309} 313}
310 314
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 44e8c1242781..df9203199102 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -27,14 +27,6 @@ static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb)
27 local->ops->tx(&local->hw, skb); 27 local->ops->tx(&local->hw, skb);
28} 28}
29 29
30static inline void drv_tx_frags(struct ieee80211_local *local,
31 struct ieee80211_vif *vif,
32 struct ieee80211_sta *sta,
33 struct sk_buff_head *skbs)
34{
35 local->ops->tx_frags(&local->hw, vif, sta, skbs);
36}
37
38static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata, 30static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata,
39 u32 sset, u8 *data) 31 u32 sset, u8 *data)
40{ 32{
@@ -860,4 +852,18 @@ static inline int drv_get_rssi(struct ieee80211_local *local,
860 852
861 return ret; 853 return ret;
862} 854}
855
856static inline void drv_mgd_prepare_tx(struct ieee80211_local *local,
857 struct ieee80211_sub_if_data *sdata)
858{
859 might_sleep();
860
861 check_sdata_in_driver(sdata);
862 WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION);
863
864 trace_drv_mgd_prepare_tx(local, sdata);
865 if (local->ops->mgd_prepare_tx)
866 local->ops->mgd_prepare_tx(&local->hw, &sdata->vif);
867 trace_drv_return_void(local);
868}
863#endif /* __MAC80211_DRIVER_OPS */ 869#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f834a005e1c5..e0423f8c0ce1 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1284,7 +1284,6 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
1284 enum nl80211_iftype type); 1284 enum nl80211_iftype type);
1285void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); 1285void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata);
1286void ieee80211_remove_interfaces(struct ieee80211_local *local); 1286void ieee80211_remove_interfaces(struct ieee80211_local *local);
1287u32 __ieee80211_recalc_idle(struct ieee80211_local *local);
1288void ieee80211_recalc_idle(struct ieee80211_local *local); 1287void ieee80211_recalc_idle(struct ieee80211_local *local);
1289void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, 1288void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
1290 const int offset); 1289 const int offset);
@@ -1481,6 +1480,16 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1481 struct ieee80211_channel *channel, 1480 struct ieee80211_channel *channel,
1482 enum nl80211_channel_type channel_type, 1481 enum nl80211_channel_type channel_type,
1483 u16 prot_mode); 1482 u16 prot_mode);
1483u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
1484 u32 cap);
1485int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
1486 struct sk_buff *skb, bool need_basic);
1487int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
1488 struct sk_buff *skb, bool need_basic);
1489
1490/* virtual monitor */
1491int ieee80211_add_virtual_monitor(struct ieee80211_local *local);
1492void ieee80211_del_virtual_monitor(struct ieee80211_local *local);
1484 1493
1485/* channel management */ 1494/* channel management */
1486enum ieee80211_chan_mode { 1495enum ieee80211_chan_mode {
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 58c2ab3d483a..fbef7a1ada7a 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -43,6 +43,127 @@
43 */ 43 */
44 44
45 45
46static u32 ieee80211_idle_off(struct ieee80211_local *local,
47 const char *reason)
48{
49 if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
50 return 0;
51
52 local->hw.conf.flags &= ~IEEE80211_CONF_IDLE;
53 return IEEE80211_CONF_CHANGE_IDLE;
54}
55
56static u32 ieee80211_idle_on(struct ieee80211_local *local)
57{
58 if (local->hw.conf.flags & IEEE80211_CONF_IDLE)
59 return 0;
60
61 drv_flush(local, false);
62
63 local->hw.conf.flags |= IEEE80211_CONF_IDLE;
64 return IEEE80211_CONF_CHANGE_IDLE;
65}
66
67static u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
68{
69 struct ieee80211_sub_if_data *sdata;
70 int count = 0;
71 bool working = false, scanning = false;
72 unsigned int led_trig_start = 0, led_trig_stop = 0;
73 struct ieee80211_roc_work *roc;
74
75#ifdef CONFIG_PROVE_LOCKING
76 WARN_ON(debug_locks && !lockdep_rtnl_is_held() &&
77 !lockdep_is_held(&local->iflist_mtx));
78#endif
79 lockdep_assert_held(&local->mtx);
80
81 list_for_each_entry(sdata, &local->interfaces, list) {
82 if (!ieee80211_sdata_running(sdata)) {
83 sdata->vif.bss_conf.idle = true;
84 continue;
85 }
86
87 sdata->old_idle = sdata->vif.bss_conf.idle;
88
89 /* do not count disabled managed interfaces */
90 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
91 !sdata->u.mgd.associated &&
92 !sdata->u.mgd.auth_data &&
93 !sdata->u.mgd.assoc_data) {
94 sdata->vif.bss_conf.idle = true;
95 continue;
96 }
97 /* do not count unused IBSS interfaces */
98 if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
99 !sdata->u.ibss.ssid_len) {
100 sdata->vif.bss_conf.idle = true;
101 continue;
102 }
103 /* count everything else */
104 sdata->vif.bss_conf.idle = false;
105 count++;
106 }
107
108 if (!local->ops->remain_on_channel) {
109 list_for_each_entry(roc, &local->roc_list, list) {
110 working = true;
111 roc->sdata->vif.bss_conf.idle = false;
112 }
113 }
114
115 if (local->scan_sdata &&
116 !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) {
117 scanning = true;
118 local->scan_sdata->vif.bss_conf.idle = false;
119 }
120
121 list_for_each_entry(sdata, &local->interfaces, list) {
122 if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
123 sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
124 continue;
125 if (sdata->old_idle == sdata->vif.bss_conf.idle)
126 continue;
127 if (!ieee80211_sdata_running(sdata))
128 continue;
129 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
130 }
131
132 if (working || scanning)
133 led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK;
134 else
135 led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK;
136
137 if (count)
138 led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
139 else
140 led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
141
142 ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop);
143
144 if (working)
145 return ieee80211_idle_off(local, "working");
146 if (scanning)
147 return ieee80211_idle_off(local, "scanning");
148 if (!count)
149 return ieee80211_idle_on(local);
150 else
151 return ieee80211_idle_off(local, "in use");
152
153 return 0;
154}
155
156void ieee80211_recalc_idle(struct ieee80211_local *local)
157{
158 u32 chg;
159
160 mutex_lock(&local->iflist_mtx);
161 chg = __ieee80211_recalc_idle(local);
162 mutex_unlock(&local->iflist_mtx);
163 if (chg)
164 ieee80211_hw_config(local, chg);
165}
166
46static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) 167static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
47{ 168{
48 int meshhdrlen; 169 int meshhdrlen;
@@ -209,7 +330,7 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
209 sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; 330 sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
210} 331}
211 332
212static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) 333int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
213{ 334{
214 struct ieee80211_sub_if_data *sdata; 335 struct ieee80211_sub_if_data *sdata;
215 int ret; 336 int ret;
@@ -250,7 +371,7 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
250 return 0; 371 return 0;
251} 372}
252 373
253static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) 374void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
254{ 375{
255 struct ieee80211_sub_if_data *sdata; 376 struct ieee80211_sub_if_data *sdata;
256 377
@@ -366,12 +487,6 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
366 break; 487 break;
367 } 488 }
368 489
369 if (local->monitors == 0 && local->open_count == 0) {
370 res = ieee80211_add_virtual_monitor(local);
371 if (res)
372 goto err_stop;
373 }
374
375 /* must be before the call to ieee80211_configure_filter */ 490 /* must be before the call to ieee80211_configure_filter */
376 local->monitors++; 491 local->monitors++;
377 if (local->monitors == 1) { 492 if (local->monitors == 1) {
@@ -386,8 +501,6 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
386 break; 501 break;
387 default: 502 default:
388 if (coming_up) { 503 if (coming_up) {
389 ieee80211_del_virtual_monitor(local);
390
391 res = drv_add_interface(local, sdata); 504 res = drv_add_interface(local, sdata);
392 if (res) 505 if (res)
393 goto err_stop; 506 goto err_stop;
@@ -622,7 +735,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
622 if (local->monitors == 0) { 735 if (local->monitors == 0) {
623 local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; 736 local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR;
624 hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; 737 hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
625 ieee80211_del_virtual_monitor(local);
626 } 738 }
627 739
628 ieee80211_adjust_monitor_flags(sdata, -1); 740 ieee80211_adjust_monitor_flags(sdata, -1);
@@ -696,9 +808,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
696 } 808 }
697 } 809 }
698 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 810 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
699
700 if (local->monitors == local->open_count && local->monitors > 0)
701 ieee80211_add_virtual_monitor(local);
702} 811}
703 812
704static int ieee80211_stop(struct net_device *dev) 813static int ieee80211_stop(struct net_device *dev)
@@ -1403,127 +1512,6 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
1403 list_del(&unreg_list); 1512 list_del(&unreg_list);
1404} 1513}
1405 1514
1406static u32 ieee80211_idle_off(struct ieee80211_local *local,
1407 const char *reason)
1408{
1409 if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
1410 return 0;
1411
1412 local->hw.conf.flags &= ~IEEE80211_CONF_IDLE;
1413 return IEEE80211_CONF_CHANGE_IDLE;
1414}
1415
1416static u32 ieee80211_idle_on(struct ieee80211_local *local)
1417{
1418 if (local->hw.conf.flags & IEEE80211_CONF_IDLE)
1419 return 0;
1420
1421 drv_flush(local, false);
1422
1423 local->hw.conf.flags |= IEEE80211_CONF_IDLE;
1424 return IEEE80211_CONF_CHANGE_IDLE;
1425}
1426
1427u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
1428{
1429 struct ieee80211_sub_if_data *sdata;
1430 int count = 0;
1431 bool working = false, scanning = false;
1432 unsigned int led_trig_start = 0, led_trig_stop = 0;
1433 struct ieee80211_roc_work *roc;
1434
1435#ifdef CONFIG_PROVE_LOCKING
1436 WARN_ON(debug_locks && !lockdep_rtnl_is_held() &&
1437 !lockdep_is_held(&local->iflist_mtx));
1438#endif
1439 lockdep_assert_held(&local->mtx);
1440
1441 list_for_each_entry(sdata, &local->interfaces, list) {
1442 if (!ieee80211_sdata_running(sdata)) {
1443 sdata->vif.bss_conf.idle = true;
1444 continue;
1445 }
1446
1447 sdata->old_idle = sdata->vif.bss_conf.idle;
1448
1449 /* do not count disabled managed interfaces */
1450 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
1451 !sdata->u.mgd.associated &&
1452 !sdata->u.mgd.auth_data &&
1453 !sdata->u.mgd.assoc_data) {
1454 sdata->vif.bss_conf.idle = true;
1455 continue;
1456 }
1457 /* do not count unused IBSS interfaces */
1458 if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
1459 !sdata->u.ibss.ssid_len) {
1460 sdata->vif.bss_conf.idle = true;
1461 continue;
1462 }
1463 /* count everything else */
1464 sdata->vif.bss_conf.idle = false;
1465 count++;
1466 }
1467
1468 if (!local->ops->remain_on_channel) {
1469 list_for_each_entry(roc, &local->roc_list, list) {
1470 working = true;
1471 roc->sdata->vif.bss_conf.idle = false;
1472 }
1473 }
1474
1475 if (local->scan_sdata &&
1476 !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) {
1477 scanning = true;
1478 local->scan_sdata->vif.bss_conf.idle = false;
1479 }
1480
1481 list_for_each_entry(sdata, &local->interfaces, list) {
1482 if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
1483 sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1484 continue;
1485 if (sdata->old_idle == sdata->vif.bss_conf.idle)
1486 continue;
1487 if (!ieee80211_sdata_running(sdata))
1488 continue;
1489 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
1490 }
1491
1492 if (working || scanning)
1493 led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK;
1494 else
1495 led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK;
1496
1497 if (count)
1498 led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
1499 else
1500 led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
1501
1502 ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop);
1503
1504 if (working)
1505 return ieee80211_idle_off(local, "working");
1506 if (scanning)
1507 return ieee80211_idle_off(local, "scanning");
1508 if (!count)
1509 return ieee80211_idle_on(local);
1510 else
1511 return ieee80211_idle_off(local, "in use");
1512
1513 return 0;
1514}
1515
1516void ieee80211_recalc_idle(struct ieee80211_local *local)
1517{
1518 u32 chg;
1519
1520 mutex_lock(&local->iflist_mtx);
1521 chg = __ieee80211_recalc_idle(local);
1522 mutex_unlock(&local->iflist_mtx);
1523 if (chg)
1524 ieee80211_hw_config(local, chg);
1525}
1526
1527static int netdev_notify(struct notifier_block *nb, 1515static int netdev_notify(struct notifier_block *nb,
1528 unsigned long state, 1516 unsigned long state,
1529 void *ndev) 1517 void *ndev)
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 0b040fb73673..c794101f8987 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -587,7 +587,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
587 587
588 local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); 588 local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN);
589 589
590 BUG_ON(!ops->tx && !ops->tx_frags); 590 BUG_ON(!ops->tx);
591 BUG_ON(!ops->start); 591 BUG_ON(!ops->start);
592 BUG_ON(!ops->stop); 592 BUG_ON(!ops->stop);
593 BUG_ON(!ops->config); 593 BUG_ON(!ops->config);
@@ -688,7 +688,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
688 int result, i; 688 int result, i;
689 enum ieee80211_band band; 689 enum ieee80211_band band;
690 int channels, max_bitrates; 690 int channels, max_bitrates;
691 bool supp_ht; 691 bool supp_ht, supp_vht;
692 netdev_features_t feature_whitelist; 692 netdev_features_t feature_whitelist;
693 static const u32 cipher_suites[] = { 693 static const u32 cipher_suites[] = {
694 /* keep WEP first, it may be removed below */ 694 /* keep WEP first, it may be removed below */
@@ -706,12 +706,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
706 local->hw.offchannel_tx_hw_queue >= local->hw.queues)) 706 local->hw.offchannel_tx_hw_queue >= local->hw.queues))
707 return -EINVAL; 707 return -EINVAL;
708 708
709 if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns)
710#ifdef CONFIG_PM 709#ifdef CONFIG_PM
711 && (!local->ops->suspend || !local->ops->resume) 710 if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) &&
712#endif 711 (!local->ops->suspend || !local->ops->resume))
713 )
714 return -EINVAL; 712 return -EINVAL;
713#endif
715 714
716 if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan) 715 if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan)
717 return -EINVAL; 716 return -EINVAL;
@@ -733,6 +732,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
733 channels = 0; 732 channels = 0;
734 max_bitrates = 0; 733 max_bitrates = 0;
735 supp_ht = false; 734 supp_ht = false;
735 supp_vht = false;
736 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 736 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
737 struct ieee80211_supported_band *sband; 737 struct ieee80211_supported_band *sband;
738 738
@@ -750,6 +750,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
750 if (max_bitrates < sband->n_bitrates) 750 if (max_bitrates < sband->n_bitrates)
751 max_bitrates = sband->n_bitrates; 751 max_bitrates = sband->n_bitrates;
752 supp_ht = supp_ht || sband->ht_cap.ht_supported; 752 supp_ht = supp_ht || sband->ht_cap.ht_supported;
753 supp_vht = supp_vht || sband->vht_cap.vht_supported;
753 } 754 }
754 755
755 local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) + 756 local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
@@ -825,6 +826,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
825 if (supp_ht) 826 if (supp_ht)
826 local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); 827 local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap);
827 828
829 if (supp_vht)
830 local->scan_ies_len +=
831 2 + sizeof(struct ieee80211_vht_capabilities);
832
828 if (!local->ops->hw_scan) { 833 if (!local->ops->hw_scan) {
829 /* For hw_scan, driver needs to set these up. */ 834 /* For hw_scan, driver needs to set these up. */
830 local->hw.wiphy->max_scan_ssids = 4; 835 local->hw.wiphy->max_scan_ssids = 4;
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 9ad74dd87a7b..af671b984df3 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -258,8 +258,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
258 pos = skb_put(skb, 2); 258 pos = skb_put(skb, 2);
259 memcpy(pos + 2, &plid, 2); 259 memcpy(pos + 2, &plid, 2);
260 } 260 }
261 if (ieee80211_add_srates_ie(&sdata->vif, skb, true) || 261 if (ieee80211_add_srates_ie(sdata, skb, true) ||
262 ieee80211_add_ext_srates_ie(&sdata->vif, skb, true) || 262 ieee80211_add_ext_srates_ie(sdata, skb, true) ||
263 mesh_add_rsn_ie(skb, sdata) || 263 mesh_add_rsn_ie(skb, sdata) ||
264 mesh_add_meshid_ie(skb, sdata) || 264 mesh_add_meshid_ie(skb, sdata) ||
265 mesh_add_meshconf_ie(skb, sdata)) 265 mesh_add_meshconf_ie(skb, sdata))
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index aa69a331f374..f49f14f8ba82 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -541,6 +541,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
541 memcpy(pos, assoc_data->ie + offset, noffset - offset); 541 memcpy(pos, assoc_data->ie + offset, noffset - offset);
542 } 542 }
543 543
544 drv_mgd_prepare_tx(local, sdata);
545
544 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 546 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
545 ieee80211_tx_skb(sdata, skb); 547 ieee80211_tx_skb(sdata, skb);
546} 548}
@@ -580,6 +582,9 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
580 if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) 582 if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED))
581 IEEE80211_SKB_CB(skb)->flags |= 583 IEEE80211_SKB_CB(skb)->flags |=
582 IEEE80211_TX_INTFL_DONT_ENCRYPT; 584 IEEE80211_TX_INTFL_DONT_ENCRYPT;
585
586 drv_mgd_prepare_tx(local, sdata);
587
583 ieee80211_tx_skb(sdata, skb); 588 ieee80211_tx_skb(sdata, skb);
584 } 589 }
585} 590}
@@ -902,9 +907,6 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata)
902 if (!mgd->associated) 907 if (!mgd->associated)
903 return false; 908 return false;
904 909
905 if (!mgd->associated->beacon_ies)
906 return false;
907
908 if (mgd->flags & (IEEE80211_STA_BEACON_POLL | 910 if (mgd->flags & (IEEE80211_STA_BEACON_POLL |
909 IEEE80211_STA_CONNECTION_POLL)) 911 IEEE80211_STA_CONNECTION_POLL))
910 return false; 912 return false;
@@ -1362,6 +1364,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1362 } 1364 }
1363 mutex_unlock(&local->sta_mtx); 1365 mutex_unlock(&local->sta_mtx);
1364 1366
1367 /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */
1368 if (tx)
1369 drv_flush(local, false);
1370
1365 /* deauthenticate/disassociate now */ 1371 /* deauthenticate/disassociate now */
1366 if (tx || frame_buf) 1372 if (tx || frame_buf)
1367 ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype, 1373 ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype,
@@ -1610,6 +1616,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
1610{ 1616{
1611 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 1617 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
1612 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1618 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1619 struct cfg80211_bss *cbss;
1613 struct sk_buff *skb; 1620 struct sk_buff *skb;
1614 const u8 *ssid; 1621 const u8 *ssid;
1615 int ssid_len; 1622 int ssid_len;
@@ -1619,16 +1626,22 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
1619 1626
1620 ASSERT_MGD_MTX(ifmgd); 1627 ASSERT_MGD_MTX(ifmgd);
1621 1628
1622 if (!ifmgd->associated) 1629 if (ifmgd->associated)
1630 cbss = ifmgd->associated;
1631 else if (ifmgd->auth_data)
1632 cbss = ifmgd->auth_data->bss;
1633 else if (ifmgd->assoc_data)
1634 cbss = ifmgd->assoc_data->bss;
1635 else
1623 return NULL; 1636 return NULL;
1624 1637
1625 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); 1638 ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID);
1626 if (WARN_ON_ONCE(ssid == NULL)) 1639 if (WARN_ON_ONCE(ssid == NULL))
1627 ssid_len = 0; 1640 ssid_len = 0;
1628 else 1641 else
1629 ssid_len = ssid[1]; 1642 ssid_len = ssid[1];
1630 1643
1631 skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid, 1644 skb = ieee80211_build_probe_req(sdata, cbss->bssid,
1632 (u32) -1, ssid + 2, ssid_len, 1645 (u32) -1, ssid + 2, ssid_len,
1633 NULL, 0, true); 1646 NULL, 0, true);
1634 1647
@@ -1747,6 +1760,7 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
1747 if (!elems.challenge) 1760 if (!elems.challenge)
1748 return; 1761 return;
1749 auth_data->expected_transaction = 4; 1762 auth_data->expected_transaction = 4;
1763 drv_mgd_prepare_tx(sdata->local, sdata);
1750 ieee80211_send_auth(sdata, 3, auth_data->algorithm, 1764 ieee80211_send_auth(sdata, 3, auth_data->algorithm,
1751 elems.challenge - 2, elems.challenge_len + 2, 1765 elems.challenge - 2, elems.challenge_len + 2,
1752 auth_data->bss->bssid, auth_data->bss->bssid, 1766 auth_data->bss->bssid, auth_data->bss->bssid,
@@ -2630,6 +2644,8 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
2630 return -ETIMEDOUT; 2644 return -ETIMEDOUT;
2631 } 2645 }
2632 2646
2647 drv_mgd_prepare_tx(local, sdata);
2648
2633 if (auth_data->bss->proberesp_ies) { 2649 if (auth_data->bss->proberesp_ies) {
2634 sdata_info(sdata, "send auth to %pM (try %d/%d)\n", 2650 sdata_info(sdata, "send auth to %pM (try %d/%d)\n",
2635 auth_data->bss->bssid, auth_data->tries, 2651 auth_data->bss->bssid, auth_data->tries,
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 2e60f4acd027..e1e9d10ec2e7 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -1244,6 +1244,13 @@ TRACE_EVENT(drv_get_rssi,
1244 ) 1244 )
1245); 1245);
1246 1246
1247DEFINE_EVENT(local_sdata_evt, drv_mgd_prepare_tx,
1248 TP_PROTO(struct ieee80211_local *local,
1249 struct ieee80211_sub_if_data *sdata),
1250
1251 TP_ARGS(local, sdata)
1252);
1253
1247/* 1254/*
1248 * Tracing for API calls that drivers call. 1255 * Tracing for API calls that drivers call.
1249 */ 1256 */
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index ec8f53467374..c9d2175d15c1 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -140,6 +140,8 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
140 if (r->flags & IEEE80211_RATE_MANDATORY_A) 140 if (r->flags & IEEE80211_RATE_MANDATORY_A)
141 mrate = r->bitrate; 141 mrate = r->bitrate;
142 break; 142 break;
143 case IEEE80211_BAND_60GHZ:
144 /* TODO, for now fall through */
143 case IEEE80211_NUM_BANDS: 145 case IEEE80211_NUM_BANDS:
144 WARN_ON(1); 146 WARN_ON(1);
145 break; 147 break;
@@ -957,8 +959,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
957 info->control.rates[1].idx = -1; 959 info->control.rates[1].idx = -1;
958 info->control.rates[2].idx = -1; 960 info->control.rates[2].idx = -1;
959 info->control.rates[3].idx = -1; 961 info->control.rates[3].idx = -1;
960 info->control.rates[4].idx = -1; 962 BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 4);
961 BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5);
962 info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; 963 info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE;
963 } else { 964 } else {
964 hdr->frame_control &= ~morefrags; 965 hdr->frame_control &= ~morefrags;
@@ -1293,11 +1294,8 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
1293 break; 1294 break;
1294 } 1295 }
1295 1296
1296 if (local->ops->tx_frags) 1297 result = ieee80211_tx_frags(local, vif, pubsta, skbs,
1297 drv_tx_frags(local, vif, pubsta, skbs); 1298 txpending);
1298 else
1299 result = ieee80211_tx_frags(local, vif, pubsta, skbs,
1300 txpending);
1301 1299
1302 ieee80211_tpt_led_trig_tx(local, fc, led_len); 1300 ieee80211_tpt_led_trig_tx(local, fc, led_len);
1303 ieee80211_led_tx(local, 1); 1301 ieee80211_led_tx(local, 1);
@@ -2420,9 +2418,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2420 *pos++ = WLAN_EID_SSID; 2418 *pos++ = WLAN_EID_SSID;
2421 *pos++ = 0x0; 2419 *pos++ = 0x0;
2422 2420
2423 if (ieee80211_add_srates_ie(&sdata->vif, skb, true) || 2421 if (ieee80211_add_srates_ie(sdata, skb, true) ||
2424 mesh_add_ds_params_ie(skb, sdata) || 2422 mesh_add_ds_params_ie(skb, sdata) ||
2425 ieee80211_add_ext_srates_ie(&sdata->vif, skb, true) || 2423 ieee80211_add_ext_srates_ie(sdata, skb, true) ||
2426 mesh_add_rsn_ie(skb, sdata) || 2424 mesh_add_rsn_ie(skb, sdata) ||
2427 mesh_add_ht_cap_ie(skb, sdata) || 2425 mesh_add_ht_cap_ie(skb, sdata) ||
2428 mesh_add_ht_oper_ie(skb, sdata) || 2426 mesh_add_ht_oper_ie(skb, sdata) ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 242ecde381f6..64493a7bef1a 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -268,6 +268,10 @@ EXPORT_SYMBOL(ieee80211_ctstoself_duration);
268void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) 268void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
269{ 269{
270 struct ieee80211_sub_if_data *sdata; 270 struct ieee80211_sub_if_data *sdata;
271 int n_acs = IEEE80211_NUM_ACS;
272
273 if (local->hw.queues < IEEE80211_NUM_ACS)
274 n_acs = 1;
271 275
272 list_for_each_entry_rcu(sdata, &local->interfaces, list) { 276 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
273 int ac; 277 int ac;
@@ -279,7 +283,7 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
279 local->queue_stop_reasons[sdata->vif.cab_queue] != 0) 283 local->queue_stop_reasons[sdata->vif.cab_queue] != 0)
280 continue; 284 continue;
281 285
282 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { 286 for (ac = 0; ac < n_acs; ac++) {
283 int ac_queue = sdata->vif.hw_queue[ac]; 287 int ac_queue = sdata->vif.hw_queue[ac];
284 288
285 if (ac_queue == queue || 289 if (ac_queue == queue ||
@@ -341,6 +345,7 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
341{ 345{
342 struct ieee80211_local *local = hw_to_local(hw); 346 struct ieee80211_local *local = hw_to_local(hw);
343 struct ieee80211_sub_if_data *sdata; 347 struct ieee80211_sub_if_data *sdata;
348 int n_acs = IEEE80211_NUM_ACS;
344 349
345 trace_stop_queue(local, queue, reason); 350 trace_stop_queue(local, queue, reason);
346 351
@@ -352,11 +357,14 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
352 357
353 __set_bit(reason, &local->queue_stop_reasons[queue]); 358 __set_bit(reason, &local->queue_stop_reasons[queue]);
354 359
360 if (local->hw.queues < IEEE80211_NUM_ACS)
361 n_acs = 1;
362
355 rcu_read_lock(); 363 rcu_read_lock();
356 list_for_each_entry_rcu(sdata, &local->interfaces, list) { 364 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
357 int ac; 365 int ac;
358 366
359 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { 367 for (ac = 0; ac < n_acs; ac++) {
360 if (sdata->vif.hw_queue[ac] == queue || 368 if (sdata->vif.hw_queue[ac] == queue ||
361 sdata->vif.cab_queue == queue) 369 sdata->vif.cab_queue == queue)
362 netif_stop_subqueue(sdata->dev, ac); 370 netif_stop_subqueue(sdata->dev, ac);
@@ -1072,6 +1080,10 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1072 pos += noffset - offset; 1080 pos += noffset - offset;
1073 } 1081 }
1074 1082
1083 if (sband->vht_cap.vht_supported)
1084 pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap,
1085 sband->vht_cap.cap);
1086
1075 return pos - buffer; 1087 return pos - buffer;
1076} 1088}
1077 1089
@@ -1411,10 +1423,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1411 if (ieee80211_sdata_running(sdata)) 1423 if (ieee80211_sdata_running(sdata))
1412 ieee80211_enable_keys(sdata); 1424 ieee80211_enable_keys(sdata);
1413 1425
1426 wake_up:
1414 local->in_reconfig = false; 1427 local->in_reconfig = false;
1415 barrier(); 1428 barrier();
1416 1429
1417 wake_up:
1418 /* 1430 /*
1419 * Clear the WLAN_STA_BLOCK_BA flag so new aggregation 1431 * Clear the WLAN_STA_BLOCK_BA flag so new aggregation
1420 * sessions can be established after a resume. 1432 * sessions can be established after a resume.
@@ -1699,6 +1711,27 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1699 return pos; 1711 return pos;
1700} 1712}
1701 1713
1714u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
1715 u32 cap)
1716{
1717 __le32 tmp;
1718
1719 *pos++ = WLAN_EID_VHT_CAPABILITY;
1720 *pos++ = sizeof(struct ieee80211_vht_capabilities);
1721 memset(pos, 0, sizeof(struct ieee80211_vht_capabilities));
1722
1723 /* capability flags */
1724 tmp = cpu_to_le32(cap);
1725 memcpy(pos, &tmp, sizeof(u32));
1726 pos += sizeof(u32);
1727
1728 /* VHT MCS set */
1729 memcpy(pos, &vht_cap->vht_mcs, sizeof(vht_cap->vht_mcs));
1730 pos += sizeof(vht_cap->vht_mcs);
1731
1732 return pos;
1733}
1734
1702u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, 1735u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1703 struct ieee80211_channel *channel, 1736 struct ieee80211_channel *channel,
1704 enum nl80211_channel_type channel_type, 1737 enum nl80211_channel_type channel_type,
@@ -1764,15 +1797,14 @@ ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper)
1764 return channel_type; 1797 return channel_type;
1765} 1798}
1766 1799
1767int ieee80211_add_srates_ie(struct ieee80211_vif *vif, 1800int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
1768 struct sk_buff *skb, bool need_basic) 1801 struct sk_buff *skb, bool need_basic)
1769{ 1802{
1770 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
1771 struct ieee80211_local *local = sdata->local; 1803 struct ieee80211_local *local = sdata->local;
1772 struct ieee80211_supported_band *sband; 1804 struct ieee80211_supported_band *sband;
1773 int rate; 1805 int rate;
1774 u8 i, rates, *pos; 1806 u8 i, rates, *pos;
1775 u32 basic_rates = vif->bss_conf.basic_rates; 1807 u32 basic_rates = sdata->vif.bss_conf.basic_rates;
1776 1808
1777 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 1809 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1778 rates = sband->n_bitrates; 1810 rates = sband->n_bitrates;
@@ -1796,15 +1828,14 @@ int ieee80211_add_srates_ie(struct ieee80211_vif *vif,
1796 return 0; 1828 return 0;
1797} 1829}
1798 1830
1799int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, 1831int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
1800 struct sk_buff *skb, bool need_basic) 1832 struct sk_buff *skb, bool need_basic)
1801{ 1833{
1802 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
1803 struct ieee80211_local *local = sdata->local; 1834 struct ieee80211_local *local = sdata->local;
1804 struct ieee80211_supported_band *sband; 1835 struct ieee80211_supported_band *sband;
1805 int rate; 1836 int rate;
1806 u8 i, exrates, *pos; 1837 u8 i, exrates, *pos;
1807 u32 basic_rates = vif->bss_conf.basic_rates; 1838 u32 basic_rates = sdata->vif.bss_conf.basic_rates;
1808 1839
1809 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 1840 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1810 exrates = sband->n_bitrates; 1841 exrates = sband->n_bitrates;
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 4177bb5104b9..ff749794bc5b 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -29,6 +29,8 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/nfc.h> 30#include <linux/nfc.h>
31 31
32#include <net/genetlink.h>
33
32#include "nfc.h" 34#include "nfc.h"
33 35
34#define VERSION "0.1" 36#define VERSION "0.1"
@@ -560,6 +562,8 @@ EXPORT_SYMBOL(nfc_alloc_recv_skb);
560 * The device driver must call this function when one or many nfc targets 562 * The device driver must call this function when one or many nfc targets
561 * are found. After calling this function, the device driver must stop 563 * are found. After calling this function, the device driver must stop
562 * polling for targets. 564 * polling for targets.
565 * NOTE: This function can be called with targets=NULL and n_targets=0 to
566 * notify a driver error, meaning that the polling operation cannot complete.
563 * IMPORTANT: this function must not be called from an atomic context. 567 * IMPORTANT: this function must not be called from an atomic context.
564 * In addition, it must also not be called from a context that would prevent 568 * In addition, it must also not be called from a context that would prevent
565 * the NFC Core to call other nfc ops entry point concurrently. 569 * the NFC Core to call other nfc ops entry point concurrently.
@@ -571,23 +575,33 @@ int nfc_targets_found(struct nfc_dev *dev,
571 575
572 pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets); 576 pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets);
573 577
574 dev->polling = false;
575
576 for (i = 0; i < n_targets; i++) 578 for (i = 0; i < n_targets; i++)
577 targets[i].idx = dev->target_next_idx++; 579 targets[i].idx = dev->target_next_idx++;
578 580
579 device_lock(&dev->dev); 581 device_lock(&dev->dev);
580 582
583 if (dev->polling == false) {
584 device_unlock(&dev->dev);
585 return 0;
586 }
587
588 dev->polling = false;
589
581 dev->targets_generation++; 590 dev->targets_generation++;
582 591
583 kfree(dev->targets); 592 kfree(dev->targets);
584 dev->targets = kmemdup(targets, n_targets * sizeof(struct nfc_target), 593 dev->targets = NULL;
585 GFP_ATOMIC);
586 594
587 if (!dev->targets) { 595 if (targets) {
588 dev->n_targets = 0; 596 dev->targets = kmemdup(targets,
589 device_unlock(&dev->dev); 597 n_targets * sizeof(struct nfc_target),
590 return -ENOMEM; 598 GFP_ATOMIC);
599
600 if (!dev->targets) {
601 dev->n_targets = 0;
602 device_unlock(&dev->dev);
603 return -ENOMEM;
604 }
591 } 605 }
592 606
593 dev->n_targets = n_targets; 607 dev->n_targets = n_targets;
@@ -651,6 +665,12 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)
651} 665}
652EXPORT_SYMBOL(nfc_target_lost); 666EXPORT_SYMBOL(nfc_target_lost);
653 667
668inline void nfc_driver_failure(struct nfc_dev *dev, int err)
669{
670 nfc_targets_found(dev, NULL, 0);
671}
672EXPORT_SYMBOL(nfc_driver_failure);
673
654static void nfc_release(struct device *d) 674static void nfc_release(struct device *d)
655{ 675{
656 struct nfc_dev *dev = to_nfc_dev(d); 676 struct nfc_dev *dev = to_nfc_dev(d);
@@ -906,3 +926,5 @@ MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>");
906MODULE_DESCRIPTION("NFC Core ver " VERSION); 926MODULE_DESCRIPTION("NFC Core ver " VERSION);
907MODULE_VERSION(VERSION); 927MODULE_VERSION(VERSION);
908MODULE_LICENSE("GPL"); 928MODULE_LICENSE("GPL");
929MODULE_ALIAS_NETPROTO(PF_NFC);
930MODULE_ALIAS_GENL_FAMILY(NFC_GENL_NAME);
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c
index 8729abf5f18b..46362ef979db 100644
--- a/net/nfc/hci/command.c
+++ b/net/nfc/hci/command.c
@@ -28,26 +28,14 @@
28 28
29#include "hci.h" 29#include "hci.h"
30 30
31static int nfc_hci_result_to_errno(u8 result) 31static void nfc_hci_execute_cb(struct nfc_hci_dev *hdev, int err,
32{
33 switch (result) {
34 case NFC_HCI_ANY_OK:
35 return 0;
36 case NFC_HCI_ANY_E_TIMEOUT:
37 return -ETIMEDOUT;
38 default:
39 return -1;
40 }
41}
42
43static void nfc_hci_execute_cb(struct nfc_hci_dev *hdev, u8 result,
44 struct sk_buff *skb, void *cb_data) 32 struct sk_buff *skb, void *cb_data)
45{ 33{
46 struct hcp_exec_waiter *hcp_ew = (struct hcp_exec_waiter *)cb_data; 34 struct hcp_exec_waiter *hcp_ew = (struct hcp_exec_waiter *)cb_data;
47 35
48 pr_debug("HCI Cmd completed with HCI result=%d\n", result); 36 pr_debug("HCI Cmd completed with result=%d\n", err);
49 37
50 hcp_ew->exec_result = nfc_hci_result_to_errno(result); 38 hcp_ew->exec_result = err;
51 if (hcp_ew->exec_result == 0) 39 if (hcp_ew->exec_result == 0)
52 hcp_ew->result_skb = skb; 40 hcp_ew->result_skb = skb;
53 else 41 else
@@ -311,9 +299,9 @@ int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev)
311} 299}
312EXPORT_SYMBOL(nfc_hci_disconnect_all_gates); 300EXPORT_SYMBOL(nfc_hci_disconnect_all_gates);
313 301
314int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate) 302int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate,
303 u8 pipe)
315{ 304{
316 u8 pipe = NFC_HCI_INVALID_PIPE;
317 bool pipe_created = false; 305 bool pipe_created = false;
318 int r; 306 int r;
319 307
@@ -322,6 +310,9 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate)
322 if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE) 310 if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE)
323 return -EADDRINUSE; 311 return -EADDRINUSE;
324 312
313 if (pipe != NFC_HCI_INVALID_PIPE)
314 goto pipe_is_open;
315
325 switch (dest_gate) { 316 switch (dest_gate) {
326 case NFC_HCI_LINK_MGMT_GATE: 317 case NFC_HCI_LINK_MGMT_GATE:
327 pipe = NFC_HCI_LINK_MGMT_PIPE; 318 pipe = NFC_HCI_LINK_MGMT_PIPE;
@@ -347,6 +338,7 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate)
347 return r; 338 return r;
348 } 339 }
349 340
341pipe_is_open:
350 hdev->gate2pipe[dest_gate] = pipe; 342 hdev->gate2pipe[dest_gate] = pipe;
351 343
352 return 0; 344 return 0;
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index a8b0b71e8f86..36717cebfbb6 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -32,6 +32,18 @@
32/* Largest headroom needed for outgoing HCI commands */ 32/* Largest headroom needed for outgoing HCI commands */
33#define HCI_CMDS_HEADROOM 1 33#define HCI_CMDS_HEADROOM 1
34 34
35static int nfc_hci_result_to_errno(u8 result)
36{
37 switch (result) {
38 case NFC_HCI_ANY_OK:
39 return 0;
40 case NFC_HCI_ANY_E_TIMEOUT:
41 return -ETIME;
42 default:
43 return -1;
44 }
45}
46
35static void nfc_hci_msg_tx_work(struct work_struct *work) 47static void nfc_hci_msg_tx_work(struct work_struct *work)
36{ 48{
37 struct nfc_hci_dev *hdev = container_of(work, struct nfc_hci_dev, 49 struct nfc_hci_dev *hdev = container_of(work, struct nfc_hci_dev,
@@ -46,7 +58,7 @@ static void nfc_hci_msg_tx_work(struct work_struct *work)
46 if (timer_pending(&hdev->cmd_timer) == 0) { 58 if (timer_pending(&hdev->cmd_timer) == 0) {
47 if (hdev->cmd_pending_msg->cb) 59 if (hdev->cmd_pending_msg->cb)
48 hdev->cmd_pending_msg->cb(hdev, 60 hdev->cmd_pending_msg->cb(hdev,
49 NFC_HCI_ANY_E_TIMEOUT, 61 -ETIME,
50 NULL, 62 NULL,
51 hdev-> 63 hdev->
52 cmd_pending_msg-> 64 cmd_pending_msg->
@@ -71,8 +83,7 @@ next_msg:
71 kfree_skb(skb); 83 kfree_skb(skb);
72 skb_queue_purge(&msg->msg_frags); 84 skb_queue_purge(&msg->msg_frags);
73 if (msg->cb) 85 if (msg->cb)
74 msg->cb(hdev, NFC_HCI_ANY_E_NOK, NULL, 86 msg->cb(hdev, r, NULL, msg->cb_context);
75 msg->cb_context);
76 kfree(msg); 87 kfree(msg);
77 break; 88 break;
78 } 89 }
@@ -116,20 +127,13 @@ static void nfc_hci_msg_rx_work(struct work_struct *work)
116 } 127 }
117} 128}
118 129
119void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result, 130static void __nfc_hci_cmd_completion(struct nfc_hci_dev *hdev, int err,
120 struct sk_buff *skb) 131 struct sk_buff *skb)
121{ 132{
122 mutex_lock(&hdev->msg_tx_mutex);
123
124 if (hdev->cmd_pending_msg == NULL) {
125 kfree_skb(skb);
126 goto exit;
127 }
128
129 del_timer_sync(&hdev->cmd_timer); 133 del_timer_sync(&hdev->cmd_timer);
130 134
131 if (hdev->cmd_pending_msg->cb) 135 if (hdev->cmd_pending_msg->cb)
132 hdev->cmd_pending_msg->cb(hdev, result, skb, 136 hdev->cmd_pending_msg->cb(hdev, err, skb,
133 hdev->cmd_pending_msg->cb_context); 137 hdev->cmd_pending_msg->cb_context);
134 else 138 else
135 kfree_skb(skb); 139 kfree_skb(skb);
@@ -138,6 +142,19 @@ void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result,
138 hdev->cmd_pending_msg = NULL; 142 hdev->cmd_pending_msg = NULL;
139 143
140 queue_work(hdev->msg_tx_wq, &hdev->msg_tx_work); 144 queue_work(hdev->msg_tx_wq, &hdev->msg_tx_work);
145}
146
147void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result,
148 struct sk_buff *skb)
149{
150 mutex_lock(&hdev->msg_tx_mutex);
151
152 if (hdev->cmd_pending_msg == NULL) {
153 kfree_skb(skb);
154 goto exit;
155 }
156
157 __nfc_hci_cmd_completion(hdev, nfc_hci_result_to_errno(result), skb);
141 158
142exit: 159exit:
143 mutex_unlock(&hdev->msg_tx_mutex); 160 mutex_unlock(&hdev->msg_tx_mutex);
@@ -213,7 +230,7 @@ static int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate)
213 } 230 }
214 break; 231 break;
215 case NFC_HCI_RF_READER_B_GATE: 232 case NFC_HCI_RF_READER_B_GATE:
216 targets->supported_protocols = NFC_PROTO_ISO14443_MASK; 233 targets->supported_protocols = NFC_PROTO_ISO14443_B_MASK;
217 break; 234 break;
218 default: 235 default:
219 if (hdev->ops->target_from_gate) 236 if (hdev->ops->target_from_gate)
@@ -298,15 +315,15 @@ static void nfc_hci_cmd_timeout(unsigned long data)
298} 315}
299 316
300static int hci_dev_connect_gates(struct nfc_hci_dev *hdev, u8 gate_count, 317static int hci_dev_connect_gates(struct nfc_hci_dev *hdev, u8 gate_count,
301 u8 gates[]) 318 struct nfc_hci_gate *gates)
302{ 319{
303 int r; 320 int r;
304 u8 *p = gates;
305 while (gate_count--) { 321 while (gate_count--) {
306 r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, *p); 322 r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID,
323 gates->gate, gates->pipe);
307 if (r < 0) 324 if (r < 0)
308 return r; 325 return r;
309 p++; 326 gates++;
310 } 327 }
311 328
312 return 0; 329 return 0;
@@ -316,14 +333,13 @@ static int hci_dev_session_init(struct nfc_hci_dev *hdev)
316{ 333{
317 struct sk_buff *skb = NULL; 334 struct sk_buff *skb = NULL;
318 int r; 335 int r;
319 u8 hci_gates[] = { /* NFC_HCI_ADMIN_GATE MUST be first */ 336
320 NFC_HCI_ADMIN_GATE, NFC_HCI_LOOPBACK_GATE, 337 if (hdev->init_data.gates[0].gate != NFC_HCI_ADMIN_GATE)
321 NFC_HCI_ID_MGMT_GATE, NFC_HCI_LINK_MGMT_GATE, 338 return -EPROTO;
322 NFC_HCI_RF_READER_B_GATE, NFC_HCI_RF_READER_A_GATE
323 };
324 339
325 r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, 340 r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID,
326 NFC_HCI_ADMIN_GATE); 341 hdev->init_data.gates[0].gate,
342 hdev->init_data.gates[0].pipe);
327 if (r < 0) 343 if (r < 0)
328 goto exit; 344 goto exit;
329 345
@@ -351,10 +367,6 @@ static int hci_dev_session_init(struct nfc_hci_dev *hdev)
351 if (r < 0) 367 if (r < 0)
352 goto exit; 368 goto exit;
353 369
354 r = hci_dev_connect_gates(hdev, sizeof(hci_gates), hci_gates);
355 if (r < 0)
356 goto disconnect_all;
357
358 r = hci_dev_connect_gates(hdev, hdev->init_data.gate_count, 370 r = hci_dev_connect_gates(hdev, hdev->init_data.gate_count,
359 hdev->init_data.gates); 371 hdev->init_data.gates);
360 if (r < 0) 372 if (r < 0)
@@ -717,6 +729,27 @@ void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev)
717} 729}
718EXPORT_SYMBOL(nfc_hci_get_clientdata); 730EXPORT_SYMBOL(nfc_hci_get_clientdata);
719 731
732static void nfc_hci_failure(struct nfc_hci_dev *hdev, int err)
733{
734 mutex_lock(&hdev->msg_tx_mutex);
735
736 if (hdev->cmd_pending_msg == NULL) {
737 nfc_driver_failure(hdev->ndev, err);
738 goto exit;
739 }
740
741 __nfc_hci_cmd_completion(hdev, err, NULL);
742
743exit:
744 mutex_unlock(&hdev->msg_tx_mutex);
745}
746
747void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err)
748{
749 nfc_hci_failure(hdev, err);
750}
751EXPORT_SYMBOL(nfc_hci_driver_failure);
752
720void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) 753void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb)
721{ 754{
722 struct hcp_packet *packet; 755 struct hcp_packet *packet;
@@ -727,16 +760,6 @@ void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb)
727 struct sk_buff *frag_skb; 760 struct sk_buff *frag_skb;
728 int msg_len; 761 int msg_len;
729 762
730 if (skb == NULL) {
731 /* TODO ELa: lower layer had permanent failure, need to
732 * propagate that up
733 */
734
735 skb_queue_purge(&hdev->rx_hcp_frags);
736
737 return;
738 }
739
740 packet = (struct hcp_packet *)skb->data; 763 packet = (struct hcp_packet *)skb->data;
741 if ((packet->header & ~NFC_HCI_FRAGMENT) == 0) { 764 if ((packet->header & ~NFC_HCI_FRAGMENT) == 0) {
742 skb_queue_tail(&hdev->rx_hcp_frags, skb); 765 skb_queue_tail(&hdev->rx_hcp_frags, skb);
@@ -757,9 +780,8 @@ void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb)
757 hcp_skb = nfc_alloc_recv_skb(NFC_HCI_HCP_PACKET_HEADER_LEN + 780 hcp_skb = nfc_alloc_recv_skb(NFC_HCI_HCP_PACKET_HEADER_LEN +
758 msg_len, GFP_KERNEL); 781 msg_len, GFP_KERNEL);
759 if (hcp_skb == NULL) { 782 if (hcp_skb == NULL) {
760 /* TODO ELa: cannot deliver HCP message. How to 783 nfc_hci_failure(hdev, -ENOMEM);
761 * propagate error up? 784 return;
762 */
763 } 785 }
764 786
765 *skb_put(hcp_skb, NFC_HCI_HCP_PACKET_HEADER_LEN) = pipe; 787 *skb_put(hcp_skb, NFC_HCI_HCP_PACKET_HEADER_LEN) = pipe;
diff --git a/net/nfc/hci/hci.h b/net/nfc/hci/hci.h
index 45f2fe4fd486..fa9a21e92239 100644
--- a/net/nfc/hci/hci.h
+++ b/net/nfc/hci/hci.h
@@ -37,10 +37,11 @@ struct hcp_packet {
37 37
38/* 38/*
39 * HCI command execution completion callback. 39 * HCI command execution completion callback.
40 * result will be one of the HCI response codes. 40 * result will be a standard linux error (may be converted from HCI response)
41 * skb contains the response data and must be disposed. 41 * skb contains the response data and must be disposed, or may be NULL if
42 * an error occured
42 */ 43 */
43typedef void (*hci_cmd_cb_t) (struct nfc_hci_dev *hdev, u8 result, 44typedef void (*hci_cmd_cb_t) (struct nfc_hci_dev *hdev, int result,
44 struct sk_buff *skb, void *cb_data); 45 struct sk_buff *skb, void *cb_data);
45 46
46struct hcp_exec_waiter { 47struct hcp_exec_waiter {
@@ -131,9 +132,4 @@ void nfc_hci_hcp_message_rx(struct nfc_hci_dev *hdev, u8 pipe, u8 type,
131#define NFC_HCI_ANY_E_REG_ACCESS_DENIED 0x0a 132#define NFC_HCI_ANY_E_REG_ACCESS_DENIED 0x0a
132#define NFC_HCI_ANY_E_PIPE_ACCESS_DENIED 0x0b 133#define NFC_HCI_ANY_E_PIPE_ACCESS_DENIED 0x0b
133 134
134/* Pipes */
135#define NFC_HCI_INVALID_PIPE 0x80
136#define NFC_HCI_LINK_MGMT_PIPE 0x00
137#define NFC_HCI_ADMIN_PIPE 0x01
138
139#endif /* __LOCAL_HCI_H */ 135#endif /* __LOCAL_HCI_H */
diff --git a/net/nfc/hci/shdlc.c b/net/nfc/hci/shdlc.c
index 6b836e6242b7..6f840c18c892 100644
--- a/net/nfc/hci/shdlc.c
+++ b/net/nfc/hci/shdlc.c
@@ -340,15 +340,6 @@ static void nfc_shdlc_connect_complete(struct nfc_shdlc *shdlc, int r)
340 shdlc->state = SHDLC_CONNECTED; 340 shdlc->state = SHDLC_CONNECTED;
341 } else { 341 } else {
342 shdlc->state = SHDLC_DISCONNECTED; 342 shdlc->state = SHDLC_DISCONNECTED;
343
344 /*
345 * TODO: Could it be possible that there are pending
346 * executing commands that are waiting for connect to complete
347 * before they can be carried? As connect is a blocking
348 * operation, it would require that the userspace process can
349 * send commands on the same device from a second thread before
350 * the device is up. I don't think that is possible, is it?
351 */
352 } 343 }
353 344
354 shdlc->connect_result = r; 345 shdlc->connect_result = r;
@@ -413,12 +404,12 @@ static void nfc_shdlc_rcv_u_frame(struct nfc_shdlc *shdlc,
413 r = nfc_shdlc_connect_send_ua(shdlc); 404 r = nfc_shdlc_connect_send_ua(shdlc);
414 nfc_shdlc_connect_complete(shdlc, r); 405 nfc_shdlc_connect_complete(shdlc, r);
415 } 406 }
416 } else if (shdlc->state > SHDLC_NEGOCIATING) { 407 } else if (shdlc->state == SHDLC_CONNECTED) {
417 /* 408 /*
418 * TODO: Chip wants to reset link 409 * Chip wants to reset link. This is unexpected and
419 * send ua, empty skb lists, reset counters 410 * unsupported.
420 * propagate info to HCI layer
421 */ 411 */
412 shdlc->hard_fault = -ECONNRESET;
422 } 413 }
423 break; 414 break;
424 case U_FRAME_UA: 415 case U_FRAME_UA:
@@ -523,10 +514,6 @@ static void nfc_shdlc_handle_send_queue(struct nfc_shdlc *shdlc)
523 514
524 r = shdlc->ops->xmit(shdlc, skb); 515 r = shdlc->ops->xmit(shdlc, skb);
525 if (r < 0) { 516 if (r < 0) {
526 /*
527 * TODO: Cannot send, shdlc machine is dead, we
528 * must propagate the information up to HCI.
529 */
530 shdlc->hard_fault = r; 517 shdlc->hard_fault = r;
531 break; 518 break;
532 } 519 }
@@ -590,6 +577,11 @@ static void nfc_shdlc_sm_work(struct work_struct *work)
590 skb_queue_purge(&shdlc->ack_pending_q); 577 skb_queue_purge(&shdlc->ack_pending_q);
591 break; 578 break;
592 case SHDLC_CONNECTING: 579 case SHDLC_CONNECTING:
580 if (shdlc->hard_fault) {
581 nfc_shdlc_connect_complete(shdlc, shdlc->hard_fault);
582 break;
583 }
584
593 if (shdlc->connect_tries++ < 5) 585 if (shdlc->connect_tries++ < 5)
594 r = nfc_shdlc_connect_initiate(shdlc); 586 r = nfc_shdlc_connect_initiate(shdlc);
595 else 587 else
@@ -610,6 +602,11 @@ static void nfc_shdlc_sm_work(struct work_struct *work)
610 } 602 }
611 603
612 nfc_shdlc_handle_rcv_queue(shdlc); 604 nfc_shdlc_handle_rcv_queue(shdlc);
605
606 if (shdlc->hard_fault) {
607 nfc_shdlc_connect_complete(shdlc, shdlc->hard_fault);
608 break;
609 }
613 break; 610 break;
614 case SHDLC_CONNECTED: 611 case SHDLC_CONNECTED:
615 nfc_shdlc_handle_rcv_queue(shdlc); 612 nfc_shdlc_handle_rcv_queue(shdlc);
@@ -637,10 +634,7 @@ static void nfc_shdlc_sm_work(struct work_struct *work)
637 } 634 }
638 635
639 if (shdlc->hard_fault) { 636 if (shdlc->hard_fault) {
640 /* 637 nfc_hci_driver_failure(shdlc->hdev, shdlc->hard_fault);
641 * TODO: Handle hard_fault that occured during
642 * this invocation of the shdlc worker
643 */
644 } 638 }
645 break; 639 break;
646 default: 640 default:
@@ -923,8 +917,6 @@ void nfc_shdlc_free(struct nfc_shdlc *shdlc)
923{ 917{
924 pr_debug("\n"); 918 pr_debug("\n");
925 919
926 /* TODO: Check that this cannot be called while still in use */
927
928 nfc_hci_unregister_device(shdlc->hdev); 920 nfc_hci_unregister_device(shdlc->hdev);
929 nfc_hci_free_device(shdlc->hdev); 921 nfc_hci_free_device(shdlc->hdev);
930 922
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 5d503eeb15a1..82f0f7588b46 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -45,7 +45,7 @@ void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk)
45 write_unlock(&l->lock); 45 write_unlock(&l->lock);
46} 46}
47 47
48static void nfc_llcp_socket_release(struct nfc_llcp_local *local) 48static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
49{ 49{
50 struct sock *sk; 50 struct sock *sk;
51 struct hlist_node *node, *tmp; 51 struct hlist_node *node, *tmp;
@@ -78,6 +78,11 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
78 78
79 sock_orphan(accept_sk); 79 sock_orphan(accept_sk);
80 } 80 }
81
82 if (listen == true) {
83 release_sock(sk);
84 continue;
85 }
81 } 86 }
82 87
83 sk->sk_state = LLCP_CLOSED; 88 sk->sk_state = LLCP_CLOSED;
@@ -106,7 +111,7 @@ static void local_release(struct kref *ref)
106 local = container_of(ref, struct nfc_llcp_local, ref); 111 local = container_of(ref, struct nfc_llcp_local, ref);
107 112
108 list_del(&local->list); 113 list_del(&local->list);
109 nfc_llcp_socket_release(local); 114 nfc_llcp_socket_release(local, false);
110 del_timer_sync(&local->link_timer); 115 del_timer_sync(&local->link_timer);
111 skb_queue_purge(&local->tx_queue); 116 skb_queue_purge(&local->tx_queue);
112 destroy_workqueue(local->tx_wq); 117 destroy_workqueue(local->tx_wq);
@@ -118,23 +123,48 @@ static void local_release(struct kref *ref)
118 123
119int nfc_llcp_local_put(struct nfc_llcp_local *local) 124int nfc_llcp_local_put(struct nfc_llcp_local *local)
120{ 125{
121 WARN_ON(local == NULL);
122
123 if (local == NULL) 126 if (local == NULL)
124 return 0; 127 return 0;
125 128
126 return kref_put(&local->ref, local_release); 129 return kref_put(&local->ref, local_release);
127} 130}
128 131
129static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local) 132static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
133 u8 ssap, u8 dsap)
130{ 134{
131 mutex_lock(&local->sdp_lock); 135 struct sock *sk;
136 struct hlist_node *node;
137 struct nfc_llcp_sock *llcp_sock;
132 138
133 local->local_wks = 0; 139 pr_debug("ssap dsap %d %d\n", ssap, dsap);
134 local->local_sdp = 0;
135 local->local_sap = 0;
136 140
137 mutex_unlock(&local->sdp_lock); 141 if (ssap == 0 && dsap == 0)
142 return NULL;
143
144 read_lock(&local->sockets.lock);
145
146 llcp_sock = NULL;
147
148 sk_for_each(sk, node, &local->sockets.head) {
149 llcp_sock = nfc_llcp_sock(sk);
150
151 if (llcp_sock->ssap == ssap && llcp_sock->dsap == dsap)
152 break;
153 }
154
155 read_unlock(&local->sockets.lock);
156
157 if (llcp_sock == NULL)
158 return NULL;
159
160 sock_hold(&llcp_sock->sk);
161
162 return llcp_sock;
163}
164
165static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock)
166{
167 sock_put(&sock->sk);
138} 168}
139 169
140static void nfc_llcp_timeout_work(struct work_struct *work) 170static void nfc_llcp_timeout_work(struct work_struct *work)
@@ -197,6 +227,51 @@ static int nfc_llcp_wks_sap(char *service_name, size_t service_name_len)
197 return -EINVAL; 227 return -EINVAL;
198} 228}
199 229
230static
231struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local,
232 u8 *sn, size_t sn_len)
233{
234 struct sock *sk;
235 struct hlist_node *node;
236 struct nfc_llcp_sock *llcp_sock, *tmp_sock;
237
238 pr_debug("sn %zd %p\n", sn_len, sn);
239
240 if (sn == NULL || sn_len == 0)
241 return NULL;
242
243 read_lock(&local->sockets.lock);
244
245 llcp_sock = NULL;
246
247 sk_for_each(sk, node, &local->sockets.head) {
248 tmp_sock = nfc_llcp_sock(sk);
249
250 pr_debug("llcp sock %p\n", tmp_sock);
251
252 if (tmp_sock->sk.sk_state != LLCP_LISTEN)
253 continue;
254
255 if (tmp_sock->service_name == NULL ||
256 tmp_sock->service_name_len == 0)
257 continue;
258
259 if (tmp_sock->service_name_len != sn_len)
260 continue;
261
262 if (memcmp(sn, tmp_sock->service_name, sn_len) == 0) {
263 llcp_sock = tmp_sock;
264 break;
265 }
266 }
267
268 read_unlock(&local->sockets.lock);
269
270 pr_debug("Found llcp sock %p\n", llcp_sock);
271
272 return llcp_sock;
273}
274
200u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, 275u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
201 struct nfc_llcp_sock *sock) 276 struct nfc_llcp_sock *sock)
202{ 277{
@@ -223,41 +298,26 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
223 } 298 }
224 299
225 /* 300 /*
226 * This is not a well known service, 301 * Check if there already is a non WKS socket bound
227 * we should try to find a local SDP free spot 302 * to this service name.
228 */ 303 */
229 ssap = find_first_zero_bit(&local->local_sdp, LLCP_SDP_NUM_SAP); 304 if (nfc_llcp_sock_from_sn(local, sock->service_name,
230 if (ssap == LLCP_SDP_NUM_SAP) { 305 sock->service_name_len) != NULL) {
231 mutex_unlock(&local->sdp_lock); 306 mutex_unlock(&local->sdp_lock);
232 307
233 return LLCP_SAP_MAX; 308 return LLCP_SAP_MAX;
234 } 309 }
235 310
236 pr_debug("SDP ssap %d\n", LLCP_WKS_NUM_SAP + ssap);
237
238 set_bit(ssap, &local->local_sdp);
239 mutex_unlock(&local->sdp_lock); 311 mutex_unlock(&local->sdp_lock);
240 312
241 return LLCP_WKS_NUM_SAP + ssap; 313 return LLCP_SDP_UNBOUND;
242
243 } else if (sock->ssap != 0) {
244 if (sock->ssap < LLCP_WKS_NUM_SAP) {
245 if (!test_bit(sock->ssap, &local->local_wks)) {
246 set_bit(sock->ssap, &local->local_wks);
247 mutex_unlock(&local->sdp_lock);
248
249 return sock->ssap;
250 }
251 314
252 } else if (sock->ssap < LLCP_SDP_NUM_SAP) { 315 } else if (sock->ssap != 0 && sock->ssap < LLCP_WKS_NUM_SAP) {
253 if (!test_bit(sock->ssap - LLCP_WKS_NUM_SAP, 316 if (!test_bit(sock->ssap, &local->local_wks)) {
254 &local->local_sdp)) { 317 set_bit(sock->ssap, &local->local_wks);
255 set_bit(sock->ssap - LLCP_WKS_NUM_SAP, 318 mutex_unlock(&local->sdp_lock);
256 &local->local_sdp);
257 mutex_unlock(&local->sdp_lock);
258 319
259 return sock->ssap; 320 return sock->ssap;
260 }
261 } 321 }
262 } 322 }
263 323
@@ -294,8 +354,34 @@ void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap)
294 local_ssap = ssap; 354 local_ssap = ssap;
295 sdp = &local->local_wks; 355 sdp = &local->local_wks;
296 } else if (ssap < LLCP_LOCAL_NUM_SAP) { 356 } else if (ssap < LLCP_LOCAL_NUM_SAP) {
357 atomic_t *client_cnt;
358
297 local_ssap = ssap - LLCP_WKS_NUM_SAP; 359 local_ssap = ssap - LLCP_WKS_NUM_SAP;
298 sdp = &local->local_sdp; 360 sdp = &local->local_sdp;
361 client_cnt = &local->local_sdp_cnt[local_ssap];
362
363 pr_debug("%d clients\n", atomic_read(client_cnt));
364
365 mutex_lock(&local->sdp_lock);
366
367 if (atomic_dec_and_test(client_cnt)) {
368 struct nfc_llcp_sock *l_sock;
369
370 pr_debug("No more clients for SAP %d\n", ssap);
371
372 clear_bit(local_ssap, sdp);
373
374 /* Find the listening sock and set it back to UNBOUND */
375 l_sock = nfc_llcp_sock_get(local, ssap, LLCP_SAP_SDP);
376 if (l_sock) {
377 l_sock->ssap = LLCP_SDP_UNBOUND;
378 nfc_llcp_sock_put(l_sock);
379 }
380 }
381
382 mutex_unlock(&local->sdp_lock);
383
384 return;
299 } else if (ssap < LLCP_MAX_SAP) { 385 } else if (ssap < LLCP_MAX_SAP) {
300 local_ssap = ssap - LLCP_LOCAL_NUM_SAP; 386 local_ssap = ssap - LLCP_LOCAL_NUM_SAP;
301 sdp = &local->local_sap; 387 sdp = &local->local_sap;
@@ -310,19 +396,26 @@ void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap)
310 mutex_unlock(&local->sdp_lock); 396 mutex_unlock(&local->sdp_lock);
311} 397}
312 398
313u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) 399static u8 nfc_llcp_reserve_sdp_ssap(struct nfc_llcp_local *local)
314{ 400{
315 struct nfc_llcp_local *local; 401 u8 ssap;
316 402
317 local = nfc_llcp_find_local(dev); 403 mutex_lock(&local->sdp_lock);
318 if (local == NULL) { 404
319 *general_bytes_len = 0; 405 ssap = find_first_zero_bit(&local->local_sdp, LLCP_SDP_NUM_SAP);
320 return NULL; 406 if (ssap == LLCP_SDP_NUM_SAP) {
407 mutex_unlock(&local->sdp_lock);
408
409 return LLCP_SAP_MAX;
321 } 410 }
322 411
323 *general_bytes_len = local->gb_len; 412 pr_debug("SDP ssap %d\n", LLCP_WKS_NUM_SAP + ssap);
324 413
325 return local->gb; 414 set_bit(ssap, &local->local_sdp);
415
416 mutex_unlock(&local->sdp_lock);
417
418 return LLCP_WKS_NUM_SAP + ssap;
326} 419}
327 420
328static int nfc_llcp_build_gb(struct nfc_llcp_local *local) 421static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
@@ -386,6 +479,23 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
386 return 0; 479 return 0;
387} 480}
388 481
482u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len)
483{
484 struct nfc_llcp_local *local;
485
486 local = nfc_llcp_find_local(dev);
487 if (local == NULL) {
488 *general_bytes_len = 0;
489 return NULL;
490 }
491
492 nfc_llcp_build_gb(local);
493
494 *general_bytes_len = local->gb_len;
495
496 return local->gb;
497}
498
389int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) 499int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
390{ 500{
391 struct nfc_llcp_local *local = nfc_llcp_find_local(dev); 501 struct nfc_llcp_local *local = nfc_llcp_find_local(dev);
@@ -509,74 +619,12 @@ out:
509 return llcp_sock; 619 return llcp_sock;
510} 620}
511 621
512static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
513 u8 ssap, u8 dsap)
514{
515 struct sock *sk;
516 struct hlist_node *node;
517 struct nfc_llcp_sock *llcp_sock;
518
519 pr_debug("ssap dsap %d %d\n", ssap, dsap);
520
521 if (ssap == 0 && dsap == 0)
522 return NULL;
523
524 read_lock(&local->sockets.lock);
525
526 llcp_sock = NULL;
527
528 sk_for_each(sk, node, &local->sockets.head) {
529 llcp_sock = nfc_llcp_sock(sk);
530
531 if (llcp_sock->ssap == ssap &&
532 llcp_sock->dsap == dsap)
533 break;
534 }
535
536 read_unlock(&local->sockets.lock);
537
538 if (llcp_sock == NULL)
539 return NULL;
540
541 sock_hold(&llcp_sock->sk);
542
543 return llcp_sock;
544}
545
546static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, 622static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local,
547 u8 *sn, size_t sn_len) 623 u8 *sn, size_t sn_len)
548{ 624{
549 struct sock *sk;
550 struct hlist_node *node;
551 struct nfc_llcp_sock *llcp_sock; 625 struct nfc_llcp_sock *llcp_sock;
552 626
553 pr_debug("sn %zd\n", sn_len); 627 llcp_sock = nfc_llcp_sock_from_sn(local, sn, sn_len);
554
555 if (sn == NULL || sn_len == 0)
556 return NULL;
557
558 read_lock(&local->sockets.lock);
559
560 llcp_sock = NULL;
561
562 sk_for_each(sk, node, &local->sockets.head) {
563 llcp_sock = nfc_llcp_sock(sk);
564
565 if (llcp_sock->sk.sk_state != LLCP_LISTEN)
566 continue;
567
568 if (llcp_sock->service_name == NULL ||
569 llcp_sock->service_name_len == 0)
570 continue;
571
572 if (llcp_sock->service_name_len != sn_len)
573 continue;
574
575 if (memcmp(sn, llcp_sock->service_name, sn_len) == 0)
576 break;
577 }
578
579 read_unlock(&local->sockets.lock);
580 628
581 if (llcp_sock == NULL) 629 if (llcp_sock == NULL)
582 return NULL; 630 return NULL;
@@ -586,11 +634,6 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local,
586 return llcp_sock; 634 return llcp_sock;
587} 635}
588 636
589static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock)
590{
591 sock_put(&sock->sk);
592}
593
594static u8 *nfc_llcp_connect_sn(struct sk_buff *skb, size_t *sn_len) 637static u8 *nfc_llcp_connect_sn(struct sk_buff *skb, size_t *sn_len)
595{ 638{
596 u8 *tlv = &skb->data[2], type, length; 639 u8 *tlv = &skb->data[2], type, length;
@@ -662,6 +705,21 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
662 goto fail; 705 goto fail;
663 } 706 }
664 707
708 if (sock->ssap == LLCP_SDP_UNBOUND) {
709 u8 ssap = nfc_llcp_reserve_sdp_ssap(local);
710
711 pr_debug("First client, reserving %d\n", ssap);
712
713 if (ssap == LLCP_SAP_MAX) {
714 reason = LLCP_DM_REJ;
715 release_sock(&sock->sk);
716 sock_put(&sock->sk);
717 goto fail;
718 }
719
720 sock->ssap = ssap;
721 }
722
665 new_sk = nfc_llcp_sock_alloc(NULL, parent->sk_type, GFP_ATOMIC); 723 new_sk = nfc_llcp_sock_alloc(NULL, parent->sk_type, GFP_ATOMIC);
666 if (new_sk == NULL) { 724 if (new_sk == NULL) {
667 reason = LLCP_DM_REJ; 725 reason = LLCP_DM_REJ;
@@ -675,9 +733,21 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
675 new_sock->local = nfc_llcp_local_get(local); 733 new_sock->local = nfc_llcp_local_get(local);
676 new_sock->miu = local->remote_miu; 734 new_sock->miu = local->remote_miu;
677 new_sock->nfc_protocol = sock->nfc_protocol; 735 new_sock->nfc_protocol = sock->nfc_protocol;
678 new_sock->ssap = sock->ssap;
679 new_sock->dsap = ssap; 736 new_sock->dsap = ssap;
737 new_sock->target_idx = local->target_idx;
680 new_sock->parent = parent; 738 new_sock->parent = parent;
739 new_sock->ssap = sock->ssap;
740 if (sock->ssap < LLCP_LOCAL_NUM_SAP && sock->ssap >= LLCP_WKS_NUM_SAP) {
741 atomic_t *client_count;
742
743 pr_debug("reserved_ssap %d for %p\n", sock->ssap, new_sock);
744
745 client_count =
746 &local->local_sdp_cnt[sock->ssap - LLCP_WKS_NUM_SAP];
747
748 atomic_inc(client_count);
749 new_sock->reserved_ssap = sock->ssap;
750 }
681 751
682 nfc_llcp_parse_connection_tlv(new_sock, &skb->data[LLCP_HEADER_SIZE], 752 nfc_llcp_parse_connection_tlv(new_sock, &skb->data[LLCP_HEADER_SIZE],
683 skb->len - LLCP_HEADER_SIZE); 753 skb->len - LLCP_HEADER_SIZE);
@@ -886,6 +956,45 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb)
886 nfc_llcp_sock_put(llcp_sock); 956 nfc_llcp_sock_put(llcp_sock);
887} 957}
888 958
959static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, struct sk_buff *skb)
960{
961 struct nfc_llcp_sock *llcp_sock;
962 struct sock *sk;
963 u8 dsap, ssap, reason;
964
965 dsap = nfc_llcp_dsap(skb);
966 ssap = nfc_llcp_ssap(skb);
967 reason = skb->data[2];
968
969 pr_debug("%d %d reason %d\n", ssap, dsap, reason);
970
971 switch (reason) {
972 case LLCP_DM_NOBOUND:
973 case LLCP_DM_REJ:
974 llcp_sock = nfc_llcp_connecting_sock_get(local, dsap);
975 break;
976
977 default:
978 llcp_sock = nfc_llcp_sock_get(local, dsap, ssap);
979 break;
980 }
981
982 if (llcp_sock == NULL) {
983 pr_err("Invalid DM\n");
984 return;
985 }
986
987 sk = &llcp_sock->sk;
988
989 sk->sk_err = ENXIO;
990 sk->sk_state = LLCP_CLOSED;
991 sk->sk_state_change(sk);
992
993 nfc_llcp_sock_put(llcp_sock);
994
995 return;
996}
997
889static void nfc_llcp_rx_work(struct work_struct *work) 998static void nfc_llcp_rx_work(struct work_struct *work)
890{ 999{
891 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, 1000 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
@@ -929,6 +1038,11 @@ static void nfc_llcp_rx_work(struct work_struct *work)
929 nfc_llcp_recv_cc(local, skb); 1038 nfc_llcp_recv_cc(local, skb);
930 break; 1039 break;
931 1040
1041 case LLCP_PDU_DM:
1042 pr_debug("DM\n");
1043 nfc_llcp_recv_dm(local, skb);
1044 break;
1045
932 case LLCP_PDU_I: 1046 case LLCP_PDU_I:
933 case LLCP_PDU_RR: 1047 case LLCP_PDU_RR:
934 case LLCP_PDU_RNR: 1048 case LLCP_PDU_RNR:
@@ -985,10 +1099,8 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)
985 if (local == NULL) 1099 if (local == NULL)
986 return; 1100 return;
987 1101
988 nfc_llcp_clear_sdp(local);
989
990 /* Close and purge all existing sockets */ 1102 /* Close and purge all existing sockets */
991 nfc_llcp_socket_release(local); 1103 nfc_llcp_socket_release(local, true);
992} 1104}
993 1105
994void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, 1106void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index 7286c86982ff..83b8bba5a280 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -37,6 +37,7 @@ enum llcp_state {
37#define LLCP_LOCAL_NUM_SAP 32 37#define LLCP_LOCAL_NUM_SAP 32
38#define LLCP_LOCAL_SAP_OFFSET (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP) 38#define LLCP_LOCAL_SAP_OFFSET (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP)
39#define LLCP_MAX_SAP (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP + LLCP_LOCAL_NUM_SAP) 39#define LLCP_MAX_SAP (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP + LLCP_LOCAL_NUM_SAP)
40#define LLCP_SDP_UNBOUND (LLCP_MAX_SAP + 1)
40 41
41struct nfc_llcp_sock; 42struct nfc_llcp_sock;
42 43
@@ -69,6 +70,7 @@ struct nfc_llcp_local {
69 unsigned long local_wks; /* Well known services */ 70 unsigned long local_wks; /* Well known services */
70 unsigned long local_sdp; /* Local services */ 71 unsigned long local_sdp; /* Local services */
71 unsigned long local_sap; /* Local SAPs, not available for discovery */ 72 unsigned long local_sap; /* Local SAPs, not available for discovery */
73 atomic_t local_sdp_cnt[LLCP_SDP_NUM_SAP];
72 74
73 /* local */ 75 /* local */
74 u8 gb[NFC_MAX_GT_LEN]; 76 u8 gb[NFC_MAX_GT_LEN];
@@ -113,6 +115,9 @@ struct nfc_llcp_sock {
113 /* Is the remote peer ready to receive */ 115 /* Is the remote peer ready to receive */
114 u8 remote_ready; 116 u8 remote_ready;
115 117
118 /* Reserved source SAP */
119 u8 reserved_ssap;
120
116 struct sk_buff_head tx_queue; 121 struct sk_buff_head tx_queue;
117 struct sk_buff_head tx_pending_queue; 122 struct sk_buff_head tx_pending_queue;
118 struct sk_buff_head tx_backlog_queue; 123 struct sk_buff_head tx_backlog_queue;
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index 05ca5a680071..ddeb9aa398f0 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -78,11 +78,11 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
78 struct sockaddr_nfc_llcp llcp_addr; 78 struct sockaddr_nfc_llcp llcp_addr;
79 int len, ret = 0; 79 int len, ret = 0;
80 80
81 pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family);
82
83 if (!addr || addr->sa_family != AF_NFC) 81 if (!addr || addr->sa_family != AF_NFC)
84 return -EINVAL; 82 return -EINVAL;
85 83
84 pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family);
85
86 memset(&llcp_addr, 0, sizeof(llcp_addr)); 86 memset(&llcp_addr, 0, sizeof(llcp_addr));
87 len = min_t(unsigned int, sizeof(llcp_addr), alen); 87 len = min_t(unsigned int, sizeof(llcp_addr), alen);
88 memcpy(&llcp_addr, addr, len); 88 memcpy(&llcp_addr, addr, len);
@@ -121,8 +121,12 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
121 GFP_KERNEL); 121 GFP_KERNEL);
122 122
123 llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock); 123 llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock);
124 if (llcp_sock->ssap == LLCP_MAX_SAP) 124 if (llcp_sock->ssap == LLCP_SAP_MAX) {
125 ret = -EADDRINUSE;
125 goto put_dev; 126 goto put_dev;
127 }
128
129 llcp_sock->reserved_ssap = llcp_sock->ssap;
126 130
127 nfc_llcp_sock_link(&local->sockets, sk); 131 nfc_llcp_sock_link(&local->sockets, sk);
128 132
@@ -283,22 +287,28 @@ error:
283 return ret; 287 return ret;
284} 288}
285 289
286static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr, 290static int llcp_sock_getname(struct socket *sock, struct sockaddr *uaddr,
287 int *len, int peer) 291 int *len, int peer)
288{ 292{
289 struct sockaddr_nfc_llcp *llcp_addr = (struct sockaddr_nfc_llcp *)addr;
290 struct sock *sk = sock->sk; 293 struct sock *sk = sock->sk;
291 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); 294 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
295 DECLARE_SOCKADDR(struct sockaddr_nfc_llcp *, llcp_addr, uaddr);
292 296
293 pr_debug("%p\n", sk); 297 if (llcp_sock == NULL || llcp_sock->dev == NULL)
298 return -EBADFD;
299
300 pr_debug("%p %d %d %d\n", sk, llcp_sock->target_idx,
301 llcp_sock->dsap, llcp_sock->ssap);
294 302
295 if (llcp_sock == NULL || llcp_sock->dev == NULL) 303 if (llcp_sock == NULL || llcp_sock->dev == NULL)
296 return -EBADFD; 304 return -EBADFD;
297 305
298 addr->sa_family = AF_NFC; 306 uaddr->sa_family = AF_NFC;
307
299 *len = sizeof(struct sockaddr_nfc_llcp); 308 *len = sizeof(struct sockaddr_nfc_llcp);
300 309
301 llcp_addr->dev_idx = llcp_sock->dev->idx; 310 llcp_addr->dev_idx = llcp_sock->dev->idx;
311 llcp_addr->target_idx = llcp_sock->target_idx;
302 llcp_addr->dsap = llcp_sock->dsap; 312 llcp_addr->dsap = llcp_sock->dsap;
303 llcp_addr->ssap = llcp_sock->ssap; 313 llcp_addr->ssap = llcp_sock->ssap;
304 llcp_addr->service_name_len = llcp_sock->service_name_len; 314 llcp_addr->service_name_len = llcp_sock->service_name_len;
@@ -406,7 +416,8 @@ static int llcp_sock_release(struct socket *sock)
406 } 416 }
407 } 417 }
408 418
409 nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); 419 if (llcp_sock->reserved_ssap < LLCP_SAP_MAX)
420 nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap);
410 421
411 release_sock(sk); 422 release_sock(sk);
412 423
@@ -486,6 +497,9 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
486 ret = -ENOMEM; 497 ret = -ENOMEM;
487 goto put_dev; 498 goto put_dev;
488 } 499 }
500
501 llcp_sock->reserved_ssap = llcp_sock->ssap;
502
489 if (addr->service_name_len == 0) 503 if (addr->service_name_len == 0)
490 llcp_sock->dsap = addr->dsap; 504 llcp_sock->dsap = addr->dsap;
491 else 505 else
@@ -687,6 +701,7 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
687 llcp_sock->send_n = llcp_sock->send_ack_n = 0; 701 llcp_sock->send_n = llcp_sock->send_ack_n = 0;
688 llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; 702 llcp_sock->recv_n = llcp_sock->recv_ack_n = 0;
689 llcp_sock->remote_ready = 1; 703 llcp_sock->remote_ready = 1;
704 llcp_sock->reserved_ssap = LLCP_SAP_MAX;
690 skb_queue_head_init(&llcp_sock->tx_queue); 705 skb_queue_head_init(&llcp_sock->tx_queue);
691 skb_queue_head_init(&llcp_sock->tx_pending_queue); 706 skb_queue_head_init(&llcp_sock->tx_pending_queue);
692 skb_queue_head_init(&llcp_sock->tx_backlog_queue); 707 skb_queue_head_init(&llcp_sock->tx_backlog_queue);
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 766a02b1dfa1..5bb4da680427 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -194,7 +194,7 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt)
194 } 194 }
195 195
196 if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && 196 if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
197 (protocols & NFC_PROTO_ISO14443_MASK)) { 197 (protocols & NFC_PROTO_ISO14443_B_MASK)) {
198 cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = 198 cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
199 NCI_NFC_B_PASSIVE_POLL_MODE; 199 NCI_NFC_B_PASSIVE_POLL_MODE;
200 cmd.disc_configs[cmd.num_disc_configs].frequency = 1; 200 cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
@@ -486,7 +486,8 @@ static int nci_activate_target(struct nfc_dev *nfc_dev,
486 param.rf_protocol = NCI_RF_PROTOCOL_T2T; 486 param.rf_protocol = NCI_RF_PROTOCOL_T2T;
487 else if (protocol == NFC_PROTO_FELICA) 487 else if (protocol == NFC_PROTO_FELICA)
488 param.rf_protocol = NCI_RF_PROTOCOL_T3T; 488 param.rf_protocol = NCI_RF_PROTOCOL_T3T;
489 else if (protocol == NFC_PROTO_ISO14443) 489 else if (protocol == NFC_PROTO_ISO14443 ||
490 protocol == NFC_PROTO_ISO14443_B)
490 param.rf_protocol = NCI_RF_PROTOCOL_ISO_DEP; 491 param.rf_protocol = NCI_RF_PROTOCOL_ISO_DEP;
491 else 492 else
492 param.rf_protocol = NCI_RF_PROTOCOL_NFC_DEP; 493 param.rf_protocol = NCI_RF_PROTOCOL_NFC_DEP;
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 2ab196a9f228..af7a93b04393 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -170,7 +170,10 @@ static int nci_add_new_protocol(struct nci_dev *ndev,
170 if (rf_protocol == NCI_RF_PROTOCOL_T2T) 170 if (rf_protocol == NCI_RF_PROTOCOL_T2T)
171 protocol = NFC_PROTO_MIFARE_MASK; 171 protocol = NFC_PROTO_MIFARE_MASK;
172 else if (rf_protocol == NCI_RF_PROTOCOL_ISO_DEP) 172 else if (rf_protocol == NCI_RF_PROTOCOL_ISO_DEP)
173 protocol = NFC_PROTO_ISO14443_MASK; 173 if (rf_tech_and_mode == NCI_NFC_A_PASSIVE_POLL_MODE)
174 protocol = NFC_PROTO_ISO14443_MASK;
175 else
176 protocol = NFC_PROTO_ISO14443_B_MASK;
174 else if (rf_protocol == NCI_RF_PROTOCOL_T3T) 177 else if (rf_protocol == NCI_RF_PROTOCOL_T3T)
175 protocol = NFC_PROTO_FELICA_MASK; 178 protocol = NFC_PROTO_FELICA_MASK;
176 else 179 else
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index f4f07f9b61c0..4c51714ee741 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -634,6 +634,15 @@ static int nfc_genl_stop_poll(struct sk_buff *skb, struct genl_info *info)
634 if (!dev) 634 if (!dev)
635 return -ENODEV; 635 return -ENODEV;
636 636
637 device_lock(&dev->dev);
638
639 if (!dev->polling) {
640 device_unlock(&dev->dev);
641 return -EINVAL;
642 }
643
644 device_unlock(&dev->dev);
645
637 mutex_lock(&dev->genl_data.genl_data_mutex); 646 mutex_lock(&dev->genl_data.genl_data_mutex);
638 647
639 if (dev->genl_data.poll_req_pid != info->snd_pid) { 648 if (dev->genl_data.poll_req_pid != info->snd_pid) {
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index 55a28ab21db9..0f7e0d621ab0 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_WEXT_SPY) += wext-spy.o
10obj-$(CONFIG_WEXT_PRIV) += wext-priv.o 10obj-$(CONFIG_WEXT_PRIV) += wext-priv.o
11 11
12cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o 12cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
13cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o 13cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o
14cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o 14cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
15cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o 15cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
16cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o 16cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o
diff --git a/net/wireless/ap.c b/net/wireless/ap.c
new file mode 100644
index 000000000000..fcc60d8dbefa
--- /dev/null
+++ b/net/wireless/ap.c
@@ -0,0 +1,46 @@
1#include <linux/ieee80211.h>
2#include <linux/export.h>
3#include <net/cfg80211.h>
4#include "nl80211.h"
5#include "core.h"
6
7
8static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
9 struct net_device *dev)
10{
11 struct wireless_dev *wdev = dev->ieee80211_ptr;
12 int err;
13
14 ASSERT_WDEV_LOCK(wdev);
15
16 if (!rdev->ops->stop_ap)
17 return -EOPNOTSUPP;
18
19 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
20 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
21 return -EOPNOTSUPP;
22
23 if (!wdev->beacon_interval)
24 return -ENOENT;
25
26 err = rdev->ops->stop_ap(&rdev->wiphy, dev);
27 if (!err) {
28 wdev->beacon_interval = 0;
29 wdev->channel = NULL;
30 }
31
32 return err;
33}
34
35int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
36 struct net_device *dev)
37{
38 struct wireless_dev *wdev = dev->ieee80211_ptr;
39 int err;
40
41 wdev_lock(wdev);
42 err = __cfg80211_stop_ap(rdev, dev);
43 wdev_unlock(wdev);
44
45 return err;
46}
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index c1999e45a07c..434c56b92c3c 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -82,13 +82,73 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
82 int freq, enum nl80211_channel_type chantype) 82 int freq, enum nl80211_channel_type chantype)
83{ 83{
84 struct ieee80211_channel *chan; 84 struct ieee80211_channel *chan;
85 int err;
85 86
86 if (!rdev->ops->set_monitor_channel) 87 if (!rdev->ops->set_monitor_channel)
87 return -EOPNOTSUPP; 88 return -EOPNOTSUPP;
89 if (!cfg80211_has_monitors_only(rdev))
90 return -EBUSY;
88 91
89 chan = rdev_freq_to_chan(rdev, freq, chantype); 92 chan = rdev_freq_to_chan(rdev, freq, chantype);
90 if (!chan) 93 if (!chan)
91 return -EINVAL; 94 return -EINVAL;
92 95
93 return rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype); 96 err = rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype);
97 if (!err) {
98 rdev->monitor_channel = chan;
99 rdev->monitor_channel_type = chantype;
100 }
101
102 return err;
103}
104
105void
106cfg80211_get_chan_state(struct cfg80211_registered_device *rdev,
107 struct wireless_dev *wdev,
108 struct ieee80211_channel **chan,
109 enum cfg80211_chan_mode *chanmode)
110{
111 *chan = NULL;
112 *chanmode = CHAN_MODE_UNDEFINED;
113
114 ASSERT_RDEV_LOCK(rdev);
115 ASSERT_WDEV_LOCK(wdev);
116
117 if (!netif_running(wdev->netdev))
118 return;
119
120 switch (wdev->iftype) {
121 case NL80211_IFTYPE_ADHOC:
122 if (wdev->current_bss) {
123 *chan = wdev->current_bss->pub.channel;
124 *chanmode = wdev->ibss_fixed
125 ? CHAN_MODE_SHARED
126 : CHAN_MODE_EXCLUSIVE;
127 return;
128 }
129 case NL80211_IFTYPE_STATION:
130 case NL80211_IFTYPE_P2P_CLIENT:
131 if (wdev->current_bss) {
132 *chan = wdev->current_bss->pub.channel;
133 *chanmode = CHAN_MODE_SHARED;
134 return;
135 }
136 break;
137 case NL80211_IFTYPE_AP:
138 case NL80211_IFTYPE_P2P_GO:
139 case NL80211_IFTYPE_MESH_POINT:
140 *chan = wdev->channel;
141 *chanmode = CHAN_MODE_SHARED;
142 return;
143 case NL80211_IFTYPE_MONITOR:
144 case NL80211_IFTYPE_AP_VLAN:
145 case NL80211_IFTYPE_WDS:
146 /* these interface types don't really have a channel */
147 return;
148 case NL80211_IFTYPE_UNSPECIFIED:
149 case NUM_NL80211_IFTYPES:
150 WARN_ON(1);
151 }
152
153 return;
94} 154}
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 907f62c80e28..eb60410ae588 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -373,6 +373,14 @@ static int wiphy_verify_combinations(struct wiphy *wiphy)
373 if (WARN_ON(!c->num_different_channels)) 373 if (WARN_ON(!c->num_different_channels))
374 return -EINVAL; 374 return -EINVAL;
375 375
376 /*
377 * Put a sane limit on maximum number of different
378 * channels to simplify channel accounting code.
379 */
380 if (WARN_ON(c->num_different_channels >
381 CFG80211_MAX_NUM_DIFFERENT_CHANNELS))
382 return -EINVAL;
383
376 if (WARN_ON(!c->n_limits)) 384 if (WARN_ON(!c->n_limits))
377 return -EINVAL; 385 return -EINVAL;
378 386
@@ -421,9 +429,11 @@ int wiphy_register(struct wiphy *wiphy)
421 int i; 429 int i;
422 u16 ifmodes = wiphy->interface_modes; 430 u16 ifmodes = wiphy->interface_modes;
423 431
432#ifdef CONFIG_PM
424 if (WARN_ON((wiphy->wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && 433 if (WARN_ON((wiphy->wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
425 !(wiphy->wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY))) 434 !(wiphy->wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY)))
426 return -EINVAL; 435 return -EINVAL;
436#endif
427 437
428 if (WARN_ON(wiphy->ap_sme_capa && 438 if (WARN_ON(wiphy->ap_sme_capa &&
429 !(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME))) 439 !(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME)))
@@ -458,8 +468,14 @@ int wiphy_register(struct wiphy *wiphy)
458 continue; 468 continue;
459 469
460 sband->band = band; 470 sband->band = band;
461 471 if (WARN_ON(!sband->n_channels))
462 if (WARN_ON(!sband->n_channels || !sband->n_bitrates)) 472 return -EINVAL;
473 /*
474 * on 60gHz band, there are no legacy rates, so
475 * n_bitrates is 0
476 */
477 if (WARN_ON(band != IEEE80211_BAND_60GHZ &&
478 !sband->n_bitrates))
463 return -EINVAL; 479 return -EINVAL;
464 480
465 /* 481 /*
@@ -500,12 +516,14 @@ int wiphy_register(struct wiphy *wiphy)
500 return -EINVAL; 516 return -EINVAL;
501 } 517 }
502 518
519#ifdef CONFIG_PM
503 if (rdev->wiphy.wowlan.n_patterns) { 520 if (rdev->wiphy.wowlan.n_patterns) {
504 if (WARN_ON(!rdev->wiphy.wowlan.pattern_min_len || 521 if (WARN_ON(!rdev->wiphy.wowlan.pattern_min_len ||
505 rdev->wiphy.wowlan.pattern_min_len > 522 rdev->wiphy.wowlan.pattern_min_len >
506 rdev->wiphy.wowlan.pattern_max_len)) 523 rdev->wiphy.wowlan.pattern_max_len))
507 return -EINVAL; 524 return -EINVAL;
508 } 525 }
526#endif
509 527
510 /* check and set up bitrates */ 528 /* check and set up bitrates */
511 ieee80211_set_bitrate_flags(wiphy); 529 ieee80211_set_bitrate_flags(wiphy);
@@ -713,6 +731,61 @@ static struct device_type wiphy_type = {
713 .name = "wlan", 731 .name = "wlan",
714}; 732};
715 733
734static struct ieee80211_channel *
735cfg80211_get_any_chan(struct cfg80211_registered_device *rdev)
736{
737 struct ieee80211_supported_band *sband;
738 int i;
739
740 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
741 sband = rdev->wiphy.bands[i];
742 if (sband && sband->n_channels > 0)
743 return &sband->channels[0];
744 }
745
746 return NULL;
747}
748
749static void cfg80211_init_mon_chan(struct cfg80211_registered_device *rdev)
750{
751 struct ieee80211_channel *chan;
752
753 chan = cfg80211_get_any_chan(rdev);
754 if (WARN_ON(!chan))
755 return;
756
757 mutex_lock(&rdev->devlist_mtx);
758 WARN_ON(cfg80211_set_monitor_channel(rdev, chan->center_freq,
759 NL80211_CHAN_NO_HT));
760 mutex_unlock(&rdev->devlist_mtx);
761}
762
763void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
764 enum nl80211_iftype iftype, int num)
765{
766 bool has_monitors_only_old = cfg80211_has_monitors_only(rdev);
767 bool has_monitors_only_new;
768
769 ASSERT_RTNL();
770
771 rdev->num_running_ifaces += num;
772 if (iftype == NL80211_IFTYPE_MONITOR)
773 rdev->num_running_monitor_ifaces += num;
774
775 has_monitors_only_new = cfg80211_has_monitors_only(rdev);
776 if (has_monitors_only_new != has_monitors_only_old) {
777 rdev->ops->set_monitor_enabled(&rdev->wiphy,
778 has_monitors_only_new);
779
780 if (!has_monitors_only_new) {
781 rdev->monitor_channel = NULL;
782 rdev->monitor_channel_type = NL80211_CHAN_NO_HT;
783 } else {
784 cfg80211_init_mon_chan(rdev);
785 }
786 }
787}
788
716static int cfg80211_netdev_notifier_call(struct notifier_block *nb, 789static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
717 unsigned long state, 790 unsigned long state,
718 void *ndev) 791 void *ndev)
@@ -806,12 +879,16 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
806 case NL80211_IFTYPE_MESH_POINT: 879 case NL80211_IFTYPE_MESH_POINT:
807 cfg80211_leave_mesh(rdev, dev); 880 cfg80211_leave_mesh(rdev, dev);
808 break; 881 break;
882 case NL80211_IFTYPE_AP:
883 cfg80211_stop_ap(rdev, dev);
884 break;
809 default: 885 default:
810 break; 886 break;
811 } 887 }
812 wdev->beacon_interval = 0; 888 wdev->beacon_interval = 0;
813 break; 889 break;
814 case NETDEV_DOWN: 890 case NETDEV_DOWN:
891 cfg80211_update_iface_num(rdev, wdev->iftype, -1);
815 dev_hold(dev); 892 dev_hold(dev);
816 queue_work(cfg80211_wq, &wdev->cleanup_work); 893 queue_work(cfg80211_wq, &wdev->cleanup_work);
817 break; 894 break;
@@ -917,9 +994,12 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
917 return notifier_from_errno(-EOPNOTSUPP); 994 return notifier_from_errno(-EOPNOTSUPP);
918 if (rfkill_blocked(rdev->rfkill)) 995 if (rfkill_blocked(rdev->rfkill))
919 return notifier_from_errno(-ERFKILL); 996 return notifier_from_errno(-ERFKILL);
997 mutex_lock(&rdev->devlist_mtx);
920 ret = cfg80211_can_add_interface(rdev, wdev->iftype); 998 ret = cfg80211_can_add_interface(rdev, wdev->iftype);
999 mutex_unlock(&rdev->devlist_mtx);
921 if (ret) 1000 if (ret)
922 return notifier_from_errno(ret); 1001 return notifier_from_errno(ret);
1002 cfg80211_update_iface_num(rdev, wdev->iftype, 1);
923 break; 1003 break;
924 } 1004 }
925 1005
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 609a579255ac..377dc394f48c 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -13,6 +13,7 @@
13#include <linux/debugfs.h> 13#include <linux/debugfs.h>
14#include <linux/rfkill.h> 14#include <linux/rfkill.h>
15#include <linux/workqueue.h> 15#include <linux/workqueue.h>
16#include <linux/rtnetlink.h>
16#include <net/genetlink.h> 17#include <net/genetlink.h>
17#include <net/cfg80211.h> 18#include <net/cfg80211.h>
18#include "reg.h" 19#include "reg.h"
@@ -56,6 +57,13 @@ struct cfg80211_registered_device {
56 57
57 u32 ap_beacons_nlpid; 58 u32 ap_beacons_nlpid;
58 59
60 /* protected by RTNL only */
61 int num_running_ifaces;
62 int num_running_monitor_ifaces;
63
64 struct ieee80211_channel *monitor_channel;
65 enum nl80211_channel_type monitor_channel_type;
66
59 /* BSSes/scanning */ 67 /* BSSes/scanning */
60 spinlock_t bss_lock; 68 spinlock_t bss_lock;
61 struct list_head bss_list; 69 struct list_head bss_list;
@@ -197,6 +205,14 @@ static inline void wdev_unlock(struct wireless_dev *wdev)
197#define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx) 205#define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx)
198#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx) 206#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
199 207
208static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)
209{
210 ASSERT_RTNL();
211
212 return rdev->num_running_ifaces == rdev->num_running_monitor_ifaces &&
213 rdev->num_running_ifaces > 0;
214}
215
200enum cfg80211_event_type { 216enum cfg80211_event_type {
201 EVENT_CONNECT_RESULT, 217 EVENT_CONNECT_RESULT,
202 EVENT_ROAMED, 218 EVENT_ROAMED,
@@ -241,6 +257,12 @@ struct cfg80211_cached_keys {
241 int def, defmgmt; 257 int def, defmgmt;
242}; 258};
243 259
260enum cfg80211_chan_mode {
261 CHAN_MODE_UNDEFINED,
262 CHAN_MODE_SHARED,
263 CHAN_MODE_EXCLUSIVE,
264};
265
244 266
245/* free object */ 267/* free object */
246extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev); 268extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
@@ -289,6 +311,10 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
289 struct wireless_dev *wdev, int freq, 311 struct wireless_dev *wdev, int freq,
290 enum nl80211_channel_type channel_type); 312 enum nl80211_channel_type channel_type);
291 313
314/* AP */
315int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
316 struct net_device *dev);
317
292/* MLME */ 318/* MLME */
293int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, 319int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
294 struct net_device *dev, 320 struct net_device *dev,
@@ -404,9 +430,20 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
404 u32 *flags, struct vif_params *params); 430 u32 *flags, struct vif_params *params);
405void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); 431void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
406 432
407int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, 433int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
408 struct wireless_dev *wdev, 434 struct wireless_dev *wdev,
409 enum nl80211_iftype iftype); 435 enum nl80211_iftype iftype,
436 struct ieee80211_channel *chan,
437 enum cfg80211_chan_mode chanmode);
438
439static inline int
440cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
441 struct wireless_dev *wdev,
442 enum nl80211_iftype iftype)
443{
444 return cfg80211_can_use_iftype_chan(rdev, wdev, iftype, NULL,
445 CHAN_MODE_UNDEFINED);
446}
410 447
411static inline int 448static inline int
412cfg80211_can_add_interface(struct cfg80211_registered_device *rdev, 449cfg80211_can_add_interface(struct cfg80211_registered_device *rdev,
@@ -415,6 +452,22 @@ cfg80211_can_add_interface(struct cfg80211_registered_device *rdev,
415 return cfg80211_can_change_interface(rdev, NULL, iftype); 452 return cfg80211_can_change_interface(rdev, NULL, iftype);
416} 453}
417 454
455static inline int
456cfg80211_can_use_chan(struct cfg80211_registered_device *rdev,
457 struct wireless_dev *wdev,
458 struct ieee80211_channel *chan,
459 enum cfg80211_chan_mode chanmode)
460{
461 return cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
462 chan, chanmode);
463}
464
465void
466cfg80211_get_chan_state(struct cfg80211_registered_device *rdev,
467 struct wireless_dev *wdev,
468 struct ieee80211_channel **chan,
469 enum cfg80211_chan_mode *chanmode);
470
418struct ieee80211_channel * 471struct ieee80211_channel *
419rdev_freq_to_chan(struct cfg80211_registered_device *rdev, 472rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
420 int freq, enum nl80211_channel_type channel_type); 473 int freq, enum nl80211_channel_type channel_type);
@@ -428,6 +481,11 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
428int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, 481int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
429 u32 beacon_int); 482 u32 beacon_int);
430 483
484void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
485 enum nl80211_iftype iftype, int num);
486
487#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
488
431#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS 489#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
432#define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond) 490#define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond)
433#else 491#else
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 89baa3328411..ca5672f6ee2f 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -113,10 +113,21 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
113 kfree(wdev->connect_keys); 113 kfree(wdev->connect_keys);
114 wdev->connect_keys = connkeys; 114 wdev->connect_keys = connkeys;
115 115
116 wdev->ibss_fixed = params->channel_fixed;
116#ifdef CONFIG_CFG80211_WEXT 117#ifdef CONFIG_CFG80211_WEXT
117 wdev->wext.ibss.channel = params->channel; 118 wdev->wext.ibss.channel = params->channel;
118#endif 119#endif
119 wdev->sme_state = CFG80211_SME_CONNECTING; 120 wdev->sme_state = CFG80211_SME_CONNECTING;
121
122 err = cfg80211_can_use_chan(rdev, wdev, params->channel,
123 params->channel_fixed
124 ? CHAN_MODE_SHARED
125 : CHAN_MODE_EXCLUSIVE);
126 if (err) {
127 wdev->connect_keys = NULL;
128 return err;
129 }
130
120 err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); 131 err = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
121 if (err) { 132 if (err) {
122 wdev->connect_keys = NULL; 133 wdev->connect_keys = NULL;
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 3b73b07486cf..c384e77ff77a 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -155,10 +155,16 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
155 setup->channel_type)) 155 setup->channel_type))
156 return -EINVAL; 156 return -EINVAL;
157 157
158 err = cfg80211_can_use_chan(rdev, wdev, setup->channel,
159 CHAN_MODE_SHARED);
160 if (err)
161 return err;
162
158 err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup); 163 err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup);
159 if (!err) { 164 if (!err) {
160 memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); 165 memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
161 wdev->mesh_id_len = setup->mesh_id_len; 166 wdev->mesh_id_len = setup->mesh_id_len;
167 wdev->channel = setup->channel;
162 } 168 }
163 169
164 return err; 170 return err;
@@ -172,9 +178,11 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
172 struct wireless_dev *wdev = dev->ieee80211_ptr; 178 struct wireless_dev *wdev = dev->ieee80211_ptr;
173 int err; 179 int err;
174 180
181 mutex_lock(&rdev->devlist_mtx);
175 wdev_lock(wdev); 182 wdev_lock(wdev);
176 err = __cfg80211_join_mesh(rdev, dev, setup, conf); 183 err = __cfg80211_join_mesh(rdev, dev, setup, conf);
177 wdev_unlock(wdev); 184 wdev_unlock(wdev);
185 mutex_unlock(&rdev->devlist_mtx);
178 186
179 return err; 187 return err;
180} 188}
@@ -184,6 +192,7 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
184 enum nl80211_channel_type channel_type) 192 enum nl80211_channel_type channel_type)
185{ 193{
186 struct ieee80211_channel *channel; 194 struct ieee80211_channel *channel;
195 int err;
187 196
188 channel = rdev_freq_to_chan(rdev, freq, channel_type); 197 channel = rdev_freq_to_chan(rdev, freq, channel_type);
189 if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy, 198 if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy,
@@ -205,9 +214,19 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
205 214
206 if (!netif_running(wdev->netdev)) 215 if (!netif_running(wdev->netdev))
207 return -ENETDOWN; 216 return -ENETDOWN;
208 return rdev->ops->libertas_set_mesh_channel(&rdev->wiphy, 217
209 wdev->netdev, 218 err = cfg80211_can_use_chan(rdev, wdev, channel,
210 channel); 219 CHAN_MODE_SHARED);
220 if (err)
221 return err;
222
223 err = rdev->ops->libertas_set_mesh_channel(&rdev->wiphy,
224 wdev->netdev,
225 channel);
226 if (!err)
227 wdev->channel = channel;
228
229 return err;
211 } 230 }
212 231
213 if (wdev->mesh_id_len) 232 if (wdev->mesh_id_len)
@@ -249,8 +268,11 @@ static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
249 return -ENOTCONN; 268 return -ENOTCONN;
250 269
251 err = rdev->ops->leave_mesh(&rdev->wiphy, dev); 270 err = rdev->ops->leave_mesh(&rdev->wiphy, dev);
252 if (!err) 271 if (!err) {
253 wdev->mesh_id_len = 0; 272 wdev->mesh_id_len = 0;
273 wdev->channel = NULL;
274 }
275
254 return err; 276 return err;
255} 277}
256 278
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index da4406f11929..d4fece3bb18a 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -302,8 +302,14 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
302 if (!req.bss) 302 if (!req.bss)
303 return -ENOENT; 303 return -ENOENT;
304 304
305 err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel,
306 CHAN_MODE_SHARED);
307 if (err)
308 goto out;
309
305 err = rdev->ops->auth(&rdev->wiphy, dev, &req); 310 err = rdev->ops->auth(&rdev->wiphy, dev, &req);
306 311
312out:
307 cfg80211_put_bss(req.bss); 313 cfg80211_put_bss(req.bss);
308 return err; 314 return err;
309} 315}
@@ -317,11 +323,13 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
317{ 323{
318 int err; 324 int err;
319 325
326 mutex_lock(&rdev->devlist_mtx);
320 wdev_lock(dev->ieee80211_ptr); 327 wdev_lock(dev->ieee80211_ptr);
321 err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, 328 err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
322 ssid, ssid_len, ie, ie_len, 329 ssid, ssid_len, ie, ie_len,
323 key, key_len, key_idx); 330 key, key_len, key_idx);
324 wdev_unlock(dev->ieee80211_ptr); 331 wdev_unlock(dev->ieee80211_ptr);
332 mutex_unlock(&rdev->devlist_mtx);
325 333
326 return err; 334 return err;
327} 335}
@@ -397,8 +405,14 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
397 return -ENOENT; 405 return -ENOENT;
398 } 406 }
399 407
408 err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel,
409 CHAN_MODE_SHARED);
410 if (err)
411 goto out;
412
400 err = rdev->ops->assoc(&rdev->wiphy, dev, &req); 413 err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
401 414
415out:
402 if (err) { 416 if (err) {
403 if (was_connected) 417 if (was_connected)
404 wdev->sme_state = CFG80211_SME_CONNECTED; 418 wdev->sme_state = CFG80211_SME_CONNECTED;
@@ -421,11 +435,13 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
421 struct wireless_dev *wdev = dev->ieee80211_ptr; 435 struct wireless_dev *wdev = dev->ieee80211_ptr;
422 int err; 436 int err;
423 437
438 mutex_lock(&rdev->devlist_mtx);
424 wdev_lock(wdev); 439 wdev_lock(wdev);
425 err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, 440 err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
426 ssid, ssid_len, ie, ie_len, use_mfp, crypt, 441 ssid, ssid_len, ie, ie_len, use_mfp, crypt,
427 assoc_flags, ht_capa, ht_capa_mask); 442 assoc_flags, ht_capa, ht_capa_mask);
428 wdev_unlock(wdev); 443 wdev_unlock(wdev);
444 mutex_unlock(&rdev->devlist_mtx);
429 445
430 return err; 446 return err;
431} 447}
@@ -947,6 +963,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
947 if (WARN_ON(!chan)) 963 if (WARN_ON(!chan))
948 goto out; 964 goto out;
949 965
966 wdev->channel = chan;
950 nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL); 967 nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL);
951out: 968out:
952 wdev_unlock(wdev); 969 wdev_unlock(wdev);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 3b508eaf2d07..0249cea53852 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -921,6 +921,15 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
921 dev->wiphy.bands[band]->ht_cap.ampdu_density))) 921 dev->wiphy.bands[band]->ht_cap.ampdu_density)))
922 goto nla_put_failure; 922 goto nla_put_failure;
923 923
924 /* add VHT info */
925 if (dev->wiphy.bands[band]->vht_cap.vht_supported &&
926 (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET,
927 sizeof(dev->wiphy.bands[band]->vht_cap.vht_mcs),
928 &dev->wiphy.bands[band]->vht_cap.vht_mcs) ||
929 nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA,
930 dev->wiphy.bands[band]->vht_cap.cap)))
931 goto nla_put_failure;
932
924 /* add frequencies */ 933 /* add frequencies */
925 nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS); 934 nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
926 if (!nl_freqs) 935 if (!nl_freqs)
@@ -1112,6 +1121,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
1112 nla_nest_end(msg, nl_ifs); 1121 nla_nest_end(msg, nl_ifs);
1113 } 1122 }
1114 1123
1124#ifdef CONFIG_PM
1115 if (dev->wiphy.wowlan.flags || dev->wiphy.wowlan.n_patterns) { 1125 if (dev->wiphy.wowlan.flags || dev->wiphy.wowlan.n_patterns) {
1116 struct nlattr *nl_wowlan; 1126 struct nlattr *nl_wowlan;
1117 1127
@@ -1152,6 +1162,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
1152 1162
1153 nla_nest_end(msg, nl_wowlan); 1163 nla_nest_end(msg, nl_wowlan);
1154 } 1164 }
1165#endif
1155 1166
1156 if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, 1167 if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
1157 dev->wiphy.software_iftypes)) 1168 dev->wiphy.software_iftypes))
@@ -1678,16 +1689,11 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
1678 (cfg80211_rdev_list_generation << 2))) 1689 (cfg80211_rdev_list_generation << 2)))
1679 goto nla_put_failure; 1690 goto nla_put_failure;
1680 1691
1681 if (rdev->ops->get_channel) { 1692 if (rdev->monitor_channel) {
1682 struct ieee80211_channel *chan; 1693 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
1683 enum nl80211_channel_type channel_type; 1694 rdev->monitor_channel->center_freq) ||
1684 1695 nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
1685 chan = rdev->ops->get_channel(&rdev->wiphy, &channel_type); 1696 rdev->monitor_channel_type))
1686 if (chan &&
1687 (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
1688 chan->center_freq) ||
1689 nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
1690 channel_type)))
1691 goto nla_put_failure; 1697 goto nla_put_failure;
1692 } 1698 }
1693 1699
@@ -2472,11 +2478,20 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
2472 params.channel_type)) 2478 params.channel_type))
2473 return -EINVAL; 2479 return -EINVAL;
2474 2480
2481 mutex_lock(&rdev->devlist_mtx);
2482 err = cfg80211_can_use_chan(rdev, wdev, params.channel,
2483 CHAN_MODE_SHARED);
2484 mutex_unlock(&rdev->devlist_mtx);
2485
2486 if (err)
2487 return err;
2488
2475 err = rdev->ops->start_ap(&rdev->wiphy, dev, &params); 2489 err = rdev->ops->start_ap(&rdev->wiphy, dev, &params);
2476 if (!err) { 2490 if (!err) {
2477 wdev->preset_chan = params.channel; 2491 wdev->preset_chan = params.channel;
2478 wdev->preset_chantype = params.channel_type; 2492 wdev->preset_chantype = params.channel_type;
2479 wdev->beacon_interval = params.beacon_interval; 2493 wdev->beacon_interval = params.beacon_interval;
2494 wdev->channel = params.channel;
2480 } 2495 }
2481 return err; 2496 return err;
2482} 2497}
@@ -2510,23 +2525,8 @@ static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
2510{ 2525{
2511 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 2526 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2512 struct net_device *dev = info->user_ptr[1]; 2527 struct net_device *dev = info->user_ptr[1];
2513 struct wireless_dev *wdev = dev->ieee80211_ptr;
2514 int err;
2515 2528
2516 if (!rdev->ops->stop_ap) 2529 return cfg80211_stop_ap(rdev, dev);
2517 return -EOPNOTSUPP;
2518
2519 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
2520 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
2521 return -EOPNOTSUPP;
2522
2523 if (!wdev->beacon_interval)
2524 return -ENOENT;
2525
2526 err = rdev->ops->stop_ap(&rdev->wiphy, dev);
2527 if (!err)
2528 wdev->beacon_interval = 0;
2529 return err;
2530} 2530}
2531 2531
2532static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { 2532static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
@@ -2618,7 +2618,8 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
2618 int attr) 2618 int attr)
2619{ 2619{
2620 struct nlattr *rate; 2620 struct nlattr *rate;
2621 u16 bitrate; 2621 u32 bitrate;
2622 u16 bitrate_compat;
2622 2623
2623 rate = nla_nest_start(msg, attr); 2624 rate = nla_nest_start(msg, attr);
2624 if (!rate) 2625 if (!rate)
@@ -2626,8 +2627,12 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
2626 2627
2627 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ 2628 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
2628 bitrate = cfg80211_calculate_bitrate(info); 2629 bitrate = cfg80211_calculate_bitrate(info);
2630 /* report 16-bit bitrate only if we can */
2631 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
2629 if ((bitrate > 0 && 2632 if ((bitrate > 0 &&
2630 nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate)) || 2633 nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate)) ||
2634 (bitrate_compat > 0 &&
2635 nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat)) ||
2631 ((info->flags & RATE_INFO_FLAGS_MCS) && 2636 ((info->flags & RATE_INFO_FLAGS_MCS) &&
2632 nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) || 2637 nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) ||
2633 ((info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) && 2638 ((info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) &&
@@ -6276,6 +6281,7 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
6276 return cfg80211_leave_mesh(rdev, dev); 6281 return cfg80211_leave_mesh(rdev, dev);
6277} 6282}
6278 6283
6284#ifdef CONFIG_PM
6279static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) 6285static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
6280{ 6286{
6281 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 6287 struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -6504,6 +6510,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
6504 kfree(new_triggers.patterns); 6510 kfree(new_triggers.patterns);
6505 return err; 6511 return err;
6506} 6512}
6513#endif
6507 6514
6508static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info) 6515static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
6509{ 6516{
@@ -7158,6 +7165,7 @@ static struct genl_ops nl80211_ops[] = {
7158 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 7165 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
7159 NL80211_FLAG_NEED_RTNL, 7166 NL80211_FLAG_NEED_RTNL,
7160 }, 7167 },
7168#ifdef CONFIG_PM
7161 { 7169 {
7162 .cmd = NL80211_CMD_GET_WOWLAN, 7170 .cmd = NL80211_CMD_GET_WOWLAN,
7163 .doit = nl80211_get_wowlan, 7171 .doit = nl80211_get_wowlan,
@@ -7174,6 +7182,7 @@ static struct genl_ops nl80211_ops[] = {
7174 .internal_flags = NL80211_FLAG_NEED_WIPHY | 7182 .internal_flags = NL80211_FLAG_NEED_WIPHY |
7175 NL80211_FLAG_NEED_RTNL, 7183 NL80211_FLAG_NEED_RTNL,
7176 }, 7184 },
7185#endif
7177 { 7186 {
7178 .cmd = NL80211_CMD_SET_REKEY_OFFLOAD, 7187 .cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
7179 .doit = nl80211_set_rekey_data, 7188 .doit = nl80211_set_rekey_data,
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index baf5704740ee..b2b32229b607 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -129,7 +129,7 @@ static DECLARE_DELAYED_WORK(reg_timeout, reg_timeout_work);
129 129
130/* We keep a static world regulatory domain in case of the absence of CRDA */ 130/* We keep a static world regulatory domain in case of the absence of CRDA */
131static const struct ieee80211_regdomain world_regdom = { 131static const struct ieee80211_regdomain world_regdom = {
132 .n_reg_rules = 5, 132 .n_reg_rules = 6,
133 .alpha2 = "00", 133 .alpha2 = "00",
134 .reg_rules = { 134 .reg_rules = {
135 /* IEEE 802.11b/g, channels 1..11 */ 135 /* IEEE 802.11b/g, channels 1..11 */
@@ -156,6 +156,9 @@ static const struct ieee80211_regdomain world_regdom = {
156 REG_RULE(5745-10, 5825+10, 40, 6, 20, 156 REG_RULE(5745-10, 5825+10, 40, 6, 20,
157 NL80211_RRF_PASSIVE_SCAN | 157 NL80211_RRF_PASSIVE_SCAN |
158 NL80211_RRF_NO_IBSS), 158 NL80211_RRF_NO_IBSS),
159
160 /* IEEE 802.11ad (60gHz), channels 1..3 */
161 REG_RULE(56160+2160*1-1080, 56160+2160*3+1080, 2160, 0, 0, 0),
159 } 162 }
160}; 163};
161 164
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 316cfd00914f..e31f1dba79ec 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -35,19 +35,29 @@ int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band)
35{ 35{
36 /* see 802.11 17.3.8.3.2 and Annex J 36 /* see 802.11 17.3.8.3.2 and Annex J
37 * there are overlapping channel numbers in 5GHz and 2GHz bands */ 37 * there are overlapping channel numbers in 5GHz and 2GHz bands */
38 if (band == IEEE80211_BAND_5GHZ) { 38 if (chan <= 0)
39 if (chan >= 182 && chan <= 196) 39 return 0; /* not supported */
40 return 4000 + chan * 5; 40 switch (band) {
41 else 41 case IEEE80211_BAND_2GHZ:
42 return 5000 + chan * 5;
43 } else { /* IEEE80211_BAND_2GHZ */
44 if (chan == 14) 42 if (chan == 14)
45 return 2484; 43 return 2484;
46 else if (chan < 14) 44 else if (chan < 14)
47 return 2407 + chan * 5; 45 return 2407 + chan * 5;
46 break;
47 case IEEE80211_BAND_5GHZ:
48 if (chan >= 182 && chan <= 196)
49 return 4000 + chan * 5;
48 else 50 else
49 return 0; /* not supported */ 51 return 5000 + chan * 5;
52 break;
53 case IEEE80211_BAND_60GHZ:
54 if (chan < 5)
55 return 56160 + chan * 2160;
56 break;
57 default:
58 ;
50 } 59 }
60 return 0; /* not supported */
51} 61}
52EXPORT_SYMBOL(ieee80211_channel_to_frequency); 62EXPORT_SYMBOL(ieee80211_channel_to_frequency);
53 63
@@ -60,8 +70,12 @@ int ieee80211_frequency_to_channel(int freq)
60 return (freq - 2407) / 5; 70 return (freq - 2407) / 5;
61 else if (freq >= 4910 && freq <= 4980) 71 else if (freq >= 4910 && freq <= 4980)
62 return (freq - 4000) / 5; 72 return (freq - 4000) / 5;
63 else 73 else if (freq <= 45000) /* DMG band lower limit */
64 return (freq - 5000) / 5; 74 return (freq - 5000) / 5;
75 else if (freq >= 58320 && freq <= 64800)
76 return (freq - 56160) / 2160;
77 else
78 return 0;
65} 79}
66EXPORT_SYMBOL(ieee80211_frequency_to_channel); 80EXPORT_SYMBOL(ieee80211_frequency_to_channel);
67 81
@@ -137,6 +151,11 @@ static void set_mandatory_flags_band(struct ieee80211_supported_band *sband,
137 } 151 }
138 WARN_ON(want != 0 && want != 3 && want != 6); 152 WARN_ON(want != 0 && want != 3 && want != 6);
139 break; 153 break;
154 case IEEE80211_BAND_60GHZ:
155 /* check for mandatory HT MCS 1..4 */
156 WARN_ON(!sband->ht_cap.ht_supported);
157 WARN_ON((sband->ht_cap.mcs.rx_mask[0] & 0x1e) != 0x1e);
158 break;
140 case IEEE80211_NUM_BANDS: 159 case IEEE80211_NUM_BANDS:
141 WARN_ON(1); 160 WARN_ON(1);
142 break; 161 break;
@@ -805,8 +824,10 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
805 return -EBUSY; 824 return -EBUSY;
806 825
807 if (ntype != otype && netif_running(dev)) { 826 if (ntype != otype && netif_running(dev)) {
827 mutex_lock(&rdev->devlist_mtx);
808 err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, 828 err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr,
809 ntype); 829 ntype);
830 mutex_unlock(&rdev->devlist_mtx);
810 if (err) 831 if (err)
811 return err; 832 return err;
812 833
@@ -814,6 +835,9 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
814 dev->ieee80211_ptr->mesh_id_up_len = 0; 835 dev->ieee80211_ptr->mesh_id_up_len = 0;
815 836
816 switch (otype) { 837 switch (otype) {
838 case NL80211_IFTYPE_AP:
839 cfg80211_stop_ap(rdev, dev);
840 break;
817 case NL80211_IFTYPE_ADHOC: 841 case NL80211_IFTYPE_ADHOC:
818 cfg80211_leave_ibss(rdev, dev, false); 842 cfg80211_leave_ibss(rdev, dev, false);
819 break; 843 break;
@@ -868,15 +892,69 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
868 } 892 }
869 } 893 }
870 894
895 if (!err && ntype != otype && netif_running(dev)) {
896 cfg80211_update_iface_num(rdev, ntype, 1);
897 cfg80211_update_iface_num(rdev, otype, -1);
898 }
899
871 return err; 900 return err;
872} 901}
873 902
874u16 cfg80211_calculate_bitrate(struct rate_info *rate) 903static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate)
904{
905 static const u32 __mcs2bitrate[] = {
906 /* control PHY */
907 [0] = 275,
908 /* SC PHY */
909 [1] = 3850,
910 [2] = 7700,
911 [3] = 9625,
912 [4] = 11550,
913 [5] = 12512, /* 1251.25 mbps */
914 [6] = 15400,
915 [7] = 19250,
916 [8] = 23100,
917 [9] = 25025,
918 [10] = 30800,
919 [11] = 38500,
920 [12] = 46200,
921 /* OFDM PHY */
922 [13] = 6930,
923 [14] = 8662, /* 866.25 mbps */
924 [15] = 13860,
925 [16] = 17325,
926 [17] = 20790,
927 [18] = 27720,
928 [19] = 34650,
929 [20] = 41580,
930 [21] = 45045,
931 [22] = 51975,
932 [23] = 62370,
933 [24] = 67568, /* 6756.75 mbps */
934 /* LP-SC PHY */
935 [25] = 6260,
936 [26] = 8340,
937 [27] = 11120,
938 [28] = 12510,
939 [29] = 16680,
940 [30] = 22240,
941 [31] = 25030,
942 };
943
944 if (WARN_ON_ONCE(rate->mcs >= ARRAY_SIZE(__mcs2bitrate)))
945 return 0;
946
947 return __mcs2bitrate[rate->mcs];
948}
949
950u32 cfg80211_calculate_bitrate(struct rate_info *rate)
875{ 951{
876 int modulation, streams, bitrate; 952 int modulation, streams, bitrate;
877 953
878 if (!(rate->flags & RATE_INFO_FLAGS_MCS)) 954 if (!(rate->flags & RATE_INFO_FLAGS_MCS))
879 return rate->legacy; 955 return rate->legacy;
956 if (rate->flags & RATE_INFO_FLAGS_60G)
957 return cfg80211_calculate_bitrate_60g(rate);
880 958
881 /* the formula below does only work for MCS values smaller than 32 */ 959 /* the formula below does only work for MCS values smaller than 32 */
882 if (WARN_ON_ONCE(rate->mcs >= 32)) 960 if (WARN_ON_ONCE(rate->mcs >= 32))
@@ -930,27 +1008,48 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
930 return res; 1008 return res;
931} 1009}
932 1010
933int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, 1011int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
934 struct wireless_dev *wdev, 1012 struct wireless_dev *wdev,
935 enum nl80211_iftype iftype) 1013 enum nl80211_iftype iftype,
1014 struct ieee80211_channel *chan,
1015 enum cfg80211_chan_mode chanmode)
936{ 1016{
937 struct wireless_dev *wdev_iter; 1017 struct wireless_dev *wdev_iter;
938 u32 used_iftypes = BIT(iftype); 1018 u32 used_iftypes = BIT(iftype);
939 int num[NUM_NL80211_IFTYPES]; 1019 int num[NUM_NL80211_IFTYPES];
1020 struct ieee80211_channel
1021 *used_channels[CFG80211_MAX_NUM_DIFFERENT_CHANNELS];
1022 struct ieee80211_channel *ch;
1023 enum cfg80211_chan_mode chmode;
1024 int num_different_channels = 0;
940 int total = 1; 1025 int total = 1;
941 int i, j; 1026 int i, j;
942 1027
943 ASSERT_RTNL(); 1028 ASSERT_RTNL();
1029 lockdep_assert_held(&rdev->devlist_mtx);
944 1030
945 /* Always allow software iftypes */ 1031 /* Always allow software iftypes */
946 if (rdev->wiphy.software_iftypes & BIT(iftype)) 1032 if (rdev->wiphy.software_iftypes & BIT(iftype))
947 return 0; 1033 return 0;
948 1034
949 memset(num, 0, sizeof(num)); 1035 memset(num, 0, sizeof(num));
1036 memset(used_channels, 0, sizeof(used_channels));
950 1037
951 num[iftype] = 1; 1038 num[iftype] = 1;
952 1039
953 mutex_lock(&rdev->devlist_mtx); 1040 switch (chanmode) {
1041 case CHAN_MODE_UNDEFINED:
1042 break;
1043 case CHAN_MODE_SHARED:
1044 WARN_ON(!chan);
1045 used_channels[0] = chan;
1046 num_different_channels++;
1047 break;
1048 case CHAN_MODE_EXCLUSIVE:
1049 num_different_channels++;
1050 break;
1051 }
1052
954 list_for_each_entry(wdev_iter, &rdev->netdev_list, list) { 1053 list_for_each_entry(wdev_iter, &rdev->netdev_list, list) {
955 if (wdev_iter == wdev) 1054 if (wdev_iter == wdev)
956 continue; 1055 continue;
@@ -960,11 +1059,33 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
960 if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype)) 1059 if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype))
961 continue; 1060 continue;
962 1061
1062 cfg80211_get_chan_state(rdev, wdev_iter, &ch, &chmode);
1063
1064 switch (chmode) {
1065 case CHAN_MODE_UNDEFINED:
1066 break;
1067 case CHAN_MODE_SHARED:
1068 for (i = 0; i < CFG80211_MAX_NUM_DIFFERENT_CHANNELS; i++)
1069 if (!used_channels[i] || used_channels[i] == ch)
1070 break;
1071
1072 if (i == CFG80211_MAX_NUM_DIFFERENT_CHANNELS)
1073 return -EBUSY;
1074
1075 if (used_channels[i] == NULL) {
1076 used_channels[i] = ch;
1077 num_different_channels++;
1078 }
1079 break;
1080 case CHAN_MODE_EXCLUSIVE:
1081 num_different_channels++;
1082 break;
1083 }
1084
963 num[wdev_iter->iftype]++; 1085 num[wdev_iter->iftype]++;
964 total++; 1086 total++;
965 used_iftypes |= BIT(wdev_iter->iftype); 1087 used_iftypes |= BIT(wdev_iter->iftype);
966 } 1088 }
967 mutex_unlock(&rdev->devlist_mtx);
968 1089
969 if (total == 1) 1090 if (total == 1)
970 return 0; 1091 return 0;
@@ -976,12 +1097,15 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
976 1097
977 c = &rdev->wiphy.iface_combinations[i]; 1098 c = &rdev->wiphy.iface_combinations[i];
978 1099
1100 if (total > c->max_interfaces)
1101 continue;
1102 if (num_different_channels > c->num_different_channels)
1103 continue;
1104
979 limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits, 1105 limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits,
980 GFP_KERNEL); 1106 GFP_KERNEL);
981 if (!limits) 1107 if (!limits)
982 return -ENOMEM; 1108 return -ENOMEM;
983 if (total > c->max_interfaces)
984 goto cont;
985 1109
986 for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { 1110 for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
987 if (rdev->wiphy.software_iftypes & BIT(iftype)) 1111 if (rdev->wiphy.software_iftypes & BIT(iftype))
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index bc879833b21f..7df42f541873 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -827,8 +827,6 @@ static int cfg80211_wext_giwfreq(struct net_device *dev,
827{ 827{
828 struct wireless_dev *wdev = dev->ieee80211_ptr; 828 struct wireless_dev *wdev = dev->ieee80211_ptr;
829 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 829 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
830 struct ieee80211_channel *chan;
831 enum nl80211_channel_type channel_type;
832 830
833 switch (wdev->iftype) { 831 switch (wdev->iftype) {
834 case NL80211_IFTYPE_STATION: 832 case NL80211_IFTYPE_STATION:
@@ -836,13 +834,10 @@ static int cfg80211_wext_giwfreq(struct net_device *dev,
836 case NL80211_IFTYPE_ADHOC: 834 case NL80211_IFTYPE_ADHOC:
837 return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); 835 return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
838 case NL80211_IFTYPE_MONITOR: 836 case NL80211_IFTYPE_MONITOR:
839 if (!rdev->ops->get_channel) 837 if (!rdev->monitor_channel)
840 return -EINVAL; 838 return -EINVAL;
841 839
842 chan = rdev->ops->get_channel(wdev->wiphy, &channel_type); 840 freq->m = rdev->monitor_channel->center_freq;
843 if (!chan)
844 return -EINVAL;
845 freq->m = chan->center_freq;
846 freq->e = 6; 841 freq->e = 6;
847 return 0; 842 return 0;
848 default: 843 default: