summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-03-09 14:57:30 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-03-09 14:57:30 -0500
commit74dd1521d0b4f940cdd3ce7b9d988836bef589b8 (patch)
tree42f3d4ee1d4e6d60a91aaadab771f766a3024bc0
parent2f2d76cc3e938389feee671b46252dde6880b3b7 (diff)
parent1745e4405b2c0da6db2ec4b6bc0ad930612d8295 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
-rw-r--r--arch/mips/bcm47xx/Makefile2
-rw-r--r--arch/mips/bcm47xx/nvram.c3
-rw-r--r--arch/mips/bcm47xx/setup.c188
-rw-r--r--arch/mips/bcm47xx/sprom.c620
-rw-r--r--arch/mips/include/asm/mach-bcm47xx/bcm47xx.h3
-rw-r--r--arch/mips/include/asm/mach-bcm47xx/nvram.h2
-rw-r--r--drivers/bcma/driver_chipcommon_pmu.c1
-rw-r--r--drivers/bcma/main.c3
-rw-r--r--drivers/bcma/sprom.c182
-rw-r--r--drivers/net/wireless/airo.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h1
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c20
-rw-r--r--drivers/net/wireless/ath/ath5k/mac80211-ops.c4
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c34
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/Kconfig8
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.c26
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c41
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h27
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c14
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c66
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c7
-rw-r--r--drivers/net/wireless/b43/main.c2
-rw-r--r--drivers/net/wireless/b43legacy/phy.c2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h4
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c30
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.c32
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.h27
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/ampdu.c20
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c31
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c2
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.h2
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig11
-rw-r--r--drivers/net/wireless/iwlwifi/Makefile2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c31
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-2000.c44
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c63
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c103
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.c65
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c101
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rx.c180
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c91
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-sta.c385
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tt.c47
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c164
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c357
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h166
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-cfg.h82
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h106
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c111
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h78
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h26
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c167
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h37
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-devtrace.h141
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c684
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c69
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw-file.h (renamed from drivers/net/wireless/iwlwifi/iwl-ucode.h)66
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw.h (renamed from drivers/net/wireless/iwlwifi/iwl-wifi.h)97
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.c69
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.h8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-mac80211.c403
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-notif-wait.c157
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-notif-wait.h (renamed from drivers/net/wireless/iwlwifi/iwl-trans.c)76
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-op-mode.h26
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-pci.c13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-prph.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c218
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-shared.h331
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-testmode.c103
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-testmode.h13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h104
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c313
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c164
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie.c285
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h191
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-ucode.c911
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c45
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c32
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c8
-rw-r--r--drivers/net/wireless/mwifiex/decl.h5
-rw-r--r--drivers/net/wireless/mwifiex/fw.h10
-rw-r--r--drivers/net/wireless/mwifiex/ioctl.h4
-rw-r--r--drivers/net/wireless/mwifiex/join.c6
-rw-r--r--drivers/net/wireless/mwifiex/main.h19
-rw-r--r--drivers/net/wireless/mwifiex/scan.c47
-rw-r--r--drivers/net/wireless/mwifiex/sta_event.c2
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c20
-rw-r--r--drivers/net/wireless/p54/main.c5
-rw-r--r--drivers/net/wireless/p54/p54pci.c48
-rw-r--r--drivers/net/wireless/p54/p54spi.c14
-rw-r--r--drivers/net/wireless/rndis_wlan.c61
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187/dev.c110
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187/rtl8187.h9
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c15
-rw-r--r--drivers/net/wireless/rtlwifi/usb.c18
-rw-r--r--drivers/net/wireless/wl12xx/cmd.c26
-rw-r--r--drivers/net/wireless/wl12xx/conf.h3
-rw-r--r--drivers/net/wireless/wl12xx/main.c438
-rw-r--r--drivers/net/wireless/wl12xx/ps.c4
-rw-r--r--drivers/net/wireless/wl12xx/scan.c6
-rw-r--r--drivers/net/wireless/wl12xx/tx.c41
-rw-r--r--drivers/net/wireless/wl12xx/tx.h1
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h7
-rw-r--r--drivers/nfc/pn533.c31
-rw-r--r--drivers/ssb/pci.c41
-rw-r--r--drivers/ssb/pcmcia.c12
-rw-r--r--drivers/ssb/sdio.c12
-rw-r--r--include/linux/bcma/bcma.h7
-rw-r--r--include/linux/bcma/bcma_driver_chipcommon.h10
-rw-r--r--include/linux/nfc.h1
-rw-r--r--include/linux/nl80211.h26
-rw-r--r--include/linux/ssb/ssb.h102
-rw-r--r--include/net/cfg80211.h29
-rw-r--r--include/net/mac80211.h12
-rw-r--r--include/net/nfc/nci_core.h10
-rw-r--r--include/net/nfc/nfc.h30
-rw-r--r--net/mac80211/cfg.c31
-rw-r--r--net/mac80211/debugfs_netdev.c9
-rw-r--r--net/mac80211/ibss.c10
-rw-r--r--net/mac80211/ieee80211_i.h46
-rw-r--r--net/mac80211/iface.c2
-rw-r--r--net/mac80211/mesh.c2
-rw-r--r--net/mac80211/mesh.h4
-rw-r--r--net/mac80211/mesh_hwmp.c54
-rw-r--r--net/mac80211/mesh_pathtbl.c34
-rw-r--r--net/mac80211/mesh_plink.c17
-rw-r--r--net/mac80211/mlme.c56
-rw-r--r--net/mac80211/rx.c70
-rw-r--r--net/mac80211/scan.c74
-rw-r--r--net/mac80211/sta_info.c5
-rw-r--r--net/mac80211/sta_info.h6
-rw-r--r--net/mac80211/status.c3
-rw-r--r--net/mac80211/util.c46
-rw-r--r--net/nfc/af_nfc.c2
-rw-r--r--net/nfc/core.c50
-rw-r--r--net/nfc/llcp/commands.c163
-rw-r--r--net/nfc/llcp/llcp.c201
-rw-r--r--net/nfc/llcp/llcp.h12
-rw-r--r--net/nfc/llcp/sock.c120
-rw-r--r--net/nfc/nci/core.c113
-rw-r--r--net/nfc/nci/data.c28
-rw-r--r--net/nfc/nci/ntf.c75
-rw-r--r--net/nfc/nci/rsp.c17
-rw-r--r--net/nfc/netlink.c71
-rw-r--r--net/nfc/nfc.h18
-rw-r--r--net/nfc/rawsock.c16
-rw-r--r--net/wireless/mesh.c3
-rw-r--r--net/wireless/mlme.c7
-rw-r--r--net/wireless/nl80211.c22
-rw-r--r--net/wireless/nl80211.h3
-rw-r--r--net/wireless/util.c1
166 files changed, 6183 insertions, 4874 deletions
diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile
index 4add17349ff..4389de182eb 100644
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -3,5 +3,5 @@
# under Linux.
#
-obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o
+obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c
index a84e3bb7387..d43ceff5be4 100644
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -107,8 +107,7 @@ int nvram_getenv(char *name, char *val, size_t val_len)
value = eq + 1;
if ((eq - var) == strlen(name) &&
strncmp(var, name, (eq - var)) == 0) {
- snprintf(val, val_len, "%s", value);
- return 0;
+ return snprintf(val, val_len, "%s", value);
}
}
return NVRAM_ERR_ENVNOTFOUND;
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index aab6b0c40a7..19780aa9170 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -3,7 +3,7 @@
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2006 Michael Buesch <m@bues.ch>
* Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
- * Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de>
+ * Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -85,156 +85,7 @@ static void bcm47xx_machine_halt(void)
}
#ifdef CONFIG_BCM47XX_SSB
-#define READ_FROM_NVRAM(_outvar, name, buf) \
- if (nvram_getprefix(prefix, name, buf, sizeof(buf)) >= 0)\
- sprom->_outvar = simple_strtoul(buf, NULL, 0);
-
-#define READ_FROM_NVRAM2(_outvar, name1, name2, buf) \
- if (nvram_getprefix(prefix, name1, buf, sizeof(buf)) >= 0 || \
- nvram_getprefix(prefix, name2, buf, sizeof(buf)) >= 0)\
- sprom->_outvar = simple_strtoul(buf, NULL, 0);
-
-static inline int nvram_getprefix(const char *prefix, char *name,
- char *buf, int len)
-{
- if (prefix) {
- char key[100];
-
- snprintf(key, sizeof(key), "%s%s", prefix, name);
- return nvram_getenv(key, buf, len);
- }
-
- return nvram_getenv(name, buf, len);
-}
-
-static u32 nvram_getu32(const char *name, char *buf, int len)
-{
- int rv;
- char key[100];
- u16 var0, var1;
-
- snprintf(key, sizeof(key), "%s0", name);
- rv = nvram_getenv(key, buf, len);
- /* return 0 here so this looks like unset */
- if (rv < 0)
- return 0;
- var0 = simple_strtoul(buf, NULL, 0);
-
- snprintf(key, sizeof(key), "%s1", name);
- rv = nvram_getenv(key, buf, len);
- if (rv < 0)
- return 0;
- var1 = simple_strtoul(buf, NULL, 0);
- return var1 << 16 | var0;
-}
-
-static void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
-{
- char buf[100];
- u32 boardflags;
-
- memset(sprom, 0, sizeof(struct ssb_sprom));
-
- sprom->revision = 1; /* Fallback: Old hardware does not define this. */
- READ_FROM_NVRAM(revision, "sromrev", buf);
- if (nvram_getprefix(prefix, "il0macaddr", buf, sizeof(buf)) >= 0 ||
- nvram_getprefix(prefix, "macaddr", buf, sizeof(buf)) >= 0)
- nvram_parse_macaddr(buf, sprom->il0mac);
- if (nvram_getprefix(prefix, "et0macaddr", buf, sizeof(buf)) >= 0)
- nvram_parse_macaddr(buf, sprom->et0mac);
- if (nvram_getprefix(prefix, "et1macaddr", buf, sizeof(buf)) >= 0)
- nvram_parse_macaddr(buf, sprom->et1mac);
- READ_FROM_NVRAM(et0phyaddr, "et0phyaddr", buf);
- READ_FROM_NVRAM(et1phyaddr, "et1phyaddr", buf);
- READ_FROM_NVRAM(et0mdcport, "et0mdcport", buf);
- READ_FROM_NVRAM(et1mdcport, "et1mdcport", buf);
- READ_FROM_NVRAM(board_rev, "boardrev", buf);
- READ_FROM_NVRAM(country_code, "ccode", buf);
- READ_FROM_NVRAM(ant_available_a, "aa5g", buf);
- READ_FROM_NVRAM(ant_available_bg, "aa2g", buf);
- READ_FROM_NVRAM(pa0b0, "pa0b0", buf);
- READ_FROM_NVRAM(pa0b1, "pa0b1", buf);
- READ_FROM_NVRAM(pa0b2, "pa0b2", buf);
- READ_FROM_NVRAM(pa1b0, "pa1b0", buf);
- READ_FROM_NVRAM(pa1b1, "pa1b1", buf);
- READ_FROM_NVRAM(pa1b2, "pa1b2", buf);
- READ_FROM_NVRAM(pa1lob0, "pa1lob0", buf);
- READ_FROM_NVRAM(pa1lob2, "pa1lob1", buf);
- READ_FROM_NVRAM(pa1lob1, "pa1lob2", buf);
- READ_FROM_NVRAM(pa1hib0, "pa1hib0", buf);
- READ_FROM_NVRAM(pa1hib2, "pa1hib1", buf);
- READ_FROM_NVRAM(pa1hib1, "pa1hib2", buf);
- READ_FROM_NVRAM2(gpio0, "ledbh0", "wl0gpio0", buf);
- READ_FROM_NVRAM2(gpio1, "ledbh1", "wl0gpio1", buf);
- READ_FROM_NVRAM2(gpio2, "ledbh2", "wl0gpio2", buf);
- READ_FROM_NVRAM2(gpio3, "ledbh3", "wl0gpio3", buf);
- READ_FROM_NVRAM2(maxpwr_bg, "maxp2ga0", "pa0maxpwr", buf);
- READ_FROM_NVRAM2(maxpwr_al, "maxp5gla0", "pa1lomaxpwr", buf);
- READ_FROM_NVRAM2(maxpwr_a, "maxp5ga0", "pa1maxpwr", buf);
- READ_FROM_NVRAM2(maxpwr_ah, "maxp5gha0", "pa1himaxpwr", buf);
- READ_FROM_NVRAM2(itssi_bg, "itt5ga0", "pa0itssit", buf);
- READ_FROM_NVRAM2(itssi_a, "itt2ga0", "pa1itssit", buf);
- READ_FROM_NVRAM(tri2g, "tri2g", buf);
- READ_FROM_NVRAM(tri5gl, "tri5gl", buf);
- READ_FROM_NVRAM(tri5g, "tri5g", buf);
- READ_FROM_NVRAM(tri5gh, "tri5gh", buf);
- READ_FROM_NVRAM(txpid2g[0], "txpid2ga0", buf);
- READ_FROM_NVRAM(txpid2g[1], "txpid2ga1", buf);
- READ_FROM_NVRAM(txpid2g[2], "txpid2ga2", buf);
- READ_FROM_NVRAM(txpid2g[3], "txpid2ga3", buf);
- READ_FROM_NVRAM(txpid5g[0], "txpid5ga0", buf);
- READ_FROM_NVRAM(txpid5g[1], "txpid5ga1", buf);
- READ_FROM_NVRAM(txpid5g[2], "txpid5ga2", buf);
- READ_FROM_NVRAM(txpid5g[3], "txpid5ga3", buf);
- READ_FROM_NVRAM(txpid5gl[0], "txpid5gla0", buf);
- READ_FROM_NVRAM(txpid5gl[1], "txpid5gla1", buf);
- READ_FROM_NVRAM(txpid5gl[2], "txpid5gla2", buf);
- READ_FROM_NVRAM(txpid5gl[3], "txpid5gla3", buf);
- READ_FROM_NVRAM(txpid5gh[0], "txpid5gha0", buf);
- READ_FROM_NVRAM(txpid5gh[1], "txpid5gha1", buf);
- READ_FROM_NVRAM(txpid5gh[2], "txpid5gha2", buf);
- READ_FROM_NVRAM(txpid5gh[3], "txpid5gha3", buf);
- READ_FROM_NVRAM(rxpo2g, "rxpo2g", buf);
- READ_FROM_NVRAM(rxpo5g, "rxpo5g", buf);
- READ_FROM_NVRAM(rssisav2g, "rssisav2g", buf);
- READ_FROM_NVRAM(rssismc2g, "rssismc2g", buf);
- READ_FROM_NVRAM(rssismf2g, "rssismf2g", buf);
- READ_FROM_NVRAM(bxa2g, "bxa2g", buf);
- READ_FROM_NVRAM(rssisav5g, "rssisav5g", buf);
- READ_FROM_NVRAM(rssismc5g, "rssismc5g", buf);
- READ_FROM_NVRAM(rssismf5g, "rssismf5g", buf);
- READ_FROM_NVRAM(bxa5g, "bxa5g", buf);
- READ_FROM_NVRAM(cck2gpo, "cck2gpo", buf);
-
- sprom->ofdm2gpo = nvram_getu32("ofdm2gpo", buf, sizeof(buf));
- sprom->ofdm5glpo = nvram_getu32("ofdm5glpo", buf, sizeof(buf));
- sprom->ofdm5gpo = nvram_getu32("ofdm5gpo", buf, sizeof(buf));
- sprom->ofdm5ghpo = nvram_getu32("ofdm5ghpo", buf, sizeof(buf));
-
- READ_FROM_NVRAM(antenna_gain.ghz24.a0, "ag0", buf);
- READ_FROM_NVRAM(antenna_gain.ghz24.a1, "ag1", buf);
- READ_FROM_NVRAM(antenna_gain.ghz24.a2, "ag2", buf);
- READ_FROM_NVRAM(antenna_gain.ghz24.a3, "ag3", buf);
- memcpy(&sprom->antenna_gain.ghz5, &sprom->antenna_gain.ghz24,
- sizeof(sprom->antenna_gain.ghz5));
-
- if (nvram_getprefix(prefix, "boardflags", buf, sizeof(buf)) >= 0) {
- boardflags = simple_strtoul(buf, NULL, 0);
- if (boardflags) {
- sprom->boardflags_lo = (boardflags & 0x0000FFFFU);
- sprom->boardflags_hi = (boardflags & 0xFFFF0000U) >> 16;
- }
- }
- if (nvram_getprefix(prefix, "boardflags2", buf, sizeof(buf)) >= 0) {
- boardflags = simple_strtoul(buf, NULL, 0);
- if (boardflags) {
- sprom->boardflags2_lo = (boardflags & 0x0000FFFFU);
- sprom->boardflags2_hi = (boardflags & 0xFFFF0000U) >> 16;
- }
- }
-}
-
-int bcm47xx_get_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
+static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
{
char prefix[10];
@@ -251,7 +102,7 @@ int bcm47xx_get_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
}
static int bcm47xx_get_invariants(struct ssb_bus *bus,
- struct ssb_init_invariants *iv)
+ struct ssb_init_invariants *iv)
{
char buf[20];
@@ -281,7 +132,7 @@ static void __init bcm47xx_register_ssb(void)
char buf[100];
struct ssb_mipscore *mcore;
- err = ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom);
+ err = ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom_ssb);
if (err)
printk(KERN_WARNING "bcm47xx: someone else already registered"
" a ssb SPROM callback handler (err %d)\n", err);
@@ -308,10 +159,41 @@ static void __init bcm47xx_register_ssb(void)
#endif
#ifdef CONFIG_BCM47XX_BCMA
+static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
+{
+ char prefix[10];
+ struct bcma_device *core;
+
+ switch (bus->hosttype) {
+ case BCMA_HOSTTYPE_PCI:
+ snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
+ bus->host_pci->bus->number + 1,
+ PCI_SLOT(bus->host_pci->devfn));
+ bcm47xx_fill_sprom(out, prefix);
+ return 0;
+ case BCMA_HOSTTYPE_SOC:
+ bcm47xx_fill_sprom_ethernet(out, NULL);
+ core = bcma_find_core(bus, BCMA_CORE_80211);
+ if (core) {
+ snprintf(prefix, sizeof(prefix), "sb/%u/",
+ core->core_index);
+ bcm47xx_fill_sprom(out, prefix);
+ }
+ return 0;
+ default:
+ pr_warn("bcm47xx: unable to fill SPROM for given bustype.\n");
+ return -EINVAL;
+ }
+}
+
static void __init bcm47xx_register_bcma(void)
{
int err;
+ err = bcma_arch_register_fallback_sprom(&bcm47xx_get_sprom_bcma);
+ if (err)
+ pr_warn("bcm47xx: someone else already registered a bcma SPROM callback handler (err %d)\n", err);
+
err = bcma_host_soc_register(&bcm47xx_bus.bcma);
if (err)
panic("Failed to initialize BCMA bus (err %d)", err);
diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c
new file mode 100644
index 00000000000..5c8dcd2a8a9
--- /dev/null
+++ b/arch/mips/bcm47xx/sprom.c
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
+ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006 Michael Buesch <m@bues.ch>
+ * Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
+ * Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <bcm47xx.h>
+#include <nvram.h>
+
+static void create_key(const char *prefix, const char *postfix,
+ const char *name, char *buf, int len)
+{
+ if (prefix && postfix)
+ snprintf(buf, len, "%s%s%s", prefix, name, postfix);
+ else if (prefix)
+ snprintf(buf, len, "%s%s", prefix, name);
+ else if (postfix)
+ snprintf(buf, len, "%s%s", name, postfix);
+ else
+ snprintf(buf, len, "%s", name);
+}
+
+#define NVRAM_READ_VAL(type) \
+static void nvram_read_ ## type (const char *prefix, \
+ const char *postfix, const char *name, \
+ type *val, type allset) \
+{ \
+ char buf[100]; \
+ char key[40]; \
+ int err; \
+ type var; \
+ \
+ create_key(prefix, postfix, name, key, sizeof(key)); \
+ \
+ err = nvram_getenv(key, buf, sizeof(buf)); \
+ if (err < 0) \
+ return; \
+ err = kstrto ## type (buf, 0, &var); \
+ if (err) { \
+ pr_warn("can not parse nvram name %s with value %s" \
+ " got %i", key, buf, err); \
+ return; \
+ } \
+ if (allset && var == allset) \
+ return; \
+ *val = var; \
+}
+
+NVRAM_READ_VAL(u8)
+NVRAM_READ_VAL(s8)
+NVRAM_READ_VAL(u16)
+NVRAM_READ_VAL(u32)
+
+#undef NVRAM_READ_VAL
+
+static void nvram_read_u32_2(const char *prefix, const char *name,
+ u16 *val_lo, u16 *val_hi)
+{
+ char buf[100];
+ char key[40];
+ int err;
+ u32 val;
+
+ create_key(prefix, NULL, name, key, sizeof(key));
+
+ err = nvram_getenv(key, buf, sizeof(buf));
+ if (err < 0)
+ return;
+ err = kstrtou32(buf, 0, &val);
+ if (err) {
+ pr_warn("can not parse nvram name %s with value %s got %i",
+ key, buf, err);
+ return;
+ }
+ *val_lo = (val & 0x0000FFFFU);
+ *val_hi = (val & 0xFFFF0000U) >> 16;
+}
+
+static void nvram_read_leddc(const char *prefix, const char *name,
+ u8 *leddc_on_time, u8 *leddc_off_time)
+{
+ char buf[100];
+ char key[40];
+ int err;
+ u32 val;
+
+ create_key(prefix, NULL, name, key, sizeof(key));
+
+ err = nvram_getenv(key, buf, sizeof(buf));
+ if (err < 0)
+ return;
+ err = kstrtou32(buf, 0, &val);
+ if (err) {
+ pr_warn("can not parse nvram name %s with value %s got %i",
+ key, buf, err);
+ return;
+ }
+
+ if (val == 0xffff || val == 0xffffffff)
+ return;
+
+ *leddc_on_time = val & 0xff;
+ *leddc_off_time = (val >> 16) & 0xff;
+}
+
+static void nvram_read_macaddr(const char *prefix, const char *name,
+ u8 (*val)[6])
+{
+ char buf[100];
+ char key[40];
+ int err;
+
+ create_key(prefix, NULL, name, key, sizeof(key));
+
+ err = nvram_getenv(key, buf, sizeof(buf));
+ if (err < 0)
+ return;
+ nvram_parse_macaddr(buf, *val);
+}
+
+static void nvram_read_alpha2(const char *prefix, const char *name,
+ char (*val)[2])
+{
+ char buf[10];
+ char key[40];
+ int err;
+
+ create_key(prefix, NULL, name, key, sizeof(key));
+
+ err = nvram_getenv(key, buf, sizeof(buf));
+ if (err < 0)
+ return;
+ if (buf[0] == '0')
+ return;
+ if (strlen(buf) > 2) {
+ pr_warn("alpha2 is too long %s", buf);
+ return;
+ }
+ memcpy(val, buf, sizeof(val));
+}
+
+static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom,
+ const char *prefix)
+{
+ nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0);
+ nvram_read_u16(prefix, NULL, "boardnum", &sprom->board_num, 0);
+ nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff);
+ nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff);
+ nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff);
+ nvram_read_u8(prefix, NULL, "ledbh3", &sprom->gpio3, 0xff);
+ nvram_read_u8(prefix, NULL, "aa2g", &sprom->ant_available_bg, 0);
+ nvram_read_u8(prefix, NULL, "aa5g", &sprom->ant_available_a, 0);
+ nvram_read_s8(prefix, NULL, "ag0", &sprom->antenna_gain.a0, 0);
+ nvram_read_s8(prefix, NULL, "ag1", &sprom->antenna_gain.a1, 0);
+ nvram_read_alpha2(prefix, "ccode", &sprom->alpha2);
+}
+
+static void bcm47xx_fill_sprom_r12389(struct ssb_sprom *sprom,
+ const char *prefix)
+{
+ nvram_read_u16(prefix, NULL, "pa0b0", &sprom->pa0b0, 0);
+ nvram_read_u16(prefix, NULL, "pa0b1", &sprom->pa0b1, 0);
+ nvram_read_u16(prefix, NULL, "pa0b2", &sprom->pa0b2, 0);
+ nvram_read_u8(prefix, NULL, "pa0itssit", &sprom->itssi_bg, 0);
+ nvram_read_u8(prefix, NULL, "pa0maxpwr", &sprom->maxpwr_bg, 0);
+ nvram_read_u16(prefix, NULL, "pa1b0", &sprom->pa1b0, 0);
+ nvram_read_u16(prefix, NULL, "pa1b1", &sprom->pa1b1, 0);
+ nvram_read_u16(prefix, NULL, "pa1b2", &sprom->pa1b2, 0);
+ nvram_read_u8(prefix, NULL, "pa1itssit", &sprom->itssi_a, 0);
+ nvram_read_u8(prefix, NULL, "pa1maxpwr", &sprom->maxpwr_a, 0);
+}
+
+static void bcm47xx_fill_sprom_r1(struct ssb_sprom *sprom, const char *prefix)
+{
+ nvram_read_u16(prefix, NULL, "boardflags", &sprom->boardflags_lo, 0);
+ nvram_read_u8(prefix, NULL, "cc", &sprom->country_code, 0);
+}
+
+static void bcm47xx_fill_sprom_r2389(struct ssb_sprom *sprom,
+ const char *prefix)
+{
+ nvram_read_u8(prefix, NULL, "opo", &sprom->opo, 0);
+ nvram_read_u16(prefix, NULL, "pa1lob0", &sprom->pa1lob0, 0);
+ nvram_read_u16(prefix, NULL, "pa1lob1", &sprom->pa1lob1, 0);
+ nvram_read_u16(prefix, NULL, "pa1lob2", &sprom->pa1lob2, 0);
+ nvram_read_u16(prefix, NULL, "pa1hib0", &sprom->pa1hib0, 0);
+ nvram_read_u16(prefix, NULL, "pa1hib1", &sprom->pa1hib1, 0);
+ nvram_read_u16(prefix, NULL, "pa1hib2", &sprom->pa1hib2, 0);
+ nvram_read_u8(prefix, NULL, "pa1lomaxpwr", &sprom->maxpwr_al, 0);
+ nvram_read_u8(prefix, NULL, "pa1himaxpwr", &sprom->maxpwr_ah, 0);
+}
+
+static void bcm47xx_fill_sprom_r2(struct ssb_sprom *sprom, const char *prefix)
+{
+ nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
+ &sprom->boardflags_hi);
+ nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
+}
+
+static void bcm47xx_fill_sprom_r389(struct ssb_sprom *sprom, const char *prefix)
+{
+ nvram_read_u8(prefix, NULL, "bxa2g", &sprom->bxa2g, 0);
+ nvram_read_u8(prefix, NULL, "rssisav2g", &sprom->rssisav2g, 0);
+ nvram_read_u8(prefix, NULL, "rssismc2g", &sprom->rssismc2g, 0);
+ nvram_read_u8(prefix, NULL, "rssismf2g", &sprom->rssismf2g, 0);
+ nvram_read_u8(prefix, NULL, "bxa5g", &sprom->bxa5g, 0);
+ nvram_read_u8(prefix, NULL, "rssisav5g", &sprom->rssisav5g, 0);
+ nvram_read_u8(prefix, NULL, "rssismc5g", &sprom->rssismc5g, 0);
+ nvram_read_u8(prefix, NULL, "rssismf5g", &sprom->rssismf5g, 0);
+ nvram_read_u8(prefix, NULL, "tri2g", &sprom->tri2g, 0);
+ nvram_read_u8(prefix, NULL, "tri5g", &sprom->tri5g, 0);
+ nvram_read_u8(prefix, NULL, "tri5gl", &sprom->tri5gl, 0);
+ nvram_read_u8(prefix, NULL, "tri5gh", &sprom->tri5gh, 0);
+ nvram_read_s8(prefix, NULL, "rxpo2g", &sprom->rxpo2g, 0);
+ nvram_read_s8(prefix, NULL, "rxpo5g", &sprom->rxpo5g, 0);
+}
+
+static void bcm47xx_fill_sprom_r3(struct ssb_sprom *sprom, const char *prefix)
+{
+ nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
+ &sprom->boardflags_hi);
+ nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
+ nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0);
+ nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
+ &sprom->leddc_off_time);
+}
+
+static void bcm47xx_fill_sprom_r4589(struct ssb_sprom *sprom,
+ const char *prefix)
+{
+ nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
+ &sprom->boardflags_hi);
+ nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo,
+ &sprom->boardflags2_hi);
+ nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
+ nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0);
+ nvram_read_s8(prefix, NULL, "ag2", &sprom->antenna_gain.a2, 0);
+ nvram_read_s8(prefix, NULL, "ag3", &sprom->antenna_gain.a3, 0);
+ nvram_read_u8(prefix, NULL, "txchain", &sprom->txchain, 0xf);
+ nvram_read_u8(prefix, NULL, "rxchain", &sprom->rxchain, 0xf);
+ nvram_read_u8(prefix, NULL, "antswitch", &sprom->antswitch, 0xff);
+ nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
+ &sprom->leddc_off_time);
+}
+
+static void bcm47xx_fill_sprom_r458(struct ssb_sprom *sprom, const char *prefix)
+{
+ nvram_read_u16(prefix, NULL, "cck2gpo", &sprom->cck2gpo, 0);
+ nvram_read_u32(prefix, NULL, "ofdm2gpo", &sprom->ofdm2gpo, 0);
+ nvram_read_u32(prefix, NULL, "ofdm5gpo", &sprom->ofdm5gpo, 0);
+ nvram_read_u32(prefix, NULL, "ofdm5glpo", &sprom->ofdm5glpo, 0);
+ nvram_read_u32(prefix, NULL, "ofdm5ghpo", &sprom->ofdm5ghpo, 0);
+ nvram_read_u16(prefix, NULL, "cddpo", &sprom->cddpo, 0);
+ nvram_read_u16(prefix, NULL, "stbcpo", &sprom->stbcpo, 0);
+ nvram_read_u16(prefix, NULL, "bw40po", &sprom->bw40po, 0);
+ nvram_read_u16(prefix, NULL, "bwduppo", &sprom->bwduppo, 0);
+ nvram_read_u16(prefix, NULL, "mcs2gpo0", &sprom->mcs2gpo[0], 0);
+ nvram_read_u16(prefix, NULL, "mcs2gpo1", &sprom->mcs2gpo[1], 0);
+ nvram_read_u16(prefix, NULL, "mcs2gpo2", &sprom->mcs2gpo[2], 0);
+ nvram_read_u16(prefix, NULL, "mcs2gpo3", &sprom->mcs2gpo[3], 0);
+ nvram_read_u16(prefix, NULL, "mcs2gpo4", &sprom->mcs2gpo[4], 0);
+ nvram_read_u16(prefix, NULL, "mcs2gpo5", &sprom->mcs2gpo[5], 0);
+ nvram_read_u16(prefix, NULL, "mcs2gpo6", &sprom->mcs2gpo[6], 0);
+ nvram_read_u16(prefix, NULL, "mcs2gpo7", &sprom->mcs2gpo[7], 0);
+ nvram_read_u16(prefix, NULL, "mcs5gpo0", &sprom->mcs5gpo[0], 0);
+ nvram_read_u16(prefix, NULL, "mcs5gpo1", &sprom->mcs5gpo[1], 0);
+ nvram_read_u16(prefix, NULL, "mcs5gpo2", &sprom->mcs5gpo[2], 0);
+ nvram_read_u16(prefix, NULL, "mcs5gpo3", &sprom->mcs5gpo[3], 0);
+ nvram_read_u16(prefix, NULL, "mcs5gpo4", &sprom->mcs5gpo[4], 0);
+ nvram_read_u16(prefix, NULL, "mcs5gpo5", &sprom->mcs5gpo[5], 0);
+ nvram_read_u16(prefix, NULL, "mcs5gpo6", &sprom->mcs5gpo[6], 0);
+ nvram_read_u16(prefix, NULL, "mcs5gpo7", &sprom->mcs5gpo[7], 0);
+ nvram_read_u16(prefix, NULL, "mcs5glpo0", &sprom->mcs5glpo[0], 0);
+ nvram_read_u16(prefix, NULL, "mcs5glpo1", &sprom->mcs5glpo[1], 0);
+ nvram_read_u16(prefix, NULL, "mcs5glpo2", &sprom->mcs5glpo[2], 0);
+ nvram_read_u16(prefix, NULL, "mcs5glpo3", &sprom->mcs5glpo[3], 0);
+ nvram_read_u16(prefix, NULL, "mcs5glpo4", &sprom->mcs5glpo[4], 0);
+ nvram_read_u16(prefix, NULL, "mcs5glpo5", &sprom->mcs5glpo[5], 0);
+ nvram_read_u16(prefix, NULL, "mcs5glpo6", &sprom->mcs5glpo[6], 0);
+ nvram_read_u16(prefix, NULL, "mcs5glpo7", &sprom->mcs5glpo[7], 0);
+ nvram_read_u16(prefix, NULL, "mcs5ghpo0", &sprom->mcs5ghpo[0], 0);
+ nvram_read_u16(prefix, NULL, "mcs5ghpo1", &sprom->mcs5ghpo[1], 0);
+ nvram_read_u16(prefix, NULL, "mcs5ghpo2", &sprom->mcs5ghpo[2], 0);
+ nvram_read_u16(prefix, NULL, "mcs5ghpo3", &sprom->mcs5ghpo[3], 0);
+ nvram_read_u16(prefix, NULL, "mcs5ghpo4", &sprom->mcs5ghpo[4], 0);
+ nvram_read_u16(prefix, NULL, "mcs5ghpo5", &sprom->mcs5ghpo[5], 0);
+ nvram_read_u16(prefix, NULL, "mcs5ghpo6", &sprom->mcs5ghpo[6], 0);
+ nvram_read_u16(prefix, NULL, "mcs5ghpo7", &sprom->mcs5ghpo[7], 0);
+}
+
+static void bcm47xx_fill_sprom_r45(struct ssb_sprom *sprom, const char *prefix)
+{
+ nvram_read_u8(prefix, NULL, "txpid2ga0", &sprom->txpid2g[0], 0);
+ nvram_read_u8(prefix, NULL, "txpid2ga1", &sprom->txpid2g[1], 0);
+ nvram_read_u8(prefix, NULL, "txpid2ga2", &sprom->txpid2g[2], 0);
+ nvram_read_u8(prefix, NULL, "txpid2ga3", &sprom->txpid2g[3], 0);
+ nvram_read_u8(prefix, NULL, "txpid5ga0", &sprom->txpid5g[0], 0);
+ nvram_read_u8(prefix, NULL, "txpid5ga1", &sprom->txpid5g[1], 0);
+ nvram_read_u8(prefix, NULL, "txpid5ga2", &sprom->txpid5g[2], 0);
+ nvram_read_u8(prefix, NULL, "txpid5ga3", &sprom->txpid5g[3], 0);
+ nvram_read_u8(prefix, NULL, "txpid5gla0", &sprom->txpid5gl[0], 0);
+ nvram_read_u8(prefix, NULL, "txpid5gla1", &sprom->txpid5gl[1], 0);
+ nvram_read_u8(prefix, NULL, "txpid5gla2", &sprom->txpid5gl[2], 0);
+ nvram_read_u8(prefix, NULL, "txpid5gla3", &sprom->txpid5gl[3], 0);
+ nvram_read_u8(prefix, NULL, "txpid5gha0", &sprom->txpid5gh[0], 0);
+ nvram_read_u8(prefix, NULL, "txpid5gha1", &sprom->txpid5gh[1], 0);
+ nvram_read_u8(prefix, NULL, "txpid5gha2", &sprom->txpid5gh[2], 0);
+ nvram_read_u8(prefix, NULL, "txpid5gha3", &sprom->txpid5gh[3], 0);
+}
+
+static void bcm47xx_fill_sprom_r89(struct ssb_sprom *sprom, const char *prefix)
+{
+ nvram_read_u8(prefix, NULL, "tssipos2g", &sprom->fem.ghz2.tssipos, 0);
+ nvram_read_u8(prefix, NULL, "extpagain2g",
+ &sprom->fem.ghz2.extpa_gain, 0);
+ nvram_read_u8(prefix, NULL, "pdetrange2g",
+ &sprom->fem.ghz2.pdet_range, 0);
+ nvram_read_u8(prefix, NULL, "triso2g", &sprom->fem.ghz2.tr_iso, 0);
+ nvram_read_u8(prefix, NULL, "antswctl2g", &sprom->fem.ghz2.antswlut, 0);
+ nvram_read_u8(prefix, NULL, "tssipos5g", &sprom->fem.ghz5.tssipos, 0);
+ nvram_read_u8(prefix, NULL, "extpagain5g",
+ &sprom->fem.ghz5.extpa_gain, 0);
+ nvram_read_u8(prefix, NULL, "pdetrange5g",
+ &sprom->fem.ghz5.pdet_range, 0);
+ nvram_read_u8(prefix, NULL, "triso5g", &sprom->fem.ghz5.tr_iso, 0);
+ nvram_read_u8(prefix, NULL, "antswctl5g", &sprom->fem.ghz5.antswlut, 0);
+ nvram_read_u8(prefix, NULL, "tempthresh", &sprom->tempthresh, 0);
+ nvram_read_u8(prefix, NULL, "tempoffset", &sprom->tempoffset, 0);
+ nvram_read_u16(prefix, NULL, "rawtempsense", &sprom->rawtempsense, 0);
+ nvram_read_u8(prefix, NULL, "measpower", &sprom->measpower, 0);
+ nvram_read_u8(prefix, NULL, "tempsense_slope",
+ &sprom->tempsense_slope, 0);
+ nvram_read_u8(prefix, NULL, "tempcorrx", &sprom->tempcorrx, 0);
+ nvram_read_u8(prefix, NULL, "tempsense_option",
+ &sprom->tempsense_option, 0);
+ nvram_read_u8(prefix, NULL, "freqoffset_corr",
+ &sprom->freqoffset_corr, 0);
+ nvram_read_u8(prefix, NULL, "iqcal_swp_dis", &sprom->iqcal_swp_dis, 0);
+ nvram_read_u8(prefix, NULL, "hw_iqcal_en", &sprom->hw_iqcal_en, 0);
+ nvram_read_u8(prefix, NULL, "elna2g", &sprom->elna2g, 0);
+ nvram_read_u8(prefix, NULL, "elna5g", &sprom->elna5g, 0);
+ nvram_read_u8(prefix, NULL, "phycal_tempdelta",
+ &sprom->phycal_tempdelta, 0);
+ nvram_read_u8(prefix, NULL, "temps_period", &sprom->temps_period, 0);
+ nvram_read_u8(prefix, NULL, "temps_hysteresis",
+ &sprom->temps_hysteresis, 0);
+ nvram_read_u8(prefix, NULL, "measpower1", &sprom->measpower1, 0);
+ nvram_read_u8(prefix, NULL, "measpower2", &sprom->measpower2, 0);
+ nvram_read_u8(prefix, NULL, "rxgainerr2ga0",
+ &sprom->rxgainerr2ga[0], 0);
+ nvram_read_u8(prefix, NULL, "rxgainerr2ga1",
+ &sprom->rxgainerr2ga[1], 0);
+ nvram_read_u8(prefix, NULL, "rxgainerr2ga2",
+ &sprom->rxgainerr2ga[2], 0);
+ nvram_read_u8(prefix, NULL, "rxgainerr5gla0",
+ &sprom->rxgainerr5gla[0], 0);
+ nvram_read_u8(prefix, NULL, "rxgainerr5gla1",
+ &sprom->rxgainerr5gla[1], 0);
+ nvram_read_u8(prefix, NULL, "rxgainerr5gla2",
+ &sprom->rxgainerr5gla[2], 0);
+ nvram_read_u8(prefix, NULL, "rxgainerr5gma0",
+ &sprom->rxgainerr5gma[0], 0);
+ nvram_read_u8(prefix, NULL, "rxgainerr5gma1",
+ &sprom->rxgainerr5gma[1], 0);
+ nvram_read_u8(prefix, NULL, "rxgainerr5gma2",
+ &sprom->rxgainerr5gma[2], 0);
+ nvram_read_u8(prefix, NULL, "rxgainerr5gha0",
+ &sprom->rxgainerr5gha[0], 0);
+ nvram_read_u8(prefix, NULL, "rxgainerr5gha1",
+ &sprom->rxgainerr5gha[1], 0);
+ nvram_read_u8(prefix, NULL, "rxgainerr5gha2",
+ &sprom->rxgainerr5gha[2], 0);
+ nvram_read_u8(prefix, NULL, "rxgainerr5gua0",
+ &sprom->rxgainerr5gua[0], 0);
+ nvram_read_u8(prefix, NULL, "rxgainerr5gua1",
+ &sprom->rxgainerr5gua[1], 0);
+ nvram_read_u8(prefix, NULL, "rxgainerr5gua2",
+ &sprom->rxgainerr5gua[2], 0);
+ nvram_read_u8(prefix, NULL, "noiselvl2ga0", &sprom->noiselvl2ga[0], 0);
+ nvram_read_u8(prefix, NULL, "noiselvl2ga1", &sprom->noiselvl2ga[1], 0);
+ nvram_read_u8(prefix, NULL, "noiselvl2ga2", &sprom->noiselvl2ga[2], 0);
+ nvram_read_u8(prefix, NULL, "noiselvl5gla0",
+ &sprom->noiselvl5gla[0], 0);
+ nvram_read_u8(prefix, NULL, "noiselvl5gla1",
+ &sprom->noiselvl5gla[1], 0);
+ nvram_read_u8(prefix, NULL, "noiselvl5gla2",
+ &sprom->noiselvl5gla[2], 0);
+ nvram_read_u8(prefix, NULL, "noiselvl5gma0",
+ &sprom->noiselvl5gma[0], 0);
+ nvram_read_u8(prefix, NULL, "noiselvl5gma1",
+ &sprom->noiselvl5gma[1], 0);
+ nvram_read_u8(prefix, NULL, "noiselvl5gma2",
+ &sprom->noiselvl5gma[2], 0);
+ nvram_read_u8(prefix, NULL, "noiselvl5gha0",
+ &sprom->noiselvl5gha[0], 0);
+ nvram_read_u8(prefix, NULL, "noiselvl5gha1",
+ &sprom->noiselvl5gha[1], 0);
+ nvram_read_u8(prefix, NULL, "noiselvl5gha2",
+ &sprom->noiselvl5gha[2], 0);
+ nvram_read_u8(prefix, NULL, "noiselvl5gua0",
+ &sprom->noiselvl5gua[0], 0);
+ nvram_read_u8(prefix, NULL, "noiselvl5gua1",
+ &sprom->noiselvl5gua[1], 0);
+ nvram_read_u8(prefix, NULL, "noiselvl5gua2",
+ &sprom->noiselvl5gua[2], 0);
+ nvram_read_u8(prefix, NULL, "pcieingress_war",
+ &sprom->pcieingress_war, 0);
+}
+
+static void bcm47xx_fill_sprom_r9(struct ssb_sprom *sprom, const char *prefix)
+{
+ nvram_read_u16(prefix, NULL, "cckbw202gpo", &sprom->cckbw202gpo, 0);
+ nvram_read_u16(prefix, NULL, "cckbw20ul2gpo", &sprom->cckbw20ul2gpo, 0);
+ nvram_read_u32(prefix, NULL, "legofdmbw202gpo",
+ &sprom->legofdmbw202gpo, 0);
+ nvram_read_u32(prefix, NULL, "legofdmbw20ul2gpo",
+ &sprom->legofdmbw20ul2gpo, 0);
+ nvram_read_u32(prefix, NULL, "legofdmbw205glpo",
+ &sprom->legofdmbw205glpo, 0);
+ nvram_read_u32(prefix, NULL, "legofdmbw20ul5glpo",
+ &sprom->legofdmbw20ul5glpo, 0);
+ nvram_read_u32(prefix, NULL, "legofdmbw205gmpo",
+ &sprom->legofdmbw205gmpo, 0);
+ nvram_read_u32(prefix, NULL, "legofdmbw20ul5gmpo",
+ &sprom->legofdmbw20ul5gmpo, 0);
+ nvram_read_u32(prefix, NULL, "legofdmbw205ghpo",
+ &sprom->legofdmbw205ghpo, 0);
+ nvram_read_u32(prefix, NULL, "legofdmbw20ul5ghpo",
+ &sprom->legofdmbw20ul5ghpo, 0);
+ nvram_read_u32(prefix, NULL, "mcsbw202gpo", &sprom->mcsbw202gpo, 0);
+ nvram_read_u32(prefix, NULL, "mcsbw20ul2gpo", &sprom->mcsbw20ul2gpo, 0);
+ nvram_read_u32(prefix, NULL, "mcsbw402gpo", &sprom->mcsbw402gpo, 0);
+ nvram_read_u32(prefix, NULL, "mcsbw205glpo", &sprom->mcsbw205glpo, 0);
+ nvram_read_u32(prefix, NULL, "mcsbw20ul5glpo",
+ &sprom->mcsbw20ul5glpo, 0);
+ nvram_read_u32(prefix, NULL, "mcsbw405glpo", &sprom->mcsbw405glpo, 0);
+ nvram_read_u32(prefix, NULL, "mcsbw205gmpo", &sprom->mcsbw205gmpo, 0);
+ nvram_read_u32(prefix, NULL, "mcsbw20ul5gmpo",
+ &sprom->mcsbw20ul5gmpo, 0);
+ nvram_read_u32(prefix, NULL, "mcsbw405gmpo", &sprom->mcsbw405gmpo, 0);
+ nvram_read_u32(prefix, NULL, "mcsbw205ghpo", &sprom->mcsbw205ghpo, 0);
+ nvram_read_u32(prefix, NULL, "mcsbw20ul5ghpo",
+ &sprom->mcsbw20ul5ghpo, 0);
+ nvram_read_u32(prefix, NULL, "mcsbw405ghpo", &sprom->mcsbw405ghpo, 0);
+ nvram_read_u16(prefix, NULL, "mcs32po", &sprom->mcs32po, 0);
+ nvram_read_u16(prefix, NULL, "legofdm40duppo",
+ &sprom->legofdm40duppo, 0);
+ nvram_read_u8(prefix, NULL, "sar2g", &sprom->sar2g, 0);
+ nvram_read_u8(prefix, NULL, "sar5g", &sprom->sar5g, 0);
+}
+
+static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,
+ const char *prefix)
+{
+ char postfix[2];
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
+ struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
+ snprintf(postfix, sizeof(postfix), "%i", i);
+ nvram_read_u8(prefix, postfix, "maxp2ga",
+ &pwr_info->maxpwr_2g, 0);
+ nvram_read_u8(prefix, postfix, "itt2ga",
+ &pwr_info->itssi_2g, 0);
+ nvram_read_u8(prefix, postfix, "itt5ga",
+ &pwr_info->itssi_5g, 0);
+ nvram_read_u16(prefix, postfix, "pa2gw0a",
+ &pwr_info->pa_2g[0], 0);
+ nvram_read_u16(prefix, postfix, "pa2gw1a",
+ &pwr_info->pa_2g[1], 0);
+ nvram_read_u16(prefix, postfix, "pa2gw2a",
+ &pwr_info->pa_2g[2], 0);
+ nvram_read_u8(prefix, postfix, "maxp5ga",
+ &pwr_info->maxpwr_5g, 0);
+ nvram_read_u8(prefix, postfix, "maxp5gha",
+ &pwr_info->maxpwr_5gh, 0);
+ nvram_read_u8(prefix, postfix, "maxp5gla",
+ &pwr_info->maxpwr_5gl, 0);
+ nvram_read_u16(prefix, postfix, "pa5gw0a",
+ &pwr_info->pa_5g[0], 0);
+ nvram_read_u16(prefix, postfix, "pa5gw1a",
+ &pwr_info->pa_5g[1], 0);
+ nvram_read_u16(prefix, postfix, "pa5gw2a",
+ &pwr_info->pa_5g[2], 0);
+ nvram_read_u16(prefix, postfix, "pa5glw0a",
+ &pwr_info->pa_5gl[0], 0);
+ nvram_read_u16(prefix, postfix, "pa5glw1a",
+ &pwr_info->pa_5gl[1], 0);
+ nvram_read_u16(prefix, postfix, "pa5glw2a",
+ &pwr_info->pa_5gl[2], 0);
+ nvram_read_u16(prefix, postfix, "pa5ghw0a",
+ &pwr_info->pa_5gh[0], 0);
+ nvram_read_u16(prefix, postfix, "pa5ghw1a",
+ &pwr_info->pa_5gh[1], 0);
+ nvram_read_u16(prefix, postfix, "pa5ghw2a",
+ &pwr_info->pa_5gh[2], 0);
+ }
+}
+
+static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
+ const char *prefix)
+{
+ char postfix[2];
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
+ struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
+ snprintf(postfix, sizeof(postfix), "%i", i);
+ nvram_read_u16(prefix, postfix, "pa2gw3a",
+ &pwr_info->pa_2g[3], 0);
+ nvram_read_u16(prefix, postfix, "pa5gw3a",
+ &pwr_info->pa_5g[3], 0);
+ nvram_read_u16(prefix, postfix, "pa5glw3a",
+ &pwr_info->pa_5gl[3], 0);
+ nvram_read_u16(prefix, postfix, "pa5ghw3a",
+ &pwr_info->pa_5gh[3], 0);
+ }
+}
+
+void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix)
+{
+ nvram_read_macaddr(prefix, "et0macaddr", &sprom->et0mac);
+ nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0);
+ nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0);
+
+ nvram_read_macaddr(prefix, "et1macaddr", &sprom->et1mac);
+ nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0);
+ nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0);
+
+ nvram_read_macaddr(prefix, "macaddr", &sprom->il0mac);
+ nvram_read_macaddr(prefix, "il0macaddr", &sprom->il0mac);
+}
+
+void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
+{
+ memset(sprom, 0, sizeof(struct ssb_sprom));
+
+ bcm47xx_fill_sprom_ethernet(sprom, prefix);
+
+ nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0);
+
+ switch (sprom->revision) {
+ case 1:
+ bcm47xx_fill_sprom_r1234589(sprom, prefix);
+ bcm47xx_fill_sprom_r12389(sprom, prefix);
+ bcm47xx_fill_sprom_r1(sprom, prefix);
+ break;
+ case 2:
+ bcm47xx_fill_sprom_r1234589(sprom, prefix);
+ bcm47xx_fill_sprom_r12389(sprom, prefix);
+ bcm47xx_fill_sprom_r2389(sprom, prefix);
+ bcm47xx_fill_sprom_r2(sprom, prefix);
+ break;
+ case 3:
+ bcm47xx_fill_sprom_r1234589(sprom, prefix);
+ bcm47xx_fill_sprom_r12389(sprom, prefix);
+ bcm47xx_fill_sprom_r2389(sprom, prefix);
+ bcm47xx_fill_sprom_r389(sprom, prefix);
+ bcm47xx_fill_sprom_r3(sprom, prefix);
+ break;
+ case 4:
+ case 5:
+ bcm47xx_fill_sprom_r1234589(sprom, prefix);
+ bcm47xx_fill_sprom_r4589(sprom, prefix);
+ bcm47xx_fill_sprom_r458(sprom, prefix);
+ bcm47xx_fill_sprom_r45(sprom, prefix);
+ bcm47xx_fill_sprom_path_r4589(sprom, prefix);
+ bcm47xx_fill_sprom_path_r45(sprom, prefix);
+ break;
+ case 8:
+ bcm47xx_fill_sprom_r1234589(sprom, prefix);
+ bcm47xx_fill_sprom_r12389(sprom, prefix);
+ bcm47xx_fill_sprom_r2389(sprom, prefix);
+ bcm47xx_fill_sprom_r389(sprom, prefix);
+ bcm47xx_fill_sprom_r4589(sprom, prefix);
+ bcm47xx_fill_sprom_r458(sprom, prefix);
+ bcm47xx_fill_sprom_r89(sprom, prefix);
+ bcm47xx_fill_sprom_path_r4589(sprom, prefix);
+ break;
+ case 9:
+ bcm47xx_fill_sprom_r1234589(sprom, prefix);
+ bcm47xx_fill_sprom_r12389(sprom, prefix);
+ bcm47xx_fill_sprom_r2389(sprom, prefix);
+ bcm47xx_fill_sprom_r389(sprom, prefix);
+ bcm47xx_fill_sprom_r4589(sprom, prefix);
+ bcm47xx_fill_sprom_r89(sprom, prefix);
+ bcm47xx_fill_sprom_r9(sprom, prefix);
+ bcm47xx_fill_sprom_path_r4589(sprom, prefix);
+ break;
+ default:
+ pr_warn("Unsupported SPROM revision %d detected. Will extract"
+ " v1\n", sprom->revision);
+ sprom->revision = 1;
+ bcm47xx_fill_sprom_r1234589(sprom, prefix);
+ bcm47xx_fill_sprom_r12389(sprom, prefix);
+ bcm47xx_fill_sprom_r1(sprom, prefix);
+ }
+}
diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
index de95e0723e2..5ecaf47b34d 100644
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
@@ -44,4 +44,7 @@ union bcm47xx_bus {
extern union bcm47xx_bus bcm47xx_bus;
extern enum bcm47xx_bus_type bcm47xx_bus_type;
+void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix);
+void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix);
+
#endif /* __ASM_BCM47XX_H */
diff --git a/arch/mips/include/asm/mach-bcm47xx/nvram.h b/arch/mips/include/asm/mach-bcm47xx/nvram.h
index 184d5ecb5f5..69ef3efe06e 100644
--- a/arch/mips/include/asm/mach-bcm47xx/nvram.h
+++ b/arch/mips/include/asm/mach-bcm47xx/nvram.h
@@ -37,7 +37,7 @@ struct nvram_header {
extern int nvram_getenv(char *name, char *val, size_t val_len);
-static inline void nvram_parse_macaddr(char *buf, u8 *macaddr)
+static inline void nvram_parse_macaddr(char *buf, u8 macaddr[6])
{
if (strchr(buf, ':'))
sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index 800163c8c2e..a058842f14f 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -80,6 +80,7 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
min_msk = 0x200D;
max_msk = 0xFFFF;
break;
+ case 0x4331:
case 43224:
case 43225:
break;
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index b8379b90d04..7e138ec2135 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -61,7 +61,7 @@ static struct bus_type bcma_bus_type = {
.dev_attrs = bcma_device_attrs,
};
-static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
+struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
{
struct bcma_device *core;
@@ -71,6 +71,7 @@ static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
}
return NULL;
}
+EXPORT_SYMBOL_GPL(bcma_find_core);
static void bcma_release_core_dev(struct device *dev)
{
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index ca7752510d5..cdcf75c0954 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -2,6 +2,8 @@
* Broadcom specific AMBA
* SPROM reading
*
+ * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
+ *
* Licensed under the GNU/GPL. See COPYING for details.
*/
@@ -14,6 +16,58 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
+static int(*get_fallback_sprom)(struct bcma_bus *dev, struct ssb_sprom *out);
+
+/**
+ * bcma_arch_register_fallback_sprom - Registers a method providing a
+ * fallback SPROM if no SPROM is found.
+ *
+ * @sprom_callback: The callback function.
+ *
+ * With this function the architecture implementation may register a
+ * callback handler which fills the SPROM data structure. The fallback is
+ * used for PCI based BCMA devices, where no valid SPROM can be found
+ * in the shadow registers and to provide the SPROM for SoCs where BCMA is
+ * to controll the system bus.
+ *
+ * This function is useful for weird architectures that have a half-assed
+ * BCMA device hardwired to their PCI bus.
+ *
+ * This function is available for architecture code, only. So it is not
+ * exported.
+ */
+int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus,
+ struct ssb_sprom *out))
+{
+ if (get_fallback_sprom)
+ return -EEXIST;
+ get_fallback_sprom = sprom_callback;
+
+ return 0;
+}
+
+static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus,
+ struct ssb_sprom *out)
+{
+ int err;
+
+ if (!get_fallback_sprom) {
+ err = -ENOENT;
+ goto fail;
+ }
+
+ err = get_fallback_sprom(bus, out);
+ if (err)
+ goto fail;
+
+ pr_debug("Using SPROM revision %d provided by"
+ " platform.\n", bus->sprom.revision);
+ return 0;
+fail:
+ pr_warn("Using fallback SPROM failed (err %d)\n", err);
+ return err;
+}
+
/**************************************************
* R/W ops.
**************************************************/
@@ -246,23 +300,128 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
SSB_SROM8_FEM_ANTSWLUT_SHIFT);
}
+/*
+ * Indicates the presence of external SPROM.
+ */
+static bool bcma_sprom_ext_available(struct bcma_bus *bus)
+{
+ u32 chip_status;
+ u32 srom_control;
+ u32 present_mask;
+
+ if (bus->drv_cc.core->id.rev >= 31) {
+ if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
+ return false;
+
+ srom_control = bcma_read32(bus->drv_cc.core,
+ BCMA_CC_SROM_CONTROL);
+ return srom_control & BCMA_CC_SROM_CONTROL_PRESENT;
+ }
+
+ /* older chipcommon revisions use chip status register */
+ chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
+ switch (bus->chipinfo.id) {
+ case 0x4313:
+ present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT;
+ break;
+
+ case 0x4331:
+ present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT;
+ break;
+
+ default:
+ return true;
+ }
+
+ return chip_status & present_mask;
+}
+
+/*
+ * Indicates that on-chip OTP memory is present and enabled.
+ */
+static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
+{
+ u32 chip_status;
+ u32 otpsize = 0;
+ bool present;
+
+ chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
+ switch (bus->chipinfo.id) {
+ case 0x4313:
+ present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT;
+ break;
+
+ case 0x4331:
+ present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT;
+ break;
+
+ case 43224:
+ case 43225:
+ /* for these chips OTP is always available */
+ present = true;
+ break;
+
+ default:
+ present = false;
+ break;
+ }
+
+ if (present) {
+ otpsize = bus->drv_cc.capabilities & BCMA_CC_CAP_OTPS;
+ otpsize >>= BCMA_CC_CAP_OTPS_SHIFT;
+ }
+
+ return otpsize != 0;
+}
+
+/*
+ * Verify OTP is filled and determine the byte
+ * offset where SPROM data is located.
+ *
+ * On error, returns 0; byte offset otherwise.
+ */
+static int bcma_sprom_onchip_offset(struct bcma_bus *bus)
+{
+ struct bcma_device *cc = bus->drv_cc.core;
+ u32 offset;
+
+ /* verify OTP status */
+ if ((bcma_read32(cc, BCMA_CC_OTPS) & BCMA_CC_OTPS_GU_PROG_HW) == 0)
+ return 0;
+
+ /* obtain bit offset from otplayout register */
+ offset = (bcma_read32(cc, BCMA_CC_OTPL) & BCMA_CC_OTPL_GURGN_OFFSET);
+ return BCMA_CC_SPROM + (offset >> 3);
+}
+
int bcma_sprom_get(struct bcma_bus *bus)
{
- u16 offset;
+ u16 offset = BCMA_CC_SPROM;
u16 *sprom;
- u32 sromctrl;
int err = 0;
if (!bus->drv_cc.core)
return -EOPNOTSUPP;
- if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
- return -ENOENT;
-
- if (bus->drv_cc.core->id.rev >= 32) {
- sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL);
- if (!(sromctrl & BCMA_CC_SROM_CONTROL_PRESENT))
- return -ENOENT;
+ if (!bcma_sprom_ext_available(bus)) {
+ /*
+ * External SPROM takes precedence so check
+ * on-chip OTP only when no external SPROM
+ * is present.
+ */
+ if (bcma_sprom_onchip_available(bus)) {
+ /* determine offset */
+ offset = bcma_sprom_onchip_offset(bus);
+ }
+ if (!offset) {
+ /*
+ * Maybe there is no SPROM on the device?
+ * Now we ask the arch code if there is some sprom
+ * available for this device in some other storage.
+ */
+ err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
+ return err;
+ }
}
sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
@@ -273,11 +432,6 @@ int bcma_sprom_get(struct bcma_bus *bus)
if (bus->chipinfo.id == 0x4331)
bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
- /* Most cards have SPROM moved by additional offset 0x30 (48 dwords).
- * According to brcm80211 this applies to cards with PCIe rev >= 6
- * TODO: understand this condition and use it */
- offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM :
- BCMA_CC_SPROM_PCIE6;
pr_debug("SPROM offset 0x%x\n", offset);
bcma_sprom_read(bus, offset, sprom);
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 1c008c61b95..ddc061dd150 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -1869,7 +1869,7 @@ static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock)
static void try_auto_wep(struct airo_info *ai)
{
- if (auto_wep && !(ai->flags & FLAG_RADIO_DOWN)) {
+ if (auto_wep && !test_bit(FLAG_RADIO_DOWN, &ai->flags)) {
ai->expires = RUN_AT(3*HZ);
wake_up_interruptible(&ai->thr_wait);
}
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 6640326f700..8d434b8f585 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1320,6 +1320,7 @@ struct ath5k_hw {
struct ieee80211_vif *bslot[ATH_BCBUF];
u16 num_ap_vifs;
u16 num_adhoc_vifs;
+ u16 num_mesh_vifs;
unsigned int bhalq, /* SW q for outgoing beacons */
bmisscount, /* missed beacon transmits */
bintval, /* beacon interval in TU */
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index a339693fbe2..0e643b016b3 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -1867,7 +1867,8 @@ ath5k_beacon_send(struct ath5k_hw *ah)
ah->bmisscount = 0;
}
- if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) ||
+ if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +
+ ah->num_mesh_vifs > 1) ||
ah->opmode == NL80211_IFTYPE_MESH_POINT) {
u64 tsf = ath5k_hw_get_tsf64(ah);
u32 tsftu = TSF_TO_TU(tsf);
@@ -1952,7 +1953,8 @@ ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf)
u64 hw_tsf;
intval = ah->bintval & AR5K_BEACON_PERIOD;
- if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) {
+ if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs
+ + ah->num_mesh_vifs > 1) {
intval /= ATH_BCBUF; /* staggered multi-bss beacons */
if (intval < 15)
ATH5K_WARN(ah, "intval %u is too low, min 15\n",
@@ -2330,15 +2332,6 @@ ath5k_calibrate_work(struct work_struct *work)
"got new rfgain, resetting\n");
ieee80211_queue_work(ah->hw, &ah->reset_work);
}
-
- /* TODO: On full calibration we should stop TX here,
- * so that it doesn't interfere (mostly due to gain_f
- * calibration that messes with tx packets -see phy.c).
- *
- * NOTE: Stopping the queues from above is not enough
- * to stop TX but saves us from disconecting (at least
- * we don't lose packets). */
- ieee80211_stop_queues(ah->hw);
} else
ah->ah_cal_mask |= AR5K_CALIBRATION_SHORT;
@@ -2353,10 +2346,9 @@ ath5k_calibrate_work(struct work_struct *work)
ah->curchan->center_freq));
/* Clear calibration flags */
- if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL) {
- ieee80211_wake_queues(ah->hw);
+ if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL)
ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL;
- } else if (ah->ah_cal_mask & AR5K_CALIBRATION_SHORT)
+ else if (ah->ah_cal_mask & AR5K_CALIBRATION_SHORT)
ah->ah_cal_mask &= ~AR5K_CALIBRATION_SHORT;
}
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index af4c7ecb4b3..5c532995541 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -134,6 +134,8 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
ah->num_ap_vifs++;
else if (avf->opmode == NL80211_IFTYPE_ADHOC)
ah->num_adhoc_vifs++;
+ else if (avf->opmode == NL80211_IFTYPE_MESH_POINT)
+ ah->num_mesh_vifs++;
}
/* Any MAC address is fine, all others are included through the
@@ -175,6 +177,8 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
ah->num_ap_vifs--;
else if (avf->opmode == NL80211_IFTYPE_ADHOC)
ah->num_adhoc_vifs--;
+ else if (avf->opmode == NL80211_IFTYPE_MESH_POINT)
+ ah->num_mesh_vifs--;
ath5k_update_bssid_mask_and_opmode(ah, NULL);
mutex_unlock(&ah->lock);
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index e1f8613426a..3a2845489a1 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -1871,31 +1871,15 @@ ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
ret = 0;
}
- /* On full calibration do an AGC calibration and
- * request a PAPD probe for gainf calibration if
- * needed */
- if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL) {
-
- AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
- AR5K_PHY_AGCCTL_CAL);
-
- ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
- AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF,
- 0, false);
- if (ret) {
- ATH5K_ERR(ah,
- "gain calibration timeout (%uMHz)\n",
- channel->center_freq);
- }
-
- if ((ah->ah_radio == AR5K_RF5111 ||
- ah->ah_radio == AR5K_RF5112)
- && (channel->hw_value != AR5K_MODE_11B))
- ath5k_hw_request_rfgain_probe(ah);
- }
-
- /* Update noise floor
- * XXX: Only do this after AGC calibration */
+ /* On full calibration request a PAPD probe for
+ * gainf calibration if needed */
+ if ((ah->ah_cal_mask & AR5K_CALIBRATION_FULL) &&
+ (ah->ah_radio == AR5K_RF5111 ||
+ ah->ah_radio == AR5K_RF5112) &&
+ channel->hw_value != AR5K_MODE_11B)
+ ath5k_hw_request_rfgain_probe(ah);
+
+ /* Update noise floor */
if (!(ah->ah_cal_mask & AR5K_CALIBRATION_NF))
ath5k_hw_update_noise_floor(ah);
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 18fa9aa8af9..97abf4699b4 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -556,7 +556,8 @@ static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len,
dlen, freq, vif->probe_req_report);
if (vif->probe_req_report || vif->nw_type == AP_NETWORK)
- cfg80211_rx_mgmt(vif->ndev, freq, ev->data, dlen, GFP_ATOMIC);
+ cfg80211_rx_mgmt(vif->ndev, freq, 0,
+ ev->data, dlen, GFP_ATOMIC);
return 0;
}
@@ -595,7 +596,8 @@ static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len,
return -EINVAL;
}
ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq);
- cfg80211_rx_mgmt(vif->ndev, freq, ev->data, dlen, GFP_ATOMIC);
+ cfg80211_rx_mgmt(vif->ndev, freq, 0,
+ ev->data, dlen, GFP_ATOMIC);
return 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 595a272aa96..e507e78398f 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -81,6 +81,14 @@ config ATH9K_DFS_CERTIFIED
developed. At this point enabling this option won't do anything
except increase code size.
+config ATH9K_MAC_DEBUG
+ bool "Atheros MAC statistics"
+ depends on ATH9K_DEBUGFS
+ default y
+ ---help---
+ This option enables collection of statistics for Rx/Tx status
+ data and some other MAC related statistics
+
config ATH9K_RATE_CONTROL
bool "Atheros ath9k rate control"
depends on ATH9K
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 8d1bca03bc0..a66a13b7684 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -326,7 +326,6 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts)
{
- struct ar9003_txc *txc = (struct ar9003_txc *) ds;
struct ar9003_txs *ads;
u32 status;
@@ -336,11 +335,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
if ((status & AR_TxDone) == 0)
return -EINPROGRESS;
- ts->qid = MS(ads->ds_info, AR_TxQcuNum);
- if (!txc || (MS(txc->info, AR_TxQcuNum) == ts->qid))
- ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
- else
- return -ENOENT;
+ ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
(MS(ads->ds_info, AR_TxRxDesc) != 1)) {
@@ -354,6 +349,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
ts->ts_seqnum = MS(status, AR_SeqNum);
ts->tid = MS(status, AR_TxTid);
+ ts->qid = MS(ads->ds_info, AR_TxQcuNum);
ts->desc_id = MS(ads->status1, AR_TxDescId);
ts->ts_tstamp = ads->status4;
ts->ts_status = 0;
@@ -440,20 +436,14 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
struct ar9003_rxs *rxsp = (struct ar9003_rxs *) buf_addr;
unsigned int phyerr;
- /* TODO: byte swap on big endian for ar9300_10 */
-
- if (!rxs) {
- if ((rxsp->status11 & AR_RxDone) == 0)
- return -EINPROGRESS;
-
- if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
- return -EINVAL;
+ if ((rxsp->status11 & AR_RxDone) == 0)
+ return -EINPROGRESS;
- if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
- return -EINPROGRESS;
+ if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
+ return -EINVAL;
- return 0;
- }
+ if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
+ return -EINPROGRESS;
rxs->rs_status = 0;
rxs->rs_flags = 0;
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index c2ccba676ec..3d8e51cd5d8 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -299,7 +299,6 @@ struct ath_tx {
struct ath_rx_edma {
struct sk_buff_head rx_fifo;
- struct sk_buff_head rx_buffers;
u32 rx_fifo_hwsize;
};
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index b8967e482e6..43882f9e25c 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -91,7 +91,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
info.txpower = MAX_RATE_POWER;
info.keyix = ATH9K_TXKEYIX_INVALID;
info.keytype = ATH9K_KEY_TYPE_CLEAR;
- info.flags = ATH9K_TXDESC_NOACK;
+ info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_INTREQ;
info.buf_addr[0] = bf->bf_buf_addr;
info.buf_len[0] = roundup(skb->len, 4);
@@ -355,7 +355,6 @@ void ath_beacon_tasklet(unsigned long data)
struct ath_common *common = ath9k_hw_common(ah);
struct ath_buf *bf = NULL;
struct ieee80211_vif *vif;
- struct ath_tx_status ts;
bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
int slot;
u32 bfaddr, bc = 0;
@@ -462,11 +461,6 @@ void ath_beacon_tasklet(unsigned long data)
ath9k_hw_txstart(ah, sc->beacon.beaconq);
sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */
- if (edma) {
- spin_lock_bh(&sc->sc_pcu_lock);
- ath9k_hw_txprocdesc(ah, bf->bf_desc, (void *)&ts);
- spin_unlock_bh(&sc->sc_pcu_lock);
- }
}
}
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 228c18189a3..c2edf688da4 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -818,6 +818,7 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
TX_STAT_INC(qnum, delim_underrun);
+#ifdef CONFIG_ATH9K_MAC_DEBUG
spin_lock(&sc->debug.samp_lock);
TX_SAMP_DBG(jiffies) = jiffies;
TX_SAMP_DBG(rssi_ctl0) = ts->ts_rssi_ctl0;
@@ -844,6 +845,7 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES;
spin_unlock(&sc->debug.samp_lock);
+#endif
#undef TX_SAMP_DBG
}
@@ -942,27 +944,6 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL);
len += snprintf(buf + len, size - len,
- "%22s : %10d\n", "RSSI-CTL0",
- sc->debug.stats.rxstats.rs_rssi_ctl0);
- len += snprintf(buf + len, size - len,
- "%22s : %10d\n", "RSSI-CTL1",
- sc->debug.stats.rxstats.rs_rssi_ctl1);
- len += snprintf(buf + len, size - len,
- "%22s : %10d\n", "RSSI-CTL2",
- sc->debug.stats.rxstats.rs_rssi_ctl2);
- len += snprintf(buf + len, size - len,
- "%22s : %10d\n", "RSSI-EXT0",
- sc->debug.stats.rxstats.rs_rssi_ext0);
- len += snprintf(buf + len, size - len,
- "%22s : %10d\n", "RSSI-EXT1",
- sc->debug.stats.rxstats.rs_rssi_ext1);
- len += snprintf(buf + len, size - len,
- "%22s : %10d\n", "RSSI-EXT2",
- sc->debug.stats.rxstats.rs_rssi_ext2);
- len += snprintf(buf + len, size - len,
- "%22s : %10d\n", "Rx Antenna",
- sc->debug.stats.rxstats.rs_antenna);
- len += snprintf(buf + len, size - len,
"%22s : %10u\n", "RX-Pkts-All",
sc->debug.stats.rxstats.rx_pkts_all);
len += snprintf(buf + len, size - len,
@@ -1009,16 +990,7 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
RX_PHY_ERR_INC(rs->rs_phyerr);
}
- sc->debug.stats.rxstats.rs_rssi_ctl0 = rs->rs_rssi_ctl0;
- sc->debug.stats.rxstats.rs_rssi_ctl1 = rs->rs_rssi_ctl1;
- sc->debug.stats.rxstats.rs_rssi_ctl2 = rs->rs_rssi_ctl2;
-
- sc->debug.stats.rxstats.rs_rssi_ext0 = rs->rs_rssi_ext0;
- sc->debug.stats.rxstats.rs_rssi_ext1 = rs->rs_rssi_ext1;
- sc->debug.stats.rxstats.rs_rssi_ext2 = rs->rs_rssi_ext2;
-
- sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna;
-
+#ifdef CONFIG_ATH9K_MAC_DEBUG
spin_lock(&sc->debug.samp_lock);
RX_SAMP_DBG(jiffies) = jiffies;
RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0;
@@ -1035,6 +1007,8 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
sc->debug.rsidx = (sc->debug.rsidx + 1) % ATH_DBG_MAX_SAMPLES;
spin_unlock(&sc->debug.samp_lock);
+#endif
+
#undef RX_STAT_INC
#undef RX_PHY_ERR_INC
#undef RX_SAMP_DBG
@@ -1278,6 +1252,8 @@ static const struct file_operations fops_modal_eeprom = {
.llseek = default_llseek,
};
+#ifdef CONFIG_ATH9K_MAC_DEBUG
+
void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
{
#define ATH_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].c)
@@ -1551,6 +1527,7 @@ static const struct file_operations fops_samps = {
.llseek = default_llseek,
};
+#endif
int ath9k_init_debug(struct ath_hw *ah)
{
@@ -1604,8 +1581,10 @@ int ath9k_init_debug(struct ath_hw *ah)
&fops_base_eeprom);
debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_modal_eeprom);
+#ifdef CONFIG_ATH9K_MAC_DEBUG
debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_samps);
+#endif
debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 776a24ada60..64fcfad467b 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -165,13 +165,6 @@ struct ath_rx_stats {
u32 post_delim_crc_err;
u32 decrypt_busy_err;
u32 phy_err_stats[ATH9K_PHYERR_MAX];
- int8_t rs_rssi_ctl0;
- int8_t rs_rssi_ctl1;
- int8_t rs_rssi_ctl2;
- int8_t rs_rssi_ext0;
- int8_t rs_rssi_ext1;
- int8_t rs_rssi_ext2;
- u8 rs_antenna;
};
enum ath_reset_type {
@@ -235,16 +228,17 @@ struct ath9k_debug {
struct dentry *debugfs_phy;
u32 regidx;
struct ath_stats stats;
+#ifdef CONFIG_ATH9K_MAC_DEBUG
spinlock_t samp_lock;
struct ath_dbg_bb_mac_samp bb_mac_samp[ATH_DBG_MAX_SAMPLES];
u8 sampidx;
u8 tsidx;
u8 rsidx;
+#endif
};
int ath9k_init_debug(struct ath_hw *ah);
-void ath9k_debug_samp_bb_mac(struct ath_softc *sc);
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, struct ath_txq *txq,
@@ -258,10 +252,6 @@ static inline int ath9k_init_debug(struct ath_hw *ah)
return 0;
}
-static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
-{
-}
-
static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
enum ath9k_int status)
{
@@ -282,4 +272,17 @@ static inline void ath_debug_stat_rx(struct ath_softc *sc,
#endif /* CONFIG_ATH9K_DEBUGFS */
+#ifdef CONFIG_ATH9K_MAC_DEBUG
+
+void ath9k_debug_samp_bb_mac(struct ath_softc *sc);
+
+#else
+
+static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
+{
+}
+
+#endif
+
+
#endif /* DEBUG_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 5c57568c64d..2eb0ef315e3 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1386,10 +1386,16 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
static bool ath9k_hw_chip_reset(struct ath_hw *ah,
struct ath9k_channel *chan)
{
- if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) {
- if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
- return false;
- } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
+ int reset_type = ATH9K_RESET_WARM;
+
+ if (AR_SREV_9280(ah)) {
+ if (ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+ reset_type = ATH9K_RESET_POWER_ON;
+ else
+ reset_type = ATH9K_RESET_COLD;
+ }
+
+ if (!ath9k_hw_set_reset_reg(ah, reset_type))
return false;
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index d8b05961f7e..944e9b518f1 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -555,9 +555,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
mutex_init(&sc->mutex);
#ifdef CONFIG_ATH9K_DEBUGFS
spin_lock_init(&sc->nodes_lock);
- spin_lock_init(&sc->debug.samp_lock);
INIT_LIST_HEAD(&sc->nodes);
#endif
+#ifdef CONFIG_ATH9K_MAC_DEBUG
+ spin_lock_init(&sc->debug.samp_lock);
+#endif
tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
(unsigned long)sc);
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index e196aba77ac..5f4ae6c9a93 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -745,7 +745,11 @@ int ath9k_hw_beaconq_setup(struct ath_hw *ah)
qi.tqi_aifs = 1;
qi.tqi_cwmin = 0;
qi.tqi_cwmax = 0;
- /* NB: don't enable any interrupts */
+
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+ qi.tqi_qflags = TXQ_FLAG_TXOKINT_ENABLE |
+ TXQ_FLAG_TXERRINT_ENABLE;
+
return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
}
EXPORT_SYMBOL(ath9k_hw_beaconq_setup);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 02e95c8e746..cc2535c38be 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -2300,6 +2300,7 @@ static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
struct ath_vif *avp;
struct ath_buf *bf;
struct ath_tx_status ts;
+ bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
int status;
vif = sc->beacon.bslot[0];
@@ -2310,7 +2311,7 @@ static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
if (!avp->is_bslot_active)
return 0;
- if (!sc->beacon.tx_processed) {
+ if (!sc->beacon.tx_processed && !edma) {
tasklet_disable(&sc->bcon_tasklet);
bf = avp->av_bcbuf;
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index b8c6c38cbb9..6407af22f7b 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -1226,7 +1226,7 @@ static void ath_rc_init(struct ath_softc *sc,
ath_rc_init_valid_rate_idx(ath_rc_priv);
for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
- for (j = 0; j < MAX_TX_RATE_PHY; j++)
+ for (j = 0; j < RATE_TABLE_SIZE; j++)
ath_rc_priv->valid_phy_rateidx[i][j] = 0;
ath_rc_priv->valid_phy_ratecnt[i] = 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
index b7a4bcd3eec..75f8e9b06b2 100644
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ b/drivers/net/wireless/ath/ath9k/rc.h
@@ -25,8 +25,6 @@ struct ath_softc;
#define ATH_RATE_MAX 30
#define RATE_TABLE_SIZE 72
-#define MAX_TX_RATE_PHY 48
-
#define RC_INVALID 0x0000
#define RC_LEGACY 0x0001
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 7e1a91af149..1b1b279c304 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -169,22 +169,17 @@ static void ath_rx_addbuffer_edma(struct ath_softc *sc,
enum ath9k_rx_qtype qtype, int size)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- u32 nbuf = 0;
+ struct ath_buf *bf, *tbf;
if (list_empty(&sc->rx.rxbuf)) {
ath_dbg(common, QUEUE, "No free rx buf available\n");
return;
}
- while (!list_empty(&sc->rx.rxbuf)) {
- nbuf++;
-
+ list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list)
if (!ath_rx_edma_buf_link(sc, qtype))
break;
- if (nbuf >= size)
- break;
- }
}
static void ath_rx_remove_buffer(struct ath_softc *sc,
@@ -232,7 +227,6 @@ static void ath_rx_edma_cleanup(struct ath_softc *sc)
static void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size)
{
skb_queue_head_init(&rx_edma->rx_fifo);
- skb_queue_head_init(&rx_edma->rx_buffers);
rx_edma->rx_fifo_hwsize = size;
}
@@ -658,7 +652,9 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon)
}
static bool ath_edma_get_buffers(struct ath_softc *sc,
- enum ath9k_rx_qtype qtype)
+ enum ath9k_rx_qtype qtype,
+ struct ath_rx_status *rs,
+ struct ath_buf **dest)
{
struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype];
struct ath_hw *ah = sc->sc_ah;
@@ -677,7 +673,7 @@ static bool ath_edma_get_buffers(struct ath_softc *sc,
dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
common->rx_bufsize, DMA_FROM_DEVICE);
- ret = ath9k_hw_process_rxdesc_edma(ah, NULL, skb->data);
+ ret = ath9k_hw_process_rxdesc_edma(ah, rs, skb->data);
if (ret == -EINPROGRESS) {
/*let device gain the buffer again*/
dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
@@ -690,20 +686,21 @@ static bool ath_edma_get_buffers(struct ath_softc *sc,
/* corrupt descriptor, skip this one and the following one */
list_add_tail(&bf->list, &sc->rx.rxbuf);
ath_rx_edma_buf_link(sc, qtype);
- skb = skb_peek(&rx_edma->rx_fifo);
- if (!skb)
- return true;
- bf = SKB_CB_ATHBUF(skb);
- BUG_ON(!bf);
+ skb = skb_peek(&rx_edma->rx_fifo);
+ if (skb) {
+ bf = SKB_CB_ATHBUF(skb);
+ BUG_ON(!bf);
- __skb_unlink(skb, &rx_edma->rx_fifo);
- list_add_tail(&bf->list, &sc->rx.rxbuf);
- ath_rx_edma_buf_link(sc, qtype);
- return true;
+ __skb_unlink(skb, &rx_edma->rx_fifo);
+ list_add_tail(&bf->list, &sc->rx.rxbuf);
+ ath_rx_edma_buf_link(sc, qtype);
+ } else {
+ bf = NULL;
+ }
}
- skb_queue_tail(&rx_edma->rx_buffers, skb);
+ *dest = bf;
return true;
}
@@ -711,18 +708,15 @@ static struct ath_buf *ath_edma_get_next_rx_buf(struct ath_softc *sc,
struct ath_rx_status *rs,
enum ath9k_rx_qtype qtype)
{
- struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype];
- struct sk_buff *skb;
- struct ath_buf *bf;
+ struct ath_buf *bf = NULL;
- while (ath_edma_get_buffers(sc, qtype));
- skb = __skb_dequeue(&rx_edma->rx_buffers);
- if (!skb)
- return NULL;
+ while (ath_edma_get_buffers(sc, qtype, rs, &bf)) {
+ if (!bf)
+ continue;
- bf = SKB_CB_ATHBUF(skb);
- ath9k_hw_process_rxdesc_edma(sc->sc_ah, rs, skb->data);
- return bf;
+ return bf;
+ }
+ return NULL;
}
static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
@@ -954,6 +948,7 @@ static void ath9k_process_rssi(struct ath_common *common,
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = common->ah;
int last_rssi;
+ int rssi = rx_stats->rs_rssi;
if (!rx_stats->is_mybeacon ||
((ah->opmode != NL80211_IFTYPE_STATION) &&
@@ -965,13 +960,12 @@ static void ath9k_process_rssi(struct ath_common *common,
last_rssi = sc->last_rssi;
if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
- rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
- ATH_RSSI_EP_MULTIPLIER);
- if (rx_stats->rs_rssi < 0)
- rx_stats->rs_rssi = 0;
+ rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
+ if (rssi < 0)
+ rssi = 0;
/* Update Beacon RSSI, this is used by ANI. */
- ah->stats.avgbrssi = rx_stats->rs_rssi;
+ ah->stats.avgbrssi = rssi;
}
/*
@@ -1011,6 +1005,8 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
rx_status->signal = ah->noise + rx_stats->rs_rssi;
rx_status->antenna = rx_stats->rs_antenna;
rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+ if (rx_stats->rs_moreaggr)
+ rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
return 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 5dd27d2712f..9f785015a7d 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -2296,9 +2296,12 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
break;
}
- /* Skip beacon completions */
- if (ts.qid == sc->beacon.beaconq)
+ /* Process beacon completions separately */
+ if (ts.qid == sc->beacon.beaconq) {
+ sc->beacon.tx_processed = true;
+ sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK);
continue;
+ }
txq = &sc->tx.txq[ts.qid];
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 5189cf38123..1d633f3b327 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -2706,6 +2706,8 @@ static int b43_gpio_init(struct b43_wldev *dev)
mask |= 0x0060;
set |= 0x0060;
}
+ if (dev->dev->chip_id == 0x5354)
+ set &= 0xff02;
if (0 /* FIXME: conditional unknown */ ) {
b43_write16(dev, B43_MMIO_GPIO_MASK,
b43_read16(dev, B43_MMIO_GPIO_MASK)
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c
index 96faaef3661..950334197f4 100644
--- a/drivers/net/wireless/b43legacy/phy.c
+++ b/drivers/net/wireless/b43legacy/phy.c
@@ -1860,7 +1860,7 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
* which accounts for the factor of 4 */
#define REG_MAX_PWR 20
max_pwr = min(REG_MAX_PWR * 4
- - dev->dev->bus->sprom.antenna_gain.ghz24.a0
+ - dev->dev->bus->sprom.antenna_gain.a0
- 0x6, max_pwr);
/* find the desired power in Q5.2 - power_level is in dBm
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 83ca3cc2ccc..4688904908e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -604,7 +604,7 @@ void brcmf_sdio_exit(void)
sdio_unregister_driver(&brcmf_sdmmc_driver);
}
-int brcmf_sdio_init(void)
+void brcmf_sdio_init(void)
{
int ret;
@@ -614,6 +614,4 @@ int brcmf_sdio_init(void)
if (ret)
brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret);
-
- return ret;
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index b7671b30692..366916494be 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -108,11 +108,11 @@ extern int brcmf_add_if(struct device *dev, int ifidx,
#ifdef CONFIG_BRCMFMAC_SDIO
extern void brcmf_sdio_exit(void);
-extern int brcmf_sdio_init(void);
+extern void brcmf_sdio_init(void);
#endif
#ifdef CONFIG_BRCMFMAC_USB
extern void brcmf_usb_exit(void);
-extern int brcmf_usb_init(void);
+extern void brcmf_usb_init(void);
#endif
#endif /* _BRCMF_BUS_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index c4da0581744..2a1e5ae0c40 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -1181,27 +1181,29 @@ exit:
}
#endif /* DEBUG */
-static int __init brcmfmac_init(void)
+static void brcmf_driver_init(struct work_struct *work)
{
- int ret = 0;
-
#ifdef CONFIG_BRCMFMAC_SDIO
- ret = brcmf_sdio_init();
- if (ret)
- goto fail;
+ brcmf_sdio_init();
#endif
#ifdef CONFIG_BRCMFMAC_USB
- ret = brcmf_usb_init();
- if (ret)
- goto fail;
+ brcmf_usb_init();
#endif
+}
+static DECLARE_WORK(brcmf_driver_work, brcmf_driver_init);
-fail:
- return ret;
+static int __init brcmfmac_module_init(void)
+{
+ if (!schedule_work(&brcmf_driver_work))
+ return -EBUSY;
+
+ return 0;
}
-static void __exit brcmfmac_exit(void)
+static void __exit brcmfmac_module_exit(void)
{
+ cancel_work_sync(&brcmf_driver_work);
+
#ifdef CONFIG_BRCMFMAC_SDIO
brcmf_sdio_exit();
#endif
@@ -1210,5 +1212,5 @@ static void __exit brcmfmac_exit(void)
#endif
}
-module_init(brcmfmac_init);
-module_exit(brcmfmac_exit);
+module_init(brcmfmac_module_init);
+module_exit(brcmfmac_module_exit);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index d4a9e8e7deb..82364223e81 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -514,9 +514,9 @@ static void brcmf_usb_tx_complete(struct urb *urb)
brcmf_usb_del_fromq(devinfo, req);
if (urb->status == 0)
- devinfo->bus_pub.stats.tx_packets++;
+ devinfo->bus_pub.bus->dstats.tx_packets++;
else
- devinfo->bus_pub.stats.tx_errors++;
+ devinfo->bus_pub.bus->dstats.tx_errors++;
dev_kfree_skb(req->skb);
req->skb = NULL;
@@ -536,9 +536,9 @@ static void brcmf_usb_rx_complete(struct urb *urb)
req->skb = NULL;
if (urb->status == 0) {
- devinfo->bus_pub.stats.rx_packets++;
+ devinfo->bus_pub.bus->dstats.rx_packets++;
} else {
- devinfo->bus_pub.stats.rx_errors++;
+ devinfo->bus_pub.bus->dstats.rx_errors++;
dev_kfree_skb(skb);
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
return;
@@ -712,9 +712,6 @@ static int brcmf_usb_up(struct device *dev)
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
u16 ifnum;
- if (devinfo == NULL)
- return -EINVAL;
-
if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
return 0;
@@ -900,8 +897,8 @@ brcmf_usb_dlneeded(struct brcmf_usbdev_info *devinfo)
sizeof(struct bootrom_id_le));
return false;
} else {
- devinfo->bus_pub.attrib.devid = chipid;
- devinfo->bus_pub.attrib.chiprev = chiprev;
+ devinfo->bus_pub.devid = chipid;
+ devinfo->bus_pub.chiprev = chiprev;
}
return true;
}
@@ -1067,7 +1064,7 @@ static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len)
if (devinfo == NULL)
return -EINVAL;
- if (devinfo->bus_pub.attrib.devid == 0xDEAD)
+ if (devinfo->bus_pub.devid == 0xDEAD)
return -EINVAL;
err = brcmf_usb_dl_writeimage(devinfo, fw, len);
@@ -1088,7 +1085,7 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
if (!devinfo)
return -EINVAL;
- if (devinfo->bus_pub.attrib.devid == 0xDEAD)
+ if (devinfo->bus_pub.devid == 0xDEAD)
return -EINVAL;
/* Check we are runnable */
@@ -1127,18 +1124,19 @@ static bool brcmf_usb_chip_support(int chipid, int chiprev)
static int
brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
{
- struct brcmf_usb_attrib *attr;
+ int devid, chiprev;
int err;
brcmf_dbg(TRACE, "enter\n");
if (devinfo == NULL)
return -ENODEV;
- attr = &devinfo->bus_pub.attrib;
+ devid = devinfo->bus_pub.devid;
+ chiprev = devinfo->bus_pub.chiprev;
- if (!brcmf_usb_chip_support(attr->devid, attr->chiprev)) {
+ if (!brcmf_usb_chip_support(devid, chiprev)) {
brcmf_dbg(ERROR, "unsupported chip %d rev %d\n",
- attr->devid, attr->chiprev);
+ devid, chiprev);
return -EINVAL;
}
@@ -1617,7 +1615,7 @@ void brcmf_usb_exit(void)
g_image.len = 0;
}
-int brcmf_usb_init(void)
+void brcmf_usb_init(void)
{
- return usb_register(&brcmf_usbdrvr);
+ usb_register(&brcmf_usbdrvr);
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.h b/drivers/net/wireless/brcm80211/brcmfmac/usb.h
index b31da7b83ff..acfa5e89872 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.h
@@ -33,36 +33,12 @@ enum brcmf_usb_pnp_state {
};
struct brcmf_stats {
- u32 tx_errors;
- u32 tx_packets;
- u32 tx_multicast;
u32 tx_ctlpkts;
u32 tx_ctlerrs;
- u32 tx_dropped;
- u32 tx_flushed;
- u32 rx_errors;
- u32 rx_packets;
- u32 rx_multicast;
u32 rx_ctlpkts;
u32 rx_ctlerrs;
- u32 rx_dropped;
- u32 rx_flushed;
-
-};
-
-struct brcmf_usb_attrib {
- int bustype;
- int vid;
- int pid;
- int devid;
- int chiprev; /* chip revsion number */
- int mtu;
- int nchan; /* Data Channels */
- int has_2nd_bulk_in_ep;
};
-struct brcmf_usbdev_info;
-
struct brcmf_usbdev {
struct brcmf_bus *bus;
struct brcmf_usbdev_info *devinfo;
@@ -70,7 +46,8 @@ struct brcmf_usbdev {
struct brcmf_stats stats;
int ntxq, nrxq, rxsize;
u32 bus_mtu;
- struct brcmf_usb_attrib attrib;
+ int devid;
+ int chiprev; /* chip revsion number */
};
/* IO Request Block (IRB) */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
index dbee69620a9..95b5902bc4b 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
@@ -959,14 +959,13 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
if (supr_status) {
update_rate = false;
if (supr_status == TX_STATUS_SUPR_BADCH) {
- wiphy_err(wiphy, "%s: Pkt tx suppressed, "
- "illegal channel possibly %d\n",
+ wiphy_err(wiphy,
+ "%s: Pkt tx suppressed, illegal channel possibly %d\n",
__func__, CHSPEC_CHANNEL(
wlc->default_bss->chanspec));
} else {
if (supr_status != TX_STATUS_SUPR_FRAG)
- wiphy_err(wiphy, "%s:"
- "supr_status 0x%x\n",
+ wiphy_err(wiphy, "%s: supr_status 0x%x\n",
__func__, supr_status);
}
/* no need to retry for badch; will fail again */
@@ -988,9 +987,8 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
}
} else if (txs->phyerr) {
update_rate = false;
- wiphy_err(wiphy, "wl%d: ampdu tx phy "
- "error (0x%x)\n", wlc->pub->unit,
- txs->phyerr);
+ wiphy_err(wiphy, "%s: ampdu tx phy error (0x%x)\n",
+ __func__, txs->phyerr);
if (brcm_msg_level & LOG_ERROR_VAL) {
brcmu_prpkt("txpkt (AMPDU)", p);
@@ -1018,10 +1016,10 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
ack_recd = false;
if (ba_recd) {
bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
- BCMMSG(wlc->wiphy, "tid %d seq %d,"
- " start_seq %d, bindex %d set %d, index %d\n",
- tid, seq, start_seq, bindex,
- isset(bitmap, bindex), index);
+ BCMMSG(wiphy,
+ "tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n",
+ tid, seq, start_seq, bindex,
+ isset(bitmap, bindex), index);
/* if acked then clear bit and free packet */
if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
&& isset(bitmap, bindex)) {
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index fec0f10773e..569ab8abd2a 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -1169,25 +1169,31 @@ static struct bcma_driver brcms_bcma_driver = {
/**
* This is the main entry point for the brcmsmac driver.
*
- * This function determines if a device pointed to by pdev is a WL device,
- * and if so, performs a brcms_attach() on it.
- *
+ * This function is scheduled upon module initialization and
+ * does the driver registration, which result in brcms_bcma_probe()
+ * call resulting in the driver bringup.
*/
-static int __init brcms_module_init(void)
+static void brcms_driver_init(struct work_struct *work)
{
- int error = -ENODEV;
+ int error;
+ error = bcma_driver_register(&brcms_bcma_driver);
+ if (error)
+ pr_err("%s: register returned %d\n", __func__, error);
+}
+
+static DECLARE_WORK(brcms_driver_work, brcms_driver_init);
+
+static int __init brcms_module_init(void)
+{
#ifdef DEBUG
if (msglevel != 0xdeadbeef)
brcm_msg_level = msglevel;
-#endif /* DEBUG */
-
- error = bcma_driver_register(&brcms_bcma_driver);
- pr_err("%s: register returned %d\n", __func__, error);
- if (!error)
- return 0;
+#endif
+ if (!schedule_work(&brcms_driver_work))
+ return -EBUSY;
- return error;
+ return 0;
}
/**
@@ -1199,6 +1205,7 @@ static int __init brcms_module_init(void)
*/
static void __exit brcms_module_exit(void)
{
+ cancel_work_sync(&brcms_driver_work);
bcma_driver_unregister(&brcms_bcma_driver);
}
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 5fd56addca4..f0551f807f6 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -298,8 +298,6 @@ static const char *command_types[] = {
};
#endif
-#define WEXT_USECHANNELS 1
-
static const long ipw2100_frequencies[] = {
2412, 2417, 2422, 2427,
2432, 2437, 2442, 2447,
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.h b/drivers/net/wireless/ipw2x00/ipw2200.h
index ecb561d7a7a..66e84ec0eb5 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.h
+++ b/drivers/net/wireless/ipw2x00/ipw2200.h
@@ -27,8 +27,6 @@
#ifndef __ipw2200_h__
#define __ipw2200_h__
-#define WEXT_USECHANNELS 1
-
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index ae08498dfca..2fe62730ddd 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -1,6 +1,6 @@
config IWLWIFI
tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) "
- depends on PCI && MAC80211
+ depends on PCI && MAC80211 && HAS_IOMEM
select FW_LOADER
select NEW_LEDS
select LEDS_CLASS
@@ -127,3 +127,12 @@ config IWLWIFI_P2P
support when it is loaded.
Say Y only if you want to experiment with P2P.
+
+config IWLWIFI_EXPERIMENTAL_MFP
+ bool "support MFP (802.11w) even if uCode doesn't advertise"
+ depends on IWLWIFI
+ help
+ This option enables experimental MFP (802.11W) support
+ even if the microcode doesn't advertise it.
+
+ Say Y only if you want to experiment with MFP.
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index afa0bb8f324..85d163ed3db 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -14,7 +14,7 @@ iwlwifi-objs += iwl-1000.o
iwlwifi-objs += iwl-2000.o
iwlwifi-objs += iwl-pci.o
iwlwifi-objs += iwl-drv.o
-iwlwifi-objs += iwl-trans.o
+iwlwifi-objs += iwl-notif-wait.o
iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o
iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 605ee3df1d8..5b0d888f746 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -43,6 +43,7 @@
#include "iwl-agn-hw.h"
#include "iwl-shared.h"
#include "iwl-cfg.h"
+#include "iwl-prph.h"
/* Highest firmware API version supported */
#define IWL1000_UCODE_API_MAX 6
@@ -95,9 +96,8 @@ static void iwl1000_nic_config(struct iwl_priv *priv)
~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK);
}
-static struct iwl_sensitivity_ranges iwl1000_sensitivity = {
+static const struct iwl_sensitivity_ranges iwl1000_sensitivity = {
.min_nrg_cck = 95,
- .max_nrg_cck = 0, /* not used, set to 0 */
.auto_corr_min_ofdm = 90,
.auto_corr_min_ofdm_mrc = 170,
.auto_corr_min_ofdm_x1 = 120,
@@ -122,23 +122,15 @@ static struct iwl_sensitivity_ranges iwl1000_sensitivity = {
static void iwl1000_hw_set_hw_params(struct iwl_priv *priv)
{
- if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
- iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
- cfg(priv)->base_params->num_of_queues =
- iwlagn_mod_params.num_of_queues;
-
- hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
-
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ);
- hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
+ hw_params(priv).tx_chains_num =
+ num_of_ant(hw_params(priv).valid_tx_ant);
if (cfg(priv)->rx_with_siso_diversity)
hw_params(priv).rx_chains_num = 1;
else
hw_params(priv).rx_chains_num =
- num_of_ant(cfg(priv)->valid_rx_ant);
- hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
- hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
+ num_of_ant(hw_params(priv).valid_rx_ant);
iwl1000_set_ct_threshold(priv);
@@ -163,7 +155,7 @@ static struct iwl_lib_ops iwl1000_lib = {
.temperature = iwlagn_temperature,
};
-static struct iwl_base_params iwl1000_base_params = {
+static const struct iwl_base_params iwl1000_base_params = {
.num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
.eeprom_size = OTP_LOW_IMAGE_SIZE,
@@ -178,7 +170,8 @@ static struct iwl_base_params iwl1000_base_params = {
.max_event_log_size = 128,
.wd_disable = true,
};
-static struct iwl_ht_params iwl1000_ht_params = {
+
+static const struct iwl_ht_params iwl1000_ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.smps_mode = IEEE80211_SMPS_DYNAMIC,
@@ -197,13 +190,13 @@ static struct iwl_ht_params iwl1000_ht_params = {
.base_params = &iwl1000_base_params, \
.led_mode = IWL_LED_BLINK
-struct iwl_cfg iwl1000_bgn_cfg = {
+const struct iwl_cfg iwl1000_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 1000 BGN",
IWL_DEVICE_1000,
.ht_params = &iwl1000_ht_params,
};
-struct iwl_cfg iwl1000_bg_cfg = {
+const struct iwl_cfg iwl1000_bg_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 1000 BG",
IWL_DEVICE_1000,
};
@@ -222,13 +215,13 @@ struct iwl_cfg iwl1000_bg_cfg = {
.led_mode = IWL_LED_RF_STATE, \
.rx_with_siso_diversity = true
-struct iwl_cfg iwl100_bgn_cfg = {
+const struct iwl_cfg iwl100_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 100 BGN",
IWL_DEVICE_100,
.ht_params = &iwl1000_ht_params,
};
-struct iwl_cfg iwl100_bg_cfg = {
+const struct iwl_cfg iwl100_bg_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 100 BG",
IWL_DEVICE_100,
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c
index e6e8c79a80d..5635b9e2c69 100644
--- a/drivers/net/wireless/iwlwifi/iwl-2000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-2000.c
@@ -91,9 +91,8 @@ static void iwl2000_nic_config(struct iwl_priv *priv)
CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
}
-static struct iwl_sensitivity_ranges iwl2000_sensitivity = {
+static const struct iwl_sensitivity_ranges iwl2000_sensitivity = {
.min_nrg_cck = 97,
- .max_nrg_cck = 0, /* not used, set to 0 */
.auto_corr_min_ofdm = 80,
.auto_corr_min_ofdm_mrc = 128,
.auto_corr_min_ofdm_x1 = 105,
@@ -118,23 +117,15 @@ static struct iwl_sensitivity_ranges iwl2000_sensitivity = {
static void iwl2000_hw_set_hw_params(struct iwl_priv *priv)
{
- if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
- iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
- cfg(priv)->base_params->num_of_queues =
- iwlagn_mod_params.num_of_queues;
-
- hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
-
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ);
- hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
+ hw_params(priv).tx_chains_num =
+ num_of_ant(hw_params(priv).valid_tx_ant);
if (cfg(priv)->rx_with_siso_diversity)
hw_params(priv).rx_chains_num = 1;
else
hw_params(priv).rx_chains_num =
- num_of_ant(cfg(priv)->valid_rx_ant);
- hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
- hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
+ num_of_ant(hw_params(priv).valid_rx_ant);
iwl2000_set_ct_threshold(priv);
@@ -155,16 +146,13 @@ static struct iwl_lib_ops iwl2000_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REGULATORY_BAND_NO_HT40,
},
- .update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
+ .enhanced_txpower = true,
},
.temperature = iwlagn_temperature,
};
static struct iwl_lib_ops iwl2030_lib = {
.set_hw_params = iwl2000_hw_set_hw_params,
- .bt_rx_handler_setup = iwlagn_bt_rx_handler_setup,
- .bt_setup_deferred_work = iwlagn_bt_setup_deferred_work,
- .cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
.nic_config = iwl2000_nic_config,
.eeprom_ops = {
.regulatory_bands = {
@@ -176,12 +164,12 @@ static struct iwl_lib_ops iwl2030_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REGULATORY_BAND_NO_HT40,
},
- .update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
+ .enhanced_txpower = true,
},
.temperature = iwlagn_temperature,
};
-static struct iwl_base_params iwl2000_base_params = {
+static const struct iwl_base_params iwl2000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE,
.num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
@@ -200,7 +188,7 @@ static struct iwl_base_params iwl2000_base_params = {
};
-static struct iwl_base_params iwl2030_base_params = {
+static const struct iwl_base_params iwl2030_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE,
.num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
@@ -218,12 +206,12 @@ static struct iwl_base_params iwl2030_base_params = {
.hd_v2 = true,
};
-static struct iwl_ht_params iwl2000_ht_params = {
+static const struct iwl_ht_params iwl2000_ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
};
-static struct iwl_bt_params iwl2030_bt_params = {
+static const struct iwl_bt_params iwl2030_bt_params = {
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
.advanced_bt_coexist = true,
.agg_time_limit = BT_AGG_THRESHOLD_DEF,
@@ -249,13 +237,13 @@ static struct iwl_bt_params iwl2030_bt_params = {
.led_mode = IWL_LED_RF_STATE, \
.iq_invert = true \
-struct iwl_cfg iwl2000_2bgn_cfg = {
+const struct iwl_cfg iwl2000_2bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 2200 BGN",
IWL_DEVICE_2000,
.ht_params = &iwl2000_ht_params,
};
-struct iwl_cfg iwl2000_2bgn_d_cfg = {
+const struct iwl_cfg iwl2000_2bgn_d_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 2200D BGN",
IWL_DEVICE_2000,
.ht_params = &iwl2000_ht_params,
@@ -279,7 +267,7 @@ struct iwl_cfg iwl2000_2bgn_d_cfg = {
.adv_pm = true, \
.iq_invert = true \
-struct iwl_cfg iwl2030_2bgn_cfg = {
+const struct iwl_cfg iwl2030_2bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 2230 BGN",
IWL_DEVICE_2030,
.ht_params = &iwl2000_ht_params,
@@ -303,13 +291,13 @@ struct iwl_cfg iwl2030_2bgn_cfg = {
.rx_with_siso_diversity = true, \
.iq_invert = true \
-struct iwl_cfg iwl105_bgn_cfg = {
+const struct iwl_cfg iwl105_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 105 BGN",
IWL_DEVICE_105,
.ht_params = &iwl2000_ht_params,
};
-struct iwl_cfg iwl105_bgn_d_cfg = {
+const struct iwl_cfg iwl105_bgn_d_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 105D BGN",
IWL_DEVICE_105,
.ht_params = &iwl2000_ht_params,
@@ -334,7 +322,7 @@ struct iwl_cfg iwl105_bgn_d_cfg = {
.rx_with_siso_diversity = true, \
.iq_invert = true \
-struct iwl_cfg iwl135_bgn_cfg = {
+const struct iwl_cfg iwl135_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 135 BGN",
IWL_DEVICE_135,
.ht_params = &iwl2000_ht_params,
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 1527dec7a26..a805e97b89a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -45,6 +45,7 @@
#include "iwl-trans.h"
#include "iwl-shared.h"
#include "iwl-cfg.h"
+#include "iwl-prph.h"
/* Highest firmware API version supported */
#define IWL5000_UCODE_API_MAX 5
@@ -63,12 +64,8 @@
/* NIC configuration for 5000 series */
static void iwl5000_nic_config(struct iwl_priv *priv)
{
- unsigned long flags;
-
iwl_rf_config(priv);
- spin_lock_irqsave(&priv->shrd->lock, flags);
-
/* W/A : NIC is stuck in a reset state after Early PCIe power off
* (PCIe power is lost before PERST# is asserted),
* causing ME FW to lose ownership and not being able to obtain it back.
@@ -76,14 +73,10 @@ static void iwl5000_nic_config(struct iwl_priv *priv)
iwl_set_bits_mask_prph(trans(priv), APMG_PS_CTRL_REG,
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
-
-
- spin_unlock_irqrestore(&priv->shrd->lock, flags);
}
-static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
+static const struct iwl_sensitivity_ranges iwl5000_sensitivity = {
.min_nrg_cck = 100,
- .max_nrg_cck = 0, /* not used, set to 0 */
.auto_corr_min_ofdm = 90,
.auto_corr_min_ofdm_mrc = 170,
.auto_corr_min_ofdm_x1 = 105,
@@ -108,7 +101,6 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
.min_nrg_cck = 95,
- .max_nrg_cck = 0, /* not used, set to 0 */
.auto_corr_min_ofdm = 90,
.auto_corr_min_ofdm_mrc = 170,
.auto_corr_min_ofdm_x1 = 105,
@@ -164,20 +156,13 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv)
static void iwl5000_hw_set_hw_params(struct iwl_priv *priv)
{
- if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
- iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
- cfg(priv)->base_params->num_of_queues =
- iwlagn_mod_params.num_of_queues;
-
- hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
-
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ);
- hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
- hw_params(priv).rx_chains_num = num_of_ant(cfg(priv)->valid_rx_ant);
- hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
- hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
+ hw_params(priv).tx_chains_num =
+ num_of_ant(hw_params(priv).valid_tx_ant);
+ hw_params(priv).rx_chains_num =
+ num_of_ant(hw_params(priv).valid_rx_ant);
iwl5000_set_ct_threshold(priv);
@@ -187,20 +172,13 @@ static void iwl5000_hw_set_hw_params(struct iwl_priv *priv)
static void iwl5150_hw_set_hw_params(struct iwl_priv *priv)
{
- if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
- iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
- cfg(priv)->base_params->num_of_queues =
- iwlagn_mod_params.num_of_queues;
-
- hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
-
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ);
- hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
- hw_params(priv).rx_chains_num = num_of_ant(cfg(priv)->valid_rx_ant);
- hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
- hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
+ hw_params(priv).tx_chains_num =
+ num_of_ant(hw_params(priv).valid_tx_ant);
+ hw_params(priv).rx_chains_num =
+ num_of_ant(hw_params(priv).valid_rx_ant);
iwl5150_set_ct_threshold(priv);
@@ -288,7 +266,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
return -EFAULT;
}
- return iwl_trans_send_cmd(trans(priv), &hcmd);
+ return iwl_dvm_send_cmd(priv, &hcmd);
}
static struct iwl_lib_ops iwl5000_lib = {
@@ -327,7 +305,7 @@ static struct iwl_lib_ops iwl5150_lib = {
.temperature = iwl5150_temperature,
};
-static struct iwl_base_params iwl5000_base_params = {
+static const struct iwl_base_params iwl5000_base_params = {
.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
.num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
@@ -340,7 +318,8 @@ static struct iwl_base_params iwl5000_base_params = {
.no_idle_support = true,
.wd_disable = true,
};
-static struct iwl_ht_params iwl5000_ht_params = {
+
+static const struct iwl_ht_params iwl5000_ht_params = {
.ht_greenfield_support = true,
};
@@ -356,7 +335,7 @@ static struct iwl_ht_params iwl5000_ht_params = {
.base_params = &iwl5000_base_params, \
.led_mode = IWL_LED_BLINK
-struct iwl_cfg iwl5300_agn_cfg = {
+const struct iwl_cfg iwl5300_agn_cfg = {
.name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
IWL_DEVICE_5000,
/* at least EEPROM 0x11A has wrong info */
@@ -365,7 +344,7 @@ struct iwl_cfg iwl5300_agn_cfg = {
.ht_params = &iwl5000_ht_params,
};
-struct iwl_cfg iwl5100_bgn_cfg = {
+const struct iwl_cfg iwl5100_bgn_cfg = {
.name = "Intel(R) WiFi Link 5100 BGN",
IWL_DEVICE_5000,
.valid_tx_ant = ANT_B, /* .cfg overwrite */
@@ -373,14 +352,14 @@ struct iwl_cfg iwl5100_bgn_cfg = {
.ht_params = &iwl5000_ht_params,
};
-struct iwl_cfg iwl5100_abg_cfg = {
+const struct iwl_cfg iwl5100_abg_cfg = {
.name = "Intel(R) WiFi Link 5100 ABG",
IWL_DEVICE_5000,
.valid_tx_ant = ANT_B, /* .cfg overwrite */
.valid_rx_ant = ANT_AB, /* .cfg overwrite */
};
-struct iwl_cfg iwl5100_agn_cfg = {
+const struct iwl_cfg iwl5100_agn_cfg = {
.name = "Intel(R) WiFi Link 5100 AGN",
IWL_DEVICE_5000,
.valid_tx_ant = ANT_B, /* .cfg overwrite */
@@ -388,7 +367,7 @@ struct iwl_cfg iwl5100_agn_cfg = {
.ht_params = &iwl5000_ht_params,
};
-struct iwl_cfg iwl5350_agn_cfg = {
+const struct iwl_cfg iwl5350_agn_cfg = {
.name = "Intel(R) WiMAX/WiFi Link 5350 AGN",
.fw_name_pre = IWL5000_FW_PRE,
.ucode_api_max = IWL5000_UCODE_API_MAX,
@@ -418,14 +397,14 @@ struct iwl_cfg iwl5350_agn_cfg = {
.led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true
-struct iwl_cfg iwl5150_agn_cfg = {
+const struct iwl_cfg iwl5150_agn_cfg = {
.name = "Intel(R) WiMAX/WiFi Link 5150 AGN",
IWL_DEVICE_5150,
.ht_params = &iwl5000_ht_params,
};
-struct iwl_cfg iwl5150_abg_cfg = {
+const struct iwl_cfg iwl5150_abg_cfg = {
.name = "Intel(R) WiMAX/WiFi Link 5150 ABG",
IWL_DEVICE_5150,
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 223e60a1b79..64060cd738b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -96,25 +96,25 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv)
CSR_GP_DRIVER_REG_BIT_6050_1x2);
}
+static void iwl6000i_additional_nic_config(struct iwl_priv *priv)
+{
+ /* 2x2 IPA phy type */
+ iwl_write32(trans(priv), CSR_GP_DRIVER_REG,
+ CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
+}
+
/* NIC configuration for 6000 series */
static void iwl6000_nic_config(struct iwl_priv *priv)
{
iwl_rf_config(priv);
- /* no locking required for register write */
- if (cfg(priv)->pa_type == IWL_PA_INTERNAL) {
- /* 2x2 IPA phy type */
- iwl_write32(trans(priv), CSR_GP_DRIVER_REG,
- CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
- }
/* do additional nic configuration if needed */
if (cfg(priv)->additional_nic_config)
- cfg(priv)->additional_nic_config(priv);
+ cfg(priv)->additional_nic_config(priv);
}
-static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
+static const struct iwl_sensitivity_ranges iwl6000_sensitivity = {
.min_nrg_cck = 110,
- .max_nrg_cck = 0, /* not used, set to 0 */
.auto_corr_min_ofdm = 80,
.auto_corr_min_ofdm_mrc = 128,
.auto_corr_min_ofdm_x1 = 105,
@@ -139,24 +139,16 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
static void iwl6000_hw_set_hw_params(struct iwl_priv *priv)
{
- if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
- iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
- cfg(priv)->base_params->num_of_queues =
- iwlagn_mod_params.num_of_queues;
-
- hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
-
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ);
- hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
+ hw_params(priv).tx_chains_num =
+ num_of_ant(hw_params(priv).valid_tx_ant);
if (cfg(priv)->rx_with_siso_diversity)
hw_params(priv).rx_chains_num = 1;
else
hw_params(priv).rx_chains_num =
- num_of_ant(cfg(priv)->valid_rx_ant);
- hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
- hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
+ num_of_ant(hw_params(priv).valid_rx_ant);
iwl6000_set_ct_threshold(priv);
@@ -233,7 +225,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
return -EFAULT;
}
- return iwl_trans_send_cmd(trans(priv), &hcmd);
+ return iwl_dvm_send_cmd(priv, &hcmd);
}
static struct iwl_lib_ops iwl6000_lib = {
@@ -250,16 +242,13 @@ static struct iwl_lib_ops iwl6000_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
- .update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
+ .enhanced_txpower = true,
},
.temperature = iwlagn_temperature,
};
static struct iwl_lib_ops iwl6030_lib = {
.set_hw_params = iwl6000_hw_set_hw_params,
- .bt_rx_handler_setup = iwlagn_bt_rx_handler_setup,
- .bt_setup_deferred_work = iwlagn_bt_setup_deferred_work,
- .cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
.set_channel_switch = iwl6000_hw_channel_switch,
.nic_config = iwl6000_nic_config,
.eeprom_ops = {
@@ -272,12 +261,12 @@ static struct iwl_lib_ops iwl6030_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
- .update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
+ .enhanced_txpower = true,
},
.temperature = iwlagn_temperature,
};
-static struct iwl_base_params iwl6000_base_params = {
+static const struct iwl_base_params iwl6000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE,
.num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
@@ -294,7 +283,7 @@ static struct iwl_base_params iwl6000_base_params = {
.shadow_reg_enable = true,
};
-static struct iwl_base_params iwl6050_base_params = {
+static const struct iwl_base_params iwl6050_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE,
.num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
@@ -310,7 +299,8 @@ static struct iwl_base_params iwl6050_base_params = {
.max_event_log_size = 1024,
.shadow_reg_enable = true,
};
-static struct iwl_base_params iwl6000_g2_base_params = {
+
+static const struct iwl_base_params iwl6000_g2_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE,
.num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
@@ -327,12 +317,12 @@ static struct iwl_base_params iwl6000_g2_base_params = {
.shadow_reg_enable = true,
};
-static struct iwl_ht_params iwl6000_ht_params = {
+static const struct iwl_ht_params iwl6000_ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
};
-static struct iwl_bt_params iwl6000_bt_params = {
+static const struct iwl_bt_params iwl6000_bt_params = {
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
.advanced_bt_coexist = true,
.agg_time_limit = BT_AGG_THRESHOLD_DEF,
@@ -355,40 +345,41 @@ static struct iwl_bt_params iwl6000_bt_params = {
.need_temp_offset_calib = true, \
.led_mode = IWL_LED_RF_STATE
-struct iwl_cfg iwl6005_2agn_cfg = {
+const struct iwl_cfg iwl6005_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6205 AGN",
IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params,
};
-struct iwl_cfg iwl6005_2abg_cfg = {
+const struct iwl_cfg iwl6005_2abg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6205 ABG",
IWL_DEVICE_6005,
};
-struct iwl_cfg iwl6005_2bg_cfg = {
+const struct iwl_cfg iwl6005_2bg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6205 BG",
IWL_DEVICE_6005,
};
-struct iwl_cfg iwl6005_2agn_sff_cfg = {
+const struct iwl_cfg iwl6005_2agn_sff_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6205S AGN",
IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params,
};
-struct iwl_cfg iwl6005_2agn_d_cfg = {
+const struct iwl_cfg iwl6005_2agn_d_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6205D AGN",
IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params,
};
-struct iwl_cfg iwl6005_2agn_mow1_cfg = {
+const struct iwl_cfg iwl6005_2agn_mow1_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6206 AGN",
IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params,
};
-struct iwl_cfg iwl6005_2agn_mow2_cfg = {
+
+const struct iwl_cfg iwl6005_2agn_mow2_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6207 AGN",
IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params,
@@ -410,53 +401,53 @@ struct iwl_cfg iwl6005_2agn_mow2_cfg = {
.led_mode = IWL_LED_RF_STATE, \
.adv_pm = true \
-struct iwl_cfg iwl6030_2agn_cfg = {
+const struct iwl_cfg iwl6030_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6230 AGN",
IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params,
};
-struct iwl_cfg iwl6030_2abg_cfg = {
+const struct iwl_cfg iwl6030_2abg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6230 ABG",
IWL_DEVICE_6030,
};
-struct iwl_cfg iwl6030_2bgn_cfg = {
+const struct iwl_cfg iwl6030_2bgn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6230 BGN",
IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params,
};
-struct iwl_cfg iwl6030_2bg_cfg = {
+const struct iwl_cfg iwl6030_2bg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6230 BG",
IWL_DEVICE_6030,
};
-struct iwl_cfg iwl6035_2agn_cfg = {
+const struct iwl_cfg iwl6035_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6235 AGN",
IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params,
};
-struct iwl_cfg iwl1030_bgn_cfg = {
+const struct iwl_cfg iwl1030_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 1030 BGN",
IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params,
};
-struct iwl_cfg iwl1030_bg_cfg = {
+const struct iwl_cfg iwl1030_bg_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 1030 BG",
IWL_DEVICE_6030,
};
-struct iwl_cfg iwl130_bgn_cfg = {
+const struct iwl_cfg iwl130_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 130 BGN",
IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params,
.rx_with_siso_diversity = true,
};
-struct iwl_cfg iwl130_bg_cfg = {
+const struct iwl_cfg iwl130_bg_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 130 BG",
IWL_DEVICE_6030,
.rx_with_siso_diversity = true,
@@ -477,22 +468,22 @@ struct iwl_cfg iwl130_bg_cfg = {
.eeprom_ver = EEPROM_6000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \
.lib = &iwl6000_lib, \
+ .additional_nic_config = iwl6000i_additional_nic_config,\
.base_params = &iwl6000_base_params, \
- .pa_type = IWL_PA_INTERNAL, \
.led_mode = IWL_LED_BLINK
-struct iwl_cfg iwl6000i_2agn_cfg = {
+const struct iwl_cfg iwl6000i_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6200 AGN",
IWL_DEVICE_6000i,
.ht_params = &iwl6000_ht_params,
};
-struct iwl_cfg iwl6000i_2abg_cfg = {
+const struct iwl_cfg iwl6000i_2abg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6200 ABG",
IWL_DEVICE_6000i,
};
-struct iwl_cfg iwl6000i_2bg_cfg = {
+const struct iwl_cfg iwl6000i_2bg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6200 BG",
IWL_DEVICE_6000i,
};
@@ -513,13 +504,13 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
.led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true
-struct iwl_cfg iwl6050_2agn_cfg = {
+const struct iwl_cfg iwl6050_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN",
IWL_DEVICE_6050,
.ht_params = &iwl6000_ht_params,
};
-struct iwl_cfg iwl6050_2abg_cfg = {
+const struct iwl_cfg iwl6050_2abg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG",
IWL_DEVICE_6050,
};
@@ -538,18 +529,18 @@ struct iwl_cfg iwl6050_2abg_cfg = {
.led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true
-struct iwl_cfg iwl6150_bgn_cfg = {
+const struct iwl_cfg iwl6150_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN",
IWL_DEVICE_6150,
.ht_params = &iwl6000_ht_params,
};
-struct iwl_cfg iwl6150_bg_cfg = {
+const struct iwl_cfg iwl6150_bg_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BG",
IWL_DEVICE_6150,
};
-struct iwl_cfg iwl6000_3agn_cfg = {
+const struct iwl_cfg iwl6000_3agn_cfg = {
.name = "Intel(R) Centrino(R) Ultimate-N 6300 AGN",
.fw_name_pre = IWL6000_FW_PRE,
.ucode_api_max = IWL6000_UCODE_API_MAX,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
index 988ee454a94..84cbe7bb504 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
@@ -68,13 +68,19 @@
#include "iwl-agn-calib.h"
#include "iwl-trans.h"
#include "iwl-agn.h"
-#include "iwl-wifi.h"
-#include "iwl-ucode.h"
/*****************************************************************************
* INIT calibrations framework
*****************************************************************************/
+/* Opaque calibration results */
+struct iwl_calib_result {
+ struct list_head list;
+ size_t cmd_len;
+ struct iwl_calib_hdr hdr;
+ /* data follows */
+};
+
struct statistics_general_data {
u32 beacon_silence_rssi_a;
u32 beacon_silence_rssi_b;
@@ -84,7 +90,7 @@ struct statistics_general_data {
u32 beacon_energy_c;
};
-int iwl_send_calib_results(struct iwl_trans *trans)
+int iwl_send_calib_results(struct iwl_priv *priv)
{
struct iwl_host_cmd hcmd = {
.id = REPLY_PHY_CALIBRATION_CMD,
@@ -92,15 +98,15 @@ int iwl_send_calib_results(struct iwl_trans *trans)
};
struct iwl_calib_result *res;
- list_for_each_entry(res, &trans->calib_results, list) {
+ list_for_each_entry(res, &priv->calib_results, list) {
int ret;
hcmd.len[0] = res->cmd_len;
hcmd.data[0] = &res->hdr;
hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
- ret = iwl_trans_send_cmd(trans, &hcmd);
+ ret = iwl_dvm_send_cmd(priv, &hcmd);
if (ret) {
- IWL_ERR(trans, "Error %d on calib cmd %d\n",
+ IWL_ERR(priv, "Error %d on calib cmd %d\n",
ret, res->hdr.op_code);
return ret;
}
@@ -109,7 +115,7 @@ int iwl_send_calib_results(struct iwl_trans *trans)
return 0;
}
-int iwl_calib_set(struct iwl_trans *trans,
+int iwl_calib_set(struct iwl_priv *priv,
const struct iwl_calib_hdr *cmd, int len)
{
struct iwl_calib_result *res, *tmp;
@@ -121,7 +127,7 @@ int iwl_calib_set(struct iwl_trans *trans,
memcpy(&res->hdr, cmd, len);
res->cmd_len = len;
- list_for_each_entry(tmp, &trans->calib_results, list) {
+ list_for_each_entry(tmp, &priv->calib_results, list) {
if (tmp->hdr.op_code == res->hdr.op_code) {
list_replace(&tmp->list, &res->list);
kfree(tmp);
@@ -130,16 +136,16 @@ int iwl_calib_set(struct iwl_trans *trans,
}
/* wasn't in list already */
- list_add_tail(&res->list, &trans->calib_results);
+ list_add_tail(&res->list, &priv->calib_results);
return 0;
}
-void iwl_calib_free_results(struct iwl_trans *trans)
+void iwl_calib_free_results(struct iwl_priv *priv)
{
struct iwl_calib_result *res, *tmp;
- list_for_each_entry_safe(res, tmp, &trans->calib_results, list) {
+ list_for_each_entry_safe(res, tmp, &priv->calib_results, list) {
list_del(&res->list);
kfree(res);
}
@@ -494,7 +500,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
sizeof(u16)*HD_TABLE_SIZE);
- return iwl_trans_send_cmd(trans(priv), &cmd_out);
+ return iwl_dvm_send_cmd(priv, &cmd_out);
}
/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
@@ -583,7 +589,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv)
&(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]),
sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES);
- return iwl_trans_send_cmd(trans(priv), &cmd_out);
+ return iwl_dvm_send_cmd(priv, &cmd_out);
}
void iwl_init_sensitivity(struct iwl_priv *priv)
@@ -636,7 +642,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
data->last_bad_plcp_cnt_cck = 0;
data->last_fa_cnt_cck = 0;
- if (nic(priv)->fw.enhance_sensitivity_table)
+ if (priv->fw->enhance_sensitivity_table)
ret |= iwl_enhance_sensitivity_write(priv);
else
ret |= iwl_sensitivity_write(priv);
@@ -655,7 +661,6 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv)
struct iwl_sensitivity_data *data = NULL;
struct statistics_rx_non_phy *rx_info;
struct statistics_rx_phy *ofdm, *cck;
- unsigned long flags;
struct statistics_general_data statis;
if (priv->disable_sens_cal)
@@ -668,13 +673,13 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv)
return;
}
- spin_lock_irqsave(&priv->shrd->lock, flags);
+ spin_lock_bh(&priv->statistics.lock);
rx_info = &priv->statistics.rx_non_phy;
ofdm = &priv->statistics.rx_ofdm;
cck = &priv->statistics.rx_cck;
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
IWL_DEBUG_CALIB(priv, "<< invalid data.\n");
- spin_unlock_irqrestore(&priv->shrd->lock, flags);
+ spin_unlock_bh(&priv->statistics.lock);
return;
}
@@ -698,7 +703,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv)
statis.beacon_energy_c =
le32_to_cpu(rx_info->beacon_energy_c);
- spin_unlock_irqrestore(&priv->shrd->lock, flags);
+ spin_unlock_bh(&priv->statistics.lock);
IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time);
@@ -747,7 +752,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv)
iwl_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time);
iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
- if (nic(priv)->fw.enhance_sensitivity_table)
+ if (priv->fw->enhance_sensitivity_table)
iwl_enhance_sensitivity_write(priv);
else
iwl_sensitivity_write(priv);
@@ -849,7 +854,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
* connect the first valid tx chain
*/
first_chain =
- find_first_chain(cfg(priv)->valid_tx_ant);
+ find_first_chain(hw_params(priv).valid_tx_ant);
data->disconn_array[first_chain] = 0;
active_chains |= BIT(first_chain);
IWL_DEBUG_CALIB(priv,
@@ -874,10 +879,8 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
}
static void iwlagn_gain_computation(struct iwl_priv *priv,
- u32 average_noise[NUM_RX_CHAINS],
- u16 min_average_noise_antenna_i,
- u32 min_average_noise,
- u8 default_chain)
+ u32 average_noise[NUM_RX_CHAINS],
+ u8 default_chain)
{
int i;
s32 delta_g;
@@ -925,7 +928,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv,
priv->phy_calib_chain_noise_gain_cmd);
cmd.delta_gain_1 = data->delta_gain_code[1];
cmd.delta_gain_2 = data->delta_gain_code[2];
- iwl_trans_send_cmd_pdu(trans(priv), REPLY_PHY_CALIBRATION_CMD,
+ iwl_dvm_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
CMD_ASYNC, sizeof(cmd), &cmd);
data->radio_write = 1;
@@ -958,7 +961,6 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
u16 stat_chnum = INITIALIZATION_VALUE;
u8 rxon_band24;
u8 stat_band24;
- unsigned long flags;
struct statistics_rx_non_phy *rx_info;
/*
@@ -983,13 +985,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
return;
}
- spin_lock_irqsave(&priv->shrd->lock, flags);
+ spin_lock_bh(&priv->statistics.lock);
rx_info = &priv->statistics.rx_non_phy;
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n");
- spin_unlock_irqrestore(&priv->shrd->lock, flags);
+ spin_unlock_bh(&priv->statistics.lock);
return;
}
@@ -1004,7 +1006,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) {
IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n",
rxon_chnum, rxon_band24);
- spin_unlock_irqrestore(&priv->shrd->lock, flags);
+ spin_unlock_bh(&priv->statistics.lock);
return;
}
@@ -1023,7 +1025,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER;
chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER;
- spin_unlock_irqrestore(&priv->shrd->lock, flags);
+ spin_unlock_bh(&priv->statistics.lock);
data->beacon_count++;
@@ -1083,8 +1085,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
min_average_noise, min_average_noise_antenna_i);
iwlagn_gain_computation(priv, average_noise,
- min_average_noise_antenna_i, min_average_noise,
- find_first_chain(cfg(priv)->valid_rx_ant));
+ find_first_chain(hw_params(priv).valid_rx_ant));
/* Some power changes may have been made during the calibration.
* Update and commit the RXON
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 5be0d3695d0..915183a3a87 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -32,7 +32,6 @@
#include <linux/init.h>
#include <linux/sched.h>
-#include "iwl-wifi.h"
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-io.h"
@@ -52,7 +51,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
struct iwlagn_tx_power_dbm_cmd tx_power_cmd;
u8 tx_ant_cfg_cmd;
- if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->shrd->status),
+ if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
"TX Power requested while scanning!\n"))
return -EAGAIN;
@@ -77,17 +76,19 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED;
tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO;
- if (IWL_UCODE_API(nic(priv)->fw.ucode_ver) == 1)
+ if (IWL_UCODE_API(priv->fw->ucode_ver) == 1)
tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1;
else
tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
- return iwl_trans_send_cmd_pdu(trans(priv), tx_ant_cfg_cmd, CMD_SYNC,
+ return iwl_dvm_send_cmd_pdu(priv, tx_ant_cfg_cmd, CMD_SYNC,
sizeof(tx_power_cmd), &tx_power_cmd);
}
void iwlagn_temperature(struct iwl_priv *priv)
{
+ lockdep_assert_held(&priv->statistics.lock);
+
/* store temperature from correct statistics (in Celsius) */
priv->temperature = le32_to_cpu(priv->statistics.common.temperature);
iwl_tt_handler(priv);
@@ -233,19 +234,19 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
IWL_PAN_SCD_MULTICAST_MSK;
- if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
+ if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE)
flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
flush_cmd.fifo_control);
flush_cmd.flush_control = cpu_to_le16(flush_control);
- return iwl_trans_send_cmd(trans(priv), &cmd);
+ return iwl_dvm_send_cmd(priv, &cmd);
}
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
{
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
ieee80211_stop_queues(priv->hw);
if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
IWL_ERR(priv, "flush request fail\n");
@@ -255,7 +256,7 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
iwl_trans_wait_tx_queue_empty(trans(priv));
done:
ieee80211_wake_queues(priv->hw);
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
}
/*
@@ -434,12 +435,12 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
if (cfg(priv)->bt_params->bt_session_2) {
memcpy(&bt_cmd_2000.basic, &basic,
sizeof(basic));
- ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
+ ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000);
} else {
memcpy(&bt_cmd_6000.basic, &basic,
sizeof(basic));
- ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
+ ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000);
}
if (ret)
@@ -452,7 +453,7 @@ void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena)
struct iwl_rxon_context *ctx, *found_ctx = NULL;
bool found_ap = false;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
/* Check whether AP or GO mode is active. */
if (rssi_ena) {
@@ -565,7 +566,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
break;
}
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
/*
* We can not send command to firmware while scanning. When the scan
@@ -574,7 +575,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
* STATUS_SCANNING to avoid race when queue_work two times from
* different notifications, but quit and not perform any work at all.
*/
- if (test_bit(STATUS_SCAN_HW, &priv->shrd->status))
+ if (test_bit(STATUS_SCAN_HW, &priv->status))
goto out;
iwl_update_chain_flags(priv);
@@ -593,7 +594,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
*/
iwlagn_bt_coex_rssi_monitor(priv);
out:
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
}
/*
@@ -705,12 +706,11 @@ static void iwlagn_set_kill_msk(struct iwl_priv *priv,
}
int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
- unsigned long flags;
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif;
+ struct iwl_bt_coex_profile_notif *coex = (void *)pkt->data;
struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg;
if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) {
@@ -754,9 +754,7 @@ int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
/* FIXME: based on notification, adjust the prio_boost */
- spin_lock_irqsave(&priv->shrd->lock, flags);
priv->bt_ci_compliance = coex->bt_ci_compliance;
- spin_unlock_irqrestore(&priv->shrd->lock, flags);
return 0;
}
@@ -971,7 +969,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
u16 p1k[IWLAGN_P1K_SIZE];
int ret, i;
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
@@ -1077,7 +1075,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
break;
}
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
}
int iwlagn_send_patterns(struct iwl_priv *priv,
@@ -1117,13 +1115,12 @@ int iwlagn_send_patterns(struct iwl_priv *priv,
}
cmd.data[0] = pattern_cmd;
- err = iwl_trans_send_cmd(trans(priv), &cmd);
+ err = iwl_dvm_send_cmd(priv, &cmd);
kfree(pattern_cmd);
return err;
}
-int iwlagn_suspend(struct iwl_priv *priv,
- struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
+int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan)
{
struct iwlagn_wowlan_wakeup_filter_cmd wakeup_filter_cmd;
struct iwl_rxon_cmd rxon;
@@ -1194,9 +1191,9 @@ int iwlagn_suspend(struct iwl_priv *priv,
iwl_trans_stop_device(trans(priv));
- priv->shrd->wowlan = true;
+ priv->wowlan = true;
- ret = iwl_load_ucode_wait_alive(trans(priv), IWL_UCODE_WOWLAN);
+ ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
if (ret)
goto out;
@@ -1224,11 +1221,11 @@ int iwlagn_suspend(struct iwl_priv *priv,
* constraints. Since we're in the suspend path
* that isn't really a problem though.
*/
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
ieee80211_iter_keys(priv->hw, ctx->vif,
iwlagn_wowlan_program_keys,
&key_data);
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
if (key_data.error) {
ret = -EIO;
goto out;
@@ -1243,13 +1240,13 @@ int iwlagn_suspend(struct iwl_priv *priv,
.len[0] = sizeof(key_data.rsc_tsc),
};
- ret = iwl_trans_send_cmd(trans(priv), &rsc_tsc_cmd);
+ ret = iwl_dvm_send_cmd(priv, &rsc_tsc_cmd);
if (ret)
goto out;
}
if (key_data.use_tkip) {
- ret = iwl_trans_send_cmd_pdu(trans(priv),
+ ret = iwl_dvm_send_cmd_pdu(priv,
REPLY_WOWLAN_TKIP_PARAMS,
CMD_SYNC, sizeof(tkip_cmd),
&tkip_cmd);
@@ -1265,7 +1262,7 @@ int iwlagn_suspend(struct iwl_priv *priv,
kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN);
kek_kck_cmd.replay_ctr = priv->replay_ctr;
- ret = iwl_trans_send_cmd_pdu(trans(priv),
+ ret = iwl_dvm_send_cmd_pdu(priv,
REPLY_WOWLAN_KEK_KCK_MATERIAL,
CMD_SYNC, sizeof(kek_kck_cmd),
&kek_kck_cmd);
@@ -1274,12 +1271,12 @@ int iwlagn_suspend(struct iwl_priv *priv,
}
}
- ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_D3_CONFIG, CMD_SYNC,
+ ret = iwl_dvm_send_cmd_pdu(priv, REPLY_D3_CONFIG, CMD_SYNC,
sizeof(d3_cfg_cmd), &d3_cfg_cmd);
if (ret)
goto out;
- ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WOWLAN_WAKEUP_FILTER,
+ ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WOWLAN_WAKEUP_FILTER,
CMD_SYNC, sizeof(wakeup_filter_cmd),
&wakeup_filter_cmd);
if (ret)
@@ -1291,3 +1288,41 @@ int iwlagn_suspend(struct iwl_priv *priv,
return ret;
}
#endif
+
+int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+{
+ if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) {
+ IWL_WARN(priv, "Not sending command - %s KILL\n",
+ iwl_is_rfkill(priv) ? "RF" : "CT");
+ return -EIO;
+ }
+
+ /*
+ * Synchronous commands from this op-mode must hold
+ * the mutex, this ensures we don't try to send two
+ * (or more) synchronous commands at a time.
+ */
+ if (cmd->flags & CMD_SYNC)
+ lockdep_assert_held(&priv->mutex);
+
+ if (priv->ucode_owner == IWL_OWNERSHIP_TM &&
+ !(cmd->flags & CMD_ON_DEMAND)) {
+ IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n");
+ return -EIO;
+ }
+
+ return iwl_trans_send_cmd(trans(priv), cmd);
+}
+
+int iwl_dvm_send_cmd_pdu(struct iwl_priv *priv, u8 id,
+ u32 flags, u16 len, const void *data)
+{
+ struct iwl_host_cmd cmd = {
+ .id = id,
+ .len = { len, },
+ .data = { data, },
+ .flags = flags,
+ };
+
+ return iwl_dvm_send_cmd(priv, &cmd);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index a7d67135e3d..53f8c51cfcd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -870,19 +870,16 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
{
struct iwl_scale_tbl_info *tbl;
bool full_concurrent = priv->bt_full_concurrent;
- unsigned long flags;
if (priv->bt_ant_couple_ok) {
/*
* Is there a need to switch between
* full concurrency and 3-wire?
*/
- spin_lock_irqsave(&priv->shrd->lock, flags);
if (priv->bt_ci_compliance && priv->bt_ant_couple_ok)
full_concurrent = true;
else
full_concurrent = false;
- spin_unlock_irqrestore(&priv->shrd->lock, flags);
}
if ((priv->bt_traffic_load != priv->last_bt_traffic_load) ||
(priv->bt_full_concurrent != full_concurrent)) {
@@ -2680,7 +2677,6 @@ out:
* which requires station table entry to exist).
*/
static void rs_initialize_lq(struct iwl_priv *priv,
- struct ieee80211_conf *conf,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta)
{
@@ -2915,7 +2911,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
lq_sta->dbg_fixed_rate = 0;
#endif
- rs_initialize_lq(priv, conf, sta, lq_sta);
+ rs_initialize_lq(priv, sta, lq_sta);
}
static void rs_fill_link_cmd(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index 30bb5bbb0cd..cc0227c1f35 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -131,26 +131,27 @@ const char *get_cmd_string(u8 cmd)
******************************************************************************/
static int iwlagn_rx_reply_error(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_error_resp *err_resp = (void *)pkt->data;
IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
"seq 0x%04X ser 0x%08X\n",
- le32_to_cpu(pkt->u.err_resp.error_type),
- get_cmd_string(pkt->u.err_resp.cmd_id),
- pkt->u.err_resp.cmd_id,
- le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
- le32_to_cpu(pkt->u.err_resp.error_info));
+ le32_to_cpu(err_resp->error_type),
+ get_cmd_string(err_resp->cmd_id),
+ err_resp->cmd_id,
+ le16_to_cpu(err_resp->bad_cmd_seq_num),
+ le32_to_cpu(err_resp->error_info));
return 0;
}
-static int iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+static int iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
+ struct iwl_csa_notification *csa = (void *)pkt->data;
/*
* MULTI-FIXME
* See iwlagn_mac_channel_switch.
@@ -158,7 +159,7 @@ static int iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
- if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status))
+ if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
return 0;
if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) {
@@ -177,11 +178,11 @@ static int iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
static int iwlagn_rx_spectrum_measure_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
+ struct iwl_spectrum_notification *report = (void *)pkt->data;
if (!report->state) {
IWL_DEBUG_11H(priv,
@@ -195,12 +196,12 @@ static int iwlagn_rx_spectrum_measure_notif(struct iwl_priv *priv,
}
static int iwlagn_rx_pm_sleep_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
+ struct iwl_sleep_notification *sleep = (void *)pkt->data;
IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
sleep->pm_sleep_mode, sleep->pm_wakeup_src);
#endif
@@ -208,7 +209,7 @@ static int iwlagn_rx_pm_sleep_notif(struct iwl_priv *priv,
}
static int iwlagn_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -217,16 +218,16 @@ static int iwlagn_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
"notification for %s:\n", len,
get_cmd_string(pkt->hdr.cmd));
- iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
+ iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->data, len);
return 0;
}
static int iwlagn_rx_beacon_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw;
+ struct iwlagn_beacon_notif *beacon = (void *)pkt->data;
#ifdef CONFIG_IWLWIFI_DEBUG
u16 status = le16_to_cpu(beacon->beacon_notify_hdr.status.status);
u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
@@ -266,6 +267,8 @@ static bool iwlagn_good_ack_health(struct iwl_priv *priv,
if (priv->agg_tids_count)
return true;
+ lockdep_assert_held(&priv->statistics.lock);
+
old = &priv->statistics.tx;
actual_delta = le32_to_cpu(cur->actual_ack_cnt) -
@@ -318,7 +321,7 @@ static bool iwlagn_good_plcp_health(struct iwl_priv *priv,
unsigned int msecs)
{
int delta;
- int threshold = cfg(priv)->base_params->plcp_delta_threshold;
+ int threshold = priv->plcp_delta_threshold;
if (threshold == IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
@@ -352,7 +355,7 @@ static void iwlagn_recover_from_statistics(struct iwl_priv *priv,
{
unsigned int msecs;
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies);
@@ -487,7 +490,7 @@ iwlagn_accumulative_statistics(struct iwl_priv *priv,
#endif
static int iwlagn_rx_statistics(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
unsigned long stamp = jiffies;
@@ -509,9 +512,11 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv,
IWL_DEBUG_RX(priv, "Statistics notification received (%d bytes).\n",
len);
+ spin_lock(&priv->statistics.lock);
+
if (len == sizeof(struct iwl_bt_notif_statistics)) {
struct iwl_bt_notif_statistics *stats;
- stats = &pkt->u.stats_bt;
+ stats = (void *)&pkt->data;
flag = &stats->flag;
common = &stats->general.common;
rx_non_phy = &stats->rx.general.common;
@@ -529,7 +534,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv,
#endif
} else if (len == sizeof(struct iwl_notif_statistics)) {
struct iwl_notif_statistics *stats;
- stats = &pkt->u.stats;
+ stats = (void *)&pkt->data;
flag = &stats->flag;
common = &stats->general.common;
rx_non_phy = &stats->rx.general;
@@ -542,6 +547,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv,
WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n",
len, sizeof(struct iwl_bt_notif_statistics),
sizeof(struct iwl_notif_statistics));
+ spin_unlock(&priv->statistics.lock);
return 0;
}
@@ -569,7 +575,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv,
priv->rx_statistics_jiffies = stamp;
- set_bit(STATUS_STATISTICS, &priv->shrd->status);
+ set_bit(STATUS_STATISTICS, &priv->status);
/* Reschedule the statistics timer to occur in
* reg_recalib_period seconds to ensure we get a
@@ -578,23 +584,27 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv,
mod_timer(&priv->statistics_periodic, jiffies +
msecs_to_jiffies(reg_recalib_period * 1000));
- if (unlikely(!test_bit(STATUS_SCANNING, &priv->shrd->status)) &&
+ if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
(pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
iwlagn_rx_calc_noise(priv);
queue_work(priv->workqueue, &priv->run_time_calib_work);
}
if (cfg(priv)->lib->temperature && change)
cfg(priv)->lib->temperature(priv);
+
+ spin_unlock(&priv->statistics.lock);
+
return 0;
}
static int iwlagn_rx_reply_statistics(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_notif_statistics *stats = (void *)pkt->data;
- if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
+ if (le32_to_cpu(stats->flag) & UCODE_STATISTICS_CLEAR_MSK) {
#ifdef CONFIG_IWLWIFI_DEBUGFS
memset(&priv->accum_stats, 0,
sizeof(priv->accum_stats));
@@ -612,12 +622,13 @@ static int iwlagn_rx_reply_statistics(struct iwl_priv *priv,
/* Handle notification from uCode that card's power state is changing
* due to software, hardware, or critical temperature RFKILL */
static int iwlagn_rx_card_state_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
- unsigned long status = priv->shrd->status;
+ struct iwl_card_state_notif *card_state_notif = (void *)pkt->data;
+ u32 flags = le32_to_cpu(card_state_notif->flags);
+ unsigned long status = priv->status;
IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n",
(flags & HW_CARD_DISABLED) ? "Kill" : "On",
@@ -647,32 +658,31 @@ static int iwlagn_rx_card_state_notif(struct iwl_priv *priv,
iwl_tt_exit_ct_kill(priv);
if (flags & HW_CARD_DISABLED)
- set_bit(STATUS_RF_KILL_HW, &priv->shrd->status);
+ set_bit(STATUS_RF_KILL_HW, &priv->status);
else
- clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status);
+ clear_bit(STATUS_RF_KILL_HW, &priv->status);
if (!(flags & RXON_CARD_DISABLED))
iwl_scan_cancel(priv);
if ((test_bit(STATUS_RF_KILL_HW, &status) !=
- test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)))
+ test_bit(STATUS_RF_KILL_HW, &priv->status)))
wiphy_rfkill_set_hw_state(priv->hw->wiphy,
- test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
+ test_bit(STATUS_RF_KILL_HW, &priv->status));
else
wake_up(&priv->shrd->wait_command_queue);
return 0;
}
static int iwlagn_rx_missed_beacon_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_missed_beacon_notif *missed_beacon;
+ struct iwl_missed_beacon_notif *missed_beacon = (void *)pkt->data;
- missed_beacon = &pkt->u.missed_beacon;
if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
priv->missed_beacon_threshold) {
IWL_DEBUG_CALIB(priv,
@@ -681,7 +691,7 @@ static int iwlagn_rx_missed_beacon_notif(struct iwl_priv *priv,
le32_to_cpu(missed_beacon->total_missed_becons),
le32_to_cpu(missed_beacon->num_recvd_beacons),
le32_to_cpu(missed_beacon->num_expected_beacons));
- if (!test_bit(STATUS_SCANNING, &priv->shrd->status))
+ if (!test_bit(STATUS_SCANNING, &priv->status))
iwl_init_sensitivity(priv);
}
return 0;
@@ -690,13 +700,13 @@ static int iwlagn_rx_missed_beacon_notif(struct iwl_priv *priv,
/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
* This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
static int iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
priv->last_phy_res_valid = true;
- memcpy(&priv->last_phy_res, pkt->u.raw,
+ memcpy(&priv->last_phy_res, pkt->data,
sizeof(struct iwl_rx_phy_res));
return 0;
}
@@ -757,12 +767,14 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
struct ieee80211_hdr *hdr,
u16 len,
u32 ampdu_status,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct ieee80211_rx_status *stats)
{
struct sk_buff *skb;
__le16 fc = hdr->frame_control;
struct iwl_rxon_context *ctx;
+ struct page *p;
+ int offset;
/* We only process data packets if the interface is open */
if (unlikely(!priv->is_open)) {
@@ -782,7 +794,9 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
return;
}
- skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
+ offset = (void *)hdr - rxb_addr(rxb);
+ p = rxb_steal_page(rxb);
+ skb_add_rx_frag(skb, 0, p, offset, len);
iwl_update_stats(priv, false, fc, len);
@@ -793,23 +807,18 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
* sometimes even after already having transmitted frames for the
* association because the new RXON may reset the information.
*/
- if (unlikely(ieee80211_is_beacon(fc))) {
+ if (unlikely(ieee80211_is_beacon(fc) && priv->passive_no_rx)) {
for_each_context(priv, ctx) {
- if (!ctx->last_tx_rejected)
- continue;
if (compare_ether_addr(hdr->addr3,
ctx->active.bssid_addr))
continue;
- ctx->last_tx_rejected = false;
- iwl_trans_wake_any_queue(trans(priv), ctx->ctxid,
- "channel got active");
+ iwlagn_lift_passive_no_rx(priv);
}
}
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
ieee80211_rx(priv->hw, skb);
- rxb->page = NULL;
}
static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
@@ -915,7 +924,7 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv,
/* Called for REPLY_RX (legacy ABG frames), or
* REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct ieee80211_hdr *header;
@@ -938,12 +947,12 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
* received.
*/
if (pkt->hdr.cmd == REPLY_RX) {
- phy_res = (struct iwl_rx_phy_res *)pkt->u.raw;
- header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res)
+ phy_res = (struct iwl_rx_phy_res *)pkt->data;
+ header = (struct ieee80211_hdr *)(pkt->data + sizeof(*phy_res)
+ phy_res->cfg_phy_cnt);
len = le16_to_cpu(phy_res->byte_count);
- rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) +
+ rx_pkt_status = *(__le32 *)(pkt->data + sizeof(*phy_res) +
phy_res->cfg_phy_cnt + len);
ampdu_status = le32_to_cpu(rx_pkt_status);
} else {
@@ -952,10 +961,10 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
return 0;
}
phy_res = &priv->last_phy_res;
- amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw;
- header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
+ amsdu = (struct iwl_rx_mpdu_res_start *)pkt->data;
+ header = (struct ieee80211_hdr *)(pkt->data + sizeof(*amsdu));
len = le16_to_cpu(amsdu->byte_count);
- rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len);
+ rx_pkt_status = *(__le32 *)(pkt->data + sizeof(*amsdu) + len);
ampdu_status = iwlagn_translate_rx_status(priv,
le32_to_cpu(rx_pkt_status));
}
@@ -1035,12 +1044,12 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
}
static int iwlagn_rx_noa_notification(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_wipan_noa_data *new_data, *old_data;
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_wipan_noa_notification *noa_notif = (void *)pkt->u.raw;
+ struct iwl_wipan_noa_notification *noa_notif = (void *)pkt->data;
/* no condition -- we're in softirq */
old_data = rcu_dereference_protected(priv->noa_data, true);
@@ -1086,7 +1095,7 @@ static int iwlagn_rx_noa_notification(struct iwl_priv *priv,
*/
void iwl_setup_rx_handlers(struct iwl_priv *priv)
{
- int (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+ int (**handlers)(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
handlers = priv->rx_handlers;
@@ -1131,21 +1140,20 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
/* set up notification wait support */
- spin_lock_init(&priv->shrd->notif_wait_lock);
- INIT_LIST_HEAD(&priv->shrd->notif_waits);
- init_waitqueue_head(&priv->shrd->notif_waitq);
+ iwl_notification_wait_init(&priv->notif_wait);
/* Set up BT Rx handlers */
- if (cfg(priv)->lib->bt_rx_handler_setup)
- cfg(priv)->lib->bt_rx_handler_setup(priv);
-
+ if (cfg(priv)->bt_params)
+ iwlagn_bt_rx_handler_setup(priv);
}
-int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_mem_buffer *rxb,
- struct iwl_device_cmd *cmd)
+int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+ void (*pre_rx_handler)(struct iwl_priv *,
+ struct iwl_rx_cmd_buffer *);
int err = 0;
/*
@@ -1153,30 +1161,22 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_mem_buffer *rxb,
* even if the RX handler consumes the RXB we have
* access to it in the notification wait entry.
*/
- if (!list_empty(&priv->shrd->notif_waits)) {
- struct iwl_notification_wait *w;
-
- spin_lock(&priv->shrd->notif_wait_lock);
- list_for_each_entry(w, &priv->shrd->notif_waits, list) {
- if (w->cmd != pkt->hdr.cmd)
- continue;
- IWL_DEBUG_RX(priv,
- "Notif: %s, 0x%02x - wake the callers up\n",
- get_cmd_string(pkt->hdr.cmd),
- pkt->hdr.cmd);
- w->triggered = true;
- if (w->fn)
- w->fn(trans(priv), pkt, w->fn_data);
- }
- spin_unlock(&priv->shrd->notif_wait_lock);
-
- wake_up_all(&priv->shrd->notif_waitq);
- }
-
- if (priv->pre_rx_handler &&
- priv->shrd->ucode_owner == IWL_OWNERSHIP_TM)
- priv->pre_rx_handler(priv, rxb);
- else {
+ iwl_notification_wait_notify(&priv->notif_wait, pkt);
+
+ /* RX data may be forwarded to userspace (using pre_rx_handler) in one
+ * of two cases: the first, that the user owns the uCode through
+ * testmode - in such case the pre_rx_handler is set and no further
+ * processing takes place. The other case is when the user want to
+ * monitor the rx w/o affecting the regular flow - the pre_rx_handler
+ * will be set but the ownership flag != IWL_OWNERSHIP_TM and the flow
+ * continues.
+ * We need to use ACCESS_ONCE to prevent a case where the handler
+ * changes between the check and the call.
+ */
+ pre_rx_handler = ACCESS_ONCE(priv->pre_rx_handler);
+ if (pre_rx_handler)
+ pre_rx_handler(priv, rxb);
+ if (priv->ucode_owner != IWL_OWNERSHIP_TM) {
/* Based on type of command response or notification,
* handle those that need handling via function in
* rx_handlers table. See iwl_setup_rx_handlers() */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 73653a6cf32..36909077f99 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -39,7 +39,7 @@ static int iwlagn_disable_bss(struct iwl_priv *priv,
int ret;
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd,
+ ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd,
CMD_SYNC, sizeof(*send), send);
send->filter_flags = old_filter;
@@ -60,13 +60,13 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
u8 old_dev_type = send->dev_type;
int ret;
- iwl_init_notification_wait(priv->shrd, &disable_wait,
- REPLY_WIPAN_DEACTIVATION_COMPLETE,
- NULL, NULL);
+ iwl_init_notification_wait(&priv->notif_wait, &disable_wait,
+ REPLY_WIPAN_DEACTIVATION_COMPLETE,
+ NULL, NULL);
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
send->dev_type = RXON_DEV_TYPE_P2P;
- ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd,
+ ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd,
CMD_SYNC, sizeof(*send), send);
send->filter_flags = old_filter;
@@ -74,9 +74,10 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
if (ret) {
IWL_ERR(priv, "Error disabling PAN (%d)\n", ret);
- iwl_remove_notification(priv->shrd, &disable_wait);
+ iwl_remove_notification(&priv->notif_wait, &disable_wait);
} else {
- ret = iwl_wait_notification(priv->shrd, &disable_wait, HZ);
+ ret = iwl_wait_notification(&priv->notif_wait,
+ &disable_wait, HZ);
if (ret)
IWL_ERR(priv, "Timed out waiting for PAN disable\n");
}
@@ -92,7 +93,7 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv,
int ret;
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC,
+ ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC,
sizeof(*send), send);
send->filter_flags = old_filter;
@@ -121,7 +122,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
ctx->qos_data.qos_active,
ctx->qos_data.def_qos_parm.qos_flags);
- ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->qos_cmd, CMD_SYNC,
+ ret = iwl_dvm_send_cmd_pdu(priv, ctx->qos_cmd, CMD_SYNC,
sizeof(struct iwl_qosparam_cmd),
&ctx->qos_data.def_qos_parm);
if (ret)
@@ -131,7 +132,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
static int iwlagn_update_beacon(struct iwl_priv *priv,
struct ieee80211_vif *vif)
{
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
dev_kfree_skb(priv->beacon_skb);
priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif);
@@ -180,7 +181,7 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
ctx->staging.ofdm_ht_triple_stream_basic_rates;
rxon_assoc.acquisition_data = ctx->staging.acquisition_data;
- ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_assoc_cmd,
+ ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_assoc_cmd,
CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc);
return ret;
}
@@ -266,7 +267,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
* Associated RXON doesn't clear the station table in uCode,
* so we don't need to restore stations etc. after this.
*/
- ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC,
+ ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC,
sizeof(struct iwl_rxon_cmd), &ctx->staging);
if (ret) {
IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
@@ -274,8 +275,6 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
}
memcpy(active, &ctx->staging, sizeof(*active));
- iwl_reprogram_ap_sta(priv, ctx);
-
/* IBSS beacon needs to be sent after setting assoc */
if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC))
if (iwlagn_update_beacon(priv, ctx->vif))
@@ -315,7 +314,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS];
ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN];
@@ -362,7 +361,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
slot0 = bcnint / 2;
slot1 = bcnint - slot0;
- if (test_bit(STATUS_SCAN_HW, &priv->shrd->status) ||
+ if (test_bit(STATUS_SCAN_HW, &priv->status) ||
(!ctx_bss->vif->bss_conf.idle &&
!ctx_bss->vif->bss_conf.assoc)) {
slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME;
@@ -378,7 +377,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
ctx_pan->beacon_int;
slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1);
- if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
+ if (test_bit(STATUS_SCAN_HW, &priv->status)) {
slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME;
slot1 = IWL_MIN_SLOT_TIME;
}
@@ -387,7 +386,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
cmd.slots[0].width = cpu_to_le16(slot0);
cmd.slots[1].width = cpu_to_le16(slot1);
- ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WIPAN_PARAMS, CMD_SYNC,
+ ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, CMD_SYNC,
sizeof(cmd), &cmd);
if (ret)
IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);
@@ -420,12 +419,9 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
int ret;
- lockdep_assert_held(&priv->shrd->mutex);
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
- return -EINVAL;
+ lockdep_assert_held(&priv->mutex);
- if (!iwl_is_alive(priv->shrd))
+ if (!iwl_is_alive(priv))
return -EBUSY;
/* This function hardcodes a bunch of dual-mode assumptions */
@@ -434,10 +430,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
if (!ctx->is_active)
return 0;
- /* override BSSID if necessary due to preauth */
- if (ctx->preauth_bssid)
- memcpy(ctx->staging.bssid_addr, ctx->bssid, ETH_ALEN);
-
/* always get timestamp with Rx frame */
ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
@@ -445,8 +437,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
* force CTS-to-self frames protection if RTS-CTS is not preferred
* one aggregation protection method
*/
- if (!(cfg(priv)->ht_params &&
- cfg(priv)->ht_params->use_rts_for_aggregation))
+ if (!hw_params(priv).use_rts_for_aggregation)
ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
@@ -466,7 +457,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
* receive commit_rxon request
* abort any previous channel switch if still in process
*/
- if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status) &&
+ if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) &&
(priv->switch_channel != ctx->staging.channel)) {
IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
le16_to_cpu(priv->switch_channel));
@@ -558,17 +549,14 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
IWL_DEBUG_MAC80211(priv, "enter: changed %#x", changed);
- mutex_lock(&priv->shrd->mutex);
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
- goto out;
+ mutex_lock(&priv->mutex);
- if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) {
+ if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
goto out;
}
- if (!iwl_is_ready(priv->shrd)) {
+ if (!iwl_is_ready(priv)) {
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
goto out;
}
@@ -590,8 +578,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
- unsigned long flags;
-
ch_info = iwl_get_channel_info(priv, channel->band,
channel->hw_value);
if (!is_channel_valid(ch_info)) {
@@ -600,8 +586,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
goto out;
}
- spin_lock_irqsave(&priv->shrd->lock, flags);
-
for_each_context(priv, ctx) {
/* Configure HT40 channels */
if (ctx->ht.enabled != conf_is_ht(conf))
@@ -636,8 +620,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
ctx->vif);
}
- spin_unlock_irqrestore(&priv->shrd->lock, flags);
-
iwl_update_bcast_stations(priv);
/*
@@ -668,7 +650,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
iwlagn_commit_rxon(priv, ctx);
}
out:
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return ret;
@@ -685,7 +667,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
struct ieee80211_sta_ht_cap *ht_cap;
bool need_multiple;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
switch (vif->type) {
case NL80211_IFTYPE_STATION:
@@ -789,7 +771,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
memset(&cmd, 0, sizeof(cmd));
iwl_set_calib_hdr(&cmd.hdr,
priv->phy_calib_chain_noise_reset_cmd);
- ret = iwl_trans_send_cmd_pdu(trans(priv),
+ ret = iwl_dvm_send_cmd_pdu(priv,
REPLY_PHY_CALIBRATION_CMD,
CMD_SYNC, sizeof(cmd), &cmd);
if (ret)
@@ -810,17 +792,17 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
int ret;
bool force = false;
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
- if (unlikely(!iwl_is_ready(priv->shrd))) {
+ if (unlikely(!iwl_is_ready(priv))) {
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
return;
}
if (unlikely(!ctx->vif)) {
IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n");
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
return;
}
@@ -851,12 +833,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
* not get stuck in this case either since it
* can happen if userspace gets confused.
*/
- if (ctx->last_tx_rejected) {
- ctx->last_tx_rejected = false;
- iwl_trans_wake_any_queue(trans(priv),
- ctx->ctxid,
- "Disassoc: flush queue");
- }
+ iwlagn_lift_passive_no_rx(priv);
+
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
if (ctx->ctxid == IWL_RXON_CTX_BSS)
@@ -932,7 +910,6 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
if (!priv->disable_chain_noise_cal)
iwlagn_chain_noise_reset(priv);
priv->start_calib = 1;
- WARN_ON(ctx->preauth_bssid);
}
if (changes & BSS_CHANGED_IBSS) {
@@ -950,7 +927,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
IWL_ERR(priv, "Error sending IBSS beacon\n");
}
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
}
void iwlagn_post_scan(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
index f1298cd6a19..c4175603864 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
@@ -26,7 +26,7 @@
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
-
+#include <linux/etherdevice.h>
#include <net/mac80211.h>
#include "iwl-dev.h"
@@ -34,9 +34,10 @@
#include "iwl-agn.h"
#include "iwl-trans.h"
-/* priv->shrd->sta_lock must be held */
static int iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
{
+ lockdep_assert_held(&priv->sta_lock);
+
if (sta_id >= IWLAGN_STATION_COUNT) {
IWL_ERR(priv, "invalid sta_id %u", sta_id);
return -EINVAL;
@@ -63,8 +64,8 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
struct iwl_addsta_cmd *addsta,
struct iwl_rx_packet *pkt)
{
+ struct iwl_add_sta_resp *add_sta_resp = (void *)pkt->data;
u8 sta_id = addsta->sta.sta_id;
- unsigned long flags;
int ret = -EIO;
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
@@ -76,9 +77,9 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
sta_id);
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock(&priv->sta_lock);
- switch (pkt->u.add_sta.status) {
+ switch (add_sta_resp->status) {
case ADD_STA_SUCCESS_MSK:
IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
ret = iwl_sta_ucode_activate(priv, sta_id);
@@ -97,7 +98,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
break;
default:
IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n",
- pkt->u.add_sta.status);
+ add_sta_resp->status);
break;
}
@@ -118,12 +119,12 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
priv->stations[sta_id].sta.mode ==
STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
addsta->sta.addr);
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock(&priv->sta_lock);
return ret;
}
-int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -153,14 +154,14 @@ int iwl_send_add_sta(struct iwl_priv *priv,
might_sleep();
}
- ret = iwl_trans_send_cmd(trans(priv), &cmd);
+ ret = iwl_dvm_send_cmd(priv, &cmd);
if (ret || (flags & CMD_ASYNC))
return ret;
/*else the command was successfully sent in SYNC mode, need to free
* the reply page */
- iwl_free_pages(priv->shrd, cmd.reply_page);
+ iwl_free_resp(&cmd);
if (cmd.handler_status)
IWL_ERR(priv, "%s - error in the CMD response %d", __func__,
@@ -169,34 +170,38 @@ int iwl_send_add_sta(struct iwl_priv *priv,
return cmd.handler_status;
}
-static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
- struct ieee80211_sta *sta,
- struct iwl_rxon_context *ctx)
+static void iwl_sta_calc_ht_flags(struct iwl_priv *priv,
+ struct ieee80211_sta *sta,
+ struct iwl_rxon_context *ctx,
+ __le32 *flags, __le32 *mask)
{
struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap;
- __le32 sta_flags;
u8 mimo_ps_mode;
+ *mask = STA_FLG_RTS_MIMO_PROT_MSK |
+ STA_FLG_MIMO_DIS_MSK |
+ STA_FLG_HT40_EN_MSK |
+ STA_FLG_MAX_AGG_SIZE_MSK |
+ STA_FLG_AGG_MPDU_DENSITY_MSK;
+ *flags = 0;
+
if (!sta || !sta_ht_inf->ht_supported)
- goto done;
+ return;
mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
- IWL_DEBUG_ASSOC(priv, "spatial multiplexing power save mode: %s\n",
+
+ IWL_DEBUG_INFO(priv, "STA %pM SM PS mode: %s\n",
(mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ?
"static" :
(mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ?
"dynamic" : "disabled");
- sta_flags = priv->stations[index].sta.station_flags;
-
- sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK);
-
switch (mimo_ps_mode) {
case WLAN_HT_CAP_SM_PS_STATIC:
- sta_flags |= STA_FLG_MIMO_DIS_MSK;
+ *flags |= STA_FLG_MIMO_DIS_MSK;
break;
case WLAN_HT_CAP_SM_PS_DYNAMIC:
- sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK;
+ *flags |= STA_FLG_RTS_MIMO_PROT_MSK;
break;
case WLAN_HT_CAP_SM_PS_DISABLED:
break;
@@ -205,20 +210,53 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
break;
}
- sta_flags |= cpu_to_le32(
- (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
+ *flags |= cpu_to_le32(
+ (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
- sta_flags |= cpu_to_le32(
- (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
+ *flags |= cpu_to_le32(
+ (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
- sta_flags |= STA_FLG_HT40_EN_MSK;
- else
- sta_flags &= ~STA_FLG_HT40_EN_MSK;
+ *flags |= STA_FLG_HT40_EN_MSK;
+}
- priv->stations[index].sta.station_flags = sta_flags;
- done:
- return;
+int iwl_sta_update_ht(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ struct ieee80211_sta *sta)
+{
+ u8 sta_id = iwl_sta_id(sta);
+ __le32 flags, mask;
+ struct iwl_addsta_cmd cmd;
+
+ if (WARN_ON_ONCE(sta_id == IWL_INVALID_STATION))
+ return -EINVAL;
+
+ iwl_sta_calc_ht_flags(priv, sta, ctx, &flags, &mask);
+
+ spin_lock_bh(&priv->sta_lock);
+ priv->stations[sta_id].sta.station_flags &= ~mask;
+ priv->stations[sta_id].sta.station_flags |= flags;
+ spin_unlock_bh(&priv->sta_lock);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.mode = STA_CONTROL_MODIFY_MSK;
+ cmd.station_flags_msk = mask;
+ cmd.station_flags = flags;
+ cmd.sta.sta_id = sta_id;
+
+ return iwl_send_add_sta(priv, &cmd, CMD_SYNC);
+}
+
+static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
+ struct ieee80211_sta *sta,
+ struct iwl_rxon_context *ctx)
+{
+ __le32 flags, mask;
+
+ iwl_sta_calc_ht_flags(priv, sta, ctx, &flags, &mask);
+
+ lockdep_assert_held(&priv->sta_lock);
+ priv->stations[index].sta.station_flags &= ~mask;
+ priv->stations[index].sta.station_flags |= flags;
}
/**
@@ -317,18 +355,17 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
const u8 *addr, bool is_ap,
struct ieee80211_sta *sta, u8 *sta_id_r)
{
- unsigned long flags_spin;
int ret = 0;
u8 sta_id;
struct iwl_addsta_cmd sta_cmd;
*sta_id_r = 0;
- spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+ spin_lock_bh(&priv->sta_lock);
sta_id = iwl_prep_station(priv, ctx, addr, is_ap, sta);
if (sta_id == IWL_INVALID_STATION) {
IWL_ERR(priv, "Unable to prepare station %pM for addition\n",
addr);
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ spin_unlock_bh(&priv->sta_lock);
return -EINVAL;
}
@@ -340,7 +377,7 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
IWL_DEBUG_INFO(priv, "STA %d already in process of being "
"added.\n", sta_id);
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ spin_unlock_bh(&priv->sta_lock);
return -EEXIST;
}
@@ -348,24 +385,24 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not "
"adding again.\n", sta_id, addr);
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ spin_unlock_bh(&priv->sta_lock);
return -EEXIST;
}
priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS;
memcpy(&sta_cmd, &priv->stations[sta_id].sta,
sizeof(struct iwl_addsta_cmd));
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ spin_unlock_bh(&priv->sta_lock);
/* Add station to device's station table */
ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
if (ret) {
- spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+ spin_lock_bh(&priv->sta_lock);
IWL_ERR(priv, "Adding station %pM failed.\n",
priv->stations[sta_id].sta.sta.addr);
priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ spin_unlock_bh(&priv->sta_lock);
}
*sta_id_r = sta_id;
return ret;
@@ -373,11 +410,11 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
/**
* iwl_sta_ucode_deactivate - deactivate ucode status for a station
- *
- * priv->shrd->sta_lock must be held
*/
static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id)
{
+ lockdep_assert_held(&priv->sta_lock);
+
/* Ucode must be active and driver must be non active */
if ((priv->stations[sta_id].used &
(IWL_STA_UCODE_ACTIVE | IWL_STA_DRIVER_ACTIVE)) !=
@@ -396,8 +433,6 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
{
struct iwl_rx_packet *pkt;
int ret;
-
- unsigned long flags_spin;
struct iwl_rem_sta_cmd rm_sta_cmd;
struct iwl_host_cmd cmd = {
@@ -413,12 +448,12 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
cmd.flags |= CMD_WANT_SKB;
- ret = iwl_trans_send_cmd(trans(priv), &cmd);
+ ret = iwl_dvm_send_cmd(priv, &cmd);
if (ret)
return ret;
- pkt = (struct iwl_rx_packet *)cmd.reply_page;
+ pkt = cmd.resp_pkt;
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
pkt->hdr.flags);
@@ -426,14 +461,13 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
}
if (!ret) {
- switch (pkt->u.rem_sta.status) {
+ struct iwl_rem_sta_resp *rem_sta_resp = (void *)pkt->data;
+ switch (rem_sta_resp->status) {
case REM_STA_SUCCESS_MSK:
if (!temporary) {
- spin_lock_irqsave(&priv->shrd->sta_lock,
- flags_spin);
+ spin_lock_bh(&priv->sta_lock);
iwl_sta_ucode_deactivate(priv, sta_id);
- spin_unlock_irqrestore(&priv->shrd->sta_lock,
- flags_spin);
+ spin_unlock_bh(&priv->sta_lock);
}
IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
break;
@@ -443,7 +477,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
break;
}
}
- iwl_free_pages(priv->shrd, cmd.reply_page);
+ iwl_free_resp(&cmd);
return ret;
}
@@ -454,10 +488,9 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
const u8 *addr)
{
- unsigned long flags;
u8 tid;
- if (!iwl_is_ready(priv->shrd)) {
+ if (!iwl_is_ready(priv)) {
IWL_DEBUG_INFO(priv,
"Unable to remove station %pM, device not ready.\n",
addr);
@@ -475,7 +508,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
if (WARN_ON(sta_id == IWL_INVALID_STATION))
return -EINVAL;
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock_bh(&priv->sta_lock);
if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n",
@@ -505,14 +538,49 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
if (WARN_ON(priv->num_stations < 0))
priv->num_stations = 0;
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
return iwl_send_remove_station(priv, addr, sta_id, false);
out_err:
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
return -EINVAL;
}
+void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id,
+ const u8 *addr)
+{
+ u8 tid;
+
+ if (!iwl_is_ready(priv)) {
+ IWL_DEBUG_INFO(priv,
+ "Unable to remove station %pM, device not ready.\n",
+ addr);
+ return;
+ }
+
+ IWL_DEBUG_ASSOC(priv, "Deactivating STA: %pM (%d)\n", addr, sta_id);
+
+ if (WARN_ON_ONCE(sta_id == IWL_INVALID_STATION))
+ return;
+
+ spin_lock_bh(&priv->sta_lock);
+
+ WARN_ON_ONCE(!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE));
+
+ for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
+ memset(&priv->tid_data[sta_id][tid], 0,
+ sizeof(priv->tid_data[sta_id][tid]));
+
+ priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+
+ priv->num_stations--;
+
+ if (WARN_ON_ONCE(priv->num_stations < 0))
+ priv->num_stations = 0;
+
+ spin_unlock_bh(&priv->sta_lock);
+}
+
/**
* iwl_clear_ucode_stations - clear ucode station table bits
*
@@ -525,12 +593,11 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{
int i;
- unsigned long flags_spin;
bool cleared = false;
IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n");
- spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+ spin_lock_bh(&priv->sta_lock);
for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
if (ctx && ctx->ctxid != priv->stations[i].ctxid)
continue;
@@ -542,7 +609,7 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv,
cleared = true;
}
}
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ spin_unlock_bh(&priv->sta_lock);
if (!cleared)
IWL_DEBUG_INFO(priv,
@@ -561,20 +628,19 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
struct iwl_addsta_cmd sta_cmd;
struct iwl_link_quality_cmd lq;
- unsigned long flags_spin;
int i;
bool found = false;
int ret;
bool send_lq;
- if (!iwl_is_ready(priv->shrd)) {
+ if (!iwl_is_ready(priv)) {
IWL_DEBUG_INFO(priv,
"Not ready yet, not restoring any stations.\n");
return;
}
IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n");
- spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+ spin_lock_bh(&priv->sta_lock);
for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
if (ctx->ctxid != priv->stations[i].ctxid)
continue;
@@ -594,27 +660,24 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
sizeof(struct iwl_addsta_cmd));
send_lq = false;
if (priv->stations[i].lq) {
- if (priv->shrd->wowlan)
+ if (priv->wowlan)
iwl_sta_fill_lq(priv, ctx, i, &lq);
else
memcpy(&lq, priv->stations[i].lq,
sizeof(struct iwl_link_quality_cmd));
send_lq = true;
}
- spin_unlock_irqrestore(&priv->shrd->sta_lock,
- flags_spin);
+ spin_unlock_bh(&priv->sta_lock);
ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
if (ret) {
- spin_lock_irqsave(&priv->shrd->sta_lock,
- flags_spin);
+ spin_lock_bh(&priv->sta_lock);
IWL_ERR(priv, "Adding station %pM failed.\n",
priv->stations[i].sta.sta.addr);
priv->stations[i].used &=
~IWL_STA_DRIVER_ACTIVE;
priv->stations[i].used &=
~IWL_STA_UCODE_INPROGRESS;
- spin_unlock_irqrestore(&priv->shrd->sta_lock,
- flags_spin);
+ spin_unlock_bh(&priv->sta_lock);
}
/*
* Rate scaling has already been initialized, send
@@ -623,12 +686,12 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
if (send_lq)
iwl_send_lq_cmd(priv, ctx, &lq,
CMD_SYNC, true);
- spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+ spin_lock_bh(&priv->sta_lock);
priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
}
}
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ spin_unlock_bh(&priv->sta_lock);
if (!found)
IWL_DEBUG_INFO(priv, "Restoring all known stations .... "
"no stations to be restored.\n");
@@ -637,52 +700,6 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
"complete.\n");
}
-void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
- unsigned long flags;
- int sta_id = ctx->ap_sta_id;
- int ret;
- struct iwl_addsta_cmd sta_cmd;
- struct iwl_link_quality_cmd lq;
- bool active, have_lq = false;
-
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
- if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
- return;
- }
-
- memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
- sta_cmd.mode = 0;
- if (priv->stations[sta_id].lq) {
- memcpy(&lq, priv->stations[sta_id].lq, sizeof(lq));
- have_lq = true;
- }
-
- active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE;
- priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-
- if (active) {
- ret = iwl_send_remove_station(
- priv, priv->stations[sta_id].sta.sta.addr,
- sta_id, true);
- if (ret)
- IWL_ERR(priv, "failed to remove STA %pM (%d)\n",
- priv->stations[sta_id].sta.sta.addr, ret);
- }
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
- priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-
- ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
- if (ret)
- IWL_ERR(priv, "failed to re-add STA %pM (%d)\n",
- priv->stations[sta_id].sta.sta.addr, ret);
- if (have_lq)
- iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
-}
-
int iwl_get_free_ucode_key_offset(struct iwl_priv *priv)
{
int i;
@@ -696,10 +713,9 @@ int iwl_get_free_ucode_key_offset(struct iwl_priv *priv)
void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
{
- unsigned long flags;
int i;
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock_bh(&priv->sta_lock);
for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
if (!(priv->stations[i].used & IWL_STA_BCAST))
continue;
@@ -711,7 +727,7 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
kfree(priv->stations[i].lq);
priv->stations[i].lq = NULL;
}
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
}
#ifdef CONFIG_IWLWIFI_DEBUG
@@ -783,8 +799,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
struct iwl_link_quality_cmd *lq, u8 flags, bool init)
{
int ret = 0;
- unsigned long flags_spin;
-
struct iwl_host_cmd cmd = {
.id = REPLY_TX_LINK_QUALITY_CMD,
.len = { sizeof(struct iwl_link_quality_cmd), },
@@ -796,19 +810,19 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
return -EINVAL;
- spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+ spin_lock_bh(&priv->sta_lock);
if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ spin_unlock_bh(&priv->sta_lock);
return -EINVAL;
}
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ spin_unlock_bh(&priv->sta_lock);
iwl_dump_lq_cmd(priv, lq);
if (WARN_ON(init && (cmd.flags & CMD_ASYNC)))
return -EINVAL;
if (is_lq_table_valid(priv, ctx, lq))
- ret = iwl_trans_send_cmd(trans(priv), &cmd);
+ ret = iwl_dvm_send_cmd(priv, &cmd);
else
ret = -EINVAL;
@@ -819,9 +833,9 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
IWL_DEBUG_INFO(priv, "init LQ command complete, "
"clearing sta addition status for sta %d\n",
lq->sta_id);
- spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+ spin_lock_bh(&priv->sta_lock);
priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ spin_unlock_bh(&priv->sta_lock);
}
return ret;
}
@@ -834,7 +848,7 @@ void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
u32 rate_flags = 0;
__le32 rate_n_flags;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
memset(link_cmd, 0, sizeof(*link_cmd));
@@ -906,7 +920,6 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv,
int ret;
u8 sta_id;
struct iwl_link_quality_cmd *link_cmd;
- unsigned long flags;
if (sta_id_r)
*sta_id_r = IWL_INVALID_STATION;
@@ -920,9 +933,9 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv,
if (sta_id_r)
*sta_id_r = sta_id;
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock_bh(&priv->sta_lock);
priv->stations[sta_id].used |= IWL_STA_LOCAL;
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
/* Set up default rate scaling table in device's station table */
link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
@@ -937,9 +950,9 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv,
if (ret)
IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock_bh(&priv->sta_lock);
priv->stations[sta_id].lq = link_cmd;
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
return 0;
}
@@ -994,7 +1007,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
cmd.len[0] = cmd_size;
if (not_empty || send_if_empty)
- return iwl_trans_send_cmd(trans(priv), &cmd);
+ return iwl_dvm_send_cmd(priv, &cmd);
else
return 0;
}
@@ -1002,7 +1015,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
int iwl_restore_default_wep_keys(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
return iwl_send_static_wepkey_cmd(priv, ctx, false);
}
@@ -1013,13 +1026,13 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
{
int ret;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
keyconf->keyidx);
memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
- if (iwl_is_rfkill(priv->shrd)) {
+ if (iwl_is_rfkill(priv)) {
IWL_DEBUG_WEP(priv,
"Not sending REPLY_WEPKEY command due to RFKILL.\n");
/* but keys in device are clear anyway so return success */
@@ -1038,7 +1051,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
{
int ret;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
if (keyconf->keylen != WEP_KEY_LEN_128 &&
keyconf->keylen != WEP_KEY_LEN_64) {
@@ -1080,32 +1093,19 @@ static u8 iwlagn_key_sta_id(struct iwl_priv *priv,
struct ieee80211_sta *sta)
{
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
- u8 sta_id = IWL_INVALID_STATION;
if (sta)
- sta_id = iwl_sta_id(sta);
+ return iwl_sta_id(sta);
/*
* The device expects GTKs for station interfaces to be
* installed as GTKs for the AP station. If we have no
* station ID, then use the ap_sta_id in that case.
*/
- if (!sta && vif && vif_priv->ctx) {
- switch (vif->type) {
- case NL80211_IFTYPE_STATION:
- sta_id = vif_priv->ctx->ap_sta_id;
- break;
- default:
- /*
- * In all other cases, the key will be
- * used either for TX only or is bound
- * to a station already.
- */
- break;
- }
- }
+ if (vif->type == NL80211_IFTYPE_STATION && vif_priv->ctx)
+ return vif_priv->ctx->ap_sta_id;
- return sta_id;
+ return IWL_INVALID_STATION;
}
static int iwlagn_send_sta_key(struct iwl_priv *priv,
@@ -1113,14 +1113,13 @@ static int iwlagn_send_sta_key(struct iwl_priv *priv,
u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k,
u32 cmd_flags)
{
- unsigned long flags;
__le16 key_flags;
struct iwl_addsta_cmd sta_cmd;
int i;
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock_bh(&priv->sta_lock);
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
key_flags |= STA_KEY_FLG_MAP_KEY_MSK;
@@ -1187,7 +1186,6 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
struct ieee80211_key_conf *keyconf,
struct ieee80211_sta *sta)
{
- unsigned long flags;
struct iwl_addsta_cmd sta_cmd;
u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta);
__le16 key_flags;
@@ -1196,16 +1194,16 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
if (sta_id == IWL_INVALID_STATION)
return -ENOENT;
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock_bh(&priv->sta_lock);
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE))
sta_id = IWL_INVALID_STATION;
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
if (sta_id == IWL_INVALID_STATION)
return 0;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
ctx->key_mapping_keys--;
@@ -1245,7 +1243,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
if (sta_id == IWL_INVALID_STATION)
return -EINVAL;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv);
if (keyconf->hw_key_idx == WEP_INVALID_OFFSET)
@@ -1300,21 +1298,20 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{
struct iwl_link_quality_cmd *link_cmd;
- unsigned long flags;
u8 sta_id;
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock_bh(&priv->sta_lock);
sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL);
if (sta_id == IWL_INVALID_STATION) {
IWL_ERR(priv, "Unable to prepare broadcast station\n");
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
return -EINVAL;
}
priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
priv->stations[sta_id].used |= IWL_STA_BCAST;
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
if (!link_cmd) {
@@ -1323,9 +1320,9 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
return -ENOMEM;
}
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock_bh(&priv->sta_lock);
priv->stations[sta_id].lq = link_cmd;
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
return 0;
}
@@ -1339,7 +1336,6 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
int iwl_update_bcast_station(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{
- unsigned long flags;
struct iwl_link_quality_cmd *link_cmd;
u8 sta_id = ctx->bcast_sta_id;
@@ -1349,13 +1345,13 @@ int iwl_update_bcast_station(struct iwl_priv *priv,
return -ENOMEM;
}
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock_bh(&priv->sta_lock);
if (priv->stations[sta_id].lq)
kfree(priv->stations[sta_id].lq);
else
IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n");
priv->stations[sta_id].lq = link_cmd;
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
return 0;
}
@@ -1379,18 +1375,17 @@ int iwl_update_bcast_stations(struct iwl_priv *priv)
*/
int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
{
- unsigned long flags;
struct iwl_addsta_cmd sta_cmd;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
/* Remove "disable" flag, to enable Tx for this TID */
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock_bh(&priv->sta_lock);
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
}
@@ -1398,24 +1393,23 @@ int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
int tid, u16 ssn)
{
- unsigned long flags;
int sta_id;
struct iwl_addsta_cmd sta_cmd;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
sta_id = iwl_sta_id(sta);
if (sta_id == IWL_INVALID_STATION)
return -ENXIO;
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock_bh(&priv->sta_lock);
priv->stations[sta_id].sta.station_flags_msk = 0;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
}
@@ -1423,11 +1417,10 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
int tid)
{
- unsigned long flags;
int sta_id;
struct iwl_addsta_cmd sta_cmd;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
sta_id = iwl_sta_id(sta);
if (sta_id == IWL_INVALID_STATION) {
@@ -1435,13 +1428,13 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
return -ENXIO;
}
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock_bh(&priv->sta_lock);
priv->stations[sta_id].sta.station_flags_msk = 0;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
}
@@ -1450,16 +1443,14 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
{
- unsigned long flags;
-
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
- priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
- priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
- priv->stations[sta_id].sta.sta.modify_mask =
- STA_MODIFY_SLEEP_TX_COUNT_MSK;
- priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ struct iwl_addsta_cmd cmd = {
+ .mode = STA_CONTROL_MODIFY_MSK,
+ .station_flags = STA_FLG_PWR_SAVE_MSK,
+ .station_flags_msk = STA_FLG_PWR_SAVE_MSK,
+ .sta.sta_id = sta_id,
+ .sta.modify_mask = STA_MODIFY_SLEEP_TX_COUNT_MSK,
+ .sleep_tx_count = cpu_to_le16(cnt),
+ };
+ iwl_send_add_sta(priv, &cmd, CMD_ASYNC);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
index 56d7c0e3816..baaf5ba2fc3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
@@ -34,6 +34,7 @@
#include <net/mac80211.h>
+#include "iwl-agn.h"
#include "iwl-eeprom.h"
#include "iwl-dev.h"
#include "iwl-core.h"
@@ -173,7 +174,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
unsigned long flags;
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
if (tt->state == IWL_TI_CT_KILL) {
@@ -188,7 +189,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
}
iwl_read32(trans(priv), CSR_UCODE_DRV_GP1);
spin_lock_irqsave(&trans(priv)->reg_lock, flags);
- if (!iwl_grab_nic_access(trans(priv)))
+ if (likely(iwl_grab_nic_access(trans(priv))))
iwl_release_nic_access(trans(priv));
spin_unlock_irqrestore(&trans(priv)->reg_lock, flags);
@@ -224,7 +225,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data)
struct iwl_priv *priv = (struct iwl_priv *)data;
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
/* temperature timer expired, ready to go into CT_KILL state */
@@ -232,7 +233,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data)
IWL_DEBUG_TEMP(priv, "entering CT_KILL state when "
"temperature timer expired\n");
tt->state = IWL_TI_CT_KILL;
- set_bit(STATUS_CT_KILL, &priv->shrd->status);
+ set_bit(STATUS_CT_KILL, &priv->status);
iwl_perform_ct_kill_task(priv, true);
}
}
@@ -310,24 +311,23 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
tt->tt_power_mode = IWL_POWER_INDEX_5;
break;
}
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
if (old_state == IWL_TI_CT_KILL)
- clear_bit(STATUS_CT_KILL, &priv->shrd->status);
+ clear_bit(STATUS_CT_KILL, &priv->status);
if (tt->state != IWL_TI_CT_KILL &&
iwl_power_update_mode(priv, true)) {
/* TT state not updated
* try again during next temperature read
*/
if (old_state == IWL_TI_CT_KILL)
- set_bit(STATUS_CT_KILL, &priv->shrd->status);
+ set_bit(STATUS_CT_KILL, &priv->status);
tt->state = old_state;
IWL_ERR(priv, "Cannot update power mode, "
"TT state not updated\n");
} else {
if (tt->state == IWL_TI_CT_KILL) {
if (force) {
- set_bit(STATUS_CT_KILL,
- &priv->shrd->status);
+ set_bit(STATUS_CT_KILL, &priv->status);
iwl_perform_ct_kill_task(priv, true);
} else {
iwl_prepare_ct_kill_task(priv);
@@ -341,7 +341,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
IWL_DEBUG_TEMP(priv, "Power Index change to %u\n",
tt->tt_power_mode);
}
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
}
}
@@ -451,9 +451,9 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
* in case get disabled before */
iwl_set_rxon_ht(priv, &priv->current_ht_config);
}
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
if (old_state == IWL_TI_CT_KILL)
- clear_bit(STATUS_CT_KILL, &priv->shrd->status);
+ clear_bit(STATUS_CT_KILL, &priv->status);
if (tt->state != IWL_TI_CT_KILL &&
iwl_power_update_mode(priv, true)) {
/* TT state not updated
@@ -462,7 +462,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
IWL_ERR(priv, "Cannot update power mode, "
"TT state not updated\n");
if (old_state == IWL_TI_CT_KILL)
- set_bit(STATUS_CT_KILL, &priv->shrd->status);
+ set_bit(STATUS_CT_KILL, &priv->status);
tt->state = old_state;
} else {
IWL_DEBUG_TEMP(priv,
@@ -473,8 +473,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
if (force) {
IWL_DEBUG_TEMP(priv,
"Enter IWL_TI_CT_KILL\n");
- set_bit(STATUS_CT_KILL,
- &priv->shrd->status);
+ set_bit(STATUS_CT_KILL, &priv->status);
iwl_perform_ct_kill_task(priv, true);
} else {
iwl_prepare_ct_kill_task(priv);
@@ -486,7 +485,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
iwl_perform_ct_kill_task(priv, false);
}
}
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
}
}
@@ -505,10 +504,10 @@ static void iwl_bg_ct_enter(struct work_struct *work)
struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- if (!iwl_is_ready(priv->shrd))
+ if (!iwl_is_ready(priv))
return;
if (tt->state != IWL_TI_CT_KILL) {
@@ -534,10 +533,10 @@ static void iwl_bg_ct_exit(struct work_struct *work)
struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- if (!iwl_is_ready(priv->shrd))
+ if (!iwl_is_ready(priv))
return;
/* stop ct_kill_exit_tm timer */
@@ -564,7 +563,7 @@ static void iwl_bg_ct_exit(struct work_struct *work)
void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
{
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n");
@@ -573,7 +572,7 @@ void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
{
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n");
@@ -585,7 +584,7 @@ static void iwl_bg_tt_work(struct work_struct *work)
struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
s32 temp = priv->temperature; /* degrees CELSIUS except specified */
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
if (!priv->thermal_throttle.advanced_tt)
@@ -596,7 +595,7 @@ static void iwl_bg_tt_work(struct work_struct *work)
void iwl_tt_handler(struct iwl_priv *priv)
{
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 5f78567f418..34adedc74d3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -126,7 +126,7 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
u8 data_retry_limit;
u8 rate_plcp;
- if (priv->shrd->wowlan) {
+ if (priv->wowlan) {
rts_retry_limit = IWLAGN_LOW_RETRY_LIMIT;
data_retry_limit = IWLAGN_LOW_RETRY_LIMIT;
} else {
@@ -208,10 +208,9 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
}
static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
- struct ieee80211_tx_info *info,
- struct iwl_tx_cmd *tx_cmd,
- struct sk_buff *skb_frag,
- int sta_id)
+ struct ieee80211_tx_info *info,
+ struct iwl_tx_cmd *tx_cmd,
+ struct sk_buff *skb_frag)
{
struct ieee80211_key_conf *keyconf = info->control.hw_key;
@@ -249,6 +248,35 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
}
}
+/**
+ * iwl_sta_id_or_broadcast - return sta_id or broadcast sta
+ * @context: the current context
+ * @sta: mac80211 station
+ *
+ * In certain circumstances mac80211 passes a station pointer
+ * that may be %NULL, for example during TX or key setup. In
+ * that case, we need to use the broadcast station, so this
+ * inline wraps that pattern.
+ */
+static int iwl_sta_id_or_broadcast(struct iwl_rxon_context *context,
+ struct ieee80211_sta *sta)
+{
+ int sta_id;
+
+ if (!sta)
+ return context->bcast_sta_id;
+
+ sta_id = iwl_sta_id(sta);
+
+ /*
+ * mac80211 should not be passing a partially
+ * initialised station!
+ */
+ WARN_ON(sta_id == IWL_INVALID_STATION);
+
+ return sta_id;
+}
+
/*
* start REPLY_TX command process
*/
@@ -260,19 +288,16 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwl_device_cmd *dev_cmd = NULL;
struct iwl_tx_cmd *tx_cmd;
-
__le16 fc;
u8 hdr_len;
u16 len, seq_number = 0;
u8 sta_id, tid = IWL_MAX_TID_COUNT;
- unsigned long flags;
bool is_agg = false;
if (info->control.vif)
ctx = iwl_rxon_ctx_from_vif(info->control.vif);
- spin_lock_irqsave(&priv->shrd->lock, flags);
- if (iwl_is_rfkill(priv->shrd)) {
+ if (iwl_is_rfkill(priv)) {
IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
goto drop_unlock_priv;
}
@@ -308,7 +333,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
sta_id = ctx->bcast_sta_id;
else {
/* Find index into station table for destination station */
- sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta);
+ sta_id = iwl_sta_id_or_broadcast(ctx, info->control.sta);
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
hdr->addr1);
@@ -342,13 +367,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
if (info->flags & IEEE80211_TX_CTL_AMPDU)
is_agg = true;
- /* irqs already disabled/saved above when locking priv->shrd->lock */
- spin_lock(&priv->shrd->sta_lock);
-
- dev_cmd = kmem_cache_alloc(priv->tx_cmd_pool, GFP_ATOMIC);
+ dev_cmd = kmem_cache_alloc(iwl_tx_cmd_pool, GFP_ATOMIC);
if (unlikely(!dev_cmd))
- goto drop_unlock_sta;
+ goto drop_unlock_priv;
memset(dev_cmd, 0, sizeof(*dev_cmd));
tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload;
@@ -358,7 +380,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
tx_cmd->len = cpu_to_le16(len);
if (info->control.hw_key)
- iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id);
+ iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb);
/* TODO need this for burst mode later on */
iwlagn_tx_cmd_build_basic(priv, skb, tx_cmd, info, hdr, sta_id);
@@ -373,6 +395,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
info->driver_data[0] = ctx;
info->driver_data[1] = dev_cmd;
+ spin_lock(&priv->sta_lock);
+
if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) {
u8 *qc = NULL;
struct iwl_tid_data *tid_data;
@@ -418,8 +442,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
!ieee80211_has_morefrags(fc))
priv->tid_data[sta_id][tid].seq_number = seq_number;
- spin_unlock(&priv->shrd->sta_lock);
- spin_unlock_irqrestore(&priv->shrd->lock, flags);
+ spin_unlock(&priv->sta_lock);
/*
* Avoid atomic ops if it isn't an associated client.
@@ -435,10 +458,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
drop_unlock_sta:
if (dev_cmd)
- kmem_cache_free(priv->tx_cmd_pool, dev_cmd);
- spin_unlock(&priv->shrd->sta_lock);
+ kmem_cache_free(iwl_tx_cmd_pool, dev_cmd);
+ spin_unlock(&priv->sta_lock);
drop_unlock_priv:
- spin_unlock_irqrestore(&priv->shrd->lock, flags);
return -1;
}
@@ -446,7 +468,6 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid)
{
struct iwl_tid_data *tid_data;
- unsigned long flags;
int sta_id;
sta_id = iwl_sta_id(sta);
@@ -456,7 +477,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
return -ENXIO;
}
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock_bh(&priv->sta_lock);
tid_data = &priv->tid_data[sta_id][tid];
@@ -476,7 +497,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
IWL_WARN(priv, "Stopping AGG while state not ON "
"or starting for %d on %d (%d)\n", sta_id, tid,
priv->tid_data[sta_id][tid].agg.state);
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
return 0;
}
@@ -490,7 +511,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
tid_data->next_reclaimed);
priv->tid_data[sta_id][tid].agg.state =
IWL_EMPTYING_HW_QUEUE_DELBA;
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
return 0;
}
@@ -499,14 +520,10 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
turn_off:
priv->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF;
- /* do not restore/save irqs */
- spin_unlock(&priv->shrd->sta_lock);
- spin_lock(&priv->shrd->lock);
+ spin_unlock_bh(&priv->sta_lock);
iwl_trans_tx_agg_disable(trans(priv), sta_id, tid);
- spin_unlock_irqrestore(&priv->shrd->lock, flags);
-
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
return 0;
@@ -516,7 +533,6 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
{
struct iwl_tid_data *tid_data;
- unsigned long flags;
int sta_id;
int ret;
@@ -540,7 +556,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
if (ret)
return ret;
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock_bh(&priv->sta_lock);
tid_data = &priv->tid_data[sta_id][tid];
tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number);
@@ -549,7 +565,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
ret = iwl_trans_tx_agg_alloc(trans(priv), sta_id, tid);
if (ret) {
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
return ret;
}
@@ -566,7 +582,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
}
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
return ret;
}
@@ -576,14 +592,13 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
{
struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
- unsigned long flags;
u16 ssn;
buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF);
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock_bh(&priv->sta_lock);
ssn = priv->tid_data[sta_priv->sta_id][tid].agg.ssn;
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
iwl_trans_tx_agg_setup(trans(priv), ctx->ctxid, sta_priv->sta_id, tid,
buf_size, ssn);
@@ -608,8 +623,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
sta_priv->max_agg_bufsize =
min(sta_priv->max_agg_bufsize, buf_size);
- if (cfg(priv)->ht_params &&
- cfg(priv)->ht_params->use_rts_for_aggregation) {
+ if (hw_params(priv).use_rts_for_aggregation) {
/*
* switch to RTS/CTS if it is the prefer protection
* method for HT traffic
@@ -639,7 +653,7 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid)
struct ieee80211_vif *vif;
u8 *addr;
- lockdep_assert_held(&priv->shrd->sta_lock);
+ lockdep_assert_held(&priv->sta_lock);
addr = priv->stations[sta_id].sta.sta.addr;
ctx = priv->stations[sta_id].ctxid;
@@ -986,19 +1000,19 @@ static void iwl_check_abort_status(struct iwl_priv *priv,
{
if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
IWL_ERR(priv, "Tx flush command to flush out all frames\n");
- if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
queue_work(priv->workqueue, &priv->tx_flush);
}
}
-int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
int txq_id = SEQ_TO_QUEUE(sequence);
int cmd_index __maybe_unused = SEQ_TO_INDEX(sequence);
- struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+ struct iwlagn_tx_resp *tx_resp = (void *)pkt->data;
struct ieee80211_hdr *hdr;
u32 status = le16_to_cpu(tx_resp->status.status);
u16 ssn = iwlagn_get_scd_ssn(tx_resp);
@@ -1006,7 +1020,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
int sta_id;
int freed;
struct ieee80211_tx_info *info;
- unsigned long flags;
struct sk_buff_head skbs;
struct sk_buff *skb;
struct iwl_rxon_context *ctx;
@@ -1017,11 +1030,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >>
IWLAGN_TX_RES_RA_POS;
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock(&priv->sta_lock);
if (is_agg)
iwl_rx_reply_tx_agg(priv, tx_resp);
+ __skb_queue_head_init(&skbs);
+
if (tx_resp->frame_count == 1) {
u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl);
next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10);
@@ -1041,8 +1056,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
next_reclaimed = ssn;
}
- __skb_queue_head_init(&skbs);
-
if (tid != IWL_TID_NON_QOS) {
priv->tid_data[sta_id][tid].next_reclaimed =
next_reclaimed;
@@ -1051,12 +1064,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
}
/*we can free until ssn % q.n_bd not inclusive */
- WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id,
- ssn, status, &skbs));
+ WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid,
+ txq_id, ssn, &skbs));
iwlagn_check_ratid_empty(priv, sta_id, tid);
freed = 0;
- while (!skb_queue_empty(&skbs)) {
- skb = __skb_dequeue(&skbs);
+
+ /* process frames */
+ skb_queue_walk(&skbs, skb) {
hdr = (struct ieee80211_hdr *)skb->data;
if (!ieee80211_is_data_qos(hdr->frame_control))
@@ -1064,7 +1078,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
info = IEEE80211_SKB_CB(skb);
ctx = info->driver_data[0];
- kmem_cache_free(priv->tx_cmd_pool,
+ kmem_cache_free(iwl_tx_cmd_pool,
(info->driver_data[1]));
memset(&info->status, 0, sizeof(info->status));
@@ -1072,9 +1086,11 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
if (status == TX_STATUS_FAIL_PASSIVE_NO_RX &&
iwl_is_associated_ctx(ctx) && ctx->vif &&
ctx->vif->type == NL80211_IFTYPE_STATION) {
- ctx->last_tx_rejected = true;
- iwl_trans_stop_queue(trans(priv), txq_id,
- "Tx on passive channel");
+ /* block and stop all queues */
+ priv->passive_no_rx = true;
+ IWL_DEBUG_TX_QUEUES(priv, "stop all queues: "
+ "passive channel");
+ ieee80211_stop_queues(priv->hw);
IWL_DEBUG_TX_REPLY(priv,
"TXQ %d status %s (0x%08x) "
@@ -1098,8 +1114,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
if (!is_agg)
iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1);
- ieee80211_tx_status_irqsafe(priv->hw, skb);
-
freed++;
}
@@ -1107,7 +1121,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
}
iwl_check_abort_status(priv, tx_resp->frame_count, status);
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock(&priv->sta_lock);
+
+ while (!skb_queue_empty(&skbs)) {
+ skb = __skb_dequeue(&skbs);
+ ieee80211_tx_status(priv->hw, skb);
+ }
+
return 0;
}
@@ -1118,17 +1138,16 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
* of frames sent via aggregation.
*/
int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
+ struct iwl_compressed_ba_resp *ba_resp = (void *)pkt->data;
struct iwl_ht_agg *agg;
struct sk_buff_head reclaimed_skbs;
struct ieee80211_tx_info *info;
struct ieee80211_hdr *hdr;
struct sk_buff *skb;
- unsigned long flags;
int sta_id;
int tid;
int freed;
@@ -1140,7 +1159,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
* (in Tx queue's circular buffer) of first TFD/frame in window */
u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
- if (scd_flow >= hw_params(priv).max_txq_num) {
+ if (scd_flow >= cfg(priv)->base_params->num_of_queues) {
IWL_ERR(priv,
"BUG_ON scd_flow is bigger than number of queues\n");
return 0;
@@ -1150,12 +1169,12 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
tid = ba_resp->tid;
agg = &priv->tid_data[sta_id][tid].agg;
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ spin_lock(&priv->sta_lock);
if (unlikely(!agg->wait_for_ba)) {
if (unlikely(ba_resp->bitmap))
IWL_ERR(priv, "Received BA when not expected\n");
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ spin_unlock(&priv->sta_lock);
return 0;
}
@@ -1165,8 +1184,8 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
* block-ack window (we assume that they've been successfully
* transmitted ... if not, it's too late anyway). */
if (iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow,
- ba_resp_scd_ssn, 0, &reclaimed_skbs)) {
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ ba_resp_scd_ssn, &reclaimed_skbs)) {
+ spin_unlock(&priv->sta_lock);
return 0;
}
@@ -1202,9 +1221,8 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
iwlagn_check_ratid_empty(priv, sta_id, tid);
freed = 0;
- while (!skb_queue_empty(&reclaimed_skbs)) {
- skb = __skb_dequeue(&reclaimed_skbs);
+ skb_queue_walk(&reclaimed_skbs, skb) {
hdr = (struct ieee80211_hdr *)skb->data;
if (ieee80211_is_data_qos(hdr->frame_control))
@@ -1213,7 +1231,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
WARN_ON_ONCE(1);
info = IEEE80211_SKB_CB(skb);
- kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));
+ kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1]));
if (freed == 1) {
/* this is the first skb we deliver in this batch */
@@ -1227,10 +1245,14 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags,
info);
}
+ }
+
+ spin_unlock(&priv->sta_lock);
- ieee80211_tx_status_irqsafe(priv->hw, skb);
+ while (!skb_queue_empty(&reclaimed_skbs)) {
+ skb = __skb_dequeue(&reclaimed_skbs);
+ ieee80211_tx_status(priv->hw, skb);
}
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return 0;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index e0fef9f257c..28422c03d67 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -41,9 +41,7 @@
#include <asm/div64.h>
-#include "iwl-ucode.h"
#include "iwl-eeprom.h"
-#include "iwl-wifi.h"
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-io.h"
@@ -134,7 +132,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
* beacon contents.
*/
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
if (!priv->beacon_ctx) {
IWL_ERR(priv, "trying to build beacon w/o beacon context!\n");
@@ -199,7 +197,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
cmd.data[1] = priv->beacon_skb->data;
cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
- return iwl_trans_send_cmd(trans(priv), &cmd);
+ return iwl_dvm_send_cmd(priv, &cmd);
}
static void iwl_bg_beacon_update(struct work_struct *work)
@@ -208,7 +206,7 @@ static void iwl_bg_beacon_update(struct work_struct *work)
container_of(work, struct iwl_priv, beacon_update);
struct sk_buff *beacon;
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
if (!priv->beacon_ctx) {
IWL_ERR(priv, "updating beacon w/o beacon context!\n");
goto out;
@@ -238,7 +236,7 @@ static void iwl_bg_beacon_update(struct work_struct *work)
iwlagn_send_beacon_cmd(priv);
out:
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
}
static void iwl_bg_bt_runtime_config(struct work_struct *work)
@@ -246,11 +244,11 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work)
struct iwl_priv *priv =
container_of(work, struct iwl_priv, bt_runtime_config);
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
/* dont send host command if rf-kill is on */
- if (!iwl_is_ready_rf(priv->shrd))
+ if (!iwl_is_ready_rf(priv))
return;
iwlagn_send_advance_bt_config(priv);
}
@@ -261,13 +259,13 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
container_of(work, struct iwl_priv, bt_full_concurrency);
struct iwl_rxon_context *ctx;
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
goto out;
/* dont send host command if rf-kill is on */
- if (!iwl_is_ready_rf(priv->shrd))
+ if (!iwl_is_ready_rf(priv))
goto out;
IWL_DEBUG_INFO(priv, "BT coex in %s mode\n",
@@ -285,7 +283,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
iwlagn_send_advance_bt_config(priv);
out:
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
}
/**
@@ -302,11 +300,11 @@ static void iwl_bg_statistics_periodic(unsigned long data)
{
struct iwl_priv *priv = (struct iwl_priv *)data;
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
/* dont send host command if rf-kill is on */
- if (!iwl_is_ready_rf(priv->shrd))
+ if (!iwl_is_ready_rf(priv))
return;
iwl_send_statistics_request(priv, CMD_ASYNC, false);
@@ -329,14 +327,13 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
/* Make sure device is powered up for SRAM reads */
spin_lock_irqsave(&trans(priv)->reg_lock, reg_flags);
- if (iwl_grab_nic_access(trans(priv))) {
+ if (unlikely(!iwl_grab_nic_access(trans(priv)))) {
spin_unlock_irqrestore(&trans(priv)->reg_lock, reg_flags);
return;
}
/* Set starting address; reads will auto-increment */
iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, ptr);
- rmb();
/*
* Refuse to read more than would have fit into the log from
@@ -355,11 +352,12 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
ev = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
time = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
if (mode == 0) {
- trace_iwlwifi_dev_ucode_cont_event(priv, 0, time, ev);
+ trace_iwlwifi_dev_ucode_cont_event(
+ trans(priv)->dev, 0, time, ev);
} else {
data = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
- trace_iwlwifi_dev_ucode_cont_event(priv, time,
- data, ev);
+ trace_iwlwifi_dev_ucode_cont_event(
+ trans(priv)->dev, time, data, ev);
}
}
/* Allow device to power down */
@@ -424,7 +422,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
else
priv->event_log.wraps_once_count++;
- trace_iwlwifi_dev_ucode_wrap_event(priv,
+ trace_iwlwifi_dev_ucode_wrap_event(trans(priv)->dev,
num_wraps - priv->event_log.num_wraps,
next_entry, priv->event_log.next_entry);
@@ -463,7 +461,7 @@ static void iwl_bg_ucode_trace(unsigned long data)
{
struct iwl_priv *priv = (struct iwl_priv *)data;
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
if (priv->event_log.ucode_trace) {
@@ -479,18 +477,18 @@ static void iwl_bg_tx_flush(struct work_struct *work)
struct iwl_priv *priv =
container_of(work, struct iwl_priv, tx_flush);
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
/* do nothing if rf-kill is on */
- if (!iwl_is_ready_rf(priv->shrd))
+ if (!iwl_is_ready_rf(priv))
return;
IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
}
-void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
+static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
{
int i;
@@ -552,13 +550,11 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
{
struct iwl_ct_kill_config cmd;
struct iwl_ct_kill_throttling_config adv_cmd;
- unsigned long flags;
int ret = 0;
- spin_lock_irqsave(&priv->shrd->lock, flags);
iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
- spin_unlock_irqrestore(&priv->shrd->lock, flags);
+
priv->thermal_throttle.ct_kill_toggle = false;
if (cfg(priv)->base_params->support_ct_kill_exit) {
@@ -567,7 +563,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
adv_cmd.critical_temperature_exit =
cpu_to_le32(hw_params(priv).ct_kill_exit_threshold);
- ret = iwl_trans_send_cmd_pdu(trans(priv),
+ ret = iwl_dvm_send_cmd_pdu(priv,
REPLY_CT_KILL_CONFIG_CMD,
CMD_SYNC, sizeof(adv_cmd), &adv_cmd);
if (ret)
@@ -582,7 +578,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
cmd.critical_temperature_R =
cpu_to_le32(hw_params(priv).ct_kill_threshold);
- ret = iwl_trans_send_cmd_pdu(trans(priv),
+ ret = iwl_dvm_send_cmd_pdu(priv,
REPLY_CT_KILL_CONFIG_CMD,
CMD_SYNC, sizeof(cmd), &cmd);
if (ret)
@@ -608,7 +604,7 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_RT_CFG_ALL;
calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg);
- return iwl_trans_send_cmd(trans(priv), &cmd);
+ return iwl_dvm_send_cmd(priv, &cmd);
}
@@ -618,9 +614,9 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
.valid = cpu_to_le32(valid_tx_ant),
};
- if (IWL_UCODE_API(nic(priv)->fw.ucode_ver) > 1) {
+ if (IWL_UCODE_API(priv->fw->ucode_ver) > 1) {
IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
- return iwl_trans_send_cmd_pdu(trans(priv),
+ return iwl_dvm_send_cmd_pdu(priv,
TX_ANT_CONFIGURATION_CMD,
CMD_SYNC,
sizeof(struct iwl_tx_ant_config_cmd),
@@ -644,12 +640,12 @@ int iwl_alive_start(struct iwl_priv *priv)
IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
/* After the ALIVE response, we can send host commands to the uCode */
- set_bit(STATUS_ALIVE, &priv->shrd->status);
+ set_bit(STATUS_ALIVE, &priv->status);
/* Enable watchdog to monitor the driver tx queues */
iwl_setup_watchdog(priv);
- if (iwl_is_rfkill(priv->shrd))
+ if (iwl_is_rfkill(priv))
return -ERFKILL;
if (priv->event_log.ucode_trace) {
@@ -673,14 +669,14 @@ int iwl_alive_start(struct iwl_priv *priv)
priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
priv->cur_rssi_ctx = NULL;
- iwl_send_prio_tbl(trans(priv));
+ iwl_send_prio_tbl(priv);
/* FIXME: w/a to force change uCode BT state machine */
- ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_OPEN,
+ ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
if (ret)
return ret;
- ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_CLOSE,
+ ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
if (ret)
return ret;
@@ -701,9 +697,9 @@ int iwl_alive_start(struct iwl_priv *priv)
priv->active_rate = IWL_RATES_MASK;
/* Configure Tx antenna selection based on H/W config */
- iwlagn_send_tx_ant_config(priv, cfg(priv)->valid_tx_ant);
+ iwlagn_send_tx_ant_config(priv, hw_params(priv).valid_tx_ant);
- if (iwl_is_associated_ctx(ctx) && !priv->shrd->wowlan) {
+ if (iwl_is_associated_ctx(ctx) && !priv->wowlan) {
struct iwl_rxon_cmd *active_rxon =
(struct iwl_rxon_cmd *)&ctx->active;
/* apply any changes in staging */
@@ -718,12 +714,12 @@ int iwl_alive_start(struct iwl_priv *priv)
iwlagn_set_rxon_chain(priv, ctx);
}
- if (!priv->shrd->wowlan) {
+ if (!priv->wowlan) {
/* WoWLAN ucode will not reply in the same way, skip it */
iwl_reset_run_time_calib(priv);
}
- set_bit(STATUS_READY, &priv->shrd->status);
+ set_bit(STATUS_READY, &priv->status);
/* Configure the adapter for unassociated operation */
ret = iwlagn_commit_rxon(priv, ctx);
@@ -738,13 +734,47 @@ int iwl_alive_start(struct iwl_priv *priv)
return iwl_power_update_mode(priv, true);
}
+/**
+ * iwl_clear_driver_stations - clear knowledge of all stations from driver
+ * @priv: iwl priv struct
+ *
+ * This is called during iwl_down() to make sure that in the case
+ * we're coming there from a hardware restart mac80211 will be
+ * able to reconfigure stations -- if we're getting there in the
+ * normal down flow then the stations will already be cleared.
+ */
+static void iwl_clear_driver_stations(struct iwl_priv *priv)
+{
+ struct iwl_rxon_context *ctx;
+
+ spin_lock_bh(&priv->sta_lock);
+ memset(priv->stations, 0, sizeof(priv->stations));
+ priv->num_stations = 0;
+
+ priv->ucode_key_table = 0;
+
+ for_each_context(priv, ctx) {
+ /*
+ * Remove all key information that is not stored as part
+ * of station information since mac80211 may not have had
+ * a chance to remove all the keys. When device is
+ * reconfigured by mac80211 after an error all keys will
+ * be reconfigured.
+ */
+ memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
+ ctx->key_mapping_keys = 0;
+ }
+
+ spin_unlock_bh(&priv->sta_lock);
+}
+
void iwl_down(struct iwl_priv *priv)
{
int exit_pending;
IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
iwl_scan_cancel_timeout(priv, 200);
@@ -756,7 +786,7 @@ void iwl_down(struct iwl_priv *priv)
ieee80211_remain_on_channel_expired(priv->hw);
exit_pending =
- test_and_set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
+ test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
/* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
* to prevent rearm timer */
@@ -781,7 +811,7 @@ void iwl_down(struct iwl_priv *priv)
/* Wipe out the EXIT_PENDING status bit if we are not actually
* exiting the module */
if (!exit_pending)
- clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
+ clear_bit(STATUS_EXIT_PENDING, &priv->status);
if (priv->mac80211_registered)
ieee80211_stop_queues(priv->hw);
@@ -789,15 +819,15 @@ void iwl_down(struct iwl_priv *priv)
iwl_trans_stop_device(trans(priv));
/* Clear out all status bits but a few that are stable across reset */
- priv->shrd->status &=
- test_bit(STATUS_RF_KILL_HW, &priv->shrd->status) <<
+ priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
STATUS_RF_KILL_HW |
- test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) <<
+ test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
STATUS_GEO_CONFIGURED |
- test_bit(STATUS_FW_ERROR, &priv->shrd->status) <<
- STATUS_FW_ERROR |
- test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) <<
+ test_bit(STATUS_EXIT_PENDING, &priv->status) <<
STATUS_EXIT_PENDING;
+ priv->shrd->status &=
+ test_bit(STATUS_FW_ERROR, &priv->shrd->status) <<
+ STATUS_FW_ERROR;
dev_kfree_skb(priv->beacon_skb);
priv->beacon_skb = NULL;
@@ -814,11 +844,11 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
struct iwl_priv *priv = container_of(work, struct iwl_priv,
run_time_calib_work);
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) ||
- test_bit(STATUS_SCANNING, &priv->shrd->status)) {
- mutex_unlock(&priv->shrd->mutex);
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+ test_bit(STATUS_SCANNING, &priv->status)) {
+ mutex_unlock(&priv->mutex);
return;
}
@@ -827,7 +857,7 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
iwl_sensitivity_calibration(priv);
}
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
}
void iwlagn_prepare_restart(struct iwl_priv *priv)
@@ -839,7 +869,7 @@ void iwlagn_prepare_restart(struct iwl_priv *priv)
u8 bt_status;
bool bt_is_sco;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
for_each_context(priv, ctx)
ctx->vif = NULL;
@@ -873,13 +903,13 @@ static void iwl_bg_restart(struct work_struct *data)
{
struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
if (test_and_clear_bit(STATUS_FW_ERROR, &priv->shrd->status)) {
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
iwlagn_prepare_restart(priv);
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
iwl_cancel_deferred_work(priv);
ieee80211_restart_hw(priv->hw);
} else {
@@ -894,7 +924,7 @@ void iwlagn_disable_roc(struct iwl_priv *priv)
{
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
if (!priv->hw_roc_setup)
return;
@@ -917,9 +947,9 @@ static void iwlagn_disable_roc_work(struct work_struct *work)
struct iwl_priv *priv = container_of(work, struct iwl_priv,
hw_roc_disable_work.work);
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
iwlagn_disable_roc(priv);
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
}
/*****************************************************************************
@@ -945,8 +975,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
iwl_setup_scan_deferred_work(priv);
- if (cfg(priv)->lib->bt_setup_deferred_work)
- cfg(priv)->lib->bt_setup_deferred_work(priv);
+ if (cfg(priv)->bt_params)
+ iwlagn_bt_setup_deferred_work(priv);
init_timer(&priv->statistics_periodic);
priv->statistics_periodic.data = (unsigned long)priv;
@@ -963,8 +993,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
void iwl_cancel_deferred_work(struct iwl_priv *priv)
{
- if (cfg(priv)->lib->cancel_deferred_work)
- cfg(priv)->lib->cancel_deferred_work(priv);
+ if (cfg(priv)->bt_params)
+ iwlagn_bt_cancel_deferred_work(priv);
cancel_work_sync(&priv->run_time_calib_work);
cancel_work_sync(&priv->beacon_update);
@@ -979,8 +1009,7 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv)
del_timer_sync(&priv->ucode_trace);
}
-static void iwl_init_hw_rates(struct iwl_priv *priv,
- struct ieee80211_rate *rates)
+static void iwl_init_hw_rates(struct ieee80211_rate *rates)
{
int i;
@@ -1004,21 +1033,26 @@ static int iwl_init_drv(struct iwl_priv *priv)
{
int ret;
- spin_lock_init(&priv->shrd->sta_lock);
+ spin_lock_init(&priv->sta_lock);
- mutex_init(&priv->shrd->mutex);
+ mutex_init(&priv->mutex);
- INIT_LIST_HEAD(&trans(priv)->calib_results);
+ INIT_LIST_HEAD(&priv->calib_results);
priv->ieee_channels = NULL;
priv->ieee_rates = NULL;
priv->band = IEEE80211_BAND_2GHZ;
+ priv->plcp_delta_threshold =
+ cfg(priv)->base_params->plcp_delta_threshold;
+
priv->iw_mode = NL80211_IFTYPE_STATION;
priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
priv->agg_tids_count = 0;
+ priv->ucode_owner = IWL_OWNERSHIP_DRIVER;
+
/* initialize force reset */
priv->force_reset[IWL_RF_RESET].reset_duration =
IWL_DELAY_NEXT_FORCE_RF_RESET;
@@ -1054,7 +1088,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
IWL_ERR(priv, "initializing geos failed: %d\n", ret);
goto err_free_channel_map;
}
- iwl_init_hw_rates(priv, priv->ieee_rates);
+ iwl_init_hw_rates(priv->ieee_rates);
return 0;
@@ -1068,11 +1102,10 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
{
iwl_free_geos(priv);
iwl_free_channel_map(priv);
- if (priv->tx_cmd_pool)
- kmem_cache_destroy(priv->tx_cmd_pool);
kfree(priv->scan_cmd);
kfree(priv->beacon_cmd);
kfree(rcu_dereference_raw(priv->noa_data));
+ iwl_calib_free_results(priv);
#ifdef CONFIG_IWLWIFI_DEBUGFS
kfree(priv->wowlan_sram);
#endif
@@ -1084,6 +1117,10 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
static void iwl_set_hw_params(struct iwl_priv *priv)
{
+ if (cfg(priv)->ht_params)
+ hw_params(priv).use_rts_for_aggregation =
+ cfg(priv)->ht_params->use_rts_for_aggregation;
+
if (iwlagn_mod_params.amsdu_size_8K)
hw_params(priv).rx_page_order =
get_order(IWL_RX_BUF_SIZE_8K);
@@ -1092,13 +1129,10 @@ static void iwl_set_hw_params(struct iwl_priv *priv)
get_order(IWL_RX_BUF_SIZE_4K);
if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
- cfg(priv)->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
+ hw_params(priv).sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
hw_params(priv).num_ampdu_queues =
cfg(priv)->base_params->num_of_ampdu_queues;
- hw_params(priv).shadow_reg_enable =
- cfg(priv)->base_params->shadow_reg_enable;
- hw_params(priv).sku = cfg(priv)->sku;
hw_params(priv).wd_timeout = cfg(priv)->base_params->wd_timeout;
/* Device-specific setup */
@@ -1142,15 +1176,16 @@ static void iwl_debug_config(struct iwl_priv *priv)
#endif
}
-static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
+static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
+ const struct iwl_fw *fw)
{
- struct iwl_fw *fw = &nic(trans)->fw;
int err = 0;
struct iwl_priv *priv;
struct ieee80211_hw *hw;
struct iwl_op_mode *op_mode;
u16 num_mac;
u32 ucode_flags;
+ struct iwl_trans_config trans_cfg;
/************************
* 1. Allocating HW data
@@ -1167,9 +1202,32 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
op_mode->ops = &iwl_dvm_ops;
priv = IWL_OP_MODE_GET_DVM(op_mode);
priv->shrd = trans->shrd;
- priv->shrd->priv = priv;
+ priv->fw = fw;
+ /* TODO: remove fw from shared data later */
+ priv->shrd->fw = fw;
- iwl_trans_configure(trans(priv), op_mode);
+ /*
+ * Populate the state variables that the transport layer needs
+ * to know about.
+ */
+ trans_cfg.op_mode = op_mode;
+
+ ucode_flags = fw->ucode_capa.flags;
+
+#ifndef CONFIG_IWLWIFI_P2P
+ ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
+#endif
+
+ if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
+ priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
+ trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
+ } else {
+ priv->sta_key_max_num = STA_KEY_MAX_NUM;
+ trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
+ }
+
+ /* Configure transport layer */
+ iwl_trans_configure(trans(priv), &trans_cfg);
/* At this point both hw and priv are allocated. */
@@ -1198,10 +1256,10 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
* we should init now
*/
spin_lock_init(&trans(priv)->reg_lock);
- spin_lock_init(&priv->shrd->lock);
+ spin_lock_init(&priv->statistics.lock);
/***********************
- * 3. Read REV register
+ * 2. Read REV register
***********************/
IWL_INFO(priv, "Detected %s, REV=0x%X\n",
cfg(priv)->name, trans(priv)->hw_rev);
@@ -1211,9 +1269,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
goto out_free_traffic_mem;
/*****************
- * 4. Read EEPROM
+ * 3. Read EEPROM
*****************/
- /* Read the EEPROM */
err = iwl_eeprom_init(trans(priv), trans(priv)->hw_rev);
/* Reset chip to save power until we load uCode during "up". */
iwl_trans_stop_hw(trans(priv));
@@ -1225,7 +1282,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
if (err)
goto out_free_eeprom;
- err = iwl_eeprom_check_sku(priv);
+ err = iwl_eeprom_init_hw_params(priv);
if (err)
goto out_free_eeprom;
@@ -1243,28 +1300,27 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
}
/************************
- * 5. Setup HW constants
+ * 4. Setup HW constants
************************/
iwl_set_hw_params(priv);
- ucode_flags = fw->ucode_capa.flags;
-
-#ifndef CONFIG_IWLWIFI_P2P
- ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
-#endif
- if (!(hw_params(priv).sku & EEPROM_SKU_CAP_IPAN_ENABLE))
+ if (!(hw_params(priv).sku & EEPROM_SKU_CAP_IPAN_ENABLE)) {
+ IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN");
ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
-
- /*
- * if not PAN, then don't support P2P -- might be a uCode
- * packaging bug or due to the eeprom check above
- */
- if (!(ucode_flags & IWL_UCODE_TLV_FLAGS_PAN))
+ /*
+ * if not PAN, then don't support P2P -- might be a uCode
+ * packaging bug or due to the eeprom check above
+ */
ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
+ priv->sta_key_max_num = STA_KEY_MAX_NUM;
+ trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
+ /* Configure transport layer again*/
+ iwl_trans_configure(trans(priv), &trans_cfg);
+ }
/*******************
- * 6. Setup priv
+ * 5. Setup priv
*******************/
err = iwl_init_drv(priv);
@@ -1273,7 +1329,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
/* At this point both hw and priv are initialized. */
/********************
- * 7. Setup services
+ * 6. Setup services
********************/
iwl_setup_deferred_work(priv);
iwl_setup_rx_handlers(priv);
@@ -1289,14 +1345,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
priv->new_scan_threshold_behaviour =
!!(ucode_flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
- if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
- priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
- priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
- } else {
- priv->sta_key_max_num = STA_KEY_MAX_NUM;
- priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
- }
-
priv->phy_calib_chain_noise_reset_cmd =
fw->ucode_capa.standard_phy_calibration_size;
priv->phy_calib_chain_noise_gain_cmd =
@@ -1308,7 +1356,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
/**************************************************
* This is still part of probe() in a sense...
*
- * 9. Setup and register with mac80211 and debugfs
+ * 7. Setup and register with mac80211 and debugfs
**************************************************/
err = iwlagn_mac_setup_register(priv, &fw->ucode_capa);
if (err)
@@ -1340,18 +1388,10 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
{
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
- wait_for_completion(&nic(priv)->request_firmware_complete);
-
IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
iwl_dbgfs_unregister(priv);
- /* ieee80211_unregister_hw call wil cause iwlagn_mac_stop to
- * to be called and iwl_down since we are removing the device
- * we need to set STATUS_EXIT_PENDING bit.
- */
- set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
-
iwl_testmode_cleanup(priv);
iwlagn_mac_unregister(priv);
@@ -1360,8 +1400,6 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
/*This will stop the queues, move the device to low power state */
iwl_trans_stop_device(trans(priv));
- iwl_dealloc_ucode(nic(priv));
-
iwl_eeprom_free(priv->shrd);
/*netif_stop_queue(dev); */
@@ -1381,6 +1419,60 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
ieee80211_free_hw(priv->hw);
}
+static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode)
+{
+ struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+ if (!iwl_check_for_ct_kill(priv)) {
+ IWL_ERR(priv, "Restarting adapter queue is full\n");
+ iwl_nic_error(op_mode);
+ }
+}
+
+static void iwl_nic_config(struct iwl_op_mode *op_mode)
+{
+ struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+ cfg(priv)->lib->nic_config(priv);
+}
+
+static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
+{
+ struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+ set_bit(ac, &priv->transport_queue_stop);
+ ieee80211_stop_queue(priv->hw, ac);
+}
+
+static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
+{
+ struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+ clear_bit(ac, &priv->transport_queue_stop);
+
+ if (!priv->passive_no_rx)
+ ieee80211_wake_queue(priv->hw, ac);
+}
+
+void iwlagn_lift_passive_no_rx(struct iwl_priv *priv)
+{
+ int ac;
+
+ if (!priv->passive_no_rx)
+ return;
+
+ for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++) {
+ if (!test_bit(ac, &priv->transport_queue_stop)) {
+ IWL_DEBUG_TX_QUEUES(priv, "Wake queue %d");
+ ieee80211_wake_queue(priv->hw, ac);
+ } else {
+ IWL_DEBUG_TX_QUEUES(priv, "Don't wake queue %d");
+ }
+ }
+
+ priv->passive_no_rx = false;
+}
+
const struct iwl_op_mode_ops iwl_dvm_ops = {
.start = iwl_op_mode_dvm_start,
.stop = iwl_op_mode_dvm_stop,
@@ -1390,6 +1482,8 @@ const struct iwl_op_mode_ops iwl_dvm_ops = {
.hw_rf_kill = iwl_set_hw_rfkill_state,
.free_skb = iwl_free_skb,
.nic_error = iwl_nic_error,
+ .cmd_queue_full = iwl_cmd_queue_full,
+ .nic_config = iwl_nic_config,
};
/*****************************************************************************
@@ -1397,6 +1491,9 @@ const struct iwl_op_mode_ops iwl_dvm_ops = {
* driver and module entry point
*
*****************************************************************************/
+
+struct kmem_cache *iwl_tx_cmd_pool;
+
static int __init iwl_init(void)
{
@@ -1404,20 +1501,27 @@ static int __init iwl_init(void)
pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
pr_info(DRV_COPYRIGHT "\n");
+ iwl_tx_cmd_pool = kmem_cache_create("iwl_dev_cmd",
+ sizeof(struct iwl_device_cmd),
+ sizeof(void *), 0, NULL);
+ if (!iwl_tx_cmd_pool)
+ return -ENOMEM;
+
ret = iwlagn_rate_control_register();
if (ret) {
pr_err("Unable to register rate control algorithm: %d\n", ret);
- return ret;
+ goto error_rc_register;
}
ret = iwl_pci_register_driver();
-
if (ret)
- goto error_register;
+ goto error_pci_register;
return ret;
-error_register:
+error_pci_register:
iwlagn_rate_control_unregister();
+error_rc_register:
+ kmem_cache_destroy(iwl_tx_cmd_pool);
return ret;
}
@@ -1425,6 +1529,7 @@ static void __exit iwl_exit(void)
{
iwl_pci_unregister_driver();
iwlagn_rate_control_unregister();
+ kmem_cache_destroy(iwl_tx_cmd_pool);
}
module_exit(iwl_exit);
@@ -1438,8 +1543,6 @@ MODULE_PARM_DESC(debug, "debug output mask");
module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO);
MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
-module_param_named(queues_num, iwlagn_mod_params.num_of_queues, int, S_IRUGO);
-MODULE_PARM_DESC(queues_num, "number of hw queues.");
module_param_named(11n_disable, iwlagn_mod_params.disable_11n, uint, S_IRUGO);
MODULE_PARM_DESC(11n_disable,
"disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index cb484e273b9..3780a03f271 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -82,20 +82,26 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv);
void iwlagn_prepare_restart(struct iwl_priv *priv);
void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb);
int __must_check iwl_rx_dispatch(struct iwl_op_mode *op_mode,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
-void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
-void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state);
-void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
void iwl_nic_error(struct iwl_op_mode *op_mode);
+bool iwl_check_for_ct_kill(struct iwl_priv *priv);
+
+void iwlagn_lift_passive_no_rx(struct iwl_priv *priv);
+
/* MAC80211 */
struct ieee80211_hw *iwl_alloc_all(void);
int iwlagn_mac_setup_register(struct iwl_priv *priv,
- struct iwl_ucode_capabilities *capa);
+ const struct iwl_ucode_capabilities *capa);
void iwlagn_mac_unregister(struct iwl_priv *priv);
+/* commands */
+int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
+int iwl_dvm_send_cmd_pdu(struct iwl_priv *priv, u8 id,
+ u32 flags, u16 len, const void *data);
+
/* RXON */
int iwlagn_set_pan_params(struct iwl_priv *priv);
int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
@@ -110,9 +116,18 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf,
/* uCode */
int iwlagn_rx_calib_result(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
-void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags);
+int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type);
+void iwl_send_prio_tbl(struct iwl_priv *priv);
+int iwl_init_alive_start(struct iwl_priv *priv);
+int iwl_run_init_ucode(struct iwl_priv *priv);
+int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
+ enum iwl_ucode_type ucode_type);
+int iwl_send_calib_results(struct iwl_priv *priv);
+int iwl_calib_set(struct iwl_priv *priv,
+ const struct iwl_calib_hdr *cmd, int len);
+void iwl_calib_free_results(struct iwl_priv *priv);
/* lib */
int iwlagn_send_tx_power(struct iwl_priv *priv);
@@ -124,8 +139,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
#ifdef CONFIG_PM_SLEEP
int iwlagn_send_patterns(struct iwl_priv *priv,
struct cfg80211_wowlan *wowlan);
-int iwlagn_suspend(struct iwl_priv *priv,
- struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
+int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan);
#endif
/* rx */
@@ -142,9 +156,9 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid);
int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
-int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
static inline u32 iwl_tx_status_to_mac80211(u32 status)
@@ -179,7 +193,7 @@ void iwlagn_disable_roc(struct iwl_priv *priv);
/* bt coex */
void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv);
void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv);
@@ -220,6 +234,8 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
struct ieee80211_sta *sta, u8 *sta_id_r);
int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
const u8 *addr);
+void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id,
+ const u8 *addr);
u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
const u8 *addr, bool is_ap, struct ieee80211_sta *sta);
@@ -227,46 +243,12 @@ void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
u8 sta_id, struct iwl_link_quality_cmd *link_cmd);
int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
struct iwl_link_quality_cmd *lq, u8 flags, bool init);
-void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
-int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
+int iwl_sta_update_ht(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ struct ieee80211_sta *sta);
-/**
- * iwl_clear_driver_stations - clear knowledge of all stations from driver
- * @priv: iwl priv struct
- *
- * This is called during iwl_down() to make sure that in the case
- * we're coming there from a hardware restart mac80211 will be
- * able to reconfigure stations -- if we're getting there in the
- * normal down flow then the stations will already be cleared.
- */
-static inline void iwl_clear_driver_stations(struct iwl_priv *priv)
-{
- unsigned long flags;
- struct iwl_rxon_context *ctx;
-
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
- memset(priv->stations, 0, sizeof(priv->stations));
- priv->num_stations = 0;
-
- priv->ucode_key_table = 0;
-
- for_each_context(priv, ctx) {
- /*
- * Remove all key information that is not stored as part
- * of station information since mac80211 may not have had
- * a chance to remove all the keys. When device is
- * reconfigured by mac80211 after an error all keys will
- * be reconfigured.
- */
- memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
- ctx->key_mapping_keys = 0;
- }
-
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-}
-
static inline int iwl_sta_id(struct ieee80211_sta *sta)
{
if (WARN_ON(!sta))
@@ -275,37 +257,6 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta)
return ((struct iwl_station_priv *)sta->drv_priv)->sta_id;
}
-/**
- * iwl_sta_id_or_broadcast - return sta_id or broadcast sta
- * @priv: iwl priv
- * @context: the current context
- * @sta: mac80211 station
- *
- * In certain circumstances mac80211 passes a station pointer
- * that may be %NULL, for example during TX or key setup. In
- * that case, we need to use the broadcast station, so this
- * inline wraps that pattern.
- */
-static inline int iwl_sta_id_or_broadcast(struct iwl_priv *priv,
- struct iwl_rxon_context *context,
- struct ieee80211_sta *sta)
-{
- int sta_id;
-
- if (!sta)
- return context->bcast_sta_id;
-
- sta_id = iwl_sta_id(sta);
-
- /*
- * mac80211 should not be passing a partially
- * initialised station!
- */
- WARN_ON(sta_id == IWL_INVALID_STATION);
-
- return sta_id;
-}
-
int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
struct iwl_rxon_context *ctx);
int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
@@ -355,7 +306,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
}
/* eeprom */
-void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv);
void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac);
extern int iwl_alive_start(struct iwl_priv *priv);
@@ -402,4 +352,58 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
}
#endif
+/* status checks */
+
+static inline int iwl_is_ready(struct iwl_priv *priv)
+{
+ /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
+ * set but EXIT_PENDING is not */
+ return test_bit(STATUS_READY, &priv->status) &&
+ test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
+ !test_bit(STATUS_EXIT_PENDING, &priv->status);
+}
+
+static inline int iwl_is_alive(struct iwl_priv *priv)
+{
+ return test_bit(STATUS_ALIVE, &priv->status);
+}
+
+static inline int iwl_is_rfkill(struct iwl_priv *priv)
+{
+ return test_bit(STATUS_RF_KILL_HW, &priv->status);
+}
+
+static inline int iwl_is_ctkill(struct iwl_priv *priv)
+{
+ return test_bit(STATUS_CT_KILL, &priv->status);
+}
+
+static inline int iwl_is_ready_rf(struct iwl_priv *priv)
+{
+ if (iwl_is_rfkill(priv))
+ return 0;
+
+ return iwl_is_ready(priv);
+}
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...) \
+do { \
+ if (!iwl_is_rfkill((m))) \
+ IWL_ERR(m, fmt, ##args); \
+ else \
+ __iwl_err(trans(m)->dev, true, \
+ !iwl_have_debug_level(IWL_DL_RADIO), \
+ fmt, ##args); \
+} while (0)
+#else
+#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...) \
+do { \
+ if (!iwl_is_rfkill((m))) \
+ IWL_ERR(m, fmt, ##args); \
+ else \
+ __iwl_err(trans(m)->dev, true, true, fmt, ##args); \
+} while (0)
+#endif /* CONFIG_IWLWIFI_DEBUG */
+
#endif /* __iwl_agn_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-cfg.h b/drivers/net/wireless/iwlwifi/iwl-cfg.h
index 1ad14bbccc9..82152311d73 100644
--- a/drivers/net/wireless/iwlwifi/iwl-cfg.h
+++ b/drivers/net/wireless/iwlwifi/iwl-cfg.h
@@ -68,46 +68,46 @@
* This file declares the config structures for all devices.
*/
-extern struct iwl_cfg iwl5300_agn_cfg;
-extern struct iwl_cfg iwl5100_agn_cfg;
-extern struct iwl_cfg iwl5350_agn_cfg;
-extern struct iwl_cfg iwl5100_bgn_cfg;
-extern struct iwl_cfg iwl5100_abg_cfg;
-extern struct iwl_cfg iwl5150_agn_cfg;
-extern struct iwl_cfg iwl5150_abg_cfg;
-extern struct iwl_cfg iwl6005_2agn_cfg;
-extern struct iwl_cfg iwl6005_2abg_cfg;
-extern struct iwl_cfg iwl6005_2bg_cfg;
-extern struct iwl_cfg iwl6005_2agn_sff_cfg;
-extern struct iwl_cfg iwl6005_2agn_d_cfg;
-extern struct iwl_cfg iwl6005_2agn_mow1_cfg;
-extern struct iwl_cfg iwl6005_2agn_mow2_cfg;
-extern struct iwl_cfg iwl1030_bgn_cfg;
-extern struct iwl_cfg iwl1030_bg_cfg;
-extern struct iwl_cfg iwl6030_2agn_cfg;
-extern struct iwl_cfg iwl6030_2abg_cfg;
-extern struct iwl_cfg iwl6030_2bgn_cfg;
-extern struct iwl_cfg iwl6030_2bg_cfg;
-extern struct iwl_cfg iwl6000i_2agn_cfg;
-extern struct iwl_cfg iwl6000i_2abg_cfg;
-extern struct iwl_cfg iwl6000i_2bg_cfg;
-extern struct iwl_cfg iwl6000_3agn_cfg;
-extern struct iwl_cfg iwl6050_2agn_cfg;
-extern struct iwl_cfg iwl6050_2abg_cfg;
-extern struct iwl_cfg iwl6150_bgn_cfg;
-extern struct iwl_cfg iwl6150_bg_cfg;
-extern struct iwl_cfg iwl1000_bgn_cfg;
-extern struct iwl_cfg iwl1000_bg_cfg;
-extern struct iwl_cfg iwl100_bgn_cfg;
-extern struct iwl_cfg iwl100_bg_cfg;
-extern struct iwl_cfg iwl130_bgn_cfg;
-extern struct iwl_cfg iwl130_bg_cfg;
-extern struct iwl_cfg iwl2000_2bgn_cfg;
-extern struct iwl_cfg iwl2000_2bgn_d_cfg;
-extern struct iwl_cfg iwl2030_2bgn_cfg;
-extern struct iwl_cfg iwl6035_2agn_cfg;
-extern struct iwl_cfg iwl105_bgn_cfg;
-extern struct iwl_cfg iwl105_bgn_d_cfg;
-extern struct iwl_cfg iwl135_bgn_cfg;
+extern const struct iwl_cfg iwl5300_agn_cfg;
+extern const struct iwl_cfg iwl5100_agn_cfg;
+extern const struct iwl_cfg iwl5350_agn_cfg;
+extern const struct iwl_cfg iwl5100_bgn_cfg;
+extern const struct iwl_cfg iwl5100_abg_cfg;
+extern const struct iwl_cfg iwl5150_agn_cfg;
+extern const struct iwl_cfg iwl5150_abg_cfg;
+extern const struct iwl_cfg iwl6005_2agn_cfg;
+extern const struct iwl_cfg iwl6005_2abg_cfg;
+extern const struct iwl_cfg iwl6005_2bg_cfg;
+extern const struct iwl_cfg iwl6005_2agn_sff_cfg;
+extern const struct iwl_cfg iwl6005_2agn_d_cfg;
+extern const struct iwl_cfg iwl6005_2agn_mow1_cfg;
+extern const struct iwl_cfg iwl6005_2agn_mow2_cfg;
+extern const struct iwl_cfg iwl1030_bgn_cfg;
+extern const struct iwl_cfg iwl1030_bg_cfg;
+extern const struct iwl_cfg iwl6030_2agn_cfg;
+extern const struct iwl_cfg iwl6030_2abg_cfg;
+extern const struct iwl_cfg iwl6030_2bgn_cfg;
+extern const struct iwl_cfg iwl6030_2bg_cfg;
+extern const struct iwl_cfg iwl6000i_2agn_cfg;
+extern const struct iwl_cfg iwl6000i_2abg_cfg;
+extern const struct iwl_cfg iwl6000i_2bg_cfg;
+extern const struct iwl_cfg iwl6000_3agn_cfg;
+extern const struct iwl_cfg iwl6050_2agn_cfg;
+extern const struct iwl_cfg iwl6050_2abg_cfg;
+extern const struct iwl_cfg iwl6150_bgn_cfg;
+extern const struct iwl_cfg iwl6150_bg_cfg;
+extern const struct iwl_cfg iwl1000_bgn_cfg;
+extern const struct iwl_cfg iwl1000_bg_cfg;
+extern const struct iwl_cfg iwl100_bgn_cfg;
+extern const struct iwl_cfg iwl100_bg_cfg;
+extern const struct iwl_cfg iwl130_bgn_cfg;
+extern const struct iwl_cfg iwl130_bg_cfg;
+extern const struct iwl_cfg iwl2000_2bgn_cfg;
+extern const struct iwl_cfg iwl2000_2bgn_d_cfg;
+extern const struct iwl_cfg iwl2030_2bgn_cfg;
+extern const struct iwl_cfg iwl6035_2agn_cfg;
+extern const struct iwl_cfg iwl105_bgn_cfg;
+extern const struct iwl_cfg iwl105_bgn_d_cfg;
+extern const struct iwl_cfg iwl135_bgn_cfg;
#endif /* __iwl_pci_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index c20618d9226..9ed73e5154b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -69,22 +69,9 @@
#ifndef __iwl_commands_h__
#define __iwl_commands_h__
-#include <linux/etherdevice.h>
#include <linux/ieee80211.h>
+#include <linux/types.h>
-struct iwl_priv;
-
-/* uCode version contains 4 values: Major/Minor/API/Serial */
-#define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24)
-#define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16)
-#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8)
-#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF)
-
-
-/* Tx rates */
-#define IWL_CCK_RATES 4
-#define IWL_OFDM_RATES 8
-#define IWL_MAX_RATES (IWL_CCK_RATES + IWL_OFDM_RATES)
enum {
REPLY_ALIVE = 0x1,
@@ -213,48 +200,6 @@ enum {
/* iwl_cmd_header flags value */
#define IWL_CMD_FAILED_MSK 0x40
-#define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f)
-#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8)
-#define SEQ_TO_INDEX(s) ((s) & 0xff)
-#define INDEX_TO_SEQ(i) ((i) & 0xff)
-#define SEQ_RX_FRAME cpu_to_le16(0x8000)
-
-/**
- * struct iwl_cmd_header
- *
- * This header format appears in the beginning of each command sent from the
- * driver, and each response/notification received from uCode.
- */
-struct iwl_cmd_header {
- u8 cmd; /* Command ID: REPLY_RXON, etc. */
- u8 flags; /* 0:5 reserved, 6 abort, 7 internal */
- /*
- * The driver sets up the sequence number to values of its choosing.
- * uCode does not use this value, but passes it back to the driver
- * when sending the response to each driver-originated command, so
- * the driver can match the response to the command. Since the values
- * don't get used by uCode, the driver may set up an arbitrary format.
- *
- * There is one exception: uCode sets bit 15 when it originates
- * the response/notification, i.e. when the response/notification
- * is not a direct response to a command sent by the driver. For
- * example, uCode issues REPLY_RX when it sends a received frame
- * to the driver; it is not a direct response to any driver command.
- *
- * The Linux driver uses the following format:
- *
- * 0:7 tfd index - position within TX queue
- * 8:12 TX queue id
- * 13:14 reserved
- * 15 unsolicited RX or uCode-originated notification
- */
- __le16 sequence;
-
- /* command or response/notification data follows immediately */
- u8 data[0];
-} __packed;
-
-
/**
* iwlagn rate_n_flags bit fields
*
@@ -3151,8 +3096,6 @@ struct iwl_enhance_sensitivity_cmd {
*/
/* Phy calibration command for series */
-/* The default calibrate table size if not specified by firmware */
-#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18
enum {
IWL_PHY_CALIBRATE_DC_CMD = 8,
IWL_PHY_CALIBRATE_LO_CMD = 9,
@@ -3161,11 +3104,8 @@ enum {
IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16,
IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD = 18,
- IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE = 19,
};
-#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE (253)
-
/* This enum defines the bitmap of various calibrations to enable in both
* init ucode and runtime ucode through CALIBRATION_CFG_CMD.
*/
@@ -3905,50 +3845,6 @@ struct iwlagn_wowlan_kek_kck_material_cmd {
__le64 replay_ctr;
} __packed;
-/******************************************************************************
- * (13)
- * Union of all expected notifications/responses:
- *
- *****************************************************************************/
-#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */
-
-struct iwl_rx_packet {
- /*
- * The first 4 bytes of the RX frame header contain both the RX frame
- * size and some flags.
- * Bit fields:
- * 31: flag flush RB request
- * 30: flag ignore TC (terminal counter) request
- * 29: flag fast IRQ request
- * 28-14: Reserved
- * 13-00: RX frame size
- */
- __le32 len_n_flags;
- struct iwl_cmd_header hdr;
- union {
- struct iwl_alive_resp alive_frame;
- struct iwl_spectrum_notification spectrum_notif;
- struct iwl_csa_notification csa_notif;
- struct iwl_error_resp err_resp;
- struct iwl_card_state_notif card_state_notif;
- struct iwl_add_sta_resp add_sta;
- struct iwl_rem_sta_resp rem_sta;
- struct iwl_sleep_notification sleep_notif;
- struct iwl_spectrum_resp spectrum;
- struct iwl_notif_statistics stats;
- struct iwl_bt_notif_statistics stats_bt;
- struct iwl_compressed_ba_resp compressed_ba;
- struct iwl_missed_beacon_notif missed_beacon;
- struct iwl_coex_medium_notification coex_medium_notif;
- struct iwl_coex_event_resp coex_event;
- struct iwl_bt_coex_profile_notif bt_coex_profile_notif;
- __le32 status;
- u8 raw[0];
- } u;
-} __packed;
-
-int iwl_agn_check_rxon_cmd(struct iwl_priv *priv);
-
/*
* REPLY_WIPAN_PARAMS = 0xb2 (Commands and Notification)
*/
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 275e0896605..8b85940731f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -41,7 +41,6 @@
#include "iwl-shared.h"
#include "iwl-agn.h"
#include "iwl-trans.h"
-#include "iwl-wifi.h"
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
@@ -114,7 +113,7 @@ int iwl_init_geos(struct iwl_priv *priv)
if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n");
- set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
+ set_bit(STATUS_GEO_CONFIGURED, &priv->status);
return 0;
}
@@ -137,7 +136,7 @@ int iwl_init_geos(struct iwl_priv *priv)
sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
- if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
+ if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE)
iwl_init_ht_hw_capab(priv, &sband->ht_cap,
IEEE80211_BAND_5GHZ);
@@ -147,7 +146,7 @@ int iwl_init_geos(struct iwl_priv *priv)
sband->bitrates = rates;
sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
- if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
+ if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE)
iwl_init_ht_hw_capab(priv, &sband->ht_cap,
IEEE80211_BAND_2GHZ);
@@ -202,18 +201,18 @@ int iwl_init_geos(struct iwl_priv *priv)
priv->tx_power_next = max_tx_power;
if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
- cfg(priv)->sku & EEPROM_SKU_CAP_BAND_52GHZ) {
+ hw_params(priv).sku & EEPROM_SKU_CAP_BAND_52GHZ) {
IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
"Please send your %s to maintainer.\n",
trans(priv)->hw_id_str);
- cfg(priv)->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
+ hw_params(priv).sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
}
IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
priv->bands[IEEE80211_BAND_2GHZ].n_channels,
priv->bands[IEEE80211_BAND_5GHZ].n_channels);
- set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
+ set_bit(STATUS_GEO_CONFIGURED, &priv->status);
return 0;
}
@@ -225,7 +224,7 @@ void iwl_free_geos(struct iwl_priv *priv)
{
kfree(priv->ieee_channels);
kfree(priv->ieee_rates);
- clear_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
+ clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
}
static bool iwl_is_channel_extension(struct iwl_priv *priv,
@@ -317,7 +316,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
conf = &priv->hw->conf;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd));
@@ -370,7 +369,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
le32_to_cpu(ctx->timing.beacon_init_val),
le16_to_cpu(ctx->timing.atim_window));
- return iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_timing_cmd,
+ return iwl_dvm_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
CMD_SYNC, sizeof(ctx->timing), &ctx->timing);
}
@@ -799,11 +798,10 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
*/
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
- &priv->shrd->status))
+ if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
ieee80211_chswitch_done(ctx->vif, is_success);
}
@@ -836,7 +834,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
unsigned long reload_jiffies;
#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS)
+ if (iwl_have_debug_level(IWL_DL_FW_ERRORS))
iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS);
#endif
@@ -846,11 +844,11 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
/* Cancel currently queued command. */
clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status);
- iwl_abort_notification_waits(priv->shrd);
+ iwl_abort_notification_waits(&priv->notif_wait);
/* Keep the restart process from trying to send host
* commands by clearing the ready bit */
- clear_bit(STATUS_READY, &priv->shrd->status);
+ clear_bit(STATUS_READY, &priv->status);
wake_up(&priv->shrd->wait_command_queue);
@@ -875,7 +873,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
priv->reload_count = 0;
}
- if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) {
+ if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
if (iwlagn_mod_params.restart_fw) {
IWL_DEBUG_FW_ERRORS(priv,
"Restarting adapter due to uCode error.\n");
@@ -893,7 +891,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
bool defer;
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
if (priv->tx_power_user_lmt == tx_power && !force)
return 0;
@@ -913,7 +911,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
return -EINVAL;
}
- if (!iwl_is_ready_rf(priv->shrd))
+ if (!iwl_is_ready_rf(priv))
return -EIO;
/* scan complete and commit_rxon use tx_power_next value,
@@ -921,7 +919,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
priv->tx_power_next = tx_power;
/* do not set tx power when scanning or channel changing */
- defer = test_bit(STATUS_SCANNING, &priv->shrd->status) ||
+ defer = test_bit(STATUS_SCANNING, &priv->status) ||
memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging));
if (defer && !force) {
IWL_DEBUG_INFO(priv, "Deferring tx power set\n");
@@ -959,7 +957,7 @@ void iwl_send_bt_config(struct iwl_priv *priv)
IWL_DEBUG_INFO(priv, "BT coex %s\n",
(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
- if (iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
+ if (iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd))
IWL_ERR(priv, "failed to send BT Coex Config\n");
}
@@ -972,12 +970,12 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
};
if (flags & CMD_ASYNC)
- return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD,
+ return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
CMD_ASYNC,
sizeof(struct iwl_statistics_cmd),
&statistics_cmd);
else
- return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD,
+ return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
CMD_SYNC,
sizeof(struct iwl_statistics_cmd),
&statistics_cmd);
@@ -1004,7 +1002,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv)
{
u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE;
- if (iwl_get_debug_level(priv->shrd) & IWL_DL_TX) {
+ if (iwl_have_debug_level(IWL_DL_TX)) {
if (!priv->tx_traffic) {
priv->tx_traffic =
kzalloc(traffic_size, GFP_KERNEL);
@@ -1012,7 +1010,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv)
return -ENOMEM;
}
}
- if (iwl_get_debug_level(priv->shrd) & IWL_DL_RX) {
+ if (iwl_have_debug_level(IWL_DL_RX)) {
if (!priv->rx_traffic) {
priv->rx_traffic =
kzalloc(traffic_size, GFP_KERNEL);
@@ -1039,7 +1037,7 @@ void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
__le16 fc;
u16 len;
- if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_TX)))
+ if (likely(!iwl_have_debug_level(IWL_DL_TX)))
return;
if (!priv->tx_traffic)
@@ -1063,7 +1061,7 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
__le16 fc;
u16 len;
- if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_RX)))
+ if (likely(!iwl_have_debug_level(IWL_DL_RX)))
return;
if (!priv->rx_traffic)
@@ -1220,7 +1218,7 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
static void iwl_force_rf_reset(struct iwl_priv *priv)
{
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
if (!iwl_is_any_associated(priv)) {
@@ -1245,7 +1243,7 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
{
struct iwl_force_reset *force_reset;
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return -EINVAL;
if (mode >= IWL_MAX_FORCE_RESET) {
@@ -1301,7 +1299,7 @@ int iwl_cmd_echo_test(struct iwl_priv *priv)
.flags = CMD_SYNC,
};
- ret = iwl_trans_send_cmd(trans(priv), &cmd);
+ ret = iwl_dvm_send_cmd(priv, &cmd);
if (ret)
IWL_ERR(priv, "echo testing fail: 0X%x\n", ret);
else
@@ -1335,30 +1333,20 @@ void iwl_bg_watchdog(unsigned long data)
int cnt;
unsigned long timeout;
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- if (iwl_is_rfkill(priv->shrd))
+ if (iwl_is_rfkill(priv))
return;
- timeout = cfg(priv)->base_params->wd_timeout;
+ timeout = hw_params(priv).wd_timeout;
if (timeout == 0)
return;
- /* monitor and check for stuck cmd queue */
- if (iwl_check_stuck_queue(priv, priv->shrd->cmd_queue))
- return;
-
- /* monitor and check for other stuck queues */
- if (iwl_is_any_associated(priv)) {
- for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) {
- /* skip as we already checked the command queue */
- if (cnt == priv->shrd->cmd_queue)
- continue;
- if (iwl_check_stuck_queue(priv, cnt))
- return;
- }
- }
+ /* monitor and check for stuck queues */
+ for (cnt = 0; cnt < cfg(priv)->base_params->num_of_queues; cnt++)
+ if (iwl_check_stuck_queue(priv, cnt))
+ return;
mod_timer(&priv->watchdog, jiffies +
msecs_to_jiffies(IWL_WD_TICK(timeout)));
@@ -1366,7 +1354,7 @@ void iwl_bg_watchdog(unsigned long data)
void iwl_setup_watchdog(struct iwl_priv *priv)
{
- unsigned int timeout = cfg(priv)->base_params->wd_timeout;
+ unsigned int timeout = hw_params(priv).wd_timeout;
if (!iwlagn_mod_params.wd_disable) {
/* use system default */
@@ -1471,34 +1459,19 @@ void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
{
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
- wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
-}
+ if (state)
+ set_bit(STATUS_RF_KILL_HW, &priv->status);
+ else
+ clear_bit(STATUS_RF_KILL_HW, &priv->status);
-void iwl_nic_config(struct iwl_priv *priv)
-{
- cfg(priv)->lib->nic_config(priv);
+ wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
}
void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
{
- struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
struct ieee80211_tx_info *info;
info = IEEE80211_SKB_CB(skb);
- kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));
+ kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1]));
dev_kfree_skb_any(skb);
}
-
-void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
-{
- struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
-
- ieee80211_stop_queue(priv->hw, ac);
-}
-
-void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
-{
- struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
-
- ieee80211_wake_queue(priv->hw, ac);
-}
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 42630f5e8de..635eb685ede 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -77,12 +77,6 @@ struct iwl_cmd;
struct iwl_lib_ops {
/* set hw dependent parameters */
void (*set_hw_params)(struct iwl_priv *priv);
- /* setup BT Rx handler */
- void (*bt_rx_handler_setup)(struct iwl_priv *priv);
- /* setup BT related deferred work */
- void (*bt_setup_deferred_work)(struct iwl_priv *priv);
- /* cancel deferred work */
- void (*cancel_deferred_work)(struct iwl_priv *priv);
int (*set_channel_switch)(struct iwl_priv *priv,
struct ieee80211_channel_switch *ch_switch);
/* device specific configuration */
@@ -95,72 +89,6 @@ struct iwl_lib_ops {
void (*temperature)(struct iwl_priv *priv);
};
-/*
- * @max_ll_items: max number of OTP blocks
- * @shadow_ram_support: shadow support for OTP memory
- * @led_compensation: compensate on the led on/off time per HW according
- * to the deviation to achieve the desired led frequency.
- * The detail algorithm is described in iwl-led.c
- * @chain_noise_num_beacons: number of beacons used to compute chain noise
- * @adv_thermal_throttle: support advance thermal throttle
- * @support_ct_kill_exit: support ct kill exit condition
- * @support_wimax_coexist: support wimax/wifi co-exist
- * @plcp_delta_threshold: plcp error rate threshold used to trigger
- * radio tuning when there is a high receiving plcp error rate
- * @chain_noise_scale: default chain noise scale used for gain computation
- * @wd_timeout: TX queues watchdog timeout
- * @max_event_log_size: size of event log buffer size for ucode event logging
- * @shadow_reg_enable: HW shadhow register bit
- * @no_idle_support: do not support idle mode
- * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up
- * wd_disable: disable watchdog timer
- */
-struct iwl_base_params {
- int eeprom_size;
- int num_of_queues; /* def: HW dependent */
- int num_of_ampdu_queues;/* def: HW dependent */
- /* for iwl_apm_init() */
- u32 pll_cfg_val;
-
- const u16 max_ll_items;
- const bool shadow_ram_support;
- u16 led_compensation;
- bool adv_thermal_throttle;
- bool support_ct_kill_exit;
- const bool support_wimax_coexist;
- u8 plcp_delta_threshold;
- s32 chain_noise_scale;
- unsigned int wd_timeout;
- u32 max_event_log_size;
- const bool shadow_reg_enable;
- const bool no_idle_support;
- const bool hd_v2;
- const bool wd_disable;
-};
-/*
- * @advanced_bt_coexist: support advanced bt coexist
- * @bt_init_traffic_load: specify initial bt traffic load
- * @bt_prio_boost: default bt priority boost value
- * @agg_time_limit: maximum number of uSec in aggregation
- * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode
- */
-struct iwl_bt_params {
- bool advanced_bt_coexist;
- u8 bt_init_traffic_load;
- u8 bt_prio_boost;
- u16 agg_time_limit;
- bool bt_sco_disable;
- bool bt_session_2;
-};
-/*
- * @use_rts_for_aggregation: use rts/cts protection for HT traffic
- */
-struct iwl_ht_params {
- const bool ht_greenfield_support; /* if used set to true */
- bool use_rts_for_aggregation;
- enum ieee80211_smps_mode smps_mode;
-};
-
/***************************
* L i b *
***************************/
@@ -244,8 +172,6 @@ void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
void iwl_force_scan_end(struct iwl_priv *priv);
void iwl_internal_short_hw_scan(struct iwl_priv *priv);
int iwl_force_reset(struct iwl_priv *priv, int mode, bool external);
-u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
- const u8 *ta, const u8 *ie, int ie_len, int left);
void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
void iwl_cancel_scan_deferred_work(struct iwl_priv *priv);
@@ -265,6 +191,10 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
#define IWL_SCAN_CHECK_WATCHDOG (HZ * 7)
+/* traffic log definitions */
+#define IWL_TRAFFIC_ENTRIES (256)
+#define IWL_TRAFFIC_ENTRY_SIZE (64)
+
/*****************************************************
* S e n d i n g H o s t C o m m a n d s *
*****************************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.c b/drivers/net/wireless/iwlwifi/iwl-debug.c
index 4bc2e70051d..059efabda18 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.c
@@ -104,7 +104,7 @@ void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only,
}
#if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING)
-void __iwl_dbg(struct iwl_shared *shared, struct device *dev,
+void __iwl_dbg(struct device *dev,
u32 level, bool limit, const char *function,
const char *fmt, ...)
{
@@ -116,7 +116,7 @@ void __iwl_dbg(struct iwl_shared *shared, struct device *dev,
va_start(args, fmt);
vaf.va = &args;
#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_get_debug_level(shared) & level &&
+ if (iwl_have_debug_level(level) &&
(!limit || net_ratelimit()))
dev_err(dev, "%c %s %pV", in_interrupt() ? 'I' : 'U',
function, &vaf);
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 01b23303d73..a6b32a11e10 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -47,12 +47,12 @@ void __iwl_crit(struct device *dev, const char *fmt, ...);
#define IWL_CRIT(m, f, a...) __iwl_crit(trans(m)->dev, f, ## a)
#if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING)
-void __iwl_dbg(struct iwl_shared *shared, struct device *dev,
+void __iwl_dbg(struct device *dev,
u32 level, bool limit, const char *function,
const char *fmt, ...);
#else
static inline void
-__iwl_dbg(struct iwl_shared *shared, struct device *dev,
+__iwl_dbg(struct device *dev,
u32 level, bool limit, const char *function,
const char *fmt, ...)
{}
@@ -65,35 +65,19 @@ do { \
} while (0)
#define IWL_DEBUG(m, level, fmt, args...) \
- __iwl_dbg((m)->shrd, trans(m)->dev, level, false, __func__, fmt, ##args)
+ __iwl_dbg(trans(m)->dev, level, false, __func__, fmt, ##args)
#define IWL_DEBUG_LIMIT(m, level, fmt, args...) \
- __iwl_dbg((m)->shrd, trans(m)->dev, level, true, __func__, fmt, ##args)
+ __iwl_dbg(trans(m)->dev, level, true, __func__, fmt, ##args)
#ifdef CONFIG_IWLWIFI_DEBUG
#define iwl_print_hex_dump(m, level, p, len) \
do { \
- if (iwl_get_debug_level((m)->shrd) & level) \
+ if (iwl_have_debug_level(level)) \
print_hex_dump(KERN_DEBUG, "iwl data: ", \
DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
} while (0)
-#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...) \
-do { \
- if (!iwl_is_rfkill((m)->shrd)) \
- IWL_ERR(m, fmt, ##args); \
- else \
- __iwl_err(trans(m)->dev, true, \
- !(iwl_get_debug_level((m)->shrd) & IWL_DL_RADIO),\
- fmt, ##args); \
-} while (0)
#else
#define iwl_print_hex_dump(m, level, p, len)
-#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...) \
-do { \
- if (!iwl_is_rfkill((m)->shrd)) \
- IWL_ERR(m, fmt, ##args); \
- else \
- __iwl_err(trans(m)->dev, true, true, fmt, ##args); \
-} while (0)
#endif /* CONFIG_IWLWIFI_DEBUG */
#ifdef CONFIG_IWLWIFI_DEBUGFS
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index ad74138e1c7..9b71c87847c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -40,7 +40,6 @@
#include "iwl-core.h"
#include "iwl-io.h"
#include "iwl-agn.h"
-#include "iwl-wifi.h"
/* create and remove of files */
#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
@@ -235,12 +234,11 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
/* default is to dump the entire data segment */
if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
- struct iwl_nic *nic = nic(priv);
priv->dbgfs_sram_offset = 0x800000;
- if (nic->shrd->ucode_type == IWL_UCODE_INIT)
- priv->dbgfs_sram_len = nic->fw.ucode_init.data.len;
+ if (priv->shrd->ucode_type == IWL_UCODE_INIT)
+ priv->dbgfs_sram_len = priv->fw->ucode_init.data.len;
else
- priv->dbgfs_sram_len = nic->fw.ucode_rt.data.len;
+ priv->dbgfs_sram_len = priv->fw->ucode_rt.data.len;
}
len = priv->dbgfs_sram_len;
@@ -343,7 +341,7 @@ static ssize_t iwl_dbgfs_wowlan_sram_read(struct file *file,
return simple_read_from_buffer(user_buf, count, ppos,
priv->wowlan_sram,
- nic(priv)->fw.ucode_wowlan.data.len);
+ priv->fw->ucode_wowlan.data.len);
}
static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -456,7 +454,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
char *buf;
ssize_t ret;
- if (!test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status))
+ if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
@@ -527,32 +525,26 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
test_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status));
- pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
- test_bit(STATUS_INT_ENABLED, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
- test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
+ test_bit(STATUS_RF_KILL_HW, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",
- test_bit(STATUS_CT_KILL, &priv->shrd->status));
- pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
- test_bit(STATUS_INIT, &priv->shrd->status));
+ test_bit(STATUS_CT_KILL, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
- test_bit(STATUS_ALIVE, &priv->shrd->status));
+ test_bit(STATUS_ALIVE, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
- test_bit(STATUS_READY, &priv->shrd->status));
- pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
- test_bit(STATUS_TEMPERATURE, &priv->shrd->status));
+ test_bit(STATUS_READY, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
- test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status));
+ test_bit(STATUS_GEO_CONFIGURED, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
- test_bit(STATUS_EXIT_PENDING, &priv->shrd->status));
+ test_bit(STATUS_EXIT_PENDING, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
- test_bit(STATUS_STATISTICS, &priv->shrd->status));
+ test_bit(STATUS_STATISTICS, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
- test_bit(STATUS_SCANNING, &priv->shrd->status));
+ test_bit(STATUS_SCANNING, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
- test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status));
+ test_bit(STATUS_SCAN_ABORTING, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
- test_bit(STATUS_SCAN_HW, &priv->shrd->status));
+ test_bit(STATUS_SCAN_HW, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
test_bit(STATUS_POWER_PMI, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
@@ -758,14 +750,14 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))
return -EINVAL;
- if (!iwl_is_ready_rf(priv->shrd))
+ if (!iwl_is_ready_rf(priv))
return -EAGAIN;
priv->power_data.debug_sleep_level_override = value;
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
iwl_power_update_mode(priv, true);
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
return count;
}
@@ -836,7 +828,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
char *buf;
int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
- (hw_params(priv).max_txq_num * 32 * 8) + 400;
+ (cfg(priv)->base_params->num_of_queues * 32 * 8) + 400;
const u8 *ptr;
ssize_t ret;
@@ -845,8 +837,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
IWL_ERR(priv, "Can not allocate buffer\n");
return -ENOMEM;
}
- if (priv->tx_traffic &&
- (iwl_get_debug_level(priv->shrd) & IWL_DL_TX)) {
+ if (priv->tx_traffic && iwl_have_debug_level(IWL_DL_TX)) {
ptr = priv->tx_traffic;
pos += scnprintf(buf + pos, bufsz - pos,
"Tx Traffic idx: %u\n", priv->tx_traffic_idx);
@@ -864,8 +855,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
}
}
- if (priv->rx_traffic &&
- (iwl_get_debug_level(priv->shrd) & IWL_DL_RX)) {
+ if (priv->rx_traffic && iwl_have_debug_level(IWL_DL_RX)) {
ptr = priv->rx_traffic;
pos += scnprintf(buf + pos, bufsz - pos,
"Rx Traffic idx: %u\n", priv->rx_traffic_idx);
@@ -920,6 +910,8 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
int p = 0;
u32 flag;
+ lockdep_assert_held(&priv->statistics.lock);
+
flag = le32_to_cpu(priv->statistics.flag);
p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag);
@@ -953,7 +945,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
struct statistics_rx_non_phy *delta_general, *max_general;
struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;
- if (!iwl_is_alive(priv->shrd))
+ if (!iwl_is_alive(priv))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
@@ -967,6 +959,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
+ spin_lock_bh(&priv->statistics.lock);
ofdm = &priv->statistics.rx_ofdm;
cck = &priv->statistics.rx_cck;
general = &priv->statistics.rx_non_phy;
@@ -1363,6 +1356,8 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
accum_ht->unsupport_mcs,
delta_ht->unsupport_mcs, max_ht->unsupport_mcs);
+ spin_unlock_bh(&priv->statistics.lock);
+
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
@@ -1379,7 +1374,7 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
ssize_t ret;
struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
- if (!iwl_is_alive(priv->shrd))
+ if (!iwl_is_alive(priv))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
@@ -1392,6 +1387,8 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
+ spin_lock_bh(&priv->statistics.lock);
+
tx = &priv->statistics.tx;
accum_tx = &priv->accum_stats.tx;
delta_tx = &priv->delta_stats.tx;
@@ -1541,19 +1538,25 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) {
pos += scnprintf(buf + pos, bufsz - pos,
"tx power: (1/2 dB step)\n");
- if ((cfg(priv)->valid_tx_ant & ANT_A) && tx->tx_power.ant_a)
+ if ((hw_params(priv).valid_tx_ant & ANT_A) &&
+ tx->tx_power.ant_a)
pos += scnprintf(buf + pos, bufsz - pos,
fmt_hex, "antenna A:",
tx->tx_power.ant_a);
- if ((cfg(priv)->valid_tx_ant & ANT_B) && tx->tx_power.ant_b)
+ if ((hw_params(priv).valid_tx_ant & ANT_B) &&
+ tx->tx_power.ant_b)
pos += scnprintf(buf + pos, bufsz - pos,
fmt_hex, "antenna B:",
tx->tx_power.ant_b);
- if ((cfg(priv)->valid_tx_ant & ANT_C) && tx->tx_power.ant_c)
+ if ((hw_params(priv).valid_tx_ant & ANT_C) &&
+ tx->tx_power.ant_c)
pos += scnprintf(buf + pos, bufsz - pos,
fmt_hex, "antenna C:",
tx->tx_power.ant_c);
}
+
+ spin_unlock_bh(&priv->statistics.lock);
+
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
@@ -1573,7 +1576,7 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
struct statistics_div *div, *accum_div, *delta_div, *max_div;
- if (!iwl_is_alive(priv->shrd))
+ if (!iwl_is_alive(priv))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
@@ -1586,6 +1589,9 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
+
+ spin_lock_bh(&priv->statistics.lock);
+
general = &priv->statistics.common;
dbg = &priv->statistics.common.dbg;
div = &priv->statistics.common.div;
@@ -1670,6 +1676,9 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
accum_general->num_of_sos_states,
delta_general->num_of_sos_states,
max_general->num_of_sos_states);
+
+ spin_unlock_bh(&priv->statistics.lock);
+
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
@@ -1686,16 +1695,16 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
ssize_t ret;
struct statistics_bt_activity *bt, *accum_bt;
- if (!iwl_is_alive(priv->shrd))
+ if (!iwl_is_alive(priv))
return -EAGAIN;
if (!priv->bt_enable_flag)
return -EINVAL;
/* make request to uCode to retrieve statistics information */
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
if (ret) {
IWL_ERR(priv,
@@ -1713,6 +1722,9 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
+
+ spin_lock_bh(&priv->statistics.lock);
+
bt = &priv->statistics.bt_activity;
accum_bt = &priv->accum_stats.bt_activity;
@@ -1758,6 +1770,8 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
le32_to_cpu(priv->statistics.num_bt_kills),
priv->statistics.accum_num_bt_kills);
+ spin_unlock_bh(&priv->statistics.lock);
+
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
@@ -1774,7 +1788,7 @@ static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file,
(sizeof(struct reply_agg_tx_error_statistics) * 24) + 200;
ssize_t ret;
- if (!iwl_is_alive(priv->shrd))
+ if (!iwl_is_alive(priv))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
@@ -2086,9 +2100,9 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file,
return -EFAULT;
/* make request to uCode to retrieve statistics information */
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
iwl_send_statistics_request(priv, CMD_SYNC, true);
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
return count;
}
@@ -2132,7 +2146,7 @@ static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file,
if (trace) {
priv->event_log.ucode_trace = true;
- if (iwl_is_alive(priv->shrd)) {
+ if (iwl_is_alive(priv)) {
/* start collecting data now */
mod_timer(&priv->ucode_trace, jiffies);
}
@@ -2221,7 +2235,7 @@ static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,
const size_t bufsz = sizeof(buf);
pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
- cfg(priv)->base_params->plcp_delta_threshold);
+ priv->plcp_delta_threshold);
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@@ -2243,10 +2257,10 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
return -EINVAL;
if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
(plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
- cfg(priv)->base_params->plcp_delta_threshold =
+ priv->plcp_delta_threshold =
IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
else
- cfg(priv)->base_params->plcp_delta_threshold = plcp;
+ priv->plcp_delta_threshold = plcp;
return count;
}
@@ -2322,7 +2336,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,
if (sscanf(buf, "%d", &flush) != 1)
return -EINVAL;
- if (iwl_is_rfkill(priv->shrd))
+ if (iwl_is_rfkill(priv))
return -EFAULT;
iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
@@ -2348,7 +2362,7 @@ static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file,
if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT)
timeout = IWL_DEF_WD_TIMEOUT;
- cfg(priv)->base_params->wd_timeout = timeout;
+ hw_params(priv).wd_timeout = timeout;
iwl_setup_watchdog(priv);
return count;
}
@@ -2411,7 +2425,7 @@ static ssize_t iwl_dbgfs_protection_mode_read(struct file *file,
if (cfg(priv)->ht_params)
pos += scnprintf(buf + pos, bufsz - pos,
"use %s for aggregation\n",
- (cfg(priv)->ht_params->use_rts_for_aggregation) ?
+ (hw_params(priv).use_rts_for_aggregation) ?
"rts/cts" : "cts-to-self");
else
pos += scnprintf(buf + pos, bufsz - pos, "N/A");
@@ -2438,9 +2452,9 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
if (sscanf(buf, "%d", &rts) != 1)
return -EINVAL;
if (rts)
- cfg(priv)->ht_params->use_rts_for_aggregation = true;
+ hw_params(priv).use_rts_for_aggregation = true;
else
- cfg(priv)->ht_params->use_rts_for_aggregation = false;
+ hw_params(priv).use_rts_for_aggregation = false;
return count;
}
@@ -2486,52 +2500,6 @@ DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);
DEBUGFS_READ_FILE_OPS(reply_tx_error);
DEBUGFS_WRITE_FILE_OPS(echo_test);
-#ifdef CONFIG_IWLWIFI_DEBUG
-static ssize_t iwl_dbgfs_debug_level_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- struct iwl_shared *shrd = priv->shrd;
- char buf[11];
- int len;
-
- len = scnprintf(buf, sizeof(buf), "0x%.8x",
- iwl_get_debug_level(shrd));
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static ssize_t iwl_dbgfs_debug_level_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- struct iwl_shared *shrd = priv->shrd;
- char buf[11];
- unsigned long val;
- int ret;
-
- if (count > sizeof(buf))
- return -EINVAL;
-
- memset(buf, 0, sizeof(buf));
- if (copy_from_user(buf, user_buf, count))
- return -EFAULT;
-
- ret = strict_strtoul(buf, 0, &val);
- if (ret)
- return ret;
-
- shrd->dbg_level_dev = val;
- if (iwl_alloc_traffic_mem(priv))
- IWL_ERR(priv, "Not enough memory to generate traffic log\n");
-
- return count;
-}
-DEBUGFS_READ_WRITE_FILE_OPS(debug_level);
-#endif /* CONFIG_IWLWIFI_DEBUG */
-
/*
* Create the debugfs files and directories
*
@@ -2596,9 +2564,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR);
if (iwl_advanced_bt_coexist(priv))
DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR);
-#ifdef CONFIG_IWLWIFI_DEBUG
- DEBUGFS_ADD_FILE(debug_level, dir_debug, S_IRUSR | S_IWUSR);
-#endif
DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
&priv->disable_sens_cal);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 6e5bf0a1460..aa4b3b122da 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -36,11 +36,10 @@
#include <linux/wait.h>
#include <linux/leds.h>
#include <linux/slab.h>
-#include <net/ieee80211_radiotap.h>
+#include <linux/mutex.h>
#include "iwl-eeprom.h"
#include "iwl-csr.h"
-#include "iwl-prph.h"
#include "iwl-debug.h"
#include "iwl-agn-hw.h"
#include "iwl-led.h"
@@ -50,6 +49,7 @@
#include "iwl-trans.h"
#include "iwl-shared.h"
#include "iwl-op-mode.h"
+#include "iwl-notif-wait.h"
struct iwl_tx_queue;
@@ -294,7 +294,6 @@ struct iwl_vif_priv {
struct iwl_sensitivity_ranges {
u16 min_nrg_cck;
- u16 max_nrg_cck;
u16 nrg_th_cck;
u16 nrg_th_ofdm;
@@ -670,11 +669,6 @@ struct iwl_rxon_context {
bool enabled, is_40mhz;
u8 extension_chan_offset;
} ht;
-
- u8 bssid[ETH_ALEN];
- bool preauth_bssid;
-
- bool last_tx_rejected;
};
enum iwl_scan_type {
@@ -718,29 +712,44 @@ struct iwl_priv {
/*data shared among all the driver's layers */
struct iwl_shared *shrd;
+ const struct iwl_fw *fw;
+ unsigned long status;
+
+ spinlock_t sta_lock;
+ struct mutex mutex;
+
+ unsigned long transport_queue_stop;
+ bool passive_no_rx;
/* ieee device used by generic ieee processing code */
struct ieee80211_hw *hw;
struct ieee80211_channel *ieee_channels;
struct ieee80211_rate *ieee_rates;
- struct kmem_cache *tx_cmd_pool;
+
+ struct list_head calib_results;
struct workqueue_struct *workqueue;
enum ieee80211_band band;
void (*pre_rx_handler)(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb);
+ struct iwl_rx_cmd_buffer *rxb);
int (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
+ struct iwl_notif_wait_data notif_wait;
+
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
/* spectrum measurement report caching */
struct iwl_spectrum_notification measure_report;
u8 measurement_status;
+#define IWL_OWNERSHIP_DRIVER 0
+#define IWL_OWNERSHIP_TM 1
+ u8 ucode_owner;
+
/* ucode beacon time */
u32 ucode_beacon_time;
int missed_beacon_threshold;
@@ -766,6 +775,8 @@ struct iwl_priv {
struct iwl_channel_info *channel_info; /* channel info array */
u8 channel_count; /* # of channels */
+ u8 plcp_delta_threshold;
+
/* thermal calibration */
s32 temperature; /* Celsius */
s32 last_temperature;
@@ -788,6 +799,8 @@ struct iwl_priv {
bool new_scan_threshold_behaviour;
+ bool wowlan;
+
/* EEPROM MAC addresses */
struct mac_address addresses[2];
@@ -845,6 +858,7 @@ struct iwl_priv {
struct statistics_bt_activity bt_activity;
__le32 num_bt_kills, accum_num_bt_kills;
#endif
+ spinlock_t lock;
} statistics;
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct {
@@ -968,6 +982,7 @@ struct iwl_priv {
bool have_rekey_data;
}; /*iwl_priv */
+extern struct kmem_cache *iwl_tx_cmd_pool;
extern struct iwl_mod_params iwlagn_mod_params;
static inline struct iwl_rxon_context *
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
index 96e62338cec..06203d6a1d8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h
+++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
@@ -41,130 +41,134 @@ static inline void trace_ ## name(proto) {}
static inline void trace_ ## name(proto) {}
#endif
-#define PRIV_ENTRY __field(void *, priv)
-#define PRIV_ASSIGN __entry->priv = priv
+#define DEV_ENTRY __string(dev, dev_name(dev))
+#define DEV_ASSIGN __assign_str(dev, dev_name(dev))
#undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi_io
TRACE_EVENT(iwlwifi_dev_ioread32,
- TP_PROTO(void *priv, u32 offs, u32 val),
- TP_ARGS(priv, offs, val),
+ TP_PROTO(const struct device *dev, u32 offs, u32 val),
+ TP_ARGS(dev, offs, val),
TP_STRUCT__entry(
- PRIV_ENTRY
+ DEV_ENTRY
__field(u32, offs)
__field(u32, val)
),
TP_fast_assign(
- PRIV_ASSIGN;
+ DEV_ASSIGN;
__entry->offs = offs;
__entry->val = val;
),
- TP_printk("[%p] read io[%#x] = %#x", __entry->priv, __entry->offs, __entry->val)
+ TP_printk("[%s] read io[%#x] = %#x",
+ __get_str(dev), __entry->offs, __entry->val)
);
TRACE_EVENT(iwlwifi_dev_iowrite8,
- TP_PROTO(void *priv, u32 offs, u8 val),
- TP_ARGS(priv, offs, val),
+ TP_PROTO(const struct device *dev, u32 offs, u8 val),
+ TP_ARGS(dev, offs, val),
TP_STRUCT__entry(
- PRIV_ENTRY
+ DEV_ENTRY
__field(u32, offs)
__field(u8, val)
),
TP_fast_assign(
- PRIV_ASSIGN;
+ DEV_ASSIGN;
__entry->offs = offs;
__entry->val = val;
),
- TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val)
+ TP_printk("[%s] write io[%#x] = %#x)",
+ __get_str(dev), __entry->offs, __entry->val)
);
TRACE_EVENT(iwlwifi_dev_iowrite32,
- TP_PROTO(void *priv, u32 offs, u32 val),
- TP_ARGS(priv, offs, val),
+ TP_PROTO(const struct device *dev, u32 offs, u32 val),
+ TP_ARGS(dev, offs, val),
TP_STRUCT__entry(
- PRIV_ENTRY
+ DEV_ENTRY
__field(u32, offs)
__field(u32, val)
),
TP_fast_assign(
- PRIV_ASSIGN;
+ DEV_ASSIGN;
__entry->offs = offs;
__entry->val = val;
),
- TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val)
+ TP_printk("[%s] write io[%#x] = %#x)",
+ __get_str(dev), __entry->offs, __entry->val)
);
TRACE_EVENT(iwlwifi_dev_irq,
- TP_PROTO(void *priv),
- TP_ARGS(priv),
+ TP_PROTO(const struct device *dev),
+ TP_ARGS(dev),
TP_STRUCT__entry(
- PRIV_ENTRY
+ DEV_ENTRY
),
TP_fast_assign(
- PRIV_ASSIGN;
+ DEV_ASSIGN;
),
/* TP_printk("") doesn't compile */
TP_printk("%d", 0)
);
TRACE_EVENT(iwlwifi_dev_ict_read,
- TP_PROTO(void *priv, u32 index, u32 value),
- TP_ARGS(priv, index, value),
+ TP_PROTO(const struct device *dev, u32 index, u32 value),
+ TP_ARGS(dev, index, value),
TP_STRUCT__entry(
- PRIV_ENTRY
+ DEV_ENTRY
__field(u32, index)
__field(u32, value)
),
TP_fast_assign(
- PRIV_ASSIGN;
+ DEV_ASSIGN;
__entry->index = index;
__entry->value = value;
),
- TP_printk("read ict[%d] = %#.8x", __entry->index, __entry->value)
+ TP_printk("[%s] read ict[%d] = %#.8x",
+ __get_str(dev), __entry->index, __entry->value)
);
#undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi_ucode
TRACE_EVENT(iwlwifi_dev_ucode_cont_event,
- TP_PROTO(void *priv, u32 time, u32 data, u32 ev),
- TP_ARGS(priv, time, data, ev),
+ TP_PROTO(const struct device *dev, u32 time, u32 data, u32 ev),
+ TP_ARGS(dev, time, data, ev),
TP_STRUCT__entry(
- PRIV_ENTRY
+ DEV_ENTRY
__field(u32, time)
__field(u32, data)
__field(u32, ev)
),
TP_fast_assign(
- PRIV_ASSIGN;
+ DEV_ASSIGN;
__entry->time = time;
__entry->data = data;
__entry->ev = ev;
),
- TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
- __entry->priv, __entry->time, __entry->data, __entry->ev)
+ TP_printk("[%s] EVT_LOGT:%010u:0x%08x:%04u",
+ __get_str(dev), __entry->time, __entry->data, __entry->ev)
);
TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
- TP_PROTO(void *priv, u32 wraps, u32 n_entry, u32 p_entry),
- TP_ARGS(priv, wraps, n_entry, p_entry),
+ TP_PROTO(const struct device *dev, u32 wraps, u32 n_entry, u32 p_entry),
+ TP_ARGS(dev, wraps, n_entry, p_entry),
TP_STRUCT__entry(
- PRIV_ENTRY
+ DEV_ENTRY
__field(u32, wraps)
__field(u32, n_entry)
__field(u32, p_entry)
),
TP_fast_assign(
- PRIV_ASSIGN;
+ DEV_ASSIGN;
__entry->wraps = wraps;
__entry->n_entry = n_entry;
__entry->p_entry = p_entry;
),
- TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X",
- __entry->priv, __entry->wraps, __entry->n_entry,
+ TP_printk("[%s] wraps=#%02d n=0x%X p=0x%X",
+ __get_str(dev), __entry->wraps, __entry->n_entry,
__entry->p_entry)
);
@@ -232,52 +236,52 @@ TRACE_EVENT(iwlwifi_dbg,
#define TRACE_SYSTEM iwlwifi
TRACE_EVENT(iwlwifi_dev_hcmd,
- TP_PROTO(void *priv, u32 flags,
+ TP_PROTO(const struct device *dev, u32 flags,
const void *hcmd0, size_t len0,
const void *hcmd1, size_t len1,
const void *hcmd2, size_t len2),
- TP_ARGS(priv, flags, hcmd0, len0, hcmd1, len1, hcmd2, len2),
+ TP_ARGS(dev, flags, hcmd0, len0, hcmd1, len1, hcmd2, len2),
TP_STRUCT__entry(
- PRIV_ENTRY
+ DEV_ENTRY
__dynamic_array(u8, hcmd0, len0)
__dynamic_array(u8, hcmd1, len1)
__dynamic_array(u8, hcmd2, len2)
__field(u32, flags)
),
TP_fast_assign(
- PRIV_ASSIGN;
+ DEV_ASSIGN;
memcpy(__get_dynamic_array(hcmd0), hcmd0, len0);
memcpy(__get_dynamic_array(hcmd1), hcmd1, len1);
memcpy(__get_dynamic_array(hcmd2), hcmd2, len2);
__entry->flags = flags;
),
- TP_printk("[%p] hcmd %#.2x (%ssync)",
- __entry->priv, ((u8 *)__get_dynamic_array(hcmd0))[0],
+ TP_printk("[%s] hcmd %#.2x (%ssync)",
+ __get_str(dev), ((u8 *)__get_dynamic_array(hcmd0))[0],
__entry->flags & CMD_ASYNC ? "a" : "")
);
TRACE_EVENT(iwlwifi_dev_rx,
- TP_PROTO(void *priv, void *rxbuf, size_t len),
- TP_ARGS(priv, rxbuf, len),
+ TP_PROTO(const struct device *dev, void *rxbuf, size_t len),
+ TP_ARGS(dev, rxbuf, len),
TP_STRUCT__entry(
- PRIV_ENTRY
+ DEV_ENTRY
__dynamic_array(u8, rxbuf, len)
),
TP_fast_assign(
- PRIV_ASSIGN;
+ DEV_ASSIGN;
memcpy(__get_dynamic_array(rxbuf), rxbuf, len);
),
- TP_printk("[%p] RX cmd %#.2x",
- __entry->priv, ((u8 *)__get_dynamic_array(rxbuf))[4])
+ TP_printk("[%s] RX cmd %#.2x",
+ __get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4])
);
TRACE_EVENT(iwlwifi_dev_tx,
- TP_PROTO(void *priv, void *tfd, size_t tfdlen,
+ TP_PROTO(const struct device *dev, void *tfd, size_t tfdlen,
void *buf0, size_t buf0_len,
void *buf1, size_t buf1_len),
- TP_ARGS(priv, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
+ TP_ARGS(dev, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
TP_STRUCT__entry(
- PRIV_ENTRY
+ DEV_ENTRY
__field(size_t, framelen)
__dynamic_array(u8, tfd, tfdlen)
@@ -291,29 +295,28 @@ TRACE_EVENT(iwlwifi_dev_tx,
__dynamic_array(u8, buf1, buf1_len)
),
TP_fast_assign(
- PRIV_ASSIGN;
+ DEV_ASSIGN;
__entry->framelen = buf0_len + buf1_len;
memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
),
- TP_printk("[%p] TX %.2x (%zu bytes)",
- __entry->priv,
- ((u8 *)__get_dynamic_array(buf0))[0],
+ TP_printk("[%s] TX %.2x (%zu bytes)",
+ __get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0],
__entry->framelen)
);
TRACE_EVENT(iwlwifi_dev_ucode_error,
- TP_PROTO(void *priv, u32 desc, u32 tsf_low,
+ TP_PROTO(const struct device *dev, u32 desc, u32 tsf_low,
u32 data1, u32 data2, u32 line, u32 blink1,
u32 blink2, u32 ilink1, u32 ilink2, u32 bcon_time,
u32 gp1, u32 gp2, u32 gp3, u32 ucode_ver, u32 hw_ver,
u32 brd_ver),
- TP_ARGS(priv, desc, tsf_low, data1, data2, line,
+ TP_ARGS(dev, desc, tsf_low, data1, data2, line,
blink1, blink2, ilink1, ilink2, bcon_time, gp1, gp2,
gp3, ucode_ver, hw_ver, brd_ver),
TP_STRUCT__entry(
- PRIV_ENTRY
+ DEV_ENTRY
__field(u32, desc)
__field(u32, tsf_low)
__field(u32, data1)
@@ -332,7 +335,7 @@ TRACE_EVENT(iwlwifi_dev_ucode_error,
__field(u32, brd_ver)
),
TP_fast_assign(
- PRIV_ASSIGN;
+ DEV_ASSIGN;
__entry->desc = desc;
__entry->tsf_low = tsf_low;
__entry->data1 = data1;
@@ -350,11 +353,11 @@ TRACE_EVENT(iwlwifi_dev_ucode_error,
__entry->hw_ver = hw_ver;
__entry->brd_ver = brd_ver;
),
- TP_printk("[%p] #%02d %010u data 0x%08X 0x%08X line %u, "
+ TP_printk("[%s] #%02d %010u data 0x%08X 0x%08X line %u, "
"blink 0x%05X 0x%05X ilink 0x%05X 0x%05X "
"bcon_tm %010u gp 0x%08X 0x%08X 0x%08X uCode 0x%08X "
"hw 0x%08X brd 0x%08X",
- __entry->priv, __entry->desc, __entry->tsf_low,
+ __get_str(dev), __entry->desc, __entry->tsf_low,
__entry->data1,
__entry->data2, __entry->line, __entry->blink1,
__entry->blink2, __entry->ilink1, __entry->ilink2,
@@ -364,23 +367,23 @@ TRACE_EVENT(iwlwifi_dev_ucode_error,
);
TRACE_EVENT(iwlwifi_dev_ucode_event,
- TP_PROTO(void *priv, u32 time, u32 data, u32 ev),
- TP_ARGS(priv, time, data, ev),
+ TP_PROTO(const struct device *dev, u32 time, u32 data, u32 ev),
+ TP_ARGS(dev, time, data, ev),
TP_STRUCT__entry(
- PRIV_ENTRY
+ DEV_ENTRY
__field(u32, time)
__field(u32, data)
__field(u32, ev)
),
TP_fast_assign(
- PRIV_ASSIGN;
+ DEV_ASSIGN;
__entry->time = time;
__entry->data = data;
__entry->ev = ev;
),
- TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
- __entry->priv, __entry->time, __entry->data, __entry->ev)
+ TP_printk("[%s] EVT_LOGT:%010u:0x%08x:%04u",
+ __get_str(dev), __entry->time, __entry->data, __entry->ev)
);
#endif /* __IWLWIFI_DEVICE_TRACE */
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 8ff52568cf6..29a3ae48df6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -61,33 +61,686 @@
*
*****************************************************************************/
#include <linux/completion.h>
+#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
+#include <linux/module.h>
#include "iwl-drv.h"
#include "iwl-trans.h"
-#include "iwl-wifi.h"
+#include "iwl-shared.h"
#include "iwl-op-mode.h"
+/* private includes */
+#include "iwl-fw-file.h"
+
+/**
+ * struct iwl_drv - drv common data
+ * @fw: the iwl_fw structure
+ * @shrd: pointer to common shared structure
+ * @op_mode: the running op_mode
+ * @fw_index: firmware revision to try loading
+ * @firmware_name: composite filename of ucode file to load
+ * @request_firmware_complete: the firmware has been obtained from user space
+ */
+struct iwl_drv {
+ struct iwl_fw fw;
+
+ struct iwl_shared *shrd;
+ struct iwl_op_mode *op_mode;
+
+ int fw_index; /* firmware we're trying to load */
+ char firmware_name[25]; /* name of firmware file to load */
+
+ struct completion request_firmware_complete;
+};
+
+
+
+static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc)
+{
+ if (desc->v_addr)
+ dma_free_coherent(trans(drv)->dev, desc->len,
+ desc->v_addr, desc->p_addr);
+ desc->v_addr = NULL;
+ desc->len = 0;
+}
+
+static void iwl_free_fw_img(struct iwl_drv *drv, struct fw_img *img)
+{
+ iwl_free_fw_desc(drv, &img->code);
+ iwl_free_fw_desc(drv, &img->data);
+}
+
+static void iwl_dealloc_ucode(struct iwl_drv *drv)
+{
+ iwl_free_fw_img(drv, &drv->fw.ucode_rt);
+ iwl_free_fw_img(drv, &drv->fw.ucode_init);
+ iwl_free_fw_img(drv, &drv->fw.ucode_wowlan);
+}
+
+static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
+ const void *data, size_t len)
+{
+ if (!len) {
+ desc->v_addr = NULL;
+ return -EINVAL;
+ }
+
+ desc->v_addr = dma_alloc_coherent(trans(drv)->dev, len,
+ &desc->p_addr, GFP_KERNEL);
+ if (!desc->v_addr)
+ return -ENOMEM;
+
+ desc->len = len;
+ memcpy(desc->v_addr, data, len);
+ return 0;
+}
+
+static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
+
+#define UCODE_EXPERIMENTAL_INDEX 100
+#define UCODE_EXPERIMENTAL_TAG "exp"
+
+static int iwl_request_firmware(struct iwl_drv *drv, bool first)
+{
+ const struct iwl_cfg *cfg = cfg(drv);
+ const char *name_pre = cfg->fw_name_pre;
+ char tag[8];
+
+ if (first) {
+#ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
+ drv->fw_index = UCODE_EXPERIMENTAL_INDEX;
+ strcpy(tag, UCODE_EXPERIMENTAL_TAG);
+ } else if (drv->fw_index == UCODE_EXPERIMENTAL_INDEX) {
+#endif
+ drv->fw_index = cfg->ucode_api_max;
+ sprintf(tag, "%d", drv->fw_index);
+ } else {
+ drv->fw_index--;
+ sprintf(tag, "%d", drv->fw_index);
+ }
+
+ if (drv->fw_index < cfg->ucode_api_min) {
+ IWL_ERR(drv, "no suitable firmware found!\n");
+ return -ENOENT;
+ }
+
+ sprintf(drv->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
+
+ IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n",
+ (drv->fw_index == UCODE_EXPERIMENTAL_INDEX)
+ ? "EXPERIMENTAL " : "",
+ drv->firmware_name);
+
+ return request_firmware_nowait(THIS_MODULE, 1, drv->firmware_name,
+ trans(drv)->dev,
+ GFP_KERNEL, drv, iwl_ucode_callback);
+}
+
+struct iwlagn_firmware_pieces {
+ const void *inst, *data, *init, *init_data, *wowlan_inst, *wowlan_data;
+ size_t inst_size, data_size, init_size, init_data_size,
+ wowlan_inst_size, wowlan_data_size;
+
+ u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
+ u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
+};
+
+static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv,
+ const struct firmware *ucode_raw,
+ struct iwlagn_firmware_pieces *pieces)
+{
+ struct iwl_ucode_header *ucode = (void *)ucode_raw->data;
+ u32 api_ver, hdr_size, build;
+ char buildstr[25];
+ const u8 *src;
+
+ drv->fw.ucode_ver = le32_to_cpu(ucode->ver);
+ api_ver = IWL_UCODE_API(drv->fw.ucode_ver);
+
+ switch (api_ver) {
+ default:
+ hdr_size = 28;
+ if (ucode_raw->size < hdr_size) {
+ IWL_ERR(drv, "File size too small!\n");
+ return -EINVAL;
+ }
+ build = le32_to_cpu(ucode->u.v2.build);
+ pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size);
+ pieces->data_size = le32_to_cpu(ucode->u.v2.data_size);
+ pieces->init_size = le32_to_cpu(ucode->u.v2.init_size);
+ pieces->init_data_size =
+ le32_to_cpu(ucode->u.v2.init_data_size);
+ src = ucode->u.v2.data;
+ break;
+ case 0:
+ case 1:
+ case 2:
+ hdr_size = 24;
+ if (ucode_raw->size < hdr_size) {
+ IWL_ERR(drv, "File size too small!\n");
+ return -EINVAL;
+ }
+ build = 0;
+ pieces->inst_size = le32_to_cpu(ucode->u.v1.inst_size);
+ pieces->data_size = le32_to_cpu(ucode->u.v1.data_size);
+ pieces->init_size = le32_to_cpu(ucode->u.v1.init_size);
+ pieces->init_data_size =
+ le32_to_cpu(ucode->u.v1.init_data_size);
+ src = ucode->u.v1.data;
+ break;
+ }
+
+ if (build)
+ sprintf(buildstr, " build %u%s", build,
+ (drv->fw_index == UCODE_EXPERIMENTAL_INDEX)
+ ? " (EXP)" : "");
+ else
+ buildstr[0] = '\0';
+
+ snprintf(drv->fw.fw_version,
+ sizeof(drv->fw.fw_version),
+ "%u.%u.%u.%u%s",
+ IWL_UCODE_MAJOR(drv->fw.ucode_ver),
+ IWL_UCODE_MINOR(drv->fw.ucode_ver),
+ IWL_UCODE_API(drv->fw.ucode_ver),
+ IWL_UCODE_SERIAL(drv->fw.ucode_ver),
+ buildstr);
+
+ /* Verify size of file vs. image size info in file's header */
+ if (ucode_raw->size != hdr_size + pieces->inst_size +
+ pieces->data_size + pieces->init_size +
+ pieces->init_data_size) {
+
+ IWL_ERR(drv,
+ "uCode file size %d does not match expected size\n",
+ (int)ucode_raw->size);
+ return -EINVAL;
+ }
+
+ pieces->inst = src;
+ src += pieces->inst_size;
+ pieces->data = src;
+ src += pieces->data_size;
+ pieces->init = src;
+ src += pieces->init_size;
+ pieces->init_data = src;
+ src += pieces->init_data_size;
+
+ return 0;
+}
+
+static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
+ const struct firmware *ucode_raw,
+ struct iwlagn_firmware_pieces *pieces,
+ struct iwl_ucode_capabilities *capa)
+{
+ struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data;
+ struct iwl_ucode_tlv *tlv;
+ size_t len = ucode_raw->size;
+ const u8 *data;
+ int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative;
+ int tmp;
+ u64 alternatives;
+ u32 tlv_len;
+ enum iwl_ucode_tlv_type tlv_type;
+ const u8 *tlv_data;
+ char buildstr[25];
+ u32 build;
+
+ if (len < sizeof(*ucode)) {
+ IWL_ERR(drv, "uCode has invalid length: %zd\n", len);
+ return -EINVAL;
+ }
+
+ if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) {
+ IWL_ERR(drv, "invalid uCode magic: 0X%x\n",
+ le32_to_cpu(ucode->magic));
+ return -EINVAL;
+ }
+
+ /*
+ * Check which alternatives are present, and "downgrade"
+ * when the chosen alternative is not present, warning
+ * the user when that happens. Some files may not have
+ * any alternatives, so don't warn in that case.
+ */
+ alternatives = le64_to_cpu(ucode->alternatives);
+ tmp = wanted_alternative;
+ if (wanted_alternative > 63)
+ wanted_alternative = 63;
+ while (wanted_alternative && !(alternatives & BIT(wanted_alternative)))
+ wanted_alternative--;
+ if (wanted_alternative && wanted_alternative != tmp)
+ IWL_WARN(drv,
+ "uCode alternative %d not available, choosing %d\n",
+ tmp, wanted_alternative);
+
+ drv->fw.ucode_ver = le32_to_cpu(ucode->ver);
+ build = le32_to_cpu(ucode->build);
+
+ if (build)
+ sprintf(buildstr, " build %u%s", build,
+ (drv->fw_index == UCODE_EXPERIMENTAL_INDEX)
+ ? " (EXP)" : "");
+ else
+ buildstr[0] = '\0';
+
+ snprintf(drv->fw.fw_version,
+ sizeof(drv->fw.fw_version),
+ "%u.%u.%u.%u%s",
+ IWL_UCODE_MAJOR(drv->fw.ucode_ver),
+ IWL_UCODE_MINOR(drv->fw.ucode_ver),
+ IWL_UCODE_API(drv->fw.ucode_ver),
+ IWL_UCODE_SERIAL(drv->fw.ucode_ver),
+ buildstr);
+
+ data = ucode->data;
+
+ len -= sizeof(*ucode);
+
+ while (len >= sizeof(*tlv)) {
+ u16 tlv_alt;
+
+ len -= sizeof(*tlv);
+ tlv = (void *)data;
+
+ tlv_len = le32_to_cpu(tlv->length);
+ tlv_type = le16_to_cpu(tlv->type);
+ tlv_alt = le16_to_cpu(tlv->alternative);
+ tlv_data = tlv->data;
+
+ if (len < tlv_len) {
+ IWL_ERR(drv, "invalid TLV len: %zd/%u\n",
+ len, tlv_len);
+ return -EINVAL;
+ }
+ len -= ALIGN(tlv_len, 4);
+ data += sizeof(*tlv) + ALIGN(tlv_len, 4);
+
+ /*
+ * Alternative 0 is always valid.
+ *
+ * Skip alternative TLVs that are not selected.
+ */
+ if (tlv_alt != 0 && tlv_alt != wanted_alternative)
+ continue;
+
+ switch (tlv_type) {
+ case IWL_UCODE_TLV_INST:
+ pieces->inst = tlv_data;
+ pieces->inst_size = tlv_len;
+ break;
+ case IWL_UCODE_TLV_DATA:
+ pieces->data = tlv_data;
+ pieces->data_size = tlv_len;
+ break;
+ case IWL_UCODE_TLV_INIT:
+ pieces->init = tlv_data;
+ pieces->init_size = tlv_len;
+ break;
+ case IWL_UCODE_TLV_INIT_DATA:
+ pieces->init_data = tlv_data;
+ pieces->init_data_size = tlv_len;
+ break;
+ case IWL_UCODE_TLV_BOOT:
+ IWL_ERR(drv, "Found unexpected BOOT ucode\n");
+ break;
+ case IWL_UCODE_TLV_PROBE_MAX_LEN:
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ capa->max_probe_length =
+ le32_to_cpup((__le32 *)tlv_data);
+ break;
+ case IWL_UCODE_TLV_PAN:
+ if (tlv_len)
+ goto invalid_tlv_len;
+ capa->flags |= IWL_UCODE_TLV_FLAGS_PAN;
+ break;
+ case IWL_UCODE_TLV_FLAGS:
+ /* must be at least one u32 */
+ if (tlv_len < sizeof(u32))
+ goto invalid_tlv_len;
+ /* and a proper number of u32s */
+ if (tlv_len % sizeof(u32))
+ goto invalid_tlv_len;
+ /*
+ * This driver only reads the first u32 as
+ * right now no more features are defined,
+ * if that changes then either the driver
+ * will not work with the new firmware, or
+ * it'll not take advantage of new features.
+ */
+ capa->flags = le32_to_cpup((__le32 *)tlv_data);
+ break;
+ case IWL_UCODE_TLV_INIT_EVTLOG_PTR:
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ pieces->init_evtlog_ptr =
+ le32_to_cpup((__le32 *)tlv_data);
+ break;
+ case IWL_UCODE_TLV_INIT_EVTLOG_SIZE:
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ pieces->init_evtlog_size =
+ le32_to_cpup((__le32 *)tlv_data);
+ break;
+ case IWL_UCODE_TLV_INIT_ERRLOG_PTR:
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ pieces->init_errlog_ptr =
+ le32_to_cpup((__le32 *)tlv_data);
+ break;
+ case IWL_UCODE_TLV_RUNT_EVTLOG_PTR:
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ pieces->inst_evtlog_ptr =
+ le32_to_cpup((__le32 *)tlv_data);
+ break;
+ case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE:
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ pieces->inst_evtlog_size =
+ le32_to_cpup((__le32 *)tlv_data);
+ break;
+ case IWL_UCODE_TLV_RUNT_ERRLOG_PTR:
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ pieces->inst_errlog_ptr =
+ le32_to_cpup((__le32 *)tlv_data);
+ break;
+ case IWL_UCODE_TLV_ENHANCE_SENS_TBL:
+ if (tlv_len)
+ goto invalid_tlv_len;
+ drv->fw.enhance_sensitivity_table = true;
+ break;
+ case IWL_UCODE_TLV_WOWLAN_INST:
+ pieces->wowlan_inst = tlv_data;
+ pieces->wowlan_inst_size = tlv_len;
+ break;
+ case IWL_UCODE_TLV_WOWLAN_DATA:
+ pieces->wowlan_data = tlv_data;
+ pieces->wowlan_data_size = tlv_len;
+ break;
+ case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE:
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ capa->standard_phy_calibration_size =
+ le32_to_cpup((__le32 *)tlv_data);
+ break;
+ default:
+ IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
+ break;
+ }
+ }
+
+ if (len) {
+ IWL_ERR(drv, "invalid TLV after parsing: %zd\n", len);
+ iwl_print_hex_dump(drv, IWL_DL_FW, (u8 *)data, len);
+ return -EINVAL;
+ }
+
+ return 0;
+
+ invalid_tlv_len:
+ IWL_ERR(drv, "TLV %d has invalid size: %u\n", tlv_type, tlv_len);
+ iwl_print_hex_dump(drv, IWL_DL_FW, tlv_data, tlv_len);
+
+ return -EINVAL;
+}
+
+/**
+ * iwl_ucode_callback - callback when firmware was loaded
+ *
+ * If loaded successfully, copies the firmware into buffers
+ * for the card to fetch (via DMA).
+ */
+static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
+{
+ struct iwl_drv *drv = context;
+ const struct iwl_cfg *cfg = cfg(drv);
+ struct iwl_fw *fw = &drv->fw;
+ struct iwl_ucode_header *ucode;
+ int err;
+ struct iwlagn_firmware_pieces pieces;
+ const unsigned int api_max = cfg->ucode_api_max;
+ unsigned int api_ok = cfg->ucode_api_ok;
+ const unsigned int api_min = cfg->ucode_api_min;
+ u32 api_ver;
+
+ fw->ucode_capa.max_probe_length = 200;
+ fw->ucode_capa.standard_phy_calibration_size =
+ IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
+
+ if (!api_ok)
+ api_ok = api_max;
+
+ memset(&pieces, 0, sizeof(pieces));
+
+ if (!ucode_raw) {
+ if (drv->fw_index <= api_ok)
+ IWL_ERR(drv,
+ "request for firmware file '%s' failed.\n",
+ drv->firmware_name);
+ goto try_again;
+ }
+
+ IWL_DEBUG_INFO(drv, "Loaded firmware file '%s' (%zd bytes).\n",
+ drv->firmware_name, ucode_raw->size);
+
+ /* Make sure that we got at least the API version number */
+ if (ucode_raw->size < 4) {
+ IWL_ERR(drv, "File size way too small!\n");
+ goto try_again;
+ }
+
+ /* Data from ucode file: header followed by uCode images */
+ ucode = (struct iwl_ucode_header *)ucode_raw->data;
+
+ if (ucode->ver)
+ err = iwl_parse_v1_v2_firmware(drv, ucode_raw, &pieces);
+ else
+ err = iwl_parse_tlv_firmware(drv, ucode_raw, &pieces,
+ &fw->ucode_capa);
+
+ if (err)
+ goto try_again;
+
+ api_ver = IWL_UCODE_API(drv->fw.ucode_ver);
+
+ /*
+ * api_ver should match the api version forming part of the
+ * firmware filename ... but we don't check for that and only rely
+ * on the API version read from firmware header from here on forward
+ */
+ /* no api version check required for experimental uCode */
+ if (drv->fw_index != UCODE_EXPERIMENTAL_INDEX) {
+ if (api_ver < api_min || api_ver > api_max) {
+ IWL_ERR(drv,
+ "Driver unable to support your firmware API. "
+ "Driver supports v%u, firmware is v%u.\n",
+ api_max, api_ver);
+ goto try_again;
+ }
+
+ if (api_ver < api_ok) {
+ if (api_ok != api_max)
+ IWL_ERR(drv, "Firmware has old API version, "
+ "expected v%u through v%u, got v%u.\n",
+ api_ok, api_max, api_ver);
+ else
+ IWL_ERR(drv, "Firmware has old API version, "
+ "expected v%u, got v%u.\n",
+ api_max, api_ver);
+ IWL_ERR(drv, "New firmware can be obtained from "
+ "http://www.intellinuxwireless.org/.\n");
+ }
+ }
+
+ IWL_INFO(drv, "loaded firmware version %s", drv->fw.fw_version);
+
+ /*
+ * For any of the failures below (before allocating pci memory)
+ * we will try to load a version with a smaller API -- maybe the
+ * user just got a corrupted version of the latest API.
+ */
+
+ IWL_DEBUG_INFO(drv, "f/w package hdr ucode version raw = 0x%x\n",
+ drv->fw.ucode_ver);
+ IWL_DEBUG_INFO(drv, "f/w package hdr runtime inst size = %Zd\n",
+ pieces.inst_size);
+ IWL_DEBUG_INFO(drv, "f/w package hdr runtime data size = %Zd\n",
+ pieces.data_size);
+ IWL_DEBUG_INFO(drv, "f/w package hdr init inst size = %Zd\n",
+ pieces.init_size);
+ IWL_DEBUG_INFO(drv, "f/w package hdr init data size = %Zd\n",
+ pieces.init_data_size);
+
+ /* Verify that uCode images will fit in card's SRAM */
+ if (pieces.inst_size > cfg->max_inst_size) {
+ IWL_ERR(drv, "uCode instr len %Zd too large to fit in\n",
+ pieces.inst_size);
+ goto try_again;
+ }
+
+ if (pieces.data_size > cfg->max_data_size) {
+ IWL_ERR(drv, "uCode data len %Zd too large to fit in\n",
+ pieces.data_size);
+ goto try_again;
+ }
+
+ if (pieces.init_size > cfg->max_inst_size) {
+ IWL_ERR(drv, "uCode init instr len %Zd too large to fit in\n",
+ pieces.init_size);
+ goto try_again;
+ }
+
+ if (pieces.init_data_size > cfg->max_data_size) {
+ IWL_ERR(drv, "uCode init data len %Zd too large to fit in\n",
+ pieces.init_data_size);
+ goto try_again;
+ }
+
+ /* Allocate ucode buffers for card's bus-master loading ... */
+
+ /* Runtime instructions and 2 copies of data:
+ * 1) unmodified from disk
+ * 2) backup cache for save/restore during power-downs */
+ if (iwl_alloc_fw_desc(drv, &drv->fw.ucode_rt.code,
+ pieces.inst, pieces.inst_size))
+ goto err_pci_alloc;
+ if (iwl_alloc_fw_desc(drv, &drv->fw.ucode_rt.data,
+ pieces.data, pieces.data_size))
+ goto err_pci_alloc;
+
+ /* Initialization instructions and data */
+ if (pieces.init_size && pieces.init_data_size) {
+ if (iwl_alloc_fw_desc(drv,
+ &drv->fw.ucode_init.code,
+ pieces.init, pieces.init_size))
+ goto err_pci_alloc;
+ if (iwl_alloc_fw_desc(drv,
+ &drv->fw.ucode_init.data,
+ pieces.init_data, pieces.init_data_size))
+ goto err_pci_alloc;
+ }
+
+ /* WoWLAN instructions and data */
+ if (pieces.wowlan_inst_size && pieces.wowlan_data_size) {
+ if (iwl_alloc_fw_desc(drv,
+ &drv->fw.ucode_wowlan.code,
+ pieces.wowlan_inst,
+ pieces.wowlan_inst_size))
+ goto err_pci_alloc;
+ if (iwl_alloc_fw_desc(drv,
+ &drv->fw.ucode_wowlan.data,
+ pieces.wowlan_data,
+ pieces.wowlan_data_size))
+ goto err_pci_alloc;
+ }
+
+ /* Now that we can no longer fail, copy information */
+
+ /*
+ * The (size - 16) / 12 formula is based on the information recorded
+ * for each event, which is of mode 1 (including timestamp) for all
+ * new microcodes that include this information.
+ */
+ fw->init_evtlog_ptr = pieces.init_evtlog_ptr;
+ if (pieces.init_evtlog_size)
+ fw->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
+ else
+ fw->init_evtlog_size =
+ cfg->base_params->max_event_log_size;
+ fw->init_errlog_ptr = pieces.init_errlog_ptr;
+ fw->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
+ if (pieces.inst_evtlog_size)
+ fw->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
+ else
+ fw->inst_evtlog_size =
+ cfg->base_params->max_event_log_size;
+ fw->inst_errlog_ptr = pieces.inst_errlog_ptr;
+
+ /*
+ * figure out the offset of chain noise reset and gain commands
+ * base on the size of standard phy calibration commands table size
+ */
+ if (fw->ucode_capa.standard_phy_calibration_size >
+ IWL_MAX_PHY_CALIBRATE_TBL_SIZE)
+ fw->ucode_capa.standard_phy_calibration_size =
+ IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE;
+
+ /* We have our copies now, allow OS release its copies */
+ release_firmware(ucode_raw);
+ complete(&drv->request_firmware_complete);
+
+ drv->op_mode = iwl_dvm_ops.start(drv->shrd->trans, &drv->fw);
+
+ if (!drv->op_mode)
+ goto out_unbind;
+
+ return;
+
+ try_again:
+ /* try next, if any */
+ release_firmware(ucode_raw);
+ if (iwl_request_firmware(drv, false))
+ goto out_unbind;
+ return;
+
+ err_pci_alloc:
+ IWL_ERR(drv, "failed to allocate pci memory\n");
+ iwl_dealloc_ucode(drv);
+ release_firmware(ucode_raw);
+ out_unbind:
+ complete(&drv->request_firmware_complete);
+ device_release_driver(trans(drv)->dev);
+}
+
int iwl_drv_start(struct iwl_shared *shrd,
- struct iwl_trans *trans, struct iwl_cfg *cfg)
+ struct iwl_trans *trans, const struct iwl_cfg *cfg)
{
+ struct iwl_drv *drv;
int ret;
shrd->cfg = cfg;
- shrd->nic = kzalloc(sizeof(*shrd->nic), GFP_KERNEL);
- if (!shrd->nic) {
- dev_printk(KERN_ERR, trans->dev, "Couldn't allocate iwl_nic");
+ drv = kzalloc(sizeof(*drv), GFP_KERNEL);
+ if (!drv) {
+ dev_printk(KERN_ERR, trans->dev, "Couldn't allocate iwl_drv");
return -ENOMEM;
}
- shrd->nic->shrd = shrd;
+ drv->shrd = shrd;
+ shrd->drv = drv;
- init_completion(&shrd->nic->request_firmware_complete);
+ init_completion(&drv->request_firmware_complete);
- ret = iwl_request_firmware(shrd->nic, true);
+ ret = iwl_request_firmware(drv, true);
if (ret) {
dev_printk(KERN_ERR, trans->dev, "Couldn't request the fw");
- kfree(shrd->nic);
+ kfree(drv);
+ shrd->drv = NULL;
}
return ret;
@@ -95,9 +748,16 @@ int iwl_drv_start(struct iwl_shared *shrd,
void iwl_drv_stop(struct iwl_shared *shrd)
{
+ struct iwl_drv *drv = shrd->drv;
+
+ wait_for_completion(&drv->request_firmware_complete);
+
/* op_mode can be NULL if its start failed */
- if (shrd->nic->op_mode)
- iwl_op_mode_stop(shrd->nic->op_mode);
+ if (drv->op_mode)
+ iwl_op_mode_stop(drv->op_mode);
+
+ iwl_dealloc_ucode(drv);
- kfree(shrd->nic);
+ kfree(drv);
+ shrd->drv = NULL;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.h b/drivers/net/wireless/iwlwifi/iwl-drv.h
index 90534a23ddc..3b771c1d909 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.h
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.h
@@ -105,7 +105,7 @@
* function.
*/
int iwl_drv_start(struct iwl_shared *shrd,
- struct iwl_trans *trans, struct iwl_cfg *cfg);
+ struct iwl_trans *trans, const struct iwl_cfg *cfg);
/**
* iwl_drv_stop - stop the drv
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 07e93787bce..23cea42b949 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -75,6 +75,7 @@
#include "iwl-agn.h"
#include "iwl-eeprom.h"
#include "iwl-io.h"
+#include "iwl-prph.h"
/************************** EEPROM BANDS ****************************
*
@@ -252,46 +253,46 @@ err:
}
-int iwl_eeprom_check_sku(struct iwl_priv *priv)
+int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
{
struct iwl_shared *shrd = priv->shrd;
u16 radio_cfg;
- if (!cfg(priv)->sku) {
- /* not using sku overwrite */
- cfg(priv)->sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP);
- if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE &&
- !cfg(priv)->ht_params) {
- IWL_ERR(priv, "Invalid 11n configuration\n");
- return -EINVAL;
- }
+ hw_params(priv).sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP);
+ if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE &&
+ !cfg(priv)->ht_params) {
+ IWL_ERR(priv, "Invalid 11n configuration\n");
+ return -EINVAL;
}
- if (!cfg(priv)->sku) {
+
+ if (!hw_params(priv).sku) {
IWL_ERR(priv, "Invalid device sku\n");
return -EINVAL;
}
- IWL_INFO(priv, "Device SKU: 0x%X\n", cfg(priv)->sku);
-
- if (!cfg(priv)->valid_tx_ant && !cfg(priv)->valid_rx_ant) {
- /* not using .cfg overwrite */
- radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG);
- cfg(priv)->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
- cfg(priv)->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
- if (!cfg(priv)->valid_tx_ant || !cfg(priv)->valid_rx_ant) {
- IWL_ERR(priv, "Invalid chain (0x%X, 0x%X)\n",
- cfg(priv)->valid_tx_ant,
- cfg(priv)->valid_rx_ant);
- return -EINVAL;
- }
- IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
- cfg(priv)->valid_tx_ant, cfg(priv)->valid_rx_ant);
+ IWL_INFO(priv, "Device SKU: 0x%X\n", hw_params(priv).sku);
+
+ radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG);
+
+ hw_params(priv).valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
+ hw_params(priv).valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
+
+ /* check overrides (some devices have wrong EEPROM) */
+ if (cfg(priv)->valid_tx_ant)
+ hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
+ if (cfg(priv)->valid_rx_ant)
+ hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
+
+ if (!hw_params(priv).valid_tx_ant || !hw_params(priv).valid_rx_ant) {
+ IWL_ERR(priv, "Invalid chain (0x%X, 0x%X)\n",
+ hw_params(priv).valid_tx_ant,
+ hw_params(priv).valid_rx_ant);
+ return -EINVAL;
}
- /*
- * for some special cases,
- * EEPROM did not reflect the correct antenna setting
- * so overwrite the valid tx/rx antenna from .cfg
- */
+
+ IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
+ hw_params(priv).valid_tx_ant, hw_params(priv).valid_rx_ant);
+
return 0;
}
@@ -512,7 +513,7 @@ static int iwl_find_otp_image(struct iwl_trans *trans,
* iwl_get_max_txpower_avg - get the highest tx power from all chains.
* find the highest tx power from all chains for the channel
*/
-static s8 iwl_get_max_txpower_avg(struct iwl_cfg *cfg,
+static s8 iwl_get_max_txpower_avg(const struct iwl_cfg *cfg,
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
int element, s8 *max_txpower_in_half_dbm)
{
@@ -588,7 +589,7 @@ iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv,
#define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \
? # x " " : "")
-void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
+static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
{
struct iwl_shared *shrd = priv->shrd;
struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
@@ -1024,8 +1025,8 @@ int iwl_init_channel_map(struct iwl_priv *priv)
* driver need to process addition information
* to determine the max channel tx power limits
*/
- if (cfg(priv)->lib->eeprom_ops.update_enhanced_txpower)
- cfg(priv)->lib->eeprom_ops.update_enhanced_txpower(priv);
+ if (cfg(priv)->lib->eeprom_ops.enhanced_txpower)
+ iwl_eeprom_enhanced_txpower(priv);
return 0;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index cbb86116917..e4a75834099 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -302,14 +302,14 @@ extern const u8 iwl_eeprom_band_1[14];
struct iwl_eeprom_ops {
const u32 regulatory_bands[7];
- void (*update_enhanced_txpower) (struct iwl_priv *priv);
+ bool enhanced_txpower;
};
int iwl_eeprom_init(struct iwl_trans *trans, u32 hw_rev);
void iwl_eeprom_free(struct iwl_shared *shrd);
int iwl_eeprom_check_version(struct iwl_priv *priv);
-int iwl_eeprom_check_sku(struct iwl_priv *priv);
+int iwl_eeprom_init_hw_params(struct iwl_priv *priv);
const u8 *iwl_eeprom_query_addr(const struct iwl_shared *shrd, size_t offset);
u16 iwl_eeprom_query16(const struct iwl_shared *shrd, size_t offset);
int iwl_init_channel_map(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
index 8bebeb003be..7ca6c952635 100644
--- a/drivers/net/wireless/iwlwifi/iwl-ucode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
@@ -60,8 +60,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
-#ifndef __iwl_ucode_h__
-#define __iwl_ucode_h__
+#ifndef __iwl_fw_file_h__
+#define __iwl_fw_file_h__
#include <linux/netdevice.h>
@@ -126,22 +126,6 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_FLAGS = 18,
};
-/**
- * enum iwl_ucode_tlv_flag - ucode API flags
- * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
- * was a separate TLV but moved here to save space.
- * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
- * treats good CRC threshold as a boolean
- * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
- * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
- */
-enum iwl_ucode_tlv_flag {
- IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
- IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1),
- IWL_UCODE_TLV_FLAGS_MFP = BIT(2),
- IWL_UCODE_TLV_FLAGS_P2P = BIT(3),
-};
-
struct iwl_ucode_tlv {
__le16 type; /* see above */
__le16 alternative; /* see comment */
@@ -173,48 +157,4 @@ struct iwl_tlv_ucode_header {
u8 data[0];
};
-struct iwl_ucode_capabilities {
- u32 max_probe_length;
- u32 standard_phy_calibration_size;
- u32 flags;
-};
-
-/* one for each uCode image (inst/data, boot/init/runtime) */
-struct fw_desc {
- dma_addr_t p_addr; /* hardware address */
- void *v_addr; /* software address */
- u32 len; /* size in bytes */
-};
-
-struct fw_img {
- struct fw_desc code; /* firmware code image */
- struct fw_desc data; /* firmware data image */
-};
-
-/**
- * struct iwl_fw - variables associated with the firmware
- *
- * @ucode_ver: ucode version from the ucode file
- * @fw_version: firmware version string
- * @ucode_rt: run time ucode image
- * @ucode_init: init ucode image
- * @ucode_wowlan: wake on wireless ucode image (optional)
- * @ucode_capa: capabilities parsed from the ucode file.
- * @enhance_sensitivity_table: device can do enhanced sensitivity.
- */
-struct iwl_fw {
-
- u32 ucode_ver;
-
- char fw_version[ETHTOOL_BUSINFO_LEN];
-
- /* ucode images */
- struct fw_img ucode_rt;
- struct fw_img ucode_init;
- struct fw_img ucode_wowlan;
-
- struct iwl_ucode_capabilities ucode_capa;
- bool enhance_sensitivity_table;
-};
-
-#endif /* __iwl_ucode_h__ */
+#endif /* __iwl_fw_file_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-wifi.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index d5cba07a24c..453812a2117 100644
--- a/drivers/net/wireless/iwlwifi/iwl-wifi.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -60,52 +60,87 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
-#ifndef __iwl_wifi_h__
-#define __iwl_wifi_h__
+#ifndef __iwl_fw_h__
+#define __iwl_fw_h__
+#include <linux/types.h>
-#include "iwl-shared.h"
-#include "iwl-ucode.h"
+/**
+ * enum iwl_ucode_tlv_flag - ucode API flags
+ * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
+ * was a separate TLV but moved here to save space.
+ * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
+ * treats good CRC threshold as a boolean
+ * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
+ * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
+ */
+enum iwl_ucode_tlv_flag {
+ IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
+ IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1),
+ IWL_UCODE_TLV_FLAGS_MFP = BIT(2),
+ IWL_UCODE_TLV_FLAGS_P2P = BIT(3),
+};
+
+/* The default calibrate table size if not specified by firmware file */
+#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18
+#define IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE 19
+#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE 253
-#define UCODE_EXPERIMENTAL_INDEX 100
+struct iwl_ucode_capabilities {
+ u32 max_probe_length;
+ u32 standard_phy_calibration_size;
+ u32 flags;
+};
+
+/* one for each uCode image (inst/data, boot/init/runtime) */
+struct fw_desc {
+ dma_addr_t p_addr; /* hardware address */
+ void *v_addr; /* software address */
+ u32 len; /* size in bytes */
+};
+
+struct fw_img {
+ struct fw_desc code; /* firmware code image */
+ struct fw_desc data; /* firmware data image */
+};
+
+/* uCode version contains 4 values: Major/Minor/API/Serial */
+#define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24)
+#define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16)
+#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8)
+#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF)
/**
- * struct iwl_nic - nic common data
- * @fw: the iwl_fw structure
- * @shrd: pointer to common shared structure
- * @op_mode: the running op_mode
- * @fw_index: firmware revision to try loading
- * @firmware_name: composite filename of ucode file to load
+ * struct iwl_fw - variables associated with the firmware
+ *
+ * @ucode_ver: ucode version from the ucode file
+ * @fw_version: firmware version string
+ * @ucode_rt: run time ucode image
+ * @ucode_init: init ucode image
+ * @ucode_wowlan: wake on wireless ucode image (optional)
+ * @ucode_capa: capabilities parsed from the ucode file.
+ * @enhance_sensitivity_table: device can do enhanced sensitivity.
* @init_evtlog_ptr: event log offset for init ucode.
* @init_evtlog_size: event log size for init ucode.
* @init_errlog_ptr: error log offfset for init ucode.
* @inst_evtlog_ptr: event log offset for runtime ucode.
* @inst_evtlog_size: event log size for runtime ucode.
* @inst_errlog_ptr: error log offfset for runtime ucode.
- * @request_firmware_complete: the firmware has been obtained from user space
*/
-struct iwl_nic {
- struct iwl_fw fw;
+struct iwl_fw {
+ u32 ucode_ver;
+
+ char fw_version[ETHTOOL_BUSINFO_LEN];
- struct iwl_shared *shrd;
- struct iwl_op_mode *op_mode;
+ /* ucode images */
+ struct fw_img ucode_rt;
+ struct fw_img ucode_init;
+ struct fw_img ucode_wowlan;
- int fw_index; /* firmware we're trying to load */
- char firmware_name[25]; /* name of firmware file to load */
+ struct iwl_ucode_capabilities ucode_capa;
+ bool enhance_sensitivity_table;
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
-
- struct completion request_firmware_complete;
};
-
-int __must_check iwl_request_firmware(struct iwl_nic *nic, bool first);
-void iwl_dealloc_ucode(struct iwl_nic *nic);
-
-int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type);
-void iwl_send_prio_tbl(struct iwl_trans *trans);
-int iwl_init_alive_start(struct iwl_trans *trans);
-int iwl_run_init_ucode(struct iwl_trans *trans);
-int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
- enum iwl_ucode_type ucode_type);
-#endif /* __iwl_wifi_h__ */
+#endif /* __iwl_fw_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c
index e2e3b5c9cf7..081dd34d238 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/iwlwifi/iwl-io.c
@@ -118,16 +118,17 @@ int iwl_grab_nic_access_silent(struct iwl_trans *trans)
return 0;
}
-int iwl_grab_nic_access(struct iwl_trans *trans)
+bool iwl_grab_nic_access(struct iwl_trans *trans)
{
int ret = iwl_grab_nic_access_silent(trans);
- if (ret) {
+ if (unlikely(ret)) {
u32 val = iwl_read32(trans, CSR_GP_CNTRL);
- IWL_ERR(trans,
- "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val);
+ WARN_ONCE(1, "Timeout waiting for hardware access "
+ "(CSR_GP_CNTRL 0x%08x)\n", val);
+ return false;
}
- return ret;
+ return true;
}
void iwl_release_nic_access(struct iwl_trans *trans)
@@ -135,6 +136,13 @@ void iwl_release_nic_access(struct iwl_trans *trans)
lockdep_assert_held(&trans->reg_lock);
__iwl_clear_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ /*
+ * Above we read the CSR_GP_CNTRL register, which will flush
+ * any previous writes, but we need the write that clears the
+ * MAC_ACCESS_REQ bit to be performed before any other writes
+ * scheduled on different CPUs (after we drop reg_lock).
+ */
+ mmiowb();
}
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
@@ -156,7 +164,7 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags);
- if (!iwl_grab_nic_access(trans)) {
+ if (likely(iwl_grab_nic_access(trans))) {
iwl_write32(trans, reg, value);
iwl_release_nic_access(trans);
}
@@ -181,7 +189,6 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 reg)
{
iwl_write32(trans, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
- rmb();
return iwl_read32(trans, HBUS_TARG_PRPH_RDAT);
}
@@ -189,7 +196,6 @@ static inline void __iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val)
{
iwl_write32(trans, HBUS_TARG_PRPH_WADDR,
((addr & 0x0000FFFF) | (3 << 24)));
- wmb();
iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val);
}
@@ -211,7 +217,7 @@ void iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val)
unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags);
- if (!iwl_grab_nic_access(trans)) {
+ if (likely(iwl_grab_nic_access(trans))) {
__iwl_write_prph(trans, addr, val);
iwl_release_nic_access(trans);
}
@@ -223,9 +229,11 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask)
unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags);
- iwl_grab_nic_access(trans);
- __iwl_write_prph(trans, reg, __iwl_read_prph(trans, reg) | mask);
- iwl_release_nic_access(trans);
+ if (likely(iwl_grab_nic_access(trans))) {
+ __iwl_write_prph(trans, reg,
+ __iwl_read_prph(trans, reg) | mask);
+ iwl_release_nic_access(trans);
+ }
spin_unlock_irqrestore(&trans->reg_lock, flags);
}
@@ -235,10 +243,11 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 reg,
unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags);
- iwl_grab_nic_access(trans);
- __iwl_write_prph(trans, reg,
- (__iwl_read_prph(trans, reg) & mask) | bits);
- iwl_release_nic_access(trans);
+ if (likely(iwl_grab_nic_access(trans))) {
+ __iwl_write_prph(trans, reg,
+ (__iwl_read_prph(trans, reg) & mask) | bits);
+ iwl_release_nic_access(trans);
+ }
spin_unlock_irqrestore(&trans->reg_lock, flags);
}
@@ -248,10 +257,11 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask)
u32 val;
spin_lock_irqsave(&trans->reg_lock, flags);
- iwl_grab_nic_access(trans);
- val = __iwl_read_prph(trans, reg);
- __iwl_write_prph(trans, reg, (val & ~mask));
- iwl_release_nic_access(trans);
+ if (likely(iwl_grab_nic_access(trans))) {
+ val = __iwl_read_prph(trans, reg);
+ __iwl_write_prph(trans, reg, (val & ~mask));
+ iwl_release_nic_access(trans);
+ }
spin_unlock_irqrestore(&trans->reg_lock, flags);
}
@@ -263,15 +273,12 @@ void _iwl_read_targ_mem_words(struct iwl_trans *trans, u32 addr,
u32 *vals = buf;
spin_lock_irqsave(&trans->reg_lock, flags);
- iwl_grab_nic_access(trans);
-
- iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr);
- rmb();
-
- for (offs = 0; offs < words; offs++)
- vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
-
- iwl_release_nic_access(trans);
+ if (likely(iwl_grab_nic_access(trans))) {
+ iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr);
+ for (offs = 0; offs < words; offs++)
+ vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
+ iwl_release_nic_access(trans);
+ }
spin_unlock_irqrestore(&trans->reg_lock, flags);
}
@@ -292,10 +299,8 @@ int _iwl_write_targ_mem_words(struct iwl_trans *trans, u32 addr,
u32 *vals = buf;
spin_lock_irqsave(&trans->reg_lock, flags);
- if (!iwl_grab_nic_access(trans)) {
+ if (likely(iwl_grab_nic_access(trans))) {
iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr);
- wmb();
-
for (offs = 0; offs < words; offs++)
iwl_write32(trans, HBUS_TARG_MEM_WDAT, vals[offs]);
iwl_release_nic_access(trans);
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index 782486fc2f8..09b856768f6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -35,20 +35,20 @@
static inline void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val)
{
- trace_iwlwifi_dev_iowrite8(priv(trans), ofs, val);
+ trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val);
iwl_trans_write8(trans, ofs, val);
}
static inline void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val)
{
- trace_iwlwifi_dev_iowrite32(priv(trans), ofs, val);
+ trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val);
iwl_trans_write32(trans, ofs, val);
}
static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs)
{
u32 val = iwl_trans_read32(trans, ofs);
- trace_iwlwifi_dev_ioread32(priv(trans), ofs, val);
+ trace_iwlwifi_dev_ioread32(trans->dev, ofs, val);
return val;
}
@@ -61,7 +61,7 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
int timeout);
int iwl_grab_nic_access_silent(struct iwl_trans *trans);
-int iwl_grab_nic_access(struct iwl_trans *trans);
+bool iwl_grab_nic_access(struct iwl_trans *trans);
void iwl_release_nic_access(struct iwl_trans *trans);
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg);
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index 5c7741f07aa..1993a2b7ae6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -112,7 +112,7 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
iwl_write32(trans(priv), CSR_LED_REG,
reg & CSR_LED_BSM_CTRL_MSK);
- return iwl_trans_send_cmd(trans(priv), &cmd);
+ return iwl_dvm_send_cmd(priv, &cmd);
}
/* Set led pattern command */
@@ -126,7 +126,7 @@ static int iwl_led_cmd(struct iwl_priv *priv,
};
int ret;
- if (!test_bit(STATUS_READY, &priv->shrd->status))
+ if (!test_bit(STATUS_READY, &priv->status))
return -EBUSY;
if (priv->blink_on == on && priv->blink_off == off)
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
index 03f770543d8..9212ee3bef9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c
+++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
@@ -42,9 +42,7 @@
#include <asm/div64.h>
-#include "iwl-ucode.h"
#include "iwl-eeprom.h"
-#include "iwl-wifi.h"
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-io.h"
@@ -136,7 +134,7 @@ iwlagn_iface_combinations_p2p[] = {
* other mac80211 functions grouped here.
*/
int iwlagn_mac_setup_register(struct iwl_priv *priv,
- struct iwl_ucode_capabilities *capa)
+ const struct iwl_ucode_capabilities *capa)
{
int ret;
struct ieee80211_hw *hw = priv->hw;
@@ -161,11 +159,14 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
hw->flags |= IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
- if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
+ if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE)
hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
IEEE80211_HW_SUPPORTS_STATIC_SMPS;
+#ifndef CONFIG_IWLWIFI_EXPERIMENTAL_MFP
+ /* enable 11w if the uCode advertise */
if (capa->flags & IWL_UCODE_TLV_FLAGS_MFP)
+#endif /* !CONFIG_IWLWIFI_EXPERIMENTAL_MFP */
hw->flags |= IEEE80211_HW_MFP_CAPABLE;
hw->sta_data_size = sizeof(struct iwl_station_priv);
@@ -195,7 +196,8 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
WIPHY_FLAG_DISABLE_BEACON_HINTS |
WIPHY_FLAG_IBSS_RSN;
- if (nic(priv)->fw.ucode_wowlan.code.len &&
+ if (priv->fw->ucode_wowlan.code.len &&
+ trans(priv)->ops->wowlan_suspend &&
device_can_wakeup(trans(priv)->dev)) {
hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
WIPHY_WOWLAN_DISCONNECT |
@@ -262,9 +264,9 @@ static int __iwl_up(struct iwl_priv *priv)
struct iwl_rxon_context *ctx;
int ret;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) {
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
return -EIO;
}
@@ -277,13 +279,13 @@ static int __iwl_up(struct iwl_priv *priv)
}
}
- ret = iwl_run_init_ucode(trans(priv));
+ ret = iwl_run_init_ucode(priv);
if (ret) {
IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret);
goto error;
}
- ret = iwl_load_ucode_wait_alive(trans(priv), IWL_UCODE_REGULAR);
+ ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR);
if (ret) {
IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret);
goto error;
@@ -295,9 +297,9 @@ static int __iwl_up(struct iwl_priv *priv)
return 0;
error:
- set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
+ set_bit(STATUS_EXIT_PENDING, &priv->status);
iwl_down(priv);
- clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
+ clear_bit(STATUS_EXIT_PENDING, &priv->status);
IWL_ERR(priv, "Unable to initialize device.\n");
return ret;
@@ -311,16 +313,16 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw)
IWL_DEBUG_MAC80211(priv, "enter\n");
/* we should be verifying the device is ready to be opened */
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
ret = __iwl_up(priv);
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
if (ret)
return ret;
IWL_DEBUG_INFO(priv, "Start UP work done.\n");
/* Now we should be done, and the READY bit should be set. */
- if (WARN_ON(!test_bit(STATUS_READY, &priv->shrd->status)))
+ if (WARN_ON(!test_bit(STATUS_READY, &priv->status)))
ret = -EIO;
iwlagn_led_enable(priv);
@@ -341,9 +343,9 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
priv->is_open = 0;
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
iwl_down(priv);
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
iwl_cancel_deferred_work(priv);
@@ -368,7 +370,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
return;
IWL_DEBUG_MAC80211(priv, "enter\n");
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif)
goto out;
@@ -380,7 +382,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
priv->have_rekey_data = true;
out:
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
}
@@ -397,7 +399,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
return -EINVAL;
IWL_DEBUG_MAC80211(priv, "enter\n");
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
/* Don't attempt WoWLAN when not associated, tear down instead. */
if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION ||
@@ -406,24 +408,22 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
goto out;
}
- ret = iwlagn_suspend(priv, hw, wowlan);
+ ret = iwlagn_suspend(priv, wowlan);
if (ret)
goto error;
device_set_wakeup_enable(trans(priv)->dev, true);
- /* Now let the ucode operate on its own */
- iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_SET,
- CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
+ iwl_trans_wowlan_suspend(trans(priv));
goto out;
error:
- priv->shrd->wowlan = false;
+ priv->wowlan = false;
iwlagn_prepare_restart(priv);
ieee80211_restart_hw(priv->hw);
out:
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return ret;
@@ -439,7 +439,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
int ret = -EIO;
IWL_DEBUG_MAC80211(priv, "enter\n");
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
@@ -448,7 +448,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
if (iwlagn_hw_valid_rtc_data_addr(base)) {
spin_lock_irqsave(&trans(priv)->reg_lock, flags);
ret = iwl_grab_nic_access_silent(trans(priv));
- if (ret == 0) {
+ if (likely(ret == 0)) {
iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, base);
status = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
iwl_release_nic_access(trans(priv));
@@ -457,17 +457,16 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
#ifdef CONFIG_IWLWIFI_DEBUGFS
if (ret == 0) {
- struct iwl_nic *nic = nic(priv);
if (!priv->wowlan_sram)
priv->wowlan_sram =
- kzalloc(nic->fw.ucode_wowlan.data.len,
+ kzalloc(priv->fw->ucode_wowlan.data.len,
GFP_KERNEL);
if (priv->wowlan_sram)
_iwl_read_targ_mem_words(
trans(priv), 0x800000,
priv->wowlan_sram,
- nic->fw.ucode_wowlan.data.len / 4);
+ priv->fw->ucode_wowlan.data.len / 4);
}
#endif
}
@@ -475,7 +474,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
/* we'll clear ctx->vif during iwlagn_prepare_restart() */
vif = ctx->vif;
- priv->shrd->wowlan = false;
+ priv->wowlan = false;
device_set_wakeup_enable(trans(priv)->dev, false);
@@ -485,7 +484,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
iwl_connection_init_rx_config(priv, ctx);
iwlagn_set_rxon_chain(priv, ctx);
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
ieee80211_resume_disconnect(vif);
@@ -563,7 +562,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (cmd == DISABLE_KEY && key->hw_key_idx == WEP_INVALID_OFFSET)
return 0;
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
iwl_scan_cancel_timeout(priv, 100);
BUILD_BUG_ON(WEP_INVALID_OFFSET == IWLAGN_HW_KEY_DEFAULT);
@@ -614,7 +613,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
ret = -EINVAL;
}
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return ret;
@@ -633,11 +632,11 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
sta->addr, tid);
- if (!(cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE))
+ if (!(hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE))
return -EACCES;
IWL_DEBUG_MAC80211(priv, "enter\n");
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
switch (action) {
case IEEE80211_AMPDU_RX_START:
@@ -649,8 +648,6 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_RX_STOP:
IWL_DEBUG_HT(priv, "stop Rx\n");
ret = iwl_sta_rx_agg_stop(priv, sta, tid);
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
- ret = 0;
break;
case IEEE80211_AMPDU_TX_START:
if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
@@ -666,10 +663,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
priv->agg_tids_count);
}
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
- ret = 0;
- if (!priv->agg_tids_count && cfg(priv)->ht_params &&
- cfg(priv)->ht_params->use_rts_for_aggregation) {
+ if (!priv->agg_tids_count &&
+ hw_params(priv).use_rts_for_aggregation) {
/*
* switch off RTS/CTS if it was previously enabled
*/
@@ -683,7 +678,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
ret = iwlagn_tx_agg_oper(priv, vif, sta, tid, buf_size);
break;
}
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return ret;
}
@@ -696,12 +691,9 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
bool is_ap = vif->type == NL80211_IFTYPE_STATION;
- int ret = 0;
+ int ret;
u8 sta_id;
- IWL_DEBUG_MAC80211(priv, "received request to add station %pM\n",
- sta->addr);
- mutex_lock(&priv->shrd->mutex);
IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
sta->addr);
sta_priv->sta_id = IWL_INVALID_STATION;
@@ -716,17 +708,119 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
IWL_ERR(priv, "Unable to add station %pM (%d)\n",
sta->addr, ret);
/* Should we return success if return code is EEXIST ? */
- goto out;
+ return ret;
}
sta_priv->sta_id = sta_id;
- /* Initialize rate scaling */
- IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
- sta->addr);
- iwl_rs_rate_init(priv, sta, sta_id);
- out:
- mutex_unlock(&priv->shrd->mutex);
+ return 0;
+}
+
+static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
+ struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+ int ret;
+
+ IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", sta->addr);
+
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ /*
+ * Station will be removed from device when the RXON
+ * is set to unassociated -- just deactivate it here
+ * to avoid re-programming it.
+ */
+ ret = 0;
+ iwl_deactivate_station(priv, sta_priv->sta_id, sta->addr);
+ } else {
+ ret = iwl_remove_station(priv, sta_priv->sta_id, sta->addr);
+ if (ret)
+ IWL_DEBUG_QUIET_RFKILL(priv,
+ "Error removing station %pM\n", sta->addr);
+ }
+ return ret;
+}
+
+static int iwlagn_mac_sta_state(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ enum ieee80211_sta_state old_state,
+ enum ieee80211_sta_state new_state)
+{
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
+ struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+ enum {
+ NONE, ADD, REMOVE, HT_RATE_INIT, ADD_RATE_INIT,
+ } op = NONE;
+ int ret;
+
+ IWL_DEBUG_MAC80211(priv, "station %pM state change %d->%d\n",
+ sta->addr, old_state, new_state);
+
+ mutex_lock(&priv->mutex);
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ if (old_state == IEEE80211_STA_NOTEXIST &&
+ new_state == IEEE80211_STA_NONE)
+ op = ADD;
+ else if (old_state == IEEE80211_STA_NONE &&
+ new_state == IEEE80211_STA_NOTEXIST)
+ op = REMOVE;
+ else if (old_state == IEEE80211_STA_AUTH &&
+ new_state == IEEE80211_STA_ASSOC)
+ op = HT_RATE_INIT;
+ } else {
+ if (old_state == IEEE80211_STA_AUTH &&
+ new_state == IEEE80211_STA_ASSOC)
+ op = ADD_RATE_INIT;
+ else if (old_state == IEEE80211_STA_ASSOC &&
+ new_state == IEEE80211_STA_AUTH)
+ op = REMOVE;
+ }
+
+ switch (op) {
+ case ADD:
+ ret = iwlagn_mac_sta_add(hw, vif, sta);
+ break;
+ case REMOVE:
+ ret = iwlagn_mac_sta_remove(hw, vif, sta);
+ break;
+ case ADD_RATE_INIT:
+ ret = iwlagn_mac_sta_add(hw, vif, sta);
+ if (ret)
+ break;
+ /* Initialize rate scaling */
+ IWL_DEBUG_INFO(priv,
+ "Initializing rate scaling for station %pM\n",
+ sta->addr);
+ iwl_rs_rate_init(priv, sta, iwl_sta_id(sta));
+ ret = 0;
+ break;
+ case HT_RATE_INIT:
+ /* Initialize rate scaling */
+ ret = iwl_sta_update_ht(priv, vif_priv->ctx, sta);
+ if (ret)
+ break;
+ IWL_DEBUG_INFO(priv,
+ "Initializing rate scaling for station %pM\n",
+ sta->addr);
+ iwl_rs_rate_init(priv, sta, iwl_sta_id(sta));
+ ret = 0;
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+
+ /*
+ * mac80211 might WARN if we fail, but due the way we
+ * (badly) handle hard rfkill, we might fail here
+ */
+ if (iwl_is_rfkill(priv))
+ ret = 0;
+
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return ret;
@@ -753,14 +847,14 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "enter\n");
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
- if (iwl_is_rfkill(priv->shrd))
+ if (iwl_is_rfkill(priv))
goto out;
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) ||
- test_bit(STATUS_SCANNING, &priv->shrd->status) ||
- test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+ test_bit(STATUS_SCANNING, &priv->status) ||
+ test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
goto out;
if (!iwl_is_associated_ctx(ctx))
@@ -779,8 +873,6 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
goto out;
}
- spin_lock_irq(&priv->shrd->lock);
-
priv->current_ht_config.smps = conf->smps_mode;
/* Configure HT40 channels */
@@ -797,23 +889,21 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
iwl_set_rxon_ht(priv, ht_conf);
iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
- spin_unlock_irq(&priv->shrd->lock);
-
iwl_set_rate(priv);
/*
* at this point, staging_rxon has the
* configuration for channel switch
*/
- set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status);
+ set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
priv->switch_channel = cpu_to_le16(ch);
if (cfg(priv)->lib->set_channel_switch(priv, ch_switch)) {
- clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status);
+ clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
priv->switch_channel = 0;
ieee80211_chswitch_done(ctx->vif, false);
}
out:
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
}
@@ -843,7 +933,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
#undef CHK
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
for_each_context(priv, ctx) {
ctx->staging.filter_flags &= ~filter_nand;
@@ -855,7 +945,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
*/
}
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
/*
* Receiving all multicast frames is always enabled by the
@@ -871,14 +961,14 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "enter\n");
- if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) {
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n");
goto done;
}
- if (iwl_is_rfkill(priv->shrd)) {
+ if (iwl_is_rfkill(priv)) {
IWL_DEBUG_TX(priv, "Aborting flush due to RF Kill\n");
goto done;
}
@@ -897,7 +987,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n");
iwl_trans_wait_tx_queue_empty(trans(priv));
done:
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
}
@@ -917,9 +1007,9 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
return -EOPNOTSUPP;
IWL_DEBUG_MAC80211(priv, "enter\n");
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
- if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
+ if (test_bit(STATUS_SCAN_HW, &priv->status)) {
err = -EBUSY;
goto out;
}
@@ -988,7 +1078,7 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
iwlagn_disable_roc(priv);
out:
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return err;
@@ -1002,102 +1092,22 @@ static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
return -EOPNOTSUPP;
IWL_DEBUG_MAC80211(priv, "enter\n");
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
iwl_scan_cancel_timeout(priv, priv->hw_roc_duration);
iwlagn_disable_roc(priv);
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return 0;
}
-static int iwlagn_mac_tx_sync(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *bssid,
- enum ieee80211_tx_sync_type type)
-{
- struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
- struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
- struct iwl_rxon_context *ctx = vif_priv->ctx;
- int ret;
- u8 sta_id;
-
- if (ctx->ctxid != IWL_RXON_CTX_PAN)
- return 0;
-
- IWL_DEBUG_MAC80211(priv, "enter\n");
- mutex_lock(&priv->shrd->mutex);
-
- if (iwl_is_associated_ctx(ctx)) {
- ret = 0;
- goto out;
- }
-
- if (ctx->preauth_bssid || test_bit(STATUS_SCAN_HW,
- &priv->shrd->status)) {
- ret = -EBUSY;
- goto out;
- }
-
- ret = iwl_add_station_common(priv, ctx, bssid, true, NULL, &sta_id);
- if (ret)
- goto out;
-
- if (WARN_ON(sta_id != ctx->ap_sta_id)) {
- ret = -EIO;
- goto out_remove_sta;
- }
-
- memcpy(ctx->bssid, bssid, ETH_ALEN);
- ctx->preauth_bssid = true;
-
- ret = iwlagn_commit_rxon(priv, ctx);
-
- if (ret == 0)
- goto out;
-
- out_remove_sta:
- iwl_remove_station(priv, sta_id, bssid);
- out:
- mutex_unlock(&priv->shrd->mutex);
- IWL_DEBUG_MAC80211(priv, "leave\n");
-
- return ret;
-}
-
-static void iwlagn_mac_finish_tx_sync(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *bssid,
- enum ieee80211_tx_sync_type type)
-{
- struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
- struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
- struct iwl_rxon_context *ctx = vif_priv->ctx;
-
- if (ctx->ctxid != IWL_RXON_CTX_PAN)
- return;
-
- IWL_DEBUG_MAC80211(priv, "enter\n");
- mutex_lock(&priv->shrd->mutex);
-
- if (iwl_is_associated_ctx(ctx))
- goto out;
-
- iwl_remove_station(priv, ctx->ap_sta_id, bssid);
- ctx->preauth_bssid = false;
- /* no need to commit */
- out:
- mutex_unlock(&priv->shrd->mutex);
- IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-
static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
enum ieee80211_rssi_event rssi_event)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
IWL_DEBUG_MAC80211(priv, "enter\n");
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
if (cfg(priv)->bt_params &&
cfg(priv)->bt_params->advanced_bt_coexist) {
@@ -1112,7 +1122,7 @@ static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
"ignoring RSSI callback\n");
}
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
}
@@ -1133,7 +1143,6 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
struct iwl_rxon_context *ctx = vif_priv->ctx;
- unsigned long flags;
int q;
if (WARN_ON(!ctx))
@@ -1141,7 +1150,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "enter\n");
- if (!iwl_is_ready_rf(priv->shrd)) {
+ if (!iwl_is_ready_rf(priv)) {
IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
return -EIO;
}
@@ -1153,7 +1162,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
q = AC_NUM - 1 - queue;
- spin_lock_irqsave(&priv->shrd->lock, flags);
+ mutex_lock(&priv->mutex);
ctx->qos_data.def_qos_parm.ac[q].cw_min =
cpu_to_le16(params->cw_min);
@@ -1165,7 +1174,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0;
- spin_unlock_irqrestore(&priv->shrd->lock, flags);
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return 0;
@@ -1193,7 +1202,7 @@ static int iwl_setup_interface(struct iwl_priv *priv,
struct ieee80211_vif *vif = ctx->vif;
int err;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
/*
* This variable will be correct only when there's just
@@ -1238,11 +1247,11 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
cancel_delayed_work_sync(&priv->hw_roc_disable_work);
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
iwlagn_disable_roc(priv);
- if (!iwl_is_ready_rf(priv->shrd)) {
+ if (!iwl_is_ready_rf(priv)) {
IWL_WARN(priv, "Try to add interface when device not ready\n");
err = -EINVAL;
goto out;
@@ -1285,7 +1294,7 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
ctx->vif = NULL;
priv->iw_mode = NL80211_IFTYPE_STATION;
out:
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return err;
@@ -1297,7 +1306,7 @@ static void iwl_teardown_interface(struct iwl_priv *priv,
{
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
if (priv->scan_vif == vif) {
iwl_scan_cancel_timeout(priv, 200);
@@ -1329,7 +1338,7 @@ static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "enter\n");
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
if (WARN_ON(ctx->vif != vif)) {
struct iwl_rxon_context *tmp;
@@ -1342,7 +1351,7 @@ static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
iwl_teardown_interface(priv, vif, false);
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -1364,9 +1373,9 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
newtype = ieee80211_iftype_p2p(newtype, newp2p);
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
- if (!ctx->vif || !iwl_is_ready_rf(priv->shrd)) {
+ if (!ctx->vif || !iwl_is_ready_rf(priv)) {
/*
* Huh? But wait ... this can maybe happen when
* we're in the middle of a firmware restart!
@@ -1428,7 +1437,7 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
err = 0;
out:
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return err;
@@ -1446,7 +1455,7 @@ static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
if (req->n_channels == 0)
return -EINVAL;
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
/*
* If an internal scan is in progress, just set
@@ -1475,47 +1484,20 @@ static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "leave\n");
- mutex_unlock(&priv->shrd->mutex);
-
- return ret;
-}
-
-static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
-{
- struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
- struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
- int ret;
-
- IWL_DEBUG_MAC80211(priv, "enter: received request to remove "
- "station %pM\n", sta->addr);
- mutex_lock(&priv->shrd->mutex);
- IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
- sta->addr);
- ret = iwl_remove_station(priv, sta_priv->sta_id, sta->addr);
- if (ret)
- IWL_DEBUG_QUIET_RFKILL(priv, "Error removing station %pM\n",
- sta->addr);
- mutex_unlock(&priv->shrd->mutex);
- IWL_DEBUG_MAC80211(priv, "leave\n");
+ mutex_unlock(&priv->mutex);
return ret;
}
static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
{
- unsigned long flags;
-
- spin_lock_irqsave(&priv->shrd->sta_lock, flags);
- priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
- priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
- priv->stations[sta_id].sta.sta.modify_mask = 0;
- priv->stations[sta_id].sta.sleep_tx_count = 0;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
- spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ struct iwl_addsta_cmd cmd = {
+ .mode = STA_CONTROL_MODIFY_MSK,
+ .station_flags_msk = STA_FLG_PWR_SAVE_MSK,
+ .sta.sta_id = sta_id,
+ };
+ iwl_send_add_sta(priv, &cmd, CMD_ASYNC);
}
static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
@@ -1572,8 +1554,7 @@ struct ieee80211_ops iwlagn_hw_ops = {
.ampdu_action = iwlagn_mac_ampdu_action,
.hw_scan = iwlagn_mac_hw_scan,
.sta_notify = iwlagn_mac_sta_notify,
- .sta_add = iwlagn_mac_sta_add,
- .sta_remove = iwlagn_mac_sta_remove,
+ .sta_state = iwlagn_mac_sta_state,
.channel_switch = iwlagn_mac_channel_switch,
.flush = iwlagn_mac_flush,
.tx_last_beacon = iwlagn_mac_tx_last_beacon,
@@ -1582,8 +1563,6 @@ struct ieee80211_ops iwlagn_hw_ops = {
.rssi_callback = iwlagn_mac_rssi_callback,
CFG80211_TESTMODE_CMD(iwlagn_mac_testmode_cmd)
CFG80211_TESTMODE_DUMP(iwlagn_mac_testmode_dump)
- .tx_sync = iwlagn_mac_tx_sync,
- .finish_tx_sync = iwlagn_mac_finish_tx_sync,
.set_tim = iwlagn_mac_set_tim,
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c
new file mode 100644
index 00000000000..88dc4a0f96b
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c
@@ -0,0 +1,157 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#include <linux/sched.h>
+
+#include "iwl-notif-wait.h"
+
+
+void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_wait)
+{
+ spin_lock_init(&notif_wait->notif_wait_lock);
+ INIT_LIST_HEAD(&notif_wait->notif_waits);
+ init_waitqueue_head(&notif_wait->notif_waitq);
+}
+
+void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait,
+ struct iwl_rx_packet *pkt)
+{
+ if (!list_empty(&notif_wait->notif_waits)) {
+ struct iwl_notification_wait *w;
+
+ spin_lock(&notif_wait->notif_wait_lock);
+ list_for_each_entry(w, &notif_wait->notif_waits, list) {
+ if (w->cmd != pkt->hdr.cmd)
+ continue;
+ w->triggered = true;
+ if (w->fn)
+ w->fn(notif_wait, pkt, w->fn_data);
+ }
+ spin_unlock(&notif_wait->notif_wait_lock);
+
+ wake_up_all(&notif_wait->notif_waitq);
+ }
+}
+
+void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait)
+{
+ unsigned long flags;
+ struct iwl_notification_wait *wait_entry;
+
+ spin_lock_irqsave(&notif_wait->notif_wait_lock, flags);
+ list_for_each_entry(wait_entry, &notif_wait->notif_waits, list)
+ wait_entry->aborted = true;
+ spin_unlock_irqrestore(&notif_wait->notif_wait_lock, flags);
+
+ wake_up_all(&notif_wait->notif_waitq);
+}
+
+
+void
+iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait,
+ struct iwl_notification_wait *wait_entry,
+ u8 cmd,
+ void (*fn)(struct iwl_notif_wait_data *notif_wait,
+ struct iwl_rx_packet *pkt, void *data),
+ void *fn_data)
+{
+ wait_entry->fn = fn;
+ wait_entry->fn_data = fn_data;
+ wait_entry->cmd = cmd;
+ wait_entry->triggered = false;
+ wait_entry->aborted = false;
+
+ spin_lock_bh(&notif_wait->notif_wait_lock);
+ list_add(&wait_entry->list, &notif_wait->notif_waits);
+ spin_unlock_bh(&notif_wait->notif_wait_lock);
+}
+
+int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait,
+ struct iwl_notification_wait *wait_entry,
+ unsigned long timeout)
+{
+ int ret;
+
+ ret = wait_event_timeout(notif_wait->notif_waitq,
+ wait_entry->triggered || wait_entry->aborted,
+ timeout);
+
+ spin_lock_bh(&notif_wait->notif_wait_lock);
+ list_del(&wait_entry->list);
+ spin_unlock_bh(&notif_wait->notif_wait_lock);
+
+ if (wait_entry->aborted)
+ return -EIO;
+
+ /* return value is always >= 0 */
+ if (ret <= 0)
+ return -ETIMEDOUT;
+ return 0;
+}
+
+void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait,
+ struct iwl_notification_wait *wait_entry)
+{
+ spin_lock_bh(&notif_wait->notif_wait_lock);
+ list_del(&wait_entry->list);
+ spin_unlock_bh(&notif_wait->notif_wait_lock);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h
index 506c062343b..5e8af957aa7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h
@@ -41,7 +41,6 @@
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
@@ -60,18 +59,71 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
+#ifndef __iwl_notif_wait_h__
+#define __iwl_notif_wait_h__
+
+#include <linux/wait.h>
#include "iwl-trans.h"
-int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id,
- u32 flags, u16 len, const void *data)
-{
- struct iwl_host_cmd cmd = {
- .id = id,
- .len = { len, },
- .data = { data, },
- .flags = flags,
- };
+struct iwl_notif_wait_data {
+ struct list_head notif_waits;
+ spinlock_t notif_wait_lock;
+ wait_queue_head_t notif_waitq;
+};
+
+/**
+ * struct iwl_notification_wait - notification wait entry
+ * @list: list head for global list
+ * @fn: function called with the notification
+ * @cmd: command ID
+ *
+ * This structure is not used directly, to wait for a
+ * notification declare it on the stack, and call
+ * iwlagn_init_notification_wait() with appropriate
+ * parameters. Then do whatever will cause the ucode
+ * to notify the driver, and to wait for that then
+ * call iwlagn_wait_notification().
+ *
+ * Each notification is one-shot. If at some point we
+ * need to support multi-shot notifications (which
+ * can't be allocated on the stack) we need to modify
+ * the code for them.
+ */
+struct iwl_notification_wait {
+ struct list_head list;
+
+ void (*fn)(struct iwl_notif_wait_data *notif_data,
+ struct iwl_rx_packet *pkt, void *data);
+ void *fn_data;
+
+ u8 cmd;
+ bool triggered, aborted;
+};
+
+
+/* caller functions */
+void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_data);
+void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_data,
+ struct iwl_rx_packet *pkt);
+void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_data);
+
+/* user functions */
+void __acquires(wait_entry)
+iwl_init_notification_wait(struct iwl_notif_wait_data *notif_data,
+ struct iwl_notification_wait *wait_entry,
+ u8 cmd,
+ void (*fn)(struct iwl_notif_wait_data *notif_data,
+ struct iwl_rx_packet *pkt, void *data),
+ void *fn_data);
+
+int __must_check __releases(wait_entry)
+iwl_wait_notification(struct iwl_notif_wait_data *notif_data,
+ struct iwl_notification_wait *wait_entry,
+ unsigned long timeout);
+
+void __releases(wait_entry)
+iwl_remove_notification(struct iwl_notif_wait_data *notif_data,
+ struct iwl_notification_wait *wait_entry);
- return iwl_trans_send_cmd(trans, &cmd);
-}
+#endif /* __iwl_notif_wait_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
index d4fc9be2d2f..6ea4163ff56 100644
--- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
@@ -67,7 +67,8 @@ struct iwl_op_mode;
struct iwl_trans;
struct sk_buff;
struct iwl_device_cmd;
-struct iwl_rx_mem_buffer;
+struct iwl_rx_cmd_buffer;
+struct iwl_fw;
/**
* DOC: Operational mode - what is it ?
@@ -121,17 +122,23 @@ struct iwl_rx_mem_buffer;
* there are Tx packets pending in the transport layer.
* Must be atomic
* @nic_error: error notification. Must be atomic
+ * @cmd_queue_full: Called when the command queue gets full. Must be atomic.
+ * @nic_config: configure NIC, called before firmware is started.
+ * May sleep
*/
struct iwl_op_mode_ops {
- struct iwl_op_mode *(*start)(struct iwl_trans *trans);
+ struct iwl_op_mode *(*start)(struct iwl_trans *trans,
+ const struct iwl_fw *fw);
void (*stop)(struct iwl_op_mode *op_mode);
- int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_mem_buffer *rxb,
+ int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
void (*queue_full)(struct iwl_op_mode *op_mode, u8 ac);
void (*queue_not_full)(struct iwl_op_mode *op_mode, u8 ac);
void (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);
void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb);
void (*nic_error)(struct iwl_op_mode *op_mode);
+ void (*cmd_queue_full)(struct iwl_op_mode *op_mode);
+ void (*nic_config)(struct iwl_op_mode *op_mode);
};
/**
@@ -156,7 +163,7 @@ static inline void iwl_op_mode_stop(struct iwl_op_mode *op_mode)
}
static inline int iwl_op_mode_rx(struct iwl_op_mode *op_mode,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
return op_mode->ops->rx(op_mode, rxb, cmd);
@@ -190,6 +197,17 @@ static inline void iwl_op_mode_nic_error(struct iwl_op_mode *op_mode)
op_mode->ops->nic_error(op_mode);
}
+static inline void iwl_op_mode_cmd_queue_full(struct iwl_op_mode *op_mode)
+{
+ op_mode->ops->cmd_queue_full(op_mode);
+}
+
+static inline void iwl_op_mode_nic_config(struct iwl_op_mode *op_mode)
+{
+ might_sleep();
+ op_mode->ops->nic_config(op_mode);
+}
+
/*****************************************************
* Op mode layers implementations
******************************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c
index 06e004157dc..c5e339ee918 100644
--- a/drivers/net/wireless/iwlwifi/iwl-pci.c
+++ b/drivers/net/wireless/iwlwifi/iwl-pci.c
@@ -263,7 +263,7 @@ MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
+ const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
struct iwl_shared *shrd;
struct iwl_trans *iwl_trans;
int err;
@@ -278,17 +278,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
#ifdef CONFIG_IWLWIFI_IDI
iwl_trans = iwl_trans_idi_alloc(shrd, pdev, ent);
- if (iwl_trans == NULL) {
- err = -ENOMEM;
- goto out_free_bus;
- }
-
- shrd->trans = iwl_trans;
- pci_set_drvdata(pdev, iwl_trans);
-
- err = iwl_drv_start(shrd, iwl_trans, cfg);
#else
iwl_trans = iwl_trans_pcie_alloc(shrd, pdev, ent);
+#endif
if (iwl_trans == NULL) {
err = -ENOMEM;
goto out_free_bus;
@@ -298,7 +290,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, iwl_trans);
err = iwl_drv_start(shrd, iwl_trans, cfg);
-#endif
if (err)
goto out_free_trans;
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index fd008c4e41f..958d9d09aee 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -215,7 +215,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
else
cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
- if (hw_params(priv).shadow_reg_enable)
+ if (cfg(priv)->base_params->shadow_reg_enable)
cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
else
cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
@@ -301,7 +301,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
if (priv->power_data.bus_pm)
cmd->flags |= IWL_POWER_PCI_PM_MSK;
- if (hw_params(priv).shadow_reg_enable)
+ if (cfg(priv)->base_params->shadow_reg_enable)
cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
else
cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
@@ -336,7 +336,7 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
le32_to_cpu(cmd->sleep_interval[3]),
le32_to_cpu(cmd->sleep_interval[4]));
- return iwl_trans_send_cmd_pdu(trans(priv), POWER_TABLE_CMD, CMD_SYNC,
+ return iwl_dvm_send_cmd_pdu(priv, POWER_TABLE_CMD, CMD_SYNC,
sizeof(struct iwl_powertable_cmd), cmd);
}
@@ -348,7 +348,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
dtimper = priv->hw->conf.ps_dtim_period ?: 1;
- if (priv->shrd->wowlan)
+ if (priv->wowlan)
iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper);
else if (!cfg(priv)->base_params->no_idle_support &&
priv->hw->conf.flags & IEEE80211_CONF_IDLE)
@@ -383,7 +383,7 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
int ret;
bool update_chains;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
/* Don't update the RX chain when chain noise calibration is running */
update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
@@ -392,12 +392,12 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force)
return 0;
- if (!iwl_is_ready_rf(priv->shrd))
+ if (!iwl_is_ready_rf(priv))
return -EIO;
/* scan complete use sleep_power_next, need to be updated */
memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd));
- if (test_bit(STATUS_SCANNING, &priv->shrd->status) && !force) {
+ if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n");
return 0;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index a4d11016c3b..75dc20bd965 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -216,10 +216,6 @@
#define SCD_TRANS_TBL_OFFSET_QUEUE(x) \
((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)
-#define SCD_QUEUECHAIN_SEL_ALL(priv) \
- (((1<<hw_params(priv).max_txq_num) - 1) &\
- (~(1<<(priv)->shrd->cmd_queue)))
-
#define SCD_BASE (PRPH_BASE + 0xa02c00)
#define SCD_SRAM_BASE_ADDR (SCD_BASE + 0x0)
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 42ee1c410ef..902efe4bc89 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -57,39 +57,39 @@
static int iwl_send_scan_abort(struct iwl_priv *priv)
{
int ret;
- struct iwl_rx_packet *pkt;
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_ABORT_CMD,
.flags = CMD_SYNC | CMD_WANT_SKB,
};
+ __le32 *status;
/* Exit instantly with error when device is not ready
* to receive scan abort command or it does not perform
* hardware scan currently */
- if (!test_bit(STATUS_READY, &priv->shrd->status) ||
- !test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) ||
- !test_bit(STATUS_SCAN_HW, &priv->shrd->status) ||
- test_bit(STATUS_FW_ERROR, &priv->shrd->status) ||
- test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ if (!test_bit(STATUS_READY, &priv->status) ||
+ !test_bit(STATUS_GEO_CONFIGURED, &priv->status) ||
+ !test_bit(STATUS_SCAN_HW, &priv->status) ||
+ test_bit(STATUS_FW_ERROR, &priv->shrd->status))
return -EIO;
- ret = iwl_trans_send_cmd(trans(priv), &cmd);
+ ret = iwl_dvm_send_cmd(priv, &cmd);
if (ret)
return ret;
- pkt = (struct iwl_rx_packet *)cmd.reply_page;
- if (pkt->u.status != CAN_ABORT_STATUS) {
+ status = (void *)cmd.resp_pkt->data;
+ if (*status != CAN_ABORT_STATUS) {
/* The scan abort will return 1 for success or
* 2 for "failure". A failure condition can be
* due to simply not being in an active scan which
* can occur if we send the scan abort before we
* the microcode has notified us that a scan is
* completed. */
- IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n", pkt->u.status);
+ IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n",
+ le32_to_cpu(*status));
ret = -EIO;
}
- iwl_free_pages(priv->shrd, cmd.reply_page);
+ iwl_free_resp(&cmd);
return ret;
}
@@ -116,20 +116,20 @@ static void iwl_process_scan_complete(struct iwl_priv *priv)
{
bool aborted;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
- if (!test_and_clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status))
+ if (!test_and_clear_bit(STATUS_SCAN_COMPLETE, &priv->status))
return;
IWL_DEBUG_SCAN(priv, "Completed scan.\n");
cancel_delayed_work(&priv->scan_check);
- aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status);
+ aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status);
if (aborted)
IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n");
- if (!test_and_clear_bit(STATUS_SCANNING, &priv->shrd->status)) {
+ if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Scan already completed.\n");
goto out_settings;
}
@@ -165,7 +165,7 @@ out_complete:
out_settings:
/* Can we still talk to firmware ? */
- if (!iwl_is_ready_rf(priv->shrd))
+ if (!iwl_is_ready_rf(priv))
return;
iwlagn_post_scan(priv);
@@ -173,18 +173,18 @@ out_settings:
void iwl_force_scan_end(struct iwl_priv *priv)
{
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
- if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) {
+ if (!test_bit(STATUS_SCANNING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n");
return;
}
IWL_DEBUG_SCAN(priv, "Forcing scan end\n");
- clear_bit(STATUS_SCANNING, &priv->shrd->status);
- clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
- clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status);
- clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status);
+ clear_bit(STATUS_SCANNING, &priv->status);
+ clear_bit(STATUS_SCAN_HW, &priv->status);
+ clear_bit(STATUS_SCAN_ABORTING, &priv->status);
+ clear_bit(STATUS_SCAN_COMPLETE, &priv->status);
iwl_complete_scan(priv, true);
}
@@ -192,14 +192,14 @@ static void iwl_do_scan_abort(struct iwl_priv *priv)
{
int ret;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
- if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) {
+ if (!test_bit(STATUS_SCANNING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n");
return;
}
- if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) {
+ if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Scan abort in progress\n");
return;
}
@@ -231,14 +231,14 @@ void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
{
unsigned long timeout = jiffies + msecs_to_jiffies(ms);
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n");
iwl_do_scan_abort(priv);
while (time_before_eq(jiffies, timeout)) {
- if (!test_bit(STATUS_SCAN_HW, &priv->shrd->status))
+ if (!test_bit(STATUS_SCAN_HW, &priv->status))
goto finished;
msleep(20);
}
@@ -261,13 +261,12 @@ void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
/* Service response to REPLY_SCAN_CMD (0x80) */
static int iwl_rx_reply_scan(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_scanreq_notification *notif =
- (struct iwl_scanreq_notification *)pkt->u.raw;
+ struct iwl_scanreq_notification *notif = (void *)pkt->data;
IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status);
#endif
@@ -276,12 +275,12 @@ static int iwl_rx_reply_scan(struct iwl_priv *priv,
/* Service SCAN_START_NOTIFICATION (0x82) */
static int iwl_rx_scan_start_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_scanstart_notification *notif =
- (struct iwl_scanstart_notification *)pkt->u.raw;
+ struct iwl_scanstart_notification *notif = (void *)pkt->data;
+
priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
IWL_DEBUG_SCAN(priv, "Scan start: "
"%d [802.11%s] "
@@ -303,13 +302,12 @@ static int iwl_rx_scan_start_notif(struct iwl_priv *priv,
/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
static int iwl_rx_scan_results_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_scanresults_notification *notif =
- (struct iwl_scanresults_notification *)pkt->u.raw;
+ struct iwl_scanresults_notification *notif = (void *)pkt->data;
IWL_DEBUG_SCAN(priv, "Scan ch.res: "
"%d [802.11%s] "
@@ -329,11 +327,11 @@ static int iwl_rx_scan_results_notif(struct iwl_priv *priv,
/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
static int iwl_rx_scan_complete_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
+ struct iwl_scancomplete_notification *scan_notif = (void *)pkt->data;
IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
scan_notif->scanned_channels,
@@ -352,8 +350,8 @@ static int iwl_rx_scan_complete_notif(struct iwl_priv *priv,
* to clear, we need to set SCAN_COMPLETE before clearing SCAN_HW
* to avoid a race there.
*/
- set_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status);
- clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
+ set_bit(STATUS_SCAN_COMPLETE, &priv->status);
+ clear_bit(STATUS_SCAN_HW, &priv->status);
queue_work(priv->workqueue, &priv->scan_completed);
if (priv->iw_mode != NL80211_IFTYPE_ADHOC &&
@@ -574,6 +572,53 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
return added;
}
+/**
+ * iwl_fill_probe_req - fill in all required fields and IE for probe request
+ */
+
+static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta,
+ const u8 *ies, int ie_len, int left)
+{
+ int len = 0;
+ u8 *pos = NULL;
+
+ /* Make sure there is enough space for the probe request,
+ * two mandatory IEs and the data */
+ left -= 24;
+ if (left < 0)
+ return 0;
+
+ frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
+ memcpy(frame->da, iwl_bcast_addr, ETH_ALEN);
+ memcpy(frame->sa, ta, ETH_ALEN);
+ memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN);
+ frame->seq_ctrl = 0;
+
+ len += 24;
+
+ /* ...next IE... */
+ pos = &frame->u.probe_req.variable[0];
+
+ /* fill in our indirect SSID IE */
+ left -= 2;
+ if (left < 0)
+ return 0;
+ *pos++ = WLAN_EID_SSID;
+ *pos++ = 0;
+
+ len += 2;
+
+ if (WARN_ON(left < ie_len))
+ return len;
+
+ if (ies && ie_len) {
+ memcpy(pos, ies, ie_len);
+ len += ie_len;
+ }
+
+ return (u16)len;
+}
+
static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
struct iwl_host_cmd cmd = {
@@ -596,7 +641,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
u8 scan_tx_antennas = hw_params(priv).valid_tx_ant;
int ret;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
if (vif)
ctx = iwl_rxon_ctx_from_vif(vif);
@@ -793,7 +838,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan->rx_chain = cpu_to_le16(rx_chain);
switch (priv->scan_type) {
case IWL_SCAN_NORMAL:
- cmd_len = iwl_fill_probe_req(priv,
+ cmd_len = iwl_fill_probe_req(
(struct ieee80211_mgmt *)scan->data,
vif->addr,
priv->scan_request->ie,
@@ -803,7 +848,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
case IWL_SCAN_RADIO_RESET:
case IWL_SCAN_ROC:
/* use bcast addr, will not be transmitted but must be valid */
- cmd_len = iwl_fill_probe_req(priv,
+ cmd_len = iwl_fill_probe_req(
(struct ieee80211_mgmt *)scan->data,
iwl_bcast_addr, NULL, 0,
IWL_MAX_SCAN_SIZE - sizeof(*scan));
@@ -882,15 +927,15 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan->len = cpu_to_le16(cmd.len[0]);
/* set scan bit here for PAN params */
- set_bit(STATUS_SCAN_HW, &priv->shrd->status);
+ set_bit(STATUS_SCAN_HW, &priv->status);
ret = iwlagn_set_pan_params(priv);
if (ret)
return ret;
- ret = iwl_trans_send_cmd(trans(priv), &cmd);
+ ret = iwl_dvm_send_cmd(priv, &cmd);
if (ret) {
- clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
+ clear_bit(STATUS_SCAN_HW, &priv->status);
iwlagn_set_pan_params(priv);
}
@@ -913,22 +958,22 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
{
int ret;
- lockdep_assert_held(&priv->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
cancel_delayed_work(&priv->scan_check);
- if (!iwl_is_ready_rf(priv->shrd)) {
+ if (!iwl_is_ready_rf(priv)) {
IWL_WARN(priv, "Request scan called when driver not ready.\n");
return -EIO;
}
- if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
+ if (test_bit(STATUS_SCAN_HW, &priv->status)) {
IWL_DEBUG_SCAN(priv,
"Multiple concurrent scan requests in parallel.\n");
return -EBUSY;
}
- if (test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) {
+ if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n");
return -EBUSY;
}
@@ -938,14 +983,14 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
scan_type == IWL_SCAN_ROC ? "remain-on-channel " :
"internal short ");
- set_bit(STATUS_SCANNING, &priv->shrd->status);
+ set_bit(STATUS_SCANNING, &priv->status);
priv->scan_type = scan_type;
priv->scan_start = jiffies;
priv->scan_band = band;
ret = iwlagn_request_scan(priv, vif);
if (ret) {
- clear_bit(STATUS_SCANNING, &priv->shrd->status);
+ clear_bit(STATUS_SCANNING, &priv->status);
priv->scan_type = IWL_SCAN_NORMAL;
return ret;
}
@@ -973,14 +1018,14 @@ static void iwl_bg_start_internal_scan(struct work_struct *work)
IWL_DEBUG_SCAN(priv, "Start internal scan\n");
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
if (priv->scan_type == IWL_SCAN_RADIO_RESET) {
IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
goto unlock;
}
- if (test_bit(STATUS_SCANNING, &priv->shrd->status)) {
+ if (test_bit(STATUS_SCANNING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
goto unlock;
}
@@ -988,7 +1033,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work)
if (iwl_scan_initiate(priv, NULL, IWL_SCAN_RADIO_RESET, priv->band))
IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
unlock:
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
}
static void iwl_bg_scan_check(struct work_struct *data)
@@ -1001,56 +1046,9 @@ static void iwl_bg_scan_check(struct work_struct *data)
/* Since we are here firmware does not finish scan and
* most likely is in bad shape, so we don't bother to
* send abort command, just force scan complete to mac80211 */
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
iwl_force_scan_end(priv);
- mutex_unlock(&priv->shrd->mutex);
-}
-
-/**
- * iwl_fill_probe_req - fill in all required fields and IE for probe request
- */
-
-u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
- const u8 *ta, const u8 *ies, int ie_len, int left)
-{
- int len = 0;
- u8 *pos = NULL;
-
- /* Make sure there is enough space for the probe request,
- * two mandatory IEs and the data */
- left -= 24;
- if (left < 0)
- return 0;
-
- frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
- memcpy(frame->da, iwl_bcast_addr, ETH_ALEN);
- memcpy(frame->sa, ta, ETH_ALEN);
- memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN);
- frame->seq_ctrl = 0;
-
- len += 24;
-
- /* ...next IE... */
- pos = &frame->u.probe_req.variable[0];
-
- /* fill in our indirect SSID IE */
- left -= 2;
- if (left < 0)
- return 0;
- *pos++ = WLAN_EID_SSID;
- *pos++ = 0;
-
- len += 2;
-
- if (WARN_ON(left < ie_len))
- return len;
-
- if (ies && ie_len) {
- memcpy(pos, ies, ie_len);
- len += ie_len;
- }
-
- return (u16)len;
+ mutex_unlock(&priv->mutex);
}
static void iwl_bg_abort_scan(struct work_struct *work)
@@ -1061,9 +1059,9 @@ static void iwl_bg_abort_scan(struct work_struct *work)
/* We keep scan_check work queued in case when firmware will not
* report back scan completed notification */
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
iwl_scan_cancel_timeout(priv, 200);
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
}
static void iwl_bg_scan_completed(struct work_struct *work)
@@ -1071,9 +1069,9 @@ static void iwl_bg_scan_completed(struct work_struct *work)
struct iwl_priv *priv =
container_of(work, struct iwl_priv, scan_completed);
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
iwl_process_scan_complete(priv);
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
}
void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
@@ -1091,8 +1089,8 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv)
cancel_work_sync(&priv->scan_completed);
if (cancel_delayed_work_sync(&priv->scan_check)) {
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
iwl_force_scan_end(priv);
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
}
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h
index a6441623e6b..cf34087aa2f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-shared.h
+++ b/drivers/net/wireless/iwlwifi/iwl-shared.h
@@ -65,12 +65,11 @@
#include <linux/types.h>
#include <linux/spinlock.h>
-#include <linux/mutex.h>
#include <linux/gfp.h>
-#include <linux/mm.h> /* for page_address */
#include <net/mac80211.h>
#include "iwl-commands.h"
+#include "iwl-fw.h"
/**
* DOC: shared area - role and goal
@@ -116,7 +115,6 @@ extern struct iwl_mod_params iwlagn_mod_params;
* Holds the module parameters
*
* @sw_crypto: using hardware encryption, default = 0
- * @num_of_queues: number of tx queue, HW dependent
* @disable_11n: disable 11n capabilities, default = 0,
* use IWL_DISABLE_HT_* constants
* @amsdu_size_8K: enable 8K amsdu size, default = 1
@@ -138,7 +136,6 @@ extern struct iwl_mod_params iwlagn_mod_params;
*/
struct iwl_mod_params {
int sw_crypto;
- int num_of_queues;
unsigned int disable_11n;
int amsdu_size_8K;
int antenna;
@@ -163,7 +160,6 @@ struct iwl_mod_params {
*
* Holds the module parameters
*
- * @max_txq_num: Max # Tx queues supported
* @num_ampdu_queues: num of ampdu queues
* @tx_chains_num: Number of TX chains
* @rx_chains_num: Number of RX chains
@@ -177,16 +173,16 @@ struct iwl_mod_params {
* relevant for 1000, 6000 and up
* @wd_timeout: TX queues watchdog timeout
* @struct iwl_sensitivity_ranges: range of sensitivity values
+ * @use_rts_for_aggregation: use rts/cts protection for HT traffic
*/
struct iwl_hw_params {
- u8 max_txq_num;
u8 num_ampdu_queues;
u8 tx_chains_num;
u8 rx_chains_num;
u8 valid_tx_ant;
u8 valid_rx_ant;
u8 ht40_channel;
- bool shadow_reg_enable;
+ bool use_rts_for_aggregation;
u16 sku;
u32 rx_page_order;
u32 ct_kill_threshold;
@@ -213,45 +209,6 @@ enum iwl_ucode_type {
IWL_UCODE_WOWLAN,
};
-/**
- * struct iwl_notification_wait - notification wait entry
- * @list: list head for global list
- * @fn: function called with the notification
- * @cmd: command ID
- *
- * This structure is not used directly, to wait for a
- * notification declare it on the stack, and call
- * iwlagn_init_notification_wait() with appropriate
- * parameters. Then do whatever will cause the ucode
- * to notify the driver, and to wait for that then
- * call iwlagn_wait_notification().
- *
- * Each notification is one-shot. If at some point we
- * need to support multi-shot notifications (which
- * can't be allocated on the stack) we need to modify
- * the code for them.
- */
-struct iwl_notification_wait {
- struct list_head list;
-
- void (*fn)(struct iwl_trans *trans, struct iwl_rx_packet *pkt,
- void *data);
- void *fn_data;
-
- u8 cmd;
- bool triggered, aborted;
-};
-
-/**
- * enum iwl_pa_type - Power Amplifier type
- * @IWL_PA_SYSTEM: based on uCode configuration
- * @IWL_PA_INTERNAL: use Internal only
- */
-enum iwl_pa_type {
- IWL_PA_SYSTEM = 0,
- IWL_PA_INTERNAL = 1,
-};
-
/*
* LED mode
* IWL_LED_DEFAULT: use device default
@@ -268,6 +225,73 @@ enum iwl_led_mode {
IWL_LED_DISABLE,
};
+/*
+ * @max_ll_items: max number of OTP blocks
+ * @shadow_ram_support: shadow support for OTP memory
+ * @led_compensation: compensate on the led on/off time per HW according
+ * to the deviation to achieve the desired led frequency.
+ * The detail algorithm is described in iwl-led.c
+ * @chain_noise_num_beacons: number of beacons used to compute chain noise
+ * @adv_thermal_throttle: support advance thermal throttle
+ * @support_ct_kill_exit: support ct kill exit condition
+ * @support_wimax_coexist: support wimax/wifi co-exist
+ * @plcp_delta_threshold: plcp error rate threshold used to trigger
+ * radio tuning when there is a high receiving plcp error rate
+ * @chain_noise_scale: default chain noise scale used for gain computation
+ * @wd_timeout: TX queues watchdog timeout
+ * @max_event_log_size: size of event log buffer size for ucode event logging
+ * @shadow_reg_enable: HW shadhow register bit
+ * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up
+ * @no_idle_support: do not support idle mode
+ * wd_disable: disable watchdog timer
+ */
+struct iwl_base_params {
+ int eeprom_size;
+ int num_of_queues; /* def: HW dependent */
+ int num_of_ampdu_queues;/* def: HW dependent */
+ /* for iwl_apm_init() */
+ u32 pll_cfg_val;
+
+ const u16 max_ll_items;
+ const bool shadow_ram_support;
+ u16 led_compensation;
+ bool adv_thermal_throttle;
+ bool support_ct_kill_exit;
+ const bool support_wimax_coexist;
+ u8 plcp_delta_threshold;
+ s32 chain_noise_scale;
+ unsigned int wd_timeout;
+ u32 max_event_log_size;
+ const bool shadow_reg_enable;
+ const bool hd_v2;
+ const bool no_idle_support;
+ const bool wd_disable;
+};
+
+/*
+ * @advanced_bt_coexist: support advanced bt coexist
+ * @bt_init_traffic_load: specify initial bt traffic load
+ * @bt_prio_boost: default bt priority boost value
+ * @agg_time_limit: maximum number of uSec in aggregation
+ * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode
+ */
+struct iwl_bt_params {
+ bool advanced_bt_coexist;
+ u8 bt_init_traffic_load;
+ u8 bt_prio_boost;
+ u16 agg_time_limit;
+ bool bt_sco_disable;
+ bool bt_session_2;
+};
+/*
+ * @use_rts_for_aggregation: use rts/cts protection for HT traffic
+ */
+struct iwl_ht_params {
+ const bool ht_greenfield_support; /* if used set to true */
+ bool use_rts_for_aggregation;
+ enum ieee80211_smps_mode smps_mode;
+};
+
/**
* struct iwl_cfg
* @name: Offical name of the device
@@ -282,7 +306,6 @@ enum iwl_led_mode {
* @max_data_size: The maximal length of the fw data section
* @valid_tx_ant: valid transmit antenna
* @valid_rx_ant: valid receive antenna
- * @sku: sku information from EEPROM
* @eeprom_ver: EEPROM version
* @eeprom_calib_ver: EEPROM calibration version
* @lib: pointer to the lib ops
@@ -290,7 +313,6 @@ enum iwl_led_mode {
* @base_params: pointer to basic parameters
* @ht_params: point to ht patameters
* @bt_params: pointer to bt parameters
- * @pa_type: used by 6000 series only to identify the type of Power Amplifier
* @need_temp_offset_calib: need to perform temperature offset calibration
* @no_xtal_calib: some devices do not need crystal calibration data,
* don't send it to those
@@ -321,17 +343,15 @@ struct iwl_cfg {
const u32 max_inst_size;
u8 valid_tx_ant;
u8 valid_rx_ant;
- u16 sku;
u16 eeprom_ver;
u16 eeprom_calib_ver;
const struct iwl_lib_ops *lib;
void (*additional_nic_config)(struct iwl_priv *priv);
/* params not likely to change within a device family */
- struct iwl_base_params *base_params;
+ const struct iwl_base_params *base_params;
/* params likely to change within a device family */
- struct iwl_ht_params *ht_params;
- struct iwl_bt_params *bt_params;
- enum iwl_pa_type pa_type; /* if used set to IWL_PA_SYSTEM */
+ const struct iwl_ht_params *ht_params;
+ const struct iwl_bt_params *bt_params;
const bool need_temp_offset_calib; /* if used set to true */
const bool no_xtal_calib;
u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
@@ -346,10 +366,6 @@ struct iwl_cfg {
/**
* struct iwl_shared - shared fields for all the layers of the driver
*
- * @dbg_level_dev: dbg level set per device. Prevails on
- * iwlagn_mod_params.debug_level if set (!= 0)
- * @ucode_owner: IWL_OWNERSHIP_*
- * @cmd_queue: command queue number
* @status: STATUS_*
* @wowlan: are we running wowlan uCode
* @valid_contexts: microcode/device supports multiple contexts
@@ -360,39 +376,20 @@ struct iwl_cfg {
* @nic: pointer to the nic data
* @hw_params: see struct iwl_hw_params
* @lock: protect general shared data
- * @sta_lock: protects the station table.
- * If lock and sta_lock are needed, lock must be acquired first.
- * @mutex:
- * @wait_command_queue: the wait_queue for SYNC host command nad uCode load
+ * @wait_command_queue: the wait_queue for SYNC host commands
* @eeprom: pointer to the eeprom/OTP image
* @ucode_type: indicator of loaded ucode image
- * @notif_waits: things waiting for notification
- * @notif_wait_lock: lock protecting notification
- * @notif_waitq: head of notification wait queue
* @device_pointers: pointers to ucode event tables
*/
struct iwl_shared {
-#ifdef CONFIG_IWLWIFI_DEBUG
- u32 dbg_level_dev;
-#endif /* CONFIG_IWLWIFI_DEBUG */
-
-#define IWL_OWNERSHIP_DRIVER 0
-#define IWL_OWNERSHIP_TM 1
- u8 ucode_owner;
- u8 cmd_queue;
unsigned long status;
- bool wowlan;
u8 valid_contexts;
- struct iwl_cfg *cfg;
- struct iwl_priv *priv;
+ const struct iwl_cfg *cfg;
struct iwl_trans *trans;
- struct iwl_nic *nic;
+ void *drv;
struct iwl_hw_params hw_params;
-
- spinlock_t lock;
- spinlock_t sta_lock;
- struct mutex mutex;
+ const struct iwl_fw *fw;
wait_queue_head_t wait_command_queue;
@@ -402,11 +399,6 @@ struct iwl_shared {
/* ucode related variables */
enum iwl_ucode_type ucode_type;
- /* notification wait support */
- struct list_head notif_waits;
- spinlock_t notif_wait_lock;
- wait_queue_head_t notif_waitq;
-
struct {
u32 error_event_table;
u32 log_event_table;
@@ -415,111 +407,13 @@ struct iwl_shared {
};
/*Whatever _m is (iwl_trans, iwl_priv, these macros will work */
-#define priv(_m) ((_m)->shrd->priv)
#define cfg(_m) ((_m)->shrd->cfg)
-#define nic(_m) ((_m)->shrd->nic)
#define trans(_m) ((_m)->shrd->trans)
#define hw_params(_m) ((_m)->shrd->hw_params)
-#ifdef CONFIG_IWLWIFI_DEBUG
-/*
- * iwl_get_debug_level: Return active debug level for device
- *
- * Using sysfs it is possible to set per device debug level. This debug
- * level will be used if set, otherwise the global debug level which can be
- * set via module parameter is used.
- */
-static inline u32 iwl_get_debug_level(struct iwl_shared *shrd)
-{
- if (shrd->dbg_level_dev)
- return shrd->dbg_level_dev;
- else
- return iwlagn_mod_params.debug_level;
-}
-#else
-static inline u32 iwl_get_debug_level(struct iwl_shared *shrd)
-{
- return iwlagn_mod_params.debug_level;
-}
-#endif
-
-static inline void iwl_free_pages(struct iwl_shared *shrd, unsigned long page)
+static inline bool iwl_have_debug_level(u32 level)
{
- free_pages(page, shrd->hw_params.rx_page_order);
-}
-
-/**
- * iwl_queue_inc_wrap - increment queue index, wrap back to beginning
- * @index -- current index
- * @n_bd -- total number of entries in queue (must be power of 2)
- */
-static inline int iwl_queue_inc_wrap(int index, int n_bd)
-{
- return ++index & (n_bd - 1);
-}
-
-/**
- * iwl_queue_dec_wrap - decrement queue index, wrap back to end
- * @index -- current index
- * @n_bd -- total number of entries in queue (must be power of 2)
- */
-static inline int iwl_queue_dec_wrap(int index, int n_bd)
-{
- return --index & (n_bd - 1);
-}
-
-struct iwl_rx_mem_buffer {
- dma_addr_t page_dma;
- struct page *page;
- struct list_head list;
-};
-
-#define rxb_addr(r) page_address(r->page)
-
-/*
- * mac80211 queues, ACs, hardware queues, FIFOs.
- *
- * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
- *
- * Mac80211 uses the following numbers, which we get as from it
- * by way of skb_get_queue_mapping(skb):
- *
- * VO 0
- * VI 1
- * BE 2
- * BK 3
- *
- *
- * Regular (not A-MPDU) frames are put into hardware queues corresponding
- * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
- * own queue per aggregation session (RA/TID combination), such queues are
- * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
- * order to map frames to the right queue, we also need an AC->hw queue
- * mapping. This is implemented here.
- *
- * Due to the way hw queues are set up (by the hw specific modules like
- * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity
- * mapping.
- */
-
-static const u8 tid_to_ac[] = {
- IEEE80211_AC_BE,
- IEEE80211_AC_BK,
- IEEE80211_AC_BK,
- IEEE80211_AC_BE,
- IEEE80211_AC_VI,
- IEEE80211_AC_VI,
- IEEE80211_AC_VO,
- IEEE80211_AC_VO
-};
-
-static inline int get_ac_from_tid(u16 tid)
-{
- if (likely(tid < ARRAY_SIZE(tid_to_ac)))
- return tid_to_ac[tid];
-
- /* no support for TIDs 8-15 yet */
- return -EINVAL;
+ return iwlagn_mod_params.debug_level & level;
}
enum iwl_rxon_context_id {
@@ -530,34 +424,9 @@ enum iwl_rxon_context_id {
};
int iwlagn_hw_valid_rtc_data_addr(u32 addr);
-void iwl_nic_config(struct iwl_priv *priv);
const char *get_cmd_string(u8 cmd);
-bool iwl_check_for_ct_kill(struct iwl_priv *priv);
-
-
-/* notification wait support */
-void iwl_abort_notification_waits(struct iwl_shared *shrd);
-void __acquires(wait_entry)
-iwl_init_notification_wait(struct iwl_shared *shrd,
- struct iwl_notification_wait *wait_entry,
- u8 cmd,
- void (*fn)(struct iwl_trans *trans,
- struct iwl_rx_packet *pkt,
- void *data),
- void *fn_data);
-int __must_check __releases(wait_entry)
-iwl_wait_notification(struct iwl_shared *shrd,
- struct iwl_notification_wait *wait_entry,
- unsigned long timeout);
-void __releases(wait_entry)
-iwl_remove_notification(struct iwl_shared *shrd,
- struct iwl_notification_wait *wait_entry);
#define IWL_CMD(x) case x: return #x
-#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
-
-#define IWL_TRAFFIC_ENTRIES (256)
-#define IWL_TRAFFIC_ENTRY_SIZE (64)
/*****************************************************
* DRIVER STATUS FUNCTIONS
@@ -583,46 +452,4 @@ iwl_remove_notification(struct iwl_shared *shrd,
#define STATUS_CHANNEL_SWITCH_PENDING 19
#define STATUS_SCAN_COMPLETE 20
-static inline int iwl_is_ready(struct iwl_shared *shrd)
-{
- /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
- * set but EXIT_PENDING is not */
- return test_bit(STATUS_READY, &shrd->status) &&
- test_bit(STATUS_GEO_CONFIGURED, &shrd->status) &&
- !test_bit(STATUS_EXIT_PENDING, &shrd->status);
-}
-
-static inline int iwl_is_alive(struct iwl_shared *shrd)
-{
- return test_bit(STATUS_ALIVE, &shrd->status);
-}
-
-static inline int iwl_is_init(struct iwl_shared *shrd)
-{
- return test_bit(STATUS_INIT, &shrd->status);
-}
-
-static inline int iwl_is_rfkill_hw(struct iwl_shared *shrd)
-{
- return test_bit(STATUS_RF_KILL_HW, &shrd->status);
-}
-
-static inline int iwl_is_rfkill(struct iwl_shared *shrd)
-{
- return iwl_is_rfkill_hw(shrd);
-}
-
-static inline int iwl_is_ctkill(struct iwl_shared *shrd)
-{
- return test_bit(STATUS_CT_KILL, &shrd->status);
-}
-
-static inline int iwl_is_ready_rf(struct iwl_shared *shrd)
-{
- if (iwl_is_rfkill(shrd))
- return 0;
-
- return iwl_is_ready(shrd);
-}
-
#endif /* #__iwl_shared_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c
index 23eea06a74a..b06c6763cb7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-testmode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c
@@ -70,7 +70,6 @@
#include <net/mac80211.h>
#include <net/netlink.h>
-#include "iwl-wifi.h"
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-debug.h"
@@ -79,6 +78,7 @@
#include "iwl-testmode.h"
#include "iwl-trans.h"
#include "iwl-fh.h"
+#include "iwl-prph.h"
/* Periphery registers absolute lower bound. This is used in order to
@@ -125,13 +125,15 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
[IWL_TM_ATTR_FW_TYPE] = { .type = NLA_U32, },
[IWL_TM_ATTR_FW_INST_SIZE] = { .type = NLA_U32, },
[IWL_TM_ATTR_FW_DATA_SIZE] = { .type = NLA_U32, },
+
+ [IWL_TM_ATTR_ENABLE_NOTIFICATION] = {.type = NLA_FLAG, },
};
/*
* See the struct iwl_rx_packet in iwl-commands.h for the format of the
* received events from the device
*/
-static inline int get_event_length(struct iwl_rx_mem_buffer *rxb)
+static inline int get_event_length(struct iwl_rx_cmd_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
if (pkt)
@@ -162,7 +164,7 @@ static inline int get_event_length(struct iwl_rx_mem_buffer *rxb)
*/
static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+ struct iwl_rx_cmd_buffer *rxb)
{
struct ieee80211_hw *hw = priv->hw;
struct sk_buff *skb;
@@ -183,7 +185,8 @@ static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv,
return;
}
NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT);
- NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, length, data);
+ /* the length doesn't include len_n_flags field, so add it manually */
+ NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, length + sizeof(__le32), data);
cfg80211_testmode_event(skb, GFP_ATOMIC);
return;
@@ -194,7 +197,7 @@ nla_put_failure:
void iwl_testmode_init(struct iwl_priv *priv)
{
- priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
+ priv->pre_rx_handler = NULL;
priv->testmode_trace.trace_enabled = false;
priv->testmode_mem.read_in_progress = false;
}
@@ -283,7 +286,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
IWL_DEBUG_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
" len %d\n", cmd.id, cmd.flags, cmd.len[0]);
- ret = iwl_trans_send_cmd(trans(priv), &cmd);
+ ret = iwl_dvm_send_cmd(priv, &cmd);
if (ret) {
IWL_ERR(priv, "Failed to send hcmd\n");
return ret;
@@ -292,7 +295,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
return ret;
/* Handling return of SKB to the user */
- pkt = (struct iwl_rx_packet *)cmd.reply_page;
+ pkt = cmd.resp_pkt;
if (!pkt) {
IWL_ERR(priv, "HCMD received a null response packet\n");
return ret;
@@ -309,7 +312,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
/* The reply is in a page, that we cannot send to user space. */
memcpy(reply_buf, &(pkt->hdr), reply_len);
- iwl_free_pages(priv->shrd, cmd.reply_page);
+ iwl_free_resp(&cmd);
NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT);
NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, reply_len, reply_buf);
@@ -419,23 +422,23 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
struct iwl_notification_wait calib_wait;
int ret;
- iwl_init_notification_wait(priv->shrd, &calib_wait,
- CALIBRATION_COMPLETE_NOTIFICATION,
- NULL, NULL);
- ret = iwl_init_alive_start(trans(priv));
+ iwl_init_notification_wait(&priv->notif_wait, &calib_wait,
+ CALIBRATION_COMPLETE_NOTIFICATION,
+ NULL, NULL);
+ ret = iwl_init_alive_start(priv);
if (ret) {
IWL_ERR(priv, "Fail init calibration: %d\n", ret);
goto cfg_init_calib_error;
}
- ret = iwl_wait_notification(priv->shrd, &calib_wait, 2 * HZ);
+ ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, 2 * HZ);
if (ret)
IWL_ERR(priv, "Error detecting"
" CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret);
return ret;
cfg_init_calib_error:
- iwl_remove_notification(priv->shrd, &calib_wait);
+ iwl_remove_notification(&priv->notif_wait, &calib_wait);
return ret;
}
@@ -484,7 +487,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
break;
case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
- status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT);
+ status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
if (status)
IWL_ERR(priv, "Error loading init ucode: %d\n", status);
break;
@@ -495,7 +498,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
break;
case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
- status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_REGULAR);
+ status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR);
if (status) {
IWL_ERR(priv,
"Error loading runtime ucode: %d\n", status);
@@ -510,7 +513,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
iwl_scan_cancel_timeout(priv, 200);
iwl_trans_stop_device(trans);
- status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_WOWLAN);
+ status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
if (status) {
IWL_ERR(priv,
"Error loading WOWLAN ucode: %d\n", status);
@@ -553,7 +556,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
case IWL_TM_CMD_APP2DEV_GET_FW_VERSION:
IWL_INFO(priv, "uCode version raw: 0x%x\n",
- nic(priv)->fw.ucode_ver);
+ priv->fw->ucode_ver);
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
if (!skb) {
@@ -561,7 +564,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
return -ENOMEM;
}
NLA_PUT_U32(skb, IWL_TM_ATTR_FW_VERSION,
- nic(priv)->fw.ucode_ver);
+ priv->fw->ucode_ver);
status = cfg80211_testmode_reply(skb);
if (status < 0)
IWL_ERR(priv, "Error sending msg : %d\n", status);
@@ -590,16 +593,16 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
}
switch (priv->shrd->ucode_type) {
case IWL_UCODE_REGULAR:
- inst_size = nic(priv)->fw.ucode_rt.code.len;
- data_size = nic(priv)->fw.ucode_rt.data.len;
+ inst_size = priv->fw->ucode_rt.code.len;
+ data_size = priv->fw->ucode_rt.data.len;
break;
case IWL_UCODE_INIT:
- inst_size = nic(priv)->fw.ucode_init.code.len;
- data_size = nic(priv)->fw.ucode_init.data.len;
+ inst_size = priv->fw->ucode_init.code.len;
+ data_size = priv->fw->ucode_init.data.len;
break;
case IWL_UCODE_WOWLAN:
- inst_size = nic(priv)->fw.ucode_wowlan.code.len;
- data_size = nic(priv)->fw.ucode_wowlan.data.len;
+ inst_size = priv->fw->ucode_wowlan.code.len;
+ data_size = priv->fw->ucode_wowlan.data.len;
break;
case IWL_UCODE_NONE:
IWL_ERR(priv, "No uCode has not been loaded\n");
@@ -713,7 +716,7 @@ nla_put_failure:
return -EMSGSIZE;
}
-static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
+static int iwl_testmode_trace_dump(struct ieee80211_hw *hw,
struct sk_buff *skb,
struct netlink_callback *cb)
{
@@ -770,9 +773,13 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
}
owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]);
- if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM))
- priv->shrd->ucode_owner = owner;
- else {
+ if (owner == IWL_OWNERSHIP_DRIVER) {
+ priv->ucode_owner = owner;
+ priv->pre_rx_handler = NULL;
+ } else if (owner == IWL_OWNERSHIP_TM) {
+ priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
+ priv->ucode_owner = owner;
+ } else {
IWL_ERR(priv, "Invalid owner\n");
return -EINVAL;
}
@@ -905,9 +912,9 @@ static int iwl_testmode_indirect_mem(struct ieee80211_hw *hw,
}
}
-static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw, struct nlattr **tb,
- struct sk_buff *skb,
- struct netlink_callback *cb)
+static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
+ struct netlink_callback *cb)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
int idx, length;
@@ -937,6 +944,20 @@ static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw, struct nlattr **tb,
return -ENOBUFS;
}
+static int iwl_testmode_notifications(struct ieee80211_hw *hw,
+ struct nlattr **tb)
+{
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
+ bool enable;
+
+ enable = nla_get_flag(tb[IWL_TM_ATTR_ENABLE_NOTIFICATION]);
+ if (enable)
+ priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
+ else
+ priv->pre_rx_handler = NULL;
+ return 0;
+}
+
/* The testmode gnl message handler that takes the gnl message from the
* user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
@@ -976,7 +997,7 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
return -ENOMSG;
}
/* in case multiple accesses to the device happens */
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
case IWL_TM_CMD_APP2DEV_UCODE:
@@ -1022,13 +1043,19 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
result = iwl_testmode_indirect_mem(hw, tb);
break;
+ case IWL_TM_CMD_APP2DEV_NOTIFICATIONS:
+ IWL_DEBUG_INFO(priv, "testmode notifications cmd "
+ "to driver\n");
+ result = iwl_testmode_notifications(hw, tb);
+ break;
+
default:
IWL_ERR(priv, "Unknown testmode command\n");
result = -ENOSYS;
break;
}
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
return result;
}
@@ -1063,21 +1090,21 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
}
/* in case multiple accesses to the device happens */
- mutex_lock(&priv->shrd->mutex);
+ mutex_lock(&priv->mutex);
switch (cmd) {
case IWL_TM_CMD_APP2DEV_READ_TRACE:
IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n");
- result = iwl_testmode_trace_dump(hw, tb, skb, cb);
+ result = iwl_testmode_trace_dump(hw, skb, cb);
break;
case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP:
IWL_DEBUG_INFO(priv, "testmode sram dump cmd to driver\n");
- result = iwl_testmode_buffer_dump(hw, tb, skb, cb);
+ result = iwl_testmode_buffer_dump(hw, skb, cb);
break;
default:
result = -EINVAL;
break;
}
- mutex_unlock(&priv->shrd->mutex);
+ mutex_unlock(&priv->mutex);
return result;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h
index 69b2e80f407..6ba211b0942 100644
--- a/drivers/net/wireless/iwlwifi/iwl-testmode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h
@@ -122,6 +122,9 @@
* Fore reading, a READ command is sent from the userspace and the data
* is returned when the user calls a DUMP command.
* For writing, only a WRITE command is used.
+ * @IWL_TM_CMD_APP2DEV_NOTIFICATIONS:
+ * Command to enable/disable notifications (currently RX packets) from the
+ * driver to userspace.
*/
enum iwl_tm_cmd_t {
IWL_TM_CMD_APP2DEV_UCODE = 1,
@@ -152,7 +155,8 @@ enum iwl_tm_cmd_t {
IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ = 26,
IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP = 27,
IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE = 28,
- IWL_TM_CMD_MAX = 29,
+ IWL_TM_CMD_APP2DEV_NOTIFICATIONS = 29,
+ IWL_TM_CMD_MAX = 30,
};
/*
@@ -256,6 +260,10 @@ enum iwl_tm_cmd_t {
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE this flag
* indicates that the user wants to receive the response of the command
* in a reply SKB. If it's not present, the response is not returned.
+ * @IWL_TM_ATTR_ENABLE_NOTIFICATIONS:
+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_NOTIFICATIONS, this
+ * flag enables (if present) or disables (if not) the forwarding
+ * to userspace.
*/
enum iwl_tm_attr_t {
IWL_TM_ATTR_NOT_APPLICABLE = 0,
@@ -282,7 +290,8 @@ enum iwl_tm_attr_t {
IWL_TM_ATTR_FW_INST_SIZE = 21,
IWL_TM_ATTR_FW_DATA_SIZE = 22,
IWL_TM_ATTR_UCODE_CMD_SKB = 23,
- IWL_TM_ATTR_MAX = 24,
+ IWL_TM_ATTR_ENABLE_NOTIFICATION = 24,
+ IWL_TM_ATTR_MAX = 25,
};
/* uCode trace buffer */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
index 5b26b71ae3d..67965599bb3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
@@ -32,6 +32,7 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/skbuff.h>
+#include <linux/wait.h>
#include <linux/pci.h>
#include "iwl-fh.h"
@@ -49,6 +50,12 @@ struct iwl_host_cmd;
/*This file includes the declaration that are internal to the
* trans_pcie layer */
+struct iwl_rx_mem_buffer {
+ dma_addr_t page_dma;
+ struct page *page;
+ struct list_head list;
+};
+
/**
* struct isr_statistics - interrupt statistics
*
@@ -109,6 +116,26 @@ struct iwl_dma_ptr {
size_t size;
};
+/**
+ * iwl_queue_inc_wrap - increment queue index, wrap back to beginning
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int iwl_queue_inc_wrap(int index, int n_bd)
+{
+ return ++index & (n_bd - 1);
+}
+
+/**
+ * iwl_queue_dec_wrap - decrement queue index, wrap back to end
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int iwl_queue_dec_wrap(int index, int n_bd)
+{
+ return --index & (n_bd - 1);
+}
+
/*
* This queue number is required for proper operation
* because the ucode will stop/start the scheduler as
@@ -169,6 +196,7 @@ struct iwl_queue {
* @meta: array of meta data for each command/tx buffer
* @dma_addr_cmd: physical address of cmd/tx buffer array
* @txb: array of per-TFD driver data
+ * lock: queue lock
* @time_stamp: time (in jiffies) of last read_ptr change
* @need_update: indicates need to update read/write index
* @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
@@ -187,6 +215,7 @@ struct iwl_tx_queue {
struct iwl_device_cmd **cmd;
struct iwl_cmd_meta *meta;
struct sk_buff **skbs;
+ spinlock_t lock;
unsigned long time_stamp;
u8 need_update;
u8 sched_retry;
@@ -202,6 +231,7 @@ struct iwl_tx_queue {
* @rxq: all the RX queue data
* @rx_replenish: work that will be called when buffers need to be allocated
* @trans: pointer to the generic transport area
+ * @irq - the irq number for the device
* @irq_requested: true when the irq has been requested
* @scd_base_addr: scheduler sram base address in SRAM
* @scd_bc_tbls: pointer to the byte count table of the scheduler
@@ -215,6 +245,10 @@ struct iwl_tx_queue {
* queue_stop_count: tracks what SW queue is stopped
* @pci_dev: basic pci-network driver stuff
* @hw_base: pci hardware address support
+ * @ucode_write_complete: indicates that the ucode has been copied.
+ * @ucode_write_waitq: wait queue for uCode load
+ * @status - transport specific status flags
+ * @cmd_queue - command queue number
*/
struct iwl_trans_pcie {
struct iwl_rx_queue rxq;
@@ -231,6 +265,7 @@ struct iwl_trans_pcie {
struct tasklet_struct irq_tasklet;
struct isr_statistics isr_stats;
+ unsigned int irq;
spinlock_t irq_lock;
u32 inta_mask;
u32 scd_base_addr;
@@ -251,6 +286,11 @@ struct iwl_trans_pcie {
/* PCI bus related data */
struct pci_dev *pci_dev;
void __iomem *hw_base;
+
+ bool ucode_write_complete;
+ wait_queue_head_t ucode_write_waitq;
+ unsigned long status;
+ u8 cmd_queue;
};
#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
@@ -285,7 +325,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id);
int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
void iwl_tx_cmd_complete(struct iwl_trans *trans,
- struct iwl_rx_mem_buffer *rxb, int handler_status);
+ struct iwl_rx_cmd_buffer *rxb, int handler_status);
void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
struct iwl_tx_queue *txq,
u16 byte_cnt);
@@ -318,7 +358,8 @@ void iwl_dump_csr(struct iwl_trans *trans);
******************************************************/
static inline void iwl_disable_interrupts(struct iwl_trans *trans)
{
- clear_bit(STATUS_INT_ENABLED, &trans->shrd->status);
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ clear_bit(STATUS_INT_ENABLED, &trans_pcie->status);
/* disable interrupts from uCode/NIC to host */
iwl_write32(trans, CSR_INT_MASK, 0x00000000);
@@ -332,14 +373,19 @@ static inline void iwl_disable_interrupts(struct iwl_trans *trans)
static inline void iwl_enable_interrupts(struct iwl_trans *trans)
{
- struct iwl_trans_pcie *trans_pcie =
- IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
IWL_DEBUG_ISR(trans, "Enabling interrupts\n");
- set_bit(STATUS_INT_ENABLED, &trans->shrd->status);
+ set_bit(STATUS_INT_ENABLED, &trans_pcie->status);
iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
}
+static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
+{
+ IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n");
+ iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
+}
+
/*
* we have 8 bits used like this:
*
@@ -365,7 +411,7 @@ static inline u8 iwl_get_queue_ac(struct iwl_tx_queue *txq)
}
static inline void iwl_wake_queue(struct iwl_trans *trans,
- struct iwl_tx_queue *txq, const char *msg)
+ struct iwl_tx_queue *txq)
{
u8 queue = txq->swq_id;
u8 ac = queue & 3;
@@ -376,19 +422,19 @@ static inline void iwl_wake_queue(struct iwl_trans *trans,
if (test_and_clear_bit(hwq, trans_pcie->queue_stopped)) {
if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0) {
iwl_op_mode_queue_not_full(trans->op_mode, ac);
- IWL_DEBUG_TX_QUEUES(trans, "Wake hwq %d ac %d. %s",
- hwq, ac, msg);
+ IWL_DEBUG_TX_QUEUES(trans, "Wake hwq %d ac %d",
+ hwq, ac);
} else {
- IWL_DEBUG_TX_QUEUES(trans, "Don't wake hwq %d ac %d"
- " stop count %d. %s",
- hwq, ac, atomic_read(&trans_pcie->
- queue_stop_count[ac]), msg);
+ IWL_DEBUG_TX_QUEUES(trans,
+ "Don't wake hwq %d ac %d stop count %d",
+ hwq, ac,
+ atomic_read(&trans_pcie->queue_stop_count[ac]));
}
}
}
static inline void iwl_stop_queue(struct iwl_trans *trans,
- struct iwl_tx_queue *txq, const char *msg)
+ struct iwl_tx_queue *txq)
{
u8 queue = txq->swq_id;
u8 ac = queue & 3;
@@ -399,34 +445,22 @@ static inline void iwl_stop_queue(struct iwl_trans *trans,
if (!test_and_set_bit(hwq, trans_pcie->queue_stopped)) {
if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0) {
iwl_op_mode_queue_full(trans->op_mode, ac);
- IWL_DEBUG_TX_QUEUES(trans, "Stop hwq %d ac %d"
- " stop count %d. %s",
- hwq, ac, atomic_read(&trans_pcie->
- queue_stop_count[ac]), msg);
+ IWL_DEBUG_TX_QUEUES(trans,
+ "Stop hwq %d ac %d stop count %d",
+ hwq, ac,
+ atomic_read(&trans_pcie->queue_stop_count[ac]));
} else {
- IWL_DEBUG_TX_QUEUES(trans, "Don't stop hwq %d ac %d"
- " stop count %d. %s",
- hwq, ac, atomic_read(&trans_pcie->
- queue_stop_count[ac]), msg);
+ IWL_DEBUG_TX_QUEUES(trans,
+ "Don't stop hwq %d ac %d stop count %d",
+ hwq, ac,
+ atomic_read(&trans_pcie->queue_stop_count[ac]));
}
} else {
- IWL_DEBUG_TX_QUEUES(trans, "stop hwq %d, but it is stopped/ %s",
- hwq, msg);
+ IWL_DEBUG_TX_QUEUES(trans, "stop hwq %d, but it is stopped",
+ hwq);
}
}
-#ifdef ieee80211_stop_queue
-#undef ieee80211_stop_queue
-#endif
-
-#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
-
-#ifdef ieee80211_wake_queue
-#undef ieee80211_wake_queue
-#endif
-
-#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
-
static inline void iwl_txq_ctx_activate(struct iwl_trans_pcie *trans_pcie,
int txq_id)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
index 2c910fddaaf..9bc3c73af5e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
@@ -30,11 +30,9 @@
#include <linux/wait.h>
#include <linux/gfp.h>
-/*TODO: Remove include to iwl-core.h*/
-#include "iwl-core.h"
+#include "iwl-prph.h"
#include "iwl-io.h"
#include "iwl-trans-pcie-int.h"
-#include "iwl-wifi.h"
#include "iwl-op-mode.h"
#ifdef CONFIG_IWLWIFI_IDI
@@ -142,7 +140,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
if (q->need_update == 0)
goto exit_unlock;
- if (hw_params(trans).shadow_reg_enable) {
+ if (cfg(trans)->base_params->shadow_reg_enable) {
/* shadow register enabled */
/* Device expects a multiple of 8 */
q->write_actual = (q->write & ~0x7);
@@ -358,6 +356,113 @@ void iwl_bg_rx_replenish(struct work_struct *data)
iwlagn_rx_replenish(trans_pcie->trans);
}
+static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
+ struct iwl_rx_mem_buffer *rxb)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_rx_queue *rxq = &trans_pcie->rxq;
+ struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
+ struct iwl_device_cmd *cmd;
+ unsigned long flags;
+ int len, err;
+ u16 sequence;
+ struct iwl_rx_cmd_buffer rxcb;
+ struct iwl_rx_packet *pkt;
+ bool reclaim;
+ int index, cmd_index;
+
+ if (WARN_ON(!rxb))
+ return;
+
+ dma_unmap_page(trans->dev, rxb->page_dma,
+ PAGE_SIZE << hw_params(trans).rx_page_order,
+ DMA_FROM_DEVICE);
+
+ rxcb._page = rxb->page;
+ pkt = rxb_addr(&rxcb);
+
+ IWL_DEBUG_RX(trans, "%s, 0x%02x\n",
+ get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
+
+
+ len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
+ len += sizeof(u32); /* account for status word */
+ trace_iwlwifi_dev_rx(trans->dev, pkt, len);
+
+ /* Reclaim a command buffer only if this packet is a response
+ * to a (driver-originated) command.
+ * If the packet (e.g. Rx frame) originated from uCode,
+ * there is no command buffer to reclaim.
+ * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
+ * but apparently a few don't get set; catch them here. */
+ reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
+ (pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
+ (pkt->hdr.cmd != REPLY_RX) &&
+ (pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
+ (pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
+ (pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
+ (pkt->hdr.cmd != REPLY_TX);
+
+ sequence = le16_to_cpu(pkt->hdr.sequence);
+ index = SEQ_TO_INDEX(sequence);
+ cmd_index = get_cmd_index(&txq->q, index);
+
+ if (reclaim)
+ cmd = txq->cmd[cmd_index];
+ else
+ cmd = NULL;
+
+ /* warn if this is cmd response / notification and the uCode
+ * didn't set the SEQ_RX_FRAME for a frame that is
+ * uCode-originated
+ * If you saw this code after the second half of 2012, then
+ * please remove it
+ */
+ WARN(pkt->hdr.cmd != REPLY_TX && reclaim == false &&
+ (!(pkt->hdr.sequence & SEQ_RX_FRAME)),
+ "reclaim is false, SEQ_RX_FRAME unset: %s\n",
+ get_cmd_string(pkt->hdr.cmd));
+
+ err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd);
+
+ /*
+ * XXX: After here, we should always check rxcb._page
+ * against NULL before touching it or its virtual
+ * memory (pkt). Because some rx_handler might have
+ * already taken or freed the pages.
+ */
+
+ if (reclaim) {
+ /* Invoke any callbacks, transfer the buffer to caller,
+ * and fire off the (possibly) blocking
+ * iwl_trans_send_cmd()
+ * as we reclaim the driver command queue */
+ if (rxcb._page)
+ iwl_tx_cmd_complete(trans, &rxcb, err);
+ else
+ IWL_WARN(trans, "Claim null rxb?\n");
+ }
+
+ /* page was stolen from us */
+ if (rxcb._page == NULL)
+ rxb->page = NULL;
+
+ /* Reuse the page if possible. For notification packets and
+ * SKBs that fail to Rx correctly, add them back into the
+ * rx_free list for reuse later. */
+ spin_lock_irqsave(&rxq->lock, flags);
+ if (rxb->page != NULL) {
+ rxb->page_dma =
+ dma_map_page(trans->dev, rxb->page, 0,
+ PAGE_SIZE << hw_params(trans).rx_page_order,
+ DMA_FROM_DEVICE);
+ list_add_tail(&rxb->list, &rxq->rx_free);
+ rxq->free_count++;
+ } else
+ list_add_tail(&rxb->list, &rxq->rx_used);
+ spin_unlock_irqrestore(&rxq->lock, flags);
+}
+
/**
* iwl_rx_handle - Main entry function for receiving responses from uCode
*
@@ -367,20 +472,12 @@ void iwl_bg_rx_replenish(struct work_struct *data)
*/
static void iwl_rx_handle(struct iwl_trans *trans)
{
- struct iwl_rx_mem_buffer *rxb;
- struct iwl_rx_packet *pkt;
- struct iwl_trans_pcie *trans_pcie =
- IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_rx_queue *rxq = &trans_pcie->rxq;
- struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
- struct iwl_device_cmd *cmd;
u32 r, i;
- int reclaim;
- unsigned long flags;
u8 fill_rx = 0;
u32 count = 8;
int total_empty;
- int index, cmd_index;
/* uCode's read index (stored in shared DRAM) indicates the last Rx
* buffer that the driver may process (last buffer filled by ucode). */
@@ -400,102 +497,14 @@ static void iwl_rx_handle(struct iwl_trans *trans)
fill_rx = 1;
while (i != r) {
- int len, err;
- u16 sequence;
+ struct iwl_rx_mem_buffer *rxb;
rxb = rxq->queue[i];
-
- /* If an RXB doesn't have a Rx queue slot associated with it,
- * then a bug has been introduced in the queue refilling
- * routines -- catch it here */
- if (WARN_ON(rxb == NULL)) {
- i = (i + 1) & RX_QUEUE_MASK;
- continue;
- }
-
rxq->queue[i] = NULL;
- dma_unmap_page(trans->dev, rxb->page_dma,
- PAGE_SIZE << hw_params(trans).rx_page_order,
- DMA_FROM_DEVICE);
- pkt = rxb_addr(rxb);
-
- IWL_DEBUG_RX(trans, "r = %d, i = %d, %s, 0x%02x\n", r,
- i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
-
- len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
- len += sizeof(u32); /* account for status word */
- trace_iwlwifi_dev_rx(priv(trans), pkt, len);
-
- /* Reclaim a command buffer only if this packet is a response
- * to a (driver-originated) command.
- * If the packet (e.g. Rx frame) originated from uCode,
- * there is no command buffer to reclaim.
- * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
- * but apparently a few don't get set; catch them here. */
- reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
- (pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
- (pkt->hdr.cmd != REPLY_RX) &&
- (pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
- (pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
- (pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
- (pkt->hdr.cmd != REPLY_TX);
-
- sequence = le16_to_cpu(pkt->hdr.sequence);
- index = SEQ_TO_INDEX(sequence);
- cmd_index = get_cmd_index(&txq->q, index);
-
- if (reclaim)
- cmd = txq->cmd[cmd_index];
- else
- cmd = NULL;
-
- /* warn if this is cmd response / notification and the uCode
- * didn't set the SEQ_RX_FRAME for a frame that is
- * uCode-originated
- * If you saw this code after the second half of 2012, then
- * please remove it
- */
- WARN(pkt->hdr.cmd != REPLY_TX && reclaim == false &&
- (!(pkt->hdr.sequence & SEQ_RX_FRAME)),
- "reclaim is false, SEQ_RX_FRAME unset: %s\n",
- get_cmd_string(pkt->hdr.cmd));
-
- err = iwl_op_mode_rx(trans->op_mode, rxb, cmd);
-
- /*
- * XXX: After here, we should always check rxb->page
- * against NULL before touching it or its virtual
- * memory (pkt). Because some rx_handler might have
- * already taken or freed the pages.
- */
+ IWL_DEBUG_RX(trans, "rxbuf: r = %d, i = %d (%p)\n", rxb);
- if (reclaim) {
- /* Invoke any callbacks, transfer the buffer to caller,
- * and fire off the (possibly) blocking
- * iwl_trans_send_cmd()
- * as we reclaim the driver command queue */
- if (rxb->page)
- iwl_tx_cmd_complete(trans, rxb, err);
- else
- IWL_WARN(trans, "Claim null rxb?\n");
- }
-
- /* Reuse the page if possible. For notification packets and
- * SKBs that fail to Rx correctly, add them back into the
- * rx_free list for reuse later. */
- spin_lock_irqsave(&rxq->lock, flags);
- if (rxb->page != NULL) {
- rxb->page_dma = dma_map_page(trans->dev, rxb->page,
- 0, PAGE_SIZE <<
- hw_params(trans).rx_page_order,
- DMA_FROM_DEVICE);
- list_add_tail(&rxb->list, &rxq->rx_free);
- rxq->free_count++;
- } else
- list_add_tail(&rxb->list, &rxq->rx_used);
-
- spin_unlock_irqrestore(&rxq->lock, flags);
+ iwl_rx_handle_rxbuf(trans, rxb);
i = (i + 1) & RX_QUEUE_MASK;
/* If there are a lot of unused frames,
@@ -591,17 +600,16 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
{
u32 base;
struct iwl_error_event_table table;
- struct iwl_nic *nic = nic(trans);
struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
base = trans->shrd->device_pointers.error_event_table;
if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
if (!base)
- base = nic->init_errlog_ptr;
+ base = trans->shrd->fw->init_errlog_ptr;
} else {
if (!base)
- base = nic->inst_errlog_ptr;
+ base = trans->shrd->fw->inst_errlog_ptr;
}
if (!iwlagn_hw_valid_rtc_data_addr(base)) {
@@ -623,7 +631,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
trans_pcie->isr_stats.err_code = table.error_id;
- trace_iwlwifi_dev_ucode_error(priv(nic), table.error_id, table.tsf_low,
+ trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low,
table.data1, table.data2, table.line,
table.blink1, table.blink2, table.ilink1,
table.ilink2, table.bcon_time, table.gp1,
@@ -689,7 +697,7 @@ static void iwl_irq_handle_error(struct iwl_trans *trans)
}
IWL_ERR(trans, "Loaded firmware version: %s\n",
- nic(trans)->fw.fw_version);
+ trans->shrd->fw->fw_version);
iwl_dump_nic_error_log(trans);
iwl_dump_csr(trans);
@@ -715,7 +723,6 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
u32 ptr; /* SRAM byte address of log data */
u32 ev, time, data; /* event log data */
unsigned long reg_flags;
- struct iwl_nic *nic = nic(trans);
if (num_events == 0)
return pos;
@@ -723,10 +730,10 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
base = trans->shrd->device_pointers.log_event_table;
if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
if (!base)
- base = nic->init_evtlog_ptr;
+ base = trans->shrd->fw->init_evtlog_ptr;
} else {
if (!base)
- base = nic->inst_evtlog_ptr;
+ base = trans->shrd->fw->inst_evtlog_ptr;
}
if (mode == 0)
@@ -738,11 +745,11 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
/* Make sure device is powered up for SRAM reads */
spin_lock_irqsave(&trans->reg_lock, reg_flags);
- iwl_grab_nic_access(trans);
+ if (unlikely(!iwl_grab_nic_access(trans)))
+ goto out_unlock;
/* Set starting address; reads will auto-increment */
iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr);
- rmb();
/* "time" is actually "data" for mode 0 (no timestamp).
* place event id # at far right for easier visual parsing. */
@@ -756,7 +763,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
"EVT_LOG:0x%08x:%04u\n",
time, ev);
} else {
- trace_iwlwifi_dev_ucode_event(priv(trans), 0,
+ trace_iwlwifi_dev_ucode_event(trans->dev, 0,
time, ev);
IWL_ERR(trans, "EVT_LOG:0x%08x:%04u\n",
time, ev);
@@ -770,7 +777,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
} else {
IWL_ERR(trans, "EVT_LOGT:%010u:0x%08x:%04u\n",
time, data, ev);
- trace_iwlwifi_dev_ucode_event(priv(trans), time,
+ trace_iwlwifi_dev_ucode_event(trans->dev, time,
data, ev);
}
}
@@ -778,6 +785,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
/* Allow device to power down */
iwl_release_nic_access(trans);
+out_unlock:
spin_unlock_irqrestore(&trans->reg_lock, reg_flags);
return pos;
}
@@ -832,17 +840,16 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
u32 logsize;
int pos = 0;
size_t bufsz = 0;
- struct iwl_nic *nic = nic(trans);
base = trans->shrd->device_pointers.log_event_table;
if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
- logsize = nic->init_evtlog_size;
+ logsize = trans->shrd->fw->init_evtlog_size;
if (!base)
- base = nic->init_evtlog_ptr;
+ base = trans->shrd->fw->init_evtlog_ptr;
} else {
- logsize = nic->inst_evtlog_size;
+ logsize = trans->shrd->fw->inst_evtlog_size;
if (!base)
- base = nic->inst_evtlog_ptr;
+ base = trans->shrd->fw->inst_evtlog_ptr;
}
if (!iwlagn_hw_valid_rtc_data_addr(base)) {
@@ -881,7 +888,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
}
#ifdef CONFIG_IWLWIFI_DEBUG
- if (!(iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) && !full_log)
+ if (!(iwl_have_debug_level(IWL_DL_FW_ERRORS)) && !full_log)
size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
#else
@@ -901,7 +908,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
if (!*buf)
return -ENOMEM;
}
- if ((iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) || full_log) {
+ if (iwl_have_debug_level(IWL_DL_FW_ERRORS) || full_log) {
/*
* if uCode has wrapped back to top of log,
* start at the oldest entry,
@@ -960,7 +967,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
inta = trans_pcie->inta;
#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_get_debug_level(trans->shrd) & IWL_DL_ISR) {
+ if (iwl_have_debug_level(IWL_DL_ISR)) {
/* just for debug */
inta_mask = iwl_read32(trans, CSR_INT_MASK);
IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n ",
@@ -989,7 +996,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
}
#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) {
+ if (iwl_have_debug_level(IWL_DL_ISR)) {
/* NIC fires this, but we don't use it, redundant with WAKEUP */
if (inta & CSR_INT_BIT_SCD) {
IWL_DEBUG_ISR(trans, "Scheduler finished to transmit "
@@ -1009,30 +1016,16 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
/* HW RF KILL switch toggled */
if (inta & CSR_INT_BIT_RF_KILL) {
- int hw_rf_kill = 0;
- if (!(iwl_read32(trans, CSR_GP_CNTRL) &
- CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
- hw_rf_kill = 1;
+ bool hw_rfkill;
+ hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) &
+ CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
IWL_WARN(trans, "RF_KILL bit toggled to %s.\n",
- hw_rf_kill ? "disable radio" : "enable radio");
+ hw_rfkill ? "disable radio" : "enable radio");
isr_stats->rfkill++;
- /* driver only loads ucode once setting the interface up.
- * the driver allows loading the ucode even if the radio
- * is killed. Hence update the killswitch state here. The
- * rfkill handler will care about restarting if needed.
- */
- if (!test_bit(STATUS_ALIVE, &trans->shrd->status)) {
- if (hw_rf_kill)
- set_bit(STATUS_RF_KILL_HW,
- &trans->shrd->status);
- else
- clear_bit(STATUS_RF_KILL_HW,
- &trans->shrd->status);
- iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rf_kill);
- }
+ iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
handled |= CSR_INT_BIT_RF_KILL;
}
@@ -1057,7 +1050,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
if (inta & CSR_INT_BIT_WAKEUP) {
IWL_DEBUG_ISR(trans, "Wakeup interrupt\n");
iwl_rx_queue_update_write_ptr(trans, &trans_pcie->rxq);
- for (i = 0; i < hw_params(trans).max_txq_num; i++)
+ for (i = 0; i < cfg(trans)->base_params->num_of_queues; i++)
iwl_txq_update_write_ptr(trans,
&trans_pcie->txq[i]);
@@ -1122,8 +1115,8 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
isr_stats->tx++;
handled |= CSR_INT_BIT_FH_TX;
/* Wake up uCode load routine, now that load is complete */
- trans->ucode_write_complete = 1;
- wake_up(&trans->shrd->wait_command_queue);
+ trans_pcie->ucode_write_complete = true;
+ wake_up(&trans_pcie->ucode_write_waitq);
}
if (inta & ~handled) {
@@ -1138,13 +1131,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
/* Re-enable all interrupts */
/* only Re-enable if disabled by irq */
- if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status))
+ if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status))
iwl_enable_interrupts(trans);
/* Re-enable RF_KILL if it occurred */
- else if (handled & CSR_INT_BIT_RF_KILL) {
- IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n");
- iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
- }
+ else if (handled & CSR_INT_BIT_RF_KILL)
+ iwl_enable_rfkill_int(trans);
}
/******************************************************************************
@@ -1269,7 +1260,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
if (!trans)
return IRQ_NONE;
- trace_iwlwifi_dev_irq(priv(trans));
+ trace_iwlwifi_dev_irq(trans->dev);
trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -1301,7 +1292,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
}
#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) {
+ if (iwl_have_debug_level(IWL_DL_ISR)) {
inta_fh = iwl_read32(trans, CSR_FH_INT_STATUS);
IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x, "
"fh 0x%08x\n", inta, inta_mask, inta_fh);
@@ -1312,7 +1303,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
/* iwl_irq_tasklet() will service interrupts and re-enable them */
if (likely(inta))
tasklet_schedule(&trans_pcie->irq_tasklet);
- else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
+ else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
!trans_pcie->inta)
iwl_enable_interrupts(trans);
@@ -1323,7 +1314,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
none:
/* re-enable interrupts here since we don't have anything to service. */
/* only Re-enable if disabled by irq and no schedules tasklet. */
- if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
+ if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
!trans_pcie->inta)
iwl_enable_interrupts(trans);
@@ -1359,7 +1350,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
if (!trans_pcie->use_ict)
return iwl_isr(irq, data);
- trace_iwlwifi_dev_irq(priv(trans));
+ trace_iwlwifi_dev_irq(trans->dev);
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
@@ -1376,7 +1367,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
* This may be due to IRQ shared with another device,
* or due to sporadic interrupts thrown from our NIC. */
read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
- trace_iwlwifi_dev_ict_read(priv(trans), trans_pcie->ict_index, read);
+ trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, read);
if (!read) {
IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
goto none;
@@ -1395,7 +1386,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT);
read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
- trace_iwlwifi_dev_ict_read(priv(trans), trans_pcie->ict_index,
+ trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index,
read);
} while (read);
@@ -1423,7 +1414,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
/* iwl_irq_tasklet() will service interrupts and re-enable them */
if (likely(inta))
tasklet_schedule(&trans_pcie->irq_tasklet);
- else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
+ else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
!trans_pcie->inta) {
/* Allow interrupt if was disabled by this handler and
* no tasklet was schedules, We should not enable interrupt,
@@ -1439,7 +1430,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
/* re-enable interrupts here since we don't have anything to service.
* only Re-enable if disabled by irq.
*/
- if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
+ if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
!trans_pcie->inta)
iwl_enable_interrupts(trans);
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
index 4e1e74e1b79..eb430b6e1cd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
@@ -41,6 +41,43 @@
#define IWL_TX_CRC_SIZE 4
#define IWL_TX_DELIMITER_SIZE 4
+/*
+ * mac80211 queues, ACs, hardware queues, FIFOs.
+ *
+ * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
+ *
+ * Mac80211 uses the following numbers, which we get as from it
+ * by way of skb_get_queue_mapping(skb):
+ *
+ * VO 0
+ * VI 1
+ * BE 2
+ * BK 3
+ *
+ *
+ * Regular (not A-MPDU) frames are put into hardware queues corresponding
+ * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
+ * own queue per aggregation session (RA/TID combination), such queues are
+ * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
+ * order to map frames to the right queue, we also need an AC->hw queue
+ * mapping. This is implemented here.
+ *
+ * Due to the way hw queues are set up (by the hw specific code), the AC->hw
+ * queue mapping is the identity mapping.
+ */
+
+static const u8 tid_to_ac[] = {
+ IEEE80211_AC_BE,
+ IEEE80211_AC_BK,
+ IEEE80211_AC_BK,
+ IEEE80211_AC_BE,
+ IEEE80211_AC_VI,
+ IEEE80211_AC_VI,
+ IEEE80211_AC_VO,
+ IEEE80211_AC_VO
+};
+
+
/**
* iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
*/
@@ -99,7 +136,7 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq)
if (txq->need_update == 0)
return;
- if (hw_params(trans).shadow_reg_enable) {
+ if (cfg(trans)->base_params->shadow_reg_enable) {
/* shadow register enabled */
iwl_write32(trans, HBUS_TARG_WRPTR,
txq->q.write_ptr | (txq_id << 8));
@@ -217,6 +254,8 @@ void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
{
struct iwl_tfd *tfd_tmp = txq->tfds;
+ lockdep_assert_held(&txq->lock);
+
iwlagn_unmap_tfd(trans, &txq->meta[index], &tfd_tmp[index], dma_dir);
/* free SKB */
@@ -358,7 +397,7 @@ static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans,
WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
- if (txq_id != trans->shrd->cmd_queue)
+ if (txq_id != trans_pcie->cmd_queue)
sta_id = tx_cmd->sta_id;
bc_ent = cpu_to_le16(1 | (sta_id << 12));
@@ -440,6 +479,15 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
scd_retry ? "BA" : "AC/CMD", txq_id);
}
+static inline int get_ac_from_tid(u16 tid)
+{
+ if (likely(tid < ARRAY_SIZE(tid_to_ac)))
+ return tid_to_ac[tid];
+
+ /* no support for TIDs 8-15 yet */
+ return -EINVAL;
+}
+
static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie,
u8 ctx, u16 tid)
{
@@ -547,7 +595,8 @@ static int iwlagn_txq_ctx_activate_free(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int txq_id;
- for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++)
+ for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues;
+ txq_id++)
if (!test_and_set_bit(txq_id,
&trans_pcie->txq_ctx_active_msk))
return txq_id;
@@ -616,15 +665,13 @@ int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int sta_id, int tid)
static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
+ struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
struct iwl_queue *q = &txq->q;
struct iwl_device_cmd *out_cmd;
struct iwl_cmd_meta *out_meta;
dma_addr_t phys_addr;
- unsigned long flags;
u32 idx;
u16 copy_size, cmd_size;
- bool is_ct_kill = false;
bool had_nocopy = false;
int i;
u8 *cmd_dest;
@@ -639,12 +686,6 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
return -EIO;
}
- if ((trans->shrd->ucode_owner == IWL_OWNERSHIP_TM) &&
- !(cmd->flags & CMD_ON_DEMAND)) {
- IWL_DEBUG_HC(trans, "tm own the uCode, no regular hcmd send\n");
- return -EIO;
- }
-
copy_size = sizeof(out_cmd->hdr);
cmd_size = sizeof(out_cmd->hdr);
@@ -674,23 +715,13 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE))
return -EINVAL;
- if (iwl_is_rfkill(trans->shrd) || iwl_is_ctkill(trans->shrd)) {
- IWL_WARN(trans, "Not sending command - %s KILL\n",
- iwl_is_rfkill(trans->shrd) ? "RF" : "CT");
- return -EIO;
- }
-
- spin_lock_irqsave(&trans->hcmd_lock, flags);
+ spin_lock_bh(&txq->lock);
if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
- spin_unlock_irqrestore(&trans->hcmd_lock, flags);
+ spin_unlock_bh(&txq->lock);
IWL_ERR(trans, "No space in command queue\n");
- is_ct_kill = iwl_check_for_ct_kill(priv(trans));
- if (!is_ct_kill) {
- IWL_ERR(trans, "Restarting adapter queue is full\n");
- iwl_op_mode_nic_error(trans->op_mode);
- }
+ iwl_op_mode_cmd_queue_full(trans->op_mode);
return -ENOSPC;
}
@@ -707,7 +738,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
out_cmd->hdr.cmd = cmd->id;
out_cmd->hdr.flags = 0;
out_cmd->hdr.sequence =
- cpu_to_le16(QUEUE_TO_SEQ(trans->shrd->cmd_queue) |
+ cpu_to_le16(QUEUE_TO_SEQ(trans_pcie->cmd_queue) |
INDEX_TO_SEQ(q->write_ptr));
/* and copy the data that needs to be copied */
@@ -727,7 +758,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
get_cmd_string(out_cmd->hdr.cmd),
out_cmd->hdr.cmd,
le16_to_cpu(out_cmd->hdr.sequence), cmd_size,
- q->write_ptr, idx, trans->shrd->cmd_queue);
+ q->write_ptr, idx, trans_pcie->cmd_queue);
phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size,
DMA_BIDIRECTIONAL);
@@ -779,7 +810,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
/* check that tracing gets all possible blocks */
BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3);
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
- trace_iwlwifi_dev_hcmd(priv(trans), cmd->flags,
+ trace_iwlwifi_dev_hcmd(trans->dev, cmd->flags,
trace_bufs[0], trace_lens[0],
trace_bufs[1], trace_lens[1],
trace_bufs[2], trace_lens[2]);
@@ -790,7 +821,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
iwl_txq_update_write_ptr(trans, txq);
out:
- spin_unlock_irqrestore(&trans->hcmd_lock, flags);
+ spin_unlock_bh(&txq->lock);
return idx;
}
@@ -809,6 +840,8 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id,
struct iwl_queue *q = &txq->q;
int nfreed = 0;
+ lockdep_assert_held(&txq->lock);
+
if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
IWL_ERR(trans, "%s: Read index for DMA queue txq id (%d), "
"index %d is out of range [0-%d] %d %d.\n", __func__,
@@ -838,7 +871,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id,
* will be executed. The attached skb (if present) will only be freed
* if the callback returns 1
*/
-void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb,
+void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb,
int handler_status)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -849,21 +882,22 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb,
struct iwl_device_cmd *cmd;
struct iwl_cmd_meta *meta;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
- unsigned long flags;
+ struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
/* If a Tx command is being handled and it isn't in the actual
* command queue then there a command routing bug has been introduced
* in the queue management code. */
- if (WARN(txq_id != trans->shrd->cmd_queue,
+ if (WARN(txq_id != trans_pcie->cmd_queue,
"wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
- txq_id, trans->shrd->cmd_queue, sequence,
- trans_pcie->txq[trans->shrd->cmd_queue].q.read_ptr,
- trans_pcie->txq[trans->shrd->cmd_queue].q.write_ptr)) {
+ txq_id, trans_pcie->cmd_queue, sequence,
+ trans_pcie->txq[trans_pcie->cmd_queue].q.read_ptr,
+ trans_pcie->txq[trans_pcie->cmd_queue].q.write_ptr)) {
iwl_print_hex_error(trans, pkt, 32);
return;
}
+ spin_lock(&txq->lock);
+
cmd_index = get_cmd_index(&txq->q, index);
cmd = txq->cmd[cmd_index];
meta = &txq->meta[cmd_index];
@@ -875,13 +909,14 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb,
/* Input error checking is done when commands are added to queue. */
if (meta->flags & CMD_WANT_SKB) {
- meta->source->reply_page = (unsigned long)rxb_addr(rxb);
+ struct page *p = rxb_steal_page(rxb);
+
+ meta->source->resp_pkt = pkt;
+ meta->source->_rx_page_addr = (unsigned long)page_address(p);
+ meta->source->_rx_page_order = hw_params(trans).rx_page_order;
meta->source->handler_status = handler_status;
- rxb->page = NULL;
}
- spin_lock_irqsave(&trans->hcmd_lock, flags);
-
iwl_hcmd_queue_reclaim(trans, txq_id, index);
if (!(meta->flags & CMD_ASYNC)) {
@@ -898,7 +933,7 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb,
meta->flags = 0;
- spin_unlock_irqrestore(&trans->hcmd_lock, flags);
+ spin_unlock(&txq->lock);
}
#define HOST_COMPLETE_TIMEOUT (2 * HZ)
@@ -912,12 +947,9 @@ static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
return -EINVAL;
- if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status))
- return -EBUSY;
-
ret = iwl_enqueue_hcmd(trans, cmd);
if (ret < 0) {
- IWL_DEBUG_QUIET_RFKILL(trans,
+ IWL_ERR(trans,
"Error sending %s: enqueue_hcmd failed: %d\n",
get_cmd_string(cmd->id), ret);
return ret;
@@ -931,26 +963,22 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
int cmd_idx;
int ret;
- lockdep_assert_held(&trans->shrd->mutex);
-
IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n",
get_cmd_string(cmd->id));
- if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status))
- return -EBUSY;
-
-
- if (test_bit(STATUS_RF_KILL_HW, &trans->shrd->status)) {
- IWL_ERR(trans, "Command %s aborted: RF KILL Switch\n",
- get_cmd_string(cmd->id));
- return -ECANCELED;
- }
if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) {
IWL_ERR(trans, "Command %s failed: FW Error\n",
get_cmd_string(cmd->id));
return -EIO;
}
- set_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
+
+ if (WARN_ON(test_and_set_bit(STATUS_HCMD_ACTIVE,
+ &trans->shrd->status))) {
+ IWL_ERR(trans, "Command %s: a command is already active!\n",
+ get_cmd_string(cmd->id));
+ return -EIO;
+ }
+
IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n",
get_cmd_string(cmd->id));
@@ -958,7 +986,7 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
if (cmd_idx < 0) {
ret = cmd_idx;
clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
- IWL_DEBUG_QUIET_RFKILL(trans,
+ IWL_ERR(trans,
"Error sending %s: enqueue_hcmd failed: %d\n",
get_cmd_string(cmd->id), ret);
return ret;
@@ -970,15 +998,15 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
if (!ret) {
if (test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status)) {
struct iwl_tx_queue *txq =
- &trans_pcie->txq[trans->shrd->cmd_queue];
+ &trans_pcie->txq[trans_pcie->cmd_queue];
struct iwl_queue *q = &txq->q;
- IWL_DEBUG_QUIET_RFKILL(trans,
+ IWL_ERR(trans,
"Error sending %s: time out after %dms.\n",
get_cmd_string(cmd->id),
jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
- IWL_DEBUG_QUIET_RFKILL(trans,
+ IWL_ERR(trans,
"Current CMD queue read_ptr %d write_ptr %d\n",
q->read_ptr, q->write_ptr);
@@ -990,7 +1018,7 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
}
}
- if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
+ if ((cmd->flags & CMD_WANT_SKB) && !cmd->resp_pkt) {
IWL_ERR(trans, "Error: Response NULL in '%s'\n",
get_cmd_string(cmd->id));
ret = -EIO;
@@ -1007,13 +1035,13 @@ cancel:
* in later, it will possibly set an invalid
* address (cmd->meta.source).
*/
- trans_pcie->txq[trans->shrd->cmd_queue].meta[cmd_idx].flags &=
+ trans_pcie->txq[trans_pcie->cmd_queue].meta[cmd_idx].flags &=
~CMD_WANT_SKB;
}
- if (cmd->reply_page) {
- iwl_free_pages(trans->shrd, cmd->reply_page);
- cmd->reply_page = 0;
+ if (cmd->resp_pkt) {
+ iwl_free_resp(cmd);
+ cmd->resp_pkt = NULL;
}
return ret;
@@ -1038,9 +1066,11 @@ int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
int freed = 0;
/* This function is not meant to release cmd queue*/
- if (WARN_ON(txq_id == trans->shrd->cmd_queue))
+ if (WARN_ON(txq_id == trans_pcie->cmd_queue))
return 0;
+ lockdep_assert_held(&txq->lock);
+
/*Since we free until index _not_ inclusive, the one before index is
* the last we will free. This one must be used */
last_to_free = iwl_queue_dec_wrap(index, q->n_bd);
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
index 9f8b2390940..91628565409 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
@@ -75,8 +75,12 @@
#include "iwl-shared.h"
#include "iwl-eeprom.h"
#include "iwl-agn-hw.h"
-#include "iwl-core.h"
-#include "iwl-ucode.h"
+
+#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
+
+#define SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie) \
+ (((1<<cfg(trans)->base_params->num_of_queues) - 1) &\
+ (~(1<<(trans_pcie)->cmd_queue)))
static int iwl_trans_rx_alloc(struct iwl_trans *trans)
{
@@ -301,6 +305,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans,
{
size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX;
int i;
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
if (WARN_ON(txq->meta || txq->cmd || txq->skbs || txq->tfds))
return -EINVAL;
@@ -313,7 +318,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans,
if (!txq->meta || !txq->cmd)
goto error;
- if (txq_id == trans->shrd->cmd_queue)
+ if (txq_id == trans_pcie->cmd_queue)
for (i = 0; i < slots_num; i++) {
txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd),
GFP_KERNEL);
@@ -324,7 +329,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans,
/* Alloc driver data array and TFD circular buffer */
/* Driver private data, only for Tx (not command) queues,
* not shared with device. */
- if (txq_id != trans->shrd->cmd_queue) {
+ if (txq_id != trans_pcie->cmd_queue) {
txq->skbs = kcalloc(TFD_QUEUE_SIZE_MAX, sizeof(txq->skbs[0]),
GFP_KERNEL);
if (!txq->skbs) {
@@ -352,7 +357,7 @@ error:
txq->skbs = NULL;
/* since txq->cmd has been zeroed,
* all non allocated cmd[i] will be NULL */
- if (txq->cmd && txq_id == trans->shrd->cmd_queue)
+ if (txq->cmd && txq_id == trans_pcie->cmd_queue)
for (i = 0; i < slots_num; i++)
kfree(txq->cmd[i]);
kfree(txq->meta);
@@ -390,6 +395,8 @@ static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq,
if (ret)
return ret;
+ spin_lock_init(&txq->lock);
+
/*
* Tell nic where to find circular buffer of Tx Frame Descriptors for
* given Tx queue, and enable the DMA channel used for that queue.
@@ -409,8 +416,6 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id)
struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
struct iwl_queue *q = &txq->q;
enum dma_data_direction dma_dir;
- unsigned long flags;
- spinlock_t *lock;
if (!q->n_bd)
return;
@@ -418,22 +423,19 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id)
/* In the command queue, all the TBs are mapped as BIDI
* so unmap them as such.
*/
- if (txq_id == trans->shrd->cmd_queue) {
+ if (txq_id == trans_pcie->cmd_queue)
dma_dir = DMA_BIDIRECTIONAL;
- lock = &trans->hcmd_lock;
- } else {
+ else
dma_dir = DMA_TO_DEVICE;
- lock = &trans->shrd->sta_lock;
- }
- spin_lock_irqsave(lock, flags);
+ spin_lock_bh(&txq->lock);
while (q->write_ptr != q->read_ptr) {
/* The read_ptr needs to bound by q->n_window */
iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr),
dma_dir);
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
}
- spin_unlock_irqrestore(lock, flags);
+ spin_unlock_bh(&txq->lock);
}
/**
@@ -457,7 +459,7 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id)
/* De-alloc array of command/tx buffers */
- if (txq_id == trans->shrd->cmd_queue)
+ if (txq_id == trans_pcie->cmd_queue)
for (i = 0; i < txq->q.n_window; i++)
kfree(txq->cmd[i]);
@@ -495,7 +497,7 @@ static void iwl_trans_pcie_tx_free(struct iwl_trans *trans)
/* Tx queues */
if (trans_pcie->txq) {
for (txq_id = 0;
- txq_id < hw_params(trans).max_txq_num; txq_id++)
+ txq_id < cfg(trans)->base_params->num_of_queues; txq_id++)
iwl_tx_queue_free(trans, txq_id);
}
@@ -520,7 +522,7 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans)
int txq_id, slots_num;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- u16 scd_bc_tbls_size = hw_params(trans).max_txq_num *
+ u16 scd_bc_tbls_size = cfg(trans)->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
/*It is not allowed to alloc twice, so warn when this happens.
@@ -544,7 +546,7 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans)
goto error;
}
- trans_pcie->txq = kcalloc(hw_params(trans).max_txq_num,
+ trans_pcie->txq = kcalloc(cfg(trans)->base_params->num_of_queues,
sizeof(struct iwl_tx_queue), GFP_KERNEL);
if (!trans_pcie->txq) {
IWL_ERR(trans, "Not enough memory for txq\n");
@@ -553,8 +555,9 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans)
}
/* Alloc and init all Tx queues, including the command queue (#4/#9) */
- for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) {
- slots_num = (txq_id == trans->shrd->cmd_queue) ?
+ for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues;
+ txq_id++) {
+ slots_num = (txq_id == trans_pcie->cmd_queue) ?
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
ret = iwl_trans_txq_alloc(trans, &trans_pcie->txq[txq_id],
slots_num, txq_id);
@@ -598,8 +601,9 @@ static int iwl_tx_init(struct iwl_trans *trans)
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
/* Alloc and init all Tx queues, including the command queue (#4/#9) */
- for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) {
- slots_num = (txq_id == trans->shrd->cmd_queue) ?
+ for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues;
+ txq_id++) {
+ slots_num = (txq_id == trans_pcie->cmd_queue) ?
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
ret = iwl_trans_txq_init(trans, &trans_pcie->txq[txq_id],
slots_num, txq_id);
@@ -687,6 +691,7 @@ static void iwl_apm_config(struct iwl_trans *trans)
*/
static int iwl_apm_init(struct iwl_trans *trans)
{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int ret = 0;
IWL_DEBUG_INFO(trans, "Init card's basic functions\n");
@@ -756,7 +761,7 @@ static int iwl_apm_init(struct iwl_trans *trans)
iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
- set_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status);
+ set_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status);
out:
return ret;
@@ -782,9 +787,10 @@ static int iwl_apm_stop_master(struct iwl_trans *trans)
static void iwl_apm_stop(struct iwl_trans *trans)
{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
IWL_DEBUG_INFO(trans, "Stop card, put in low power state\n");
- clear_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status);
+ clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status);
/* Stop device's DMA activity */
iwl_apm_stop_master(trans);
@@ -819,7 +825,7 @@ static int iwl_nic_init(struct iwl_trans *trans)
iwl_set_pwr_vmain(trans);
- iwl_nic_config(priv(trans));
+ iwl_op_mode_nic_config(trans->op_mode);
#ifndef CONFIG_IWLWIFI_IDI
/* Allocate the RX queue, or reset if it is already allocated */
@@ -830,14 +836,12 @@ static int iwl_nic_init(struct iwl_trans *trans)
if (iwl_tx_init(trans))
return -ENOMEM;
- if (hw_params(trans).shadow_reg_enable) {
+ if (cfg(trans)->base_params->shadow_reg_enable) {
/* enable shadow regs in HW */
iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL,
0x800FFFFF);
}
- set_bit(STATUS_INIT, &trans->shrd->status);
-
return 0;
}
@@ -948,13 +952,14 @@ static const u8 iwlagn_pan_ac_to_queue[] = {
* ucode
*/
static int iwl_load_section(struct iwl_trans *trans, const char *name,
- struct fw_desc *image, u32 dst_addr)
+ const struct fw_desc *image, u32 dst_addr)
{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
dma_addr_t phy_addr = image->p_addr;
u32 byte_cnt = image->len;
int ret;
- trans->ucode_write_complete = 0;
+ trans_pcie->ucode_write_complete = false;
iwl_write_direct32(trans,
FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
@@ -985,8 +990,8 @@ static int iwl_load_section(struct iwl_trans *trans, const char *name,
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
IWL_DEBUG_FW(trans, "%s uCode section being loaded...\n", name);
- ret = wait_event_timeout(trans->shrd->wait_command_queue,
- trans->ucode_write_complete, 5 * HZ);
+ ret = wait_event_timeout(trans_pcie->ucode_write_waitq,
+ trans_pcie->ucode_write_complete, 5 * HZ);
if (!ret) {
IWL_ERR(trans, "Could not load the %s uCode section\n",
name);
@@ -996,7 +1001,8 @@ static int iwl_load_section(struct iwl_trans *trans, const char *name,
return 0;
}
-static int iwl_load_given_ucode(struct iwl_trans *trans, struct fw_img *image)
+static int iwl_load_given_ucode(struct iwl_trans *trans,
+ const struct fw_img *image)
{
int ret = 0;
@@ -1016,13 +1022,14 @@ static int iwl_load_given_ucode(struct iwl_trans *trans, struct fw_img *image)
return 0;
}
-static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, struct fw_img *fw)
+static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
+ const struct fw_img *fw)
{
int ret;
struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
+ bool hw_rfkill;
- trans->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER;
trans_pcie->ac_to_queue[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_queue;
trans_pcie->ac_to_queue[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_queue;
@@ -1032,22 +1039,19 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, struct fw_img *fw)
trans_pcie->mcast_queue[IWL_RXON_CTX_BSS] = 0;
trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE;
- if ((hw_params(trans).sku & EEPROM_SKU_CAP_AMT_ENABLE) &&
- iwl_prepare_card_hw(trans)) {
+ /* This may fail if AMT took ownership of the device */
+ if (iwl_prepare_card_hw(trans)) {
IWL_WARN(trans, "Exit HW not ready\n");
return -EIO;
}
/* If platform's RF_KILL switch is NOT set to KILL */
- if (iwl_read32(trans, CSR_GP_CNTRL) &
- CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
- clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
- else
- set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
+ hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) &
+ CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
+ iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
- if (iwl_is_rfkill(trans->shrd)) {
- iwl_op_mode_hw_rf_kill(trans->op_mode, true);
- iwl_enable_interrupts(trans);
+ if (hw_rfkill) {
+ iwl_enable_rfkill_int(trans);
return -ERFKILL;
}
@@ -1073,9 +1077,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, struct fw_img *fw)
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
/* Load the given image to the HW */
- iwl_load_given_ucode(trans, fw);
-
- return 0;
+ return iwl_load_given_ucode(trans, fw);
}
/*
@@ -1116,7 +1118,8 @@ static void iwl_tx_start(struct iwl_trans *trans)
a += 4)
iwl_write_targ_mem(trans, a, 0);
for (; a < trans_pcie->scd_base_addr +
- SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(trans).max_txq_num);
+ SCD_TRANS_TBL_OFFSET_QUEUE(
+ cfg(trans)->base_params->num_of_queues);
a += 4)
iwl_write_targ_mem(trans, a, 0);
@@ -1135,11 +1138,11 @@ static void iwl_tx_start(struct iwl_trans *trans)
reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
iwl_write_prph(trans, SCD_QUEUECHAIN_SEL,
- SCD_QUEUECHAIN_SEL_ALL(trans));
+ SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie));
iwl_write_prph(trans, SCD_AGGR_SEL, 0);
/* initiate the queues */
- for (i = 0; i < hw_params(trans).max_txq_num; i++) {
+ for (i = 0; i < cfg(trans)->base_params->num_of_queues; i++) {
iwl_write_prph(trans, SCD_QUEUE_RDPTR(i), 0);
iwl_write_direct32(trans, HBUS_TARG_WRPTR, 0 | (i << 8));
iwl_write_targ_mem(trans, trans_pcie->scd_base_addr +
@@ -1156,7 +1159,7 @@ static void iwl_tx_start(struct iwl_trans *trans)
}
iwl_write_prph(trans, SCD_INTERRUPT_MASK,
- IWL_MASK(0, hw_params(trans).max_txq_num));
+ IWL_MASK(0, cfg(trans)->base_params->num_of_queues));
/* Activate all Tx DMA/FIFO channels */
iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7));
@@ -1167,7 +1170,7 @@ static void iwl_tx_start(struct iwl_trans *trans)
else
queue_to_fifo = iwlagn_default_queue_to_tx_fifo;
- iwl_trans_set_wr_ptrs(trans, trans->shrd->cmd_queue, 0);
+ iwl_trans_set_wr_ptrs(trans, trans_pcie->cmd_queue, 0);
/* make sure all queue are not stopped */
memset(&trans_pcie->queue_stopped[0], 0,
@@ -1216,7 +1219,7 @@ static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans)
*/
static int iwl_trans_tx_stop(struct iwl_trans *trans)
{
- int ch, txq_id;
+ int ch, txq_id, ret;
unsigned long flags;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -1229,9 +1232,10 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) {
iwl_write_direct32(trans,
FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
- if (iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG,
+ ret = iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG,
FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
- 1000))
+ 1000);
+ if (ret < 0)
IWL_ERR(trans, "Failing on timeout while stopping"
" DMA channel %d [0x%08x]", ch,
iwl_read_direct32(trans,
@@ -1245,7 +1249,8 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
}
/* Unmap DMA from host system and free skb's */
- for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++)
+ for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues;
+ txq_id++)
iwl_tx_queue_unmap(trans, txq_id);
return 0;
@@ -1271,7 +1276,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
* restart. So don't process again if the device is
* already dead.
*/
- if (test_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status)) {
+ if (test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) {
iwl_trans_tx_stop(trans);
#ifndef CONFIG_IWLWIFI_IDI
iwl_trans_rx_stop(trans);
@@ -1297,7 +1302,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
/* wait to make sure we flush pending tasklet*/
- synchronize_irq(trans->irq);
+ synchronize_irq(trans_pcie->irq);
tasklet_kill(&trans_pcie->irq_tasklet);
cancel_work_sync(&trans_pcie->rx_replenish);
@@ -1306,6 +1311,17 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
}
+static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans)
+{
+ /* let the ucode operate on its own */
+ iwl_write32(trans, CSR_UCODE_DRV_GP1_SET,
+ CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
+
+ iwl_disable_interrupts(trans);
+ iwl_clear_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+}
+
static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
u8 sta_id, u8 tid)
@@ -1358,6 +1374,8 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
txq = &trans_pcie->txq[txq_id];
q = &txq->q;
+ spin_lock(&txq->lock);
+
/* In AGG mode, the index in the ring must correspond to the WiFi
* sequence number. This is a HW requirements to help the SCD to parse
* the BA.
@@ -1404,7 +1422,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
&dev_cmd->hdr, firstlen,
DMA_BIDIRECTIONAL);
if (unlikely(dma_mapping_error(trans->dev, txcmd_phys)))
- return -1;
+ goto out_err;
dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
dma_unmap_len_set(out_meta, len, firstlen);
@@ -1426,7 +1444,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
dma_unmap_addr(out_meta, mapping),
dma_unmap_len(out_meta, len),
DMA_BIDIRECTIONAL);
- return -1;
+ goto out_err;
}
}
@@ -1457,7 +1475,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen,
DMA_BIDIRECTIONAL);
- trace_iwlwifi_dev_tx(priv(trans),
+ trace_iwlwifi_dev_tx(trans->dev,
&((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
sizeof(struct iwl_tfd),
&dev_cmd->hdr, firstlen,
@@ -1478,10 +1496,14 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
txq->need_update = 1;
iwl_txq_update_write_ptr(trans, txq);
} else {
- iwl_stop_queue(trans, txq, "Queue is full");
+ iwl_stop_queue(trans, txq);
}
}
+ spin_unlock(&txq->lock);
return 0;
+ out_err:
+ spin_unlock(&txq->lock);
+ return -1;
}
static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
@@ -1489,6 +1511,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
int err;
+ bool hw_rfkill;
trans_pcie->inta_mask = CSR_INI_SET_MASK;
@@ -1498,11 +1521,11 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
iwl_alloc_isr_ict(trans);
- err = request_irq(trans->irq, iwl_isr_ict, IRQF_SHARED,
+ err = request_irq(trans_pcie->irq, iwl_isr_ict, IRQF_SHARED,
DRV_NAME, trans);
if (err) {
IWL_ERR(trans, "Error allocating IRQ %d\n",
- trans->irq);
+ trans_pcie->irq);
goto error;
}
@@ -1518,21 +1541,14 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
iwl_apm_init(trans);
- /* If platform's RF_KILL switch is NOT set to KILL */
- if (iwl_read32(trans,
- CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
- clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
- else
- set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
-
- iwl_op_mode_hw_rf_kill(trans->op_mode,
- test_bit(STATUS_RF_KILL_HW,
- &trans->shrd->status));
+ hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) &
+ CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
+ iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
return err;
err_free_irq:
- free_irq(trans->irq, trans);
+ free_irq(trans_pcie->irq, trans);
error:
iwl_free_isr_ict(trans);
tasklet_kill(&trans_pcie->irq_tasklet);
@@ -1546,13 +1562,11 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans)
iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
/* Even if we stop the HW, we still want the RF kill interrupt */
- IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n");
- iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
+ iwl_enable_rfkill_int(trans);
}
static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
- int txq_id, int ssn, u32 status,
- struct sk_buff_head *skbs)
+ int txq_id, int ssn, struct sk_buff_head *skbs)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
@@ -1560,6 +1574,8 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
int tfd_num = ssn & (txq->q.n_bd - 1);
int freed = 0;
+ spin_lock(&txq->lock);
+
txq->time_stamp = jiffies;
if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE &&
@@ -1574,6 +1590,7 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
IWL_DEBUG_TX_QUEUES(trans, "Bad queue mapping txq_id %d, "
"agg_txq[sta_id[tid] %d", txq_id,
trans_pcie->agg_txq[sta_id][tid]);
+ spin_unlock(&txq->lock);
return 1;
}
@@ -1582,28 +1599,35 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
txq_id, iwl_get_queue_ac(txq), txq->q.read_ptr,
tfd_num, ssn);
freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
- if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
- (!txq->sched_retry ||
- status != TX_STATUS_FAIL_PASSIVE_NO_RX))
- iwl_wake_queue(trans, txq, "Packets reclaimed");
+ if (iwl_queue_space(&txq->q) > txq->q.low_mark)
+ iwl_wake_queue(trans, txq);
}
+
+ spin_unlock(&txq->lock);
return 0;
}
static void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val)
{
- iowrite8(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
+ writeb(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
}
static void iwl_trans_pcie_write32(struct iwl_trans *trans, u32 ofs, u32 val)
{
- iowrite32(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
+ writel(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
}
static u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs)
{
- u32 val = ioread32(IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
- return val;
+ return readl(IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
+}
+
+static void iwl_trans_pcie_configure(struct iwl_trans *trans,
+ const struct iwl_trans_config *trans_cfg)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ trans_pcie->cmd_queue = trans_cfg->cmd_queue;
}
static void iwl_trans_pcie_free(struct iwl_trans *trans)
@@ -1611,18 +1635,17 @@ static void iwl_trans_pcie_free(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
- iwl_calib_free_results(trans);
iwl_trans_pcie_tx_free(trans);
#ifndef CONFIG_IWLWIFI_IDI
iwl_trans_pcie_rx_free(trans);
#endif
if (trans_pcie->irq_requested == true) {
- free_irq(trans->irq, trans);
+ free_irq(trans_pcie->irq, trans);
iwl_free_isr_ict(trans);
}
pci_disable_msi(trans_pcie->pci_dev);
- pci_iounmap(trans_pcie->pci_dev, trans_pcie->hw_base);
+ iounmap(trans_pcie->hw_base);
pci_release_regions(trans_pcie->pci_dev);
pci_disable_device(trans_pcie->pci_dev);
@@ -1633,42 +1656,20 @@ static void iwl_trans_pcie_free(struct iwl_trans *trans)
#ifdef CONFIG_PM_SLEEP
static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
{
- /*
- * This function is called when system goes into suspend state
- * mac80211 will call iwlagn_mac_stop() from the mac80211 suspend
- * function first but since iwlagn_mac_stop() has no knowledge of
- * who the caller is,
- * it will not call apm_ops.stop() to stop the DMA operation.
- * Calling apm_ops.stop here to make sure we stop the DMA.
- *
- * But of course ... if we have configured WoWLAN then we did other
- * things already :-)
- */
- if (!trans->shrd->wowlan) {
- iwl_apm_stop(trans);
- } else {
- iwl_disable_interrupts(trans);
- iwl_clear_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- }
-
return 0;
}
static int iwl_trans_pcie_resume(struct iwl_trans *trans)
{
- bool hw_rfkill = false;
-
- iwl_enable_interrupts(trans);
+ bool hw_rfkill;
- if (!(iwl_read32(trans, CSR_GP_CNTRL) &
- CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
- hw_rfkill = true;
+ hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) &
+ CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
if (hw_rfkill)
- set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
+ iwl_enable_rfkill_int(trans);
else
- clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
+ iwl_enable_interrupts(trans);
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
@@ -1676,32 +1677,6 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans)
}
#endif /* CONFIG_PM_SLEEP */
-static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans,
- enum iwl_rxon_context_id ctx,
- const char *msg)
-{
- u8 ac, txq_id;
- struct iwl_trans_pcie *trans_pcie =
- IWL_TRANS_GET_PCIE_TRANS(trans);
-
- for (ac = 0; ac < AC_NUM; ac++) {
- txq_id = trans_pcie->ac_to_queue[ctx][ac];
- IWL_DEBUG_TX_QUEUES(trans, "Queue Status: Q[%d] %s\n",
- ac,
- (atomic_read(&trans_pcie->queue_stop_count[ac]) > 0)
- ? "stopped" : "awake");
- iwl_wake_queue(trans, &trans_pcie->txq[txq_id], msg);
- }
-}
-
-static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id,
- const char *msg)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
- iwl_stop_queue(trans, &trans_pcie->txq[txq_id], msg);
-}
-
#define IWL_FLUSH_WAIT_MS 2000
static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans)
@@ -1714,8 +1689,8 @@ static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans)
int ret = 0;
/* waiting for all the tx frames complete might take a while */
- for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) {
- if (cnt == trans->shrd->cmd_queue)
+ for (cnt = 0; cnt < cfg(trans)->base_params->num_of_queues; cnt++) {
+ if (cnt == trans_pcie->cmd_queue)
continue;
txq = &trans_pcie->txq[cnt];
q = &txq->q;
@@ -1960,7 +1935,9 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
int pos = 0;
int cnt;
int ret;
- const size_t bufsz = sizeof(char) * 64 * hw_params(trans).max_txq_num;
+ size_t bufsz;
+
+ bufsz = sizeof(char) * 64 * cfg(trans)->base_params->num_of_queues;
if (!trans_pcie->txq) {
IWL_ERR(trans, "txq not ready\n");
@@ -1970,7 +1947,7 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
if (!buf)
return -ENOMEM;
- for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) {
+ for (cnt = 0; cnt < cfg(trans)->base_params->num_of_queues; cnt++) {
txq = &trans_pcie->txq[cnt];
q = &txq->q;
pos += scnprintf(buf + pos, bufsz - pos,
@@ -2219,7 +2196,7 @@ const struct iwl_trans_ops trans_ops_pcie = {
.start_fw = iwl_trans_pcie_start_fw,
.stop_device = iwl_trans_pcie_stop_device,
- .wake_any_queue = iwl_trans_pcie_wake_any_queue,
+ .wowlan_suspend = iwl_trans_pcie_wowlan_suspend,
.send_cmd = iwl_trans_pcie_send_cmd,
@@ -2231,7 +2208,6 @@ const struct iwl_trans_ops trans_ops_pcie = {
.tx_agg_setup = iwl_trans_pcie_tx_agg_setup,
.free = iwl_trans_pcie_free,
- .stop_queue = iwl_trans_pcie_stop_queue,
.dbgfs_register = iwl_trans_pcie_dbgfs_register,
@@ -2245,6 +2221,7 @@ const struct iwl_trans_ops trans_ops_pcie = {
.write8 = iwl_trans_pcie_write8,
.write32 = iwl_trans_pcie_write32,
.read32 = iwl_trans_pcie_read32,
+ .configure = iwl_trans_pcie_configure,
};
struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd,
@@ -2267,8 +2244,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd,
trans->ops = &trans_ops_pcie;
trans->shrd = shrd;
trans_pcie->trans = trans;
- spin_lock_init(&trans->hcmd_lock);
spin_lock_init(&trans_pcie->irq_lock);
+ init_waitqueue_head(&trans_pcie->ucode_write_waitq);
/* W/A - seems to solve weird behavior. We need to remove this if we
* don't want to stay in L1 all the time. This wastes a lot of power */
@@ -2304,9 +2281,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd,
goto out_pci_disable_device;
}
- trans_pcie->hw_base = pci_iomap(pdev, 0, 0);
+ trans_pcie->hw_base = pci_ioremap_bar(pdev, 0);
if (!trans_pcie->hw_base) {
- dev_printk(KERN_ERR, &pdev->dev, "pci_iomap failed");
+ dev_printk(KERN_ERR, &pdev->dev, "pci_ioremap_bar failed");
err = -ENODEV;
goto out_pci_release_regions;
}
@@ -2330,7 +2307,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd,
"pci_enable_msi failed(0X%x)", err);
trans->dev = &pdev->dev;
- trans->irq = pdev->irq;
+ trans_pcie->irq = pdev->irq;
trans_pcie->pci_dev = pdev;
trans->hw_rev = iwl_read32(trans, CSR_HW_REV);
trans->hw_id = (pdev->device << 16) + pdev->subsystem_device;
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 4e7e6c0eede..7d1990c7f65 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -64,6 +64,7 @@
#define __iwl_trans_h__
#include <linux/ieee80211.h>
+#include <linux/mm.h> /* for page_address */
#include "iwl-shared.h"
#include "iwl-debug.h"
@@ -121,6 +122,62 @@ struct dentry;
#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
+#define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f)
+#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8)
+#define SEQ_TO_INDEX(s) ((s) & 0xff)
+#define INDEX_TO_SEQ(i) ((i) & 0xff)
+#define SEQ_RX_FRAME cpu_to_le16(0x8000)
+
+/**
+ * struct iwl_cmd_header
+ *
+ * This header format appears in the beginning of each command sent from the
+ * driver, and each response/notification received from uCode.
+ */
+struct iwl_cmd_header {
+ u8 cmd; /* Command ID: REPLY_RXON, etc. */
+ u8 flags; /* 0:5 reserved, 6 abort, 7 internal */
+ /*
+ * The driver sets up the sequence number to values of its choosing.
+ * uCode does not use this value, but passes it back to the driver
+ * when sending the response to each driver-originated command, so
+ * the driver can match the response to the command. Since the values
+ * don't get used by uCode, the driver may set up an arbitrary format.
+ *
+ * There is one exception: uCode sets bit 15 when it originates
+ * the response/notification, i.e. when the response/notification
+ * is not a direct response to a command sent by the driver. For
+ * example, uCode issues REPLY_RX when it sends a received frame
+ * to the driver; it is not a direct response to any driver command.
+ *
+ * The Linux driver uses the following format:
+ *
+ * 0:7 tfd index - position within TX queue
+ * 8:12 TX queue id
+ * 13:14 reserved
+ * 15 unsolicited RX or uCode-originated notification
+ */
+ __le16 sequence;
+} __packed;
+
+
+#define FH_RSCSR_FRAME_SIZE_MSK 0x00003FFF /* bits 0-13 */
+
+struct iwl_rx_packet {
+ /*
+ * The first 4 bytes of the RX frame header contain both the RX frame
+ * size and some flags.
+ * Bit fields:
+ * 31: flag flush RB request
+ * 30: flag ignore TC (terminal counter) request
+ * 29: flag fast IRQ request
+ * 28-14: Reserved
+ * 13-00: RX frame size
+ */
+ __le32 len_n_flags;
+ struct iwl_cmd_header hdr;
+ u8 data[];
+} __packed;
/**
* enum CMD_MODE - how to send the host commands ?
@@ -173,7 +230,9 @@ enum iwl_hcmd_dataflag {
* struct iwl_host_cmd - Host command to the uCode
*
* @data: array of chunks that composes the data of the host command
- * @reply_page: pointer to the page that holds the response to the host command
+ * @resp_pkt: response packet, if %CMD_WANT_SKB was set
+ * @_rx_page_order: (internally used to free response packet)
+ * @_rx_page_addr: (internally used to free response packet)
* @handler_status: return value of the handler of the command
* (put in setup_rx_handlers) - valid for SYNC mode only
* @flags: can be CMD_*
@@ -183,7 +242,9 @@ enum iwl_hcmd_dataflag {
*/
struct iwl_host_cmd {
const void *data[IWL_MAX_CMD_TFDS];
- unsigned long reply_page;
+ struct iwl_rx_packet *resp_pkt;
+ unsigned long _rx_page_addr;
+ u32 _rx_page_order;
int handler_status;
u32 flags;
@@ -192,6 +253,40 @@ struct iwl_host_cmd {
u8 id;
};
+static inline void iwl_free_resp(struct iwl_host_cmd *cmd)
+{
+ free_pages(cmd->_rx_page_addr, cmd->_rx_page_order);
+}
+
+struct iwl_rx_cmd_buffer {
+ struct page *_page;
+};
+
+static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r)
+{
+ return page_address(r->_page);
+}
+
+static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r)
+{
+ struct page *p = r->_page;
+ r->_page = NULL;
+ return p;
+}
+
+/**
+ * struct iwl_trans_config - transport configuration
+ *
+ * @op_mode: pointer to the upper layer.
+ * Must be set before any other call.
+ * @cmd_queue: the index of the command queue.
+ * Must be set before start_fw.
+ */
+struct iwl_trans_config {
+ struct iwl_op_mode *op_mode;
+ u8 cmd_queue;
+};
+
/**
* struct iwl_trans_ops - transport specific operations
*
@@ -207,9 +302,11 @@ struct iwl_host_cmd {
* May sleep
* @fw_alive: called when the fw sends alive notification
* May sleep
- * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_*
* @stop_device:stops the whole device (embedded CPU put to reset)
* May sleep
+ * @wowlan_suspend: put the device into the correct mode for WoWLAN during
+ * suspend. This is optional, if not implemented WoWLAN will not be
+ * supported. This callback may sleep.
* @send_cmd:send a host command
* May sleep only if CMD_SYNC is set
* @tx: send an skb
@@ -217,17 +314,16 @@ struct iwl_host_cmd {
* @reclaim: free packet until ssn. Returns a list of freed packets.
* Must be atomic
* @tx_agg_alloc: allocate resources for a TX BA session
- * May sleep
+ * Must be atomic
* @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is
* ready and a successful ADDBA response has been received.
* May sleep
* @tx_agg_disable: de-configure a Tx queue to send AMPDUs
- * May sleep
+ * Must be atomic
* @free: release all the ressource for the transport layer itself such as
* irq, tasklet etc... From this point on, the device may not issue
* any interrupt (incl. RFKILL).
* May sleep
- * @stop_queue: stop a specific queue
* @check_stuck_queue: check if a specific queue is stuck
* @wait_tx_queue_empty: wait until all tx queues are empty
* May sleep
@@ -238,18 +334,19 @@ struct iwl_host_cmd {
* @write8: write a u8 to a register at offset ofs from the BAR
* @write32: write a u32 to a register at offset ofs from the BAR
* @read32: read a u32 register at offset ofs from the BAR
+ * @configure: configure parameters required by the transport layer from
+ * the op_mode. May be called several times before start_fw, can't be
+ * called after that.
*/
struct iwl_trans_ops {
int (*start_hw)(struct iwl_trans *iwl_trans);
void (*stop_hw)(struct iwl_trans *iwl_trans);
- int (*start_fw)(struct iwl_trans *trans, struct fw_img *fw);
+ int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw);
void (*fw_alive)(struct iwl_trans *trans);
void (*stop_device)(struct iwl_trans *trans);
- void (*wake_any_queue)(struct iwl_trans *trans,
- enum iwl_rxon_context_id ctx,
- const char *msg);
+ void (*wowlan_suspend)(struct iwl_trans *trans);
int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
@@ -257,8 +354,7 @@ struct iwl_trans_ops {
struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
u8 sta_id, u8 tid);
int (*reclaim)(struct iwl_trans *trans, int sta_id, int tid,
- int txq_id, int ssn, u32 status,
- struct sk_buff_head *skbs);
+ int txq_id, int ssn, struct sk_buff_head *skbs);
int (*tx_agg_disable)(struct iwl_trans *trans,
int sta_id, int tid);
@@ -270,8 +366,6 @@ struct iwl_trans_ops {
void (*free)(struct iwl_trans *trans);
- void (*stop_queue)(struct iwl_trans *trans, int q, const char *msg);
-
int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir);
int (*check_stuck_queue)(struct iwl_trans *trans, int q);
int (*wait_tx_queue_empty)(struct iwl_trans *trans);
@@ -282,14 +376,8 @@ struct iwl_trans_ops {
void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val);
void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val);
u32 (*read32)(struct iwl_trans *trans, u32 ofs);
-};
-
-/* Opaque calibration results */
-struct iwl_calib_result {
- struct list_head list;
- size_t cmd_len;
- struct iwl_calib_hdr hdr;
- /* data follows */
+ void (*configure)(struct iwl_trans *trans,
+ const struct iwl_trans_config *trans_cfg);
};
/**
@@ -309,52 +397,44 @@ enum iwl_trans_state {
* @ops - pointer to iwl_trans_ops
* @op_mode - pointer to the op_mode
* @shrd - pointer to iwl_shared which holds shared data from the upper layer
- * @hcmd_lock: protects HCMD
* @reg_lock - protect hw register access
* @dev - pointer to struct device * that represents the device
- * @irq - the irq number for the device
* @hw_id: a u32 with the ID of the device / subdevice.
* Set during transport allocation.
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
- * @ucode_write_complete: indicates that the ucode has been copied.
* @nvm_device_type: indicates OTP or eeprom
* @pm_support: set to true in start_hw if link pm is supported
- * @calib_results: list head for init calibration results
*/
struct iwl_trans {
const struct iwl_trans_ops *ops;
struct iwl_op_mode *op_mode;
struct iwl_shared *shrd;
enum iwl_trans_state state;
- spinlock_t hcmd_lock;
spinlock_t reg_lock;
struct device *dev;
- unsigned int irq;
u32 hw_rev;
u32 hw_id;
char hw_id_str[52];
- u8 ucode_write_complete;
-
int nvm_device_type;
bool pm_support;
- struct list_head calib_results;
-
/* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
char trans_specific[0] __aligned(sizeof(void *));
};
static inline void iwl_trans_configure(struct iwl_trans *trans,
- struct iwl_op_mode *op_mode)
+ const struct iwl_trans_config *trans_cfg)
{
/*
* only set the op_mode for the moment. Later on, this function will do
* more
*/
- trans->op_mode = op_mode;
+ trans->op_mode = trans_cfg->op_mode;
+
+ trans->ops->configure(trans, trans_cfg);
}
static inline int iwl_trans_start_hw(struct iwl_trans *trans)
@@ -382,7 +462,8 @@ static inline void iwl_trans_fw_alive(struct iwl_trans *trans)
trans->state = IWL_TRANS_FW_ALIVE;
}
-static inline int iwl_trans_start_fw(struct iwl_trans *trans, struct fw_img *fw)
+static inline int iwl_trans_start_fw(struct iwl_trans *trans,
+ const struct fw_img *fw)
{
might_sleep();
@@ -398,17 +479,12 @@ static inline void iwl_trans_stop_device(struct iwl_trans *trans)
trans->state = IWL_TRANS_NO_FW;
}
-static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans,
- enum iwl_rxon_context_id ctx,
- const char *msg)
+static inline void iwl_trans_wowlan_suspend(struct iwl_trans *trans)
{
- if (trans->state != IWL_TRANS_FW_ALIVE)
- IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
-
- trans->ops->wake_any_queue(trans, ctx, msg);
+ might_sleep();
+ trans->ops->wowlan_suspend(trans);
}
-
static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
{
@@ -418,9 +494,6 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
return trans->ops->send_cmd(trans, cmd);
}
-int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id,
- u32 flags, u16 len, const void *data);
-
static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
u8 sta_id, u8 tid)
@@ -432,21 +505,18 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
}
static inline int iwl_trans_reclaim(struct iwl_trans *trans, int sta_id,
- int tid, int txq_id, int ssn, u32 status,
+ int tid, int txq_id, int ssn,
struct sk_buff_head *skbs)
{
if (trans->state != IWL_TRANS_FW_ALIVE)
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
- return trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn,
- status, skbs);
+ return trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn, skbs);
}
static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans,
int sta_id, int tid)
{
- might_sleep();
-
if (trans->state != IWL_TRANS_FW_ALIVE)
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
@@ -456,8 +526,6 @@ static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans,
static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans,
int sta_id, int tid)
{
- might_sleep();
-
if (trans->state != IWL_TRANS_FW_ALIVE)
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
@@ -483,15 +551,6 @@ static inline void iwl_trans_free(struct iwl_trans *trans)
trans->ops->free(trans);
}
-static inline void iwl_trans_stop_queue(struct iwl_trans *trans, int q,
- const char *msg)
-{
- if (trans->state != IWL_TRANS_FW_ALIVE)
- IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
-
- trans->ops->stop_queue(trans, q, msg);
-}
-
static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans)
{
if (trans->state != IWL_TRANS_FW_ALIVE)
@@ -541,14 +600,6 @@ static inline u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs)
}
/*****************************************************
-* Utils functions
-******************************************************/
-int iwl_send_calib_results(struct iwl_trans *trans);
-int iwl_calib_set(struct iwl_trans *trans,
- const struct iwl_calib_hdr *cmd, int len);
-void iwl_calib_free_results(struct iwl_trans *trans);
-
-/*****************************************************
* Transport layers implementations + their allocation function
******************************************************/
struct pci_dev;
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c
index b16efc00ba6..d97cf44b75b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c
@@ -28,14 +28,8 @@
*****************************************************************************/
#include <linux/kernel.h>
-#include <linux/module.h>
#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/dma-mapping.h>
-#include <linux/firmware.h>
-#include "iwl-ucode.h"
-#include "iwl-wifi.h"
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-io.h"
@@ -83,56 +77,16 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
*
******************************************************************************/
-static void iwl_free_fw_desc(struct iwl_nic *nic, struct fw_desc *desc)
-{
- if (desc->v_addr)
- dma_free_coherent(trans(nic)->dev, desc->len,
- desc->v_addr, desc->p_addr);
- desc->v_addr = NULL;
- desc->len = 0;
-}
-
-static void iwl_free_fw_img(struct iwl_nic *nic, struct fw_img *img)
-{
- iwl_free_fw_desc(nic, &img->code);
- iwl_free_fw_desc(nic, &img->data);
-}
-
-void iwl_dealloc_ucode(struct iwl_nic *nic)
-{
- iwl_free_fw_img(nic, &nic->fw.ucode_rt);
- iwl_free_fw_img(nic, &nic->fw.ucode_init);
- iwl_free_fw_img(nic, &nic->fw.ucode_wowlan);
-}
-
-static int iwl_alloc_fw_desc(struct iwl_nic *nic, struct fw_desc *desc,
- const void *data, size_t len)
-{
- if (!len) {
- desc->v_addr = NULL;
- return -EINVAL;
- }
-
- desc->v_addr = dma_alloc_coherent(trans(nic)->dev, len,
- &desc->p_addr, GFP_KERNEL);
- if (!desc->v_addr)
- return -ENOMEM;
-
- desc->len = len;
- memcpy(desc->v_addr, data, len);
- return 0;
-}
-
-static inline struct fw_img *iwl_get_ucode_image(struct iwl_nic *nic,
- enum iwl_ucode_type ucode_type)
+static inline const struct fw_img *
+iwl_get_ucode_image(struct iwl_priv *priv, enum iwl_ucode_type ucode_type)
{
switch (ucode_type) {
case IWL_UCODE_INIT:
- return &nic->fw.ucode_init;
+ return &priv->fw->ucode_init;
case IWL_UCODE_WOWLAN:
- return &nic->fw.ucode_wowlan;
+ return &priv->fw->ucode_wowlan;
case IWL_UCODE_REGULAR:
- return &nic->fw.ucode_rt;
+ return &priv->fw->ucode_rt;
case IWL_UCODE_NONE:
break;
}
@@ -142,23 +96,23 @@ static inline struct fw_img *iwl_get_ucode_image(struct iwl_nic *nic,
/*
* Calibration
*/
-static int iwl_set_Xtal_calib(struct iwl_trans *trans)
+static int iwl_set_Xtal_calib(struct iwl_priv *priv)
{
struct iwl_calib_xtal_freq_cmd cmd;
__le16 *xtal_calib =
- (__le16 *)iwl_eeprom_query_addr(trans->shrd, EEPROM_XTAL);
+ (__le16 *)iwl_eeprom_query_addr(priv->shrd, EEPROM_XTAL);
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD);
cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]);
- return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd));
+ return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
}
-static int iwl_set_temperature_offset_calib(struct iwl_trans *trans)
+static int iwl_set_temperature_offset_calib(struct iwl_priv *priv)
{
struct iwl_calib_temperature_offset_cmd cmd;
__le16 *offset_calib =
- (__le16 *)iwl_eeprom_query_addr(trans->shrd,
+ (__le16 *)iwl_eeprom_query_addr(priv->shrd,
EEPROM_RAW_TEMPERATURE);
memset(&cmd, 0, sizeof(cmd));
@@ -167,48 +121,48 @@ static int iwl_set_temperature_offset_calib(struct iwl_trans *trans)
if (!(cmd.radio_sensor_offset))
cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
- IWL_DEBUG_CALIB(trans, "Radio sensor offset: %d\n",
+ IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",
le16_to_cpu(cmd.radio_sensor_offset));
- return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd));
+ return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
}
-static int iwl_set_temperature_offset_calib_v2(struct iwl_trans *trans)
+static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv)
{
struct iwl_calib_temperature_offset_v2_cmd cmd;
- __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(trans->shrd,
+ __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv->shrd,
EEPROM_KELVIN_TEMPERATURE);
__le16 *offset_calib_low =
- (__le16 *)iwl_eeprom_query_addr(trans->shrd,
+ (__le16 *)iwl_eeprom_query_addr(priv->shrd,
EEPROM_RAW_TEMPERATURE);
struct iwl_eeprom_calib_hdr *hdr;
memset(&cmd, 0, sizeof(cmd));
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
- hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(trans->shrd,
+ hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv->shrd,
EEPROM_CALIB_ALL);
memcpy(&cmd.radio_sensor_offset_high, offset_calib_high,
sizeof(*offset_calib_high));
memcpy(&cmd.radio_sensor_offset_low, offset_calib_low,
sizeof(*offset_calib_low));
if (!(cmd.radio_sensor_offset_low)) {
- IWL_DEBUG_CALIB(trans, "no info in EEPROM, use default\n");
+ IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n");
cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET;
cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET;
}
memcpy(&cmd.burntVoltageRef, &hdr->voltage,
sizeof(hdr->voltage));
- IWL_DEBUG_CALIB(trans, "Radio sensor offset high: %d\n",
+ IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n",
le16_to_cpu(cmd.radio_sensor_offset_high));
- IWL_DEBUG_CALIB(trans, "Radio sensor offset low: %d\n",
+ IWL_DEBUG_CALIB(priv, "Radio sensor offset low: %d\n",
le16_to_cpu(cmd.radio_sensor_offset_low));
- IWL_DEBUG_CALIB(trans, "Voltage Ref: %d\n",
+ IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n",
le16_to_cpu(cmd.burntVoltageRef));
- return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd));
+ return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
}
-static int iwl_send_calib_cfg(struct iwl_trans *trans)
+static int iwl_send_calib_cfg(struct iwl_priv *priv)
{
struct iwl_calib_cfg_cmd calib_cfg_cmd;
struct iwl_host_cmd cmd = {
@@ -224,47 +178,47 @@ static int iwl_send_calib_cfg(struct iwl_trans *trans)
calib_cfg_cmd.ucd_calib_cfg.flags =
IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK;
- return iwl_trans_send_cmd(trans, &cmd);
+ return iwl_dvm_send_cmd(priv, &cmd);
}
int iwlagn_rx_calib_result(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;
+ struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->data;
int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
/* reduce the size of the length field itself */
len -= 4;
- if (iwl_calib_set(trans(priv), hdr, len))
+ if (iwl_calib_set(priv, hdr, len))
IWL_ERR(priv, "Failed to record calibration data %d\n",
hdr->op_code);
return 0;
}
-int iwl_init_alive_start(struct iwl_trans *trans)
+int iwl_init_alive_start(struct iwl_priv *priv)
{
int ret;
- if (cfg(trans)->bt_params &&
- cfg(trans)->bt_params->advanced_bt_coexist) {
+ if (cfg(priv)->bt_params &&
+ cfg(priv)->bt_params->advanced_bt_coexist) {
/*
* Tell uCode we are ready to perform calibration
* need to perform this before any calibration
* no need to close the envlope since we are going
* to load the runtime uCode later.
*/
- ret = iwl_send_bt_env(trans, IWL_BT_COEX_ENV_OPEN,
+ ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
if (ret)
return ret;
}
- ret = iwl_send_calib_cfg(trans);
+ ret = iwl_send_calib_cfg(priv);
if (ret)
return ret;
@@ -272,21 +226,21 @@ int iwl_init_alive_start(struct iwl_trans *trans)
* temperature offset calibration is only needed for runtime ucode,
* so prepare the value now.
*/
- if (cfg(trans)->need_temp_offset_calib) {
- if (cfg(trans)->temp_offset_v2)
- return iwl_set_temperature_offset_calib_v2(trans);
+ if (cfg(priv)->need_temp_offset_calib) {
+ if (cfg(priv)->temp_offset_v2)
+ return iwl_set_temperature_offset_calib_v2(priv);
else
- return iwl_set_temperature_offset_calib(trans);
+ return iwl_set_temperature_offset_calib(priv);
}
return 0;
}
-static int iwl_send_wimax_coex(struct iwl_trans *trans)
+static int iwl_send_wimax_coex(struct iwl_priv *priv)
{
struct iwl_wimax_coex_cmd coex_cmd;
- if (cfg(trans)->base_params->support_wimax_coexist) {
+ if (cfg(priv)->base_params->support_wimax_coexist) {
/* UnMask wake up src at associated sleep */
coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK;
@@ -305,7 +259,7 @@ static int iwl_send_wimax_coex(struct iwl_trans *trans)
/* coexistence is disabled */
memset(&coex_cmd, 0, sizeof(coex_cmd));
}
- return iwl_trans_send_cmd_pdu(trans,
+ return iwl_dvm_send_cmd_pdu(priv,
COEX_PRIORITY_TABLE_CMD, CMD_SYNC,
sizeof(coex_cmd), &coex_cmd);
}
@@ -332,64 +286,54 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
0, 0, 0, 0, 0, 0, 0
};
-void iwl_send_prio_tbl(struct iwl_trans *trans)
+void iwl_send_prio_tbl(struct iwl_priv *priv)
{
struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd;
memcpy(prio_tbl_cmd.prio_tbl, iwl_bt_prio_tbl,
sizeof(iwl_bt_prio_tbl));
- if (iwl_trans_send_cmd_pdu(trans,
+ if (iwl_dvm_send_cmd_pdu(priv,
REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC,
sizeof(prio_tbl_cmd), &prio_tbl_cmd))
- IWL_ERR(trans, "failed to send BT prio tbl command\n");
+ IWL_ERR(priv, "failed to send BT prio tbl command\n");
}
-int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type)
+int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
{
struct iwl_bt_coex_prot_env_cmd env_cmd;
int ret;
env_cmd.action = action;
env_cmd.type = type;
- ret = iwl_trans_send_cmd_pdu(trans,
+ ret = iwl_dvm_send_cmd_pdu(priv,
REPLY_BT_COEX_PROT_ENV, CMD_SYNC,
sizeof(env_cmd), &env_cmd);
if (ret)
- IWL_ERR(trans, "failed to send BT env command\n");
+ IWL_ERR(priv, "failed to send BT env command\n");
return ret;
}
-static int iwl_alive_notify(struct iwl_trans *trans)
+static int iwl_alive_notify(struct iwl_priv *priv)
{
- struct iwl_priv *priv = priv(trans);
- struct iwl_rxon_context *ctx;
int ret;
- if (!priv->tx_cmd_pool)
- priv->tx_cmd_pool =
- kmem_cache_create("iwl_dev_cmd",
- sizeof(struct iwl_device_cmd),
- sizeof(void *), 0, NULL);
-
- if (!priv->tx_cmd_pool)
- return -ENOMEM;
+ iwl_trans_fw_alive(trans(priv));
- iwl_trans_fw_alive(trans);
- for_each_context(priv, ctx)
- ctx->last_tx_rejected = false;
+ priv->passive_no_rx = false;
+ priv->transport_queue_stop = 0;
- ret = iwl_send_wimax_coex(trans);
+ ret = iwl_send_wimax_coex(priv);
if (ret)
return ret;
if (!cfg(priv)->no_xtal_calib) {
- ret = iwl_set_Xtal_calib(trans);
+ ret = iwl_set_Xtal_calib(priv);
if (ret)
return ret;
}
- return iwl_send_calib_results(trans);
+ return iwl_send_calib_results(priv);
}
@@ -398,24 +342,23 @@ static int iwl_alive_notify(struct iwl_trans *trans)
* using sample data 100 bytes apart. If these sample points are good,
* it's a pretty good bet that everything between them is good, too.
*/
-static int iwl_verify_inst_sparse(struct iwl_nic *nic,
- struct fw_desc *fw_desc)
+static int iwl_verify_inst_sparse(struct iwl_priv *priv,
+ const struct fw_desc *fw_desc)
{
- struct iwl_trans *trans = trans(nic);
__le32 *image = (__le32 *)fw_desc->v_addr;
u32 len = fw_desc->len;
u32 val;
u32 i;
- IWL_DEBUG_FW(nic, "ucode inst image size is %u\n", len);
+ IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
/* read data comes through single port, auto-incr addr */
/* NOTE: Use the debugless read so we don't flood kernel log
* if IWL_DL_IO is set */
- iwl_write_direct32(trans, HBUS_TARG_MEM_RADDR,
+ iwl_write_direct32(trans(priv), HBUS_TARG_MEM_RADDR,
i + IWLAGN_RTC_INST_LOWER_BOUND);
- val = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
+ val = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
if (val != le32_to_cpu(*image))
return -EIO;
}
@@ -423,28 +366,27 @@ static int iwl_verify_inst_sparse(struct iwl_nic *nic,
return 0;
}
-static void iwl_print_mismatch_inst(struct iwl_nic *nic,
- struct fw_desc *fw_desc)
+static void iwl_print_mismatch_inst(struct iwl_priv *priv,
+ const struct fw_desc *fw_desc)
{
- struct iwl_trans *trans = trans(nic);
__le32 *image = (__le32 *)fw_desc->v_addr;
u32 len = fw_desc->len;
u32 val;
u32 offs;
int errors = 0;
- IWL_DEBUG_FW(nic, "ucode inst image size is %u\n", len);
+ IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
- iwl_write_direct32(trans, HBUS_TARG_MEM_RADDR,
+ iwl_write_direct32(trans(priv), HBUS_TARG_MEM_RADDR,
IWLAGN_RTC_INST_LOWER_BOUND);
for (offs = 0;
offs < len && errors < 20;
offs += sizeof(u32), image++) {
/* read data comes through single port, auto-incr addr */
- val = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
+ val = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
if (val != le32_to_cpu(*image)) {
- IWL_ERR(nic, "uCode INST section at "
+ IWL_ERR(priv, "uCode INST section at "
"offset 0x%x, is 0x%x, s/b 0x%x\n",
offs, val, le32_to_cpu(*image));
errors++;
@@ -456,24 +398,24 @@ static void iwl_print_mismatch_inst(struct iwl_nic *nic,
* iwl_verify_ucode - determine which instruction image is in SRAM,
* and verify its contents
*/
-static int iwl_verify_ucode(struct iwl_nic *nic,
+static int iwl_verify_ucode(struct iwl_priv *priv,
enum iwl_ucode_type ucode_type)
{
- struct fw_img *img = iwl_get_ucode_image(nic, ucode_type);
+ const struct fw_img *img = iwl_get_ucode_image(priv, ucode_type);
if (!img) {
- IWL_ERR(nic, "Invalid ucode requested (%d)\n", ucode_type);
+ IWL_ERR(priv, "Invalid ucode requested (%d)\n", ucode_type);
return -EINVAL;
}
- if (!iwl_verify_inst_sparse(nic, &img->code)) {
- IWL_DEBUG_FW(nic, "uCode is good in inst SRAM\n");
+ if (!iwl_verify_inst_sparse(priv, &img->code)) {
+ IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n");
return 0;
}
- IWL_ERR(nic, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n");
+ IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n");
- iwl_print_mismatch_inst(nic, &img->code);
+ iwl_print_mismatch_inst(priv, &img->code);
return -EIO;
}
@@ -482,119 +424,57 @@ struct iwl_alive_data {
u8 subtype;
};
-static void iwl_alive_fn(struct iwl_trans *trans,
+static void iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
struct iwl_rx_packet *pkt,
void *data)
{
+ struct iwl_priv *priv =
+ container_of(notif_wait, struct iwl_priv, notif_wait);
struct iwl_alive_data *alive_data = data;
struct iwl_alive_resp *palive;
- palive = &pkt->u.alive_frame;
+ palive = (void *)pkt->data;
- IWL_DEBUG_FW(trans, "Alive ucode status 0x%08X revision "
+ IWL_DEBUG_FW(priv, "Alive ucode status 0x%08X revision "
"0x%01X 0x%01X\n",
palive->is_valid, palive->ver_type,
palive->ver_subtype);
- trans->shrd->device_pointers.error_event_table =
+ priv->shrd->device_pointers.error_event_table =
le32_to_cpu(palive->error_event_table_ptr);
- trans->shrd->device_pointers.log_event_table =
+ priv->shrd->device_pointers.log_event_table =
le32_to_cpu(palive->log_event_table_ptr);
alive_data->subtype = palive->ver_subtype;
alive_data->valid = palive->is_valid == UCODE_VALID_OK;
}
-/* notification wait support */
-void iwl_init_notification_wait(struct iwl_shared *shrd,
- struct iwl_notification_wait *wait_entry,
- u8 cmd,
- void (*fn)(struct iwl_trans *trans,
- struct iwl_rx_packet *pkt,
- void *data),
- void *fn_data)
-{
- wait_entry->fn = fn;
- wait_entry->fn_data = fn_data;
- wait_entry->cmd = cmd;
- wait_entry->triggered = false;
- wait_entry->aborted = false;
-
- spin_lock_bh(&shrd->notif_wait_lock);
- list_add(&wait_entry->list, &shrd->notif_waits);
- spin_unlock_bh(&shrd->notif_wait_lock);
-}
-
-int iwl_wait_notification(struct iwl_shared *shrd,
- struct iwl_notification_wait *wait_entry,
- unsigned long timeout)
-{
- int ret;
-
- ret = wait_event_timeout(shrd->notif_waitq,
- wait_entry->triggered || wait_entry->aborted,
- timeout);
-
- spin_lock_bh(&shrd->notif_wait_lock);
- list_del(&wait_entry->list);
- spin_unlock_bh(&shrd->notif_wait_lock);
-
- if (wait_entry->aborted)
- return -EIO;
-
- /* return value is always >= 0 */
- if (ret <= 0)
- return -ETIMEDOUT;
- return 0;
-}
-
-void iwl_remove_notification(struct iwl_shared *shrd,
- struct iwl_notification_wait *wait_entry)
-{
- spin_lock_bh(&shrd->notif_wait_lock);
- list_del(&wait_entry->list);
- spin_unlock_bh(&shrd->notif_wait_lock);
-}
-
-void iwl_abort_notification_waits(struct iwl_shared *shrd)
-{
- unsigned long flags;
- struct iwl_notification_wait *wait_entry;
-
- spin_lock_irqsave(&shrd->notif_wait_lock, flags);
- list_for_each_entry(wait_entry, &shrd->notif_waits, list)
- wait_entry->aborted = true;
- spin_unlock_irqrestore(&shrd->notif_wait_lock, flags);
-
- wake_up_all(&shrd->notif_waitq);
-}
-
#define UCODE_ALIVE_TIMEOUT HZ
#define UCODE_CALIB_TIMEOUT (2*HZ)
-int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
+int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
enum iwl_ucode_type ucode_type)
{
struct iwl_notification_wait alive_wait;
struct iwl_alive_data alive_data;
- struct fw_img *fw;
+ const struct fw_img *fw;
int ret;
enum iwl_ucode_type old_type;
- iwl_init_notification_wait(trans->shrd, &alive_wait, REPLY_ALIVE,
- iwl_alive_fn, &alive_data);
-
- old_type = trans->shrd->ucode_type;
- trans->shrd->ucode_type = ucode_type;
- fw = iwl_get_ucode_image(nic(trans), ucode_type);
+ old_type = priv->shrd->ucode_type;
+ priv->shrd->ucode_type = ucode_type;
+ fw = iwl_get_ucode_image(priv, ucode_type);
if (!fw)
return -EINVAL;
- ret = iwl_trans_start_fw(trans, fw);
+ iwl_init_notification_wait(&priv->notif_wait, &alive_wait, REPLY_ALIVE,
+ iwl_alive_fn, &alive_data);
+
+ ret = iwl_trans_start_fw(trans(priv), fw);
if (ret) {
- trans->shrd->ucode_type = old_type;
- iwl_remove_notification(trans->shrd, &alive_wait);
+ priv->shrd->ucode_type = old_type;
+ iwl_remove_notification(&priv->notif_wait, &alive_wait);
return ret;
}
@@ -602,16 +482,16 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
* Some things may run in the background now, but we
* just wait for the ALIVE notification here.
*/
- ret = iwl_wait_notification(trans->shrd, &alive_wait,
+ ret = iwl_wait_notification(&priv->notif_wait, &alive_wait,
UCODE_ALIVE_TIMEOUT);
if (ret) {
- trans->shrd->ucode_type = old_type;
+ priv->shrd->ucode_type = old_type;
return ret;
}
if (!alive_data.valid) {
- IWL_ERR(trans, "Loaded ucode is not valid!\n");
- trans->shrd->ucode_type = old_type;
+ IWL_ERR(priv, "Loaded ucode is not valid!\n");
+ priv->shrd->ucode_type = old_type;
return -EIO;
}
@@ -621,9 +501,9 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
* skip it for WoWLAN.
*/
if (ucode_type != IWL_UCODE_WOWLAN) {
- ret = iwl_verify_ucode(nic(trans), ucode_type);
+ ret = iwl_verify_ucode(priv, ucode_type);
if (ret) {
- trans->shrd->ucode_type = old_type;
+ priv->shrd->ucode_type = old_type;
return ret;
}
@@ -631,41 +511,41 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
msleep(5);
}
- ret = iwl_alive_notify(trans);
+ ret = iwl_alive_notify(priv);
if (ret) {
- IWL_WARN(trans,
+ IWL_WARN(priv,
"Could not complete ALIVE transition: %d\n", ret);
- trans->shrd->ucode_type = old_type;
+ priv->shrd->ucode_type = old_type;
return ret;
}
return 0;
}
-int iwl_run_init_ucode(struct iwl_trans *trans)
+int iwl_run_init_ucode(struct iwl_priv *priv)
{
struct iwl_notification_wait calib_wait;
int ret;
- lockdep_assert_held(&trans->shrd->mutex);
+ lockdep_assert_held(&priv->mutex);
/* No init ucode required? Curious, but maybe ok */
- if (!nic(trans)->fw.ucode_init.code.len)
+ if (!priv->fw->ucode_init.code.len)
return 0;
- if (trans->shrd->ucode_type != IWL_UCODE_NONE)
+ if (priv->shrd->ucode_type != IWL_UCODE_NONE)
return 0;
- iwl_init_notification_wait(trans->shrd, &calib_wait,
+ iwl_init_notification_wait(&priv->notif_wait, &calib_wait,
CALIBRATION_COMPLETE_NOTIFICATION,
NULL, NULL);
/* Will also start the device */
- ret = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT);
+ ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
if (ret)
goto error;
- ret = iwl_init_alive_start(trans);
+ ret = iwl_init_alive_start(priv);
if (ret)
goto error;
@@ -673,594 +553,15 @@ int iwl_run_init_ucode(struct iwl_trans *trans)
* Some things may run in the background now, but we
* just wait for the calibration complete notification.
*/
- ret = iwl_wait_notification(trans->shrd, &calib_wait,
+ ret = iwl_wait_notification(&priv->notif_wait, &calib_wait,
UCODE_CALIB_TIMEOUT);
goto out;
error:
- iwl_remove_notification(trans->shrd, &calib_wait);
+ iwl_remove_notification(&priv->notif_wait, &calib_wait);
out:
/* Whatever happened, stop the device */
- iwl_trans_stop_device(trans);
+ iwl_trans_stop_device(trans(priv));
return ret;
}
-
-static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
-
-#define UCODE_EXPERIMENTAL_TAG "exp"
-
-int __must_check iwl_request_firmware(struct iwl_nic *nic, bool first)
-{
- struct iwl_cfg *cfg = cfg(nic);
- const char *name_pre = cfg->fw_name_pre;
- char tag[8];
-
- if (first) {
-#ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
- nic->fw_index = UCODE_EXPERIMENTAL_INDEX;
- strcpy(tag, UCODE_EXPERIMENTAL_TAG);
- } else if (nic->fw_index == UCODE_EXPERIMENTAL_INDEX) {
-#endif
- nic->fw_index = cfg->ucode_api_max;
- sprintf(tag, "%d", nic->fw_index);
- } else {
- nic->fw_index--;
- sprintf(tag, "%d", nic->fw_index);
- }
-
- if (nic->fw_index < cfg->ucode_api_min) {
- IWL_ERR(nic, "no suitable firmware found!\n");
- return -ENOENT;
- }
-
- sprintf(nic->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
-
- IWL_DEBUG_INFO(nic, "attempting to load firmware %s'%s'\n",
- (nic->fw_index == UCODE_EXPERIMENTAL_INDEX)
- ? "EXPERIMENTAL " : "",
- nic->firmware_name);
-
- return request_firmware_nowait(THIS_MODULE, 1, nic->firmware_name,
- trans(nic)->dev,
- GFP_KERNEL, nic, iwl_ucode_callback);
-}
-
-struct iwlagn_firmware_pieces {
- const void *inst, *data, *init, *init_data, *wowlan_inst, *wowlan_data;
- size_t inst_size, data_size, init_size, init_data_size,
- wowlan_inst_size, wowlan_data_size;
-
- u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
- u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
-};
-
-static int iwl_parse_v1_v2_firmware(struct iwl_nic *nic,
- const struct firmware *ucode_raw,
- struct iwlagn_firmware_pieces *pieces)
-{
- struct iwl_ucode_header *ucode = (void *)ucode_raw->data;
- u32 api_ver, hdr_size, build;
- char buildstr[25];
- const u8 *src;
-
- nic->fw.ucode_ver = le32_to_cpu(ucode->ver);
- api_ver = IWL_UCODE_API(nic->fw.ucode_ver);
-
- switch (api_ver) {
- default:
- hdr_size = 28;
- if (ucode_raw->size < hdr_size) {
- IWL_ERR(nic, "File size too small!\n");
- return -EINVAL;
- }
- build = le32_to_cpu(ucode->u.v2.build);
- pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size);
- pieces->data_size = le32_to_cpu(ucode->u.v2.data_size);
- pieces->init_size = le32_to_cpu(ucode->u.v2.init_size);
- pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size);
- src = ucode->u.v2.data;
- break;
- case 0:
- case 1:
- case 2:
- hdr_size = 24;
- if (ucode_raw->size < hdr_size) {
- IWL_ERR(nic, "File size too small!\n");
- return -EINVAL;
- }
- build = 0;
- pieces->inst_size = le32_to_cpu(ucode->u.v1.inst_size);
- pieces->data_size = le32_to_cpu(ucode->u.v1.data_size);
- pieces->init_size = le32_to_cpu(ucode->u.v1.init_size);
- pieces->init_data_size = le32_to_cpu(ucode->u.v1.init_data_size);
- src = ucode->u.v1.data;
- break;
- }
-
- if (build)
- sprintf(buildstr, " build %u%s", build,
- (nic->fw_index == UCODE_EXPERIMENTAL_INDEX)
- ? " (EXP)" : "");
- else
- buildstr[0] = '\0';
-
- snprintf(nic->fw.fw_version,
- sizeof(nic->fw.fw_version),
- "%u.%u.%u.%u%s",
- IWL_UCODE_MAJOR(nic->fw.ucode_ver),
- IWL_UCODE_MINOR(nic->fw.ucode_ver),
- IWL_UCODE_API(nic->fw.ucode_ver),
- IWL_UCODE_SERIAL(nic->fw.ucode_ver),
- buildstr);
-
- /* Verify size of file vs. image size info in file's header */
- if (ucode_raw->size != hdr_size + pieces->inst_size +
- pieces->data_size + pieces->init_size +
- pieces->init_data_size) {
-
- IWL_ERR(nic,
- "uCode file size %d does not match expected size\n",
- (int)ucode_raw->size);
- return -EINVAL;
- }
-
- pieces->inst = src;
- src += pieces->inst_size;
- pieces->data = src;
- src += pieces->data_size;
- pieces->init = src;
- src += pieces->init_size;
- pieces->init_data = src;
- src += pieces->init_data_size;
-
- return 0;
-}
-
-static int iwl_parse_tlv_firmware(struct iwl_nic *nic,
- const struct firmware *ucode_raw,
- struct iwlagn_firmware_pieces *pieces,
- struct iwl_ucode_capabilities *capa)
-{
- struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data;
- struct iwl_ucode_tlv *tlv;
- size_t len = ucode_raw->size;
- const u8 *data;
- int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative;
- int tmp;
- u64 alternatives;
- u32 tlv_len;
- enum iwl_ucode_tlv_type tlv_type;
- const u8 *tlv_data;
- char buildstr[25];
- u32 build;
-
- if (len < sizeof(*ucode)) {
- IWL_ERR(nic, "uCode has invalid length: %zd\n", len);
- return -EINVAL;
- }
-
- if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) {
- IWL_ERR(nic, "invalid uCode magic: 0X%x\n",
- le32_to_cpu(ucode->magic));
- return -EINVAL;
- }
-
- /*
- * Check which alternatives are present, and "downgrade"
- * when the chosen alternative is not present, warning
- * the user when that happens. Some files may not have
- * any alternatives, so don't warn in that case.
- */
- alternatives = le64_to_cpu(ucode->alternatives);
- tmp = wanted_alternative;
- if (wanted_alternative > 63)
- wanted_alternative = 63;
- while (wanted_alternative && !(alternatives & BIT(wanted_alternative)))
- wanted_alternative--;
- if (wanted_alternative && wanted_alternative != tmp)
- IWL_WARN(nic,
- "uCode alternative %d not available, choosing %d\n",
- tmp, wanted_alternative);
-
- nic->fw.ucode_ver = le32_to_cpu(ucode->ver);
- build = le32_to_cpu(ucode->build);
-
- if (build)
- sprintf(buildstr, " build %u%s", build,
- (nic->fw_index == UCODE_EXPERIMENTAL_INDEX)
- ? " (EXP)" : "");
- else
- buildstr[0] = '\0';
-
- snprintf(nic->fw.fw_version,
- sizeof(nic->fw.fw_version),
- "%u.%u.%u.%u%s",
- IWL_UCODE_MAJOR(nic->fw.ucode_ver),
- IWL_UCODE_MINOR(nic->fw.ucode_ver),
- IWL_UCODE_API(nic->fw.ucode_ver),
- IWL_UCODE_SERIAL(nic->fw.ucode_ver),
- buildstr);
-
- data = ucode->data;
-
- len -= sizeof(*ucode);
-
- while (len >= sizeof(*tlv)) {
- u16 tlv_alt;
-
- len -= sizeof(*tlv);
- tlv = (void *)data;
-
- tlv_len = le32_to_cpu(tlv->length);
- tlv_type = le16_to_cpu(tlv->type);
- tlv_alt = le16_to_cpu(tlv->alternative);
- tlv_data = tlv->data;
-
- if (len < tlv_len) {
- IWL_ERR(nic, "invalid TLV len: %zd/%u\n",
- len, tlv_len);
- return -EINVAL;
- }
- len -= ALIGN(tlv_len, 4);
- data += sizeof(*tlv) + ALIGN(tlv_len, 4);
-
- /*
- * Alternative 0 is always valid.
- *
- * Skip alternative TLVs that are not selected.
- */
- if (tlv_alt != 0 && tlv_alt != wanted_alternative)
- continue;
-
- switch (tlv_type) {
- case IWL_UCODE_TLV_INST:
- pieces->inst = tlv_data;
- pieces->inst_size = tlv_len;
- break;
- case IWL_UCODE_TLV_DATA:
- pieces->data = tlv_data;
- pieces->data_size = tlv_len;
- break;
- case IWL_UCODE_TLV_INIT:
- pieces->init = tlv_data;
- pieces->init_size = tlv_len;
- break;
- case IWL_UCODE_TLV_INIT_DATA:
- pieces->init_data = tlv_data;
- pieces->init_data_size = tlv_len;
- break;
- case IWL_UCODE_TLV_BOOT:
- IWL_ERR(nic, "Found unexpected BOOT ucode\n");
- break;
- case IWL_UCODE_TLV_PROBE_MAX_LEN:
- if (tlv_len != sizeof(u32))
- goto invalid_tlv_len;
- capa->max_probe_length =
- le32_to_cpup((__le32 *)tlv_data);
- break;
- case IWL_UCODE_TLV_PAN:
- if (tlv_len)
- goto invalid_tlv_len;
- capa->flags |= IWL_UCODE_TLV_FLAGS_PAN;
- break;
- case IWL_UCODE_TLV_FLAGS:
- /* must be at least one u32 */
- if (tlv_len < sizeof(u32))
- goto invalid_tlv_len;
- /* and a proper number of u32s */
- if (tlv_len % sizeof(u32))
- goto invalid_tlv_len;
- /*
- * This driver only reads the first u32 as
- * right now no more features are defined,
- * if that changes then either the driver
- * will not work with the new firmware, or
- * it'll not take advantage of new features.
- */
- capa->flags = le32_to_cpup((__le32 *)tlv_data);
- break;
- case IWL_UCODE_TLV_INIT_EVTLOG_PTR:
- if (tlv_len != sizeof(u32))
- goto invalid_tlv_len;
- pieces->init_evtlog_ptr =
- le32_to_cpup((__le32 *)tlv_data);
- break;
- case IWL_UCODE_TLV_INIT_EVTLOG_SIZE:
- if (tlv_len != sizeof(u32))
- goto invalid_tlv_len;
- pieces->init_evtlog_size =
- le32_to_cpup((__le32 *)tlv_data);
- break;
- case IWL_UCODE_TLV_INIT_ERRLOG_PTR:
- if (tlv_len != sizeof(u32))
- goto invalid_tlv_len;
- pieces->init_errlog_ptr =
- le32_to_cpup((__le32 *)tlv_data);
- break;
- case IWL_UCODE_TLV_RUNT_EVTLOG_PTR:
- if (tlv_len != sizeof(u32))
- goto invalid_tlv_len;
- pieces->inst_evtlog_ptr =
- le32_to_cpup((__le32 *)tlv_data);
- break;
- case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE:
- if (tlv_len != sizeof(u32))
- goto invalid_tlv_len;
- pieces->inst_evtlog_size =
- le32_to_cpup((__le32 *)tlv_data);
- break;
- case IWL_UCODE_TLV_RUNT_ERRLOG_PTR:
- if (tlv_len != sizeof(u32))
- goto invalid_tlv_len;
- pieces->inst_errlog_ptr =
- le32_to_cpup((__le32 *)tlv_data);
- break;
- case IWL_UCODE_TLV_ENHANCE_SENS_TBL:
- if (tlv_len)
- goto invalid_tlv_len;
- nic->fw.enhance_sensitivity_table = true;
- break;
- case IWL_UCODE_TLV_WOWLAN_INST:
- pieces->wowlan_inst = tlv_data;
- pieces->wowlan_inst_size = tlv_len;
- break;
- case IWL_UCODE_TLV_WOWLAN_DATA:
- pieces->wowlan_data = tlv_data;
- pieces->wowlan_data_size = tlv_len;
- break;
- case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE:
- if (tlv_len != sizeof(u32))
- goto invalid_tlv_len;
- capa->standard_phy_calibration_size =
- le32_to_cpup((__le32 *)tlv_data);
- break;
- default:
- IWL_DEBUG_INFO(nic, "unknown TLV: %d\n", tlv_type);
- break;
- }
- }
-
- if (len) {
- IWL_ERR(nic, "invalid TLV after parsing: %zd\n", len);
- iwl_print_hex_dump(nic, IWL_DL_FW, (u8 *)data, len);
- return -EINVAL;
- }
-
- return 0;
-
- invalid_tlv_len:
- IWL_ERR(nic, "TLV %d has invalid size: %u\n", tlv_type, tlv_len);
- iwl_print_hex_dump(nic, IWL_DL_FW, tlv_data, tlv_len);
-
- return -EINVAL;
-}
-
-/**
- * iwl_ucode_callback - callback when firmware was loaded
- *
- * If loaded successfully, copies the firmware into buffers
- * for the card to fetch (via DMA).
- */
-static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
-{
- struct iwl_nic *nic = context;
- struct iwl_cfg *cfg = cfg(nic);
- struct iwl_fw *fw = &nic->fw;
- struct iwl_ucode_header *ucode;
- int err;
- struct iwlagn_firmware_pieces pieces;
- const unsigned int api_max = cfg->ucode_api_max;
- unsigned int api_ok = cfg->ucode_api_ok;
- const unsigned int api_min = cfg->ucode_api_min;
- u32 api_ver;
-
- fw->ucode_capa.max_probe_length = 200;
- fw->ucode_capa.standard_phy_calibration_size =
- IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
-
- if (!api_ok)
- api_ok = api_max;
-
- memset(&pieces, 0, sizeof(pieces));
-
- if (!ucode_raw) {
- if (nic->fw_index <= api_ok)
- IWL_ERR(nic,
- "request for firmware file '%s' failed.\n",
- nic->firmware_name);
- goto try_again;
- }
-
- IWL_DEBUG_INFO(nic, "Loaded firmware file '%s' (%zd bytes).\n",
- nic->firmware_name, ucode_raw->size);
-
- /* Make sure that we got at least the API version number */
- if (ucode_raw->size < 4) {
- IWL_ERR(nic, "File size way too small!\n");
- goto try_again;
- }
-
- /* Data from ucode file: header followed by uCode images */
- ucode = (struct iwl_ucode_header *)ucode_raw->data;
-
- if (ucode->ver)
- err = iwl_parse_v1_v2_firmware(nic, ucode_raw, &pieces);
- else
- err = iwl_parse_tlv_firmware(nic, ucode_raw, &pieces,
- &fw->ucode_capa);
-
- if (err)
- goto try_again;
-
- api_ver = IWL_UCODE_API(nic->fw.ucode_ver);
-
- /*
- * api_ver should match the api version forming part of the
- * firmware filename ... but we don't check for that and only rely
- * on the API version read from firmware header from here on forward
- */
- /* no api version check required for experimental uCode */
- if (nic->fw_index != UCODE_EXPERIMENTAL_INDEX) {
- if (api_ver < api_min || api_ver > api_max) {
- IWL_ERR(nic,
- "Driver unable to support your firmware API. "
- "Driver supports v%u, firmware is v%u.\n",
- api_max, api_ver);
- goto try_again;
- }
-
- if (api_ver < api_ok) {
- if (api_ok != api_max)
- IWL_ERR(nic, "Firmware has old API version, "
- "expected v%u through v%u, got v%u.\n",
- api_ok, api_max, api_ver);
- else
- IWL_ERR(nic, "Firmware has old API version, "
- "expected v%u, got v%u.\n",
- api_max, api_ver);
- IWL_ERR(nic, "New firmware can be obtained from "
- "http://www.intellinuxwireless.org/.\n");
- }
- }
-
- IWL_INFO(nic, "loaded firmware version %s", nic->fw.fw_version);
-
- /*
- * For any of the failures below (before allocating pci memory)
- * we will try to load a version with a smaller API -- maybe the
- * user just got a corrupted version of the latest API.
- */
-
- IWL_DEBUG_INFO(nic, "f/w package hdr ucode version raw = 0x%x\n",
- nic->fw.ucode_ver);
- IWL_DEBUG_INFO(nic, "f/w package hdr runtime inst size = %Zd\n",
- pieces.inst_size);
- IWL_DEBUG_INFO(nic, "f/w package hdr runtime data size = %Zd\n",
- pieces.data_size);
- IWL_DEBUG_INFO(nic, "f/w package hdr init inst size = %Zd\n",
- pieces.init_size);
- IWL_DEBUG_INFO(nic, "f/w package hdr init data size = %Zd\n",
- pieces.init_data_size);
-
- /* Verify that uCode images will fit in card's SRAM */
- if (pieces.inst_size > cfg->max_inst_size) {
- IWL_ERR(nic, "uCode instr len %Zd too large to fit in\n",
- pieces.inst_size);
- goto try_again;
- }
-
- if (pieces.data_size > cfg->max_data_size) {
- IWL_ERR(nic, "uCode data len %Zd too large to fit in\n",
- pieces.data_size);
- goto try_again;
- }
-
- if (pieces.init_size > cfg->max_inst_size) {
- IWL_ERR(nic, "uCode init instr len %Zd too large to fit in\n",
- pieces.init_size);
- goto try_again;
- }
-
- if (pieces.init_data_size > cfg->max_data_size) {
- IWL_ERR(nic, "uCode init data len %Zd too large to fit in\n",
- pieces.init_data_size);
- goto try_again;
- }
-
- /* Allocate ucode buffers for card's bus-master loading ... */
-
- /* Runtime instructions and 2 copies of data:
- * 1) unmodified from disk
- * 2) backup cache for save/restore during power-downs */
- if (iwl_alloc_fw_desc(nic, &nic->fw.ucode_rt.code,
- pieces.inst, pieces.inst_size))
- goto err_pci_alloc;
- if (iwl_alloc_fw_desc(nic, &nic->fw.ucode_rt.data,
- pieces.data, pieces.data_size))
- goto err_pci_alloc;
-
- /* Initialization instructions and data */
- if (pieces.init_size && pieces.init_data_size) {
- if (iwl_alloc_fw_desc(nic,
- &nic->fw.ucode_init.code,
- pieces.init, pieces.init_size))
- goto err_pci_alloc;
- if (iwl_alloc_fw_desc(nic,
- &nic->fw.ucode_init.data,
- pieces.init_data, pieces.init_data_size))
- goto err_pci_alloc;
- }
-
- /* WoWLAN instructions and data */
- if (pieces.wowlan_inst_size && pieces.wowlan_data_size) {
- if (iwl_alloc_fw_desc(nic,
- &nic->fw.ucode_wowlan.code,
- pieces.wowlan_inst,
- pieces.wowlan_inst_size))
- goto err_pci_alloc;
- if (iwl_alloc_fw_desc(nic,
- &nic->fw.ucode_wowlan.data,
- pieces.wowlan_data,
- pieces.wowlan_data_size))
- goto err_pci_alloc;
- }
-
- /* Now that we can no longer fail, copy information */
-
- /*
- * The (size - 16) / 12 formula is based on the information recorded
- * for each event, which is of mode 1 (including timestamp) for all
- * new microcodes that include this information.
- */
- nic->init_evtlog_ptr = pieces.init_evtlog_ptr;
- if (pieces.init_evtlog_size)
- nic->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
- else
- nic->init_evtlog_size =
- cfg->base_params->max_event_log_size;
- nic->init_errlog_ptr = pieces.init_errlog_ptr;
- nic->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
- if (pieces.inst_evtlog_size)
- nic->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
- else
- nic->inst_evtlog_size =
- cfg->base_params->max_event_log_size;
- nic->inst_errlog_ptr = pieces.inst_errlog_ptr;
-
- /*
- * figure out the offset of chain noise reset and gain commands
- * base on the size of standard phy calibration commands table size
- */
- if (fw->ucode_capa.standard_phy_calibration_size >
- IWL_MAX_PHY_CALIBRATE_TBL_SIZE)
- fw->ucode_capa.standard_phy_calibration_size =
- IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE;
-
- /* We have our copies now, allow OS release its copies */
- release_firmware(ucode_raw);
- complete(&nic->request_firmware_complete);
-
- nic->op_mode = iwl_dvm_ops.start(nic->shrd->trans);
-
- if (!nic->op_mode)
- goto out_unbind;
-
- return;
-
- try_again:
- /* try next, if any */
- release_firmware(ucode_raw);
- if (iwl_request_firmware(nic, false))
- goto out_unbind;
- return;
-
- err_pci_alloc:
- IWL_ERR(nic, "failed to allocate pci memory\n");
- iwl_dealloc_ucode(nic);
- release_firmware(ucode_raw);
- out_unbind:
- complete(&nic->request_firmware_complete);
- device_release_driver(trans(nic)->dev);
-}
-
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index ba16f05df0f..b4f6cb3298a 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -27,6 +27,7 @@
#include <linux/etherdevice.h>
#include <linux/debugfs.h>
#include <linux/module.h>
+#include <linux/ktime.h>
#include <net/genetlink.h>
#include "mac80211_hwsim.h"
@@ -321,11 +322,15 @@ struct mac80211_hwsim_data {
struct dentry *debugfs_group;
int power_level;
+
+ /* difference between this hw's clock and the real clock, in usecs */
+ u64 tsf_offset;
};
struct hwsim_radiotap_hdr {
struct ieee80211_radiotap_header hdr;
+ __le64 rt_tsft;
u8 rt_flags;
u8 rt_rate;
__le16 rt_channel;
@@ -367,6 +372,28 @@ static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data)
+{
+ struct timeval tv = ktime_to_timeval(ktime_get_real());
+ u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec;
+ return cpu_to_le64(now + data->tsf_offset);
+}
+
+static u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct mac80211_hwsim_data *data = hw->priv;
+ return le64_to_cpu(__mac80211_hwsim_get_tsf(data));
+}
+
+static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u64 tsf)
+{
+ struct mac80211_hwsim_data *data = hw->priv;
+ struct timeval tv = ktime_to_timeval(ktime_get_real());
+ u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec;
+ data->tsf_offset = tsf - now;
+}
static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
struct sk_buff *tx_skb)
@@ -391,7 +418,9 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr));
hdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
(1 << IEEE80211_RADIOTAP_RATE) |
+ (1 << IEEE80211_RADIOTAP_TSFT) |
(1 << IEEE80211_RADIOTAP_CHANNEL));
+ hdr->rt_tsft = __mac80211_hwsim_get_tsf(data);
hdr->rt_flags = 0;
hdr->rt_rate = txrate->bitrate / 5;
hdr->rt_channel = cpu_to_le16(data->channel->center_freq);
@@ -610,7 +639,8 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
}
memset(&rx_status, 0, sizeof(rx_status));
- /* TODO: set mactime */
+ rx_status.mactime = le64_to_cpu(__mac80211_hwsim_get_tsf(data));
+ rx_status.flag |= RX_FLAG_MACTIME_MPDU;
rx_status.freq = data->channel->center_freq;
rx_status.band = data->channel->band;
rx_status.rate_idx = info->control.rates[0].idx;
@@ -667,6 +697,12 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
bool ack;
struct ieee80211_tx_info *txi;
u32 _pid;
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
+ struct mac80211_hwsim_data *data = hw->priv;
+
+ if (ieee80211_is_beacon(mgmt->frame_control) ||
+ ieee80211_is_probe_resp(mgmt->frame_control))
+ mgmt->u.beacon.timestamp = __mac80211_hwsim_get_tsf(data);
mac80211_hwsim_monitor_rx(hw, skb);
@@ -763,9 +799,11 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
struct ieee80211_vif *vif)
{
struct ieee80211_hw *hw = arg;
+ struct mac80211_hwsim_data *data = hw->priv;
struct sk_buff *skb;
struct ieee80211_tx_info *info;
u32 _pid;
+ struct ieee80211_mgmt *mgmt;
hwsim_check_magic(vif);
@@ -779,6 +817,9 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
return;
info = IEEE80211_SKB_CB(skb);
+ mgmt = (struct ieee80211_mgmt *) skb->data;
+ mgmt->u.beacon.timestamp = __mac80211_hwsim_get_tsf(data);
+
mac80211_hwsim_monitor_rx(hw, skb);
/* wmediumd mode check */
@@ -1199,6 +1240,8 @@ static struct ieee80211_ops mac80211_hwsim_ops =
.sw_scan_start = mac80211_hwsim_sw_scan,
.sw_scan_complete = mac80211_hwsim_sw_scan_complete,
.flush = mac80211_hwsim_flush,
+ .get_tsf = mac80211_hwsim_get_tsf,
+ .set_tsf = mac80211_hwsim_set_tsf,
};
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index a460fb0cc50..84508b06526 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -613,7 +613,6 @@ static struct ieee80211_rate mwifiex_rates[] = {
{.bitrate = 20, .hw_value = 4, },
{.bitrate = 55, .hw_value = 11, },
{.bitrate = 110, .hw_value = 22, },
- {.bitrate = 220, .hw_value = 44, },
{.bitrate = 60, .hw_value = 12, },
{.bitrate = 90, .hw_value = 18, },
{.bitrate = 120, .hw_value = 24, },
@@ -622,7 +621,6 @@ static struct ieee80211_rate mwifiex_rates[] = {
{.bitrate = 360, .hw_value = 72, },
{.bitrate = 480, .hw_value = 96, },
{.bitrate = 540, .hw_value = 108, },
- {.bitrate = 720, .hw_value = 144, },
};
/* Channel definitions to be advertised to cfg80211 */
@@ -648,7 +646,7 @@ static struct ieee80211_supported_band mwifiex_band_2ghz = {
.channels = mwifiex_channels_2ghz,
.n_channels = ARRAY_SIZE(mwifiex_channels_2ghz),
.bitrates = mwifiex_rates,
- .n_bitrates = 14,
+ .n_bitrates = ARRAY_SIZE(mwifiex_rates),
};
static struct ieee80211_channel mwifiex_channels_5ghz[] = {
@@ -688,8 +686,8 @@ static struct ieee80211_channel mwifiex_channels_5ghz[] = {
static struct ieee80211_supported_band mwifiex_band_5ghz = {
.channels = mwifiex_channels_5ghz,
.n_channels = ARRAY_SIZE(mwifiex_channels_5ghz),
- .bitrates = mwifiex_rates - 4,
- .n_bitrates = ARRAY_SIZE(mwifiex_rates) + 4,
+ .bitrates = mwifiex_rates + 4,
+ .n_bitrates = ARRAY_SIZE(mwifiex_rates) - 4,
};
@@ -841,12 +839,12 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
u8 *bssid, int mode, struct ieee80211_channel *channel,
struct cfg80211_connect_params *sme, bool privacy)
{
- struct mwifiex_802_11_ssid req_ssid;
+ struct cfg80211_ssid req_ssid;
int ret, auth_type = 0;
struct cfg80211_bss *bss = NULL;
u8 is_scanning_required = 0;
- memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid));
+ memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));
req_ssid.ssid_len = ssid_len;
if (ssid_len > IEEE80211_MAX_SSID_LEN) {
@@ -873,6 +871,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
priv->sec_info.wpa2_enabled = false;
priv->wep_key_curr_index = 0;
priv->sec_info.encryption_mode = 0;
+ priv->sec_info.is_authtype_auto = 0;
ret = mwifiex_set_encode(priv, NULL, 0, 0, 1);
if (mode == NL80211_IFTYPE_ADHOC) {
@@ -894,11 +893,12 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
}
/* Now handle infra mode. "sme" is valid for infra mode only */
- if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC
- || sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM)
+ if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
- else if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY)
- auth_type = NL80211_AUTHTYPE_SHARED_KEY;
+ priv->sec_info.is_authtype_auto = 1;
+ } else {
+ auth_type = sme->auth_type;
+ }
if (sme->crypto.n_ciphers_pairwise) {
priv->sec_info.encryption_mode =
@@ -1106,12 +1106,10 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev,
dev_err(priv->adapter->dev, "failed to alloc scan_req\n");
return -ENOMEM;
}
- for (i = 0; i < request->n_ssids; i++) {
- memcpy(priv->user_scan_cfg->ssid_list[i].ssid,
- request->ssids[i].ssid, request->ssids[i].ssid_len);
- priv->user_scan_cfg->ssid_list[i].max_len =
- request->ssids[i].ssid_len;
- }
+
+ priv->user_scan_cfg->num_ssids = request->n_ssids;
+ priv->user_scan_cfg->ssid_list = request->ssids;
+
for (i = 0; i < request->n_channels; i++) {
chan = request->channels[i];
priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 6623db69e15..c82eb7ff2fa 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -771,7 +771,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
/* Check init command response */
if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) {
- if (ret == -1) {
+ if (ret) {
dev_err(adapter->dev, "%s: cmd %#x failed during "
"initialization\n", __func__, cmdresp_no);
mwifiex_init_fw_complete(adapter);
@@ -781,10 +781,8 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
}
if (adapter->curr_cmd) {
- if (adapter->curr_cmd->wait_q_enabled && (!ret))
- adapter->cmd_wait_q.status = 0;
- else if (adapter->curr_cmd->wait_q_enabled && (ret == -1))
- adapter->cmd_wait_q.status = -1;
+ if (adapter->curr_cmd->wait_q_enabled)
+ adapter->cmd_wait_q.status = ret;
/* Clean up and put current command back to cmd_free_q */
mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 3735c775495..be5fd1652e5 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -91,11 +91,6 @@ struct mwifiex_fw_image {
u32 fw_len;
};
-struct mwifiex_802_11_ssid {
- u32 ssid_len;
- u8 ssid[IEEE80211_MAX_SSID_LEN];
-};
-
struct mwifiex_wait_queue {
wait_queue_head_t wait;
int status;
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index c82620094a5..fc4ffee6c6b 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -852,11 +852,6 @@ struct mwifiex_user_scan_chan {
u32 scan_time;
} __packed;
-struct mwifiex_user_scan_ssid {
- u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
- u8 max_len;
-} __packed;
-
struct mwifiex_user_scan_cfg {
/*
* BSS mode to be sent in the firmware command
@@ -867,8 +862,9 @@ struct mwifiex_user_scan_cfg {
u8 reserved;
/* BSSID filter sent in the firmware command to limit the results */
u8 specific_bssid[ETH_ALEN];
- /* SSID filter list used in the to limit the scan results */
- struct mwifiex_user_scan_ssid ssid_list[MWIFIEX_MAX_SSID_LIST_LENGTH];
+ /* SSID filter list used in the firmware to limit the scan results */
+ struct cfg80211_ssid *ssid_list;
+ u8 num_ssids;
/* Variable number (fixed maximum) of channels to scan up */
struct mwifiex_user_scan_chan chan_list[MWIFIEX_USER_SCAN_CHAN_MAX];
} __packed;
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index d5d81f1fe41..7ca4e8234f3 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -50,7 +50,7 @@ struct mwifiex_chan_freq {
};
struct mwifiex_ssid_bssid {
- struct mwifiex_802_11_ssid ssid;
+ struct cfg80211_ssid ssid;
u8 bssid[ETH_ALEN];
};
@@ -122,7 +122,7 @@ struct mwifiex_ver_ext {
struct mwifiex_bss_info {
u32 bss_mode;
- struct mwifiex_802_11_ssid ssid;
+ struct cfg80211_ssid ssid;
u32 bss_chan;
u32 region_code;
u32 media_connected;
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index ee439fc2f4f..bce9991612c 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -585,7 +585,7 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
le16_to_cpu(assoc_rsp->cap_info_bitmap),
le16_to_cpu(assoc_rsp->a_id));
- ret = -1;
+ ret = le16_to_cpu(assoc_rsp->status_code);
goto done;
}
@@ -714,7 +714,7 @@ done:
int
mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- struct mwifiex_802_11_ssid *req_ssid)
+ struct cfg80211_ssid *req_ssid)
{
int rsn_ie_len = 0;
struct mwifiex_adapter *adapter = priv->adapter;
@@ -1245,7 +1245,7 @@ int mwifiex_associate(struct mwifiex_private *priv,
*/
int
mwifiex_adhoc_start(struct mwifiex_private *priv,
- struct mwifiex_802_11_ssid *adhoc_ssid)
+ struct cfg80211_ssid *adhoc_ssid)
{
dev_dbg(priv->adapter->dev, "info: Adhoc Channel = %d\n",
priv->adhoc_channel);
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 4c862170627..6dc11664741 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -219,6 +219,7 @@ struct mwifiex_802_11_security {
u8 wapi_key_on;
u8 wep_enabled;
u32 authentication_mode;
+ u8 is_authtype_auto;
u32 encryption_mode;
};
@@ -243,7 +244,7 @@ struct ieee_types_generic {
struct mwifiex_bssdescriptor {
u8 mac_address[ETH_ALEN];
- struct mwifiex_802_11_ssid ssid;
+ struct cfg80211_ssid ssid;
u32 privacy;
s32 rssi;
u32 channel;
@@ -387,7 +388,7 @@ struct mwifiex_private {
s16 bcn_rssi_avg;
s16 bcn_nf_avg;
struct mwifiex_bssdescriptor *attempted_bss_desc;
- struct mwifiex_802_11_ssid prev_ssid;
+ struct cfg80211_ssid prev_ssid;
u8 prev_bssid[ETH_ALEN];
struct mwifiex_current_bss_params curr_bss_params;
u16 beacon_period;
@@ -746,8 +747,7 @@ void mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
struct cmd_ctrl_node *cmd_node);
int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
-s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
- struct mwifiex_802_11_ssid *ssid2);
+s32 mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2);
int mwifiex_associate(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc);
int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
@@ -759,12 +759,12 @@ void mwifiex_reset_connect_state(struct mwifiex_private *priv);
u8 mwifiex_band_to_radio_type(u8 band);
int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac);
int mwifiex_adhoc_start(struct mwifiex_private *priv,
- struct mwifiex_802_11_ssid *adhoc_ssid);
+ struct cfg80211_ssid *adhoc_ssid);
int mwifiex_adhoc_join(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc);
int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- struct mwifiex_802_11_ssid *req_ssid);
+ struct cfg80211_ssid *req_ssid);
int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
struct mwifiex_bssdescriptor *bss_desc);
@@ -897,7 +897,7 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
struct net_device *dev);
int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter);
int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
- struct mwifiex_802_11_ssid *req_ssid);
+ struct cfg80211_ssid *req_ssid);
int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
int mwifiex_enable_hs(struct mwifiex_adapter *adapter);
int mwifiex_disable_auto_ds(struct mwifiex_private *priv);
@@ -906,13 +906,12 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv,
int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
struct mwifiex_rate_cfg *rate);
int mwifiex_request_scan(struct mwifiex_private *priv,
- struct mwifiex_802_11_ssid *req_ssid);
+ struct cfg80211_ssid *req_ssid);
int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
struct mwifiex_user_scan_cfg *scan_req);
-int mwifiex_change_adhoc_chan(struct mwifiex_private *priv, int channel);
int mwifiex_set_radio(struct mwifiex_private *priv, u8 option);
-int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel);
+int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel);
int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key,
int key_len, u8 key_index, int disable);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 8f10038d1b4..fd0302fe5bd 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -163,8 +163,7 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
* This function compares two SSIDs and checks if they match.
*/
s32
-mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
- struct mwifiex_802_11_ssid *ssid2)
+mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2)
{
if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len))
return -1;
@@ -738,7 +737,7 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv,
u16 scan_dur;
u8 channel;
u8 radio_type;
- u32 ssid_idx;
+ int i;
u8 ssid_filter;
u8 rates[MWIFIEX_SUPPORTED_RATES];
u32 rates_size;
@@ -793,14 +792,8 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv,
user_scan_in->specific_bssid,
sizeof(scan_cfg_out->specific_bssid));
- for (ssid_idx = 0;
- ((ssid_idx < ARRAY_SIZE(user_scan_in->ssid_list))
- && (*user_scan_in->ssid_list[ssid_idx].ssid
- || user_scan_in->ssid_list[ssid_idx].max_len));
- ssid_idx++) {
-
- ssid_len = strlen(user_scan_in->ssid_list[ssid_idx].
- ssid) + 1;
+ for (i = 0; i < user_scan_in->num_ssids; i++) {
+ ssid_len = user_scan_in->ssid_list[i].ssid_len;
wildcard_ssid_tlv =
(struct mwifiex_ie_types_wildcard_ssid_params *)
@@ -811,19 +804,26 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv,
(u16) (ssid_len + sizeof(wildcard_ssid_tlv->
max_ssid_length)));
- /* max_ssid_length = 0 tells firmware to perform
- specific scan for the SSID filled */
- wildcard_ssid_tlv->max_ssid_length = 0;
+ /*
+ * max_ssid_length = 0 tells firmware to perform
+ * specific scan for the SSID filled, whereas
+ * max_ssid_length = IEEE80211_MAX_SSID_LEN is for
+ * wildcard scan.
+ */
+ if (ssid_len)
+ wildcard_ssid_tlv->max_ssid_length = 0;
+ else
+ wildcard_ssid_tlv->max_ssid_length =
+ IEEE80211_MAX_SSID_LEN;
memcpy(wildcard_ssid_tlv->ssid,
- user_scan_in->ssid_list[ssid_idx].ssid,
- ssid_len);
+ user_scan_in->ssid_list[i].ssid, ssid_len);
tlv_pos += (sizeof(wildcard_ssid_tlv->header)
+ le16_to_cpu(wildcard_ssid_tlv->header.len));
- dev_dbg(adapter->dev, "info: scan: ssid_list[%d]: %s, %d\n",
- ssid_idx, wildcard_ssid_tlv->ssid,
+ dev_dbg(adapter->dev, "info: scan: ssid[%d]: %s, %d\n",
+ i, wildcard_ssid_tlv->ssid,
wildcard_ssid_tlv->max_ssid_length);
/* Empty wildcard ssid with a maxlen will match many or
@@ -832,7 +832,6 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv,
filtered. */
if (!ssid_len && wildcard_ssid_tlv->max_ssid_length)
ssid_filter = false;
-
}
/*
@@ -841,7 +840,7 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv,
* truncate scan results. That is not an issue with an SSID
* or BSSID filter applied to the scan results in the firmware.
*/
- if ((ssid_idx && ssid_filter)
+ if ((i && ssid_filter)
|| memcmp(scan_cfg_out->specific_bssid, &zero_mac,
sizeof(zero_mac)))
*filtered_scan = true;
@@ -1851,7 +1850,7 @@ mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
* firmware, filtered on a specific SSID.
*/
static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
- struct mwifiex_802_11_ssid *req_ssid)
+ struct cfg80211_ssid *req_ssid)
{
struct mwifiex_adapter *adapter = priv->adapter;
int ret = 0;
@@ -1877,8 +1876,8 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
return -ENOMEM;
}
- memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid,
- req_ssid->ssid_len);
+ scan_cfg->ssid_list = req_ssid;
+ scan_cfg->num_ssids = 1;
ret = mwifiex_scan_networks(priv, scan_cfg);
@@ -1896,7 +1895,7 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
* scan, depending upon whether an SSID is provided or not.
*/
int mwifiex_request_scan(struct mwifiex_private *priv,
- struct mwifiex_802_11_ssid *req_ssid)
+ struct cfg80211_ssid *req_ssid)
{
int ret;
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index d7aa21da84d..b9b59db6045 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -101,7 +101,7 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv)
memcpy(&priv->prev_ssid,
&priv->curr_bss_params.bss_descriptor.ssid,
- sizeof(struct mwifiex_802_11_ssid));
+ sizeof(struct cfg80211_ssid));
memcpy(priv->prev_bssid,
priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN);
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 866026ecca4..0ae1209646c 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -192,7 +192,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
* first.
*/
int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
- struct mwifiex_802_11_ssid *req_ssid)
+ struct cfg80211_ssid *req_ssid)
{
int ret;
struct mwifiex_adapter *adapter = priv->adapter;
@@ -249,6 +249,17 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
* application retrieval */
priv->assoc_rsp_size = 0;
ret = mwifiex_associate(priv, bss_desc);
+
+ /* If auth type is auto and association fails using open mode,
+ * try to connect using shared mode */
+ if (ret == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG &&
+ priv->sec_info.is_authtype_auto &&
+ priv->sec_info.wep_enabled) {
+ priv->sec_info.authentication_mode =
+ NL80211_AUTHTYPE_SHARED_KEY;
+ ret = mwifiex_associate(priv, bss_desc);
+ }
+
if (bss)
cfg80211_put_bss(bss);
} else {
@@ -453,8 +464,7 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,
info->bss_mode = priv->bss_mode;
- memcpy(&info->ssid, &bss_desc->ssid,
- sizeof(struct mwifiex_802_11_ssid));
+ memcpy(&info->ssid, &bss_desc->ssid, sizeof(struct cfg80211_ssid));
memcpy(&info->bssid, &bss_desc->mac_address, ETH_ALEN);
@@ -599,7 +609,7 @@ static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv,
* - Start/Join the IBSS
*/
int
-mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
+mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel)
{
int ret;
struct mwifiex_bss_info bss_info;
@@ -636,7 +646,7 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
ret = mwifiex_deauthenticate(priv, ssid_bssid.bssid);
ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_SET,
- (u16 *) &channel);
+ &channel);
/* Do specific SSID scanning */
if (mwifiex_request_scan(priv, &bss_info.ssid)) {
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index 40f4eb7da7b..ee8af1f047c 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -227,6 +227,7 @@ static int p54_add_interface(struct ieee80211_hw *dev,
struct ieee80211_vif *vif)
{
struct p54_common *priv = dev->priv;
+ int err;
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
@@ -251,9 +252,9 @@ static int p54_add_interface(struct ieee80211_hw *dev,
}
memcpy(priv->mac_addr, vif->addr, ETH_ALEN);
- p54_setup_mac(priv);
+ err = p54_setup_mac(priv);
mutex_unlock(&priv->conf_mutex);
- return 0;
+ return err;
}
static void p54_remove_interface(struct ieee80211_hw *dev,
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index b1f51a21579..45df728183f 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -624,36 +624,39 @@ static void __devexit p54p_remove(struct pci_dev *pdev)
}
#ifdef CONFIG_PM
-static int p54p_suspend(struct pci_dev *pdev, pm_message_t state)
+static int p54p_suspend(struct device *device)
{
- struct ieee80211_hw *dev = pci_get_drvdata(pdev);
- struct p54p_priv *priv = dev->priv;
-
- if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) {
- ieee80211_stop_queues(dev);
- p54p_stop(dev);
- }
+ struct pci_dev *pdev = to_pci_dev(device);
pci_save_state(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ pci_set_power_state(pdev, PCI_D3hot);
+ pci_disable_device(pdev);
return 0;
}
-static int p54p_resume(struct pci_dev *pdev)
+static int p54p_resume(struct device *device)
{
- struct ieee80211_hw *dev = pci_get_drvdata(pdev);
- struct p54p_priv *priv = dev->priv;
+ struct pci_dev *pdev = to_pci_dev(device);
+ int err;
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
+ err = pci_reenable_device(pdev);
+ if (err)
+ return err;
+ return pci_set_power_state(pdev, PCI_D0);
+}
- if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) {
- p54p_open(dev);
- ieee80211_wake_queues(dev);
- }
+static const struct dev_pm_ops p54pci_pm_ops = {
+ .suspend = p54p_suspend,
+ .resume = p54p_resume,
+ .freeze = p54p_suspend,
+ .thaw = p54p_resume,
+ .poweroff = p54p_suspend,
+ .restore = p54p_resume,
+};
- return 0;
-}
+#define P54P_PM_OPS (&p54pci_pm_ops)
+#else
+#define P54P_PM_OPS (NULL)
#endif /* CONFIG_PM */
static struct pci_driver p54p_driver = {
@@ -661,10 +664,7 @@ static struct pci_driver p54p_driver = {
.id_table = p54p_table,
.probe = p54p_probe,
.remove = __devexit_p(p54p_remove),
-#ifdef CONFIG_PM
- .suspend = p54p_suspend,
- .resume = p54p_resume,
-#endif /* CONFIG_PM */
+ .driver.pm = P54P_PM_OPS,
};
static int __init p54p_init(void)
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index 7faed62c637..f7929906d43 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -618,19 +618,19 @@ static int __devinit p54spi_probe(struct spi_device *spi)
ret = spi_setup(spi);
if (ret < 0) {
dev_err(&priv->spi->dev, "spi_setup failed");
- goto err_free_common;
+ goto err_free;
}
ret = gpio_request(p54spi_gpio_power, "p54spi power");
if (ret < 0) {
dev_err(&priv->spi->dev, "power GPIO request failed: %d", ret);
- goto err_free_common;
+ goto err_free;
}
ret = gpio_request(p54spi_gpio_irq, "p54spi irq");
if (ret < 0) {
dev_err(&priv->spi->dev, "irq GPIO request failed: %d", ret);
- goto err_free_common;
+ goto err_free_gpio_power;
}
gpio_direction_output(p54spi_gpio_power, 0);
@@ -641,7 +641,7 @@ static int __devinit p54spi_probe(struct spi_device *spi)
priv->spi);
if (ret < 0) {
dev_err(&priv->spi->dev, "request_irq() failed");
- goto err_free_common;
+ goto err_free_gpio_irq;
}
irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING);
@@ -673,6 +673,12 @@ static int __devinit p54spi_probe(struct spi_device *spi)
return 0;
err_free_common:
+ free_irq(gpio_to_irq(p54spi_gpio_irq), spi);
+err_free_gpio_irq:
+ gpio_free(p54spi_gpio_irq);
+err_free_gpio_power:
+ gpio_free(p54spi_gpio_power);
+err_free:
p54_free_common(priv->hw);
return ret;
}
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index a330c69583d..d66e2980bc2 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -518,7 +518,7 @@ struct rndis_wlan_private {
__le32 current_command_oid;
/* encryption stuff */
- int encr_tx_key_index;
+ u8 encr_tx_key_index;
struct rndis_wlan_encr_key encr_keys[RNDIS_WLAN_NUM_KEYS];
int wpa_version;
@@ -634,7 +634,7 @@ static u32 get_bcm4320_power_dbm(struct rndis_wlan_private *priv)
}
}
-static bool is_wpa_key(struct rndis_wlan_private *priv, int idx)
+static bool is_wpa_key(struct rndis_wlan_private *priv, u8 idx)
{
int cipher = priv->encr_keys[idx].cipher;
@@ -1350,7 +1350,7 @@ static int set_channel(struct usbnet *usbdev, int channel)
}
static struct ieee80211_channel *get_current_channel(struct usbnet *usbdev,
- u16 *beacon_interval)
+ u32 *beacon_period)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
struct ieee80211_channel *channel;
@@ -1370,14 +1370,14 @@ static struct ieee80211_channel *get_current_channel(struct usbnet *usbdev,
if (!channel)
return NULL;
- if (beacon_interval)
- *beacon_interval = le16_to_cpu(config.beacon_period);
+ if (beacon_period)
+ *beacon_period = le32_to_cpu(config.beacon_period);
return channel;
}
/* index must be 0 - N, as per NDIS */
static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len,
- int index)
+ u8 index)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
struct ndis_80211_wep_key ndis_key;
@@ -1387,13 +1387,15 @@ static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len,
netdev_dbg(usbdev->net, "%s(idx: %d, len: %d)\n",
__func__, index, key_len);
- if ((key_len != 5 && key_len != 13) || index < 0 || index > 3)
+ if (index >= RNDIS_WLAN_NUM_KEYS)
return -EINVAL;
if (key_len == 5)
cipher = WLAN_CIPHER_SUITE_WEP40;
- else
+ else if (key_len == 13)
cipher = WLAN_CIPHER_SUITE_WEP104;
+ else
+ return -EINVAL;
memset(&ndis_key, 0, sizeof(ndis_key));
@@ -1428,7 +1430,7 @@ static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len,
}
static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
- int index, const u8 *addr, const u8 *rx_seq,
+ u8 index, const u8 *addr, const u8 *rx_seq,
int seq_len, u32 cipher, __le32 flags)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
@@ -1436,7 +1438,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
bool is_addr_ok;
int ret;
- if (index < 0 || index >= 4) {
+ if (index >= RNDIS_WLAN_NUM_KEYS) {
netdev_dbg(usbdev->net, "%s(): index out of range (%i)\n",
__func__, index);
return -EINVAL;
@@ -1524,7 +1526,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
return 0;
}
-static int restore_key(struct usbnet *usbdev, int key_idx)
+static int restore_key(struct usbnet *usbdev, u8 key_idx)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
struct rndis_wlan_encr_key key;
@@ -1550,13 +1552,13 @@ static void restore_keys(struct usbnet *usbdev)
restore_key(usbdev, i);
}
-static void clear_key(struct rndis_wlan_private *priv, int idx)
+static void clear_key(struct rndis_wlan_private *priv, u8 idx)
{
memset(&priv->encr_keys[idx], 0, sizeof(priv->encr_keys[idx]));
}
/* remove_key is for both wep and wpa */
-static int remove_key(struct usbnet *usbdev, int index, const u8 *bssid)
+static int remove_key(struct usbnet *usbdev, u8 index, const u8 *bssid)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
struct ndis_80211_remove_key remove_key;
@@ -1790,9 +1792,9 @@ static struct ndis_80211_pmkid *remove_pmkid(struct usbnet *usbdev,
struct cfg80211_pmksa *pmksa,
int max_pmkids)
{
- int i, len, count, newlen, err;
+ int i, newlen, err;
+ unsigned int count;
- len = le32_to_cpu(pmkids->length);
count = le32_to_cpu(pmkids->bssid_info_count);
if (count > max_pmkids)
@@ -1831,9 +1833,9 @@ static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev,
struct cfg80211_pmksa *pmksa,
int max_pmkids)
{
- int i, err, len, count, newlen;
+ int i, err, newlen;
+ unsigned int count;
- len = le32_to_cpu(pmkids->length);
count = le32_to_cpu(pmkids->bssid_info_count);
if (count > max_pmkids)
@@ -2683,7 +2685,7 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid,
s32 signal;
u64 timestamp;
u16 capability;
- u16 beacon_interval = 0;
+ u32 beacon_period = 0;
__le32 rssi;
u8 ie_buf[34];
int len, ret, ie_len;
@@ -2708,7 +2710,7 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid,
}
/* Get channel and beacon interval */
- channel = get_current_channel(usbdev, &beacon_interval);
+ channel = get_current_channel(usbdev, &beacon_period);
if (!channel) {
netdev_warn(usbdev->net, "%s(): could not get channel.\n",
__func__);
@@ -2738,11 +2740,11 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid,
netdev_dbg(usbdev->net, "%s(): channel:%d(freq), bssid:[%pM], tsf:%d, "
"capa:%x, beacon int:%d, resp_ie(len:%d, essid:'%.32s'), "
"signal:%d\n", __func__, (channel ? channel->center_freq : -1),
- bssid, (u32)timestamp, capability, beacon_interval, ie_len,
+ bssid, (u32)timestamp, capability, beacon_period, ie_len,
ssid.essid, signal);
bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid,
- timestamp, capability, beacon_interval, ie_buf, ie_len,
+ timestamp, capability, beacon_period, ie_buf, ie_len,
signal, GFP_KERNEL);
cfg80211_put_bss(bss);
}
@@ -2755,9 +2757,10 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
struct ndis_80211_assoc_info *info = NULL;
u8 bssid[ETH_ALEN];
- int resp_ie_len, req_ie_len;
+ unsigned int resp_ie_len, req_ie_len;
+ unsigned int offset;
u8 *req_ie, *resp_ie;
- int ret, offset;
+ int ret;
bool roamed = false;
bool match_bss;
@@ -2785,7 +2788,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
ret = get_association_info(usbdev, info, CONTROL_BUFFER_SIZE);
if (!ret) {
req_ie_len = le32_to_cpu(info->req_ie_length);
- if (req_ie_len > 0) {
+ if (req_ie_len > CONTROL_BUFFER_SIZE)
+ req_ie_len = CONTROL_BUFFER_SIZE;
+ if (req_ie_len != 0) {
offset = le32_to_cpu(info->offset_req_ies);
if (offset > CONTROL_BUFFER_SIZE)
@@ -2799,7 +2804,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
}
resp_ie_len = le32_to_cpu(info->resp_ie_length);
- if (resp_ie_len > 0) {
+ if (resp_ie_len > CONTROL_BUFFER_SIZE)
+ resp_ie_len = CONTROL_BUFFER_SIZE;
+ if (resp_ie_len != 0) {
offset = le32_to_cpu(info->offset_resp_ies);
if (offset > CONTROL_BUFFER_SIZE)
@@ -3038,7 +3045,7 @@ static void rndis_wlan_media_specific_indication(struct usbnet *usbdev,
struct rndis_indicate *msg, int buflen)
{
struct ndis_80211_status_indication *indication;
- int len, offset;
+ unsigned int len, offset;
offset = offsetof(struct rndis_indicate, status) +
le32_to_cpu(msg->offset);
@@ -3050,7 +3057,7 @@ static void rndis_wlan_media_specific_indication(struct usbnet *usbdev,
return;
}
- if (offset + len > buflen) {
+ if (len > buflen || offset > buflen || offset + len > buflen) {
netdev_info(usbdev->net, "media specific indication, too large to fit to buffer (%i > %i)\n",
offset + len, buflen);
return;
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c
index 638fbef693e..cf53ac9d6f2 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c
@@ -8,7 +8,7 @@
* Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
*
* The driver was extended to the RTL8187B in 2008 by:
- * Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+ * Herton Ronaldo Krzesinski <herton@mandriva.com.br>
* Hin-Tak Leung <htl10@users.sourceforge.net>
* Larry Finger <Larry.Finger@lwfinger.net>
*
@@ -232,6 +232,7 @@ static void rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct rtl8187_priv *priv = dev->priv;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *tx_hdr = (struct ieee80211_hdr *)(skb->data);
unsigned int ep;
void *buf;
struct urb *urb;
@@ -249,7 +250,7 @@ static void rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
flags |= RTL818X_TX_DESC_FLAG_NO_ENC;
flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24;
- if (ieee80211_has_morefrags(((struct ieee80211_hdr *)skb->data)->frame_control))
+ if (ieee80211_has_morefrags(tx_hdr->frame_control))
flags |= RTL818X_TX_DESC_FLAG_MOREFRAG;
if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
flags |= RTL818X_TX_DESC_FLAG_RTS;
@@ -261,6 +262,13 @@ static void rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
}
+ if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+ if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+ priv->seqno += 0x10;
+ tx_hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+ tx_hdr->seq_ctrl |= cpu_to_le16(priv->seqno);
+ }
+
if (!priv->is_rtl8187b) {
struct rtl8187_tx_hdr *hdr =
(struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
@@ -274,8 +282,6 @@ static void rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
} else {
/* fc needs to be calculated before skb_push() */
unsigned int epmap[4] = { 6, 7, 5, 4 };
- struct ieee80211_hdr *tx_hdr =
- (struct ieee80211_hdr *)(skb->data);
u16 fc = le16_to_cpu(tx_hdr->frame_control);
struct rtl8187b_tx_hdr *hdr =
@@ -1031,10 +1037,61 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
cancel_delayed_work_sync(&priv->work);
}
+static u64 rtl8187_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif)
+{
+ struct rtl8187_priv *priv = dev->priv;
+
+ return rtl818x_ioread32(priv, &priv->map->TSFT[0]) |
+ (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32;
+}
+
+
+static void rtl8187_beacon_work(struct work_struct *work)
+{
+ struct rtl8187_vif *vif_priv =
+ container_of(work, struct rtl8187_vif, beacon_work.work);
+ struct ieee80211_vif *vif =
+ container_of((void *)vif_priv, struct ieee80211_vif, drv_priv);
+ struct ieee80211_hw *dev = vif_priv->dev;
+ struct ieee80211_mgmt *mgmt;
+ struct sk_buff *skb;
+
+ /* don't overflow the tx ring */
+ if (ieee80211_queue_stopped(dev, 0))
+ goto resched;
+
+ /* grab a fresh beacon */
+ skb = ieee80211_beacon_get(dev, vif);
+ if (!skb)
+ goto resched;
+
+ /*
+ * update beacon timestamp w/ TSF value
+ * TODO: make hardware update beacon timestamp
+ */
+ mgmt = (struct ieee80211_mgmt *)skb->data;
+ mgmt->u.beacon.timestamp = cpu_to_le64(rtl8187_get_tsf(dev, vif));
+
+ /* TODO: use actual beacon queue */
+ skb_set_queue_mapping(skb, 0);
+
+ rtl8187_tx(dev, skb);
+
+resched:
+ /*
+ * schedule next beacon
+ * TODO: use hardware support for beacon timing
+ */
+ schedule_delayed_work(&vif_priv->beacon_work,
+ usecs_to_jiffies(1024 * vif->bss_conf.beacon_int));
+}
+
+
static int rtl8187_add_interface(struct ieee80211_hw *dev,
struct ieee80211_vif *vif)
{
struct rtl8187_priv *priv = dev->priv;
+ struct rtl8187_vif *vif_priv;
int i;
int ret = -EOPNOTSUPP;
@@ -1044,6 +1101,7 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev,
switch (vif->type) {
case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
break;
default:
goto exit;
@@ -1052,6 +1110,13 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev,
ret = 0;
priv->vif = vif;
+ /* Initialize driver private area */
+ vif_priv = (struct rtl8187_vif *)&vif->drv_priv;
+ vif_priv->dev = dev;
+ INIT_DELAYED_WORK(&vif_priv->beacon_work, rtl8187_beacon_work);
+ vif_priv->enable_beacon = false;
+
+
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
for (i = 0; i < ETH_ALEN; i++)
rtl818x_iowrite8(priv, &priv->map->MAC[i],
@@ -1175,9 +1240,12 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev,
u32 changed)
{
struct rtl8187_priv *priv = dev->priv;
+ struct rtl8187_vif *vif_priv;
int i;
u8 reg;
+ vif_priv = (struct rtl8187_vif *)&vif->drv_priv;
+
if (changed & BSS_CHANGED_BSSID) {
mutex_lock(&priv->conf_mutex);
for (i = 0; i < ETH_ALEN; i++)
@@ -1189,8 +1257,12 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev,
else
reg = 0;
- if (is_valid_ether_addr(info->bssid))
- reg |= RTL818X_MSR_INFRA;
+ if (is_valid_ether_addr(info->bssid)) {
+ if (vif->type == NL80211_IFTYPE_ADHOC)
+ reg |= RTL818X_MSR_ADHOC;
+ else
+ reg |= RTL818X_MSR_INFRA;
+ }
else
reg |= RTL818X_MSR_NO_LINK;
@@ -1202,6 +1274,16 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev,
if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE))
rtl8187_conf_erp(priv, info->use_short_slot,
info->use_short_preamble);
+
+ if (changed & BSS_CHANGED_BEACON_ENABLED)
+ vif_priv->enable_beacon = info->enable_beacon;
+
+ if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON)) {
+ cancel_delayed_work_sync(&vif_priv->beacon_work);
+ if (vif_priv->enable_beacon)
+ schedule_work(&vif_priv->beacon_work.work);
+ }
+
}
static u64 rtl8187_prepare_multicast(struct ieee80211_hw *dev,
@@ -1279,13 +1361,6 @@ static int rtl8187_conf_tx(struct ieee80211_hw *dev,
return 0;
}
-static u64 rtl8187_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif)
-{
- struct rtl8187_priv *priv = dev->priv;
-
- return rtl818x_ioread32(priv, &priv->map->TSFT[0]) |
- (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32;
-}
static const struct ieee80211_ops rtl8187_ops = {
.tx = rtl8187_tx,
@@ -1514,12 +1589,9 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
if (reg & 0xFF00)
priv->rfkill_mask = RFKILL_MASK_8198;
}
-
- /*
- * XXX: Once this driver supports anything that requires
- * beacons it must implement IEEE80211_TX_CTL_ASSIGN_SEQ.
- */
- dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+ dev->vif_data_size = sizeof(struct rtl8187_vif);
+ dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC) ;
if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b)
printk(KERN_INFO "rtl8187: inconsistency between id with OEM"
diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
index f1cc90751db..e19a20a8e95 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
+++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
@@ -89,6 +89,14 @@ enum {
DEVICE_RTL8187B
};
+struct rtl8187_vif {
+ struct ieee80211_hw *dev;
+
+ /* beaconing */
+ struct delayed_work beacon_work;
+ bool enable_beacon;
+};
+
struct rtl8187_priv {
/* common between rtl818x drivers */
struct rtl818x_csr *map;
@@ -141,6 +149,7 @@ struct rtl8187_priv {
__le32 bits32;
} *io_dmabuf;
bool rfkill_off;
+ u16 seqno;
};
void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
index a64473556ea..1208b753f62 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
@@ -520,6 +520,10 @@ void rtl92c_dm_write_dig(struct ieee80211_hw *hw)
dm_digtable.cur_igvalue, dm_digtable.pre_igvalue,
dm_digtable.backoff_val);
+ dm_digtable.cur_igvalue += 2;
+ if (dm_digtable.cur_igvalue > 0x3f)
+ dm_digtable.cur_igvalue = 0x3f;
+
if (dm_digtable.pre_igvalue != dm_digtable.cur_igvalue) {
rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
dm_digtable.cur_igvalue);
@@ -1201,13 +1205,18 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
"PreState = %d, CurState = %d\n",
p_ra->pre_ratr_state, p_ra->ratr_state);
- rcu_read_lock();
- sta = ieee80211_find_sta(mac->vif, mac->bssid);
+ /* Only the PCI card uses sta in the update rate table
+ * callback routine */
+ if (rtlhal->interface == INTF_PCI) {
+ rcu_read_lock();
+ sta = ieee80211_find_sta(mac->vif, mac->bssid);
+ }
rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
p_ra->ratr_state);
p_ra->pre_ratr_state = p_ra->ratr_state;
- rcu_read_unlock();
+ if (rtlhal->interface == INTF_PCI)
+ rcu_read_unlock();
}
}
}
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index ffcf89fe45e..2e1e352864b 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -346,9 +346,14 @@ static int _rtl_usb_init(struct ieee80211_hw *hw)
pep_desc->bEndpointAddress, pep_desc->wMaxPacketSize,
pep_desc->bInterval);
}
- if (rtlusb->in_ep_nums < rtlpriv->cfg->usb_interface_cfg->in_ep_num)
- return -EINVAL ;
-
+ if (rtlusb->in_ep_nums < rtlpriv->cfg->usb_interface_cfg->in_ep_num) {
+ pr_err("Too few input end points found\n");
+ return -EINVAL;
+ }
+ if (rtlusb->out_ep_nums == 0) {
+ pr_err("No output end points found\n");
+ return -EINVAL;
+ }
/* usb endpoint mapping */
err = rtlpriv->cfg->usb_interface_cfg->usb_endpoint_mapping(hw);
rtlusb->usb_mq_to_hwq = rtlpriv->cfg->usb_interface_cfg->usb_mq_to_hwq;
@@ -357,7 +362,7 @@ static int _rtl_usb_init(struct ieee80211_hw *hw)
return err;
}
-static int _rtl_usb_init_sw(struct ieee80211_hw *hw)
+static void rtl_usb_init_sw(struct ieee80211_hw *hw)
{
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
@@ -392,7 +397,6 @@ static int _rtl_usb_init_sw(struct ieee80211_hw *hw)
/* HIMR_EX - turn all on */
rtlusb->irq_mask[1] = 0xFFFFFFFF;
rtlusb->disableHWSM = true;
- return 0;
}
#define __RADIO_TAP_SIZE_RSV 32
@@ -976,7 +980,9 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
}
rtlpriv->cfg->ops->init_sw_leds(hw);
err = _rtl_usb_init(hw);
- err = _rtl_usb_init_sw(hw);
+ if (err)
+ goto error_out;
+ rtl_usb_init_sw(hw);
/* Init mac80211 sw */
err = rtl_init_core(hw);
if (err) {
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index b776d9d5efe..3414fc11e9b 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -459,23 +459,39 @@ out:
int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
{
+ unsigned long flags;
u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS);
if (link >= WL12XX_MAX_LINKS)
return -EBUSY;
+ /* these bits are used by op_tx */
+ spin_lock_irqsave(&wl->wl_lock, flags);
__set_bit(link, wl->links_map);
__set_bit(link, wlvif->links_map);
+ spin_unlock_irqrestore(&wl->wl_lock, flags);
*hlid = link;
return 0;
}
void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
{
+ unsigned long flags;
+
if (*hlid == WL12XX_INVALID_LINK_ID)
return;
+ /* these bits are used by op_tx */
+ spin_lock_irqsave(&wl->wl_lock, flags);
__clear_bit(*hlid, wl->links_map);
__clear_bit(*hlid, wlvif->links_map);
+ spin_unlock_irqrestore(&wl->wl_lock, flags);
+
+ /*
+ * At this point op_tx() will not add more packets to the queues. We
+ * can purge them.
+ */
+ wl1271_tx_reset_link_queues(wl, *hlid);
+
*hlid = WL12XX_INVALID_LINK_ID;
}
@@ -515,7 +531,7 @@ static int wl12xx_cmd_role_start_dev(struct wl1271 *wl,
goto out_free;
}
cmd->device.hlid = wlvif->dev_hlid;
- cmd->device.session = wlvif->session_counter;
+ cmd->device.session = wl12xx_get_new_session_id(wl, wlvif);
wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d",
cmd->role_id, cmd->device.hlid, cmd->device.session);
@@ -1802,6 +1818,14 @@ int wl12xx_croc(struct wl1271 *wl, u8 role_id)
goto out;
__clear_bit(role_id, wl->roc_map);
+
+ /*
+ * Rearm the tx watchdog when removing the last ROC. This prevents
+ * recoveries due to just finished ROCs - when Tx hasn't yet had
+ * a chance to get out.
+ */
+ if (find_first_bit(wl->roc_map, WL12XX_MAX_ROLES) >= WL12XX_MAX_ROLES)
+ wl12xx_rearm_tx_watchdog_locked(wl);
out:
return ret;
}
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index cc50faaf03d..3e581e19424 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -690,6 +690,9 @@ struct conf_tx_settings {
*/
u8 tmpl_short_retry_limit;
u8 tmpl_long_retry_limit;
+
+ /* Time in ms for Tx watchdog timer to expire */
+ u32 tx_watchdog_timeout;
};
enum {
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index adf9bbcf88f..39002363611 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -217,6 +217,7 @@ static struct conf_drv_settings default_conf = {
.basic_rate_5 = CONF_HW_BIT_RATE_6MBPS,
.tmpl_short_retry_limit = 10,
.tmpl_long_retry_limit = 10,
+ .tx_watchdog_timeout = 5000,
},
.conn = {
.wake_up_event = CONF_WAKE_UP_EVENT_DTIM,
@@ -246,7 +247,7 @@ static struct conf_drv_settings default_conf = {
.psm_entry_retries = 8,
.psm_exit_retries = 16,
.psm_entry_nullfunc_retries = 3,
- .dynamic_ps_timeout = 100,
+ .dynamic_ps_timeout = 200,
.forced_ps = false,
.keep_alive_interval = 55000,
.max_listen_interval = 20,
@@ -392,15 +393,15 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
static void wl1271_op_stop(struct ieee80211_hw *hw);
static void wl1271_free_ap_keys(struct wl1271 *wl, struct wl12xx_vif *wlvif);
-static DEFINE_MUTEX(wl_list_mutex);
-static LIST_HEAD(wl_list);
-
-static int wl1271_check_operstate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
- unsigned char operstate)
+static int wl12xx_set_authorized(struct wl1271 *wl,
+ struct wl12xx_vif *wlvif)
{
int ret;
- if (operstate != IF_OPER_UP)
+ if (WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS))
+ return -EINVAL;
+
+ if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
return 0;
if (test_and_set_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags))
@@ -415,76 +416,6 @@ static int wl1271_check_operstate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
wl1271_info("Association completed.");
return 0;
}
-static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
- void *arg)
-{
- struct net_device *dev = arg;
- struct wireless_dev *wdev;
- struct wiphy *wiphy;
- struct ieee80211_hw *hw;
- struct wl1271 *wl;
- struct wl1271 *wl_temp;
- struct wl12xx_vif *wlvif;
- int ret = 0;
-
- /* Check that this notification is for us. */
- if (what != NETDEV_CHANGE)
- return NOTIFY_DONE;
-
- wdev = dev->ieee80211_ptr;
- if (wdev == NULL)
- return NOTIFY_DONE;
-
- wiphy = wdev->wiphy;
- if (wiphy == NULL)
- return NOTIFY_DONE;
-
- hw = wiphy_priv(wiphy);
- if (hw == NULL)
- return NOTIFY_DONE;
-
- wl_temp = hw->priv;
- mutex_lock(&wl_list_mutex);
- list_for_each_entry(wl, &wl_list, list) {
- if (wl == wl_temp)
- break;
- }
- mutex_unlock(&wl_list_mutex);
- if (wl != wl_temp)
- return NOTIFY_DONE;
-
- mutex_lock(&wl->mutex);
-
- if (wl->state == WL1271_STATE_OFF)
- goto out;
-
- if (dev->operstate != IF_OPER_UP)
- goto out;
- /*
- * The correct behavior should be just getting the appropriate wlvif
- * from the given dev, but currently we don't have a mac80211
- * interface for it.
- */
- wl12xx_for_each_wlvif_sta(wl, wlvif) {
- struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
-
- if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
- continue;
-
- ret = wl1271_ps_elp_wakeup(wl);
- if (ret < 0)
- goto out;
-
- wl1271_check_operstate(wl, wlvif,
- ieee80211_get_operstate(vif));
-
- wl1271_ps_elp_sleep(wl);
- }
-out:
- mutex_unlock(&wl->mutex);
-
- return NOTIFY_OK;
-}
static int wl1271_reg_notify(struct wiphy *wiphy,
struct regulatory_request *request)
@@ -623,6 +554,80 @@ static void wl1271_rx_streaming_timer(unsigned long data)
ieee80211_queue_work(wl->hw, &wlvif->rx_streaming_disable_work);
}
+/* wl->mutex must be taken */
+void wl12xx_rearm_tx_watchdog_locked(struct wl1271 *wl)
+{
+ /* if the watchdog is not armed, don't do anything */
+ if (wl->tx_allocated_blocks == 0)
+ return;
+
+ cancel_delayed_work(&wl->tx_watchdog_work);
+ ieee80211_queue_delayed_work(wl->hw, &wl->tx_watchdog_work,
+ msecs_to_jiffies(wl->conf.tx.tx_watchdog_timeout));
+}
+
+static void wl12xx_tx_watchdog_work(struct work_struct *work)
+{
+ struct delayed_work *dwork;
+ struct wl1271 *wl;
+
+ dwork = container_of(work, struct delayed_work, work);
+ wl = container_of(dwork, struct wl1271, tx_watchdog_work);
+
+ mutex_lock(&wl->mutex);
+
+ if (unlikely(wl->state == WL1271_STATE_OFF))
+ goto out;
+
+ /* Tx went out in the meantime - everything is ok */
+ if (unlikely(wl->tx_allocated_blocks == 0))
+ goto out;
+
+ /*
+ * if a ROC is in progress, we might not have any Tx for a long
+ * time (e.g. pending Tx on the non-ROC channels)
+ */
+ if (find_first_bit(wl->roc_map, WL12XX_MAX_ROLES) < WL12XX_MAX_ROLES) {
+ wl1271_debug(DEBUG_TX, "No Tx (in FW) for %d ms due to ROC",
+ wl->conf.tx.tx_watchdog_timeout);
+ wl12xx_rearm_tx_watchdog_locked(wl);
+ goto out;
+ }
+
+ /*
+ * if a scan is in progress, we might not have any Tx for a long
+ * time
+ */
+ if (wl->scan.state != WL1271_SCAN_STATE_IDLE) {
+ wl1271_debug(DEBUG_TX, "No Tx (in FW) for %d ms due to scan",
+ wl->conf.tx.tx_watchdog_timeout);
+ wl12xx_rearm_tx_watchdog_locked(wl);
+ goto out;
+ }
+
+ /*
+ * AP might cache a frame for a long time for a sleeping station,
+ * so rearm the timer if there's an AP interface with stations. If
+ * Tx is genuinely stuck we will most hopefully discover it when all
+ * stations are removed due to inactivity.
+ */
+ if (wl->active_sta_count) {
+ wl1271_debug(DEBUG_TX, "No Tx (in FW) for %d ms. AP has "
+ " %d stations",
+ wl->conf.tx.tx_watchdog_timeout,
+ wl->active_sta_count);
+ wl12xx_rearm_tx_watchdog_locked(wl);
+ goto out;
+ }
+
+ wl1271_error("Tx stuck (in FW) for %d ms. Starting recovery",
+ wl->conf.tx.tx_watchdog_timeout);
+ wl12xx_queue_recovery_work(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+}
+
static void wl1271_conf_init(struct wl1271 *wl)
{
@@ -815,6 +820,18 @@ static void wl12xx_fw_status(struct wl1271 *wl,
wl->tx_allocated_blocks -= freed_blocks;
+ /*
+ * If the FW freed some blocks:
+ * If we still have allocated blocks - re-arm the timer, Tx is
+ * not stuck. Otherwise, cancel the timer (no Tx currently).
+ */
+ if (freed_blocks) {
+ if (wl->tx_allocated_blocks)
+ wl12xx_rearm_tx_watchdog_locked(wl);
+ else
+ cancel_delayed_work(&wl->tx_watchdog_work);
+ }
+
avail = le32_to_cpu(status->tx_total) - wl->tx_allocated_blocks;
/*
@@ -1224,7 +1241,8 @@ static void wl1271_recovery_work(struct work_struct *work)
wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x",
wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4));
- BUG_ON(bug_on_recovery);
+ BUG_ON(bug_on_recovery &&
+ !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags));
/*
* Advance security sequence number to overcome potential progress
@@ -1487,6 +1505,7 @@ int wl1271_plt_stop(struct wl1271 *wl)
cancel_work_sync(&wl->netstack_work);
cancel_work_sync(&wl->recovery_work);
cancel_delayed_work_sync(&wl->elp_work);
+ cancel_delayed_work_sync(&wl->tx_watchdog_work);
mutex_lock(&wl->mutex);
wl1271_power_off(wl);
@@ -1528,7 +1547,8 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
goto out;
}
- wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q);
+ wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d len %d",
+ hlid, q, skb->len);
skb_queue_tail(&wl->links[hlid].tx_queue[q], skb);
wl->tx_queue_count[q]++;
@@ -1626,10 +1646,6 @@ static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl)
}
-static struct notifier_block wl1271_dev_notifier = {
- .notifier_call = wl1271_dev_notify,
-};
-
#ifdef CONFIG_PM
static int wl1271_configure_suspend_sta(struct wl1271 *wl,
struct wl12xx_vif *wlvif)
@@ -1737,6 +1753,8 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow);
WARN_ON(!wow || !wow->any);
+ wl1271_tx_flush(wl);
+
wl->wow_enabled = true;
wl12xx_for_each_wlvif(wl, wlvif) {
ret = wl1271_configure_suspend(wl, wlvif);
@@ -1854,15 +1872,12 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl->state = WL1271_STATE_OFF;
mutex_unlock(&wl->mutex);
- mutex_lock(&wl_list_mutex);
- list_del(&wl->list);
- mutex_unlock(&wl_list_mutex);
-
wl1271_flush_deferred_work(wl);
cancel_delayed_work_sync(&wl->scan_complete_work);
cancel_work_sync(&wl->netstack_work);
cancel_work_sync(&wl->tx_work);
cancel_delayed_work_sync(&wl->elp_work);
+ cancel_delayed_work_sync(&wl->tx_watchdog_work);
/* let's notify MAC80211 about the remaining pending TX frames */
wl12xx_tx_reset(wl, true);
@@ -2209,6 +2224,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
if (wl12xx_need_fw_change(wl, vif_count, true)) {
wl12xx_force_active_psm(wl);
+ set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags);
mutex_unlock(&wl->mutex);
wl1271_recovery_work(&wl->recovery_work);
return 0;
@@ -2268,11 +2284,6 @@ out:
out_unlock:
mutex_unlock(&wl->mutex);
- mutex_lock(&wl_list_mutex);
- if (!ret)
- list_add(&wl->list, &wl_list);
- mutex_unlock(&wl_list_mutex);
-
return ret;
}
@@ -2296,6 +2307,12 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
if (wl->scan.state != WL1271_SCAN_STATE_IDLE &&
wl->scan_vif == vif) {
+ /*
+ * Rearm the tx watchdog just before idling scan. This
+ * prevents just-finished scans from triggering the watchdog
+ */
+ wl12xx_rearm_tx_watchdog_locked(wl);
+
wl->scan.state = WL1271_SCAN_STATE_IDLE;
memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
wl->scan_vif = NULL;
@@ -2398,6 +2415,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
WARN_ON(iter != wlvif);
if (wl12xx_need_fw_change(wl, vif_count, false)) {
wl12xx_force_active_psm(wl);
+ set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags);
wl12xx_queue_recovery_work(wl);
cancel_recovery = false;
}
@@ -2417,7 +2435,7 @@ static int wl12xx_op_change_interface(struct ieee80211_hw *hw,
set_bit(WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, &wl->flags);
wl1271_op_remove_interface(hw, vif);
- vif->type = ieee80211_iftype_p2p(new_type, p2p);
+ vif->type = new_type;
vif->p2p = p2p;
ret = wl1271_op_add_interface(hw, vif);
@@ -2596,35 +2614,22 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif,
wl1271_warning("rate policy for channel "
"failed %d", ret);
- if (test_bit(WLVIF_FLAG_STA_ASSOCIATED,
- &wlvif->flags)) {
- if (wl12xx_dev_role_started(wlvif)) {
- /* roaming */
- ret = wl12xx_croc(wl,
- wlvif->dev_role_id);
- if (ret < 0)
- return ret;
- }
- ret = wl1271_join(wl, wlvif, false);
+ /*
+ * change the ROC channel. do it only if we are
+ * not idle. otherwise, CROC will be called
+ * anyway.
+ */
+ if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED,
+ &wlvif->flags) &&
+ wl12xx_dev_role_started(wlvif) &&
+ !(conf->flags & IEEE80211_CONF_IDLE)) {
+ ret = wl12xx_stop_dev(wl, wlvif);
if (ret < 0)
- wl1271_warning("cmd join on channel "
- "failed %d", ret);
- } else {
- /*
- * change the ROC channel. do it only if we are
- * not idle. otherwise, CROC will be called
- * anyway.
- */
- if (wl12xx_dev_role_started(wlvif) &&
- !(conf->flags & IEEE80211_CONF_IDLE)) {
- ret = wl12xx_stop_dev(wl, wlvif);
- if (ret < 0)
- return ret;
+ return ret;
- ret = wl12xx_start_dev(wl, wlvif);
- if (ret < 0)
- return ret;
- }
+ ret = wl12xx_start_dev(wl, wlvif);
+ if (ret < 0)
+ return ret;
}
}
}
@@ -3151,8 +3156,6 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
struct cfg80211_scan_request *req)
{
struct wl1271 *wl = hw->priv;
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
-
int ret;
u8 *ssid = NULL;
size_t len = 0;
@@ -3180,8 +3183,8 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
if (ret < 0)
goto out;
- if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) &&
- test_bit(wlvif->role_id, wl->roc_map)) {
+ /* fail if there is any role in ROC */
+ if (find_first_bit(wl->roc_map, WL12XX_MAX_ROLES) < WL12XX_MAX_ROLES) {
/* don't allow scanning right now */
ret = -EBUSY;
goto out_sleep;
@@ -3221,6 +3224,13 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw,
if (ret < 0)
goto out_sleep;
}
+
+ /*
+ * Rearm the tx watchdog just before idling scan. This
+ * prevents just-finished scans from triggering the watchdog
+ */
+ wl12xx_rearm_tx_watchdog_locked(wl);
+
wl->scan.state = WL1271_SCAN_STATE_IDLE;
memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
wl->scan_vif = NULL;
@@ -3744,10 +3754,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
ibss_joined = true;
} else {
if (test_and_clear_bit(WLVIF_FLAG_IBSS_JOINED,
- &wlvif->flags)) {
+ &wlvif->flags))
wl1271_unjoin(wl, wlvif);
- wl12xx_start_dev(wl, wlvif);
- }
}
}
@@ -3765,7 +3773,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
do_join = true;
}
- if (changed & BSS_CHANGED_IDLE) {
+ if (changed & BSS_CHANGED_IDLE && !is_ibss) {
ret = wl1271_sta_handle_idle(wl, wlvif, bss_conf->idle);
if (ret < 0)
wl1271_warning("idle mode change failed %d", ret);
@@ -3821,6 +3829,7 @@ sta_not_found:
u32 rates;
int ieoffset;
wlvif->aid = bss_conf->aid;
+ wlvif->beacon_int = bss_conf->beacon_int;
set_assoc = true;
/*
@@ -3901,7 +3910,6 @@ sta_not_found:
/* restore the bssid filter and go to dummy bssid */
if (was_assoc) {
- u32 conf_flags = wl->hw->conf.flags;
/*
* we might have to disable roc, if there was
* no IF_OPER_UP notification.
@@ -3924,7 +3932,7 @@ sta_not_found:
}
wl1271_unjoin(wl, wlvif);
- if (!(conf_flags & IEEE80211_CONF_IDLE))
+ if (!bss_conf->idle)
wl12xx_start_dev(wl, wlvif);
}
}
@@ -3968,8 +3976,8 @@ sta_not_found:
if (ret < 0)
goto out;
- wl1271_check_operstate(wl, wlvif,
- ieee80211_get_operstate(vif));
+ if (test_bit(WLVIF_FLAG_STA_AUTHORIZED, &wlvif->flags))
+ wl12xx_set_authorized(wl, wlvif);
}
/*
* stop device role if started (we might already be in
@@ -4228,107 +4236,155 @@ void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid)
clear_bit(hlid, wlvif->ap.sta_hlid_map);
memset(wl->links[hlid].addr, 0, ETH_ALEN);
wl->links[hlid].ba_bitmap = 0;
- wl1271_tx_reset_link_queues(wl, hlid);
__clear_bit(hlid, &wl->ap_ps_map);
__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
wl12xx_free_link(wl, wlvif, &hlid);
wl->active_sta_count--;
+
+ /*
+ * rearm the tx watchdog when the last STA is freed - give the FW a
+ * chance to return STA-buffered packets before complaining.
+ */
+ if (wl->active_sta_count == 0)
+ wl12xx_rearm_tx_watchdog_locked(wl);
}
-static int wl1271_op_sta_add(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+static int wl12xx_sta_add(struct wl1271 *wl,
+ struct wl12xx_vif *wlvif,
+ struct ieee80211_sta *sta)
{
- struct wl1271 *wl = hw->priv;
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
struct wl1271_station *wl_sta;
int ret = 0;
u8 hlid;
- mutex_lock(&wl->mutex);
-
- if (unlikely(wl->state == WL1271_STATE_OFF))
- goto out;
-
- if (wlvif->bss_type != BSS_TYPE_AP_BSS)
- goto out;
-
wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid);
ret = wl1271_allocate_sta(wl, wlvif, sta);
if (ret < 0)
- goto out;
+ return ret;
wl_sta = (struct wl1271_station *)sta->drv_priv;
hlid = wl_sta->hlid;
- ret = wl1271_ps_elp_wakeup(wl);
- if (ret < 0)
- goto out_free_sta;
-
ret = wl12xx_cmd_add_peer(wl, wlvif, sta, hlid);
if (ret < 0)
- goto out_sleep;
+ wl1271_free_sta(wl, wlvif, hlid);
- ret = wl12xx_cmd_set_peer_state(wl, hlid);
- if (ret < 0)
- goto out_sleep;
+ return ret;
+}
- ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, hlid);
- if (ret < 0)
- goto out_sleep;
+static int wl12xx_sta_remove(struct wl1271 *wl,
+ struct wl12xx_vif *wlvif,
+ struct ieee80211_sta *sta)
+{
+ struct wl1271_station *wl_sta;
+ int ret = 0, id;
-out_sleep:
- wl1271_ps_elp_sleep(wl);
+ wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid);
-out_free_sta:
+ wl_sta = (struct wl1271_station *)sta->drv_priv;
+ id = wl_sta->hlid;
+ if (WARN_ON(!test_bit(id, wlvif->ap.sta_hlid_map)))
+ return -EINVAL;
+
+ ret = wl12xx_cmd_remove_peer(wl, wl_sta->hlid);
if (ret < 0)
- wl1271_free_sta(wl, wlvif, hlid);
+ return ret;
-out:
- mutex_unlock(&wl->mutex);
+ wl1271_free_sta(wl, wlvif, wl_sta->hlid);
return ret;
}
-static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+static int wl12xx_update_sta_state(struct wl1271 *wl,
+ struct wl12xx_vif *wlvif,
+ struct ieee80211_sta *sta,
+ enum ieee80211_sta_state old_state,
+ enum ieee80211_sta_state new_state)
{
- struct wl1271 *wl = hw->priv;
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
struct wl1271_station *wl_sta;
- int ret = 0, id;
+ u8 hlid;
+ bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS;
+ bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS;
+ int ret;
- mutex_lock(&wl->mutex);
+ wl_sta = (struct wl1271_station *)sta->drv_priv;
+ hlid = wl_sta->hlid;
- if (unlikely(wl->state == WL1271_STATE_OFF))
- goto out;
+ /* Add station (AP mode) */
+ if (is_ap &&
+ old_state == IEEE80211_STA_NOTEXIST &&
+ new_state == IEEE80211_STA_NONE)
+ return wl12xx_sta_add(wl, wlvif, sta);
+
+ /* Remove station (AP mode) */
+ if (is_ap &&
+ old_state == IEEE80211_STA_NONE &&
+ new_state == IEEE80211_STA_NOTEXIST) {
+ /* must not fail */
+ wl12xx_sta_remove(wl, wlvif, sta);
+ return 0;
+ }
- if (wlvif->bss_type != BSS_TYPE_AP_BSS)
- goto out;
+ /* Authorize station (AP mode) */
+ if (is_ap &&
+ new_state == IEEE80211_STA_AUTHORIZED) {
+ ret = wl12xx_cmd_set_peer_state(wl, hlid);
+ if (ret < 0)
+ return ret;
- wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid);
+ ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true,
+ hlid);
+ return ret;
+ }
- wl_sta = (struct wl1271_station *)sta->drv_priv;
- id = wl_sta->hlid;
- if (WARN_ON(!test_bit(id, wlvif->ap.sta_hlid_map)))
+ /* Authorize station */
+ if (is_sta &&
+ new_state == IEEE80211_STA_AUTHORIZED) {
+ set_bit(WLVIF_FLAG_STA_AUTHORIZED, &wlvif->flags);
+ return wl12xx_set_authorized(wl, wlvif);
+ }
+
+ if (is_sta &&
+ old_state == IEEE80211_STA_AUTHORIZED &&
+ new_state == IEEE80211_STA_ASSOC) {
+ clear_bit(WLVIF_FLAG_STA_AUTHORIZED, &wlvif->flags);
+ return 0;
+ }
+
+ return 0;
+}
+
+static int wl12xx_op_sta_state(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ enum ieee80211_sta_state old_state,
+ enum ieee80211_sta_state new_state)
+{
+ struct wl1271 *wl = hw->priv;
+ struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ int ret;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 sta %d state=%d->%d",
+ sta->aid, old_state, new_state);
+
+ mutex_lock(&wl->mutex);
+
+ if (unlikely(wl->state == WL1271_STATE_OFF)) {
+ ret = -EBUSY;
goto out;
+ }
ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0)
goto out;
- ret = wl12xx_cmd_remove_peer(wl, wl_sta->hlid);
- if (ret < 0)
- goto out_sleep;
-
- wl1271_free_sta(wl, wlvif, wl_sta->hlid);
+ ret = wl12xx_update_sta_state(wl, wlvif, sta, old_state, new_state);
-out_sleep:
wl1271_ps_elp_sleep(wl);
-
out:
mutex_unlock(&wl->mutex);
+ if (new_state < old_state)
+ return 0;
return ret;
}
@@ -4497,6 +4553,8 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch");
+ wl1271_tx_flush(wl);
+
mutex_lock(&wl->mutex);
if (unlikely(wl->state == WL1271_STATE_OFF)) {
@@ -4795,8 +4853,7 @@ static const struct ieee80211_ops wl1271_ops = {
.conf_tx = wl1271_op_conf_tx,
.get_tsf = wl1271_op_get_tsf,
.get_survey = wl1271_op_get_survey,
- .sta_add = wl1271_op_sta_add,
- .sta_remove = wl1271_op_sta_remove,
+ .sta_state = wl12xx_op_sta_state,
.ampdu_action = wl1271_op_ampdu_action,
.tx_frames_pending = wl1271_tx_frames_pending,
.set_bitrate_mask = wl12xx_set_bitrate_mask,
@@ -5117,8 +5174,6 @@ static int wl1271_register_hw(struct wl1271 *wl)
wl1271_debugfs_init(wl);
- register_netdevice_notifier(&wl1271_dev_notifier);
-
wl1271_notice("loaded");
out:
@@ -5130,7 +5185,6 @@ static void wl1271_unregister_hw(struct wl1271 *wl)
if (wl->plt)
wl1271_plt_stop(wl);
- unregister_netdevice_notifier(&wl1271_dev_notifier);
ieee80211_unregister_hw(wl->hw);
wl->mac80211_registered = false;
@@ -5251,7 +5305,6 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
wl = hw->priv;
memset(wl, 0, sizeof(*wl));
- INIT_LIST_HEAD(&wl->list);
INIT_LIST_HEAD(&wl->wlvif_list);
wl->hw = hw;
@@ -5268,6 +5321,7 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
INIT_WORK(&wl->tx_work, wl1271_tx_work);
INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
+ INIT_DELAYED_WORK(&wl->tx_watchdog_work, wl12xx_tx_watchdog_work);
wl->freezable_wq = create_freezable_workqueue("wl12xx_wq");
if (!wl->freezable_wq) {
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index 23d67501c50..78f598b4f97 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -69,8 +69,6 @@ out:
mutex_unlock(&wl->mutex);
}
-#define ELP_ENTRY_DELAY 5
-
/* Routines to toggle sleep mode while in ELP */
void wl1271_ps_elp_sleep(struct wl1271 *wl)
{
@@ -90,7 +88,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
}
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
- msecs_to_jiffies(ELP_ENTRY_DELAY));
+ msecs_to_jiffies(wl->conf.conn.dynamic_ps_timeout));
}
int wl1271_ps_elp_wakeup(struct wl1271 *wl)
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index e43a6b2c1d9..fcba055ef19 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -55,6 +55,12 @@ void wl1271_scan_complete_work(struct work_struct *work)
vif = wl->scan_vif;
wlvif = wl12xx_vif_to_data(vif);
+ /*
+ * Rearm the tx watchdog just before idling scan. This
+ * prevents just-finished scans from triggering the watchdog
+ */
+ wl12xx_rearm_tx_watchdog_locked(wl);
+
wl->scan.state = WL1271_SCAN_STATE_IDLE;
memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
wl->scan.req = NULL;
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 6446e4d3e8f..43ae49143d6 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -226,6 +226,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
wl->tx_blocks_available -= total_blocks;
wl->tx_allocated_blocks += total_blocks;
+ /* If the FW was empty before, arm the Tx watchdog */
+ if (wl->tx_allocated_blocks == total_blocks)
+ wl12xx_rearm_tx_watchdog_locked(wl);
+
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
wl->tx_allocated_pkts[ac]++;
@@ -527,6 +531,7 @@ static struct sk_buff *wl12xx_lnk_skb_dequeue(struct wl1271 *wl,
if (skb) {
int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
spin_lock_irqsave(&wl->wl_lock, flags);
+ WARN_ON_ONCE(wl->tx_queue_count[q] <= 0);
wl->tx_queue_count[q]--;
spin_unlock_irqrestore(&wl->wl_lock, flags);
}
@@ -571,6 +576,7 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
struct wl12xx_vif *wlvif = wl->last_wlvif;
struct sk_buff *skb = NULL;
+ /* continue from last wlvif (round robin) */
if (wlvif) {
wl12xx_for_each_wlvif_continue(wl, wlvif) {
skb = wl12xx_vif_skb_dequeue(wl, wlvif);
@@ -581,7 +587,11 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
}
}
- /* do another pass */
+ /* dequeue from the system HLID before the restarting wlvif list */
+ if (!skb)
+ skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[wl->system_hlid]);
+
+ /* do a new pass over the wlvif list */
if (!skb) {
wl12xx_for_each_wlvif(wl, wlvif) {
skb = wl12xx_vif_skb_dequeue(wl, wlvif);
@@ -589,12 +599,16 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
wl->last_wlvif = wlvif;
break;
}
+
+ /*
+ * No need to continue after last_wlvif. The previous
+ * pass should have found it.
+ */
+ if (wlvif == wl->last_wlvif)
+ break;
}
}
- if (!skb)
- skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[wl->system_hlid]);
-
if (!skb &&
test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) {
int q;
@@ -602,6 +616,7 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
skb = wl->dummy_packet;
q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
spin_lock_irqsave(&wl->wl_lock, flags);
+ WARN_ON_ONCE(wl->tx_queue_count[q] <= 0);
wl->tx_queue_count[q]--;
spin_unlock_irqrestore(&wl->wl_lock, flags);
}
@@ -959,7 +974,6 @@ void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif)
else
wlvif->sta.ba_rx_bitmap = 0;
- wl1271_tx_reset_link_queues(wl, i);
wl->links[i].allocated_pkts = 0;
wl->links[i].prev_freed_pkts = 0;
}
@@ -973,8 +987,14 @@ void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
struct sk_buff *skb;
struct ieee80211_tx_info *info;
- for (i = 0; i < NUM_TX_QUEUES; i++)
- wl->tx_queue_count[i] = 0;
+ /* only reset the queues if something bad happened */
+ if (WARN_ON_ONCE(wl1271_tx_total_queue_count(wl) != 0)) {
+ for (i = 0; i < WL12XX_MAX_LINKS; i++)
+ wl1271_tx_reset_link_queues(wl, i);
+
+ for (i = 0; i < NUM_TX_QUEUES; i++)
+ wl->tx_queue_count[i] = 0;
+ }
wl->stopped_queues_map = 0;
@@ -1024,6 +1044,7 @@ void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
void wl1271_tx_flush(struct wl1271 *wl)
{
unsigned long timeout;
+ int i;
timeout = jiffies + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT);
while (!time_after(jiffies, timeout)) {
@@ -1041,6 +1062,12 @@ void wl1271_tx_flush(struct wl1271 *wl)
}
wl1271_warning("Unable to flush all TX buffers, timed out.");
+
+ /* forcibly flush all Tx buffers on our queues */
+ mutex_lock(&wl->mutex);
+ for (i = 0; i < WL12XX_MAX_LINKS; i++)
+ wl1271_tx_reset_link_queues(wl, i);
+ mutex_unlock(&wl->mutex);
}
u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set)
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index e3977b55a71..5cf8c32d40d 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -227,5 +227,6 @@ void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids);
/* from main.c */
void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid);
+void wl12xx_rearm_tx_watchdog_locked(struct wl1271 *wl);
#endif
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 90352415e2a..749a15a75d3 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -260,11 +260,13 @@ enum wl12xx_flags {
WL1271_FLAG_SOFT_GEMINI,
WL1271_FLAG_RECOVERY_IN_PROGRESS,
WL1271_FLAG_VIF_CHANGE_IN_PROGRESS,
+ WL1271_FLAG_INTENDED_FW_RECOVERY,
};
enum wl12xx_vif_flags {
WLVIF_FLAG_INITIALIZED,
WLVIF_FLAG_STA_ASSOCIATED,
+ WLVIF_FLAG_STA_AUTHORIZED,
WLVIF_FLAG_IBSS_JOINED,
WLVIF_FLAG_AP_STARTED,
WLVIF_FLAG_IN_PS,
@@ -452,8 +454,6 @@ struct wl1271 {
bool enable_11a;
- struct list_head list;
-
/* Most recently reported noise in dBm */
s8 noise;
@@ -495,6 +495,9 @@ struct wl1271 {
/* last wlvif we transmitted from */
struct wl12xx_vif *last_wlvif;
+
+ /* work to fire when Tx is stuck */
+ struct delayed_work tx_watchdog_work;
};
struct wl1271_station {
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 1a1500bc845..cb6204f7830 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -736,6 +736,8 @@ static int pn533_target_found_type_a(struct nfc_target *nfc_tgt, u8 *tgt_data,
nfc_tgt->sens_res = be16_to_cpu(tgt_type_a->sens_res);
nfc_tgt->sel_res = tgt_type_a->sel_res;
+ nfc_tgt->nfcid1_len = tgt_type_a->nfcid_len;
+ memcpy(nfc_tgt->nfcid1, tgt_type_a->nfcid_data, nfc_tgt->nfcid1_len);
return 0;
}
@@ -781,6 +783,9 @@ static int pn533_target_found_felica(struct nfc_target *nfc_tgt, u8 *tgt_data,
else
nfc_tgt->supported_protocols = NFC_PROTO_FELICA_MASK;
+ memcpy(nfc_tgt->sensf_res, &tgt_felica->opcode, 9);
+ nfc_tgt->sensf_res_len = 9;
+
return 0;
}
@@ -823,6 +828,8 @@ static int pn533_target_found_jewel(struct nfc_target *nfc_tgt, u8 *tgt_data,
nfc_tgt->supported_protocols = NFC_PROTO_JEWEL_MASK;
nfc_tgt->sens_res = be16_to_cpu(tgt_jewel->sens_res);
+ nfc_tgt->nfcid1_len = 4;
+ memcpy(nfc_tgt->nfcid1, tgt_jewel->jewelid, nfc_tgt->nfcid1_len);
return 0;
}
@@ -902,6 +909,8 @@ static int pn533_target_found(struct pn533 *dev,
if (resp->tg != 1)
return -EPROTO;
+ memset(&nfc_tgt, 0, sizeof(struct nfc_target));
+
target_data_len = resp_len - sizeof(struct pn533_poll_response);
switch (dev->poll_mod_curr) {
@@ -1307,6 +1316,8 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
nfc_dev_dbg(&dev->interface->dev, "Creating new target");
nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK;
+ nfc_target.nfcid1_len = 10;
+ memcpy(nfc_target.nfcid1, resp->nfcid3t, nfc_target.nfcid1_len);
rc = nfc_targets_found(dev->nfc_dev, &nfc_target, 1);
if (rc)
return 0;
@@ -1329,21 +1340,15 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
}
static int pn533_dep_link_up(struct nfc_dev *nfc_dev, int target_idx,
- u8 comm_mode, u8 rf_mode)
+ u8 comm_mode, u8* gb, size_t gb_len)
{
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
struct pn533_cmd_jump_dep *cmd;
- u8 cmd_len, local_gt_len, *local_gt;
+ u8 cmd_len;
int rc;
nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
- if (rf_mode == NFC_RF_TARGET) {
- nfc_dev_err(&dev->interface->dev, "Target mode not supported");
- return -EOPNOTSUPP;
- }
-
-
if (dev->poll_mod_count) {
nfc_dev_err(&dev->interface->dev,
"Cannot bring the DEP link up while polling");
@@ -1356,11 +1361,7 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, int target_idx,
return -EBUSY;
}
- local_gt = nfc_get_local_general_bytes(dev->nfc_dev, &local_gt_len);
- if (local_gt_len > NFC_MAX_GT_LEN)
- return -EINVAL;
-
- cmd_len = sizeof(struct pn533_cmd_jump_dep) + local_gt_len;
+ cmd_len = sizeof(struct pn533_cmd_jump_dep) + gb_len;
cmd = kzalloc(cmd_len, GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
@@ -1369,9 +1370,9 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, int target_idx,
cmd->active = !comm_mode;
cmd->baud = 0;
- if (local_gt != NULL) {
+ if (gb != NULL && gb_len > 0) {
cmd->next = 4; /* We have some Gi */
- memcpy(cmd->gt, local_gt, local_gt_len);
+ memcpy(cmd->gt, gb, gb_len);
} else {
cmd->next = 0;
}
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index befa89eac6f..ed4124469a3 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -331,7 +331,6 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
{
int i;
u16 v;
- s8 gain;
u16 loc[3];
if (out->revision == 3) /* rev 3 moved MAC */
@@ -390,20 +389,12 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
/* Extract the antenna gain values. */
- gain = r123_extract_antgain(out->revision, in,
- SSB_SPROM1_AGAIN_BG,
- SSB_SPROM1_AGAIN_BG_SHIFT);
- out->antenna_gain.ghz24.a0 = gain;
- out->antenna_gain.ghz24.a1 = gain;
- out->antenna_gain.ghz24.a2 = gain;
- out->antenna_gain.ghz24.a3 = gain;
- gain = r123_extract_antgain(out->revision, in,
- SSB_SPROM1_AGAIN_A,
- SSB_SPROM1_AGAIN_A_SHIFT);
- out->antenna_gain.ghz5.a0 = gain;
- out->antenna_gain.ghz5.a1 = gain;
- out->antenna_gain.ghz5.a2 = gain;
- out->antenna_gain.ghz5.a3 = gain;
+ out->antenna_gain.a0 = r123_extract_antgain(out->revision, in,
+ SSB_SPROM1_AGAIN_BG,
+ SSB_SPROM1_AGAIN_BG_SHIFT);
+ out->antenna_gain.a1 = r123_extract_antgain(out->revision, in,
+ SSB_SPROM1_AGAIN_A,
+ SSB_SPROM1_AGAIN_A_SHIFT);
}
/* Revs 4 5 and 8 have partially shared layout */
@@ -504,16 +495,14 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
}
/* Extract the antenna gain values. */
- SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01,
+ SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01,
SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
- SPEX(antenna_gain.ghz24.a1, SSB_SPROM4_AGAIN01,
+ SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01,
SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
- SPEX(antenna_gain.ghz24.a2, SSB_SPROM4_AGAIN23,
+ SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23,
SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
- SPEX(antenna_gain.ghz24.a3, SSB_SPROM4_AGAIN23,
+ SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23,
SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
- memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
- sizeof(out->antenna_gain.ghz5));
sprom_extract_r458(out, in);
@@ -602,16 +591,14 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
/* Extract the antenna gain values. */
- SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01,
+ SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
- SPEX(antenna_gain.ghz24.a1, SSB_SPROM8_AGAIN01,
+ SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
- SPEX(antenna_gain.ghz24.a2, SSB_SPROM8_AGAIN23,
+ SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
- SPEX(antenna_gain.ghz24.a3, SSB_SPROM8_AGAIN23,
+ SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
- memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
- sizeof(out->antenna_gain.ghz5));
/* Extract cores power info info */
for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index c821c6b2a6a..fbafed5b729 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -676,14 +676,10 @@ static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev,
case SSB_PCMCIA_CIS_ANTGAIN:
GOTO_ERROR_ON(tuple->TupleDataLen != 2,
"antg tpl size");
- sprom->antenna_gain.ghz24.a0 = tuple->TupleData[1];
- sprom->antenna_gain.ghz24.a1 = tuple->TupleData[1];
- sprom->antenna_gain.ghz24.a2 = tuple->TupleData[1];
- sprom->antenna_gain.ghz24.a3 = tuple->TupleData[1];
- sprom->antenna_gain.ghz5.a0 = tuple->TupleData[1];
- sprom->antenna_gain.ghz5.a1 = tuple->TupleData[1];
- sprom->antenna_gain.ghz5.a2 = tuple->TupleData[1];
- sprom->antenna_gain.ghz5.a3 = tuple->TupleData[1];
+ sprom->antenna_gain.a0 = tuple->TupleData[1];
+ sprom->antenna_gain.a1 = tuple->TupleData[1];
+ sprom->antenna_gain.a2 = tuple->TupleData[1];
+ sprom->antenna_gain.a3 = tuple->TupleData[1];
break;
case SSB_PCMCIA_CIS_BFLAGS:
GOTO_ERROR_ON((tuple->TupleDataLen != 3) &&
diff --git a/drivers/ssb/sdio.c b/drivers/ssb/sdio.c
index 63fd709038c..b2d36f7736c 100644
--- a/drivers/ssb/sdio.c
+++ b/drivers/ssb/sdio.c
@@ -551,14 +551,10 @@ int ssb_sdio_get_invariants(struct ssb_bus *bus,
case SSB_SDIO_CIS_ANTGAIN:
GOTO_ERROR_ON(tuple->size != 2,
"antg tpl size");
- sprom->antenna_gain.ghz24.a0 = tuple->data[1];
- sprom->antenna_gain.ghz24.a1 = tuple->data[1];
- sprom->antenna_gain.ghz24.a2 = tuple->data[1];
- sprom->antenna_gain.ghz24.a3 = tuple->data[1];
- sprom->antenna_gain.ghz5.a0 = tuple->data[1];
- sprom->antenna_gain.ghz5.a1 = tuple->data[1];
- sprom->antenna_gain.ghz5.a2 = tuple->data[1];
- sprom->antenna_gain.ghz5.a3 = tuple->data[1];
+ sprom->antenna_gain.a0 = tuple->data[1];
+ sprom->antenna_gain.a1 = tuple->data[1];
+ sprom->antenna_gain.a2 = tuple->data[1];
+ sprom->antenna_gain.a3 = tuple->data[1];
break;
case SSB_SDIO_CIS_BFLAGS:
GOTO_ERROR_ON((tuple->size != 3) &&
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index b9f65fbee42..5af9a075498 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -176,6 +176,12 @@ int __bcma_driver_register(struct bcma_driver *drv, struct module *owner);
extern void bcma_driver_unregister(struct bcma_driver *drv);
+/* Set a fallback SPROM.
+ * See kdoc at the function definition for complete documentation. */
+extern int bcma_arch_register_fallback_sprom(
+ int (*sprom_callback)(struct bcma_bus *bus,
+ struct ssb_sprom *out));
+
struct bcma_bus {
/* The MMIO area. */
void __iomem *mmio;
@@ -284,6 +290,7 @@ static inline void bcma_maskset16(struct bcma_device *cc,
bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set);
}
+extern struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid);
extern bool bcma_core_is_enabled(struct bcma_device *core);
extern void bcma_core_disable(struct bcma_device *core, u32 flags);
extern int bcma_core_enable(struct bcma_device *core, u32 flags);
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index e72938b1071..8bbfe31fbac 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -56,6 +56,9 @@
#define BCMA_CC_OTPS_HW_PROTECT 0x00000001
#define BCMA_CC_OTPS_SW_PROTECT 0x00000002
#define BCMA_CC_OTPS_CID_PROTECT 0x00000004
+#define BCMA_CC_OTPS_GU_PROG_IND 0x00000F00 /* General Use programmed indication */
+#define BCMA_CC_OTPS_GU_PROG_IND_SHIFT 8
+#define BCMA_CC_OTPS_GU_PROG_HW 0x00000100 /* HW region programmed */
#define BCMA_CC_OTPC 0x0014 /* OTP control */
#define BCMA_CC_OTPC_RECWAIT 0xFF000000
#define BCMA_CC_OTPC_PROGWAIT 0x00FFFF00
@@ -72,6 +75,8 @@
#define BCMA_CC_OTPP_READ 0x40000000
#define BCMA_CC_OTPP_START 0x80000000
#define BCMA_CC_OTPP_BUSY 0x80000000
+#define BCMA_CC_OTPL 0x001C /* OTP layout */
+#define BCMA_CC_OTPL_GURGN_OFFSET 0x00000FFF /* offset of general use region */
#define BCMA_CC_IRQSTAT 0x0020
#define BCMA_CC_IRQMASK 0x0024
#define BCMA_CC_IRQ_GPIO 0x00000001 /* gpio intr */
@@ -79,6 +84,10 @@
#define BCMA_CC_IRQ_WDRESET 0x80000000 /* watchdog reset occurred */
#define BCMA_CC_CHIPCTL 0x0028 /* Rev >= 11 only */
#define BCMA_CC_CHIPSTAT 0x002C /* Rev >= 11 only */
+#define BCMA_CC_CHIPST_4313_SPROM_PRESENT 1
+#define BCMA_CC_CHIPST_4313_OTP_PRESENT 2
+#define BCMA_CC_CHIPST_4331_SPROM_PRESENT 2
+#define BCMA_CC_CHIPST_4331_OTP_PRESENT 4
#define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */
#define BCMA_CC_JCMD_START 0x80000000
#define BCMA_CC_JCMD_BUSY 0x80000000
@@ -256,7 +265,6 @@
#define BCMA_CC_PLLCTL_ADDR 0x0660
#define BCMA_CC_PLLCTL_DATA 0x0664
#define BCMA_CC_SPROM 0x0800 /* SPROM beginning */
-#define BCMA_CC_SPROM_PCIE6 0x0830 /* SPROM beginning on PCIe rev >= 6 */
/* Divider allocation in 4716/47162/5356 */
#define BCMA_CC_PMU5_MAINPLL_CPU 1
diff --git a/include/linux/nfc.h b/include/linux/nfc.h
index b4999abcb2a..39c1fcf089c 100644
--- a/include/linux/nfc.h
+++ b/include/linux/nfc.h
@@ -107,6 +107,7 @@ enum nfc_attrs {
NFC_ATTR_TARGET_SENSF_RES,
NFC_ATTR_COMM_MODE,
NFC_ATTR_RF_MODE,
+ NFC_ATTR_DEVICE_POWERED,
/* private: internal use only */
__NFC_ATTR_AFTER_LAST
};
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index be35a68746a..c37d67add09 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -168,8 +168,8 @@
* %NL80211_ATTR_DTIM_PERIOD, %NL80211_ATTR_SSID,
* %NL80211_ATTR_HIDDEN_SSID, %NL80211_ATTR_CIPHERS_PAIRWISE,
* %NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS,
- * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY and
- * %NL80211_ATTR_AUTH_TYPE.
+ * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY,
+ * %NL80211_ATTR_AUTH_TYPE and %NL80211_ATTR_INACTIVITY_TIMEOUT.
* @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP
* @NL80211_CMD_STOP_AP: Stop AP operation on the given interface
* @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP
@@ -1197,6 +1197,16 @@ enum nl80211_commands {
* @NL80211_ATTR_NOACK_MAP: This u16 bitmap contains the No Ack Policy of
* up to 16 TIDs.
*
+ * @NL80211_ATTR_INACTIVITY_TIMEOUT: timeout value in seconds, this can be
+ * used by the drivers which has MLME in firmware and does not have support
+ * to report per station tx/rx activity to free up the staion entry from
+ * the list. This needs to be used when the driver advertises the
+ * capability to timeout the stations.
+ *
+ * @NL80211_ATTR_RX_SIGNAL_DBM: signal strength in dBm (as a 32-bit int);
+ * this attribute is (depending on the driver capabilities) added to
+ * received frames indicated with %NL80211_CMD_FRAME.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1442,6 +1452,10 @@ enum nl80211_attrs {
NL80211_ATTR_NOACK_MAP,
+ NL80211_ATTR_INACTIVITY_TIMEOUT,
+
+ NL80211_ATTR_RX_SIGNAL_DBM,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -2112,6 +2126,10 @@ enum nl80211_mntr_flags {
* @NL80211_MESHCONF_FORWARDING: set Mesh STA as forwarding or non-forwarding
* or forwarding entity (default is TRUE - forwarding entity)
*
+ * @NL80211_MESHCONF_RSSI_THRESHOLD: RSSI threshold in dBm. This specifies the
+ * threshold for average signal strength of candidate station to establish
+ * a peer link.
+ *
* @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
*
* @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
@@ -2137,6 +2155,7 @@ enum nl80211_meshconf_params {
NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
NL80211_MESHCONF_FORWARDING,
+ NL80211_MESHCONF_RSSI_THRESHOLD,
/* keep last */
__NL80211_MESHCONF_ATTR_AFTER_LAST,
@@ -2804,10 +2823,13 @@ enum nl80211_ap_sme_features {
* TX status to the socket error queue when requested with the
* socket option.
* @NL80211_FEATURE_HT_IBSS: This driver supports IBSS with HT datarates.
+ * @NL80211_FEATURE_INACTIVITY_TIMER: This driver takes care of freeing up
+ * the connected inactive stations in AP mode.
*/
enum nl80211_feature_flags {
NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
NL80211_FEATURE_HT_IBSS = 1 << 1,
+ NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2,
};
/**
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index bbc2612cb64..d2768318002 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -19,7 +19,7 @@ struct ssb_driver;
struct ssb_sprom_core_pwr_info {
u8 itssi_2g, itssi_5g;
u8 maxpwr_2g, maxpwr_5gl, maxpwr_5g, maxpwr_5gh;
- u16 pa_2g[3], pa_5gl[3], pa_5g[3], pa_5gh[3];
+ u16 pa_2g[4], pa_5gl[4], pa_5g[4], pa_5gh[4];
};
struct ssb_sprom {
@@ -32,9 +32,12 @@ struct ssb_sprom {
u8 et0mdcport; /* MDIO for enet0 */
u8 et1mdcport; /* MDIO for enet1 */
u16 board_rev; /* Board revision number from SPROM. */
+ u16 board_num; /* Board number from SPROM. */
+ u16 board_type; /* Board type from SPROM. */
u8 country_code; /* Country Code */
- u16 leddc_on_time; /* LED Powersave Duty Cycle On Count */
- u16 leddc_off_time; /* LED Powersave Duty Cycle Off Count */
+ char alpha2[2]; /* Country Code as two chars like EU or US */
+ u8 leddc_on_time; /* LED Powersave Duty Cycle On Count */
+ u8 leddc_off_time; /* LED Powersave Duty Cycle Off Count */
u8 ant_available_a; /* 2GHz antenna available bits (up to 4) */
u8 ant_available_bg; /* 5GHz antenna available bits (up to 4) */
u16 pa0b0;
@@ -53,10 +56,10 @@ struct ssb_sprom {
u8 gpio1; /* GPIO pin 1 */
u8 gpio2; /* GPIO pin 2 */
u8 gpio3; /* GPIO pin 3 */
- u16 maxpwr_bg; /* 2.4GHz Amplifier Max Power (in dBm Q5.2) */
- u16 maxpwr_al; /* 5.2GHz Amplifier Max Power (in dBm Q5.2) */
- u16 maxpwr_a; /* 5.3GHz Amplifier Max Power (in dBm Q5.2) */
- u16 maxpwr_ah; /* 5.8GHz Amplifier Max Power (in dBm Q5.2) */
+ u8 maxpwr_bg; /* 2.4GHz Amplifier Max Power (in dBm Q5.2) */
+ u8 maxpwr_al; /* 5.2GHz Amplifier Max Power (in dBm Q5.2) */
+ u8 maxpwr_a; /* 5.3GHz Amplifier Max Power (in dBm Q5.2) */
+ u8 maxpwr_ah; /* 5.8GHz Amplifier Max Power (in dBm Q5.2) */
u8 itssi_a; /* Idle TSSI Target for A-PHY */
u8 itssi_bg; /* Idle TSSI Target for B/G-PHY */
u8 tri2g; /* 2.4GHz TX isolation */
@@ -67,8 +70,8 @@ struct ssb_sprom {
u8 txpid5gl[4]; /* 4.9 - 5.1GHz TX power index */
u8 txpid5g[4]; /* 5.1 - 5.5GHz TX power index */
u8 txpid5gh[4]; /* 5.5 - ...GHz TX power index */
- u8 rxpo2g; /* 2GHz RX power offset */
- u8 rxpo5g; /* 5GHz RX power offset */
+ s8 rxpo2g; /* 2GHz RX power offset */
+ s8 rxpo5g; /* 5GHz RX power offset */
u8 rssisav2g; /* 2GHz RSSI params */
u8 rssismc2g;
u8 rssismf2g;
@@ -94,12 +97,7 @@ struct ssb_sprom {
* on each band. Values in dBm/4 (Q5.2). Negative gain means the
* loss in the connectors is bigger than the gain. */
struct {
- struct {
- s8 a0, a1, a2, a3;
- } ghz24; /* 2.4GHz band */
- struct {
- s8 a0, a1, a2, a3;
- } ghz5; /* 5GHz band */
+ s8 a0, a1, a2, a3;
} antenna_gain;
struct {
@@ -111,7 +109,79 @@ struct ssb_sprom {
} ghz5;
} fem;
- /* TODO - add any parameters needed from rev 2, 3, 4, 5 or 8 SPROMs */
+ u16 mcs2gpo[8];
+ u16 mcs5gpo[8];
+ u16 mcs5glpo[8];
+ u16 mcs5ghpo[8];
+ u8 opo;
+
+ u8 rxgainerr2ga[3];
+ u8 rxgainerr5gla[3];
+ u8 rxgainerr5gma[3];
+ u8 rxgainerr5gha[3];
+ u8 rxgainerr5gua[3];
+
+ u8 noiselvl2ga[3];
+ u8 noiselvl5gla[3];
+ u8 noiselvl5gma[3];
+ u8 noiselvl5gha[3];
+ u8 noiselvl5gua[3];
+
+ u8 regrev;
+ u8 txchain;
+ u8 rxchain;
+ u8 antswitch;
+ u16 cddpo;
+ u16 stbcpo;
+ u16 bw40po;
+ u16 bwduppo;
+
+ u8 tempthresh;
+ u8 tempoffset;
+ u16 rawtempsense;
+ u8 measpower;
+ u8 tempsense_slope;
+ u8 tempcorrx;
+ u8 tempsense_option;
+ u8 freqoffset_corr;
+ u8 iqcal_swp_dis;
+ u8 hw_iqcal_en;
+ u8 elna2g;
+ u8 elna5g;
+ u8 phycal_tempdelta;
+ u8 temps_period;
+ u8 temps_hysteresis;
+ u8 measpower1;
+ u8 measpower2;
+ u8 pcieingress_war;
+
+ /* power per rate from sromrev 9 */
+ u16 cckbw202gpo;
+ u16 cckbw20ul2gpo;
+ u32 legofdmbw202gpo;
+ u32 legofdmbw20ul2gpo;
+ u32 legofdmbw205glpo;
+ u32 legofdmbw20ul5glpo;
+ u32 legofdmbw205gmpo;
+ u32 legofdmbw20ul5gmpo;
+ u32 legofdmbw205ghpo;
+ u32 legofdmbw20ul5ghpo;
+ u32 mcsbw202gpo;
+ u32 mcsbw20ul2gpo;
+ u32 mcsbw402gpo;
+ u32 mcsbw205glpo;
+ u32 mcsbw20ul5glpo;
+ u32 mcsbw405glpo;
+ u32 mcsbw205gmpo;
+ u32 mcsbw20ul5gmpo;
+ u32 mcsbw405gmpo;
+ u32 mcsbw205ghpo;
+ u32 mcsbw20ul5ghpo;
+ u32 mcsbw405ghpo;
+ u16 mcs32po;
+ u16 legofdm40duppo;
+ u8 sar2g;
+ u8 sar5g;
};
/* Information about the PCB the circuitry is soldered on. */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 0178c748937..57c9fddc2ac 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -413,6 +413,7 @@ struct cfg80211_beacon_data {
* @crypto: crypto settings
* @privacy: the BSS uses privacy
* @auth_type: Authentication type (algorithm)
+ * @inactivity_timeout: time in seconds to determine station's inactivity.
*/
struct cfg80211_ap_settings {
struct cfg80211_beacon_data beacon;
@@ -424,6 +425,7 @@ struct cfg80211_ap_settings {
struct cfg80211_crypto_settings crypto;
bool privacy;
enum nl80211_auth_type auth_type;
+ int inactivity_timeout;
};
/**
@@ -809,6 +811,7 @@ struct mesh_config {
* Still keeping the same nomenclature to be in sync with the spec. */
bool dot11MeshGateAnnouncementProtocol;
bool dot11MeshForwarding;
+ s32 rssi_threshold;
};
/**
@@ -1356,12 +1359,10 @@ struct cfg80211_gtk_rekey_data {
*
* @set_rekey_data: give the data necessary for GTK rekeying to the driver
*
- * @add_beacon: Add a beacon with given parameters, @head, @interval
- * and @dtim_period will be valid, @tail is optional.
- * @set_beacon: Change the beacon parameters for an access point mode
- * interface. This should reject the call when no beacon has been
- * configured.
- * @del_beacon: Remove beacon configuration and stop sending the beacon.
+ * @start_ap: Start acting in AP mode defined by the parameters.
+ * @change_beacon: Change the beacon parameters for an access point mode
+ * interface. This should reject the call when AP mode wasn't started.
+ * @stop_ap: Stop being an AP, including stopping beaconing.
*
* @add_station: Add a new station.
* @del_station: Remove a station; @mac may be NULL to remove all stations.
@@ -3188,6 +3189,7 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp);
* cfg80211_rx_mgmt - notification of received, unprocessed management frame
* @dev: network device
* @freq: Frequency on which the frame was received in MHz
+ * @sig_dbm: signal strength in mBm, or 0 if unknown
* @buf: Management frame (header + body)
* @len: length of the frame data
* @gfp: context flags
@@ -3200,8 +3202,8 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp);
* This function is called whenever an Action frame is received for a station
* mode interface, but is not processed in kernel.
*/
-bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf,
- size_t len, gfp_t gfp);
+bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_dbm,
+ const u8 *buf, size_t len, gfp_t gfp);
/**
* cfg80211_mgmt_tx_status - notification of TX status for management frame
@@ -3314,6 +3316,7 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
* @frame: the frame
* @len: length of the frame
* @freq: frequency the frame was received on
+ * @sig_dbm: signal strength in mBm, or 0 if unknown
* @gfp: allocation flags
*
* Use this function to report to userspace when a beacon was
@@ -3322,7 +3325,7 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
*/
void cfg80211_report_obss_beacon(struct wiphy *wiphy,
const u8 *frame, size_t len,
- int freq, gfp_t gfp);
+ int freq, int sig_dbm, gfp_t gfp);
/*
* cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used
@@ -3334,6 +3337,14 @@ int cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type);
+/*
+ * cfg80211_calculate_bitrate - calculate actual bitrate (in 100Kbps units)
+ * @rate: given rate_info to calculate bitrate from
+ *
+ * return 0 if MCS index >= 32
+ */
+u16 cfg80211_calculate_bitrate(struct rate_info *rate);
+
/* Logging, debugging and troubleshooting/diagnostic helpers. */
/* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 7477f020ee7..f7917f765cb 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -659,6 +659,8 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
* @RX_FLAG_40MHZ: HT40 (40 MHz) was used
* @RX_FLAG_SHORT_GI: Short guard interval was used
+ * @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present.
+ * Valid only for data frames (mainly A-MPDU)
*/
enum mac80211_rx_flags {
RX_FLAG_MMIC_ERROR = 1<<0,
@@ -672,6 +674,7 @@ enum mac80211_rx_flags {
RX_FLAG_HT = 1<<9,
RX_FLAG_40MHZ = 1<<10,
RX_FLAG_SHORT_GI = 1<<11,
+ RX_FLAG_NO_SIGNAL_VAL = 1<<12,
};
/**
@@ -3565,6 +3568,8 @@ enum rate_control_changed {
* @hw: The hardware the algorithm is invoked for.
* @sband: The band this frame is being transmitted on.
* @bss_conf: the current BSS configuration
+ * @skb: the skb that will be transmitted, the control information in it needs
+ * to be filled in
* @reported_rate: The rate control algorithm can fill this in to indicate
* which rate should be reported to userspace as the current rate and
* used for rate calculations in the mesh network.
@@ -3572,12 +3577,11 @@ enum rate_control_changed {
* RTS threshold
* @short_preamble: whether mac80211 will request short-preamble transmission
* if the selected rate supports it
- * @max_rate_idx: user-requested maximum rate (not MCS for now)
+ * @max_rate_idx: user-requested maximum (legacy) rate
* (deprecated; this will be removed once drivers get updated to use
* rate_idx_mask)
- * @rate_idx_mask: user-requested rate mask (not MCS for now)
- * @skb: the skb that will be transmitted, the control information in it needs
- * to be filled in
+ * @rate_idx_mask: user-requested (legacy) rate mask
+ * @rate_idx_mcs_mask: user-requested MCS rate mask
* @bss: whether this frame is sent out in AP or IBSS mode
*/
struct ieee80211_tx_rate_control {
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 86fee8b5c65..feba74027ff 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -141,17 +141,17 @@ struct nci_dev {
/* ----- NCI Devices ----- */
struct nci_dev *nci_allocate_device(struct nci_ops *ops,
- __u32 supported_protocols,
- int tx_headroom,
- int tx_tailroom);
+ __u32 supported_protocols,
+ int tx_headroom,
+ int tx_tailroom);
void nci_free_device(struct nci_dev *ndev);
int nci_register_device(struct nci_dev *ndev);
void nci_unregister_device(struct nci_dev *ndev);
int nci_recv_frame(struct sk_buff *skb);
static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev,
- unsigned int len,
- gfp_t how)
+ unsigned int len,
+ gfp_t how)
{
struct sk_buff *skb;
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index d253278e5a9..bac070bf351 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -53,15 +53,15 @@ struct nfc_ops {
int (*dev_down)(struct nfc_dev *dev);
int (*start_poll)(struct nfc_dev *dev, u32 protocols);
void (*stop_poll)(struct nfc_dev *dev);
- int (*dep_link_up)(struct nfc_dev *dev, int target_idx,
- u8 comm_mode, u8 rf_mode);
+ int (*dep_link_up)(struct nfc_dev *dev, int target_idx, u8 comm_mode,
+ u8 *gb, size_t gb_len);
int (*dep_link_down)(struct nfc_dev *dev);
int (*activate_target)(struct nfc_dev *dev, u32 target_idx,
- u32 protocol);
+ u32 protocol);
void (*deactivate_target)(struct nfc_dev *dev, u32 target_idx);
int (*data_exchange)(struct nfc_dev *dev, u32 target_idx,
- struct sk_buff *skb, data_exchange_cb_t cb,
- void *cb_context);
+ struct sk_buff *skb, data_exchange_cb_t cb,
+ void *cb_context);
};
#define NFC_TARGET_IDX_ANY -1
@@ -110,9 +110,9 @@ struct nfc_dev {
extern struct class nfc_class;
struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
- u32 supported_protocols,
- int tx_headroom,
- int tx_tailroom);
+ u32 supported_protocols,
+ int tx_headroom,
+ int tx_tailroom);
/**
* nfc_free_device - free nfc device
@@ -135,7 +135,7 @@ void nfc_unregister_device(struct nfc_dev *dev);
* @dev: The parent device
*/
static inline void nfc_set_parent_dev(struct nfc_dev *nfc_dev,
- struct device *dev)
+ struct device *dev)
{
nfc_dev->dev.parent = dev;
}
@@ -172,17 +172,15 @@ static inline const char *nfc_device_name(struct nfc_dev *dev)
}
struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk,
- unsigned int flags, unsigned int size,
- unsigned int *err);
+ unsigned int flags, unsigned int size,
+ unsigned int *err);
struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp);
int nfc_set_remote_general_bytes(struct nfc_dev *dev,
- u8 *gt, u8 gt_len);
+ u8 *gt, u8 gt_len);
-u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, u8 *gt_len);
-
-int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
- int ntargets);
+int nfc_targets_found(struct nfc_dev *dev,
+ struct nfc_target *targets, int ntargets);
int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
u8 comm_mode, u8 rf_mode);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 6a77d4c910f..677d6592978 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -336,6 +336,20 @@ static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, in
rate->mcs = idx;
}
+void sta_set_rate_info_tx(struct sta_info *sta,
+ const struct ieee80211_tx_rate *rate,
+ struct rate_info *rinfo)
+{
+ rinfo->flags = 0;
+ if (rate->flags & IEEE80211_TX_RC_MCS)
+ rinfo->flags |= RATE_INFO_FLAGS_MCS;
+ if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+ if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+ rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
+ rate_idx_to_bitrate(rinfo, sta, rate->idx);
+}
+
static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
@@ -378,14 +392,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
}
- sinfo->txrate.flags = 0;
- if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
- sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
- if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
- sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
- if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
- sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
- rate_idx_to_bitrate(&sinfo->txrate, sta, sta->last_tx_rate.idx);
+ sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
sinfo->rxrate.flags = 0;
if (sta->last_rx_rate_flag & RX_FLAG_HT)
@@ -1314,6 +1321,14 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
}
if (_chg_mesh_attr(NL80211_MESHCONF_FORWARDING, mask))
conf->dot11MeshForwarding = nconf->dot11MeshForwarding;
+ if (_chg_mesh_attr(NL80211_MESHCONF_RSSI_THRESHOLD, mask)) {
+ /* our RSSI threshold implementation is supported only for
+ * devices that report signal in dBm.
+ */
+ if (!(sdata->local->hw.flags & IEEE80211_HW_SIGNAL_DBM))
+ return -ENOTSUPP;
+ conf->rssi_threshold = nconf->rssi_threshold;
+ }
return 0;
}
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 510ed1dab3c..f6de8a65f40 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -443,6 +443,7 @@ IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol,
IEEE80211_IF_FILE(dot11MeshHWMPRannInterval,
u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC);
+IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC);
#endif
@@ -537,11 +538,15 @@ static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
#ifdef CONFIG_MAC80211_MESH
+static void add_mesh_files(struct ieee80211_sub_if_data *sdata)
+{
+ DEBUGFS_ADD_MODE(tsf, 0600);
+}
+
static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
{
struct dentry *dir = debugfs_create_dir("mesh_stats",
sdata->debugfs.dir);
-
#define MESHSTATS_ADD(name)\
debugfs_create_file(#name, 0400, dir, sdata, &name##_ops);
@@ -581,6 +586,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
MESHPARAMS_ADD(dot11MeshHWMPRootMode);
MESHPARAMS_ADD(dot11MeshHWMPRannInterval);
MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol);
+ MESHPARAMS_ADD(rssi_threshold);
#undef MESHPARAMS_ADD
}
#endif
@@ -593,6 +599,7 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
switch (sdata->vif.type) {
case NL80211_IFTYPE_MESH_POINT:
#ifdef CONFIG_MAC80211_MESH
+ add_mesh_files(sdata);
add_mesh_stats(sdata);
add_mesh_config(sdata);
#endif
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 7f9ac577600..33fd8d9f714 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -66,7 +66,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
skb_reset_tail_pointer(skb);
skb_reserve(skb, sdata->local->hw.extra_tx_headroom);
- if (memcmp(ifibss->bssid, bssid, ETH_ALEN))
+ if (compare_ether_addr(ifibss->bssid, bssid))
sta_info_flush(sdata->local, sdata);
/* if merging, indicate to driver that we leave the old IBSS */
@@ -403,7 +403,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
return;
if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
- memcmp(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0) {
+ compare_ether_addr(mgmt->bssid, sdata->u.ibss.bssid) == 0) {
rcu_read_lock();
sta = sta_info_get(sdata, mgmt->sa);
@@ -508,7 +508,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
goto put_bss;
/* same BSSID */
- if (memcmp(cbss->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0)
+ if (compare_ether_addr(cbss->bssid, sdata->u.ibss.bssid) == 0)
goto put_bss;
if (rx_status->flag & RX_FLAG_MACTIME_MPDU) {
@@ -831,8 +831,8 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da))
return;
- if (memcmp(mgmt->bssid, ifibss->bssid, ETH_ALEN) != 0 &&
- memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0)
+ if (compare_ether_addr(mgmt->bssid, ifibss->bssid) != 0 &&
+ !is_broadcast_ether_addr(mgmt->bssid))
return;
end = ((u8 *) mgmt) + len;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index cee0c7493fd..796b13bfc95 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -105,6 +105,44 @@ struct ieee80211_bss {
*/
bool has_erp_value;
u8 erp_value;
+
+ /* Keep track of the corruption of the last beacon/probe response. */
+ u8 corrupt_data;
+
+ /* Keep track of what bits of information we have valid info for. */
+ u8 valid_data;
+};
+
+/**
+ * enum ieee80211_corrupt_data_flags - BSS data corruption flags
+ * @IEEE80211_BSS_CORRUPT_BEACON: last beacon frame received was corrupted
+ * @IEEE80211_BSS_CORRUPT_PROBE_RESP: last probe response received was corrupted
+ *
+ * These are bss flags that are attached to a bss in the
+ * @corrupt_data field of &struct ieee80211_bss.
+ */
+enum ieee80211_bss_corrupt_data_flags {
+ IEEE80211_BSS_CORRUPT_BEACON = BIT(0),
+ IEEE80211_BSS_CORRUPT_PROBE_RESP = BIT(1)
+};
+
+/**
+ * enum ieee80211_valid_data_flags - BSS valid data flags
+ * @IEEE80211_BSS_VALID_DTIM: DTIM data was gathered from non-corrupt IE
+ * @IEEE80211_BSS_VALID_WMM: WMM/UAPSD data was gathered from non-corrupt IE
+ * @IEEE80211_BSS_VALID_RATES: Supported rates were gathered from non-corrupt IE
+ * @IEEE80211_BSS_VALID_ERP: ERP flag was gathered from non-corrupt IE
+ *
+ * These are bss flags that are attached to a bss in the
+ * @valid_data field of &struct ieee80211_bss. They show which parts
+ * of the data structure were recieved as a result of an un-corrupted
+ * beacon/probe response.
+ */
+enum ieee80211_bss_valid_data_flags {
+ IEEE80211_BSS_VALID_DTIM = BIT(0),
+ IEEE80211_BSS_VALID_WMM = BIT(1),
+ IEEE80211_BSS_VALID_RATES = BIT(2),
+ IEEE80211_BSS_VALID_ERP = BIT(3)
};
static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss)
@@ -480,7 +518,7 @@ struct ieee80211_if_ibss {
bool control_port;
- u8 bssid[ETH_ALEN];
+ u8 bssid[ETH_ALEN] __aligned(2);
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 ssid_len, ie_len;
u8 *ie;
@@ -1120,6 +1158,9 @@ struct ieee802_11_elems {
u8 quiet_elem_len;
u8 num_of_quiet_elem; /* can be more the one */
u8 timeout_int_len;
+
+ /* whether a parse error occurred while retrieving these elements */
+ bool parse_error;
};
static inline struct ieee80211_local *hw_to_local(
@@ -1348,7 +1389,8 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx,
struct ieee80211_hdr *hdr, const u8 *tsc,
gfp_t gfp);
-void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata);
+void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
+ bool bss_notify);
void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 620ca8d2ad4..401c01f0731 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -304,7 +304,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
* need to initialise the hardware if the hardware
* doesn't start up with sane defaults
*/
- ieee80211_set_wmm_default(sdata);
+ ieee80211_set_wmm_default(sdata, true);
}
set_bit(SDATA_STATE_RUNNING, &sdata->state);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index c707c8bf6d2..e5fbb7cf356 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -204,7 +204,7 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
kmem_cache_free(rm_cache, p);
--entries;
} else if ((seqnum == p->seqnum) &&
- (memcmp(sa, p->sa, ETH_ALEN) == 0))
+ (compare_ether_addr(sa, p->sa) == 0))
return -1;
}
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index c7e5c49471e..8d53b71378e 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -85,6 +85,8 @@ enum mesh_deferred_task_flags {
* @state_lock: mesh path state lock used to protect changes to the
* mpath itself. No need to take this lock when adding or removing
* an mpath to a hash bucket on a path table.
+ * @rann_snd_addr: the RANN sender address
+ * @is_root: the destination station of this path is a root node
* @is_gate: the destination station of this path is a mesh gate
*
*
@@ -109,6 +111,8 @@ struct mesh_path {
u8 discovery_retries;
enum mesh_path_flags flags;
spinlock_t state_lock;
+ u8 rann_snd_addr[ETH_ALEN];
+ bool is_root;
bool is_gate;
};
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 31bc762f209..1c6f3d02aeb 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -8,6 +8,7 @@
*/
#include <linux/slab.h>
+#include <linux/etherdevice.h>
#include <asm/unaligned.h>
#include "wme.h"
#include "mesh.h"
@@ -323,6 +324,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
struct sta_info *sta)
{
struct ieee80211_supported_band *sband;
+ struct rate_info rinfo;
/* This should be adjusted for each device */
int device_constant = 1 << ARITH_SHIFT;
int test_frame_len = TEST_FRAME_LEN << ARITH_SHIFT;
@@ -336,7 +338,9 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
if (sta->fail_avg >= 100)
return MAX_METRIC;
- if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+ sta_set_rate_info_tx(sta, &sta->last_tx_rate, &rinfo);
+ rate = cfg80211_calculate_bitrate(&rinfo);
+ if (WARN_ON(!rate))
return MAX_METRIC;
err = (sta->fail_avg << ARITH_SHIFT) / 100;
@@ -344,7 +348,6 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
/* bitrate is in units of 100 Kbps, while we need rate in units of
* 1Mbps. This will be corrected on tx_time computation.
*/
- rate = sband->bitrates[sta->last_tx_rate.idx].bitrate;
tx_time = (device_constant + 10 * test_frame_len / rate);
estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err));
result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ;
@@ -419,7 +422,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
new_metric = MAX_METRIC;
exp_time = TU_TO_EXP_TIME(orig_lifetime);
- if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) {
+ if (compare_ether_addr(orig_addr, sdata->vif.addr) == 0) {
/* This MP is the originator, we are not interested in this
* frame, except for updating transmitter's path info.
*/
@@ -469,7 +472,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
/* Update and check transmitter routing info */
ta = mgmt->sa;
- if (memcmp(orig_addr, ta, ETH_ALEN) == 0)
+ if (compare_ether_addr(orig_addr, ta) == 0)
fresh_info = false;
else {
fresh_info = true;
@@ -513,8 +516,9 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
u8 *preq_elem, u32 metric)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- struct mesh_path *mpath;
+ struct mesh_path *mpath = NULL;
u8 *target_addr, *orig_addr;
+ const u8 *da;
u8 target_flags, ttl;
u32 orig_sn, target_sn, lifetime;
bool reply = false;
@@ -529,7 +533,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
mhwmp_dbg("received PREQ from %pM", orig_addr);
- if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) {
+ if (compare_ether_addr(target_addr, sdata->vif.addr) == 0) {
mhwmp_dbg("PREQ is for us");
forward = false;
reply = true;
@@ -591,9 +595,11 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
flags = PREQ_IE_FLAGS(preq_elem);
preq_id = PREQ_IE_PREQ_ID(preq_elem);
hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1;
+ da = (mpath && mpath->is_root) ?
+ mpath->rann_snd_addr : broadcast_addr;
mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr,
cpu_to_le32(orig_sn), target_flags, target_addr,
- cpu_to_le32(target_sn), broadcast_addr,
+ cpu_to_le32(target_sn), da,
hopcount, ttl, cpu_to_le32(lifetime),
cpu_to_le32(metric), cpu_to_le32(preq_id),
sdata);
@@ -615,6 +621,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt,
u8 *prep_elem, u32 metric)
{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct mesh_path *mpath;
u8 *target_addr, *orig_addr;
u8 ttl, hopcount, flags;
@@ -624,10 +631,13 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
mhwmp_dbg("received PREP from %pM", PREP_IE_ORIG_ADDR(prep_elem));
orig_addr = PREP_IE_ORIG_ADDR(prep_elem);
- if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0)
+ if (compare_ether_addr(orig_addr, sdata->vif.addr) == 0)
/* destination, no forwarding required */
return;
+ if (!ifmsh->mshcfg.dot11MeshForwarding)
+ return;
+
ttl = PREP_IE_TTL(prep_elem);
if (ttl <= 1) {
sdata->u.mesh.mshstats.dropped_frames_ttl++;
@@ -694,21 +704,26 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
rcu_read_lock();
mpath = mesh_path_lookup(target_addr, sdata);
if (mpath) {
+ struct sta_info *sta;
+
spin_lock_bh(&mpath->state_lock);
+ sta = next_hop_deref_protected(mpath);
if (mpath->flags & MESH_PATH_ACTIVE &&
- memcmp(ta, next_hop_deref_protected(mpath)->sta.addr,
- ETH_ALEN) == 0 &&
+ compare_ether_addr(ta, sta->sta.addr) == 0 &&
(!(mpath->flags & MESH_PATH_SN_VALID) ||
SN_GT(target_sn, mpath->sn))) {
mpath->flags &= ~MESH_PATH_ACTIVE;
mpath->sn = target_sn;
spin_unlock_bh(&mpath->state_lock);
+ if (!ifmsh->mshcfg.dot11MeshForwarding)
+ goto endperr;
mesh_path_error_tx(ttl, target_addr, cpu_to_le32(target_sn),
cpu_to_le16(target_rcode),
broadcast_addr, sdata);
} else
spin_unlock_bh(&mpath->state_lock);
}
+endperr:
rcu_read_unlock();
}
@@ -739,11 +754,11 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
metric = rann->rann_metric;
/* Ignore our own RANNs */
- if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0)
+ if (compare_ether_addr(orig_addr, sdata->vif.addr) == 0)
return;
- mhwmp_dbg("received RANN from %pM (is_gate=%d)", orig_addr,
- root_is_gate);
+ mhwmp_dbg("received RANN from %pM via neighbour %pM (is_gate=%d)",
+ orig_addr, mgmt->sa, root_is_gate);
rcu_read_lock();
mpath = mesh_path_lookup(orig_addr, sdata);
@@ -765,7 +780,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
}
- if (mpath->sn < orig_sn) {
+ if (mpath->sn < orig_sn && ifmsh->mshcfg.dot11MeshForwarding) {
mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
cpu_to_le32(orig_sn),
0, NULL, 0, broadcast_addr,
@@ -774,6 +789,11 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
0, sdata);
mpath->sn = orig_sn;
}
+
+ /* Using individually addressed PREQ for root node */
+ memcpy(mpath->rann_snd_addr, mgmt->sa, ETH_ALEN);
+ mpath->is_root = true;
+
if (root_is_gate)
mesh_path_add_gate(mpath);
@@ -909,6 +929,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
struct mesh_preq_queue *preq_node;
struct mesh_path *mpath;
u8 ttl, target_flags;
+ const u8 *da;
u32 lifetime;
spin_lock_bh(&ifmsh->mesh_preq_queue_lock);
@@ -971,9 +992,10 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
target_flags = MP_F_RF;
spin_unlock_bh(&mpath->state_lock);
+ da = (mpath->is_root) ? mpath->rann_snd_addr : broadcast_addr;
mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr,
cpu_to_le32(ifmsh->sn), target_flags, mpath->dst,
- cpu_to_le32(mpath->sn), broadcast_addr, 0,
+ cpu_to_le32(mpath->sn), da, 0,
ttl, cpu_to_le32(lifetime), 0,
cpu_to_le32(ifmsh->preq_id++), sdata);
mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
@@ -1064,7 +1086,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
if (time_after(jiffies,
mpath->exp_time -
msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) &&
- !memcmp(sdata->vif.addr, hdr->addr4, ETH_ALEN) &&
+ !compare_ether_addr(sdata->vif.addr, hdr->addr4) &&
!(mpath->flags & MESH_PATH_RESOLVING) &&
!(mpath->flags & MESH_PATH_FIXED))
mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index dc51669e67d..be1361b5f7a 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -348,7 +348,7 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, u8 *dst,
hlist_for_each_entry_rcu(node, n, bucket, list) {
mpath = node->mpath;
if (mpath->sdata == sdata &&
- memcmp(dst, mpath->dst, ETH_ALEN) == 0) {
+ compare_ether_addr(dst, mpath->dst) == 0) {
if (MPATH_EXPIRED(mpath)) {
spin_lock_bh(&mpath->state_lock);
mpath->flags &= ~MESH_PATH_ACTIVE;
@@ -523,7 +523,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
int err = 0;
u32 hash_idx;
- if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0)
+ if (compare_ether_addr(dst, sdata->vif.addr) == 0)
/* never add ourselves as neighbours */
return -ENOTSUPP;
@@ -559,12 +559,13 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
hash_idx = mesh_table_hash(dst, sdata, tbl);
bucket = &tbl->hash_buckets[hash_idx];
- spin_lock_bh(&tbl->hashwlock[hash_idx]);
+ spin_lock(&tbl->hashwlock[hash_idx]);
err = -EEXIST;
hlist_for_each_entry(node, n, bucket, list) {
mpath = node->mpath;
- if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0)
+ if (mpath->sdata == sdata &&
+ compare_ether_addr(dst, mpath->dst) == 0)
goto err_exists;
}
@@ -575,7 +576,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
mesh_paths_generation++;
- spin_unlock_bh(&tbl->hashwlock[hash_idx]);
+ spin_unlock(&tbl->hashwlock[hash_idx]);
read_unlock_bh(&pathtbl_resize_lock);
if (grow) {
set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags);
@@ -584,7 +585,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
return 0;
err_exists:
- spin_unlock_bh(&tbl->hashwlock[hash_idx]);
+ spin_unlock(&tbl->hashwlock[hash_idx]);
read_unlock_bh(&pathtbl_resize_lock);
kfree(new_node);
err_node_alloc:
@@ -655,7 +656,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
int err = 0;
u32 hash_idx;
- if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0)
+ if (compare_ether_addr(dst, sdata->vif.addr) == 0)
/* never add ourselves as neighbours */
return -ENOTSUPP;
@@ -687,12 +688,13 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
hash_idx = mesh_table_hash(dst, sdata, tbl);
bucket = &tbl->hash_buckets[hash_idx];
- spin_lock_bh(&tbl->hashwlock[hash_idx]);
+ spin_lock(&tbl->hashwlock[hash_idx]);
err = -EEXIST;
hlist_for_each_entry(node, n, bucket, list) {
mpath = node->mpath;
- if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0)
+ if (mpath->sdata == sdata &&
+ compare_ether_addr(dst, mpath->dst) == 0)
goto err_exists;
}
@@ -701,7 +703,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
tbl->mean_chain_len * (tbl->hash_mask + 1))
grow = 1;
- spin_unlock_bh(&tbl->hashwlock[hash_idx]);
+ spin_unlock(&tbl->hashwlock[hash_idx]);
read_unlock_bh(&pathtbl_resize_lock);
if (grow) {
set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags);
@@ -710,7 +712,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
return 0;
err_exists:
- spin_unlock_bh(&tbl->hashwlock[hash_idx]);
+ spin_unlock(&tbl->hashwlock[hash_idx]);
read_unlock_bh(&pathtbl_resize_lock);
kfree(new_node);
err_node_alloc:
@@ -809,9 +811,9 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta)
for_each_mesh_entry(tbl, p, node, i) {
mpath = node->mpath;
if (rcu_dereference(mpath->next_hop) == sta) {
- spin_lock_bh(&tbl->hashwlock[i]);
+ spin_lock(&tbl->hashwlock[i]);
__mesh_path_del(tbl, node);
- spin_unlock_bh(&tbl->hashwlock[i]);
+ spin_unlock(&tbl->hashwlock[i]);
}
}
read_unlock_bh(&pathtbl_resize_lock);
@@ -882,11 +884,11 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
hash_idx = mesh_table_hash(addr, sdata, tbl);
bucket = &tbl->hash_buckets[hash_idx];
- spin_lock_bh(&tbl->hashwlock[hash_idx]);
+ spin_lock(&tbl->hashwlock[hash_idx]);
hlist_for_each_entry(node, n, bucket, list) {
mpath = node->mpath;
if (mpath->sdata == sdata &&
- memcmp(addr, mpath->dst, ETH_ALEN) == 0) {
+ compare_ether_addr(addr, mpath->dst) == 0) {
__mesh_path_del(tbl, node);
goto enddel;
}
@@ -895,7 +897,7 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
err = -ENXIO;
enddel:
mesh_paths_generation++;
- spin_unlock_bh(&tbl->hashwlock[hash_idx]);
+ spin_unlock(&tbl->hashwlock[hash_idx]);
read_unlock_bh(&pathtbl_resize_lock);
return err;
}
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 8806e5ef8ff..4e53c4cbca9 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -31,6 +31,12 @@
#define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout)
#define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks)
+/* We only need a valid sta if user configured a minimum rssi_threshold. */
+#define rssi_threshold_check(sta, sdata) \
+ (sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\
+ (sta && (s8) -ewma_read(&sta->avg_signal) > \
+ sdata->u.mesh.mshcfg.rssi_threshold))
+
enum plink_event {
PLINK_UNDEFINED,
OPN_ACPT,
@@ -301,7 +307,8 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates,
if (mesh_peer_accepts_plinks(elems) &&
sta->plink_state == NL80211_PLINK_LISTEN &&
sdata->u.mesh.accepting_plinks &&
- sdata->u.mesh.mshcfg.auto_open_plinks)
+ sdata->u.mesh.mshcfg.auto_open_plinks &&
+ rssi_threshold_check(sta, sdata))
mesh_plink_open(sta);
rcu_read_unlock();
@@ -531,6 +538,14 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
return;
}
+ if (ftype == WLAN_SP_MESH_PEERING_OPEN &&
+ !rssi_threshold_check(sta, sdata)) {
+ mpl_dbg("Mesh plink: %pM does not meet rssi threshold\n",
+ mgmt->sa);
+ rcu_read_unlock();
+ return;
+ }
+
if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) {
mpl_dbg("Mesh plink: Action frame from non-authed peer\n");
rcu_read_unlock();
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index caf97f5a293..c08924aeac0 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1277,7 +1277,6 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
/* enable WMM or activate new settings */
sdata->vif.bss_conf.qos = true;
- ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
}
static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
@@ -1455,8 +1454,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_ASSOC;
sdata->vif.bss_conf.assoc = false;
- ieee80211_set_wmm_default(sdata);
-
/* channel(_type) changes are handled by ieee80211_hw_config */
WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
@@ -1484,10 +1481,16 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_ARP_FILTER;
}
+ sdata->vif.bss_conf.qos = false;
+ changed |= BSS_CHANGED_QOS;
+
/* The BSSID (not really interesting) and HT changed */
changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
ieee80211_bss_info_change_notify(sdata, changed);
+ /* disassociated - set to defaults now */
+ ieee80211_set_wmm_default(sdata, false);
+
del_timer_sync(&sdata->u.mgd.conn_mon_timer);
del_timer_sync(&sdata->u.mgd.bcn_mon_timer);
del_timer_sync(&sdata->u.mgd.timer);
@@ -1822,7 +1825,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN);
- if (memcmp(bssid, mgmt->bssid, ETH_ALEN))
+ if (compare_ether_addr(bssid, mgmt->bssid))
return RX_MGMT_NONE;
auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
@@ -1903,7 +1906,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
return RX_MGMT_NONE;
if (!ifmgd->associated ||
- memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN))
+ compare_ether_addr(mgmt->bssid, ifmgd->associated->bssid))
return RX_MGMT_NONE;
bssid = ifmgd->associated->bssid;
@@ -1936,7 +1939,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
return RX_MGMT_NONE;
if (!ifmgd->associated ||
- memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN))
+ compare_ether_addr(mgmt->bssid, ifmgd->associated->bssid))
return RX_MGMT_NONE;
reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
@@ -2155,7 +2158,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
elems.wmm_param_len);
else
- ieee80211_set_wmm_default(sdata);
+ ieee80211_set_wmm_default(sdata, false);
+ changed |= BSS_CHANGED_QOS;
if (elems.ht_info_elem && elems.wmm_param &&
(sdata->local->hw.queues >= 4) &&
@@ -2203,7 +2207,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
if (!assoc_data)
return RX_MGMT_NONE;
- if (memcmp(assoc_data->bss->bssid, mgmt->bssid, ETH_ALEN))
+ if (compare_ether_addr(assoc_data->bss->bssid, mgmt->bssid))
return RX_MGMT_NONE;
/*
@@ -2291,8 +2295,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
bool need_ps = false;
if (sdata->u.mgd.associated &&
- memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid,
- ETH_ALEN) == 0) {
+ compare_ether_addr(mgmt->bssid, sdata->u.mgd.associated->bssid)
+ == 0) {
bss = (void *)sdata->u.mgd.associated->priv;
/* not previously set so we may need to recalc */
need_ps = !bss->dtim_period;
@@ -2347,7 +2351,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
ASSERT_MGD_MTX(ifmgd);
- if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN))
+ if (compare_ether_addr(mgmt->da, sdata->vif.addr))
return; /* ignore ProbeResp to foreign address */
baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
@@ -2360,11 +2364,12 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false);
if (ifmgd->associated &&
- memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0)
+ compare_ether_addr(mgmt->bssid, ifmgd->associated->bssid) == 0)
ieee80211_reset_ap_probe(sdata);
if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies &&
- memcmp(mgmt->bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN) == 0) {
+ compare_ether_addr(mgmt->bssid, ifmgd->auth_data->bss->bssid)
+ == 0) {
/* got probe response, continue with auth */
printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name);
ifmgd->auth_data->tries = 0;
@@ -2421,7 +2426,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
return;
if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon &&
- memcmp(mgmt->bssid, ifmgd->assoc_data->bss->bssid, ETH_ALEN) == 0) {
+ compare_ether_addr(mgmt->bssid, ifmgd->assoc_data->bss->bssid)
+ == 0) {
ieee802_11_parse_elems(mgmt->u.beacon.variable,
len - baselen, &elems);
@@ -2436,7 +2442,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
}
if (!ifmgd->associated ||
- memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN))
+ compare_ether_addr(mgmt->bssid, ifmgd->associated->bssid))
return;
bssid = ifmgd->associated->bssid;
@@ -3299,7 +3305,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
bool match;
/* keep sta info, bssid if matching */
- match = memcmp(ifmgd->bssid, req->bss->bssid, ETH_ALEN) == 0;
+ match = compare_ether_addr(ifmgd->bssid, req->bss->bssid) == 0;
ieee80211_destroy_auth_data(sdata, match);
}
@@ -3421,7 +3427,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
goto err_clear;
}
} else
- WARN_ON_ONCE(memcmp(ifmgd->bssid, req->bss->bssid, ETH_ALEN));
+ WARN_ON_ONCE(compare_ether_addr(ifmgd->bssid, req->bss->bssid));
if (!bss->dtim_period &&
sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) {
@@ -3440,6 +3446,20 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
}
run_again(ifmgd, assoc_data->timeout);
+ if (bss->corrupt_data) {
+ char *corrupt_type = "data";
+ if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_BEACON) {
+ if (bss->corrupt_data &
+ IEEE80211_BSS_CORRUPT_PROBE_RESP)
+ corrupt_type = "beacon and probe response";
+ else
+ corrupt_type = "beacon";
+ } else if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_PROBE_RESP)
+ corrupt_type = "probe response";
+ printk(KERN_DEBUG "%s: associating with AP with corrupt %s\n",
+ sdata->name, corrupt_type);
+ }
+
err = 0;
goto out;
err_clear:
@@ -3471,7 +3491,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
sdata->name, req->bssid, req->reason_code);
if (ifmgd->associated &&
- memcmp(ifmgd->associated->bssid, req->bssid, ETH_ALEN) == 0)
+ compare_ether_addr(ifmgd->associated->bssid, req->bssid) == 0)
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
req->reason_code, true, frame_buf);
else
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 7a4ff02af26..5f6e32ca085 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -177,7 +177,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
pos += 2;
/* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */
- if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+ if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM &&
+ !(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
*pos = status->signal;
rthdr->it_present |=
cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
@@ -227,7 +228,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
{
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb);
struct ieee80211_sub_if_data *sdata;
- int needed_headroom = 0;
+ int needed_headroom;
struct sk_buff *skb, *skb2;
struct net_device *prev_dev = NULL;
int present_fcs_len = 0;
@@ -489,12 +490,12 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
if (ieee80211_has_tods(hdr->frame_control) ||
!ieee80211_has_fromds(hdr->frame_control))
return RX_DROP_MONITOR;
- if (memcmp(hdr->addr3, dev_addr, ETH_ALEN) == 0)
+ if (compare_ether_addr(hdr->addr3, dev_addr) == 0)
return RX_DROP_MONITOR;
} else {
if (!ieee80211_has_a4(hdr->frame_control))
return RX_DROP_MONITOR;
- if (memcmp(hdr->addr4, dev_addr, ETH_ALEN) == 0)
+ if (compare_ether_addr(hdr->addr4, dev_addr) == 0)
return RX_DROP_MONITOR;
}
}
@@ -1309,8 +1310,10 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
sta->rx_fragments++;
sta->rx_bytes += rx->skb->len;
- sta->last_signal = status->signal;
- ewma_add(&sta->avg_signal, -status->signal);
+ if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
+ sta->last_signal = status->signal;
+ ewma_add(&sta->avg_signal, -status->signal);
+ }
/*
* Change STA power saving mode only at the end of a frame
@@ -1957,6 +1960,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
return RX_DROP_MONITOR;
}
+ if (!ifmsh->mshcfg.dot11MeshForwarding)
+ goto out;
+
fwd_skb = skb_copy(skb, GFP_ATOMIC);
if (!fwd_skb) {
if (net_ratelimit())
@@ -2182,9 +2188,14 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
ieee80211_is_beacon(mgmt->frame_control) &&
!(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {
+ int sig = 0;
+
+ if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
+ sig = status->signal;
+
cfg80211_report_obss_beacon(rx->local->hw.wiphy,
rx->skb->data, rx->skb->len,
- status->freq, GFP_ATOMIC);
+ status->freq, sig, GFP_ATOMIC);
rx->flags |= IEEE80211_RX_BEACON_REPORTED;
}
@@ -2336,7 +2347,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
if (sdata->vif.type != NL80211_IFTYPE_STATION)
break;
- if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN))
+ if (compare_ether_addr(mgmt->bssid, sdata->u.mgd.bssid))
break;
goto queue;
@@ -2408,6 +2419,7 @@ static ieee80211_rx_result debug_noinline
ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
{
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
+ int sig = 0;
/* skip known-bad action frames and return them in the next handler */
if (status->rx_flags & IEEE80211_RX_MALFORMED_ACTION_FRM)
@@ -2420,7 +2432,10 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
* it transmitted were processed or returned.
*/
- if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq,
+ if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
+ sig = status->signal;
+
+ if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq, sig,
rx->skb->data, rx->skb->len,
GFP_ATOMIC)) {
if (rx->sta)
@@ -2538,16 +2553,10 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
{
struct ieee80211_sub_if_data *sdata;
struct ieee80211_local *local = rx->local;
- struct ieee80211_rtap_hdr {
- struct ieee80211_radiotap_header hdr;
- u8 flags;
- u8 rate_or_pad;
- __le16 chan_freq;
- __le16 chan_flags;
- } __packed *rthdr;
struct sk_buff *skb = rx->skb, *skb2;
struct net_device *prev_dev = NULL;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+ int needed_headroom;
/*
* If cooked monitor has been processed already, then
@@ -2561,30 +2570,15 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
if (!local->cooked_mntrs)
goto out_free_skb;
- if (skb_headroom(skb) < sizeof(*rthdr) &&
- pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC))
- goto out_free_skb;
-
- rthdr = (void *)skb_push(skb, sizeof(*rthdr));
- memset(rthdr, 0, sizeof(*rthdr));
- rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
- rthdr->hdr.it_present =
- cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
- (1 << IEEE80211_RADIOTAP_CHANNEL));
+ /* room for the radiotap header based on driver features */
+ needed_headroom = ieee80211_rx_radiotap_len(local, status);
- if (rate) {
- rthdr->rate_or_pad = rate->bitrate / 5;
- rthdr->hdr.it_present |=
- cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
- }
- rthdr->chan_freq = cpu_to_le16(status->freq);
+ if (skb_headroom(skb) < needed_headroom &&
+ pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC))
+ goto out_free_skb;
- if (status->band == IEEE80211_BAND_5GHZ)
- rthdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_OFDM |
- IEEE80211_CHAN_5GHZ);
- else
- rthdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_DYN |
- IEEE80211_CHAN_2GHZ);
+ /* prepend radiotap information */
+ ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom);
skb_set_mac_header(skb, 0);
skb->ip_summed = CHECKSUM_UNNECESSARY;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 9270771702f..33cd1690137 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -13,6 +13,7 @@
*/
#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>
#include <linux/pm_qos.h>
#include <net/sch_generic.h>
@@ -103,16 +104,35 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
cbss->free_priv = ieee80211_rx_bss_free;
bss = (void *)cbss->priv;
+ if (elems->parse_error) {
+ if (beacon)
+ bss->corrupt_data |= IEEE80211_BSS_CORRUPT_BEACON;
+ else
+ bss->corrupt_data |= IEEE80211_BSS_CORRUPT_PROBE_RESP;
+ } else {
+ if (beacon)
+ bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_BEACON;
+ else
+ bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_PROBE_RESP;
+ }
+
/* save the ERP value so that it is available at association time */
- if (elems->erp_info && elems->erp_info_len >= 1) {
+ if (elems->erp_info && elems->erp_info_len >= 1 &&
+ (!elems->parse_error ||
+ !(bss->valid_data & IEEE80211_BSS_VALID_ERP))) {
bss->erp_value = elems->erp_info[0];
bss->has_erp_value = true;
+ if (!elems->parse_error)
+ bss->valid_data |= IEEE80211_BSS_VALID_ERP;
}
- if (elems->tim) {
+ if (elems->tim && (!elems->parse_error ||
+ !(bss->valid_data & IEEE80211_BSS_VALID_DTIM))) {
struct ieee80211_tim_ie *tim_ie =
(struct ieee80211_tim_ie *)elems->tim;
bss->dtim_period = tim_ie->dtim_period;
+ if (!elems->parse_error)
+ bss->valid_data |= IEEE80211_BSS_VALID_DTIM;
}
/* If the beacon had no TIM IE, or it was invalid, use 1 */
@@ -120,26 +140,38 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
bss->dtim_period = 1;
/* replace old supported rates if we get new values */
- srlen = 0;
- if (elems->supp_rates) {
- clen = IEEE80211_MAX_SUPP_RATES;
- if (clen > elems->supp_rates_len)
- clen = elems->supp_rates_len;
- memcpy(bss->supp_rates, elems->supp_rates, clen);
- srlen += clen;
- }
- if (elems->ext_supp_rates) {
- clen = IEEE80211_MAX_SUPP_RATES - srlen;
- if (clen > elems->ext_supp_rates_len)
- clen = elems->ext_supp_rates_len;
- memcpy(bss->supp_rates + srlen, elems->ext_supp_rates, clen);
- srlen += clen;
+ if (!elems->parse_error ||
+ !(bss->valid_data & IEEE80211_BSS_VALID_RATES)) {
+ srlen = 0;
+ if (elems->supp_rates) {
+ clen = IEEE80211_MAX_SUPP_RATES;
+ if (clen > elems->supp_rates_len)
+ clen = elems->supp_rates_len;
+ memcpy(bss->supp_rates, elems->supp_rates, clen);
+ srlen += clen;
+ }
+ if (elems->ext_supp_rates) {
+ clen = IEEE80211_MAX_SUPP_RATES - srlen;
+ if (clen > elems->ext_supp_rates_len)
+ clen = elems->ext_supp_rates_len;
+ memcpy(bss->supp_rates + srlen, elems->ext_supp_rates,
+ clen);
+ srlen += clen;
+ }
+ if (srlen) {
+ bss->supp_rates_len = srlen;
+ if (!elems->parse_error)
+ bss->valid_data |= IEEE80211_BSS_VALID_RATES;
+ }
}
- if (srlen)
- bss->supp_rates_len = srlen;
- bss->wmm_used = elems->wmm_param || elems->wmm_info;
- bss->uapsd_supported = is_uapsd_supported(elems);
+ if (!elems->parse_error ||
+ !(bss->valid_data & IEEE80211_BSS_VALID_WMM)) {
+ bss->wmm_used = elems->wmm_param || elems->wmm_info;
+ bss->uapsd_supported = is_uapsd_supported(elems);
+ if (!elems->parse_error)
+ bss->valid_data |= IEEE80211_BSS_VALID_WMM;
+ }
if (!beacon)
bss->last_probe_resp = jiffies;
@@ -176,7 +208,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
presp = ieee80211_is_probe_resp(fc);
if (presp) {
/* ignore ProbeResp to foreign address */
- if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN))
+ if (compare_ether_addr(mgmt->da, sdata->vif.addr))
return RX_DROP_MONITOR;
presp = true;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index cd0f265f42e..38137cb5f6f 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/etherdevice.h>
#include <linux/netdevice.h>
#include <linux/types.h>
#include <linux/slab.h>
@@ -101,7 +102,7 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
lockdep_is_held(&local->sta_mtx));
while (sta) {
if (sta->sdata == sdata &&
- memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
+ compare_ether_addr(sta->sta.addr, addr) == 0)
break;
sta = rcu_dereference_check(sta->hnext,
lockdep_is_held(&local->sta_mtx));
@@ -124,7 +125,7 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
while (sta) {
if ((sta->sdata == sdata ||
(sta->sdata->bss && sta->sdata->bss == sdata->bss)) &&
- memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
+ compare_ether_addr(sta->sta.addr, addr) == 0)
break;
sta = rcu_dereference_check(sta->hnext,
lockdep_is_held(&local->sta_mtx));
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 23a97c9dc04..ab0576827ba 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -14,6 +14,7 @@
#include <linux/if_ether.h>
#include <linux/workqueue.h>
#include <linux/average.h>
+#include <linux/etherdevice.h>
#include "key.h"
/**
@@ -489,7 +490,7 @@ void for_each_sta_info_type_check(struct ieee80211_local *local,
nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \
) \
/* compare address and run code only if it matches */ \
- if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0)
+ if (compare_ether_addr(_sta->sta.addr, (_addr)) == 0)
/*
* Get STA info by index, BROKEN!
@@ -528,6 +529,9 @@ void sta_info_init(struct ieee80211_local *local);
void sta_info_stop(struct ieee80211_local *local);
int sta_info_flush(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata);
+void sta_set_rate_info_tx(struct sta_info *sta,
+ const struct ieee80211_tx_rate *rate,
+ struct rate_info *rinfo);
void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
unsigned long exp_time);
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index c928e4a4eff..5f8f89e89d6 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -10,6 +10,7 @@
*/
#include <linux/export.h>
+#include <linux/etherdevice.h>
#include <net/mac80211.h>
#include <asm/unaligned.h>
#include "ieee80211_i.h"
@@ -377,7 +378,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
for_each_sta_info(local, hdr->addr1, sta, tmp) {
/* skip wrong virtual interface */
- if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN))
+ if (compare_ether_addr(hdr->addr2, sta->sdata->vif.addr))
continue;
if (info->flags & IEEE80211_TX_STATUS_EOSP)
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index f6e4cef9202..32f7a3b3d43 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -572,24 +572,40 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
size_t left = len;
u8 *pos = start;
bool calc_crc = filter != 0;
+ DECLARE_BITMAP(seen_elems, 256);
+ bitmap_zero(seen_elems, 256);
memset(elems, 0, sizeof(*elems));
elems->ie_start = start;
elems->total_len = len;
while (left >= 2) {
u8 id, elen;
+ bool elem_parse_failed;
id = *pos++;
elen = *pos++;
left -= 2;
- if (elen > left)
+ if (elen > left) {
+ elems->parse_error = true;
break;
+ }
+
+ if (id != WLAN_EID_VENDOR_SPECIFIC &&
+ id != WLAN_EID_QUIET &&
+ test_bit(id, seen_elems)) {
+ elems->parse_error = true;
+ left -= elen;
+ pos += elen;
+ continue;
+ }
if (calc_crc && id < 64 && (filter & (1ULL << id)))
crc = crc32_be(crc, pos - 2, elen + 2);
+ elem_parse_failed = false;
+
switch (id) {
case WLAN_EID_SSID:
elems->ssid = pos;
@@ -615,7 +631,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
if (elen >= sizeof(struct ieee80211_tim_ie)) {
elems->tim = (void *)pos;
elems->tim_len = elen;
- }
+ } else
+ elem_parse_failed = true;
break;
case WLAN_EID_IBSS_PARAMS:
elems->ibss_params = pos;
@@ -664,10 +681,14 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
case WLAN_EID_HT_CAPABILITY:
if (elen >= sizeof(struct ieee80211_ht_cap))
elems->ht_cap_elem = (void *)pos;
+ else
+ elem_parse_failed = true;
break;
case WLAN_EID_HT_INFORMATION:
if (elen >= sizeof(struct ieee80211_ht_info))
elems->ht_info_elem = (void *)pos;
+ else
+ elem_parse_failed = true;
break;
case WLAN_EID_MESH_ID:
elems->mesh_id = pos;
@@ -676,6 +697,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
case WLAN_EID_MESH_CONFIG:
if (elen >= sizeof(struct ieee80211_meshconf_ie))
elems->mesh_config = (void *)pos;
+ else
+ elem_parse_failed = true;
break;
case WLAN_EID_PEER_MGMT:
elems->peering = pos;
@@ -696,6 +719,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
case WLAN_EID_RANN:
if (elen >= sizeof(struct ieee80211_rann_ie))
elems->rann = (void *)pos;
+ else
+ elem_parse_failed = true;
break;
case WLAN_EID_CHANNEL_SWITCH:
elems->ch_switch_elem = pos;
@@ -724,10 +749,18 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
break;
}
+ if (elem_parse_failed)
+ elems->parse_error = true;
+ else
+ set_bit(id, seen_elems);
+
left -= elen;
pos += elen;
}
+ if (left != 0)
+ elems->parse_error = true;
+
return crc;
}
@@ -737,7 +770,8 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
ieee802_11_parse_elems_crc(start, len, elems, 0, 0);
}
-void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
+void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
+ bool bss_notify)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_queue_params qparam;
@@ -807,7 +841,9 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
sdata->vif.bss_conf.qos =
sdata->vif.type != NL80211_IFTYPE_STATION;
- ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
+ if (bss_notify)
+ ieee80211_bss_info_change_notify(sdata,
+ BSS_CHANGED_QOS);
}
}
@@ -829,7 +865,7 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
else
sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
- ieee80211_set_wmm_default(sdata);
+ ieee80211_set_wmm_default(sdata, true);
}
u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
diff --git a/net/nfc/af_nfc.c b/net/nfc/af_nfc.c
index da67756425c..9d68441e2a5 100644
--- a/net/nfc/af_nfc.c
+++ b/net/nfc/af_nfc.c
@@ -30,7 +30,7 @@ static DEFINE_RWLOCK(proto_tab_lock);
static const struct nfc_protocol *proto_tab[NFC_SOCKPROTO_MAX];
static int nfc_sock_create(struct net *net, struct socket *sock, int proto,
- int kern)
+ int kern)
{
int rc = -EPROTONOSUPPORT;
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 6089aca67b1..295d129864d 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -181,13 +181,13 @@ error:
return rc;
}
-int nfc_dep_link_up(struct nfc_dev *dev, int target_index,
- u8 comm_mode, u8 rf_mode)
+int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode)
{
int rc = 0;
+ u8 *gb;
+ size_t gb_len;
- pr_debug("dev_name=%s comm:%d rf:%d\n",
- dev_name(&dev->dev), comm_mode, rf_mode);
+ pr_debug("dev_name=%s comm %d\n", dev_name(&dev->dev), comm_mode);
if (!dev->ops->dep_link_up)
return -EOPNOTSUPP;
@@ -204,7 +204,13 @@ int nfc_dep_link_up(struct nfc_dev *dev, int target_index,
goto error;
}
- rc = dev->ops->dep_link_up(dev, target_index, comm_mode, rf_mode);
+ gb = nfc_llcp_general_bytes(dev, &gb_len);
+ if (gb_len > NFC_MAX_GT_LEN) {
+ rc = -EINVAL;
+ goto error;
+ }
+
+ rc = dev->ops->dep_link_up(dev, target_index, comm_mode, gb, gb_len);
error:
device_unlock(&dev->dev);
@@ -250,7 +256,7 @@ error:
}
int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
- u8 comm_mode, u8 rf_mode)
+ u8 comm_mode, u8 rf_mode)
{
dev->dep_link_up = true;
dev->dep_rf_mode = rf_mode;
@@ -330,10 +336,8 @@ error:
*
* The user must wait for the callback before calling this function again.
*/
-int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx,
- struct sk_buff *skb,
- data_exchange_cb_t cb,
- void *cb_context)
+int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
+ data_exchange_cb_t cb, void *cb_context)
{
int rc;
@@ -357,8 +361,7 @@ error:
int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len)
{
- pr_debug("dev_name=%s gb_len=%d\n",
- dev_name(&dev->dev), gb_len);
+ pr_debug("dev_name=%s gb_len=%d\n", dev_name(&dev->dev), gb_len);
if (gb_len > NFC_MAX_GT_LEN)
return -EINVAL;
@@ -367,12 +370,6 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len)
}
EXPORT_SYMBOL(nfc_set_remote_general_bytes);
-u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, u8 *gt_len)
-{
- return nfc_llcp_general_bytes(dev, gt_len);
-}
-EXPORT_SYMBOL(nfc_get_local_general_bytes);
-
/**
* nfc_alloc_send_skb - allocate a skb for data exchange responses
*
@@ -380,8 +377,8 @@ EXPORT_SYMBOL(nfc_get_local_general_bytes);
* @gfp: gfp flags
*/
struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk,
- unsigned int flags, unsigned int size,
- unsigned int *err)
+ unsigned int flags, unsigned int size,
+ unsigned int *err)
{
struct sk_buff *skb;
unsigned int total_size;
@@ -428,8 +425,8 @@ EXPORT_SYMBOL(nfc_alloc_recv_skb);
* are found. After calling this function, the device driver must stop
* polling for targets.
*/
-int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
- int n_targets)
+int nfc_targets_found(struct nfc_dev *dev,
+ struct nfc_target *targets, int n_targets)
{
pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets);
@@ -441,7 +438,7 @@ int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
kfree(dev->targets);
dev->targets = kmemdup(targets, n_targets * sizeof(struct nfc_target),
- GFP_ATOMIC);
+ GFP_ATOMIC);
if (!dev->targets) {
dev->n_targets = 0;
@@ -501,15 +498,14 @@ struct nfc_dev *nfc_get_device(unsigned idx)
* @supported_protocols: NFC protocols supported by the device
*/
struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
- u32 supported_protocols,
- int tx_headroom,
- int tx_tailroom)
+ u32 supported_protocols,
+ int tx_headroom, int tx_tailroom)
{
static atomic_t dev_no = ATOMIC_INIT(0);
struct nfc_dev *dev;
if (!ops->start_poll || !ops->stop_poll || !ops->activate_target ||
- !ops->deactivate_target || !ops->data_exchange)
+ !ops->deactivate_target || !ops->data_exchange)
return NULL;
if (!supported_protocols)
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index 151f2ef429c..7b76eb7192f 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -118,7 +118,7 @@ u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length)
}
int nfc_llcp_parse_tlv(struct nfc_llcp_local *local,
- u8 *tlv_array, u16 tlv_array_len)
+ u8 *tlv_array, u16 tlv_array_len)
{
u8 *tlv = tlv_array, type, length, offset = 0;
@@ -152,6 +152,8 @@ int nfc_llcp_parse_tlv(struct nfc_llcp_local *local,
case LLCP_TLV_RW:
local->remote_rw = llcp_tlv_rw(tlv);
break;
+ case LLCP_TLV_SN:
+ break;
default:
pr_err("Invalid gt tlv value 0x%x\n", type);
break;
@@ -162,15 +164,15 @@ int nfc_llcp_parse_tlv(struct nfc_llcp_local *local,
}
pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x rw %d\n",
- local->remote_version, local->remote_miu,
- local->remote_lto, local->remote_opt,
- local->remote_wks, local->remote_rw);
+ local->remote_version, local->remote_miu,
+ local->remote_lto, local->remote_opt,
+ local->remote_wks, local->remote_rw);
return 0;
}
static struct sk_buff *llcp_add_header(struct sk_buff *pdu,
- u8 dsap, u8 ssap, u8 ptype)
+ u8 dsap, u8 ssap, u8 ptype)
{
u8 header[2];
@@ -186,7 +188,8 @@ static struct sk_buff *llcp_add_header(struct sk_buff *pdu,
return pdu;
}
-static struct sk_buff *llcp_add_tlv(struct sk_buff *pdu, u8 *tlv, u8 tlv_length)
+static struct sk_buff *llcp_add_tlv(struct sk_buff *pdu, u8 *tlv,
+ u8 tlv_length)
{
/* XXX Add an skb length check */
@@ -199,7 +202,7 @@ static struct sk_buff *llcp_add_tlv(struct sk_buff *pdu, u8 *tlv, u8 tlv_length)
}
static struct sk_buff *llcp_allocate_pdu(struct nfc_llcp_sock *sock,
- u8 cmd, u16 size)
+ u8 cmd, u16 size)
{
struct sk_buff *skb;
int err;
@@ -208,7 +211,7 @@ static struct sk_buff *llcp_allocate_pdu(struct nfc_llcp_sock *sock,
return NULL;
skb = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT,
- size + LLCP_HEADER_SIZE, &err);
+ size + LLCP_HEADER_SIZE, &err);
if (skb == NULL) {
pr_err("Could not allocate PDU\n");
return NULL;
@@ -276,7 +279,7 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM);
return nfc_data_exchange(dev, local->target_idx, skb,
- nfc_llcp_recv, local);
+ nfc_llcp_recv, local);
}
int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
@@ -284,6 +287,9 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
struct nfc_llcp_local *local;
struct sk_buff *skb;
u8 *service_name_tlv = NULL, service_name_tlv_length;
+ u8 *miux_tlv = NULL, miux_tlv_length;
+ u8 *rw_tlv = NULL, rw_tlv_length, rw;
+ __be16 miux;
int err;
u16 size = 0;
@@ -295,12 +301,21 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
if (sock->service_name != NULL) {
service_name_tlv = nfc_llcp_build_tlv(LLCP_TLV_SN,
- sock->service_name,
- sock->service_name_len,
- &service_name_tlv_length);
+ sock->service_name,
+ sock->service_name_len,
+ &service_name_tlv_length);
size += service_name_tlv_length;
}
+ miux = cpu_to_be16(LLCP_MAX_MIUX);
+ miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
+ &miux_tlv_length);
+ size += miux_tlv_length;
+
+ rw = LLCP_MAX_RW;
+ rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length);
+ size += rw_tlv_length;
+
pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len);
skb = llcp_allocate_pdu(sock, LLCP_PDU_CONNECT, size);
@@ -311,7 +326,10 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
if (service_name_tlv != NULL)
skb = llcp_add_tlv(skb, service_name_tlv,
- service_name_tlv_length);
+ service_name_tlv_length);
+
+ skb = llcp_add_tlv(skb, miux_tlv, miux_tlv_length);
+ skb = llcp_add_tlv(skb, rw_tlv, rw_tlv_length);
skb_queue_tail(&local->tx_queue, skb);
@@ -321,6 +339,8 @@ error_tlv:
pr_err("error %d\n", err);
kfree(service_name_tlv);
+ kfree(miux_tlv);
+ kfree(rw_tlv);
return err;
}
@@ -329,6 +349,11 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
{
struct nfc_llcp_local *local;
struct sk_buff *skb;
+ u8 *miux_tlv = NULL, miux_tlv_length;
+ u8 *rw_tlv = NULL, rw_tlv_length, rw;
+ __be16 miux;
+ int err;
+ u16 size = 0;
pr_debug("Sending CC\n");
@@ -336,13 +361,35 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
if (local == NULL)
return -ENODEV;
- skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, 0);
- if (skb == NULL)
- return -ENOMEM;
+ miux = cpu_to_be16(LLCP_MAX_MIUX);
+ miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
+ &miux_tlv_length);
+ size += miux_tlv_length;
+
+ rw = LLCP_MAX_RW;
+ rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length);
+ size += rw_tlv_length;
+
+ skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size);
+ if (skb == NULL) {
+ err = -ENOMEM;
+ goto error_tlv;
+ }
+
+ skb = llcp_add_tlv(skb, miux_tlv, miux_tlv_length);
+ skb = llcp_add_tlv(skb, rw_tlv, rw_tlv_length);
skb_queue_tail(&local->tx_queue, skb);
return 0;
+
+error_tlv:
+ pr_err("error %d\n", err);
+
+ kfree(miux_tlv);
+ kfree(rw_tlv);
+
+ return err;
}
int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason)
@@ -397,3 +444,87 @@ int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock)
return 0;
}
+
+int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
+ struct msghdr *msg, size_t len)
+{
+ struct sk_buff *pdu;
+ struct sock *sk = &sock->sk;
+ struct nfc_llcp_local *local;
+ size_t frag_len = 0, remaining_len;
+ u8 *msg_data, *msg_ptr;
+
+ pr_debug("Send I frame len %zd\n", len);
+
+ local = sock->local;
+ if (local == NULL)
+ return -ENODEV;
+
+ msg_data = kzalloc(len, GFP_KERNEL);
+ if (msg_data == NULL)
+ return -ENOMEM;
+
+ if (memcpy_fromiovec(msg_data, msg->msg_iov, len)) {
+ kfree(msg_data);
+ return -EFAULT;
+ }
+
+ remaining_len = len;
+ msg_ptr = msg_data;
+
+ while (remaining_len > 0) {
+
+ frag_len = min_t(u16, local->remote_miu, remaining_len);
+
+ pr_debug("Fragment %zd bytes remaining %zd",
+ frag_len, remaining_len);
+
+ pdu = llcp_allocate_pdu(sock, LLCP_PDU_I,
+ frag_len + LLCP_SEQUENCE_SIZE);
+ if (pdu == NULL)
+ return -ENOMEM;
+
+ skb_put(pdu, LLCP_SEQUENCE_SIZE);
+
+ memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
+
+ skb_queue_head(&sock->tx_queue, pdu);
+
+ lock_sock(sk);
+
+ nfc_llcp_queue_i_frames(sock);
+
+ release_sock(sk);
+
+ remaining_len -= frag_len;
+ msg_ptr += len;
+ }
+
+ kfree(msg_data);
+
+ return 0;
+}
+
+int nfc_llcp_send_rr(struct nfc_llcp_sock *sock)
+{
+ struct sk_buff *skb;
+ struct nfc_llcp_local *local;
+
+ pr_debug("Send rr nr %d\n", sock->recv_n);
+
+ local = sock->local;
+ if (local == NULL)
+ return -ENODEV;
+
+ skb = llcp_allocate_pdu(sock, LLCP_PDU_RR, LLCP_SEQUENCE_SIZE);
+ if (skb == NULL)
+ return -ENOMEM;
+
+ skb_put(skb, LLCP_SEQUENCE_SIZE);
+
+ skb->data[2] = sock->recv_n % 16;
+
+ skb_queue_head(&local->tx_queue, skb);
+
+ return 0;
+}
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 1d32680807d..17a578f641f 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -37,7 +37,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
struct sock *sk, *parent_sk;
int i;
-
mutex_lock(&local->socket_lock);
for (i = 0; i < LLCP_MAX_SAP; i++) {
@@ -47,7 +46,7 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
/* Release all child sockets */
list_for_each_entry_safe(s, n, &parent->list, list) {
- list_del(&s->list);
+ list_del_init(&s->list);
sk = &s->sk;
lock_sock(sk);
@@ -56,9 +55,12 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
nfc_put_device(s->dev);
sk->sk_state = LLCP_CLOSED;
- sock_set_flag(sk, SOCK_DEAD);
release_sock(sk);
+
+ sock_orphan(sk);
+
+ s->local = NULL;
}
parent_sk = &parent->sk;
@@ -70,18 +72,19 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
struct sock *accept_sk;
list_for_each_entry_safe(lsk, n, &parent->accept_queue,
- accept_queue) {
+ accept_queue) {
accept_sk = &lsk->sk;
lock_sock(accept_sk);
nfc_llcp_accept_unlink(accept_sk);
accept_sk->sk_state = LLCP_CLOSED;
- sock_set_flag(accept_sk, SOCK_DEAD);
release_sock(accept_sk);
sock_orphan(accept_sk);
+
+ lsk->local = NULL;
}
}
@@ -89,18 +92,32 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
nfc_put_device(parent->dev);
parent_sk->sk_state = LLCP_CLOSED;
- sock_set_flag(parent_sk, SOCK_DEAD);
release_sock(parent_sk);
+
+ sock_orphan(parent_sk);
+
+ parent->local = NULL;
}
mutex_unlock(&local->socket_lock);
}
+static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local)
+{
+ mutex_lock(&local->sdp_lock);
+
+ local->local_wks = 0;
+ local->local_sdp = 0;
+ local->local_sap = 0;
+
+ mutex_unlock(&local->sdp_lock);
+}
+
static void nfc_llcp_timeout_work(struct work_struct *work)
{
struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
- timeout_work);
+ timeout_work);
nfc_dep_link_down(local->dev);
}
@@ -146,7 +163,7 @@ static int nfc_llcp_wks_sap(char *service_name, size_t service_name_len)
num_wks = ARRAY_SIZE(wks);
- for (sap = 0 ; sap < num_wks; sap++) {
+ for (sap = 0; sap < num_wks; sap++) {
if (wks[sap] == NULL)
continue;
@@ -158,13 +175,13 @@ static int nfc_llcp_wks_sap(char *service_name, size_t service_name_len)
}
u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
- struct nfc_llcp_sock *sock)
+ struct nfc_llcp_sock *sock)
{
mutex_lock(&local->sdp_lock);
if (sock->service_name != NULL && sock->service_name_len > 0) {
int ssap = nfc_llcp_wks_sap(sock->service_name,
- sock->service_name_len);
+ sock->service_name_len);
if (ssap > 0) {
pr_debug("WKS %d\n", ssap);
@@ -176,7 +193,7 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
return LLCP_SAP_MAX;
}
- set_bit(BIT(ssap), &local->local_wks);
+ set_bit(ssap, &local->local_wks);
mutex_unlock(&local->sdp_lock);
return ssap;
@@ -195,25 +212,25 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
pr_debug("SDP ssap %d\n", LLCP_WKS_NUM_SAP + ssap);
- set_bit(BIT(ssap), &local->local_sdp);
+ set_bit(ssap, &local->local_sdp);
mutex_unlock(&local->sdp_lock);
return LLCP_WKS_NUM_SAP + ssap;
} else if (sock->ssap != 0) {
if (sock->ssap < LLCP_WKS_NUM_SAP) {
- if (!(local->local_wks & BIT(sock->ssap))) {
- set_bit(BIT(sock->ssap), &local->local_wks);
+ if (!test_bit(sock->ssap, &local->local_wks)) {
+ set_bit(sock->ssap, &local->local_wks);
mutex_unlock(&local->sdp_lock);
return sock->ssap;
}
} else if (sock->ssap < LLCP_SDP_NUM_SAP) {
- if (!(local->local_sdp &
- BIT(sock->ssap - LLCP_WKS_NUM_SAP))) {
- set_bit(BIT(sock->ssap - LLCP_WKS_NUM_SAP),
- &local->local_sdp);
+ if (!test_bit(sock->ssap - LLCP_WKS_NUM_SAP,
+ &local->local_sdp)) {
+ set_bit(sock->ssap - LLCP_WKS_NUM_SAP,
+ &local->local_sdp);
mutex_unlock(&local->sdp_lock);
return sock->ssap;
@@ -238,7 +255,7 @@ u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local)
return LLCP_SAP_MAX;
}
- set_bit(BIT(local_ssap), &local->local_sap);
+ set_bit(local_ssap, &local->local_sap);
mutex_unlock(&local->sdp_lock);
@@ -265,12 +282,12 @@ void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap)
mutex_lock(&local->sdp_lock);
- clear_bit(1 << local_ssap, sdp);
+ clear_bit(local_ssap, sdp);
mutex_unlock(&local->sdp_lock);
}
-u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, u8 *general_bytes_len)
+u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len)
{
struct nfc_llcp_local *local;
@@ -294,7 +311,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
version = LLCP_VERSION_11;
version_tlv = nfc_llcp_build_tlv(LLCP_TLV_VERSION, &version,
- 1, &version_length);
+ 1, &version_length);
gb_len += version_length;
/* 1500 ms */
@@ -304,7 +321,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
pr_debug("Local wks 0x%lx\n", local->local_wks);
wks_tlv = nfc_llcp_build_tlv(LLCP_TLV_WKS, (u8 *)&local->local_wks, 2,
- &wks_length);
+ &wks_length);
gb_len += wks_length;
gb_len += ARRAY_SIZE(llcp_magic);
@@ -349,8 +366,7 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
memcpy(local->remote_gb, gb, gb_len);
local->remote_gb_len = gb_len;
- if (local->remote_gb == NULL ||
- local->remote_gb_len == 0)
+ if (local->remote_gb == NULL || local->remote_gb_len == 0)
return -ENODEV;
if (memcmp(local->remote_gb, llcp_magic, 3)) {
@@ -359,26 +375,27 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
}
return nfc_llcp_parse_tlv(local,
- &local->remote_gb[3], local->remote_gb_len - 3);
+ &local->remote_gb[3],
+ local->remote_gb_len - 3);
}
static void nfc_llcp_tx_work(struct work_struct *work)
{
struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
- tx_work);
+ tx_work);
struct sk_buff *skb;
skb = skb_dequeue(&local->tx_queue);
if (skb != NULL) {
pr_debug("Sending pending skb\n");
nfc_data_exchange(local->dev, local->target_idx,
- skb, nfc_llcp_recv, local);
+ skb, nfc_llcp_recv, local);
} else {
nfc_llcp_send_symm(local->dev);
}
mod_timer(&local->link_timer,
- jiffies + msecs_to_jiffies(local->remote_lto));
+ jiffies + msecs_to_jiffies(local->remote_lto));
}
static u8 nfc_llcp_dsap(struct sk_buff *pdu)
@@ -408,13 +425,13 @@ static u8 nfc_llcp_nr(struct sk_buff *pdu)
static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu)
{
- pdu->data[2] = (sock->send_n << 4) | ((sock->recv_n - 1) % 16);
+ pdu->data[2] = (sock->send_n << 4) | (sock->recv_n % 16);
sock->send_n = (sock->send_n + 1) % 16;
sock->recv_ack_n = (sock->recv_n - 1) % 16;
}
static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
- u8 ssap, u8 dsap)
+ u8 ssap, u8 dsap)
{
struct nfc_llcp_sock *sock, *llcp_sock, *n;
@@ -438,7 +455,7 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
list_for_each_entry_safe(llcp_sock, n, &sock->list, list) {
pr_debug("llcp_sock %p sk %p dsap %d\n", llcp_sock,
- &llcp_sock->sk, llcp_sock->dsap);
+ &llcp_sock->sk, llcp_sock->dsap);
if (llcp_sock->dsap == dsap) {
sock_hold(&llcp_sock->sk);
mutex_unlock(&local->socket_lock);
@@ -482,7 +499,7 @@ static u8 *nfc_llcp_connect_sn(struct sk_buff *skb, size_t *sn_len)
}
static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
struct sock *new_sk, *parent;
struct nfc_llcp_sock *sock, *new_sock;
@@ -494,7 +511,7 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
pr_debug("%d %d\n", dsap, ssap);
nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE],
- skb->len - LLCP_HEADER_SIZE);
+ skb->len - LLCP_HEADER_SIZE);
if (dsap != LLCP_SAP_SDP) {
bound_sap = dsap;
@@ -513,7 +530,7 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
lock_sock(&sock->sk);
if (sock->dsap == LLCP_SAP_SDP &&
- sock->sk.sk_state == LLCP_LISTEN)
+ sock->sk.sk_state == LLCP_LISTEN)
goto enqueue;
} else {
u8 *sn;
@@ -529,23 +546,23 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
mutex_lock(&local->socket_lock);
for (bound_sap = 0; bound_sap < LLCP_LOCAL_SAP_OFFSET;
- bound_sap++) {
+ bound_sap++) {
sock = local->sockets[bound_sap];
if (sock == NULL)
continue;
if (sock->service_name == NULL ||
- sock->service_name_len == 0)
+ sock->service_name_len == 0)
continue;
if (sock->service_name_len != sn_len)
continue;
if (sock->dsap == LLCP_SAP_SDP &&
- sock->sk.sk_state == LLCP_LISTEN &&
- !memcmp(sn, sock->service_name, sn_len)) {
+ sock->sk.sk_state == LLCP_LISTEN &&
+ !memcmp(sn, sock->service_name, sn_len)) {
pr_debug("Found service name at SAP %d\n",
- bound_sap);
+ bound_sap);
sock_hold(&sock->sk);
mutex_unlock(&local->socket_lock);
@@ -570,8 +587,7 @@ enqueue:
goto fail;
}
- new_sk = nfc_llcp_sock_alloc(NULL, parent->sk_type,
- GFP_ATOMIC);
+ new_sk = nfc_llcp_sock_alloc(NULL, parent->sk_type, GFP_ATOMIC);
if (new_sk == NULL) {
reason = LLCP_DM_REJ;
release_sock(&sock->sk);
@@ -616,8 +632,39 @@ fail:
}
+int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock)
+{
+ int nr_frames = 0;
+ struct nfc_llcp_local *local = sock->local;
+
+ pr_debug("Remote ready %d tx queue len %d remote rw %d",
+ sock->remote_ready, skb_queue_len(&sock->tx_pending_queue),
+ local->remote_rw);
+
+ /* Try to queue some I frames for transmission */
+ while (sock->remote_ready &&
+ skb_queue_len(&sock->tx_pending_queue) < local->remote_rw) {
+ struct sk_buff *pdu, *pending_pdu;
+
+ pdu = skb_dequeue(&sock->tx_queue);
+ if (pdu == NULL)
+ break;
+
+ /* Update N(S)/N(R) */
+ nfc_llcp_set_nrns(sock, pdu);
+
+ pending_pdu = skb_clone(pdu, GFP_KERNEL);
+
+ skb_queue_tail(&local->tx_queue, pdu);
+ skb_queue_tail(&sock->tx_pending_queue, pending_pdu);
+ nr_frames++;
+ }
+
+ return nr_frames;
+}
+
static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
struct nfc_llcp_sock *llcp_sock;
struct sock *sk;
@@ -644,15 +691,15 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
nfc_llcp_sock_put(llcp_sock);
}
- if (ns == llcp_sock->recv_n)
- llcp_sock->recv_n = (llcp_sock->recv_n + 1) % 16;
- else
- pr_err("Received out of sequence I PDU\n");
-
/* Pass the payload upstream */
if (ptype == LLCP_PDU_I) {
pr_debug("I frame, queueing on %p\n", &llcp_sock->sk);
+ if (ns == llcp_sock->recv_n)
+ llcp_sock->recv_n = (llcp_sock->recv_n + 1) % 16;
+ else
+ pr_err("Received out of sequence I PDU\n");
+
skb_pull(skb, LLCP_HEADER_SIZE + LLCP_SEQUENCE_SIZE);
if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) {
pr_err("receive queue is full\n");
@@ -673,30 +720,20 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
}
}
- /* Queue some I frames for transmission */
- while (llcp_sock->remote_ready &&
- skb_queue_len(&llcp_sock->tx_pending_queue) <= local->remote_rw) {
- struct sk_buff *pdu, *pending_pdu;
-
- pdu = skb_dequeue(&llcp_sock->tx_queue);
- if (pdu == NULL)
- break;
-
- /* Update N(S)/N(R) */
- nfc_llcp_set_nrns(llcp_sock, pdu);
+ if (ptype == LLCP_PDU_RR)
+ llcp_sock->remote_ready = true;
+ else if (ptype == LLCP_PDU_RNR)
+ llcp_sock->remote_ready = false;
- pending_pdu = skb_clone(pdu, GFP_KERNEL);
-
- skb_queue_tail(&local->tx_queue, pdu);
- skb_queue_tail(&llcp_sock->tx_pending_queue, pending_pdu);
- }
+ if (nfc_llcp_queue_i_frames(llcp_sock) == 0)
+ nfc_llcp_send_rr(llcp_sock);
release_sock(sk);
nfc_llcp_sock_put(llcp_sock);
}
static void nfc_llcp_recv_disc(struct nfc_llcp_local *local,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
struct nfc_llcp_sock *llcp_sock;
struct sock *sk;
@@ -718,7 +755,6 @@ static void nfc_llcp_recv_disc(struct nfc_llcp_local *local,
nfc_llcp_sock_put(llcp_sock);
}
-
if (sk->sk_state == LLCP_CONNECTED) {
nfc_put_device(local->dev);
sk->sk_state = LLCP_CLOSED;
@@ -731,13 +767,11 @@ static void nfc_llcp_recv_disc(struct nfc_llcp_local *local,
nfc_llcp_sock_put(llcp_sock);
}
-static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
- struct sk_buff *skb)
+static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb)
{
struct nfc_llcp_sock *llcp_sock;
u8 dsap, ssap;
-
dsap = nfc_llcp_dsap(skb);
ssap = nfc_llcp_ssap(skb);
@@ -756,7 +790,7 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
llcp_sock->dsap = ssap;
nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE],
- skb->len - LLCP_HEADER_SIZE);
+ skb->len - LLCP_HEADER_SIZE);
nfc_llcp_sock_put(llcp_sock);
}
@@ -764,7 +798,7 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
static void nfc_llcp_rx_work(struct work_struct *work)
{
struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
- rx_work);
+ rx_work);
u8 dsap, ssap, ptype;
struct sk_buff *skb;
@@ -802,6 +836,7 @@ static void nfc_llcp_rx_work(struct work_struct *work)
case LLCP_PDU_I:
case LLCP_PDU_RR:
+ case LLCP_PDU_RNR:
pr_debug("I frame\n");
nfc_llcp_recv_hdlc(local, skb);
break;
@@ -821,7 +856,7 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err)
pr_debug("Received an LLCP PDU\n");
if (err < 0) {
- pr_err("err %d", err);
+ pr_err("err %d\n", err);
return;
}
@@ -840,6 +875,8 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)
if (local == NULL)
return;
+ nfc_llcp_clear_sdp(local);
+
/* Close and purge all existing sockets */
nfc_llcp_socket_release(local);
}
@@ -865,7 +902,7 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
queue_work(local->tx_wq, &local->tx_work);
} else {
mod_timer(&local->link_timer,
- jiffies + msecs_to_jiffies(local->remote_lto));
+ jiffies + msecs_to_jiffies(local->remote_lto));
}
}
@@ -891,8 +928,10 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
skb_queue_head_init(&local->tx_queue);
INIT_WORK(&local->tx_work, nfc_llcp_tx_work);
snprintf(name, sizeof(name), "%s_llcp_tx_wq", dev_name(dev));
- local->tx_wq = alloc_workqueue(name,
- WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+ local->tx_wq =
+ alloc_workqueue(name,
+ WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM,
+ 1);
if (local->tx_wq == NULL) {
err = -ENOMEM;
goto err_local;
@@ -901,8 +940,10 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
local->rx_pending = NULL;
INIT_WORK(&local->rx_work, nfc_llcp_rx_work);
snprintf(name, sizeof(name), "%s_llcp_rx_wq", dev_name(dev));
- local->rx_wq = alloc_workqueue(name,
- WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+ local->rx_wq =
+ alloc_workqueue(name,
+ WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM,
+ 1);
if (local->rx_wq == NULL) {
err = -ENOMEM;
goto err_tx_wq;
@@ -910,8 +951,10 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
INIT_WORK(&local->timeout_work, nfc_llcp_timeout_work);
snprintf(name, sizeof(name), "%s_llcp_timeout_wq", dev_name(dev));
- local->timeout_wq = alloc_workqueue(name,
- WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+ local->timeout_wq =
+ alloc_workqueue(name,
+ WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM,
+ 1);
if (local->timeout_wq == NULL) {
err = -ENOMEM;
goto err_rx_wq;
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index 0ad2e336158..50680ce5ae4 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -28,6 +28,10 @@ enum llcp_state {
#define LLCP_DEFAULT_RW 1
#define LLCP_DEFAULT_MIU 128
+#define LLCP_MAX_LTO 0xff
+#define LLCP_MAX_RW 15
+#define LLCP_MAX_MIUX 0x7ff
+
#define LLCP_WKS_NUM_SAP 16
#define LLCP_SDP_NUM_SAP 16
#define LLCP_LOCAL_NUM_SAP 32
@@ -162,9 +166,10 @@ struct nfc_llcp_sock {
struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
- struct nfc_llcp_sock *sock);
+ struct nfc_llcp_sock *sock);
u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local);
void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap);
+int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock);
/* Sock API */
struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp);
@@ -175,7 +180,7 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock);
/* TLV API */
int nfc_llcp_parse_tlv(struct nfc_llcp_local *local,
- u8 *tlv_array, u16 tlv_array_len);
+ u8 *tlv_array, u16 tlv_array_len);
/* Commands API */
void nfc_llcp_recv(void *data, struct sk_buff *skb, int err);
@@ -187,6 +192,9 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock);
int nfc_llcp_send_cc(struct nfc_llcp_sock *sock);
int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason);
int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock);
+int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
+ struct msghdr *msg, size_t len);
+int nfc_llcp_send_rr(struct nfc_llcp_sock *sock);
/* Socket API */
int __init nfc_llcp_sock_init(void);
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index f738ccd535f..c13e02ebdef 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -78,9 +78,11 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
llcp_sock->local = local;
llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
llcp_sock->service_name_len = min_t(unsigned int,
- llcp_addr.service_name_len, NFC_LLCP_MAX_SERVICE_NAME);
+ llcp_addr.service_name_len,
+ NFC_LLCP_MAX_SERVICE_NAME);
llcp_sock->service_name = kmemdup(llcp_addr.service_name,
- llcp_sock->service_name_len, GFP_KERNEL);
+ llcp_sock->service_name_len,
+ GFP_KERNEL);
llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock);
if (llcp_sock->ssap == LLCP_MAX_SAP)
@@ -110,7 +112,7 @@ static int llcp_sock_listen(struct socket *sock, int backlog)
lock_sock(sk);
if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
- || sk->sk_state != LLCP_BOUND) {
+ || sk->sk_state != LLCP_BOUND) {
ret = -EBADFD;
goto error;
}
@@ -149,13 +151,13 @@ void nfc_llcp_accept_enqueue(struct sock *parent, struct sock *sk)
sock_hold(sk);
list_add_tail(&llcp_sock->accept_queue,
- &llcp_sock_parent->accept_queue);
+ &llcp_sock_parent->accept_queue);
llcp_sock->parent = parent;
sk_acceptq_added(parent);
}
struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
- struct socket *newsock)
+ struct socket *newsock)
{
struct nfc_llcp_sock *lsk, *n, *llcp_parent;
struct sock *sk;
@@ -163,7 +165,7 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
llcp_parent = nfc_llcp_sock(parent);
list_for_each_entry_safe(lsk, n, &llcp_parent->accept_queue,
- accept_queue) {
+ accept_queue) {
sk = &lsk->sk;
lock_sock(sk);
@@ -192,7 +194,7 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
}
static int llcp_sock_accept(struct socket *sock, struct socket *newsock,
- int flags)
+ int flags)
{
DECLARE_WAITQUEUE(wait, current);
struct sock *sk = sock->sk, *new_sk;
@@ -248,7 +250,7 @@ error:
static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr,
int *len, int peer)
{
- struct sockaddr_nfc_llcp *llcp_addr = (struct sockaddr_nfc_llcp *) addr;
+ struct sockaddr_nfc_llcp *llcp_addr = (struct sockaddr_nfc_llcp *)addr;
struct sock *sk = sock->sk;
struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
@@ -262,7 +264,7 @@ static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr,
llcp_addr->ssap = llcp_sock->ssap;
llcp_addr->service_name_len = llcp_sock->service_name_len;
memcpy(llcp_addr->service_name, llcp_sock->service_name,
- llcp_addr->service_name_len);
+ llcp_addr->service_name_len);
return 0;
}
@@ -275,7 +277,7 @@ static inline unsigned int llcp_accept_poll(struct sock *parent)
parent_sock = nfc_llcp_sock(parent);
list_for_each_entry_safe(llcp_sock, n, &parent_sock->accept_queue,
- accept_queue) {
+ accept_queue) {
sk = &llcp_sock->sk;
if (sk->sk_state == LLCP_CONNECTED)
@@ -286,7 +288,7 @@ static inline unsigned int llcp_accept_poll(struct sock *parent)
}
static unsigned int llcp_sock_poll(struct file *file, struct socket *sock,
- poll_table *wait)
+ poll_table *wait)
{
struct sock *sk = sock->sk;
unsigned int mask = 0;
@@ -315,6 +317,7 @@ static int llcp_sock_release(struct socket *sock)
struct sock *sk = sock->sk;
struct nfc_llcp_local *local;
struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
+ int err = 0;
if (!sk)
return 0;
@@ -322,25 +325,17 @@ static int llcp_sock_release(struct socket *sock)
pr_debug("%p\n", sk);
local = llcp_sock->local;
- if (local == NULL)
- return -ENODEV;
+ if (local == NULL) {
+ err = -ENODEV;
+ goto out;
+ }
mutex_lock(&local->socket_lock);
- if (llcp_sock == local->sockets[llcp_sock->ssap]) {
+ if (llcp_sock == local->sockets[llcp_sock->ssap])
local->sockets[llcp_sock->ssap] = NULL;
- } else {
- struct nfc_llcp_sock *parent, *s, *n;
-
- parent = local->sockets[llcp_sock->ssap];
-
- list_for_each_entry_safe(s, n, &parent->list, list)
- if (llcp_sock == s) {
- list_del(&s->list);
- break;
- }
-
- }
+ else
+ list_del_init(&llcp_sock->list);
mutex_unlock(&local->socket_lock);
@@ -355,7 +350,7 @@ static int llcp_sock_release(struct socket *sock)
struct sock *accept_sk;
list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue,
- accept_queue) {
+ accept_queue) {
accept_sk = &lsk->sk;
lock_sock(accept_sk);
@@ -364,31 +359,27 @@ static int llcp_sock_release(struct socket *sock)
release_sock(accept_sk);
- sock_set_flag(sk, SOCK_DEAD);
sock_orphan(accept_sk);
- sock_put(accept_sk);
}
}
/* Freeing the SAP */
if ((sk->sk_state == LLCP_CONNECTED
- && llcp_sock->ssap > LLCP_LOCAL_SAP_OFFSET) ||
- sk->sk_state == LLCP_BOUND ||
- sk->sk_state == LLCP_LISTEN)
+ && llcp_sock->ssap > LLCP_LOCAL_SAP_OFFSET) ||
+ sk->sk_state == LLCP_BOUND || sk->sk_state == LLCP_LISTEN)
nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap);
- sock_set_flag(sk, SOCK_DEAD);
-
release_sock(sk);
+out:
sock_orphan(sk);
sock_put(sk);
- return 0;
+ return err;
}
static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
- int len, int flags)
+ int len, int flags)
{
struct sock *sk = sock->sk;
struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
@@ -400,7 +391,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
pr_debug("sock %p sk %p flags 0x%x\n", sock, sk, flags);
if (!addr || len < sizeof(struct sockaddr_nfc) ||
- addr->sa_family != AF_NFC) {
+ addr->sa_family != AF_NFC) {
pr_err("Invalid socket\n");
return -EINVAL;
}
@@ -411,7 +402,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
}
pr_debug("addr dev_idx=%u target_idx=%u protocol=%u\n", addr->dev_idx,
- addr->target_idx, addr->nfc_protocol);
+ addr->target_idx, addr->nfc_protocol);
lock_sock(sk);
@@ -441,7 +432,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
device_unlock(&dev->dev);
if (local->rf_mode == NFC_RF_INITIATOR &&
- addr->target_idx != local->target_idx) {
+ addr->target_idx != local->target_idx) {
ret = -ENOLINK;
goto put_dev;
}
@@ -459,9 +450,11 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
llcp_sock->dsap = LLCP_SAP_SDP;
llcp_sock->nfc_protocol = addr->nfc_protocol;
llcp_sock->service_name_len = min_t(unsigned int,
- addr->service_name_len, NFC_LLCP_MAX_SERVICE_NAME);
+ addr->service_name_len,
+ NFC_LLCP_MAX_SERVICE_NAME);
llcp_sock->service_name = kmemdup(addr->service_name,
- llcp_sock->service_name_len, GFP_KERNEL);
+ llcp_sock->service_name_len,
+ GFP_KERNEL);
local->sockets[llcp_sock->ssap] = llcp_sock;
@@ -482,6 +475,34 @@ error:
return ret;
}
+static int llcp_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *msg, size_t len)
+{
+ struct sock *sk = sock->sk;
+ struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
+ int ret;
+
+ pr_debug("sock %p sk %p", sock, sk);
+
+ ret = sock_error(sk);
+ if (ret)
+ return ret;
+
+ if (msg->msg_flags & MSG_OOB)
+ return -EOPNOTSUPP;
+
+ lock_sock(sk);
+
+ if (sk->sk_state != LLCP_CONNECTED) {
+ release_sock(sk);
+ return -ENOTCONN;
+ }
+
+ release_sock(sk);
+
+ return nfc_llcp_send_i_frame(llcp_sock, msg, len);
+}
+
static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len, int flags)
{
@@ -496,7 +517,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
lock_sock(sk);
if (sk->sk_state == LLCP_CLOSED &&
- skb_queue_empty(&sk->sk_receive_queue)) {
+ skb_queue_empty(&sk->sk_receive_queue)) {
release_sock(sk);
return 0;
}
@@ -509,7 +530,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
skb = skb_recv_datagram(sk, flags, noblock, &err);
if (!skb) {
pr_err("Recv datagram failed state %d %d %d",
- sk->sk_state, err, sock_error(sk));
+ sk->sk_state, err, sock_error(sk));
if (sk->sk_shutdown & RCV_SHUTDOWN)
return 0;
@@ -517,7 +538,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
return err;
}
- rlen = skb->len; /* real length of skb */
+ rlen = skb->len; /* real length of skb */
copied = min_t(unsigned int, rlen, len);
cskb = skb;
@@ -567,7 +588,7 @@ static const struct proto_ops llcp_sock_ops = {
.shutdown = sock_no_shutdown,
.setsockopt = sock_no_setsockopt,
.getsockopt = sock_no_getsockopt,
- .sendmsg = sock_no_sendmsg,
+ .sendmsg = llcp_sock_sendmsg,
.recvmsg = llcp_sock_recvmsg,
.mmap = sock_no_mmap,
};
@@ -627,6 +648,8 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
{
+ struct nfc_llcp_local *local = sock->local;
+
kfree(sock->service_name);
skb_queue_purge(&sock->tx_queue);
@@ -635,11 +658,16 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
list_del_init(&sock->accept_queue);
+ if (local != NULL && sock == local->sockets[sock->ssap])
+ local->sockets[sock->ssap] = NULL;
+ else
+ list_del_init(&sock->list);
+
sock->parent = NULL;
}
static int llcp_sock_create(struct net *net, struct socket *sock,
- const struct nfc_protocol *nfc_proto)
+ const struct nfc_protocol *nfc_proto)
{
struct sock *sk;
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index a47e90c7d9d..9ec065bb9ee 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -66,9 +66,8 @@ static void nci_req_cancel(struct nci_dev *ndev, int err)
/* Execute request and wait for completion. */
static int __nci_request(struct nci_dev *ndev,
- void (*req)(struct nci_dev *ndev, unsigned long opt),
- unsigned long opt,
- __u32 timeout)
+ void (*req)(struct nci_dev *ndev, unsigned long opt),
+ unsigned long opt, __u32 timeout)
{
int rc = 0;
long completion_rc;
@@ -77,9 +76,9 @@ static int __nci_request(struct nci_dev *ndev,
init_completion(&ndev->req_completion);
req(ndev, opt);
- completion_rc = wait_for_completion_interruptible_timeout(
- &ndev->req_completion,
- timeout);
+ completion_rc =
+ wait_for_completion_interruptible_timeout(&ndev->req_completion,
+ timeout);
pr_debug("wait_for_completion return %ld\n", completion_rc);
@@ -110,8 +109,9 @@ static int __nci_request(struct nci_dev *ndev,
}
static inline int nci_request(struct nci_dev *ndev,
- void (*req)(struct nci_dev *ndev, unsigned long opt),
- unsigned long opt, __u32 timeout)
+ void (*req)(struct nci_dev *ndev,
+ unsigned long opt),
+ unsigned long opt, __u32 timeout)
{
int rc;
@@ -152,14 +152,14 @@ static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt)
/* by default mapping is set to NCI_RF_INTERFACE_FRAME */
for (i = 0; i < ndev->num_supported_rf_interfaces; i++) {
if (ndev->supported_rf_interfaces[i] ==
- NCI_RF_INTERFACE_ISO_DEP) {
+ NCI_RF_INTERFACE_ISO_DEP) {
cfg[*num].rf_protocol = NCI_RF_PROTOCOL_ISO_DEP;
cfg[*num].mode = NCI_DISC_MAP_MODE_POLL |
NCI_DISC_MAP_MODE_LISTEN;
cfg[*num].rf_interface = NCI_RF_INTERFACE_ISO_DEP;
(*num)++;
} else if (ndev->supported_rf_interfaces[i] ==
- NCI_RF_INTERFACE_NFC_DEP) {
+ NCI_RF_INTERFACE_NFC_DEP) {
cfg[*num].rf_protocol = NCI_RF_PROTOCOL_NFC_DEP;
cfg[*num].mode = NCI_DISC_MAP_MODE_POLL |
NCI_DISC_MAP_MODE_LISTEN;
@@ -172,8 +172,7 @@ static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt)
}
nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_MAP_CMD,
- (1 + ((*num)*sizeof(struct disc_map_config))),
- &cmd);
+ (1 + ((*num) * sizeof(struct disc_map_config))), &cmd);
}
static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt)
@@ -184,36 +183,36 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt)
cmd.num_disc_configs = 0;
if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
- (protocols & NFC_PROTO_JEWEL_MASK
- || protocols & NFC_PROTO_MIFARE_MASK
- || protocols & NFC_PROTO_ISO14443_MASK
- || protocols & NFC_PROTO_NFC_DEP_MASK)) {
+ (protocols & NFC_PROTO_JEWEL_MASK
+ || protocols & NFC_PROTO_MIFARE_MASK
+ || protocols & NFC_PROTO_ISO14443_MASK
+ || protocols & NFC_PROTO_NFC_DEP_MASK)) {
cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
- NCI_NFC_A_PASSIVE_POLL_MODE;
+ NCI_NFC_A_PASSIVE_POLL_MODE;
cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
cmd.num_disc_configs++;
}
if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
- (protocols & NFC_PROTO_ISO14443_MASK)) {
+ (protocols & NFC_PROTO_ISO14443_MASK)) {
cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
- NCI_NFC_B_PASSIVE_POLL_MODE;
+ NCI_NFC_B_PASSIVE_POLL_MODE;
cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
cmd.num_disc_configs++;
}
if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
- (protocols & NFC_PROTO_FELICA_MASK
- || protocols & NFC_PROTO_NFC_DEP_MASK)) {
+ (protocols & NFC_PROTO_FELICA_MASK
+ || protocols & NFC_PROTO_NFC_DEP_MASK)) {
cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
- NCI_NFC_F_PASSIVE_POLL_MODE;
+ NCI_NFC_F_PASSIVE_POLL_MODE;
cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
cmd.num_disc_configs++;
}
nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_CMD,
- (1 + (cmd.num_disc_configs*sizeof(struct disc_config))),
- &cmd);
+ (1 + (cmd.num_disc_configs * sizeof(struct disc_config))),
+ &cmd);
}
struct nci_rf_discover_select_param {
@@ -224,7 +223,7 @@ struct nci_rf_discover_select_param {
static void nci_rf_discover_select_req(struct nci_dev *ndev, unsigned long opt)
{
struct nci_rf_discover_select_param *param =
- (struct nci_rf_discover_select_param *)opt;
+ (struct nci_rf_discover_select_param *)opt;
struct nci_rf_discover_select_cmd cmd;
cmd.rf_discovery_id = param->rf_discovery_id;
@@ -245,8 +244,7 @@ static void nci_rf_discover_select_req(struct nci_dev *ndev, unsigned long opt)
}
nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_SELECT_CMD,
- sizeof(struct nci_rf_discover_select_cmd),
- &cmd);
+ sizeof(struct nci_rf_discover_select_cmd), &cmd);
}
static void nci_rf_deactivate_req(struct nci_dev *ndev, unsigned long opt)
@@ -256,8 +254,7 @@ static void nci_rf_deactivate_req(struct nci_dev *ndev, unsigned long opt)
cmd.type = NCI_DEACTIVATE_TYPE_IDLE_MODE;
nci_send_cmd(ndev, NCI_OP_RF_DEACTIVATE_CMD,
- sizeof(struct nci_rf_deactivate_cmd),
- &cmd);
+ sizeof(struct nci_rf_deactivate_cmd), &cmd);
}
static int nci_open_device(struct nci_dev *ndev)
@@ -281,16 +278,16 @@ static int nci_open_device(struct nci_dev *ndev)
set_bit(NCI_INIT, &ndev->flags);
rc = __nci_request(ndev, nci_reset_req, 0,
- msecs_to_jiffies(NCI_RESET_TIMEOUT));
+ msecs_to_jiffies(NCI_RESET_TIMEOUT));
if (!rc) {
rc = __nci_request(ndev, nci_init_req, 0,
- msecs_to_jiffies(NCI_INIT_TIMEOUT));
+ msecs_to_jiffies(NCI_INIT_TIMEOUT));
}
if (!rc) {
rc = __nci_request(ndev, nci_init_complete_req, 0,
- msecs_to_jiffies(NCI_INIT_TIMEOUT));
+ msecs_to_jiffies(NCI_INIT_TIMEOUT));
}
clear_bit(NCI_INIT, &ndev->flags);
@@ -340,7 +337,7 @@ static int nci_close_device(struct nci_dev *ndev)
set_bit(NCI_INIT, &ndev->flags);
__nci_request(ndev, nci_reset_req, 0,
- msecs_to_jiffies(NCI_RESET_TIMEOUT));
+ msecs_to_jiffies(NCI_RESET_TIMEOUT));
clear_bit(NCI_INIT, &ndev->flags);
/* Flush cmd wq */
@@ -396,7 +393,7 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols)
int rc;
if ((atomic_read(&ndev->state) == NCI_DISCOVERY) ||
- (atomic_read(&ndev->state) == NCI_W4_ALL_DISCOVERIES)) {
+ (atomic_read(&ndev->state) == NCI_W4_ALL_DISCOVERIES)) {
pr_err("unable to start poll, since poll is already active\n");
return -EBUSY;
}
@@ -407,17 +404,17 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols)
}
if ((atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) ||
- (atomic_read(&ndev->state) == NCI_POLL_ACTIVE)) {
+ (atomic_read(&ndev->state) == NCI_POLL_ACTIVE)) {
pr_debug("target active or w4 select, implicitly deactivate\n");
rc = nci_request(ndev, nci_rf_deactivate_req, 0,
- msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
+ msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
if (rc)
return -EBUSY;
}
rc = nci_request(ndev, nci_rf_discover_req, protocols,
- msecs_to_jiffies(NCI_RF_DISC_TIMEOUT));
+ msecs_to_jiffies(NCI_RF_DISC_TIMEOUT));
if (!rc)
ndev->poll_prots = protocols;
@@ -430,17 +427,17 @@ static void nci_stop_poll(struct nfc_dev *nfc_dev)
struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
if ((atomic_read(&ndev->state) != NCI_DISCOVERY) &&
- (atomic_read(&ndev->state) != NCI_W4_ALL_DISCOVERIES)) {
+ (atomic_read(&ndev->state) != NCI_W4_ALL_DISCOVERIES)) {
pr_err("unable to stop poll, since poll is not active\n");
return;
}
nci_request(ndev, nci_rf_deactivate_req, 0,
- msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
+ msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
}
static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx,
- __u32 protocol)
+ __u32 protocol)
{
struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
struct nci_rf_discover_select_param param;
@@ -451,7 +448,7 @@ static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx,
pr_debug("target_idx %d, protocol 0x%x\n", target_idx, protocol);
if ((atomic_read(&ndev->state) != NCI_W4_HOST_SELECT) &&
- (atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) {
+ (atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) {
pr_err("there is no available target to activate\n");
return -EINVAL;
}
@@ -494,8 +491,8 @@ static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx,
param.rf_protocol = NCI_RF_PROTOCOL_NFC_DEP;
rc = nci_request(ndev, nci_rf_discover_select_req,
- (unsigned long)&param,
- msecs_to_jiffies(NCI_RF_DISC_SELECT_TIMEOUT));
+ (unsigned long)&param,
+ msecs_to_jiffies(NCI_RF_DISC_SELECT_TIMEOUT));
}
if (!rc)
@@ -519,14 +516,13 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, __u32 target_idx)
if (atomic_read(&ndev->state) == NCI_POLL_ACTIVE) {
nci_request(ndev, nci_rf_deactivate_req, 0,
- msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
+ msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
}
}
static int nci_data_exchange(struct nfc_dev *nfc_dev, __u32 target_idx,
- struct sk_buff *skb,
- data_exchange_cb_t cb,
- void *cb_context)
+ struct sk_buff *skb,
+ data_exchange_cb_t cb, void *cb_context)
{
struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
int rc;
@@ -571,9 +567,8 @@ static struct nfc_ops nci_nfc_ops = {
* @supported_protocols: NFC protocols supported by the device
*/
struct nci_dev *nci_allocate_device(struct nci_ops *ops,
- __u32 supported_protocols,
- int tx_headroom,
- int tx_tailroom)
+ __u32 supported_protocols,
+ int tx_headroom, int tx_tailroom)
{
struct nci_dev *ndev;
@@ -594,9 +589,9 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops,
ndev->tx_tailroom = tx_tailroom;
ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops,
- supported_protocols,
- tx_headroom + NCI_DATA_HDR_SIZE,
- tx_tailroom);
+ supported_protocols,
+ tx_headroom + NCI_DATA_HDR_SIZE,
+ tx_tailroom);
if (!ndev->nfc_dev)
goto free_exit;
@@ -668,9 +663,9 @@ int nci_register_device(struct nci_dev *ndev)
skb_queue_head_init(&ndev->tx_q);
setup_timer(&ndev->cmd_timer, nci_cmd_timer,
- (unsigned long) ndev);
+ (unsigned long) ndev);
setup_timer(&ndev->data_timer, nci_data_timer,
- (unsigned long) ndev);
+ (unsigned long) ndev);
mutex_init(&ndev->req_lock);
@@ -719,7 +714,7 @@ int nci_recv_frame(struct sk_buff *skb)
pr_debug("len %d\n", skb->len);
if (!ndev || (!test_bit(NCI_UP, &ndev->flags)
- && !test_bit(NCI_INIT, &ndev->flags))) {
+ && !test_bit(NCI_INIT, &ndev->flags))) {
kfree_skb(skb);
return -ENXIO;
}
@@ -799,7 +794,7 @@ static void nci_tx_work(struct work_struct *work)
/* Check if data flow control is used */
if (atomic_read(&ndev->credits_cnt) !=
- NCI_DATA_FLOW_CONTROL_NOT_USED)
+ NCI_DATA_FLOW_CONTROL_NOT_USED)
atomic_dec(&ndev->credits_cnt);
pr_debug("NCI TX: MT=data, PBF=%d, conn_id=%d, plen=%d\n",
@@ -810,7 +805,7 @@ static void nci_tx_work(struct work_struct *work)
nci_send_frame(skb);
mod_timer(&ndev->data_timer,
- jiffies + msecs_to_jiffies(NCI_DATA_TIMEOUT));
+ jiffies + msecs_to_jiffies(NCI_DATA_TIMEOUT));
}
}
@@ -879,6 +874,6 @@ static void nci_cmd_work(struct work_struct *work)
nci_send_frame(skb);
mod_timer(&ndev->cmd_timer,
- jiffies + msecs_to_jiffies(NCI_CMD_TIMEOUT));
+ jiffies + msecs_to_jiffies(NCI_CMD_TIMEOUT));
}
}
diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c
index 7880ae924d5..a0bc326308a 100644
--- a/net/nfc/nci/data.c
+++ b/net/nfc/nci/data.c
@@ -35,8 +35,7 @@
#include <linux/nfc.h>
/* Complete data exchange transaction and forward skb to nfc core */
-void nci_data_exchange_complete(struct nci_dev *ndev,
- struct sk_buff *skb,
+void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,
int err)
{
data_exchange_cb_t cb = ndev->data_exchange_cb;
@@ -67,9 +66,9 @@ void nci_data_exchange_complete(struct nci_dev *ndev,
/* ----------------- NCI TX Data ----------------- */
static inline void nci_push_data_hdr(struct nci_dev *ndev,
- __u8 conn_id,
- struct sk_buff *skb,
- __u8 pbf)
+ __u8 conn_id,
+ struct sk_buff *skb,
+ __u8 pbf)
{
struct nci_data_hdr *hdr;
int plen = skb->len;
@@ -86,8 +85,8 @@ static inline void nci_push_data_hdr(struct nci_dev *ndev,
}
static int nci_queue_tx_data_frags(struct nci_dev *ndev,
- __u8 conn_id,
- struct sk_buff *skb) {
+ __u8 conn_id,
+ struct sk_buff *skb) {
int total_len = skb->len;
unsigned char *data = skb->data;
unsigned long flags;
@@ -105,8 +104,8 @@ static int nci_queue_tx_data_frags(struct nci_dev *ndev,
min_t(int, total_len, ndev->max_data_pkt_payload_size);
skb_frag = nci_skb_alloc(ndev,
- (NCI_DATA_HDR_SIZE + frag_len),
- GFP_KERNEL);
+ (NCI_DATA_HDR_SIZE + frag_len),
+ GFP_KERNEL);
if (skb_frag == NULL) {
rc = -ENOMEM;
goto free_exit;
@@ -118,7 +117,8 @@ static int nci_queue_tx_data_frags(struct nci_dev *ndev,
/* second, set the header */
nci_push_data_hdr(ndev, conn_id, skb_frag,
- ((total_len == frag_len) ? (NCI_PBF_LAST) : (NCI_PBF_CONT)));
+ ((total_len == frag_len) ?
+ (NCI_PBF_LAST) : (NCI_PBF_CONT)));
__skb_queue_tail(&frags_q, skb_frag);
@@ -186,8 +186,8 @@ exit:
/* ----------------- NCI RX Data ----------------- */
static void nci_add_rx_data_frag(struct nci_dev *ndev,
- struct sk_buff *skb,
- __u8 pbf)
+ struct sk_buff *skb,
+ __u8 pbf)
{
int reassembly_len;
int err = 0;
@@ -211,8 +211,8 @@ static void nci_add_rx_data_frag(struct nci_dev *ndev,
/* second, combine the two fragments */
memcpy(skb_push(skb, reassembly_len),
- ndev->rx_data_reassembly->data,
- reassembly_len);
+ ndev->rx_data_reassembly->data,
+ reassembly_len);
/* third, free old reassembly */
kfree_skb(ndev->rx_data_reassembly);
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 03e7b4626a3..2e3dee42196 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -40,7 +40,7 @@
/* Handle NCI Notification packets */
static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
struct nci_core_conn_credit_ntf *ntf = (void *) skb->data;
int i;
@@ -62,7 +62,7 @@ static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev,
if (ntf->conn_entries[i].conn_id == NCI_STATIC_RF_CONN_ID) {
/* found static rf connection */
atomic_add(ntf->conn_entries[i].credits,
- &ndev->credits_cnt);
+ &ndev->credits_cnt);
}
}
@@ -72,7 +72,7 @@ static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev,
}
static void nci_core_generic_error_ntf_packet(struct nci_dev *ndev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
__u8 status = skb->data[0];
@@ -80,7 +80,7 @@ static void nci_core_generic_error_ntf_packet(struct nci_dev *ndev,
if (atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) {
/* Activation failed, so complete the request
- (the state remains the same) */
+ (the state remains the same) */
nci_req_complete(ndev, status);
}
}
@@ -101,7 +101,7 @@ static void nci_core_conn_intf_error_ntf_packet(struct nci_dev *ndev,
static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev,
struct rf_tech_specific_params_nfca_poll *nfca_poll,
- __u8 *data)
+ __u8 *data)
{
nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data));
data += 2;
@@ -128,7 +128,7 @@ static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev,
static __u8 *nci_extract_rf_params_nfcb_passive_poll(struct nci_dev *ndev,
struct rf_tech_specific_params_nfcb_poll *nfcb_poll,
- __u8 *data)
+ __u8 *data)
{
nfcb_poll->sensb_res_len = *data++;
@@ -142,13 +142,13 @@ static __u8 *nci_extract_rf_params_nfcb_passive_poll(struct nci_dev *ndev,
static __u8 *nci_extract_rf_params_nfcf_passive_poll(struct nci_dev *ndev,
struct rf_tech_specific_params_nfcf_poll *nfcf_poll,
- __u8 *data)
+ __u8 *data)
{
nfcf_poll->bit_rate = *data++;
nfcf_poll->sensf_res_len = *data++;
pr_debug("bit_rate %d, sensf_res_len %d\n",
- nfcf_poll->bit_rate, nfcf_poll->sensf_res_len);
+ nfcf_poll->bit_rate, nfcf_poll->sensf_res_len);
memcpy(nfcf_poll->sensf_res, data, nfcf_poll->sensf_res_len);
data += nfcf_poll->sensf_res_len;
@@ -189,7 +189,7 @@ static int nci_add_new_protocol(struct nci_dev *ndev,
target->nfcid1_len = nfca_poll->nfcid1_len;
if (target->nfcid1_len > 0) {
memcpy(target->nfcid1, nfca_poll->nfcid1,
- target->nfcid1_len);
+ target->nfcid1_len);
}
} else if (rf_tech_and_mode == NCI_NFC_B_PASSIVE_POLL_MODE) {
nfcb_poll = (struct rf_tech_specific_params_nfcb_poll *)params;
@@ -197,7 +197,7 @@ static int nci_add_new_protocol(struct nci_dev *ndev,
target->sensb_res_len = nfcb_poll->sensb_res_len;
if (target->sensb_res_len > 0) {
memcpy(target->sensb_res, nfcb_poll->sensb_res,
- target->sensb_res_len);
+ target->sensb_res_len);
}
} else if (rf_tech_and_mode == NCI_NFC_F_PASSIVE_POLL_MODE) {
nfcf_poll = (struct rf_tech_specific_params_nfcf_poll *)params;
@@ -205,7 +205,7 @@ static int nci_add_new_protocol(struct nci_dev *ndev,
target->sensf_res_len = nfcf_poll->sensf_res_len;
if (target->sensf_res_len > 0) {
memcpy(target->sensf_res, nfcf_poll->sensf_res,
- target->sensf_res_len);
+ target->sensf_res_len);
}
} else {
pr_err("unsupported rf_tech_and_mode 0x%x\n", rf_tech_and_mode);
@@ -220,7 +220,7 @@ static int nci_add_new_protocol(struct nci_dev *ndev,
}
static void nci_add_new_target(struct nci_dev *ndev,
- struct nci_rf_discover_ntf *ntf)
+ struct nci_rf_discover_ntf *ntf)
{
struct nfc_target *target;
int i, rc;
@@ -230,8 +230,8 @@ static void nci_add_new_target(struct nci_dev *ndev,
if (target->idx == ntf->rf_discovery_id) {
/* This target already exists, add the new protocol */
nci_add_new_protocol(ndev, target, ntf->rf_protocol,
- ntf->rf_tech_and_mode,
- &ntf->rf_tech_specific_params);
+ ntf->rf_tech_and_mode,
+ &ntf->rf_tech_specific_params);
return;
}
}
@@ -245,27 +245,27 @@ static void nci_add_new_target(struct nci_dev *ndev,
target = &ndev->targets[ndev->n_targets];
rc = nci_add_new_protocol(ndev, target, ntf->rf_protocol,
- ntf->rf_tech_and_mode,
- &ntf->rf_tech_specific_params);
+ ntf->rf_tech_and_mode,
+ &ntf->rf_tech_specific_params);
if (!rc) {
target->idx = ntf->rf_discovery_id;
ndev->n_targets++;
pr_debug("target_idx %d, n_targets %d\n", target->idx,
- ndev->n_targets);
+ ndev->n_targets);
}
}
void nci_clear_target_list(struct nci_dev *ndev)
{
memset(ndev->targets, 0,
- (sizeof(struct nfc_target)*NCI_MAX_DISCOVERED_TARGETS));
+ (sizeof(struct nfc_target)*NCI_MAX_DISCOVERED_TARGETS));
ndev->n_targets = 0;
}
static void nci_rf_discover_ntf_packet(struct nci_dev *ndev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
struct nci_rf_discover_ntf ntf;
__u8 *data = skb->data;
@@ -280,7 +280,7 @@ static void nci_rf_discover_ntf_packet(struct nci_dev *ndev,
pr_debug("rf_protocol 0x%x\n", ntf.rf_protocol);
pr_debug("rf_tech_and_mode 0x%x\n", ntf.rf_tech_and_mode);
pr_debug("rf_tech_specific_params_len %d\n",
- ntf.rf_tech_specific_params_len);
+ ntf.rf_tech_specific_params_len);
if (ntf.rf_tech_specific_params_len > 0) {
switch (ntf.rf_tech_and_mode) {
@@ -318,7 +318,7 @@ static void nci_rf_discover_ntf_packet(struct nci_dev *ndev,
} else {
atomic_set(&ndev->state, NCI_W4_HOST_SELECT);
nfc_targets_found(ndev->nfc_dev, ndev->targets,
- ndev->n_targets);
+ ndev->n_targets);
}
}
@@ -335,20 +335,17 @@ static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev,
pr_debug("rats_res_len %d\n", nfca_poll->rats_res_len);
if (nfca_poll->rats_res_len > 0) {
memcpy(nfca_poll->rats_res,
- data,
- nfca_poll->rats_res_len);
+ data, nfca_poll->rats_res_len);
}
break;
case NCI_NFC_B_PASSIVE_POLL_MODE:
nfcb_poll = &ntf->activation_params.nfcb_poll_iso_dep;
nfcb_poll->attrib_res_len = *data++;
- pr_debug("attrib_res_len %d\n",
- nfcb_poll->attrib_res_len);
+ pr_debug("attrib_res_len %d\n", nfcb_poll->attrib_res_len);
if (nfcb_poll->attrib_res_len > 0) {
memcpy(nfcb_poll->attrib_res,
- data,
- nfcb_poll->attrib_res_len);
+ data, nfcb_poll->attrib_res_len);
}
break;
@@ -362,7 +359,7 @@ static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev,
}
static void nci_target_auto_activated(struct nci_dev *ndev,
- struct nci_rf_intf_activated_ntf *ntf)
+ struct nci_rf_intf_activated_ntf *ntf)
{
struct nfc_target *target;
int rc;
@@ -370,8 +367,8 @@ static void nci_target_auto_activated(struct nci_dev *ndev,
target = &ndev->targets[ndev->n_targets];
rc = nci_add_new_protocol(ndev, target, ntf->rf_protocol,
- ntf->activation_rf_tech_and_mode,
- &ntf->rf_tech_specific_params);
+ ntf->activation_rf_tech_and_mode,
+ &ntf->rf_tech_specific_params);
if (rc)
return;
@@ -384,7 +381,7 @@ static void nci_target_auto_activated(struct nci_dev *ndev,
}
static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
struct nci_rf_intf_activated_ntf ntf;
__u8 *data = skb->data;
@@ -405,7 +402,8 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
ntf.activation_rf_tech_and_mode);
pr_debug("max_data_pkt_payload_size 0x%x\n",
ntf.max_data_pkt_payload_size);
- pr_debug("initial_num_credits 0x%x\n", ntf.initial_num_credits);
+ pr_debug("initial_num_credits 0x%x\n",
+ ntf.initial_num_credits);
pr_debug("rf_tech_specific_params_len %d\n",
ntf.rf_tech_specific_params_len);
@@ -441,18 +439,15 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
pr_debug("data_exch_rf_tech_and_mode 0x%x\n",
ntf.data_exch_rf_tech_and_mode);
- pr_debug("data_exch_tx_bit_rate 0x%x\n",
- ntf.data_exch_tx_bit_rate);
- pr_debug("data_exch_rx_bit_rate 0x%x\n",
- ntf.data_exch_rx_bit_rate);
- pr_debug("activation_params_len %d\n",
- ntf.activation_params_len);
+ pr_debug("data_exch_tx_bit_rate 0x%x\n", ntf.data_exch_tx_bit_rate);
+ pr_debug("data_exch_rx_bit_rate 0x%x\n", ntf.data_exch_rx_bit_rate);
+ pr_debug("activation_params_len %d\n", ntf.activation_params_len);
if (ntf.activation_params_len > 0) {
switch (ntf.rf_interface) {
case NCI_RF_INTERFACE_ISO_DEP:
err = nci_extract_activation_params_iso_dep(ndev,
- &ntf, data);
+ &ntf, data);
break;
case NCI_RF_INTERFACE_FRAME:
@@ -489,7 +484,7 @@ exit:
}
static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
struct nci_rf_deactivate_ntf *ntf = (void *) skb->data;
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
index aa63b1e9918..3003c3390e4 100644
--- a/net/nfc/nci/rsp.c
+++ b/net/nfc/nci/rsp.c
@@ -67,19 +67,18 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces;
if (ndev->num_supported_rf_interfaces >
- NCI_MAX_SUPPORTED_RF_INTERFACES) {
+ NCI_MAX_SUPPORTED_RF_INTERFACES) {
ndev->num_supported_rf_interfaces =
NCI_MAX_SUPPORTED_RF_INTERFACES;
}
memcpy(ndev->supported_rf_interfaces,
- rsp_1->supported_rf_interfaces,
- ndev->num_supported_rf_interfaces);
+ rsp_1->supported_rf_interfaces,
+ ndev->num_supported_rf_interfaces);
rsp_2 = (void *) (skb->data + 6 + rsp_1->num_supported_rf_interfaces);
- ndev->max_logical_connections =
- rsp_2->max_logical_connections;
+ ndev->max_logical_connections = rsp_2->max_logical_connections;
ndev->max_routing_table_size =
__le16_to_cpu(rsp_2->max_routing_table_size);
ndev->max_ctrl_pkt_payload_len =
@@ -121,7 +120,7 @@ exit:
}
static void nci_rf_disc_map_rsp_packet(struct nci_dev *ndev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
__u8 status = skb->data[0];
@@ -143,7 +142,7 @@ static void nci_rf_disc_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
}
static void nci_rf_disc_select_rsp_packet(struct nci_dev *ndev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
__u8 status = skb->data[0];
@@ -155,7 +154,7 @@ static void nci_rf_disc_select_rsp_packet(struct nci_dev *ndev,
}
static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
__u8 status = skb->data[0];
@@ -163,7 +162,7 @@ static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev,
/* If target was active, complete the request only in deactivate_ntf */
if ((status != NCI_STATUS_OK) ||
- (atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) {
+ (atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) {
nci_clear_target_list(ndev);
atomic_set(&ndev->state, NCI_IDLE);
nci_req_complete(ndev, status);
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 07f0348aabf..6404052d6c0 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -48,34 +48,34 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = {
[NFC_ATTR_PROTOCOLS] = { .type = NLA_U32 },
[NFC_ATTR_COMM_MODE] = { .type = NLA_U8 },
[NFC_ATTR_RF_MODE] = { .type = NLA_U8 },
+ [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 },
};
static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target,
- struct netlink_callback *cb, int flags)
+ struct netlink_callback *cb, int flags)
{
void *hdr;
hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
- &nfc_genl_family, flags, NFC_CMD_GET_TARGET);
+ &nfc_genl_family, flags, NFC_CMD_GET_TARGET);
if (!hdr)
return -EMSGSIZE;
genl_dump_check_consistent(cb, hdr, &nfc_genl_family);
NLA_PUT_U32(msg, NFC_ATTR_TARGET_INDEX, target->idx);
- NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS,
- target->supported_protocols);
+ NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, target->supported_protocols);
NLA_PUT_U16(msg, NFC_ATTR_TARGET_SENS_RES, target->sens_res);
NLA_PUT_U8(msg, NFC_ATTR_TARGET_SEL_RES, target->sel_res);
if (target->nfcid1_len > 0)
NLA_PUT(msg, NFC_ATTR_TARGET_NFCID1, target->nfcid1_len,
- target->nfcid1);
+ target->nfcid1);
if (target->sensb_res_len > 0)
NLA_PUT(msg, NFC_ATTR_TARGET_SENSB_RES, target->sensb_res_len,
- target->sensb_res);
+ target->sensb_res);
if (target->sensf_res_len > 0)
NLA_PUT(msg, NFC_ATTR_TARGET_SENSF_RES, target->sensf_res_len,
- target->sensf_res);
+ target->sensf_res);
return genlmsg_end(msg, hdr);
@@ -91,9 +91,9 @@ static struct nfc_dev *__get_device_from_cb(struct netlink_callback *cb)
u32 idx;
rc = nlmsg_parse(cb->nlh, GENL_HDRLEN + nfc_genl_family.hdrsize,
- nfc_genl_family.attrbuf,
- nfc_genl_family.maxattr,
- nfc_genl_policy);
+ nfc_genl_family.attrbuf,
+ nfc_genl_family.maxattr,
+ nfc_genl_policy);
if (rc < 0)
return ERR_PTR(rc);
@@ -110,7 +110,7 @@ static struct nfc_dev *__get_device_from_cb(struct netlink_callback *cb)
}
static int nfc_genl_dump_targets(struct sk_buff *skb,
- struct netlink_callback *cb)
+ struct netlink_callback *cb)
{
int i = cb->args[0];
struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];
@@ -130,7 +130,7 @@ static int nfc_genl_dump_targets(struct sk_buff *skb,
while (i < dev->n_targets) {
rc = nfc_genl_send_target(skb, &dev->targets[i], cb,
- NLM_F_MULTI);
+ NLM_F_MULTI);
if (rc < 0)
break;
@@ -166,7 +166,7 @@ int nfc_genl_targets_found(struct nfc_dev *dev)
return -ENOMEM;
hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
- NFC_EVENT_TARGETS_FOUND);
+ NFC_EVENT_TARGETS_FOUND);
if (!hdr)
goto free_msg;
@@ -193,13 +193,14 @@ int nfc_genl_device_added(struct nfc_dev *dev)
return -ENOMEM;
hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
- NFC_EVENT_DEVICE_ADDED);
+ NFC_EVENT_DEVICE_ADDED);
if (!hdr)
goto free_msg;
NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev));
NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols);
+ NLA_PUT_U8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up);
genlmsg_end(msg, hdr);
@@ -224,7 +225,7 @@ int nfc_genl_device_removed(struct nfc_dev *dev)
return -ENOMEM;
hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
- NFC_EVENT_DEVICE_REMOVED);
+ NFC_EVENT_DEVICE_REMOVED);
if (!hdr)
goto free_msg;
@@ -244,14 +245,14 @@ free_msg:
}
static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev,
- u32 pid, u32 seq,
- struct netlink_callback *cb,
- int flags)
+ u32 pid, u32 seq,
+ struct netlink_callback *cb,
+ int flags)
{
void *hdr;
hdr = genlmsg_put(msg, pid, seq, &nfc_genl_family, flags,
- NFC_CMD_GET_DEVICE);
+ NFC_CMD_GET_DEVICE);
if (!hdr)
return -EMSGSIZE;
@@ -261,6 +262,7 @@ static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev,
NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev));
NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols);
+ NLA_PUT_U8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up);
return genlmsg_end(msg, hdr);
@@ -270,7 +272,7 @@ nla_put_failure:
}
static int nfc_genl_dump_devices(struct sk_buff *skb,
- struct netlink_callback *cb)
+ struct netlink_callback *cb)
{
struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];
struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];
@@ -297,8 +299,7 @@ static int nfc_genl_dump_devices(struct sk_buff *skb,
int rc;
rc = nfc_genl_send_device(skb, dev, NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq,
- cb, NLM_F_MULTI);
+ cb->nlh->nlmsg_seq, cb, NLM_F_MULTI);
if (rc < 0)
break;
@@ -323,7 +324,7 @@ static int nfc_genl_dump_devices_done(struct netlink_callback *cb)
}
int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx,
- u8 comm_mode, u8 rf_mode)
+ u8 comm_mode, u8 rf_mode)
{
struct sk_buff *msg;
void *hdr;
@@ -334,8 +335,7 @@ int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx,
if (!msg)
return -ENOMEM;
- hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
- NFC_CMD_DEP_LINK_UP);
+ hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, NFC_CMD_DEP_LINK_UP);
if (!hdr)
goto free_msg;
@@ -372,7 +372,7 @@ int nfc_genl_dep_link_down_event(struct nfc_dev *dev)
return -ENOMEM;
hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
- NFC_CMD_DEP_LINK_DOWN);
+ NFC_CMD_DEP_LINK_DOWN);
if (!hdr)
goto free_msg;
@@ -414,7 +414,7 @@ static int nfc_genl_get_device(struct sk_buff *skb, struct genl_info *info)
}
rc = nfc_genl_send_device(msg, dev, info->snd_pid, info->snd_seq,
- NULL, 0);
+ NULL, 0);
if (rc < 0)
goto out_free;
@@ -481,7 +481,7 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info)
pr_debug("Poll start\n");
if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
- !info->attrs[NFC_ATTR_PROTOCOLS])
+ !info->attrs[NFC_ATTR_PROTOCOLS])
return -EINVAL;
idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
@@ -539,13 +539,12 @@ static int nfc_genl_dep_link_up(struct sk_buff *skb, struct genl_info *info)
struct nfc_dev *dev;
int rc, tgt_idx;
u32 idx;
- u8 comm, rf;
+ u8 comm;
pr_debug("DEP link up\n");
if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
- !info->attrs[NFC_ATTR_COMM_MODE] ||
- !info->attrs[NFC_ATTR_RF_MODE])
+ !info->attrs[NFC_ATTR_COMM_MODE])
return -EINVAL;
idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
@@ -555,19 +554,15 @@ static int nfc_genl_dep_link_up(struct sk_buff *skb, struct genl_info *info)
tgt_idx = nla_get_u32(info->attrs[NFC_ATTR_TARGET_INDEX]);
comm = nla_get_u8(info->attrs[NFC_ATTR_COMM_MODE]);
- rf = nla_get_u8(info->attrs[NFC_ATTR_RF_MODE]);
if (comm != NFC_COMM_ACTIVE && comm != NFC_COMM_PASSIVE)
return -EINVAL;
- if (rf != NFC_RF_INITIATOR && comm != NFC_RF_TARGET)
- return -EINVAL;
-
dev = nfc_get_device(idx);
if (!dev)
return -ENODEV;
- rc = nfc_dep_link_up(dev, tgt_idx, comm, rf);
+ rc = nfc_dep_link_up(dev, tgt_idx, comm);
nfc_put_device(dev);
@@ -642,7 +637,7 @@ static struct genl_ops nfc_genl_ops[] = {
};
static int nfc_genl_rcv_nl_event(struct notifier_block *this,
- unsigned long event, void *ptr)
+ unsigned long event, void *ptr)
{
struct netlink_notify *n = ptr;
struct class_dev_iter iter;
@@ -695,7 +690,7 @@ int __init nfc_genl_init(void)
int rc;
rc = genl_register_family_with_ops(&nfc_genl_family, nfc_genl_ops,
- ARRAY_SIZE(nfc_genl_ops));
+ ARRAY_SIZE(nfc_genl_ops));
if (rc)
return rc;
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
index 6d28d75995b..ec8794c1099 100644
--- a/net/nfc/nfc.h
+++ b/net/nfc/nfc.h
@@ -32,7 +32,7 @@ struct nfc_protocol {
struct proto *proto;
struct module *owner;
int (*create)(struct net *net, struct socket *sock,
- const struct nfc_protocol *nfc_proto);
+ const struct nfc_protocol *nfc_proto);
};
struct nfc_rawsock {
@@ -54,7 +54,7 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
int nfc_llcp_register_device(struct nfc_dev *dev);
void nfc_llcp_unregister_device(struct nfc_dev *dev);
int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len);
-u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, u8 *general_bytes_len);
+u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len);
int __init nfc_llcp_init(void);
void nfc_llcp_exit(void);
@@ -65,7 +65,7 @@ static inline void nfc_llcp_mac_is_down(struct nfc_dev *dev)
}
static inline void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
- u8 comm_mode, u8 rf_mode)
+ u8 comm_mode, u8 rf_mode)
{
}
@@ -78,7 +78,8 @@ static inline void nfc_llcp_unregister_device(struct nfc_dev *dev)
{
}
-static inline int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
+static inline int nfc_llcp_set_remote_gb(struct nfc_dev *dev,
+ u8 *gb, u8 gb_len)
{
return 0;
}
@@ -160,8 +161,7 @@ int nfc_start_poll(struct nfc_dev *dev, u32 protocols);
int nfc_stop_poll(struct nfc_dev *dev);
-int nfc_dep_link_up(struct nfc_dev *dev, int target_idx,
- u8 comm_mode, u8 rf_mode);
+int nfc_dep_link_up(struct nfc_dev *dev, int target_idx, u8 comm_mode);
int nfc_dep_link_down(struct nfc_dev *dev);
@@ -169,9 +169,7 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol);
int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx);
-int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx,
- struct sk_buff *skb,
- data_exchange_cb_t cb,
- void *cb_context);
+int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
+ data_exchange_cb_t cb, void *cb_context);
#endif /* __LOCAL_NFC_H */
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c
index 5325439b0c6..5a839ceb2e8 100644
--- a/net/nfc/rawsock.c
+++ b/net/nfc/rawsock.c
@@ -63,7 +63,7 @@ static int rawsock_release(struct socket *sock)
}
static int rawsock_connect(struct socket *sock, struct sockaddr *_addr,
- int len, int flags)
+ int len, int flags)
{
struct sock *sk = sock->sk;
struct sockaddr_nfc *addr = (struct sockaddr_nfc *)_addr;
@@ -73,7 +73,7 @@ static int rawsock_connect(struct socket *sock, struct sockaddr *_addr,
pr_debug("sock=%p sk=%p flags=%d\n", sock, sk, flags);
if (!addr || len < sizeof(struct sockaddr_nfc) ||
- addr->sa_family != AF_NFC)
+ addr->sa_family != AF_NFC)
return -EINVAL;
pr_debug("addr dev_idx=%u target_idx=%u protocol=%u\n",
@@ -120,7 +120,7 @@ static int rawsock_add_header(struct sk_buff *skb)
}
static void rawsock_data_exchange_complete(void *context, struct sk_buff *skb,
- int err)
+ int err)
{
struct sock *sk = (struct sock *) context;
@@ -173,7 +173,7 @@ static void rawsock_tx_work(struct work_struct *work)
sock_hold(sk);
rc = nfc_data_exchange(dev, target_idx, skb,
- rawsock_data_exchange_complete, sk);
+ rawsock_data_exchange_complete, sk);
if (rc) {
rawsock_report_error(sk, rc);
sock_put(sk);
@@ -181,7 +181,7 @@ static void rawsock_tx_work(struct work_struct *work)
}
static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock,
- struct msghdr *msg, size_t len)
+ struct msghdr *msg, size_t len)
{
struct sock *sk = sock->sk;
struct nfc_dev *dev = nfc_rawsock(sk)->dev;
@@ -218,7 +218,7 @@ static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock,
}
static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock,
- struct msghdr *msg, size_t len, int flags)
+ struct msghdr *msg, size_t len, int flags)
{
int noblock = flags & MSG_DONTWAIT;
struct sock *sk = sock->sk;
@@ -274,7 +274,7 @@ static void rawsock_destruct(struct sock *sk)
if (sk->sk_state == TCP_ESTABLISHED) {
nfc_deactivate_target(nfc_rawsock(sk)->dev,
- nfc_rawsock(sk)->target_idx);
+ nfc_rawsock(sk)->target_idx);
nfc_put_device(nfc_rawsock(sk)->dev);
}
@@ -287,7 +287,7 @@ static void rawsock_destruct(struct sock *sk)
}
static int rawsock_create(struct net *net, struct socket *sock,
- const struct nfc_protocol *nfc_proto)
+ const struct nfc_protocol *nfc_proto)
{
struct sock *sk;
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 9d3e3b6bfcf..ba21ab22187 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -23,6 +23,8 @@
#define MESH_PERR_MIN_INT 100
#define MESH_DIAM_TRAVERSAL_TIME 50
+#define MESH_RSSI_THRESHOLD 0
+
/*
* A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds
* before timing out. This way it will remain ACTIVE and no data frames
@@ -56,6 +58,7 @@ const struct mesh_config default_mesh_config = {
.dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL,
.dot11MeshGateAnnouncementProtocol = false,
.dot11MeshForwarding = true,
+ .rssi_threshold = MESH_RSSI_THRESHOLD,
};
const struct mesh_setup default_mesh_setup = {
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index fb1e7217911..f5a7ac3a093 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -814,8 +814,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
cookie);
}
-bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf,
- size_t len, gfp_t gfp)
+bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_mbm,
+ const u8 *buf, size_t len, gfp_t gfp)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
@@ -854,7 +854,8 @@ bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf,
/* found match! */
/* Indicate the received Action frame to user space */
- if (nl80211_send_mgmt(rdev, dev, reg->nlpid, freq,
+ if (nl80211_send_mgmt(rdev, dev, reg->nlpid,
+ freq, sig_mbm,
buf, len, gfp))
continue;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 1998c368277..39dbdf2adb1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -204,6 +204,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
.len = NL80211_HT_CAPABILITY_LEN
},
[NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
+ [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
};
/* policy for the key attributes */
@@ -2214,6 +2215,13 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
if (err)
return err;
+ if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
+ if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER))
+ return -EOPNOTSUPP;
+ params.inactivity_timeout = nla_get_u16(
+ info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
+ }
+
err = rdev->ops->start_ap(&rdev->wiphy, dev, &params);
if (!err)
wdev->beacon_interval = params.beacon_interval;
@@ -3290,6 +3298,8 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
cur_params.dot11MeshGateAnnouncementProtocol);
NLA_PUT_U8(msg, NL80211_MESHCONF_FORWARDING,
cur_params.dot11MeshForwarding);
+ NLA_PUT_U32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
+ cur_params.rssi_threshold);
nla_nest_end(msg, pinfoattr);
genlmsg_end(msg, hdr);
return genlmsg_reply(msg, info);
@@ -3322,6 +3332,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
[NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 },
[NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 },
[NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 },
+ [NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32},
};
static const struct nla_policy
@@ -3413,6 +3424,8 @@ do {\
nla_get_u8);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding,
mask, NL80211_MESHCONF_FORWARDING, nla_get_u8);
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold,
+ mask, NL80211_MESHCONF_RSSI_THRESHOLD, nla_get_u32);
if (mask_out)
*mask_out = mask;
@@ -7673,7 +7686,8 @@ bool nl80211_unexpected_4addr_frame(struct net_device *dev,
int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
struct net_device *netdev, u32 nlpid,
- int freq, const u8 *buf, size_t len, gfp_t gfp)
+ int freq, int sig_dbm,
+ const u8 *buf, size_t len, gfp_t gfp)
{
struct sk_buff *msg;
void *hdr;
@@ -7691,6 +7705,8 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
+ if (sig_dbm)
+ NLA_PUT_U32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm);
NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf);
genlmsg_end(msg, hdr);
@@ -7952,7 +7968,7 @@ EXPORT_SYMBOL(cfg80211_probe_status);
void cfg80211_report_obss_beacon(struct wiphy *wiphy,
const u8 *frame, size_t len,
- int freq, gfp_t gfp)
+ int freq, int sig_dbm, gfp_t gfp)
{
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
struct sk_buff *msg;
@@ -7975,6 +7991,8 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy,
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
if (freq)
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
+ if (sig_dbm)
+ NLA_PUT_U32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm);
NLA_PUT(msg, NL80211_ATTR_FRAME, len, frame);
genlmsg_end(msg, hdr);
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 12bf4d185ab..4ffe50df9f3 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -92,7 +92,8 @@ void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev,
gfp_t gfp);
int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, u32 nlpid, int freq,
+ struct net_device *netdev, u32 nlpid,
+ int freq, int sig_dbm,
const u8 *buf, size_t len, gfp_t gfp);
void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev,
struct net_device *netdev, u64 cookie,
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 9aa9db6c814..1b7a08df933 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -904,6 +904,7 @@ u16 cfg80211_calculate_bitrate(struct rate_info *rate)
/* do NOT round down here */
return (bitrate + 50000) / 100000;
}
+EXPORT_SYMBOL(cfg80211_calculate_bitrate);
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
u32 beacon_int)