aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-02-04 11:58:14 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-04 11:58:14 -0500
commit10be7eb36b93364b98688831ee7d26f58402bb96 (patch)
treeeb13ae80fcaa8baacd804a721c5a4962a501a2a4
parent90c30335a70e96b8b8493b7deb15e6b30e6d9fce (diff)
parent5ffaf8a361b4c9025963959a744f21d8173c7669 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
-rw-r--r--arch/powerpc/configs/ppc64_defconfig1
-rw-r--r--arch/powerpc/configs/ps3_defconfig1
-rw-r--r--drivers/net/Kconfig14
-rw-r--r--drivers/net/ps3_gelic_wireless.c149
-rw-r--r--drivers/net/wireless/airo.c34
-rw-r--r--drivers/net/wireless/ath/ath.h1
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h2
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c22
-rw-r--r--drivers/net/wireless/ath/ath5k/led.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/qcu.c5
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h8
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c43
-rw-r--r--drivers/net/wireless/ath/ath9k/gpio.c30
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c18
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c19
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c39
-rw-r--r--drivers/net/wireless/ath/debug.h8
-rw-r--r--drivers/net/wireless/b43/main.c28
-rw-r--r--drivers/net/wireless/b43/phy_common.c45
-rw-r--r--drivers/net/wireless/b43/phy_common.h10
-rw-r--r--drivers/net/wireless/b43/phy_lp.c52
-rw-r--r--drivers/net/wireless/b43/phy_n.c1264
-rw-r--r--drivers/net/wireless/b43/phy_n.h7
-rw-r--r--drivers/net/wireless/b43/tables_nphy.c167
-rw-r--r--drivers/net/wireless/b43/tables_nphy.h27
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig14
-rw-r--r--drivers/net/wireless/iwlwifi/Makefile3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c78
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-fh.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-hw.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-led.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-led.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-hw.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000-hw.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c79
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000-hw.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c28
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-led.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-led.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c86
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h54
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c149
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h25
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-csr.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h62
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c1267
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h46
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fh.h23
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-helpers.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-prph.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c104
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c192
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-spectrum.c198
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-spectrum.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c150
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c57
-rw-r--r--drivers/net/wireless/libertas/assoc.c78
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c8
-rw-r--r--drivers/net/wireless/mwl8k.c14
-rw-r--r--drivers/net/wireless/p54/p54pci.c74
-rw-r--r--drivers/net/wireless/p54/p54pci.h6
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_dev.c9
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_dev.c11
-rw-r--r--drivers/net/wireless/wl12xx/wl1251.h3
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_main.c25
-rw-r--r--include/linux/ieee80211.h2
-rw-r--r--include/net/cfg80211.h38
-rw-r--r--include/net/mac80211.h22
-rw-r--r--include/net/regulatory.h1
-rw-r--r--net/mac80211/debugfs_sta.c26
-rw-r--r--net/mac80211/driver-ops.h14
-rw-r--r--net/mac80211/driver-trace.h15
-rw-r--r--net/mac80211/ibss.c22
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/iface.c6
-rw-r--r--net/mac80211/mlme.c27
-rw-r--r--net/mac80211/rate.h4
-rw-r--r--net/mac80211/rc80211_pid_algo.c8
-rw-r--r--net/mac80211/rx.c45
-rw-r--r--net/mac80211/scan.c4
-rw-r--r--net/mac80211/status.c35
-rw-r--r--net/mac80211/tkip.c23
-rw-r--r--net/mac80211/tx.c50
-rw-r--r--net/mac80211/wep.c17
-rw-r--r--net/mac80211/work.c19
-rw-r--r--net/mac80211/wpa.c57
-rw-r--r--net/wireless/core.c38
-rw-r--r--net/wireless/core.h3
-rw-r--r--net/wireless/lib80211_crypt_ccmp.c2
-rw-r--r--net/wireless/lib80211_crypt_tkip.c23
-rw-r--r--net/wireless/nl80211.c4
-rw-r--r--net/wireless/reg.c161
-rw-r--r--net/wireless/reg.h18
-rw-r--r--net/wireless/scan.c38
-rw-r--r--net/wireless/sme.c40
-rw-r--r--net/wireless/sysfs.c20
-rw-r--r--net/wireless/util.c5
-rw-r--r--net/wireless/wext-compat.c2
125 files changed, 3770 insertions, 2018 deletions
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 7b3804a6e363..80e80caed2da 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -1000,7 +1000,6 @@ CONFIG_TIGON3=y
1000CONFIG_SPIDER_NET=m 1000CONFIG_SPIDER_NET=m
1001CONFIG_GELIC_NET=m 1001CONFIG_GELIC_NET=m
1002CONFIG_GELIC_WIRELESS=y 1002CONFIG_GELIC_WIRELESS=y
1003# CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE is not set
1004# CONFIG_QLA3XXX is not set 1003# CONFIG_QLA3XXX is not set
1005# CONFIG_ATL1 is not set 1004# CONFIG_ATL1 is not set
1006# CONFIG_ATL1E is not set 1005# CONFIG_ATL1E is not set
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index 7de127e4ceef..32f7058bb173 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -593,7 +593,6 @@ CONFIG_MII=m
593CONFIG_NETDEV_1000=y 593CONFIG_NETDEV_1000=y
594CONFIG_GELIC_NET=y 594CONFIG_GELIC_NET=y
595CONFIG_GELIC_WIRELESS=y 595CONFIG_GELIC_WIRELESS=y
596# CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE is not set
597# CONFIG_NETDEV_10000 is not set 596# CONFIG_NETDEV_10000 is not set
598 597
599# 598#
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 411e20703110..ef662e15c3d3 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2368,20 +2368,6 @@ config GELIC_WIRELESS
2368 the driver automatically distinguishes the models, you can 2368 the driver automatically distinguishes the models, you can
2369 safely enable this option even if you have a wireless-less model. 2369 safely enable this option even if you have a wireless-less model.
2370 2370
2371config GELIC_WIRELESS_OLD_PSK_INTERFACE
2372 bool "PS3 Wireless private PSK interface (OBSOLETE)"
2373 depends on GELIC_WIRELESS
2374 select WEXT_PRIV
2375 help
2376 This option retains the obsolete private interface to pass
2377 the PSK from user space programs to the driver. The PSK
2378 stands for 'Pre Shared Key' and is used for WPA[2]-PSK
2379 (WPA-Personal) environment.
2380 If WPA[2]-PSK is used and you need to use old programs that
2381 support only this old interface, say Y. Otherwise N.
2382
2383 If unsure, say N.
2384
2385config FSL_PQ_MDIO 2371config FSL_PQ_MDIO
2386 tristate "Freescale PQ MDIO" 2372 tristate "Freescale PQ MDIO"
2387 depends on FSL_SOC 2373 depends on FSL_SOC
diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c
index 227b141c4fbd..2663b2fdc0bb 100644
--- a/drivers/net/ps3_gelic_wireless.c
+++ b/drivers/net/ps3_gelic_wireless.c
@@ -1389,113 +1389,6 @@ static int gelic_wl_get_mode(struct net_device *netdev,
1389 return 0; 1389 return 0;
1390} 1390}
1391 1391
1392#ifdef CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE
1393/* SIOCIWFIRSTPRIV */
1394static int hex2bin(u8 *str, u8 *bin, unsigned int len)
1395{
1396 unsigned int i;
1397 static unsigned char *hex = "0123456789ABCDEF";
1398 unsigned char *p, *q;
1399 u8 tmp;
1400
1401 if (len != WPA_PSK_LEN * 2)
1402 return -EINVAL;
1403
1404 for (i = 0; i < WPA_PSK_LEN * 2; i += 2) {
1405 p = strchr(hex, toupper(str[i]));
1406 q = strchr(hex, toupper(str[i + 1]));
1407 if (!p || !q) {
1408 pr_info("%s: unconvertible PSK digit=%d\n",
1409 __func__, i);
1410 return -EINVAL;
1411 }
1412 tmp = ((p - hex) << 4) + (q - hex);
1413 *bin++ = tmp;
1414 }
1415 return 0;
1416};
1417
1418static int gelic_wl_priv_set_psk(struct net_device *net_dev,
1419 struct iw_request_info *info,
1420 union iwreq_data *data, char *extra)
1421{
1422 struct gelic_wl_info *wl = port_wl(netdev_priv(net_dev));
1423 unsigned int len;
1424 unsigned long irqflag;
1425 int ret = 0;
1426
1427 pr_debug("%s:<- len=%d\n", __func__, data->data.length);
1428 len = data->data.length - 1;
1429 if (len <= 2)
1430 return -EINVAL;
1431
1432 spin_lock_irqsave(&wl->lock, irqflag);
1433 if (extra[0] == '"' && extra[len - 1] == '"') {
1434 pr_debug("%s: passphrase mode\n", __func__);
1435 /* pass phrase */
1436 if (GELIC_WL_EURUS_PSK_MAX_LEN < (len - 2)) {
1437 pr_info("%s: passphrase too long\n", __func__);
1438 ret = -E2BIG;
1439 goto out;
1440 }
1441 memset(wl->psk, 0, sizeof(wl->psk));
1442 wl->psk_len = len - 2;
1443 memcpy(wl->psk, &(extra[1]), wl->psk_len);
1444 wl->psk_type = GELIC_EURUS_WPA_PSK_PASSPHRASE;
1445 } else {
1446 ret = hex2bin(extra, wl->psk, len);
1447 if (ret)
1448 goto out;
1449 wl->psk_len = WPA_PSK_LEN;
1450 wl->psk_type = GELIC_EURUS_WPA_PSK_BIN;
1451 }
1452 set_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat);
1453out:
1454 spin_unlock_irqrestore(&wl->lock, irqflag);
1455 pr_debug("%s:->\n", __func__);
1456 return ret;
1457}
1458
1459static int gelic_wl_priv_get_psk(struct net_device *net_dev,
1460 struct iw_request_info *info,
1461 union iwreq_data *data, char *extra)
1462{
1463 struct gelic_wl_info *wl = port_wl(netdev_priv(net_dev));
1464 char *p;
1465 unsigned long irqflag;
1466 unsigned int i;
1467
1468 pr_debug("%s:<-\n", __func__);
1469 if (!capable(CAP_NET_ADMIN))
1470 return -EPERM;
1471
1472 spin_lock_irqsave(&wl->lock, irqflag);
1473 p = extra;
1474 if (test_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat)) {
1475 if (wl->psk_type == GELIC_EURUS_WPA_PSK_BIN) {
1476 for (i = 0; i < wl->psk_len; i++) {
1477 sprintf(p, "%02xu", wl->psk[i]);
1478 p += 2;
1479 }
1480 *p = '\0';
1481 data->data.length = wl->psk_len * 2;
1482 } else {
1483 *p++ = '"';
1484 memcpy(p, wl->psk, wl->psk_len);
1485 p += wl->psk_len;
1486 *p++ = '"';
1487 *p = '\0';
1488 data->data.length = wl->psk_len + 2;
1489 }
1490 } else
1491 /* no psk set */
1492 data->data.length = 0;
1493 spin_unlock_irqrestore(&wl->lock, irqflag);
1494 pr_debug("%s:-> %d\n", __func__, data->data.length);
1495 return 0;
1496}
1497#endif
1498
1499/* SIOCGIWNICKN */ 1392/* SIOCGIWNICKN */
1500static int gelic_wl_get_nick(struct net_device *net_dev, 1393static int gelic_wl_get_nick(struct net_device *net_dev,
1501 struct iw_request_info *info, 1394 struct iw_request_info *info,
@@ -1571,8 +1464,10 @@ static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan,
1571 init_completion(&wl->scan_done); 1464 init_completion(&wl->scan_done);
1572 /* 1465 /*
1573 * If we have already a bss list, don't try to get new 1466 * If we have already a bss list, don't try to get new
1467 * unless we are doing an ESSID scan
1574 */ 1468 */
1575 if (!always_scan && wl->scan_stat == GELIC_WL_SCAN_STAT_GOT_LIST) { 1469 if ((!essid_len && !always_scan)
1470 && wl->scan_stat == GELIC_WL_SCAN_STAT_GOT_LIST) {
1576 pr_debug("%s: already has the list\n", __func__); 1471 pr_debug("%s: already has the list\n", __func__);
1577 complete(&wl->scan_done); 1472 complete(&wl->scan_done);
1578 goto out; 1473 goto out;
@@ -1673,7 +1568,7 @@ static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl)
1673 } 1568 }
1674 } 1569 }
1675 1570
1676 /* put them in the newtork_list */ 1571 /* put them in the network_list */
1677 for (i = 0, scan_info_size = 0, scan_info = buf; 1572 for (i = 0, scan_info_size = 0, scan_info = buf;
1678 scan_info_size < data_len; 1573 scan_info_size < data_len;
1679 i++, scan_info_size += be16_to_cpu(scan_info->size), 1574 i++, scan_info_size += be16_to_cpu(scan_info->size),
@@ -2009,7 +1904,7 @@ static int gelic_wl_do_wpa_setup(struct gelic_wl_info *wl)
2009 /* PSK type */ 1904 /* PSK type */
2010 wpa->psk_type = cpu_to_be16(wl->psk_type); 1905 wpa->psk_type = cpu_to_be16(wl->psk_type);
2011#ifdef DEBUG 1906#ifdef DEBUG
2012 pr_debug("%s: sec=%s psktype=%s\nn", __func__, 1907 pr_debug("%s: sec=%s psktype=%s\n", __func__,
2013 wpasecstr(wpa->security), 1908 wpasecstr(wpa->security),
2014 (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ? 1909 (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ?
2015 "BIN" : "passphrase"); 1910 "BIN" : "passphrase");
@@ -2019,9 +1914,9 @@ static int gelic_wl_do_wpa_setup(struct gelic_wl_info *wl)
2019 * the debug log because this dumps your precious 1914 * the debug log because this dumps your precious
2020 * passphrase/key. 1915 * passphrase/key.
2021 */ 1916 */
2022 pr_debug("%s: psk=%s\n", 1917 pr_debug("%s: psk=%s\n", __func__,
2023 (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ? 1918 (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ?
2024 (char *)"N/A" : (char *)wpa->psk); 1919 "N/A" : wpa->psk);
2025#endif 1920#endif
2026#endif 1921#endif
2027 /* issue wpa setup */ 1922 /* issue wpa setup */
@@ -2406,40 +2301,10 @@ static const iw_handler gelic_wl_wext_handler[] =
2406 IW_IOCTL(SIOCGIWNICKN) = gelic_wl_get_nick, 2301 IW_IOCTL(SIOCGIWNICKN) = gelic_wl_get_nick,
2407}; 2302};
2408 2303
2409#ifdef CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE
2410static struct iw_priv_args gelic_wl_private_args[] =
2411{
2412 {
2413 .cmd = GELIC_WL_PRIV_SET_PSK,
2414 .set_args = IW_PRIV_TYPE_CHAR |
2415 (GELIC_WL_EURUS_PSK_MAX_LEN + 2),
2416 .name = "set_psk"
2417 },
2418 {
2419 .cmd = GELIC_WL_PRIV_GET_PSK,
2420 .get_args = IW_PRIV_TYPE_CHAR |
2421 (GELIC_WL_EURUS_PSK_MAX_LEN + 2),
2422 .name = "get_psk"
2423 }
2424};
2425
2426static const iw_handler gelic_wl_private_handler[] =
2427{
2428 gelic_wl_priv_set_psk,
2429 gelic_wl_priv_get_psk,
2430};
2431#endif
2432
2433static const struct iw_handler_def gelic_wl_wext_handler_def = { 2304static const struct iw_handler_def gelic_wl_wext_handler_def = {
2434 .num_standard = ARRAY_SIZE(gelic_wl_wext_handler), 2305 .num_standard = ARRAY_SIZE(gelic_wl_wext_handler),
2435 .standard = gelic_wl_wext_handler, 2306 .standard = gelic_wl_wext_handler,
2436 .get_wireless_stats = gelic_wl_get_wireless_stats, 2307 .get_wireless_stats = gelic_wl_get_wireless_stats,
2437#ifdef CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE
2438 .num_private = ARRAY_SIZE(gelic_wl_private_handler),
2439 .num_private_args = ARRAY_SIZE(gelic_wl_private_args),
2440 .private = gelic_wl_private_handler,
2441 .private_args = gelic_wl_private_args,
2442#endif
2443}; 2308};
2444 2309
2445static struct net_device * __devinit gelic_wl_alloc(struct gelic_card *card) 2310static struct net_device * __devinit gelic_wl_alloc(struct gelic_card *card)
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 37e4ab737f2a..ef6b78da370f 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -5254,11 +5254,7 @@ static int set_wep_key(struct airo_info *ai, u16 index, const char *key,
5254 WepKeyRid wkr; 5254 WepKeyRid wkr;
5255 int rc; 5255 int rc;
5256 5256
5257 if (keylen == 0) { 5257 WARN_ON(keylen == 0);
5258 airo_print_err(ai->dev->name, "%s: key length to set was zero",
5259 __func__);
5260 return -1;
5261 }
5262 5258
5263 memset(&wkr, 0, sizeof(wkr)); 5259 memset(&wkr, 0, sizeof(wkr));
5264 wkr.len = cpu_to_le16(sizeof(wkr)); 5260 wkr.len = cpu_to_le16(sizeof(wkr));
@@ -6405,11 +6401,7 @@ static int airo_set_encode(struct net_device *dev,
6405 if (dwrq->length > MIN_KEY_SIZE) 6401 if (dwrq->length > MIN_KEY_SIZE)
6406 key.len = MAX_KEY_SIZE; 6402 key.len = MAX_KEY_SIZE;
6407 else 6403 else
6408 if (dwrq->length > 0) 6404 key.len = MIN_KEY_SIZE;
6409 key.len = MIN_KEY_SIZE;
6410 else
6411 /* Disable the key */
6412 key.len = 0;
6413 /* Check if the key is not marked as invalid */ 6405 /* Check if the key is not marked as invalid */
6414 if(!(dwrq->flags & IW_ENCODE_NOKEY)) { 6406 if(!(dwrq->flags & IW_ENCODE_NOKEY)) {
6415 /* Cleanup */ 6407 /* Cleanup */
@@ -6590,12 +6582,22 @@ static int airo_set_encodeext(struct net_device *dev,
6590 default: 6582 default:
6591 return -EINVAL; 6583 return -EINVAL;
6592 } 6584 }
6593 /* Send the key to the card */ 6585 if (key.len == 0) {
6594 rc = set_wep_key(local, idx, key.key, key.len, perm, 1); 6586 rc = set_wep_tx_idx(local, idx, perm, 1);
6595 if (rc < 0) { 6587 if (rc < 0) {
6596 airo_print_err(local->dev->name, "failed to set WEP key" 6588 airo_print_err(local->dev->name,
6597 " at index %d: %d.", idx, rc); 6589 "failed to set WEP transmit index to %d: %d.",
6598 return rc; 6590 idx, rc);
6591 return rc;
6592 }
6593 } else {
6594 rc = set_wep_key(local, idx, key.key, key.len, perm, 1);
6595 if (rc < 0) {
6596 airo_print_err(local->dev->name,
6597 "failed to set WEP key at index %d: %d.",
6598 idx, rc);
6599 return rc;
6600 }
6599 } 6601 }
6600 } 6602 }
6601 6603
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index 9e05648356fe..71fc960814f0 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -74,7 +74,6 @@ struct ath_common;
74 74
75struct ath_bus_ops { 75struct ath_bus_ops {
76 void (*read_cachesize)(struct ath_common *common, int *csz); 76 void (*read_cachesize)(struct ath_common *common, int *csz);
77 void (*cleanup)(struct ath_common *common);
78 bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); 77 bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
79 void (*bt_coex_prep)(struct ath_common *common); 78 void (*bt_coex_prep)(struct ath_common *common);
80}; 79};
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 66bcb506a112..ad4d446f0264 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -535,7 +535,7 @@ struct ath5k_txq_info {
535 u32 tqi_cbr_period; /* Constant bit rate period */ 535 u32 tqi_cbr_period; /* Constant bit rate period */
536 u32 tqi_cbr_overflow_limit; 536 u32 tqi_cbr_overflow_limit;
537 u32 tqi_burst_time; 537 u32 tqi_burst_time;
538 u32 tqi_ready_time; /* Not used */ 538 u32 tqi_ready_time; /* Time queue waits after an event */
539}; 539};
540 540
541/* 541/*
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 5577bcc80eac..edb6c90e376f 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -1516,7 +1516,8 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
1516 1516
1517 ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi); 1517 ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi);
1518 if (ret) 1518 if (ret)
1519 return ret; 1519 goto err;
1520
1520 if (sc->opmode == NL80211_IFTYPE_AP || 1521 if (sc->opmode == NL80211_IFTYPE_AP ||
1521 sc->opmode == NL80211_IFTYPE_MESH_POINT) { 1522 sc->opmode == NL80211_IFTYPE_MESH_POINT) {
1522 /* 1523 /*
@@ -1543,10 +1544,25 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
1543 if (ret) { 1544 if (ret) {
1544 ATH5K_ERR(sc, "%s: unable to update parameters for beacon " 1545 ATH5K_ERR(sc, "%s: unable to update parameters for beacon "
1545 "hardware queue!\n", __func__); 1546 "hardware queue!\n", __func__);
1546 return ret; 1547 goto err;
1547 } 1548 }
1549 ret = ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */
1550 if (ret)
1551 goto err;
1548 1552
1549 return ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */; 1553 /* reconfigure cabq with ready time to 80% of beacon_interval */
1554 ret = ath5k_hw_get_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi);
1555 if (ret)
1556 goto err;
1557
1558 qi.tqi_ready_time = (sc->bintval * 80) / 100;
1559 ret = ath5k_hw_set_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi);
1560 if (ret)
1561 goto err;
1562
1563 ret = ath5k_hw_reset_tx_queue(ah, AR5K_TX_QUEUE_ID_CAB);
1564err:
1565 return ret;
1550} 1566}
1551 1567
1552static void 1568static void
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index 60f547503d75..67aa52e9bf94 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -77,6 +77,8 @@ static const struct pci_device_id ath5k_led_devices[] = {
77 { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) }, 77 { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) },
78 /* HP Compaq C700 (nitrousnrg@gmail.com) */ 78 /* HP Compaq C700 (nitrousnrg@gmail.com) */
79 { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) }, 79 { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) },
80 /* LiteOn AR5BXB63 (magooz@salug.it) */
81 { ATH_SDEVICE(PCI_VENDOR_ID_ATHEROS, 0x3067), ATH_LED(3, 0) },
80 /* IBM-specific AR5212 (all others) */ 82 /* IBM-specific AR5212 (all others) */
81 { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, 83 { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) },
82 /* Dell Vostro A860 (shahar@shahar-or.co.il) */ 84 /* Dell Vostro A860 (shahar@shahar-or.co.il) */
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index abe36c0d139c..9122a8556f45 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -408,12 +408,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
408 break; 408 break;
409 409
410 case AR5K_TX_QUEUE_CAB: 410 case AR5K_TX_QUEUE_CAB:
411 /* XXX: use BCN_SENT_GT, if we can figure out how */
411 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), 412 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
412 AR5K_QCU_MISC_FRSHED_BCN_SENT_GT | 413 AR5K_QCU_MISC_FRSHED_DBA_GT |
413 AR5K_QCU_MISC_CBREXP_DIS | 414 AR5K_QCU_MISC_CBREXP_DIS |
414 AR5K_QCU_MISC_CBREXP_BCN_DIS); 415 AR5K_QCU_MISC_CBREXP_BCN_DIS);
415 416
416 ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - 417 ath5k_hw_reg_write(ah, ((tq->tqi_ready_time -
417 (AR5K_TUNE_SW_BEACON_RESP - 418 (AR5K_TUNE_SW_BEACON_RESP -
418 AR5K_TUNE_DMA_BEACON_RESP) - 419 AR5K_TUNE_DMA_BEACON_RESP) -
419 AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | 420 AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 6690923fd78c..a35a7db0fc4c 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -1374,8 +1374,9 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
1374 * Set clocks to 32KHz operation and use an 1374 * Set clocks to 32KHz operation and use an
1375 * external 32KHz crystal when sleeping if one 1375 * external 32KHz crystal when sleeping if one
1376 * exists */ 1376 * exists */
1377 if (ah->ah_version == AR5K_AR5212) 1377 if (ah->ah_version == AR5K_AR5212 &&
1378 ath5k_hw_set_sleep_clock(ah, true); 1378 ah->ah_op_mode != NL80211_IFTYPE_AP)
1379 ath5k_hw_set_sleep_clock(ah, true);
1379 1380
1380 /* 1381 /*
1381 * Disable beacons and reset the register 1382 * Disable beacons and reset the register
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 9e62a569e816..ca4994f13151 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -27,12 +27,6 @@ static void ath_ahb_read_cachesize(struct ath_common *common, int *csz)
27 *csz = L1_CACHE_BYTES >> 2; 27 *csz = L1_CACHE_BYTES >> 2;
28} 28}
29 29
30static void ath_ahb_cleanup(struct ath_common *common)
31{
32 struct ath_softc *sc = (struct ath_softc *)common->priv;
33 iounmap(sc->mem);
34}
35
36static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) 30static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
37{ 31{
38 struct ath_softc *sc = (struct ath_softc *)common->priv; 32 struct ath_softc *sc = (struct ath_softc *)common->priv;
@@ -54,8 +48,6 @@ static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
54 48
55static struct ath_bus_ops ath_ahb_bus_ops = { 49static struct ath_bus_ops ath_ahb_bus_ops = {
56 .read_cachesize = ath_ahb_read_cachesize, 50 .read_cachesize = ath_ahb_read_cachesize,
57 .cleanup = ath_ahb_cleanup,
58
59 .eeprom_read = ath_ahb_eeprom_read, 51 .eeprom_read = ath_ahb_eeprom_read,
60}; 52};
61 53
@@ -164,12 +156,12 @@ static int ath_ahb_remove(struct platform_device *pdev)
164 if (hw) { 156 if (hw) {
165 struct ath_wiphy *aphy = hw->priv; 157 struct ath_wiphy *aphy = hw->priv;
166 struct ath_softc *sc = aphy->sc; 158 struct ath_softc *sc = aphy->sc;
167 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 159 void __iomem *mem = sc->mem;
168 160
169 ath9k_deinit_device(sc); 161 ath9k_deinit_device(sc);
170 free_irq(sc->irq, sc); 162 free_irq(sc->irq, sc);
171 ieee80211_free_hw(sc->hw); 163 ieee80211_free_hw(sc->hw);
172 ath_bus_cleanup(common); 164 iounmap(mem);
173 platform_set_drvdata(pdev, NULL); 165 platform_set_drvdata(pdev, NULL);
174 } 166 }
175 167
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index bf3d4c4bfa52..0ea340fd071c 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -364,6 +364,7 @@ struct ath_btcoex {
364 int bt_stomp_type; /* Types of BT stomping */ 364 int bt_stomp_type; /* Types of BT stomping */
365 u32 btcoex_no_stomp; /* in usec */ 365 u32 btcoex_no_stomp; /* in usec */
366 u32 btcoex_period; /* in usec */ 366 u32 btcoex_period; /* in usec */
367 u32 btscan_no_stomp; /* in usec */
367 struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */ 368 struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
368}; 369};
369 370
@@ -429,6 +430,7 @@ void ath_deinit_leds(struct ath_softc *sc);
429#define SC_OP_SCANNING BIT(10) 430#define SC_OP_SCANNING BIT(10)
430#define SC_OP_TSF_RESET BIT(11) 431#define SC_OP_TSF_RESET BIT(11)
431#define SC_OP_BT_PRIORITY_DETECTED BIT(12) 432#define SC_OP_BT_PRIORITY_DETECTED BIT(12)
433#define SC_OP_BT_SCAN BIT(13)
432 434
433/* Powersave flags */ 435/* Powersave flags */
434#define PS_WAIT_FOR_BEACON BIT(0) 436#define PS_WAIT_FOR_BEACON BIT(0)
@@ -478,6 +480,7 @@ struct ath_softc {
478 u8 nbcnvifs; 480 u8 nbcnvifs;
479 u16 nvifs; 481 u16 nvifs;
480 bool ps_enabled; 482 bool ps_enabled;
483 bool ps_idle;
481 unsigned long ps_usecount; 484 unsigned long ps_usecount;
482 enum ath9k_int imask; 485 enum ath9k_int imask;
483 486
@@ -535,11 +538,6 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
535 common->bus_ops->read_cachesize(common, csz); 538 common->bus_ops->read_cachesize(common, csz);
536} 539}
537 540
538static inline void ath_bus_cleanup(struct ath_common *common)
539{
540 common->bus_ops->cleanup(common);
541}
542
543extern struct ieee80211_ops ath9k_ops; 541extern struct ieee80211_ops ath9k_ops;
544extern int modparam_nohwcrypt; 542extern int modparam_nohwcrypt;
545 543
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h
index 1ba31a73317c..1ee5a15ccbb1 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.h
+++ b/drivers/net/wireless/ath/ath9k/btcoex.h
@@ -25,10 +25,12 @@
25 25
26#define ATH_BTCOEX_DEF_BT_PERIOD 45 26#define ATH_BTCOEX_DEF_BT_PERIOD 45
27#define ATH_BTCOEX_DEF_DUTY_CYCLE 55 27#define ATH_BTCOEX_DEF_DUTY_CYCLE 55
28#define ATH_BTCOEX_BTSCAN_DUTY_CYCLE 90
28#define ATH_BTCOEX_BMISS_THRESH 50 29#define ATH_BTCOEX_BMISS_THRESH 50
29 30
30#define ATH_BT_PRIORITY_TIME_THRESHOLD 1000 /* ms */ 31#define ATH_BT_PRIORITY_TIME_THRESHOLD 1000 /* ms */
31#define ATH_BT_CNT_THRESHOLD 3 32#define ATH_BT_CNT_THRESHOLD 3
33#define ATH_BT_CNT_SCAN_THRESHOLD 15
32 34
33enum ath_btcoex_scheme { 35enum ath_btcoex_scheme {
34 ATH_BTCOEX_CFG_NONE, 36 ATH_BTCOEX_CFG_NONE,
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 9489b6b25b5f..42d2a506845a 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -75,17 +75,24 @@ static const struct file_operations fops_debug = {
75 75
76#endif 76#endif
77 77
78#define DMA_BUF_LEN 1024
79
78static ssize_t read_file_dma(struct file *file, char __user *user_buf, 80static ssize_t read_file_dma(struct file *file, char __user *user_buf,
79 size_t count, loff_t *ppos) 81 size_t count, loff_t *ppos)
80{ 82{
81 struct ath_softc *sc = file->private_data; 83 struct ath_softc *sc = file->private_data;
82 struct ath_hw *ah = sc->sc_ah; 84 struct ath_hw *ah = sc->sc_ah;
83 char buf[1024]; 85 char *buf;
86 int retval;
84 unsigned int len = 0; 87 unsigned int len = 0;
85 u32 val[ATH9K_NUM_DMA_DEBUG_REGS]; 88 u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
86 int i, qcuOffset = 0, dcuOffset = 0; 89 int i, qcuOffset = 0, dcuOffset = 0;
87 u32 *qcuBase = &val[0], *dcuBase = &val[4]; 90 u32 *qcuBase = &val[0], *dcuBase = &val[4];
88 91
92 buf = kmalloc(DMA_BUF_LEN, GFP_KERNEL);
93 if (!buf)
94 return 0;
95
89 ath9k_ps_wakeup(sc); 96 ath9k_ps_wakeup(sc);
90 97
91 REG_WRITE_D(ah, AR_MACMISC, 98 REG_WRITE_D(ah, AR_MACMISC,
@@ -93,20 +100,20 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
93 (AR_MACMISC_MISC_OBS_BUS_1 << 100 (AR_MACMISC_MISC_OBS_BUS_1 <<
94 AR_MACMISC_MISC_OBS_BUS_MSB_S))); 101 AR_MACMISC_MISC_OBS_BUS_MSB_S)));
95 102
96 len += snprintf(buf + len, sizeof(buf) - len, 103 len += snprintf(buf + len, DMA_BUF_LEN - len,
97 "Raw DMA Debug values:\n"); 104 "Raw DMA Debug values:\n");
98 105
99 for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) { 106 for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
100 if (i % 4 == 0) 107 if (i % 4 == 0)
101 len += snprintf(buf + len, sizeof(buf) - len, "\n"); 108 len += snprintf(buf + len, DMA_BUF_LEN - len, "\n");
102 109
103 val[i] = REG_READ_D(ah, AR_DMADBG_0 + (i * sizeof(u32))); 110 val[i] = REG_READ_D(ah, AR_DMADBG_0 + (i * sizeof(u32)));
104 len += snprintf(buf + len, sizeof(buf) - len, "%d: %08x ", 111 len += snprintf(buf + len, DMA_BUF_LEN - len, "%d: %08x ",
105 i, val[i]); 112 i, val[i]);
106 } 113 }
107 114
108 len += snprintf(buf + len, sizeof(buf) - len, "\n\n"); 115 len += snprintf(buf + len, DMA_BUF_LEN - len, "\n\n");
109 len += snprintf(buf + len, sizeof(buf) - len, 116 len += snprintf(buf + len, DMA_BUF_LEN - len,
110 "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"); 117 "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
111 118
112 for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) { 119 for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) {
@@ -120,7 +127,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
120 dcuBase++; 127 dcuBase++;
121 } 128 }
122 129
123 len += snprintf(buf + len, sizeof(buf) - len, 130 len += snprintf(buf + len, DMA_BUF_LEN - len,
124 "%2d %2x %1x %2x %2x\n", 131 "%2d %2x %1x %2x %2x\n",
125 i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, 132 i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
126 (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3), 133 (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
@@ -128,35 +135,37 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
128 (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); 135 (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
129 } 136 }
130 137
131 len += snprintf(buf + len, sizeof(buf) - len, "\n"); 138 len += snprintf(buf + len, DMA_BUF_LEN - len, "\n");
132 139
133 len += snprintf(buf + len, sizeof(buf) - len, 140 len += snprintf(buf + len, DMA_BUF_LEN - len,
134 "qcu_stitch state: %2x qcu_fetch state: %2x\n", 141 "qcu_stitch state: %2x qcu_fetch state: %2x\n",
135 (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22); 142 (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
136 len += snprintf(buf + len, sizeof(buf) - len, 143 len += snprintf(buf + len, DMA_BUF_LEN - len,
137 "qcu_complete state: %2x dcu_complete state: %2x\n", 144 "qcu_complete state: %2x dcu_complete state: %2x\n",
138 (val[3] & 0x1c000000) >> 26, (val[6] & 0x3)); 145 (val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
139 len += snprintf(buf + len, sizeof(buf) - len, 146 len += snprintf(buf + len, DMA_BUF_LEN - len,
140 "dcu_arb state: %2x dcu_fp state: %2x\n", 147 "dcu_arb state: %2x dcu_fp state: %2x\n",
141 (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27); 148 (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
142 len += snprintf(buf + len, sizeof(buf) - len, 149 len += snprintf(buf + len, DMA_BUF_LEN - len,
143 "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n", 150 "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n",
144 (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10); 151 (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
145 len += snprintf(buf + len, sizeof(buf) - len, 152 len += snprintf(buf + len, DMA_BUF_LEN - len,
146 "txfifo_valid_0: %1d txfifo_valid_1: %1d\n", 153 "txfifo_valid_0: %1d txfifo_valid_1: %1d\n",
147 (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12); 154 (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
148 len += snprintf(buf + len, sizeof(buf) - len, 155 len += snprintf(buf + len, DMA_BUF_LEN - len,
149 "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n", 156 "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n",
150 (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17); 157 (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
151 158
152 len += snprintf(buf + len, sizeof(buf) - len, "pcu observe: 0x%x \n", 159 len += snprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x \n",
153 REG_READ_D(ah, AR_OBS_BUS_1)); 160 REG_READ_D(ah, AR_OBS_BUS_1));
154 len += snprintf(buf + len, sizeof(buf) - len, 161 len += snprintf(buf + len, DMA_BUF_LEN - len,
155 "AR_CR: 0x%x \n", REG_READ_D(ah, AR_CR)); 162 "AR_CR: 0x%x \n", REG_READ_D(ah, AR_CR));
156 163
157 ath9k_ps_restore(sc); 164 ath9k_ps_restore(sc);
158 165
159 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 166 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
167 kfree(buf);
168 return retval;
160} 169}
161 170
162static const struct file_operations fops_dma = { 171static const struct file_operations fops_dma = {
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index e204bd25ff65..deab8beb0680 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -230,12 +230,17 @@ static void ath_detect_bt_priority(struct ath_softc *sc)
230 230
231 if (time_after(jiffies, btcoex->bt_priority_time + 231 if (time_after(jiffies, btcoex->bt_priority_time +
232 msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { 232 msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
233 if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { 233 sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN);
234 /* Detect if colocated bt started scanning */
235 if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
236 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX,
237 "BT scan detected");
238 sc->sc_flags |= (SC_OP_BT_SCAN |
239 SC_OP_BT_PRIORITY_DETECTED);
240 } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
234 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, 241 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX,
235 "BT priority traffic detected"); 242 "BT priority traffic detected");
236 sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; 243 sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED;
237 } else {
238 sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
239 } 244 }
240 245
241 btcoex->bt_priority_cnt = 0; 246 btcoex->bt_priority_cnt = 0;
@@ -316,12 +321,17 @@ static void ath_btcoex_period_timer(unsigned long data)
316 struct ath_softc *sc = (struct ath_softc *) data; 321 struct ath_softc *sc = (struct ath_softc *) data;
317 struct ath_hw *ah = sc->sc_ah; 322 struct ath_hw *ah = sc->sc_ah;
318 struct ath_btcoex *btcoex = &sc->btcoex; 323 struct ath_btcoex *btcoex = &sc->btcoex;
324 u32 timer_period;
325 bool is_btscan;
319 326
320 ath_detect_bt_priority(sc); 327 ath_detect_bt_priority(sc);
321 328
329 is_btscan = sc->sc_flags & SC_OP_BT_SCAN;
330
322 spin_lock_bh(&btcoex->btcoex_lock); 331 spin_lock_bh(&btcoex->btcoex_lock);
323 332
324 ath9k_btcoex_bt_stomp(sc, btcoex->bt_stomp_type); 333 ath9k_btcoex_bt_stomp(sc, is_btscan ? ATH_BTCOEX_STOMP_ALL :
334 btcoex->bt_stomp_type);
325 335
326 spin_unlock_bh(&btcoex->btcoex_lock); 336 spin_unlock_bh(&btcoex->btcoex_lock);
327 337
@@ -329,11 +339,12 @@ static void ath_btcoex_period_timer(unsigned long data)
329 if (btcoex->hw_timer_enabled) 339 if (btcoex->hw_timer_enabled)
330 ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); 340 ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
331 341
342 timer_period = is_btscan ? btcoex->btscan_no_stomp :
343 btcoex->btcoex_no_stomp;
332 ath9k_gen_timer_start(ah, 344 ath9k_gen_timer_start(ah,
333 btcoex->no_stomp_timer, 345 btcoex->no_stomp_timer,
334 (ath9k_hw_gettsf32(ah) + 346 (ath9k_hw_gettsf32(ah) +
335 btcoex->btcoex_no_stomp), 347 timer_period), timer_period * 10);
336 btcoex->btcoex_no_stomp * 10);
337 btcoex->hw_timer_enabled = true; 348 btcoex->hw_timer_enabled = true;
338 } 349 }
339 350
@@ -350,13 +361,14 @@ static void ath_btcoex_no_stomp_timer(void *arg)
350 struct ath_softc *sc = (struct ath_softc *)arg; 361 struct ath_softc *sc = (struct ath_softc *)arg;
351 struct ath_hw *ah = sc->sc_ah; 362 struct ath_hw *ah = sc->sc_ah;
352 struct ath_btcoex *btcoex = &sc->btcoex; 363 struct ath_btcoex *btcoex = &sc->btcoex;
364 bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN;
353 365
354 ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, 366 ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
355 "no stomp timer running \n"); 367 "no stomp timer running \n");
356 368
357 spin_lock_bh(&btcoex->btcoex_lock); 369 spin_lock_bh(&btcoex->btcoex_lock);
358 370
359 if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW) 371 if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan)
360 ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE); 372 ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE);
361 else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) 373 else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
362 ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW); 374 ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW);
@@ -371,6 +383,8 @@ int ath_init_btcoex_timer(struct ath_softc *sc)
371 btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000; 383 btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000;
372 btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * 384 btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
373 btcoex->btcoex_period / 100; 385 btcoex->btcoex_period / 100;
386 btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) *
387 btcoex->btcoex_period / 100;
374 388
375 setup_timer(&btcoex->period_timer, ath_btcoex_period_timer, 389 setup_timer(&btcoex->period_timer, ath_btcoex_period_timer,
376 (unsigned long) sc); 390 (unsigned long) sc);
@@ -405,7 +419,7 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc)
405 419
406 btcoex->bt_priority_cnt = 0; 420 btcoex->bt_priority_cnt = 0;
407 btcoex->bt_priority_time = jiffies; 421 btcoex->bt_priority_time = jiffies;
408 sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; 422 sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN);
409 423
410 mod_timer(&btcoex->period_timer, jiffies); 424 mod_timer(&btcoex->period_timer, jiffies);
411} 425}
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 1a27f39c1adc..f15fee76a4e2 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -334,7 +334,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
334 ah->config.pcie_clock_req = 0; 334 ah->config.pcie_clock_req = 0;
335 ah->config.pcie_waen = 0; 335 ah->config.pcie_waen = 0;
336 ah->config.analog_shiftreg = 1; 336 ah->config.analog_shiftreg = 1;
337 ah->config.ht_enable = 1;
338 ah->config.ofdm_trig_low = 200; 337 ah->config.ofdm_trig_low = 200;
339 ah->config.ofdm_trig_high = 500; 338 ah->config.ofdm_trig_high = 500;
340 ah->config.cck_trig_high = 200; 339 ah->config.cck_trig_high = 200;
@@ -346,6 +345,11 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
346 ah->config.spurchans[i][1] = AR_NO_SPUR; 345 ah->config.spurchans[i][1] = AR_NO_SPUR;
347 } 346 }
348 347
348 if (ah->hw_version.devid != AR2427_DEVID_PCIE)
349 ah->config.ht_enable = 1;
350 else
351 ah->config.ht_enable = 0;
352
349 ah->config.rx_intr_mitigation = true; 353 ah->config.rx_intr_mitigation = true;
350 354
351 /* 355 /*
@@ -542,6 +546,7 @@ static bool ath9k_hw_devid_supported(u16 devid)
542 case AR5416_DEVID_AR9287_PCI: 546 case AR5416_DEVID_AR9287_PCI:
543 case AR5416_DEVID_AR9287_PCIE: 547 case AR5416_DEVID_AR9287_PCIE:
544 case AR9271_USB: 548 case AR9271_USB:
549 case AR2427_DEVID_PCIE:
545 return true; 550 return true;
546 default: 551 default:
547 break; 552 break;
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index ab1f1981d857..dbbf7ca5f97d 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -40,6 +40,7 @@
40#define AR9280_DEVID_PCI 0x0029 40#define AR9280_DEVID_PCI 0x0029
41#define AR9280_DEVID_PCIE 0x002a 41#define AR9280_DEVID_PCIE 0x002a
42#define AR9285_DEVID_PCIE 0x002b 42#define AR9285_DEVID_PCIE 0x002b
43#define AR2427_DEVID_PCIE 0x002c
43 44
44#define AR5416_AR9100_DEVID 0x000b 45#define AR5416_AR9100_DEVID 0x000b
45 46
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 5f78d7a5ff22..4b5e54848683 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -620,11 +620,13 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
620 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | 620 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
621 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | 621 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
622 IEEE80211_HW_SIGNAL_DBM | 622 IEEE80211_HW_SIGNAL_DBM |
623 IEEE80211_HW_AMPDU_AGGREGATION |
624 IEEE80211_HW_SUPPORTS_PS | 623 IEEE80211_HW_SUPPORTS_PS |
625 IEEE80211_HW_PS_NULLFUNC_STACK | 624 IEEE80211_HW_PS_NULLFUNC_STACK |
626 IEEE80211_HW_SPECTRUM_MGMT; 625 IEEE80211_HW_SPECTRUM_MGMT;
627 626
627 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
628 hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
629
628 if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt) 630 if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt)
629 hw->flags |= IEEE80211_HW_MFP_CAPABLE; 631 hw->flags |= IEEE80211_HW_MFP_CAPABLE;
630 632
@@ -640,8 +642,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
640 hw->max_rates = 4; 642 hw->max_rates = 4;
641 hw->channel_change_time = 5000; 643 hw->channel_change_time = 5000;
642 hw->max_listen_interval = 10; 644 hw->max_listen_interval = 10;
643 /* Hardware supports 10 but we use 4 */ 645 hw->max_rate_tries = 10;
644 hw->max_rate_tries = 4;
645 hw->sta_data_size = sizeof(struct ath_node); 646 hw->sta_data_size = sizeof(struct ath_node);
646 hw->vif_data_size = sizeof(struct ath_vif); 647 hw->vif_data_size = sizeof(struct ath_vif);
647 648
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 6aaca0026da8..6796d5cdc293 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -143,8 +143,10 @@ void ath9k_ps_restore(struct ath_softc *sc)
143 if (--sc->ps_usecount != 0) 143 if (--sc->ps_usecount != 0)
144 goto unlock; 144 goto unlock;
145 145
146 if (sc->ps_enabled && 146 if (sc->ps_idle)
147 !(sc->ps_flags & (PS_WAIT_FOR_BEACON | 147 ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
148 else if (sc->ps_enabled &&
149 !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
148 PS_WAIT_FOR_CAB | 150 PS_WAIT_FOR_CAB |
149 PS_WAIT_FOR_PSPOLL_DATA | 151 PS_WAIT_FOR_PSPOLL_DATA |
150 PS_WAIT_FOR_TX_ACK))) 152 PS_WAIT_FOR_TX_ACK)))
@@ -204,7 +206,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
204 r = ath9k_hw_reset(ah, hchan, fastcc); 206 r = ath9k_hw_reset(ah, hchan, fastcc);
205 if (r) { 207 if (r) {
206 ath_print(common, ATH_DBG_FATAL, 208 ath_print(common, ATH_DBG_FATAL,
207 "Unable to reset channel (%u Mhz) " 209 "Unable to reset channel (%u MHz), "
208 "reset status %d\n", 210 "reset status %d\n",
209 channel->center_freq, r); 211 channel->center_freq, r);
210 spin_unlock_bh(&sc->sc_resetlock); 212 spin_unlock_bh(&sc->sc_resetlock);
@@ -867,7 +869,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
867 r = ath9k_hw_reset(ah, ah->curchan, false); 869 r = ath9k_hw_reset(ah, ah->curchan, false);
868 if (r) { 870 if (r) {
869 ath_print(common, ATH_DBG_FATAL, 871 ath_print(common, ATH_DBG_FATAL,
870 "Unable to reset channel %u (%uMhz) ", 872 "Unable to reset channel (%u MHz), "
871 "reset status %d\n", 873 "reset status %d\n",
872 channel->center_freq, r); 874 channel->center_freq, r);
873 } 875 }
@@ -922,7 +924,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
922 r = ath9k_hw_reset(ah, ah->curchan, false); 924 r = ath9k_hw_reset(ah, ah->curchan, false);
923 if (r) { 925 if (r) {
924 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, 926 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
925 "Unable to reset channel %u (%uMhz) " 927 "Unable to reset channel (%u MHz), "
926 "reset status %d\n", 928 "reset status %d\n",
927 channel->center_freq, r); 929 channel->center_freq, r);
928 } 930 }
@@ -1528,6 +1530,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
1528 spin_unlock_bh(&sc->wiphy_lock); 1530 spin_unlock_bh(&sc->wiphy_lock);
1529 1531
1530 if (enable_radio) { 1532 if (enable_radio) {
1533 sc->ps_idle = false;
1531 ath_radio_enable(sc, hw); 1534 ath_radio_enable(sc, hw);
1532 ath_print(common, ATH_DBG_CONFIG, 1535 ath_print(common, ATH_DBG_CONFIG,
1533 "not-idle: enabling radio\n"); 1536 "not-idle: enabling radio\n");
@@ -1624,8 +1627,10 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
1624 } 1627 }
1625 1628
1626skip_chan_change: 1629skip_chan_change:
1627 if (changed & IEEE80211_CONF_CHANGE_POWER) 1630 if (changed & IEEE80211_CONF_CHANGE_POWER) {
1628 sc->config.txpowlimit = 2 * conf->power_level; 1631 sc->config.txpowlimit = 2 * conf->power_level;
1632 ath_update_txpow(sc);
1633 }
1629 1634
1630 spin_lock_bh(&sc->wiphy_lock); 1635 spin_lock_bh(&sc->wiphy_lock);
1631 disable_radio = ath9k_all_wiphys_idle(sc); 1636 disable_radio = ath9k_all_wiphys_idle(sc);
@@ -1633,6 +1638,7 @@ skip_chan_change:
1633 1638
1634 if (disable_radio) { 1639 if (disable_radio) {
1635 ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); 1640 ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n");
1641 sc->ps_idle = true;
1636 ath_radio_disable(sc, hw); 1642 ath_radio_disable(sc, hw);
1637 } 1643 }
1638 1644
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index fe2c3a644a6e..9441c6718a30 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -25,6 +25,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
25 { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ 25 { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */
26 { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ 26 { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
27 { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ 27 { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
28 { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */
28 { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ 29 { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */
29 { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ 30 { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */
30 { 0 } 31 { 0 }
@@ -49,16 +50,6 @@ static void ath_pci_read_cachesize(struct ath_common *common, int *csz)
49 *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ 50 *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */
50} 51}
51 52
52static void ath_pci_cleanup(struct ath_common *common)
53{
54 struct ath_softc *sc = (struct ath_softc *) common->priv;
55 struct pci_dev *pdev = to_pci_dev(sc->dev);
56
57 pci_iounmap(pdev, sc->mem);
58 pci_disable_device(pdev);
59 pci_release_region(pdev, 0);
60}
61
62static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data) 53static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
63{ 54{
64 struct ath_hw *ah = (struct ath_hw *) common->ah; 55 struct ath_hw *ah = (struct ath_hw *) common->ah;
@@ -98,7 +89,6 @@ static void ath_pci_bt_coex_prep(struct ath_common *common)
98 89
99static const struct ath_bus_ops ath_pci_bus_ops = { 90static const struct ath_bus_ops ath_pci_bus_ops = {
100 .read_cachesize = ath_pci_read_cachesize, 91 .read_cachesize = ath_pci_read_cachesize,
101 .cleanup = ath_pci_cleanup,
102 .eeprom_read = ath_pci_eeprom_read, 92 .eeprom_read = ath_pci_eeprom_read,
103 .bt_coex_prep = ath_pci_bt_coex_prep, 93 .bt_coex_prep = ath_pci_bt_coex_prep,
104}; 94};
@@ -245,12 +235,15 @@ static void ath_pci_remove(struct pci_dev *pdev)
245 struct ieee80211_hw *hw = pci_get_drvdata(pdev); 235 struct ieee80211_hw *hw = pci_get_drvdata(pdev);
246 struct ath_wiphy *aphy = hw->priv; 236 struct ath_wiphy *aphy = hw->priv;
247 struct ath_softc *sc = aphy->sc; 237 struct ath_softc *sc = aphy->sc;
248 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 238 void __iomem *mem = sc->mem;
249 239
250 ath9k_deinit_device(sc); 240 ath9k_deinit_device(sc);
251 free_irq(sc->irq, sc); 241 free_irq(sc->irq, sc);
252 ieee80211_free_hw(sc->hw); 242 ieee80211_free_hw(sc->hw);
253 ath_bus_cleanup(common); 243
244 pci_iounmap(pdev, mem);
245 pci_disable_device(pdev);
246 pci_release_region(pdev, 0);
254} 247}
255 248
256#ifdef CONFIG_PM 249#ifdef CONFIG_PM
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 70fdb9d8db82..11968843c773 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -678,13 +678,13 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
678 * For Multi Rate Retry we use a different number of 678 * For Multi Rate Retry we use a different number of
679 * retry attempt counts. This ends up looking like this: 679 * retry attempt counts. This ends up looking like this:
680 * 680 *
681 * MRR[0] = 2 681 * MRR[0] = 4
682 * MRR[1] = 2 682 * MRR[1] = 4
683 * MRR[2] = 2 683 * MRR[2] = 4
684 * MRR[3] = 4 684 * MRR[3] = 8
685 * 685 *
686 */ 686 */
687 try_per_rate = sc->hw->max_rate_tries; 687 try_per_rate = 4;
688 688
689 rate_table = sc->cur_rate_table; 689 rate_table = sc->cur_rate_table;
690 rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe); 690 rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe);
@@ -714,7 +714,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
714 for ( ; i < 4; i++) { 714 for ( ; i < 4; i++) {
715 /* Use twice the number of tries for the last MRR segment. */ 715 /* Use twice the number of tries for the last MRR segment. */
716 if (i + 1 == 4) 716 if (i + 1 == 4)
717 try_per_rate = 4; 717 try_per_rate = 8;
718 718
719 ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix); 719 ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix);
720 /* All other rates in the series have RTS enabled */ 720 /* All other rates in the series have RTS enabled */
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 40b5d05edcce..1ca42e5148c8 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -429,7 +429,7 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
429 sc->ps_flags &= ~PS_WAIT_FOR_PSPOLL_DATA; 429 sc->ps_flags &= ~PS_WAIT_FOR_PSPOLL_DATA;
430 ath_print(common, ATH_DBG_PS, 430 ath_print(common, ATH_DBG_PS,
431 "Going back to sleep after having received " 431 "Going back to sleep after having received "
432 "PS-Poll data (0x%x)\n", 432 "PS-Poll data (0x%lx)\n",
433 sc->ps_flags & (PS_WAIT_FOR_BEACON | 433 sc->ps_flags & (PS_WAIT_FOR_BEACON |
434 PS_WAIT_FOR_CAB | 434 PS_WAIT_FOR_CAB |
435 PS_WAIT_FOR_PSPOLL_DATA | 435 PS_WAIT_FOR_PSPOLL_DATA |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 8e653fb937a1..72cfa8ebd9ae 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -1547,9 +1547,9 @@ enum {
1547 1547
1548#define AR_BT_COEX_WEIGHT 0x8174 1548#define AR_BT_COEX_WEIGHT 0x8174
1549#define AR_BT_COEX_WGHT 0xff55 1549#define AR_BT_COEX_WGHT 0xff55
1550#define AR_STOMP_ALL_WLAN_WGHT 0xffcc 1550#define AR_STOMP_ALL_WLAN_WGHT 0xfcfc
1551#define AR_STOMP_LOW_WLAN_WGHT 0xaaa8 1551#define AR_STOMP_LOW_WLAN_WGHT 0xa8a8
1552#define AR_STOMP_NONE_WLAN_WGHT 0xaa00 1552#define AR_STOMP_NONE_WLAN_WGHT 0x0000
1553#define AR_BTCOEX_BT_WGHT 0x0000ffff 1553#define AR_BTCOEX_BT_WGHT 0x0000ffff
1554#define AR_BTCOEX_BT_WGHT_S 0 1554#define AR_BTCOEX_BT_WGHT_S 0
1555#define AR_BTCOEX_WL_WGHT 0xffff0000 1555#define AR_BTCOEX_WL_WGHT 0xffff0000
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index a821bb687b3b..3c790a4f38f7 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1498,26 +1498,6 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
1498 if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) 1498 if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
1499 ctsrate |= rate->hw_value_short; 1499 ctsrate |= rate->hw_value_short;
1500 1500
1501 /*
1502 * ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive.
1503 * Check the first rate in the series to decide whether RTS/CTS
1504 * or CTS-to-self has to be used.
1505 */
1506 if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
1507 flags = ATH9K_TXDESC_CTSENA;
1508 else if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
1509 flags = ATH9K_TXDESC_RTSENA;
1510
1511 /* FIXME: Handle aggregation protection */
1512 if (sc->config.ath_aggr_prot &&
1513 (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) {
1514 flags = ATH9K_TXDESC_RTSENA;
1515 }
1516
1517 /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
1518 if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit))
1519 flags &= ~(ATH9K_TXDESC_RTSENA);
1520
1521 for (i = 0; i < 4; i++) { 1501 for (i = 0; i < 4; i++) {
1522 bool is_40, is_sgi, is_sp; 1502 bool is_40, is_sgi, is_sp;
1523 int phy; 1503 int phy;
@@ -1529,8 +1509,15 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
1529 series[i].Tries = rates[i].count; 1509 series[i].Tries = rates[i].count;
1530 series[i].ChSel = common->tx_chainmask; 1510 series[i].ChSel = common->tx_chainmask;
1531 1511
1532 if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) 1512 if ((sc->config.ath_aggr_prot && bf_isaggr(bf)) ||
1513 (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)) {
1533 series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; 1514 series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
1515 flags |= ATH9K_TXDESC_RTSENA;
1516 } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
1517 series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
1518 flags |= ATH9K_TXDESC_CTSENA;
1519 }
1520
1534 if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) 1521 if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
1535 series[i].RateFlags |= ATH9K_RATESERIES_2040; 1522 series[i].RateFlags |= ATH9K_RATESERIES_2040;
1536 if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) 1523 if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
@@ -1568,6 +1555,14 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
1568 phy, rate->bitrate * 100, bf->bf_frmlen, rix, is_sp); 1555 phy, rate->bitrate * 100, bf->bf_frmlen, rix, is_sp);
1569 } 1556 }
1570 1557
1558 /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
1559 if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit))
1560 flags &= ~ATH9K_TXDESC_RTSENA;
1561
1562 /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
1563 if (flags & ATH9K_TXDESC_RTSENA)
1564 flags &= ~ATH9K_TXDESC_CTSENA;
1565
1571 /* set dur_update_en for l-sig computation except for PS-Poll frames */ 1566 /* set dur_update_en for l-sig computation except for PS-Poll frames */
1572 ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc, 1567 ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc,
1573 bf->bf_lastbf->bf_desc, 1568 bf->bf_lastbf->bf_desc,
@@ -1862,7 +1857,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
1862 sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; 1857 sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK;
1863 ath_print(common, ATH_DBG_PS, 1858 ath_print(common, ATH_DBG_PS,
1864 "Going back to sleep after having " 1859 "Going back to sleep after having "
1865 "received TX status (0x%x)\n", 1860 "received TX status (0x%lx)\n",
1866 sc->ps_flags & (PS_WAIT_FOR_BEACON | 1861 sc->ps_flags & (PS_WAIT_FOR_BEACON |
1867 PS_WAIT_FOR_CAB | 1862 PS_WAIT_FOR_CAB |
1868 PS_WAIT_FOR_PSPOLL_DATA | 1863 PS_WAIT_FOR_PSPOLL_DATA |
diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h
index d6b685a06c5e..8263633c003c 100644
--- a/drivers/net/wireless/ath/debug.h
+++ b/drivers/net/wireless/ath/debug.h
@@ -65,11 +65,11 @@ enum ATH_DEBUG {
65#define ATH_DBG_DEFAULT (ATH_DBG_FATAL) 65#define ATH_DBG_DEFAULT (ATH_DBG_FATAL)
66 66
67#ifdef CONFIG_ATH_DEBUG 67#ifdef CONFIG_ATH_DEBUG
68void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...); 68void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
69 __attribute__ ((format (printf, 3, 4)));
69#else 70#else
70static inline void ath_print(struct ath_common *common, 71static inline void __attribute__ ((format (printf, 3, 4)))
71 int dbg_mask, 72ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
72 const char *fmt, ...)
73{ 73{
74} 74}
75#endif /* CONFIG_ATH_DEBUG */ 75#endif /* CONFIG_ATH_DEBUG */
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 9c5c7c9ad530..316a913860d7 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -844,8 +844,10 @@ static void rx_tkip_phase1_write(struct b43_wldev *dev, u8 index, u32 iv32,
844} 844}
845 845
846static void b43_op_update_tkip_key(struct ieee80211_hw *hw, 846static void b43_op_update_tkip_key(struct ieee80211_hw *hw,
847 struct ieee80211_key_conf *keyconf, const u8 *addr, 847 struct ieee80211_vif *vif,
848 u32 iv32, u16 *phase1key) 848 struct ieee80211_key_conf *keyconf,
849 struct ieee80211_sta *sta,
850 u32 iv32, u16 *phase1key)
849{ 851{
850 struct b43_wl *wl = hw_to_b43_wl(hw); 852 struct b43_wl *wl = hw_to_b43_wl(hw);
851 struct b43_wldev *dev; 853 struct b43_wldev *dev;
@@ -854,19 +856,19 @@ static void b43_op_update_tkip_key(struct ieee80211_hw *hw,
854 if (B43_WARN_ON(!modparam_hwtkip)) 856 if (B43_WARN_ON(!modparam_hwtkip))
855 return; 857 return;
856 858
857 mutex_lock(&wl->mutex); 859 /* This is only called from the RX path through mac80211, where
858 860 * our mutex is already locked. */
861 B43_WARN_ON(!mutex_is_locked(&wl->mutex));
859 dev = wl->current_dev; 862 dev = wl->current_dev;
860 if (!dev || b43_status(dev) < B43_STAT_INITIALIZED) 863 B43_WARN_ON(!dev || b43_status(dev) < B43_STAT_INITIALIZED);
861 goto out_unlock;
862 864
863 keymac_write(dev, index, NULL); /* First zero out mac to avoid race */ 865 keymac_write(dev, index, NULL); /* First zero out mac to avoid race */
864 866
865 rx_tkip_phase1_write(dev, index, iv32, phase1key); 867 rx_tkip_phase1_write(dev, index, iv32, phase1key);
866 keymac_write(dev, index, addr); 868 /* only pairwise TKIP keys are supported right now */
867 869 if (WARN_ON(!sta))
868out_unlock: 870 return;
869 mutex_unlock(&wl->mutex); 871 keymac_write(dev, index, sta->addr);
870} 872}
871 873
872static void do_key_write(struct b43_wldev *dev, 874static void do_key_write(struct b43_wldev *dev,
@@ -3571,6 +3573,12 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
3571 dev = wl->current_dev; 3573 dev = wl->current_dev;
3572 phy = &dev->phy; 3574 phy = &dev->phy;
3573 3575
3576 if (conf_is_ht(conf))
3577 phy->is_40mhz =
3578 (conf_is_ht40_minus(conf) || conf_is_ht40_plus(conf));
3579 else
3580 phy->is_40mhz = false;
3581
3574 b43_mac_suspend(dev); 3582 b43_mac_suspend(dev);
3575 3583
3576 if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) 3584 if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index 75b26e175e8f..8f7d7eff2d80 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -421,3 +421,48 @@ void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on)
421{ 421{
422 b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4); 422 b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4);
423} 423}
424
425/* http://bcm-v4.sipsolutions.net/802.11/PHY/Cordic */
426struct b43_c32 b43_cordic(int theta)
427{
428 u32 arctg[] = { 2949120, 1740967, 919879, 466945, 234379, 117304,
429 58666, 29335, 14668, 7334, 3667, 1833, 917, 458,
430 229, 115, 57, 29, };
431 u8 i;
432 s32 tmp;
433 s8 signx = 1;
434 u32 angle = 0;
435 struct b43_c32 ret = { .i = 39797, .q = 0, };
436
437 while (theta > (180 << 16))
438 theta -= (360 << 16);
439 while (theta < -(180 << 16))
440 theta += (360 << 16);
441
442 if (theta > (90 << 16)) {
443 theta -= (180 << 16);
444 signx = -1;
445 } else if (theta < -(90 << 16)) {
446 theta += (180 << 16);
447 signx = -1;
448 }
449
450 for (i = 0; i <= 17; i++) {
451 if (theta > angle) {
452 tmp = ret.i - (ret.q >> i);
453 ret.q += ret.i >> i;
454 ret.i = tmp;
455 angle += arctg[i];
456 } else {
457 tmp = ret.i + (ret.q >> i);
458 ret.q -= ret.i >> i;
459 ret.i = tmp;
460 angle -= arctg[i];
461 }
462 }
463
464 ret.i *= signx;
465 ret.q *= signx;
466
467 return ret;
468}
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index 9edd4e8e0c85..bd480b481bfc 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -5,6 +5,12 @@
5 5
6struct b43_wldev; 6struct b43_wldev;
7 7
8/* Complex number using 2 32-bit signed integers */
9struct b43_c32 { s32 i, q; };
10
11#define CORDIC_CONVERT(value) (((value) >= 0) ? \
12 ((((value) >> 15) + 1) >> 1) : \
13 -((((-(value)) >> 15) + 1) >> 1))
8 14
9/* PHY register routing bits */ 15/* PHY register routing bits */
10#define B43_PHYROUTE 0x0C00 /* PHY register routing bits mask */ 16#define B43_PHYROUTE 0x0C00 /* PHY register routing bits mask */
@@ -212,6 +218,9 @@ struct b43_phy {
212 bool supports_2ghz; 218 bool supports_2ghz;
213 bool supports_5ghz; 219 bool supports_5ghz;
214 220
221 /* HT info */
222 bool is_40mhz;
223
215 /* GMODE bit enabled? */ 224 /* GMODE bit enabled? */
216 bool gmode; 225 bool gmode;
217 226
@@ -418,5 +427,6 @@ int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset);
418 */ 427 */
419void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on); 428void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on);
420 429
430struct b43_c32 b43_cordic(int theta);
421 431
422#endif /* LINUX_B43_PHY_COMMON_H_ */ 432#endif /* LINUX_B43_PHY_COMMON_H_ */
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index b58d6cf26580..185219e0a552 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -1767,47 +1767,6 @@ out:
1767 return ret; 1767 return ret;
1768} 1768}
1769 1769
1770/* Complex number using 2 32-bit signed integers */
1771typedef struct {s32 i, q;} lpphy_c32;
1772
1773static lpphy_c32 lpphy_cordic(int theta)
1774{
1775 u32 arctg[] = { 2949120, 1740967, 919879, 466945, 234379, 117304,
1776 58666, 29335, 14668, 7334, 3667, 1833, 917, 458,
1777 229, 115, 57, 29, };
1778 int i, tmp, signx = 1, angle = 0;
1779 lpphy_c32 ret = { .i = 39797, .q = 0, };
1780
1781 theta = clamp_t(int, theta, -180, 180);
1782
1783 if (theta > 90) {
1784 theta -= 180;
1785 signx = -1;
1786 } else if (theta < -90) {
1787 theta += 180;
1788 signx = -1;
1789 }
1790
1791 for (i = 0; i <= 17; i++) {
1792 if (theta > angle) {
1793 tmp = ret.i - (ret.q >> i);
1794 ret.q += ret.i >> i;
1795 ret.i = tmp;
1796 angle += arctg[i];
1797 } else {
1798 tmp = ret.i + (ret.q >> i);
1799 ret.q -= ret.i >> i;
1800 ret.i = tmp;
1801 angle -= arctg[i];
1802 }
1803 }
1804
1805 ret.i *= signx;
1806 ret.q *= signx;
1807
1808 return ret;
1809}
1810
1811static void lpphy_run_samples(struct b43_wldev *dev, u16 samples, u16 loops, 1770static void lpphy_run_samples(struct b43_wldev *dev, u16 samples, u16 loops,
1812 u16 wait) 1771 u16 wait)
1813{ 1772{
@@ -1825,8 +1784,9 @@ static void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max)
1825{ 1784{
1826 struct b43_phy_lp *lpphy = dev->phy.lp; 1785 struct b43_phy_lp *lpphy = dev->phy.lp;
1827 u16 buf[64]; 1786 u16 buf[64];
1828 int i, samples = 0, angle = 0, rotation = (9 * freq) / 500; 1787 int i, samples = 0, angle = 0;
1829 lpphy_c32 sample; 1788 int rotation = (((36 * freq) / 20) << 16) / 100;
1789 struct b43_c32 sample;
1830 1790
1831 lpphy->tx_tone_freq = freq; 1791 lpphy->tx_tone_freq = freq;
1832 1792
@@ -1842,10 +1802,10 @@ static void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max)
1842 } 1802 }
1843 1803
1844 for (i = 0; i < samples; i++) { 1804 for (i = 0; i < samples; i++) {
1845 sample = lpphy_cordic(angle); 1805 sample = b43_cordic(angle);
1846 angle += rotation; 1806 angle += rotation;
1847 buf[i] = ((sample.i * max) & 0xFF) << 8; 1807 buf[i] = CORDIC_CONVERT((sample.i * max) & 0xFF) << 8;
1848 buf[i] |= (sample.q * max) & 0xFF; 1808 buf[i] |= CORDIC_CONVERT((sample.q * max) & 0xFF);
1849 } 1809 }
1850 1810
1851 b43_lptab_write_bulk(dev, B43_LPTAB16(5, 0), samples, buf); 1811 b43_lptab_write_bulk(dev, B43_LPTAB16(5, 0), samples, buf);
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 4a817e3da163..6392da25efed 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -55,6 +55,20 @@ struct nphy_iq_est {
55 u32 q1_pwr; 55 u32 q1_pwr;
56}; 56};
57 57
58enum b43_nphy_rf_sequence {
59 B43_RFSEQ_RX2TX,
60 B43_RFSEQ_TX2RX,
61 B43_RFSEQ_RESET2RX,
62 B43_RFSEQ_UPDATE_GAINH,
63 B43_RFSEQ_UPDATE_GAINL,
64 B43_RFSEQ_UPDATE_GAINU,
65};
66
67static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
68 u8 *events, u8 *delays, u8 length);
69static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
70 enum b43_nphy_rf_sequence seq);
71
58void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) 72void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
59{//TODO 73{//TODO
60} 74}
@@ -234,110 +248,6 @@ static void b43_nphy_tables_init(struct b43_wldev *dev)
234 b43_nphy_rev3plus_tables_init(dev); 248 b43_nphy_rev3plus_tables_init(dev);
235} 249}
236 250
237static void b43_nphy_workarounds(struct b43_wldev *dev)
238{
239 struct b43_phy *phy = &dev->phy;
240 unsigned int i;
241
242 b43_phy_set(dev, B43_NPHY_IQFLIP,
243 B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
244 if (1 /* FIXME band is 2.4GHz */) {
245 b43_phy_set(dev, B43_NPHY_CLASSCTL,
246 B43_NPHY_CLASSCTL_CCKEN);
247 } else {
248 b43_phy_mask(dev, B43_NPHY_CLASSCTL,
249 ~B43_NPHY_CLASSCTL_CCKEN);
250 }
251 b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
252 b43_phy_write(dev, B43_NPHY_TXFRAMEDELAY, 8);
253
254 /* Fixup some tables */
255 b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0xA);
256 b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0xA);
257 b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
258 b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
259 b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0);
260 b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0);
261 b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
262 b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
263 b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x800);
264 b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x800);
265
266 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
267 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
268 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
269 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
270
271 //TODO set RF sequence
272
273 /* Set narrowband clip threshold */
274 b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 66);
275 b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 66);
276
277 /* Set wideband clip 2 threshold */
278 b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
279 ~B43_NPHY_C1_CLIPWBTHRES_CLIP2,
280 21 << B43_NPHY_C1_CLIPWBTHRES_CLIP2_SHIFT);
281 b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
282 ~B43_NPHY_C2_CLIPWBTHRES_CLIP2,
283 21 << B43_NPHY_C2_CLIPWBTHRES_CLIP2_SHIFT);
284
285 /* Set Clip 2 detect */
286 b43_phy_set(dev, B43_NPHY_C1_CGAINI,
287 B43_NPHY_C1_CGAINI_CL2DETECT);
288 b43_phy_set(dev, B43_NPHY_C2_CGAINI,
289 B43_NPHY_C2_CGAINI_CL2DETECT);
290
291 if (0 /*FIXME*/) {
292 /* Set dwell lengths */
293 b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 43);
294 b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 43);
295 b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 9);
296 b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 9);
297
298 /* Set gain backoff */
299 b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,
300 ~B43_NPHY_C1_CGAINI_GAINBKOFF,
301 1 << B43_NPHY_C1_CGAINI_GAINBKOFF_SHIFT);
302 b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,
303 ~B43_NPHY_C2_CGAINI_GAINBKOFF,
304 1 << B43_NPHY_C2_CGAINI_GAINBKOFF_SHIFT);
305
306 /* Set HPVGA2 index */
307 b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN,
308 ~B43_NPHY_C1_INITGAIN_HPVGA2,
309 6 << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT);
310 b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN,
311 ~B43_NPHY_C2_INITGAIN_HPVGA2,
312 6 << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT);
313
314 //FIXME verify that the specs really mean to use autoinc here.
315 for (i = 0; i < 3; i++)
316 b43_ntab_write(dev, B43_NTAB16(7, 0x106) + i, 0x673);
317 }
318
319 /* Set minimum gain value */
320 b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN,
321 ~B43_NPHY_C1_MINGAIN,
322 23 << B43_NPHY_C1_MINGAIN_SHIFT);
323 b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN,
324 ~B43_NPHY_C2_MINGAIN,
325 23 << B43_NPHY_C2_MINGAIN_SHIFT);
326
327 if (phy->rev < 2) {
328 b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
329 ~B43_NPHY_SCRAM_SIGCTL_SCM);
330 }
331
332 /* Set phase track alpha and beta */
333 b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
334 b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
335 b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
336 b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
337 b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
338 b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
339}
340
341/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */ 251/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */
342static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable) 252static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
343{ 253{
@@ -421,7 +331,49 @@ static void b43_nphy_reset_cca(struct b43_wldev *dev)
421 udelay(1); 331 udelay(1);
422 b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA); 332 b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
423 b43_nphy_bmac_clock_fgc(dev, 0); 333 b43_nphy_bmac_clock_fgc(dev, 0);
424 /* TODO: N PHY Force RF Seq with argument 2 */ 334 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
335}
336
337/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */
338static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble)
339{
340 u16 mimocfg = b43_phy_read(dev, B43_NPHY_MIMOCFG);
341
342 mimocfg |= B43_NPHY_MIMOCFG_AUTO;
343 if (preamble == 1)
344 mimocfg |= B43_NPHY_MIMOCFG_GFMIX;
345 else
346 mimocfg &= ~B43_NPHY_MIMOCFG_GFMIX;
347
348 b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg);
349}
350
351/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */
352static void b43_nphy_update_txrx_chain(struct b43_wldev *dev)
353{
354 struct b43_phy_n *nphy = dev->phy.n;
355
356 bool override = false;
357 u16 chain = 0x33;
358
359 if (nphy->txrx_chain == 0) {
360 chain = 0x11;
361 override = true;
362 } else if (nphy->txrx_chain == 1) {
363 chain = 0x22;
364 override = true;
365 }
366
367 b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
368 ~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN),
369 chain);
370
371 if (override)
372 b43_phy_set(dev, B43_NPHY_RFSEQMODE,
373 B43_NPHY_RFSEQMODE_CAOVER);
374 else
375 b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
376 ~B43_NPHY_RFSEQMODE_CAOVER);
425} 377}
426 378
427/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */ 379/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */
@@ -480,6 +432,88 @@ static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write,
480 } 432 }
481} 433}
482 434
435/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */
436static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core)
437{
438 u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
439
440 b43_phy_write(dev, B43_NPHY_RFSEQCA, regs[0]);
441 if (core == 0) {
442 b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[1]);
443 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
444 } else {
445 b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
446 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
447 }
448 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[3]);
449 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[4]);
450 b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, regs[5]);
451 b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, regs[6]);
452 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, regs[7]);
453 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, regs[8]);
454 b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
455 b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
456}
457
458/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */
459static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
460{
461 u8 rxval, txval;
462 u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
463
464 regs[0] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
465 if (core == 0) {
466 regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
467 regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
468 } else {
469 regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
470 regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
471 }
472 regs[3] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
473 regs[4] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
474 regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
475 regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
476 regs[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S1);
477 regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
478 regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
479 regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
480
481 b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
482 b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
483
484 b43_phy_maskset(dev, B43_NPHY_RFSEQCA, (u16)~B43_NPHY_RFSEQCA_RXDIS,
485 ((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
486 b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
487 ((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT));
488 b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
489 (core << B43_NPHY_RFSEQCA_RXEN_SHIFT));
490 b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXDIS,
491 (core << B43_NPHY_RFSEQCA_TXDIS_SHIFT));
492
493 if (core == 0) {
494 b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x0007);
495 b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0007);
496 } else {
497 b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x0007);
498 b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007);
499 }
500
501 /* TODO: Call N PHY RF Ctrl Intc Override with 2, 0, 3 as arguments */
502 /* TODO: Call N PHY RF Intc Override with 8, 0, 3, 0 as arguments */
503 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
504
505 if (core == 0) {
506 rxval = 1;
507 txval = 8;
508 } else {
509 rxval = 4;
510 txval = 2;
511 }
512
513 /* TODO: Call N PHY RF Ctrl Intc Override with 1, rxval, (core + 1) */
514 /* TODO: Call N PHY RF Ctrl Intc Override with 1, txval, (2 - core) */
515}
516
483/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */ 517/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */
484static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask) 518static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
485{ 519{
@@ -653,6 +687,386 @@ static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable)
653 } 687 }
654} 688}
655 689
690/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
691static void b43_nphy_stop_playback(struct b43_wldev *dev)
692{
693 struct b43_phy_n *nphy = dev->phy.n;
694 u16 tmp;
695
696 if (nphy->hang_avoid)
697 b43_nphy_stay_in_carrier_search(dev, 1);
698
699 tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT);
700 if (tmp & 0x1)
701 b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP);
702 else if (tmp & 0x2)
703 b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, (u16)~0x8000);
704
705 b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004);
706
707 if (nphy->bb_mult_save & 0x80000000) {
708 tmp = nphy->bb_mult_save & 0xFFFF;
709 b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
710 nphy->bb_mult_save = 0;
711 }
712
713 if (nphy->hang_avoid)
714 b43_nphy_stay_in_carrier_search(dev, 0);
715}
716
717/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
718static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev)
719{
720 struct b43_phy_n *nphy = dev->phy.n;
721 u8 i, j;
722 u8 code;
723
724 /* TODO: for PHY >= 3
725 s8 *lna1_gain, *lna2_gain;
726 u8 *gain_db, *gain_bits;
727 u16 *rfseq_init;
728 u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 };
729 u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 };
730 */
731
732 u8 rfseq_events[3] = { 6, 8, 7 };
733 u8 rfseq_delays[3] = { 10, 30, 1 };
734
735 if (dev->phy.rev >= 3) {
736 /* TODO */
737 } else {
738 /* Set Clip 2 detect */
739 b43_phy_set(dev, B43_NPHY_C1_CGAINI,
740 B43_NPHY_C1_CGAINI_CL2DETECT);
741 b43_phy_set(dev, B43_NPHY_C2_CGAINI,
742 B43_NPHY_C2_CGAINI_CL2DETECT);
743
744 /* Set narrowband clip threshold */
745 b43_phy_set(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84);
746 b43_phy_set(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84);
747
748 if (!dev->phy.is_40mhz) {
749 /* Set dwell lengths */
750 b43_phy_set(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B);
751 b43_phy_set(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B);
752 b43_phy_set(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009);
753 b43_phy_set(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009);
754 }
755
756 /* Set wideband clip 2 threshold */
757 b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
758 ~B43_NPHY_C1_CLIPWBTHRES_CLIP2,
759 21);
760 b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
761 ~B43_NPHY_C2_CLIPWBTHRES_CLIP2,
762 21);
763
764 if (!dev->phy.is_40mhz) {
765 b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,
766 ~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1);
767 b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,
768 ~B43_NPHY_C2_CGAINI_GAINBKOFF, 0x1);
769 b43_phy_maskset(dev, B43_NPHY_C1_CCK_CGAINI,
770 ~B43_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1);
771 b43_phy_maskset(dev, B43_NPHY_C2_CCK_CGAINI,
772 ~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1);
773 }
774
775 b43_phy_set(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
776
777 if (nphy->gain_boost) {
778 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ &&
779 dev->phy.is_40mhz)
780 code = 4;
781 else
782 code = 5;
783 } else {
784 code = dev->phy.is_40mhz ? 6 : 7;
785 }
786
787 /* Set HPVGA2 index */
788 b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN,
789 ~B43_NPHY_C1_INITGAIN_HPVGA2,
790 code << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT);
791 b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN,
792 ~B43_NPHY_C2_INITGAIN_HPVGA2,
793 code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT);
794
795 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
796 b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
797 (code << 8 | 0x7C));
798 b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
799 (code << 8 | 0x7C));
800
801 /* TODO: b43_nphy_adjust_lna_gain_table(dev); */
802
803 if (nphy->elna_gain_config) {
804 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808);
805 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
806 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
807 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
808 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
809
810 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0C08);
811 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
812 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
813 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
814 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
815
816 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
817 b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
818 (code << 8 | 0x74));
819 b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
820 (code << 8 | 0x74));
821 }
822
823 if (dev->phy.rev == 2) {
824 for (i = 0; i < 4; i++) {
825 b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
826 (0x0400 * i) + 0x0020);
827 for (j = 0; j < 21; j++)
828 b43_phy_write(dev,
829 B43_NPHY_TABLE_DATALO, 3 * j);
830 }
831
832 b43_nphy_set_rf_sequence(dev, 5,
833 rfseq_events, rfseq_delays, 3);
834 b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1,
835 (u16)~B43_NPHY_OVER_DGAIN_CCKDGECV,
836 0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);
837
838 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
839 b43_phy_maskset(dev, B43_PHY_N(0xC5D),
840 0xFF80, 4);
841 }
842 }
843}
844
845/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
846static void b43_nphy_workarounds(struct b43_wldev *dev)
847{
848 struct ssb_bus *bus = dev->dev->bus;
849 struct b43_phy *phy = &dev->phy;
850 struct b43_phy_n *nphy = phy->n;
851
852 u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };
853 u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };
854
855 u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
856 u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
857
858 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
859 b43_nphy_classifier(dev, 1, 0);
860 else
861 b43_nphy_classifier(dev, 1, 1);
862
863 if (nphy->hang_avoid)
864 b43_nphy_stay_in_carrier_search(dev, 1);
865
866 b43_phy_set(dev, B43_NPHY_IQFLIP,
867 B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
868
869 if (dev->phy.rev >= 3) {
870 /* TODO */
871 } else {
872 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
873 nphy->band5g_pwrgain) {
874 b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
875 b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);
876 } else {
877 b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
878 b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
879 }
880
881 /* TODO: convert to b43_ntab_write? */
882 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2000);
883 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A);
884 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2010);
885 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A);
886 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2002);
887 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA);
888 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2012);
889 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA);
890
891 if (dev->phy.rev < 2) {
892 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2008);
893 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000);
894 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2018);
895 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000);
896 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2007);
897 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB);
898 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2017);
899 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB);
900 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2006);
901 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800);
902 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2016);
903 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800);
904 }
905
906 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
907 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
908 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
909 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
910
911 if (bus->sprom.boardflags2_lo & 0x100 &&
912 bus->boardinfo.type == 0x8B) {
913 delays1[0] = 0x1;
914 delays1[5] = 0x14;
915 }
916 b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
917 b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
918
919 b43_nphy_gain_crtl_workarounds(dev);
920
921 if (dev->phy.rev < 2) {
922 if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
923 ; /*TODO: b43_mhf(dev, 2, 0x0010, 0x0010, 3);*/
924 } else if (dev->phy.rev == 2) {
925 b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
926 b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
927 }
928
929 if (dev->phy.rev < 2)
930 b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
931 ~B43_NPHY_SCRAM_SIGCTL_SCM);
932
933 /* Set phase track alpha and beta */
934 b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
935 b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
936 b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
937 b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
938 b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
939 b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
940
941 b43_phy_mask(dev, B43_NPHY_PIL_DW1,
942 (u16)~B43_NPHY_PIL_DW_64QAM);
943 b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
944 b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
945 b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
946
947 if (dev->phy.rev == 2)
948 b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
949 B43_NPHY_FINERX2_CGC_DECGC);
950 }
951
952 if (nphy->hang_avoid)
953 b43_nphy_stay_in_carrier_search(dev, 0);
954}
955
956/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */
957static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max,
958 bool test)
959{
960 int i;
961 u16 bw, len, rot, angle;
962 struct b43_c32 *samples;
963
964
965 bw = (dev->phy.is_40mhz) ? 40 : 20;
966 len = bw << 3;
967
968 if (test) {
969 if (b43_phy_read(dev, B43_NPHY_BBCFG) & B43_NPHY_BBCFG_RSTRX)
970 bw = 82;
971 else
972 bw = 80;
973
974 if (dev->phy.is_40mhz)
975 bw <<= 1;
976
977 len = bw << 1;
978 }
979
980 samples = kzalloc(len * sizeof(struct b43_c32), GFP_KERNEL);
981 rot = (((freq * 36) / bw) << 16) / 100;
982 angle = 0;
983
984 for (i = 0; i < len; i++) {
985 samples[i] = b43_cordic(angle);
986 angle += rot;
987 samples[i].q = CORDIC_CONVERT(samples[i].q * max);
988 samples[i].i = CORDIC_CONVERT(samples[i].i * max);
989 }
990
991 /* TODO: Call N PHY Load Sample Table with buffer, len as arguments */
992 kfree(samples);
993 return len;
994}
995
996/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */
997static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
998 u16 wait, bool iqmode, bool dac_test)
999{
1000 struct b43_phy_n *nphy = dev->phy.n;
1001 int i;
1002 u16 seq_mode;
1003 u32 tmp;
1004
1005 if (nphy->hang_avoid)
1006 b43_nphy_stay_in_carrier_search(dev, true);
1007
1008 if ((nphy->bb_mult_save & 0x80000000) == 0) {
1009 tmp = b43_ntab_read(dev, B43_NTAB16(15, 87));
1010 nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
1011 }
1012
1013 if (!dev->phy.is_40mhz)
1014 tmp = 0x6464;
1015 else
1016 tmp = 0x4747;
1017 b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
1018
1019 if (nphy->hang_avoid)
1020 b43_nphy_stay_in_carrier_search(dev, false);
1021
1022 b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1));
1023
1024 if (loops != 0xFFFF)
1025 b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, (loops - 1));
1026 else
1027 b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, loops);
1028
1029 b43_phy_write(dev, B43_NPHY_SAMP_WAITCNT, wait);
1030
1031 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
1032
1033 b43_phy_set(dev, B43_NPHY_RFSEQMODE, B43_NPHY_RFSEQMODE_CAOVER);
1034 if (iqmode) {
1035 b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
1036 b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000);
1037 } else {
1038 if (dac_test)
1039 b43_phy_write(dev, B43_NPHY_SAMP_CMD, 5);
1040 else
1041 b43_phy_write(dev, B43_NPHY_SAMP_CMD, 1);
1042 }
1043 for (i = 0; i < 100; i++) {
1044 if (b43_phy_read(dev, B43_NPHY_RFSEQST) & 1) {
1045 i = 0;
1046 break;
1047 }
1048 udelay(10);
1049 }
1050 if (i)
1051 b43err(dev->wl, "run samples timeout\n");
1052
1053 b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
1054}
1055
1056/*
1057 * Transmits a known value for LO calibration
1058 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone
1059 */
1060static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val,
1061 bool iqmode, bool dac_test)
1062{
1063 u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test);
1064 if (samp == 0)
1065 return -1;
1066 b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test);
1067 return 0;
1068}
1069
656/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */ 1070/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */
657static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev) 1071static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)
658{ 1072{
@@ -666,8 +1080,7 @@ static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)
666 if (nphy->hang_avoid) 1080 if (nphy->hang_avoid)
667 b43_nphy_stay_in_carrier_search(dev, true); 1081 b43_nphy_stay_in_carrier_search(dev, true);
668 1082
669 /* TODO: Read an N PHY Table with ID 15, length 7, offset 80, 1083 b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
670 width 16, and data pointer buffer */
671 1084
672 for (i = 0; i < 2; i++) { 1085 for (i = 0; i < 2; i++) {
673 tmp = ((buffer[i * 2] & 0x3FF) << 10) | 1086 tmp = ((buffer[i * 2] & 0x3FF) << 10) |
@@ -720,15 +1133,32 @@ static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)
720 b43_nphy_stay_in_carrier_search(dev, false); 1133 b43_nphy_stay_in_carrier_search(dev, false);
721} 1134}
722 1135
723enum b43_nphy_rf_sequence { 1136/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */
724 B43_RFSEQ_RX2TX, 1137static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
725 B43_RFSEQ_TX2RX, 1138 u8 *events, u8 *delays, u8 length)
726 B43_RFSEQ_RESET2RX, 1139{
727 B43_RFSEQ_UPDATE_GAINH, 1140 struct b43_phy_n *nphy = dev->phy.n;
728 B43_RFSEQ_UPDATE_GAINL, 1141 u8 i;
729 B43_RFSEQ_UPDATE_GAINU, 1142 u8 end = (dev->phy.rev >= 3) ? 0x1F : 0x0F;
730}; 1143 u16 offset1 = cmd << 4;
1144 u16 offset2 = offset1 + 0x80;
731 1145
1146 if (nphy->hang_avoid)
1147 b43_nphy_stay_in_carrier_search(dev, true);
1148
1149 b43_ntab_write_bulk(dev, B43_NTAB8(7, offset1), length, events);
1150 b43_ntab_write_bulk(dev, B43_NTAB8(7, offset2), length, delays);
1151
1152 for (i = length; i < 16; i++) {
1153 b43_ntab_write(dev, B43_NTAB8(7, offset1 + i), end);
1154 b43_ntab_write(dev, B43_NTAB8(7, offset2 + i), 1);
1155 }
1156
1157 if (nphy->hang_avoid)
1158 b43_nphy_stay_in_carrier_search(dev, false);
1159}
1160
1161/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
732static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, 1162static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
733 enum b43_nphy_rf_sequence seq) 1163 enum b43_nphy_rf_sequence seq)
734{ 1164{
@@ -741,6 +1171,7 @@ static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
741 [B43_RFSEQ_UPDATE_GAINU] = B43_NPHY_RFSEQTR_UPGU, 1171 [B43_RFSEQ_UPDATE_GAINU] = B43_NPHY_RFSEQTR_UPGU,
742 }; 1172 };
743 int i; 1173 int i;
1174 u16 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
744 1175
745 B43_WARN_ON(seq >= ARRAY_SIZE(trigger)); 1176 B43_WARN_ON(seq >= ARRAY_SIZE(trigger));
746 1177
@@ -754,8 +1185,83 @@ static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
754 } 1185 }
755 b43err(dev->wl, "RF sequence status timeout\n"); 1186 b43err(dev->wl, "RF sequence status timeout\n");
756ok: 1187ok:
757 b43_phy_mask(dev, B43_NPHY_RFSEQMODE, 1188 b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
758 ~(B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER)); 1189}
1190
1191/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
1192static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
1193 u16 value, u8 core, bool off)
1194{
1195 int i;
1196 u8 index = fls(field);
1197 u8 addr, en_addr, val_addr;
1198 /* we expect only one bit set */
1199 B43_WARN_ON(field & (~(1 << (index - 1))));
1200
1201 if (dev->phy.rev >= 3) {
1202 const struct nphy_rf_control_override_rev3 *rf_ctrl;
1203 for (i = 0; i < 2; i++) {
1204 if (index == 0 || index == 16) {
1205 b43err(dev->wl,
1206 "Unsupported RF Ctrl Override call\n");
1207 return;
1208 }
1209
1210 rf_ctrl = &tbl_rf_control_override_rev3[index - 1];
1211 en_addr = B43_PHY_N((i == 0) ?
1212 rf_ctrl->en_addr0 : rf_ctrl->en_addr1);
1213 val_addr = B43_PHY_N((i == 0) ?
1214 rf_ctrl->val_addr0 : rf_ctrl->val_addr1);
1215
1216 if (off) {
1217 b43_phy_mask(dev, en_addr, ~(field));
1218 b43_phy_mask(dev, val_addr,
1219 ~(rf_ctrl->val_mask));
1220 } else {
1221 if (core == 0 || ((1 << core) & i) != 0) {
1222 b43_phy_set(dev, en_addr, field);
1223 b43_phy_maskset(dev, val_addr,
1224 ~(rf_ctrl->val_mask),
1225 (value << rf_ctrl->val_shift));
1226 }
1227 }
1228 }
1229 } else {
1230 const struct nphy_rf_control_override_rev2 *rf_ctrl;
1231 if (off) {
1232 b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~(field));
1233 value = 0;
1234 } else {
1235 b43_phy_set(dev, B43_NPHY_RFCTL_OVER, field);
1236 }
1237
1238 for (i = 0; i < 2; i++) {
1239 if (index <= 1 || index == 16) {
1240 b43err(dev->wl,
1241 "Unsupported RF Ctrl Override call\n");
1242 return;
1243 }
1244
1245 if (index == 2 || index == 10 ||
1246 (index >= 13 && index <= 15)) {
1247 core = 1;
1248 }
1249
1250 rf_ctrl = &tbl_rf_control_override_rev2[index - 2];
1251 addr = B43_PHY_N((i == 0) ?
1252 rf_ctrl->addr0 : rf_ctrl->addr1);
1253
1254 if ((core & (1 << i)) != 0)
1255 b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask),
1256 (value << rf_ctrl->shift));
1257
1258 b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1);
1259 b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
1260 B43_NPHY_RFCTL_CMD_START);
1261 udelay(1);
1262 b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 0xFFFE);
1263 }
1264 }
759} 1265}
760 1266
761static void b43_nphy_bphy_init(struct b43_wldev *dev) 1267static void b43_nphy_bphy_init(struct b43_wldev *dev)
@@ -837,66 +1343,151 @@ static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
837 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp); 1343 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
838} 1344}
839 1345
840/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */ 1346static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
841static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
842{ 1347{
843 u16 val; 1348 u16 val;
844 1349
845 if (dev->phy.rev >= 3) { 1350 if (type < 3)
846 /* TODO */ 1351 val = 0;
847 } else { 1352 else if (type == 6)
848 if (type < 3) 1353 val = 1;
849 val = 0; 1354 else if (type == 3)
850 else if (type == 6) 1355 val = 2;
851 val = 1; 1356 else
852 else if (type == 3) 1357 val = 3;
853 val = 2;
854 else
855 val = 3;
856 1358
857 val = (val << 12) | (val << 14); 1359 val = (val << 12) | (val << 14);
858 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val); 1360 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val);
859 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val); 1361 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val);
860 1362
1363 if (type < 3) {
1364 b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF,
1365 (type + 1) << 4);
1366 b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF,
1367 (type + 1) << 4);
1368 }
1369
1370 /* TODO use some definitions */
1371 if (code == 0) {
1372 b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, 0);
1373 if (type < 3) {
1374 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFEC7, 0);
1375 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xEFDC, 0);
1376 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFFFE, 0);
1377 udelay(20);
1378 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xFFFE, 0);
1379 }
1380 } else {
1381 b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF,
1382 0x3000);
861 if (type < 3) { 1383 if (type < 3) {
862 b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF, 1384 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
863 (type + 1) << 4); 1385 0xFEC7, 0x0180);
864 b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF, 1386 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
865 (type + 1) << 4); 1387 0xEFDC, (code << 1 | 0x1021));
1388 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFFFE, 0x1);
1389 udelay(20);
1390 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xFFFE, 0);
866 } 1391 }
1392 }
1393}
1394
1395static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
1396{
1397 struct b43_phy_n *nphy = dev->phy.n;
1398 u8 i;
1399 u16 reg, val;
1400
1401 if (code == 0) {
1402 b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, 0xFDFF);
1403 b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, 0xFDFF);
1404 b43_phy_mask(dev, B43_NPHY_AFECTL_C1, 0xFCFF);
1405 b43_phy_mask(dev, B43_NPHY_AFECTL_C2, 0xFCFF);
1406 b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S0, 0xFFDF);
1407 b43_phy_mask(dev, B43_NPHY_TXF_40CO_B32S1, 0xFFDF);
1408 b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3);
1409 b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3);
1410 } else {
1411 for (i = 0; i < 2; i++) {
1412 if ((code == 1 && i == 1) || (code == 2 && !i))
1413 continue;
1414
1415 reg = (i == 0) ?
1416 B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER;
1417 b43_phy_maskset(dev, reg, 0xFDFF, 0x0200);
867 1418
868 /* TODO use some definitions */
869 if (code == 0) {
870 b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, 0);
871 if (type < 3) {
872 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
873 0xFEC7, 0);
874 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
875 0xEFDC, 0);
876 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
877 0xFFFE, 0);
878 udelay(20);
879 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
880 0xFFFE, 0);
881 }
882 } else {
883 b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF,
884 0x3000);
885 if (type < 3) { 1419 if (type < 3) {
886 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 1420 reg = (i == 0) ?
887 0xFEC7, 0x0180); 1421 B43_NPHY_AFECTL_C1 :
888 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 1422 B43_NPHY_AFECTL_C2;
889 0xEFDC, (code << 1 | 0x1021)); 1423 b43_phy_maskset(dev, reg, 0xFCFF, 0);
890 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 1424
891 0xFFFE, 0x0001); 1425 reg = (i == 0) ?
892 udelay(20); 1426 B43_NPHY_RFCTL_LUT_TRSW_UP1 :
893 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 1427 B43_NPHY_RFCTL_LUT_TRSW_UP2;
894 0xFFFE, 0); 1428 b43_phy_maskset(dev, reg, 0xFFC3, 0);
1429
1430 if (type == 0)
1431 val = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 4 : 8;
1432 else if (type == 1)
1433 val = 16;
1434 else
1435 val = 32;
1436 b43_phy_set(dev, reg, val);
1437
1438 reg = (i == 0) ?
1439 B43_NPHY_TXF_40CO_B1S0 :
1440 B43_NPHY_TXF_40CO_B32S1;
1441 b43_phy_set(dev, reg, 0x0020);
1442 } else {
1443 if (type == 6)
1444 val = 0x0100;
1445 else if (type == 3)
1446 val = 0x0200;
1447 else
1448 val = 0x0300;
1449
1450 reg = (i == 0) ?
1451 B43_NPHY_AFECTL_C1 :
1452 B43_NPHY_AFECTL_C2;
1453
1454 b43_phy_maskset(dev, reg, 0xFCFF, val);
1455 b43_phy_maskset(dev, reg, 0xF3FF, val << 2);
1456
1457 if (type != 3 && type != 6) {
1458 enum ieee80211_band band =
1459 b43_current_band(dev->wl);
1460
1461 if ((nphy->ipa2g_on &&
1462 band == IEEE80211_BAND_2GHZ) ||
1463 (nphy->ipa5g_on &&
1464 band == IEEE80211_BAND_5GHZ))
1465 val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
1466 else
1467 val = 0x11;
1468 reg = (i == 0) ? 0x2000 : 0x3000;
1469 reg |= B2055_PADDRV;
1470 b43_radio_write16(dev, reg, val);
1471
1472 reg = (i == 0) ?
1473 B43_NPHY_AFECTL_OVER1 :
1474 B43_NPHY_AFECTL_OVER;
1475 b43_phy_set(dev, reg, 0x0200);
1476 }
895 } 1477 }
896 } 1478 }
897 } 1479 }
898} 1480}
899 1481
1482/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
1483static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
1484{
1485 if (dev->phy.rev >= 3)
1486 b43_nphy_rev3_rssi_select(dev, code, type);
1487 else
1488 b43_nphy_rev2_rssi_select(dev, code, type);
1489}
1490
900/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */ 1491/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
901static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf) 1492static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf)
902{ 1493{
@@ -1239,9 +1830,60 @@ static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
1239{ 1830{
1240 struct b43_phy_n *nphy = dev->phy.n; 1831 struct b43_phy_n *nphy = dev->phy.n;
1241 u16 *save = nphy->tx_rx_cal_radio_saveregs; 1832 u16 *save = nphy->tx_rx_cal_radio_saveregs;
1833 u16 tmp;
1834 u8 offset, i;
1242 1835
1243 if (dev->phy.rev >= 3) { 1836 if (dev->phy.rev >= 3) {
1244 /* TODO */ 1837 for (i = 0; i < 2; i++) {
1838 tmp = (i == 0) ? 0x2000 : 0x3000;
1839 offset = i * 11;
1840
1841 save[offset + 0] = b43_radio_read16(dev, B2055_CAL_RVARCTL);
1842 save[offset + 1] = b43_radio_read16(dev, B2055_CAL_LPOCTL);
1843 save[offset + 2] = b43_radio_read16(dev, B2055_CAL_TS);
1844 save[offset + 3] = b43_radio_read16(dev, B2055_CAL_RCCALRTS);
1845 save[offset + 4] = b43_radio_read16(dev, B2055_CAL_RCALRTS);
1846 save[offset + 5] = b43_radio_read16(dev, B2055_PADDRV);
1847 save[offset + 6] = b43_radio_read16(dev, B2055_XOCTL1);
1848 save[offset + 7] = b43_radio_read16(dev, B2055_XOCTL2);
1849 save[offset + 8] = b43_radio_read16(dev, B2055_XOREGUL);
1850 save[offset + 9] = b43_radio_read16(dev, B2055_XOMISC);
1851 save[offset + 10] = b43_radio_read16(dev, B2055_PLL_LFC1);
1852
1853 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
1854 b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x0A);
1855 b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
1856 b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
1857 b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
1858 b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
1859 if (nphy->ipa5g_on) {
1860 b43_radio_write16(dev, tmp | B2055_PADDRV, 4);
1861 b43_radio_write16(dev, tmp | B2055_XOCTL1, 1);
1862 } else {
1863 b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
1864 b43_radio_write16(dev, tmp | B2055_XOCTL1, 0x2F);
1865 }
1866 b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
1867 } else {
1868 b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x06);
1869 b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
1870 b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
1871 b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
1872 b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
1873 b43_radio_write16(dev, tmp | B2055_XOCTL1, 0);
1874 if (nphy->ipa2g_on) {
1875 b43_radio_write16(dev, tmp | B2055_PADDRV, 6);
1876 b43_radio_write16(dev, tmp | B2055_XOCTL2,
1877 (dev->phy.rev < 5) ? 0x11 : 0x01);
1878 } else {
1879 b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
1880 b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
1881 }
1882 }
1883 b43_radio_write16(dev, tmp | B2055_XOREGUL, 0);
1884 b43_radio_write16(dev, tmp | B2055_XOMISC, 0);
1885 b43_radio_write16(dev, tmp | B2055_PLL_LFC1, 0);
1886 }
1245 } else { 1887 } else {
1246 save[0] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL1); 1888 save[0] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL1);
1247 b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL1, 0x29); 1889 b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL1, 0x29);
@@ -1330,16 +1972,51 @@ static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core)
1330 for (i = 0; i < 18; i++) { 1972 for (i = 0; i < 18; i++) {
1331 scale = (ladder_lo[i].percent * tmp) / 100; 1973 scale = (ladder_lo[i].percent * tmp) / 100;
1332 entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env; 1974 entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env;
1333 /* TODO: Write an N PHY Table with ID 15, length 1, 1975 b43_ntab_write(dev, B43_NTAB16(15, i), entry);
1334 offset i, width 16, and data entry */
1335 1976
1336 scale = (ladder_iq[i].percent * tmp) / 100; 1977 scale = (ladder_iq[i].percent * tmp) / 100;
1337 entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env; 1978 entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env;
1338 /* TODO: Write an N PHY Table with ID 15, length 1, 1979 b43_ntab_write(dev, B43_NTAB16(15, i + 32), entry);
1339 offset i + 32, width 16, and data entry */
1340 } 1980 }
1341} 1981}
1342 1982
1983/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */
1984static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev)
1985{
1986 int i;
1987 for (i = 0; i < 15; i++)
1988 b43_phy_write(dev, B43_PHY_N(0x2C5 + i),
1989 tbl_tx_filter_coef_rev4[2][i]);
1990}
1991
1992/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */
1993static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev)
1994{
1995 int i, j;
1996 /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */
1997 u16 offset[] = { 0x186, 0x195, 0x2C5 };
1998
1999 for (i = 0; i < 3; i++)
2000 for (j = 0; j < 15; j++)
2001 b43_phy_write(dev, B43_PHY_N(offset[i] + j),
2002 tbl_tx_filter_coef_rev4[i][j]);
2003
2004 if (dev->phy.is_40mhz) {
2005 for (j = 0; j < 15; j++)
2006 b43_phy_write(dev, B43_PHY_N(offset[0] + j),
2007 tbl_tx_filter_coef_rev4[3][j]);
2008 } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
2009 for (j = 0; j < 15; j++)
2010 b43_phy_write(dev, B43_PHY_N(offset[0] + j),
2011 tbl_tx_filter_coef_rev4[5][j]);
2012 }
2013
2014 if (dev->phy.channel == 14)
2015 for (j = 0; j < 15; j++)
2016 b43_phy_write(dev, B43_PHY_N(offset[0] + j),
2017 tbl_tx_filter_coef_rev4[6][j]);
2018}
2019
1343/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ 2020/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
1344static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) 2021static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
1345{ 2022{
@@ -1354,8 +2031,7 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
1354 2031
1355 if (nphy->hang_avoid) 2032 if (nphy->hang_avoid)
1356 b43_nphy_stay_in_carrier_search(dev, true); 2033 b43_nphy_stay_in_carrier_search(dev, true);
1357 /* TODO: Read an N PHY Table with ID 7, length 2, 2034 b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, curr_gain);
1358 offset 0x110, width 16, and curr_gain */
1359 if (nphy->hang_avoid) 2035 if (nphy->hang_avoid)
1360 b43_nphy_stay_in_carrier_search(dev, false); 2036 b43_nphy_stay_in_carrier_search(dev, false);
1361 2037
@@ -1423,6 +2099,101 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
1423 return target; 2099 return target;
1424} 2100}
1425 2101
2102/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */
2103static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev)
2104{
2105 u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
2106
2107 if (dev->phy.rev >= 3) {
2108 b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[0]);
2109 b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
2110 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
2111 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[3]);
2112 b43_phy_write(dev, B43_NPHY_BBCFG, regs[4]);
2113 b43_ntab_write(dev, B43_NTAB16(8, 3), regs[5]);
2114 b43_ntab_write(dev, B43_NTAB16(8, 19), regs[6]);
2115 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[7]);
2116 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[8]);
2117 b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
2118 b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
2119 b43_nphy_reset_cca(dev);
2120 } else {
2121 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, regs[0]);
2122 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, regs[1]);
2123 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
2124 b43_ntab_write(dev, B43_NTAB16(8, 2), regs[3]);
2125 b43_ntab_write(dev, B43_NTAB16(8, 18), regs[4]);
2126 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[5]);
2127 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[6]);
2128 }
2129}
2130
2131/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */
2132static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
2133{
2134 u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
2135 u16 tmp;
2136
2137 regs[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
2138 regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
2139 if (dev->phy.rev >= 3) {
2140 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0xF0FF, 0x0A00);
2141 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0xF0FF, 0x0A00);
2142
2143 tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
2144 regs[2] = tmp;
2145 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, tmp | 0x0600);
2146
2147 tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
2148 regs[3] = tmp;
2149 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600);
2150
2151 regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG);
2152 b43_phy_mask(dev, B43_NPHY_BBCFG, (u16)~B43_NPHY_BBCFG_RSTRX);
2153
2154 tmp = b43_ntab_read(dev, B43_NTAB16(8, 3));
2155 regs[5] = tmp;
2156 b43_ntab_write(dev, B43_NTAB16(8, 3), 0);
2157
2158 tmp = b43_ntab_read(dev, B43_NTAB16(8, 19));
2159 regs[6] = tmp;
2160 b43_ntab_write(dev, B43_NTAB16(8, 19), 0);
2161 regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
2162 regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
2163
2164 /* TODO: Call N PHY RF Ctrl Intc Override with 2, 1, 3 */
2165 /* TODO: Call N PHY RF Ctrl Intc Override with 1, 2, 1 */
2166 /* TODO: Call N PHY RF Ctrl Intc Override with 1, 8, 2 */
2167
2168 regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
2169 regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
2170 b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
2171 b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
2172 } else {
2173 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000);
2174 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000);
2175 tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
2176 regs[2] = tmp;
2177 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x3000);
2178 tmp = b43_ntab_read(dev, B43_NTAB16(8, 2));
2179 regs[3] = tmp;
2180 tmp |= 0x2000;
2181 b43_ntab_write(dev, B43_NTAB16(8, 2), tmp);
2182 tmp = b43_ntab_read(dev, B43_NTAB16(8, 18));
2183 regs[4] = tmp;
2184 tmp |= 0x2000;
2185 b43_ntab_write(dev, B43_NTAB16(8, 18), tmp);
2186 regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
2187 regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
2188 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
2189 tmp = 0x0180;
2190 else
2191 tmp = 0x0120;
2192 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
2193 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
2194 }
2195}
2196
1426/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */ 2197/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */
1427static void b43_nphy_restore_cal(struct b43_wldev *dev) 2198static void b43_nphy_restore_cal(struct b43_wldev *dev)
1428{ 2199{
@@ -1448,8 +2219,7 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev)
1448 loft = &nphy->cal_cache.txcal_coeffs_5G[5]; 2219 loft = &nphy->cal_cache.txcal_coeffs_5G[5];
1449 } 2220 }
1450 2221
1451 /* TODO: Write an N PHY table with ID 15, length 4, offset 80, 2222 b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, table);
1452 width 16, and data from table */
1453 2223
1454 for (i = 0; i < 4; i++) { 2224 for (i = 0; i < 4; i++) {
1455 if (dev->phy.rev >= 3) 2225 if (dev->phy.rev >= 3)
@@ -1458,12 +2228,9 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev)
1458 coef[i] = 0; 2228 coef[i] = 0;
1459 } 2229 }
1460 2230
1461 /* TODO: Write an N PHY table with ID 15, length 4, offset 88, 2231 b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, coef);
1462 width 16, and data from coef */ 2232 b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, loft);
1463 /* TODO: Write an N PHY table with ID 15, length 2, offset 85, 2233 b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, loft);
1464 width 16 and data from loft */
1465 /* TODO: Write an N PHY table with ID 15, length 2, offset 93,
1466 width 16 and data from loft */
1467 2234
1468 if (dev->phy.rev < 2) 2235 if (dev->phy.rev < 2)
1469 b43_nphy_tx_iq_workaround(dev); 2236 b43_nphy_tx_iq_workaround(dev);
@@ -1524,39 +2291,47 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
1524 nphy->hang_avoid = 0; 2291 nphy->hang_avoid = 0;
1525 } 2292 }
1526 2293
1527 /* TODO: Read an N PHY Table with ID 7, length 2, offset 0x110, 2294 b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
1528 width 16, and data pointer save */
1529 2295
1530 for (i = 0; i < 2; i++) { 2296 for (i = 0; i < 2; i++) {
1531 b43_nphy_iq_cal_gain_params(dev, i, target, &params[i]); 2297 b43_nphy_iq_cal_gain_params(dev, i, target, &params[i]);
1532 gain[i] = params[i].cal_gain; 2298 gain[i] = params[i].cal_gain;
1533 } 2299 }
1534 /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, 2300
1535 width 16, and data pointer gain */ 2301 b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain);
1536 2302
1537 b43_nphy_tx_cal_radio_setup(dev); 2303 b43_nphy_tx_cal_radio_setup(dev);
1538 /* TODO: Call N PHY TX Cal PHY Setup */ 2304 b43_nphy_tx_cal_phy_setup(dev);
1539 2305
1540 phy6or5x = dev->phy.rev >= 6 || 2306 phy6or5x = dev->phy.rev >= 6 ||
1541 (dev->phy.rev == 5 && nphy->ipa2g_on && 2307 (dev->phy.rev == 5 && nphy->ipa2g_on &&
1542 b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ); 2308 b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ);
1543 if (phy6or5x) { 2309 if (phy6or5x) {
1544 /* TODO */ 2310 if (dev->phy.is_40mhz) {
2311 b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
2312 tbl_tx_iqlo_cal_loft_ladder_40);
2313 b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
2314 tbl_tx_iqlo_cal_iqimb_ladder_40);
2315 } else {
2316 b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
2317 tbl_tx_iqlo_cal_loft_ladder_20);
2318 b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
2319 tbl_tx_iqlo_cal_iqimb_ladder_20);
2320 }
1545 } 2321 }
1546 2322
1547 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9); 2323 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9);
1548 2324
1549 if (1 /* FIXME: the band width is 20 MHz */) 2325 if (!dev->phy.is_40mhz)
1550 freq = 2500; 2326 freq = 2500;
1551 else 2327 else
1552 freq = 5000; 2328 freq = 5000;
1553 2329
1554 if (nphy->mphase_cal_phase_id > 2) 2330 if (nphy->mphase_cal_phase_id > 2)
1555 ;/* TODO: Call N PHY Run Samples with (band width * 8), 2331 b43_nphy_run_samples(dev, (dev->phy.is_40mhz ? 40 : 20) * 8,
1556 0xFFFF, 0, 1, 0 as arguments */ 2332 0xFFFF, 0, true, false);
1557 else 2333 else
1558 ;/* TODO: Call N PHY TX Tone with freq, 250, 1, 0 as arguments 2334 error = b43_nphy_tx_tone(dev, freq, 250, true, false);
1559 and save result as error */
1560 2335
1561 if (error == 0) { 2336 if (error == 0) {
1562 if (nphy->mphase_cal_phase_id > 2) { 2337 if (nphy->mphase_cal_phase_id > 2) {
@@ -1582,8 +2357,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
1582 } 2357 }
1583 } 2358 }
1584 2359
1585 /* TODO: Write an N PHY Table with ID 15, length from above, 2360 b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, table);
1586 offset 64, width 16, and the data pointer from above */
1587 2361
1588 if (full) { 2362 if (full) {
1589 if (dev->phy.rev >= 3) 2363 if (dev->phy.rev >= 3)
@@ -1631,14 +2405,12 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
1631 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp); 2405 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp);
1632 2406
1633 if (type == 1 || type == 3 || type == 4) { 2407 if (type == 1 || type == 3 || type == 4) {
1634 /* TODO: Read an N PHY Table with ID 15, 2408 buffer[0] = b43_ntab_read(dev,
1635 length 1, offset 69 + core, 2409 B43_NTAB16(15, 69 + core));
1636 width 16, and data pointer buffer */
1637 diq_start = buffer[0]; 2410 diq_start = buffer[0];
1638 buffer[0] = 0; 2411 buffer[0] = 0;
1639 /* TODO: Write an N PHY Table with ID 15, 2412 b43_ntab_write(dev, B43_NTAB16(15, 69 + core),
1640 length 1, offset 69 + core, width 16, 2413 0);
1641 and data of 0 */
1642 } 2414 }
1643 2415
1644 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd); 2416 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd);
@@ -1649,12 +2421,10 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
1649 udelay(10); 2421 udelay(10);
1650 } 2422 }
1651 2423
1652 /* TODO: Read an N PHY Table with ID 15, 2424 b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
1653 length table_length, offset 96, width 16, 2425 buffer);
1654 and data pointer buffer */ 2426 b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length,
1655 /* TODO: Write an N PHY Table with ID 15, 2427 buffer);
1656 length table_length, offset 64, width 16,
1657 and data pointer buffer */
1658 2428
1659 if (type == 1 || type == 3 || type == 4) 2429 if (type == 1 || type == 3 || type == 4)
1660 buffer[0] = diq_start; 2430 buffer[0] = diq_start;
@@ -1666,30 +2436,27 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
1666 last = (dev->phy.rev < 3) ? 6 : 7; 2436 last = (dev->phy.rev < 3) ? 6 : 7;
1667 2437
1668 if (!mphase || nphy->mphase_cal_phase_id == last) { 2438 if (!mphase || nphy->mphase_cal_phase_id == last) {
1669 /* TODO: Write an N PHY Table with ID 15, length 4, 2439 b43_ntab_write_bulk(dev, B43_NTAB16(15, 96), 4, buffer);
1670 offset 96, width 16, and data pointer buffer */ 2440 b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 4, buffer);
1671 /* TODO: Read an N PHY Table with ID 15, length 4,
1672 offset 80, width 16, and data pointer buffer */
1673 if (dev->phy.rev < 3) { 2441 if (dev->phy.rev < 3) {
1674 buffer[0] = 0; 2442 buffer[0] = 0;
1675 buffer[1] = 0; 2443 buffer[1] = 0;
1676 buffer[2] = 0; 2444 buffer[2] = 0;
1677 buffer[3] = 0; 2445 buffer[3] = 0;
1678 } 2446 }
1679 /* TODO: Write an N PHY Table with ID 15, length 4, 2447 b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
1680 offset 88, width 16, and data pointer buffer */ 2448 buffer);
1681 /* TODO: Read an N PHY Table with ID 15, length 2, 2449 b43_ntab_write_bulk(dev, B43_NTAB16(15, 101), 2,
1682 offset 101, width 16, and data pointer buffer*/ 2450 buffer);
1683 /* TODO: Write an N PHY Table with ID 15, length 2, 2451 b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
1684 offset 85, width 16, and data pointer buffer */ 2452 buffer);
1685 /* TODO: Write an N PHY Table with ID 15, length 2, 2453 b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
1686 offset 93, width 16, and data pointer buffer */ 2454 buffer);
1687 length = 11; 2455 length = 11;
1688 if (dev->phy.rev < 3) 2456 if (dev->phy.rev < 3)
1689 length -= 2; 2457 length -= 2;
1690 /* TODO: Read an N PHY Table with ID 15, length length, 2458 b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
1691 offset 96, width 16, and data pointer 2459 nphy->txiqlocal_bestc);
1692 nphy->txiqlocal_bestc */
1693 nphy->txiqlocal_coeffsvalid = true; 2460 nphy->txiqlocal_coeffsvalid = true;
1694 /* TODO: Set nphy->txiqlocal_chanspec to 2461 /* TODO: Set nphy->txiqlocal_chanspec to
1695 the current channel */ 2462 the current channel */
@@ -1697,18 +2464,16 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
1697 length = 11; 2464 length = 11;
1698 if (dev->phy.rev < 3) 2465 if (dev->phy.rev < 3)
1699 length -= 2; 2466 length -= 2;
1700 /* TODO: Read an N PHY Table with ID 5, length length, 2467 b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
1701 offset 96, width 16, and data pointer 2468 nphy->mphase_txcal_bestcoeffs);
1702 nphy->mphase_txcal_bestcoeffs */
1703 } 2469 }
1704 2470
1705 /* TODO: Call N PHY Stop Playback */ 2471 b43_nphy_stop_playback(dev);
1706 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0); 2472 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0);
1707 } 2473 }
1708 2474
1709 /* TODO: Call N PHY TX Cal PHY Cleanup */ 2475 b43_nphy_tx_cal_phy_cleanup(dev);
1710 /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, 2476 b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
1711 width 16, and data from save */
1712 2477
1713 if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last)) 2478 if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last))
1714 b43_nphy_tx_iq_workaround(dev); 2479 b43_nphy_tx_iq_workaround(dev);
@@ -1739,7 +2504,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
1739 u16 lna[3] = { 3, 3, 1 }; 2504 u16 lna[3] = { 3, 3, 1 };
1740 u16 hpf1[3] = { 7, 2, 0 }; 2505 u16 hpf1[3] = { 7, 2, 0 };
1741 u16 hpf2[3] = { 2, 0, 0 }; 2506 u16 hpf2[3] = { 2, 0, 0 };
1742 u32 power[3]; 2507 u32 power[3] = { };
1743 u16 gain_save[2]; 2508 u16 gain_save[2];
1744 u16 cal_gain[2]; 2509 u16 cal_gain[2];
1745 struct nphy_iqcal_params cal_params[2]; 2510 struct nphy_iqcal_params cal_params[2];
@@ -1752,14 +2517,12 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
1752 2517
1753 if (dev->phy.rev < 2) 2518 if (dev->phy.rev < 2)
1754 ;/* TODO: Call N PHY Reapply TX Cal Coeffs */ 2519 ;/* TODO: Call N PHY Reapply TX Cal Coeffs */
1755 /* TODO: Read an N PHY Table with ID 7, length 2, offset 0x110, 2520 b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
1756 width 16, and data gain_save */
1757 for (i = 0; i < 2; i++) { 2521 for (i = 0; i < 2; i++) {
1758 b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]); 2522 b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]);
1759 cal_gain[i] = cal_params[i].cal_gain; 2523 cal_gain[i] = cal_params[i].cal_gain;
1760 } 2524 }
1761 /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, 2525 b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, cal_gain);
1762 width 16, and data from cal_gain */
1763 2526
1764 for (i = 0; i < 2; i++) { 2527 for (i = 0; i < 2; i++) {
1765 if (i == 0) { 2528 if (i == 0) {
@@ -1846,19 +2609,19 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
1846 2609
1847 tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) | 2610 tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) |
1848 (cur_lna << 2)); 2611 (cur_lna << 2));
1849 /* TODO:Call N PHY RF Ctrl Override with 0x400, tmp[0], 2612 b43_nphy_rf_control_override(dev, 0x400, tmp[0], 3,
1850 3, 0 as arguments */ 2613 false);
1851 /* TODO: Call N PHY Force RF Seq with 2 as argument */ 2614 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
1852 /* TODO: Call N PHT Stop Playback */ 2615 b43_nphy_stop_playback(dev);
1853 2616
1854 if (playtone) { 2617 if (playtone) {
1855 /* TODO: Call N PHY TX Tone with 4000, 2618 ret = b43_nphy_tx_tone(dev, 4000,
1856 (nphy_rxcalparams & 0xffff), 0, 0 2619 (nphy->rxcalparams & 0xFFFF),
1857 as arguments and save result as ret */ 2620 false, false);
1858 playtone = false; 2621 playtone = false;
1859 } else { 2622 } else {
1860 /* TODO: Call N PHY Run Samples with 160, 2623 b43_nphy_run_samples(dev, 160, 0xFFFF, 0,
1861 0xFFFF, 0, 0, 0 as arguments */ 2624 false, false);
1862 } 2625 }
1863 2626
1864 if (ret == 0) { 2627 if (ret == 0) {
@@ -1876,7 +2639,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
1876 } else { 2639 } else {
1877 b43_nphy_calc_rx_iq_comp(dev, 1 << i); 2640 b43_nphy_calc_rx_iq_comp(dev, 1 << i);
1878 } 2641 }
1879 /* TODO: Call N PHY Stop Playback */ 2642 b43_nphy_stop_playback(dev);
1880 } 2643 }
1881 2644
1882 if (ret != 0) 2645 if (ret != 0)
@@ -1895,10 +2658,9 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
1895 break; 2658 break;
1896 } 2659 }
1897 2660
1898 /* TODO: Call N PHY RF Ctrl Override with 0x400, 0, 3, 1 as arguments*/ 2661 b43_nphy_rf_control_override(dev, 0x400, 0, 3, true);
1899 /* TODO: Call N PHY Force RF Seq with 2 as argument */ 2662 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
1900 /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, 2663 b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
1901 width 16, and data from gain_save */
1902 2664
1903 b43_nphy_stay_in_carrier_search(dev, 0); 2665 b43_nphy_stay_in_carrier_search(dev, 0);
1904 2666
@@ -1990,8 +2752,8 @@ int b43_phy_initn(struct b43_wldev *dev)
1990 b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50); 2752 b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50);
1991 b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30); 2753 b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30);
1992 2754
1993 /* TODO MIMO-Config */ 2755 b43_nphy_update_mimo_config(dev, nphy->preamble_override);
1994 /* TODO Update TX/RX chain */ 2756 b43_nphy_update_txrx_chain(dev);
1995 2757
1996 if (phy->rev < 2) { 2758 if (phy->rev < 2) {
1997 b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8); 2759 b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8);
@@ -2007,9 +2769,9 @@ int b43_phy_initn(struct b43_wldev *dev)
2007 b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1); 2769 b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1);
2008 b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F, 2770 b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F,
2009 nphy->papd_epsilon_offset[1] << 7); 2771 nphy->papd_epsilon_offset[1] << 7);
2010 /* TODO N PHY IPA Set TX Dig Filters */ 2772 b43_nphy_int_pa_set_tx_dig_filters(dev);
2011 } else if (phy->rev >= 5) { 2773 } else if (phy->rev >= 5) {
2012 /* TODO N PHY Ext PA Set TX Dig Filters */ 2774 b43_nphy_ext_pa_set_tx_dig_filters(dev);
2013 } 2775 }
2014 2776
2015 b43_nphy_workarounds(dev); 2777 b43_nphy_workarounds(dev);
@@ -2040,8 +2802,10 @@ int b43_phy_initn(struct b43_wldev *dev)
2040 if (phy->rev >= 3) { 2802 if (phy->rev >= 3) {
2041 /* TODO */ 2803 /* TODO */
2042 } else { 2804 } else {
2043 /* TODO Write an N PHY table with ID 26, length 128, offset 192, width 32, and the data from Rev 2 TX Power Control Table */ 2805 b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128,
2044 /* TODO Write an N PHY table with ID 27, length 128, offset 192, width 32, and the data from Rev 2 TX Power Control Table */ 2806 b43_ntab_tx_gain_rev0_1_2);
2807 b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128,
2808 b43_ntab_tx_gain_rev0_1_2);
2045 } 2809 }
2046 2810
2047 if (nphy->phyrxchain != 3) 2811 if (nphy->phyrxchain != 3)
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h
index 4572866756fc..ae82f0fc2096 100644
--- a/drivers/net/wireless/b43/phy_n.h
+++ b/drivers/net/wireless/b43/phy_n.h
@@ -973,6 +973,12 @@ struct b43_phy_n {
973 bool hang_avoid; 973 bool hang_avoid;
974 bool mute; 974 bool mute;
975 u16 papd_epsilon_offset[2]; 975 u16 papd_epsilon_offset[2];
976 s32 preamble_override;
977 u32 bb_mult_save;
978
979 bool gain_boost;
980 bool elna_gain_config;
981 bool band5g_pwrgain;
976 982
977 u8 mphase_cal_phase_id; 983 u8 mphase_cal_phase_id;
978 u16 mphase_txcal_cmdidx; 984 u16 mphase_txcal_cmdidx;
@@ -985,6 +991,7 @@ struct b43_phy_n {
985 bool txiqlocal_coeffsvalid; 991 bool txiqlocal_coeffsvalid;
986 struct b43_phy_n_txpwrindex txpwrindex[2]; 992 struct b43_phy_n_txpwrindex txpwrindex[2];
987 993
994 u8 txrx_chain;
988 u16 tx_rx_cal_phy_saveregs[11]; 995 u16 tx_rx_cal_phy_saveregs[11];
989 u16 tx_rx_cal_radio_saveregs[22]; 996 u16 tx_rx_cal_radio_saveregs[22];
990 997
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index 7dff853ab962..a00d509150f7 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -2883,6 +2883,67 @@ const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = {
2883 0x9084, 0x9267, 0x9056, 0x9234 2883 0x9084, 0x9267, 0x9056, 0x9234
2884}; 2884};
2885 2885
2886const s16 tbl_tx_filter_coef_rev4[7][15] = {
2887 { -377, 137, -407, 208, -1527,
2888 956, 93, 186, 93, 230,
2889 -44, 230, 20, -191, 201 },
2890 { -77, 20, -98, 49, -93,
2891 60, 56, 111, 56, 26,
2892 -5, 26, 34, -32, 34 },
2893 { -360, 164, -376, 164, -1533,
2894 576, 308, -314, 308, 121,
2895 -73, 121, 91, 124, 91 },
2896 { -295, 200, -363, 142, -1391,
2897 826, 151, 301, 151, 151,
2898 301, 151, 602, -752, 602 },
2899 { -92, 58, -96, 49, -104,
2900 44, 17, 35, 17, 12,
2901 25, 12, 13, 27, 13 },
2902 { -375, 136, -399, 209, -1479,
2903 949, 130, 260, 130, 230,
2904 -44, 230, 201, -191, 201 },
2905 { 0xed9, 0xc8, 0xe95, 0x8e, 0xa91,
2906 0x33a, 0x97, 0x12d, 0x97, 0x97,
2907 0x12d, 0x97, 0x25a, 0xd10, 0x25a }
2908};
2909
2910/* addr0, addr1, bmask, shift */
2911const struct nphy_rf_control_override_rev2 tbl_rf_control_override_rev2[] = {
2912 { 0x78, 0x78, 0x0038, 3 }, /* for field == 0x0002 (fls == 2) */
2913 { 0x7A, 0x7D, 0x0001, 0 }, /* for field == 0x0004 (fls == 3) */
2914 { 0x7A, 0x7D, 0x0002, 1 }, /* for field == 0x0008 (fls == 4) */
2915 { 0x7A, 0x7D, 0x0004, 2 }, /* for field == 0x0010 (fls == 5) */
2916 { 0x7A, 0x7D, 0x0030, 4 }, /* for field == 0x0020 (fls == 6) */
2917 { 0x7A, 0x7D, 0x00C0, 6 }, /* for field == 0x0040 (fls == 7) */
2918 { 0x7A, 0x7D, 0x0100, 8 }, /* for field == 0x0080 (fls == 8) */
2919 { 0x7A, 0x7D, 0x0200, 9 }, /* for field == 0x0100 (fls == 9) */
2920 { 0x78, 0x78, 0x0004, 2 }, /* for field == 0x0200 (fls == 10) */
2921 { 0x7B, 0x7E, 0x01FF, 0 }, /* for field == 0x0400 (fls == 11) */
2922 { 0x7C, 0x7F, 0x01FF, 0 }, /* for field == 0x0800 (fls == 12) */
2923 { 0x78, 0x78, 0x0100, 8 }, /* for field == 0x1000 (fls == 13) */
2924 { 0x78, 0x78, 0x0200, 9 }, /* for field == 0x2000 (fls == 14) */
2925 { 0x78, 0x78, 0xF000, 12 } /* for field == 0x4000 (fls == 15) */
2926};
2927
2928/* val_mask, val_shift, en_addr0, val_addr0, en_addr1, val_addr1 */
2929const struct nphy_rf_control_override_rev3 tbl_rf_control_override_rev3[] = {
2930 { 0x8000, 15, 0xE5, 0xF9, 0xE6, 0xFB }, /* field == 0x0001 (fls 1) */
2931 { 0x0001, 0, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0002 (fls 2) */
2932 { 0x0002, 1, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0004 (fls 3) */
2933 { 0x0004, 2, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0008 (fls 4) */
2934 { 0x0016, 4, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0010 (fls 5) */
2935 { 0x0020, 5, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0020 (fls 6) */
2936 { 0x0040, 6, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0040 (fls 7) */
2937 { 0x0080, 6, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0080 (fls 8) */
2938 { 0x0100, 7, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0100 (fls 9) */
2939 { 0x0007, 0, 0xE7, 0xF8, 0xEC, 0xFA }, /* field == 0x0200 (fls 10) */
2940 { 0x0070, 4, 0xE7, 0xF8, 0xEC, 0xFA }, /* field == 0x0400 (fls 11) */
2941 { 0xE000, 13, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0800 (fls 12) */
2942 { 0xFFFF, 0, 0xE7, 0x7B, 0xEC, 0x7E }, /* field == 0x1000 (fls 13) */
2943 { 0xFFFF, 0, 0xE7, 0x7C, 0xEC, 0x7F }, /* field == 0x2000 (fls 14) */
2944 { 0x00C0, 6, 0xE7, 0xF9, 0xEC, 0xFB } /* field == 0x4000 (fls 15) */
2945};
2946
2886static inline void assert_ntab_array_sizes(void) 2947static inline void assert_ntab_array_sizes(void)
2887{ 2948{
2888#undef check 2949#undef check
@@ -2919,6 +2980,72 @@ static inline void assert_ntab_array_sizes(void)
2919#undef check 2980#undef check
2920} 2981}
2921 2982
2983u32 b43_ntab_read(struct b43_wldev *dev, u32 offset)
2984{
2985 u32 type, value;
2986
2987 type = offset & B43_NTAB_TYPEMASK;
2988 offset &= ~B43_NTAB_TYPEMASK;
2989 B43_WARN_ON(offset > 0xFFFF);
2990
2991 switch (type) {
2992 case B43_NTAB_8BIT:
2993 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
2994 value = b43_phy_read(dev, B43_NPHY_TABLE_DATALO) & 0xFF;
2995 break;
2996 case B43_NTAB_16BIT:
2997 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
2998 value = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
2999 break;
3000 case B43_NTAB_32BIT:
3001 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
3002 value = b43_phy_read(dev, B43_NPHY_TABLE_DATAHI);
3003 value <<= 16;
3004 value |= b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
3005 break;
3006 default:
3007 B43_WARN_ON(1);
3008 value = 0;
3009 }
3010
3011 return value;
3012}
3013
3014void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset,
3015 unsigned int nr_elements, void *_data)
3016{
3017 u32 type;
3018 u8 *data = _data;
3019 unsigned int i;
3020
3021 type = offset & B43_NTAB_TYPEMASK;
3022 offset &= ~B43_NTAB_TYPEMASK;
3023 B43_WARN_ON(offset > 0xFFFF);
3024
3025 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
3026
3027 for (i = 0; i < nr_elements; i++) {
3028 switch (type) {
3029 case B43_NTAB_8BIT:
3030 *data = b43_phy_read(dev, B43_NPHY_TABLE_DATALO) & 0xFF;
3031 data++;
3032 break;
3033 case B43_NTAB_16BIT:
3034 *((u16 *)data) = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
3035 data += 2;
3036 break;
3037 case B43_NTAB_32BIT:
3038 *((u32 *)data) = b43_phy_read(dev, B43_NPHY_TABLE_DATAHI);
3039 *((u32 *)data) <<= 16;
3040 *((u32 *)data) |= b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
3041 data += 4;
3042 break;
3043 default:
3044 B43_WARN_ON(1);
3045 }
3046 }
3047}
3048
2922void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value) 3049void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value)
2923{ 3050{
2924 u32 type; 3051 u32 type;
@@ -2952,6 +3079,46 @@ void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value)
2952 assert_ntab_array_sizes(); 3079 assert_ntab_array_sizes();
2953} 3080}
2954 3081
3082void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
3083 unsigned int nr_elements, const void *_data)
3084{
3085 u32 type, value;
3086 const u8 *data = _data;
3087 unsigned int i;
3088
3089 type = offset & B43_NTAB_TYPEMASK;
3090 offset &= ~B43_NTAB_TYPEMASK;
3091 B43_WARN_ON(offset > 0xFFFF);
3092
3093 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
3094
3095 for (i = 0; i < nr_elements; i++) {
3096 switch (type) {
3097 case B43_NTAB_8BIT:
3098 value = *data;
3099 data++;
3100 B43_WARN_ON(value & ~0xFF);
3101 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value);
3102 break;
3103 case B43_NTAB_16BIT:
3104 value = *((u16 *)data);
3105 data += 2;
3106 B43_WARN_ON(value & ~0xFFFF);
3107 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value);
3108 break;
3109 case B43_NTAB_32BIT:
3110 value = *((u32 *)data);
3111 data += 4;
3112 b43_phy_write(dev, B43_NPHY_TABLE_DATAHI, value >> 16);
3113 b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
3114 value & 0xFFFF);
3115 break;
3116 default:
3117 B43_WARN_ON(1);
3118 }
3119 }
3120}
3121
2955#define ntab_upload(dev, offset, data) do { \ 3122#define ntab_upload(dev, offset, data) do { \
2956 unsigned int i; \ 3123 unsigned int i; \
2957 for (i = 0; i < (offset##_SIZE); i++) \ 3124 for (i = 0; i < (offset##_SIZE); i++) \
diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h
index 51636d02f8b1..9c1c6ecd3672 100644
--- a/drivers/net/wireless/b43/tables_nphy.h
+++ b/drivers/net/wireless/b43/tables_nphy.h
@@ -51,6 +51,22 @@ struct nphy_txiqcal_ladder {
51 u8 g_env; 51 u8 g_env;
52}; 52};
53 53
54struct nphy_rf_control_override_rev2 {
55 u8 addr0;
56 u8 addr1;
57 u16 bmask;
58 u8 shift;
59};
60
61struct nphy_rf_control_override_rev3 {
62 u16 val_mask;
63 u8 val_shift;
64 u8 en_addr0;
65 u8 val_addr0;
66 u8 en_addr1;
67 u8 val_addr1;
68};
69
54/* Upload the default register value table. 70/* Upload the default register value table.
55 * If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz 71 * If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz
56 * table is uploaded. If "ignore_uploadflag" is true, we upload any value 72 * table is uploaded. If "ignore_uploadflag" is true, we upload any value
@@ -142,7 +158,12 @@ b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel);
142#define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL 10 158#define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL 10
143#define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3 12 159#define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3 12
144 160
161u32 b43_ntab_read(struct b43_wldev *dev, u32 offset);
162void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset,
163 unsigned int nr_elements, void *_data);
145void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value); 164void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value);
165void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
166 unsigned int nr_elements, const void *_data);
146 167
147void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev); 168void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev);
148void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev); 169void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev);
@@ -172,5 +193,11 @@ extern const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[];
172extern const u16 tbl_tx_iqlo_cal_cmds_recal[]; 193extern const u16 tbl_tx_iqlo_cal_cmds_recal[];
173extern const u16 tbl_tx_iqlo_cal_cmds_fullcal[]; 194extern const u16 tbl_tx_iqlo_cal_cmds_fullcal[];
174extern const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[]; 195extern const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[];
196extern const s16 tbl_tx_filter_coef_rev4[7][15];
197
198extern const struct nphy_rf_control_override_rev2
199 tbl_rf_control_override_rev2[];
200extern const struct nphy_rf_control_override_rev3
201 tbl_rf_control_override_rev3[];
175 202
176#endif /* B43_TABLES_NPHY_H_ */ 203#endif /* B43_TABLES_NPHY_H_ */
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index b16b06c2031f..dc8ed1527666 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -1,14 +1,8 @@
1config IWLWIFI 1config IWLWIFI
2 tristate "Intel Wireless Wifi" 2 tristate "Intel Wireless Wifi"
3 depends on PCI && MAC80211 && EXPERIMENTAL 3 depends on PCI && MAC80211
4 select FW_LOADER 4 select FW_LOADER
5 5
6config IWLWIFI_SPECTRUM_MEASUREMENT
7 bool "Enable Spectrum Measurement in iwlagn driver"
8 depends on IWLWIFI
9 ---help---
10 This option will enable spectrum measurement for the iwlagn driver.
11
12config IWLWIFI_DEBUG 6config IWLWIFI_DEBUG
13 bool "Enable full debugging output in iwlagn and iwl3945 drivers" 7 bool "Enable full debugging output in iwlagn and iwl3945 drivers"
14 depends on IWLWIFI 8 depends on IWLWIFI
@@ -120,9 +114,3 @@ config IWL3945
120 inserted in and removed from the running kernel whenever you want), 114 inserted in and removed from the running kernel whenever you want),
121 say M here and read <file:Documentation/kbuild/modules.txt>. The 115 say M here and read <file:Documentation/kbuild/modules.txt>. The
122 module will be called iwl3945. 116 module will be called iwl3945.
123
124config IWL3945_SPECTRUM_MEASUREMENT
125 bool "Enable Spectrum Measurement in iwl3945 driver"
126 depends on IWL3945
127 ---help---
128 This option will enable spectrum measurement for the iwl3945 driver.
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 7f82044af242..4e378faee650 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -3,7 +3,6 @@ iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
3iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o 3iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o
4iwlcore-objs += iwl-scan.o iwl-led.o 4iwlcore-objs += iwl-scan.o iwl-led.o
5iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o 5iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
6iwlcore-$(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) += iwl-spectrum.o
7iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o 6iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
8 7
9CFLAGS_iwl-devtrace.o := -I$(src) 8CFLAGS_iwl-devtrace.o := -I$(src)
@@ -20,3 +19,5 @@ iwlagn-$(CONFIG_IWL5000) += iwl-1000.o
20# 3945 19# 3945
21obj-$(CONFIG_IWL3945) += iwl3945.o 20obj-$(CONFIG_IWL3945) += iwl3945.o
22iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o 21iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o
22
23ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 0db1fda94a65..9d1820676f30 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2008-2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
@@ -89,8 +89,78 @@ static void iwl1000_nic_config(struct iwl_priv *priv)
89 ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); 89 ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK);
90} 90}
91 91
92static struct iwl_sensitivity_ranges iwl1000_sensitivity = {
93 .min_nrg_cck = 95,
94 .max_nrg_cck = 0, /* not used, set to 0 */
95 .auto_corr_min_ofdm = 90,
96 .auto_corr_min_ofdm_mrc = 170,
97 .auto_corr_min_ofdm_x1 = 120,
98 .auto_corr_min_ofdm_mrc_x1 = 240,
99
100 .auto_corr_max_ofdm = 120,
101 .auto_corr_max_ofdm_mrc = 210,
102 .auto_corr_max_ofdm_x1 = 155,
103 .auto_corr_max_ofdm_mrc_x1 = 290,
104
105 .auto_corr_min_cck = 125,
106 .auto_corr_max_cck = 200,
107 .auto_corr_min_cck_mrc = 170,
108 .auto_corr_max_cck_mrc = 400,
109 .nrg_th_cck = 95,
110 .nrg_th_ofdm = 95,
111
112 .barker_corr_th_min = 190,
113 .barker_corr_th_min_mrc = 390,
114 .nrg_th_cca = 62,
115};
116
117static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
118{
119 if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
120 priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES)
121 priv->cfg->num_of_queues =
122 priv->cfg->mod_params->num_of_queues;
123
124 priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
125 priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
126 priv->hw_params.scd_bc_tbls_size =
127 priv->cfg->num_of_queues *
128 sizeof(struct iwl5000_scd_bc_tbl);
129 priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
130 priv->hw_params.max_stations = IWL5000_STATION_COUNT;
131 priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
132
133 priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE;
134 priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE;
135
136 priv->hw_params.max_bsm_size = 0;
137 priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
138 BIT(IEEE80211_BAND_5GHZ);
139 priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
140
141 priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
142 priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
143 priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
144 priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
145
146 if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
147 priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
148
149 /* Set initial sensitivity parameters */
150 /* Set initial calibration set */
151 priv->hw_params.sens = &iwl1000_sensitivity;
152 priv->hw_params.calib_init_cfg =
153 BIT(IWL_CALIB_XTAL) |
154 BIT(IWL_CALIB_LO) |
155 BIT(IWL_CALIB_TX_IQ) |
156 BIT(IWL_CALIB_TX_IQ_PERD) |
157 BIT(IWL_CALIB_BASE_BAND);
158
159 return 0;
160}
161
92static struct iwl_lib_ops iwl1000_lib = { 162static struct iwl_lib_ops iwl1000_lib = {
93 .set_hw_params = iwl5000_hw_set_hw_params, 163 .set_hw_params = iwl1000_hw_set_hw_params,
94 .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, 164 .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
95 .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, 165 .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
96 .txq_set_sched = iwl5000_txq_set_sched, 166 .txq_set_sched = iwl5000_txq_set_sched,
@@ -106,6 +176,7 @@ static struct iwl_lib_ops iwl1000_lib = {
106 .dump_nic_event_log = iwl_dump_nic_event_log, 176 .dump_nic_event_log = iwl_dump_nic_event_log,
107 .dump_nic_error_log = iwl_dump_nic_error_log, 177 .dump_nic_error_log = iwl_dump_nic_error_log,
108 .dump_csr = iwl_dump_csr, 178 .dump_csr = iwl_dump_csr,
179 .dump_fh = iwl_dump_fh,
109 .init_alive_start = iwl5000_init_alive_start, 180 .init_alive_start = iwl5000_init_alive_start,
110 .alive_notify = iwl5000_alive_notify, 181 .alive_notify = iwl5000_alive_notify,
111 .send_tx_power = iwl5000_send_tx_power, 182 .send_tx_power = iwl5000_send_tx_power,
@@ -139,6 +210,7 @@ static struct iwl_lib_ops iwl1000_lib = {
139 .temperature = iwl5000_temperature, 210 .temperature = iwl5000_temperature,
140 .set_ct_kill = iwl1000_set_ct_threshold, 211 .set_ct_kill = iwl1000_set_ct_threshold,
141 }, 212 },
213 .add_bcast_station = iwl_add_bcast_station,
142}; 214};
143 215
144static const struct iwl_ops iwl1000_ops = { 216static const struct iwl_ops iwl1000_ops = {
@@ -174,6 +246,7 @@ struct iwl_cfg iwl1000_bgn_cfg = {
174 .use_rts_for_ht = true, /* use rts/cts protection */ 246 .use_rts_for_ht = true, /* use rts/cts protection */
175 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, 247 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
176 .support_ct_kill_exit = true, 248 .support_ct_kill_exit = true,
249 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
177}; 250};
178 251
179struct iwl_cfg iwl1000_bg_cfg = { 252struct iwl_cfg iwl1000_bg_cfg = {
@@ -200,6 +273,7 @@ struct iwl_cfg iwl1000_bg_cfg = {
200 .led_compensation = 51, 273 .led_compensation = 51,
201 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, 274 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
202 .support_ct_kill_exit = true, 275 .support_ct_kill_exit = true,
276 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
203}; 277};
204 278
205MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); 279MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h
index 08ce259a0e60..042f6bc0df13 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h
@@ -5,7 +5,7 @@
5 * 5 *
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 8 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as 11 * it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
30 * 30 *
31 * BSD LICENSE 31 * BSD LICENSE
32 * 32 *
33 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 33 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
index 6fd10d443ba3..3a876a8ece38 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
@@ -5,7 +5,7 @@
5 * 5 *
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 8 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as 11 * it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
30 * 30 *
31 * BSD LICENSE 31 * BSD LICENSE
32 * 32 *
33 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 33 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
index a871d09d598f..abe2b739c4dc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h
index 5a1033ca7aaa..ce990adc51e7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index d4b49883b30e..47909f94271e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 6cde661ce0bc..6940f086823c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
@@ -1951,11 +1951,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
1951 } 1951 }
1952 1952
1953 /* Add the broadcast address so we can send broadcast frames */ 1953 /* Add the broadcast address so we can send broadcast frames */
1954 if (iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL) == 1954 priv->cfg->ops->lib->add_bcast_station(priv);
1955 IWL_INVALID_STATION) {
1956 IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n");
1957 return -EIO;
1958 }
1959 1955
1960 /* If we have set the ASSOC_MSK and we are in BSS mode then 1956 /* If we have set the ASSOC_MSK and we are in BSS mode then
1961 * add the IWL_AP_ID to the station rate table */ 1957 * add the IWL_AP_ID to the station rate table */
@@ -2796,6 +2792,7 @@ static struct iwl_lib_ops iwl3945_lib = {
2796 .post_associate = iwl3945_post_associate, 2792 .post_associate = iwl3945_post_associate,
2797 .isr = iwl_isr_legacy, 2793 .isr = iwl_isr_legacy,
2798 .config_ap = iwl3945_config_ap, 2794 .config_ap = iwl3945_config_ap,
2795 .add_bcast_station = iwl3945_add_bcast_station,
2799}; 2796};
2800 2797
2801static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { 2798static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
@@ -2830,6 +2827,7 @@ static struct iwl_cfg iwl3945_bg_cfg = {
2830 .ht_greenfield_support = false, 2827 .ht_greenfield_support = false,
2831 .led_compensation = 64, 2828 .led_compensation = 64,
2832 .broken_powersave = true, 2829 .broken_powersave = true,
2830 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
2833}; 2831};
2834 2832
2835static struct iwl_cfg iwl3945_abg_cfg = { 2833static struct iwl_cfg iwl3945_abg_cfg = {
@@ -2847,6 +2845,7 @@ static struct iwl_cfg iwl3945_abg_cfg = {
2847 .ht_greenfield_support = false, 2845 .ht_greenfield_support = false,
2848 .led_compensation = 64, 2846 .led_compensation = 64,
2849 .broken_powersave = true, 2847 .broken_powersave = true,
2848 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
2850}; 2849};
2851 2850
2852DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { 2851DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index bc532ff4f883..8f553f36d270 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
index c606366b582c..67ef562e8db1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
@@ -5,7 +5,7 @@
5 * 5 *
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 8 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as 11 * it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
30 * 30 *
31 * BSD LICENSE 31 * BSD LICENSE
32 * 32 *
33 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 33 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 6a004abb5973..aebe8c51d3e1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
@@ -2206,6 +2206,7 @@ static struct iwl_lib_ops iwl4965_lib = {
2206 .temperature = iwl4965_temperature_calib, 2206 .temperature = iwl4965_temperature_calib,
2207 .set_ct_kill = iwl4965_set_ct_threshold, 2207 .set_ct_kill = iwl4965_set_ct_threshold,
2208 }, 2208 },
2209 .add_bcast_station = iwl_add_bcast_station,
2209}; 2210};
2210 2211
2211static const struct iwl_ops iwl4965_ops = { 2212static const struct iwl_ops iwl4965_ops = {
@@ -2239,6 +2240,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
2239 .broken_powersave = true, 2240 .broken_powersave = true,
2240 .led_compensation = 61, 2241 .led_compensation = 61,
2241 .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, 2242 .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
2243 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
2242}; 2244};
2243 2245
2244/* Module firmware */ 2246/* Module firmware */
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
index bc056e9ab85f..714e032f6217 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
@@ -5,7 +5,7 @@
5 * 5 *
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. 8 * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as 11 * it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
30 * 30 *
31 * BSD LICENSE 31 * BSD LICENSE
32 * 32 *
33 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 33 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index c6120f0b8f98..6d5988901341 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
@@ -263,8 +263,8 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
263 263
264 .auto_corr_max_ofdm = 120, 264 .auto_corr_max_ofdm = 120,
265 .auto_corr_max_ofdm_mrc = 210, 265 .auto_corr_max_ofdm_mrc = 210,
266 .auto_corr_max_ofdm_x1 = 155, 266 .auto_corr_max_ofdm_x1 = 120,
267 .auto_corr_max_ofdm_mrc_x1 = 290, 267 .auto_corr_max_ofdm_mrc_x1 = 240,
268 268
269 .auto_corr_min_cck = 125, 269 .auto_corr_min_cck = 125,
270 .auto_corr_max_cck = 200, 270 .auto_corr_max_cck = 200,
@@ -412,12 +412,14 @@ static void iwl5000_rx_calib_complete(struct iwl_priv *priv,
412/* 412/*
413 * ucode 413 * ucode
414 */ 414 */
415static int iwl5000_load_section(struct iwl_priv *priv, 415static int iwl5000_load_section(struct iwl_priv *priv, const char *name,
416 struct fw_desc *image, 416 struct fw_desc *image, u32 dst_addr)
417 u32 dst_addr)
418{ 417{
419 dma_addr_t phy_addr = image->p_addr; 418 dma_addr_t phy_addr = image->p_addr;
420 u32 byte_cnt = image->len; 419 u32 byte_cnt = image->len;
420 int ret;
421
422 priv->ucode_write_complete = 0;
421 423
422 iwl_write_direct32(priv, 424 iwl_write_direct32(priv,
423 FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), 425 FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
@@ -447,57 +449,36 @@ static int iwl5000_load_section(struct iwl_priv *priv,
447 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | 449 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE |
448 FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); 450 FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
449 451
450 return 0; 452 IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name);
451}
452
453static int iwl5000_load_given_ucode(struct iwl_priv *priv,
454 struct fw_desc *inst_image,
455 struct fw_desc *data_image)
456{
457 int ret = 0;
458
459 ret = iwl5000_load_section(priv, inst_image,
460 IWL50_RTC_INST_LOWER_BOUND);
461 if (ret)
462 return ret;
463
464 IWL_DEBUG_INFO(priv, "INST uCode section being loaded...\n");
465 ret = wait_event_interruptible_timeout(priv->wait_command_queue, 453 ret = wait_event_interruptible_timeout(priv->wait_command_queue,
466 priv->ucode_write_complete, 5 * HZ); 454 priv->ucode_write_complete, 5 * HZ);
467 if (ret == -ERESTARTSYS) { 455 if (ret == -ERESTARTSYS) {
468 IWL_ERR(priv, "Could not load the INST uCode section due " 456 IWL_ERR(priv, "Could not load the %s uCode section due "
469 "to interrupt\n"); 457 "to interrupt\n", name);
470 return ret; 458 return ret;
471 } 459 }
472 if (!ret) { 460 if (!ret) {
473 IWL_ERR(priv, "Could not load the INST uCode section\n"); 461 IWL_ERR(priv, "Could not load the %s uCode section\n",
462 name);
474 return -ETIMEDOUT; 463 return -ETIMEDOUT;
475 } 464 }
476 465
477 priv->ucode_write_complete = 0; 466 return 0;
478 467}
479 ret = iwl5000_load_section(
480 priv, data_image, IWL50_RTC_DATA_LOWER_BOUND);
481 if (ret)
482 return ret;
483 468
484 IWL_DEBUG_INFO(priv, "DATA uCode section being loaded...\n"); 469static int iwl5000_load_given_ucode(struct iwl_priv *priv,
470 struct fw_desc *inst_image,
471 struct fw_desc *data_image)
472{
473 int ret = 0;
485 474
486 ret = wait_event_interruptible_timeout(priv->wait_command_queue, 475 ret = iwl5000_load_section(priv, "INST", inst_image,
487 priv->ucode_write_complete, 5 * HZ); 476 IWL50_RTC_INST_LOWER_BOUND);
488 if (ret == -ERESTARTSYS) { 477 if (ret)
489 IWL_ERR(priv, "Could not load the INST uCode section due "
490 "to interrupt\n");
491 return ret; 478 return ret;
492 } else if (!ret) {
493 IWL_ERR(priv, "Could not load the DATA uCode section\n");
494 return -ETIMEDOUT;
495 } else
496 ret = 0;
497
498 priv->ucode_write_complete = 0;
499 479
500 return ret; 480 return iwl5000_load_section(priv, "DATA", data_image,
481 IWL50_RTC_DATA_LOWER_BOUND);
501} 482}
502 483
503int iwl5000_load_ucode(struct iwl_priv *priv) 484int iwl5000_load_ucode(struct iwl_priv *priv)
@@ -1467,6 +1448,7 @@ struct iwl_lib_ops iwl5000_lib = {
1467 .dump_nic_event_log = iwl_dump_nic_event_log, 1448 .dump_nic_event_log = iwl_dump_nic_event_log,
1468 .dump_nic_error_log = iwl_dump_nic_error_log, 1449 .dump_nic_error_log = iwl_dump_nic_error_log,
1469 .dump_csr = iwl_dump_csr, 1450 .dump_csr = iwl_dump_csr,
1451 .dump_fh = iwl_dump_fh,
1470 .load_ucode = iwl5000_load_ucode, 1452 .load_ucode = iwl5000_load_ucode,
1471 .init_alive_start = iwl5000_init_alive_start, 1453 .init_alive_start = iwl5000_init_alive_start,
1472 .alive_notify = iwl5000_alive_notify, 1454 .alive_notify = iwl5000_alive_notify,
@@ -1502,6 +1484,7 @@ struct iwl_lib_ops iwl5000_lib = {
1502 .temperature = iwl5000_temperature, 1484 .temperature = iwl5000_temperature,
1503 .set_ct_kill = iwl5000_set_ct_threshold, 1485 .set_ct_kill = iwl5000_set_ct_threshold,
1504 }, 1486 },
1487 .add_bcast_station = iwl_add_bcast_station,
1505}; 1488};
1506 1489
1507static struct iwl_lib_ops iwl5150_lib = { 1490static struct iwl_lib_ops iwl5150_lib = {
@@ -1555,6 +1538,7 @@ static struct iwl_lib_ops iwl5150_lib = {
1555 .temperature = iwl5150_temperature, 1538 .temperature = iwl5150_temperature,
1556 .set_ct_kill = iwl5150_set_ct_threshold, 1539 .set_ct_kill = iwl5150_set_ct_threshold,
1557 }, 1540 },
1541 .add_bcast_station = iwl_add_bcast_station,
1558}; 1542};
1559 1543
1560static const struct iwl_ops iwl5000_ops = { 1544static const struct iwl_ops iwl5000_ops = {
@@ -1602,6 +1586,7 @@ struct iwl_cfg iwl5300_agn_cfg = {
1602 .led_compensation = 51, 1586 .led_compensation = 51,
1603 .use_rts_for_ht = true, /* use rts/cts protection */ 1587 .use_rts_for_ht = true, /* use rts/cts protection */
1604 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, 1588 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
1589 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
1605}; 1590};
1606 1591
1607struct iwl_cfg iwl5100_bgn_cfg = { 1592struct iwl_cfg iwl5100_bgn_cfg = {
@@ -1626,6 +1611,7 @@ struct iwl_cfg iwl5100_bgn_cfg = {
1626 .led_compensation = 51, 1611 .led_compensation = 51,
1627 .use_rts_for_ht = true, /* use rts/cts protection */ 1612 .use_rts_for_ht = true, /* use rts/cts protection */
1628 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, 1613 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
1614 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
1629}; 1615};
1630 1616
1631struct iwl_cfg iwl5100_abg_cfg = { 1617struct iwl_cfg iwl5100_abg_cfg = {
@@ -1648,6 +1634,7 @@ struct iwl_cfg iwl5100_abg_cfg = {
1648 .use_bsm = false, 1634 .use_bsm = false,
1649 .led_compensation = 51, 1635 .led_compensation = 51,
1650 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, 1636 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
1637 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
1651}; 1638};
1652 1639
1653struct iwl_cfg iwl5100_agn_cfg = { 1640struct iwl_cfg iwl5100_agn_cfg = {
@@ -1672,6 +1659,7 @@ struct iwl_cfg iwl5100_agn_cfg = {
1672 .led_compensation = 51, 1659 .led_compensation = 51,
1673 .use_rts_for_ht = true, /* use rts/cts protection */ 1660 .use_rts_for_ht = true, /* use rts/cts protection */
1674 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, 1661 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
1662 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
1675}; 1663};
1676 1664
1677struct iwl_cfg iwl5350_agn_cfg = { 1665struct iwl_cfg iwl5350_agn_cfg = {
@@ -1696,6 +1684,7 @@ struct iwl_cfg iwl5350_agn_cfg = {
1696 .led_compensation = 51, 1684 .led_compensation = 51,
1697 .use_rts_for_ht = true, /* use rts/cts protection */ 1685 .use_rts_for_ht = true, /* use rts/cts protection */
1698 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, 1686 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
1687 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
1699}; 1688};
1700 1689
1701struct iwl_cfg iwl5150_agn_cfg = { 1690struct iwl_cfg iwl5150_agn_cfg = {
@@ -1720,6 +1709,7 @@ struct iwl_cfg iwl5150_agn_cfg = {
1720 .led_compensation = 51, 1709 .led_compensation = 51,
1721 .use_rts_for_ht = true, /* use rts/cts protection */ 1710 .use_rts_for_ht = true, /* use rts/cts protection */
1722 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, 1711 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
1712 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
1723}; 1713};
1724 1714
1725struct iwl_cfg iwl5150_abg_cfg = { 1715struct iwl_cfg iwl5150_abg_cfg = {
@@ -1742,6 +1732,7 @@ struct iwl_cfg iwl5150_abg_cfg = {
1742 .use_bsm = false, 1732 .use_bsm = false,
1743 .led_compensation = 51, 1733 .led_compensation = 51,
1744 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, 1734 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
1735 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
1745}; 1736};
1746 1737
1747MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); 1738MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h
index 90185777d98b..ddba39999997 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h
@@ -5,7 +5,7 @@
5 * 5 *
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. 8 * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as 11 * it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
30 * 30 *
31 * BSD LICENSE 31 * BSD LICENSE
32 * 32 *
33 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 33 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index a5a0ed4817a4..a9f8551e0e40 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2008-2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
@@ -108,7 +108,7 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
108 108
109 .auto_corr_max_ofdm = 145, 109 .auto_corr_max_ofdm = 145,
110 .auto_corr_max_ofdm_mrc = 232, 110 .auto_corr_max_ofdm_mrc = 232,
111 .auto_corr_max_ofdm_x1 = 145, 111 .auto_corr_max_ofdm_x1 = 110,
112 .auto_corr_max_ofdm_mrc_x1 = 232, 112 .auto_corr_max_ofdm_mrc_x1 = 232,
113 113
114 .auto_corr_min_cck = 125, 114 .auto_corr_min_cck = 125,
@@ -158,11 +158,25 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
158 /* Set initial sensitivity parameters */ 158 /* Set initial sensitivity parameters */
159 /* Set initial calibration set */ 159 /* Set initial calibration set */
160 priv->hw_params.sens = &iwl6000_sensitivity; 160 priv->hw_params.sens = &iwl6000_sensitivity;
161 priv->hw_params.calib_init_cfg = 161 switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
162 case CSR_HW_REV_TYPE_6x50:
163 priv->hw_params.calib_init_cfg =
162 BIT(IWL_CALIB_XTAL) | 164 BIT(IWL_CALIB_XTAL) |
165 BIT(IWL_CALIB_DC) |
163 BIT(IWL_CALIB_LO) | 166 BIT(IWL_CALIB_LO) |
164 BIT(IWL_CALIB_TX_IQ) | 167 BIT(IWL_CALIB_TX_IQ) |
165 BIT(IWL_CALIB_BASE_BAND); 168 BIT(IWL_CALIB_BASE_BAND);
169
170 break;
171 default:
172 priv->hw_params.calib_init_cfg =
173 BIT(IWL_CALIB_XTAL) |
174 BIT(IWL_CALIB_LO) |
175 BIT(IWL_CALIB_TX_IQ) |
176 BIT(IWL_CALIB_BASE_BAND);
177 break;
178 }
179
166 return 0; 180 return 0;
167} 181}
168 182
@@ -216,6 +230,7 @@ static struct iwl_lib_ops iwl6000_lib = {
216 .dump_nic_event_log = iwl_dump_nic_event_log, 230 .dump_nic_event_log = iwl_dump_nic_event_log,
217 .dump_nic_error_log = iwl_dump_nic_error_log, 231 .dump_nic_error_log = iwl_dump_nic_error_log,
218 .dump_csr = iwl_dump_csr, 232 .dump_csr = iwl_dump_csr,
233 .dump_fh = iwl_dump_fh,
219 .init_alive_start = iwl5000_init_alive_start, 234 .init_alive_start = iwl5000_init_alive_start,
220 .alive_notify = iwl5000_alive_notify, 235 .alive_notify = iwl5000_alive_notify,
221 .send_tx_power = iwl5000_send_tx_power, 236 .send_tx_power = iwl5000_send_tx_power,
@@ -251,6 +266,7 @@ static struct iwl_lib_ops iwl6000_lib = {
251 .temperature = iwl5000_temperature, 266 .temperature = iwl5000_temperature,
252 .set_ct_kill = iwl6000_set_ct_threshold, 267 .set_ct_kill = iwl6000_set_ct_threshold,
253 }, 268 },
269 .add_bcast_station = iwl_add_bcast_station,
254}; 270};
255 271
256static const struct iwl_ops iwl6000_ops = { 272static const struct iwl_ops iwl6000_ops = {
@@ -307,6 +323,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
307 .supports_idle = true, 323 .supports_idle = true,
308 .adv_thermal_throttle = true, 324 .adv_thermal_throttle = true,
309 .support_ct_kill_exit = true, 325 .support_ct_kill_exit = true,
326 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
310}; 327};
311 328
312struct iwl_cfg iwl6000i_2abg_cfg = { 329struct iwl_cfg iwl6000i_2abg_cfg = {
@@ -336,6 +353,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = {
336 .supports_idle = true, 353 .supports_idle = true,
337 .adv_thermal_throttle = true, 354 .adv_thermal_throttle = true,
338 .support_ct_kill_exit = true, 355 .support_ct_kill_exit = true,
356 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
339}; 357};
340 358
341struct iwl_cfg iwl6000i_2bg_cfg = { 359struct iwl_cfg iwl6000i_2bg_cfg = {
@@ -365,6 +383,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
365 .supports_idle = true, 383 .supports_idle = true,
366 .adv_thermal_throttle = true, 384 .adv_thermal_throttle = true,
367 .support_ct_kill_exit = true, 385 .support_ct_kill_exit = true,
386 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
368}; 387};
369 388
370struct iwl_cfg iwl6050_2agn_cfg = { 389struct iwl_cfg iwl6050_2agn_cfg = {
@@ -395,6 +414,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
395 .supports_idle = true, 414 .supports_idle = true,
396 .adv_thermal_throttle = true, 415 .adv_thermal_throttle = true,
397 .support_ct_kill_exit = true, 416 .support_ct_kill_exit = true,
417 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
398}; 418};
399 419
400struct iwl_cfg iwl6050_2abg_cfg = { 420struct iwl_cfg iwl6050_2abg_cfg = {
@@ -424,6 +444,7 @@ struct iwl_cfg iwl6050_2abg_cfg = {
424 .supports_idle = true, 444 .supports_idle = true,
425 .adv_thermal_throttle = true, 445 .adv_thermal_throttle = true,
426 .support_ct_kill_exit = true, 446 .support_ct_kill_exit = true,
447 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
427}; 448};
428 449
429struct iwl_cfg iwl6000_3agn_cfg = { 450struct iwl_cfg iwl6000_3agn_cfg = {
@@ -454,6 +475,7 @@ struct iwl_cfg iwl6000_3agn_cfg = {
454 .supports_idle = true, 475 .supports_idle = true,
455 .adv_thermal_throttle = true, 476 .adv_thermal_throttle = true,
456 .support_ct_kill_exit = true, 477 .support_ct_kill_exit = true,
478 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
457}; 479};
458 480
459MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); 481MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.c b/drivers/net/wireless/iwlwifi/iwl-agn-led.c
index 3bccba20f6da..1a24946bc203 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-led.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.h b/drivers/net/wireless/iwlwifi/iwl-agn-led.h
index ab55f92a161d..a594e4fdc6b8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-led.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-led.h
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index b93e49158196..6aebcedaca8d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
index affc0c5a2f2c..e71923961e69 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
@@ -191,7 +191,7 @@ enum {
191 IWL_RATE_2M_MASK) 191 IWL_RATE_2M_MASK)
192 192
193#define IWL_CCK_RATES_MASK \ 193#define IWL_CCK_RATES_MASK \
194 (IWL_BASIC_RATES_MASK | \ 194 (IWL_CCK_BASIC_RATES_MASK | \
195 IWL_RATE_5M_MASK | \ 195 IWL_RATE_5M_MASK | \
196 IWL_RATE_11M_MASK) 196 IWL_RATE_11M_MASK)
197 197
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 344e99de4cab..d0268280d679 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * Portions of this file are derived from the ipw3945 project, as well 5 * Portions of this file are derived from the ipw3945 project, as well
6 * as portions of the ieee80211 subsystem header files. 6 * as portions of the ieee80211 subsystem header files.
@@ -73,13 +73,7 @@
73#define VD 73#define VD
74#endif 74#endif
75 75
76#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT 76#define DRV_VERSION IWLWIFI_VERSION VD
77#define VS "s"
78#else
79#define VS
80#endif
81
82#define DRV_VERSION IWLWIFI_VERSION VD VS
83 77
84 78
85MODULE_DESCRIPTION(DRV_DESCRIPTION); 79MODULE_DESCRIPTION(DRV_DESCRIPTION);
@@ -203,7 +197,8 @@ int iwl_commit_rxon(struct iwl_priv *priv)
203 priv->start_calib = 0; 197 priv->start_calib = 0;
204 198
205 /* Add the broadcast address so we can send broadcast frames */ 199 /* Add the broadcast address so we can send broadcast frames */
206 iwl_add_bcast_station(priv); 200 priv->cfg->ops->lib->add_bcast_station(priv);
201
207 202
208 /* If we have set the ASSOC_MSK and we are in BSS mode then 203 /* If we have set the ASSOC_MSK and we are in BSS mode then
209 * add the IWL_AP_ID to the station rate table */ 204 * add the IWL_AP_ID to the station rate table */
@@ -704,7 +699,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
704 spin_unlock_irqrestore(&priv->reg_lock, reg_flags); 699 spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
705} 700}
706 701
707void iwl_continuous_event_trace(struct iwl_priv *priv) 702static void iwl_continuous_event_trace(struct iwl_priv *priv)
708{ 703{
709 u32 capacity; /* event log capacity in # entries */ 704 u32 capacity; /* event log capacity in # entries */
710 u32 base; /* SRAM byte address of event log header */ 705 u32 base; /* SRAM byte address of event log header */
@@ -888,6 +883,8 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv)
888 priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive; 883 priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
889 priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; 884 priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
890 priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; 885 priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
886 priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
887 iwl_rx_spectrum_measure_notif;
891 priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; 888 priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
892 priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = 889 priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
893 iwl_rx_pm_debug_statistics_notif; 890 iwl_rx_pm_debug_statistics_notif;
@@ -901,7 +898,6 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv)
901 priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_reply_statistics; 898 priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_reply_statistics;
902 priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; 899 priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
903 900
904 iwl_setup_spectrum_handlers(priv);
905 iwl_setup_rx_scan_handlers(priv); 901 iwl_setup_rx_scan_handlers(priv);
906 902
907 /* status change handler */ 903 /* status change handler */
@@ -1761,7 +1757,7 @@ static const char *desc_lookup_text[] = {
1761 "DEBUG_1", 1757 "DEBUG_1",
1762 "DEBUG_2", 1758 "DEBUG_2",
1763 "DEBUG_3", 1759 "DEBUG_3",
1764 "UNKNOWN" 1760 "ADVANCED SYSASSERT"
1765}; 1761};
1766 1762
1767static const char *desc_lookup(int i) 1763static const char *desc_lookup(int i)
@@ -1965,7 +1961,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
1965 IWL_ERR(priv, 1961 IWL_ERR(priv,
1966 "Invalid event log pointer 0x%08X for %s uCode\n", 1962 "Invalid event log pointer 0x%08X for %s uCode\n",
1967 base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); 1963 base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
1968 return pos; 1964 return -EINVAL;
1969 } 1965 }
1970 1966
1971 /* event log header */ 1967 /* event log header */
@@ -2013,7 +2009,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
2013 bufsz = size * 48; 2009 bufsz = size * 48;
2014 *buf = kmalloc(bufsz, GFP_KERNEL); 2010 *buf = kmalloc(bufsz, GFP_KERNEL);
2015 if (!*buf) 2011 if (!*buf)
2016 return pos; 2012 return -ENOMEM;
2017 } 2013 }
2018 if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { 2014 if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
2019 /* 2015 /*
@@ -2443,18 +2439,6 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
2443 return; 2439 return;
2444} 2440}
2445 2441
2446static void iwl_bg_up(struct work_struct *data)
2447{
2448 struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
2449
2450 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
2451 return;
2452
2453 mutex_lock(&priv->mutex);
2454 __iwl_up(priv);
2455 mutex_unlock(&priv->mutex);
2456}
2457
2458static void iwl_bg_restart(struct work_struct *data) 2442static void iwl_bg_restart(struct work_struct *data)
2459{ 2443{
2460 struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); 2444 struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
@@ -2471,7 +2455,13 @@ static void iwl_bg_restart(struct work_struct *data)
2471 ieee80211_restart_hw(priv->hw); 2455 ieee80211_restart_hw(priv->hw);
2472 } else { 2456 } else {
2473 iwl_down(priv); 2457 iwl_down(priv);
2474 queue_work(priv->workqueue, &priv->up); 2458
2459 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
2460 return;
2461
2462 mutex_lock(&priv->mutex);
2463 __iwl_up(priv);
2464 mutex_unlock(&priv->mutex);
2475 } 2465 }
2476} 2466}
2477 2467
@@ -2607,7 +2597,7 @@ void iwl_post_associate(struct iwl_priv *priv)
2607 * Not a mac80211 entry point function, but it fits in with all the 2597 * Not a mac80211 entry point function, but it fits in with all the
2608 * other mac80211 functions grouped here. 2598 * other mac80211 functions grouped here.
2609 */ 2599 */
2610static int iwl_setup_mac(struct iwl_priv *priv) 2600static int iwl_mac_setup_register(struct iwl_priv *priv)
2611{ 2601{
2612 int ret; 2602 int ret;
2613 struct ieee80211_hw *hw = priv->hw; 2603 struct ieee80211_hw *hw = priv->hw;
@@ -2839,14 +2829,18 @@ void iwl_config_ap(struct iwl_priv *priv)
2839} 2829}
2840 2830
2841static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, 2831static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
2842 struct ieee80211_key_conf *keyconf, const u8 *addr, 2832 struct ieee80211_vif *vif,
2843 u32 iv32, u16 *phase1key) 2833 struct ieee80211_key_conf *keyconf,
2834 struct ieee80211_sta *sta,
2835 u32 iv32, u16 *phase1key)
2844{ 2836{
2845 2837
2846 struct iwl_priv *priv = hw->priv; 2838 struct iwl_priv *priv = hw->priv;
2847 IWL_DEBUG_MAC80211(priv, "enter\n"); 2839 IWL_DEBUG_MAC80211(priv, "enter\n");
2848 2840
2849 iwl_update_tkip_key(priv, keyconf, addr, iv32, phase1key); 2841 iwl_update_tkip_key(priv, keyconf,
2842 sta ? sta->addr : iwl_bcast_addr,
2843 iv32, phase1key);
2850 2844
2851 IWL_DEBUG_MAC80211(priv, "leave\n"); 2845 IWL_DEBUG_MAC80211(priv, "leave\n");
2852} 2846}
@@ -3007,6 +3001,8 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw,
3007 break; 3001 break;
3008 case STA_NOTIFY_AWAKE: 3002 case STA_NOTIFY_AWAKE:
3009 WARN_ON(!sta_priv->client); 3003 WARN_ON(!sta_priv->client);
3004 if (!sta_priv->asleep)
3005 break;
3010 sta_priv->asleep = false; 3006 sta_priv->asleep = false;
3011 sta_id = iwl_find_station(priv, sta->addr); 3007 sta_id = iwl_find_station(priv, sta->addr);
3012 if (sta_id != IWL_INVALID_STATION) 3008 if (sta_id != IWL_INVALID_STATION)
@@ -3283,7 +3279,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
3283 3279
3284 init_waitqueue_head(&priv->wait_command_queue); 3280 init_waitqueue_head(&priv->wait_command_queue);
3285 3281
3286 INIT_WORK(&priv->up, iwl_bg_up);
3287 INIT_WORK(&priv->restart, iwl_bg_restart); 3282 INIT_WORK(&priv->restart, iwl_bg_restart);
3288 INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); 3283 INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
3289 INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); 3284 INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
@@ -3368,6 +3363,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
3368 3363
3369 priv->iw_mode = NL80211_IFTYPE_STATION; 3364 priv->iw_mode = NL80211_IFTYPE_STATION;
3370 priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; 3365 priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
3366 priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
3371 3367
3372 /* Choose which receivers/antennas to use */ 3368 /* Choose which receivers/antennas to use */
3373 if (priv->cfg->ops->hcmd->set_rxon_chain) 3369 if (priv->cfg->ops->hcmd->set_rxon_chain)
@@ -3619,9 +3615,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3619 iwl_setup_deferred_work(priv); 3615 iwl_setup_deferred_work(priv);
3620 iwl_setup_rx_handlers(priv); 3616 iwl_setup_rx_handlers(priv);
3621 3617
3622 /********************************** 3618 /*********************************************
3623 * 8. Setup and register mac80211 3619 * 8. Enable interrupts and read RFKILL state
3624 **********************************/ 3620 *********************************************/
3625 3621
3626 /* enable interrupts if needed: hw bug w/a */ 3622 /* enable interrupts if needed: hw bug w/a */
3627 pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); 3623 pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
@@ -3632,14 +3628,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3632 3628
3633 iwl_enable_interrupts(priv); 3629 iwl_enable_interrupts(priv);
3634 3630
3635 err = iwl_setup_mac(priv);
3636 if (err)
3637 goto out_remove_sysfs;
3638
3639 err = iwl_dbgfs_register(priv, DRV_NAME);
3640 if (err)
3641 IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
3642
3643 /* If platform's RF_KILL switch is NOT set to KILL */ 3631 /* If platform's RF_KILL switch is NOT set to KILL */
3644 if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) 3632 if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
3645 clear_bit(STATUS_RF_KILL_HW, &priv->status); 3633 clear_bit(STATUS_RF_KILL_HW, &priv->status);
@@ -3651,6 +3639,18 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3651 3639
3652 iwl_power_initialize(priv); 3640 iwl_power_initialize(priv);
3653 iwl_tt_initialize(priv); 3641 iwl_tt_initialize(priv);
3642
3643 /**************************************************
3644 * 9. Setup and register with mac80211 and debugfs
3645 **************************************************/
3646 err = iwl_mac_setup_register(priv);
3647 if (err)
3648 goto out_remove_sysfs;
3649
3650 err = iwl_dbgfs_register(priv, DRV_NAME);
3651 if (err)
3652 IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
3653
3654 return 0; 3654 return 0;
3655 3655
3656 out_remove_sysfs: 3656 out_remove_sysfs:
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index dc61906290e8..845831ac053e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -5,7 +5,7 @@
5 * 5 *
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. 8 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as 11 * it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
30 * 30 *
31 * BSD LICENSE 31 * BSD LICENSE
32 * 32 *
33 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 33 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-calib.h
index b6cef989a796..2b7b1df83ba0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.h
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.h
@@ -5,7 +5,7 @@
5 * 5 *
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. 8 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as 11 * it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
30 * 30 *
31 * BSD LICENSE 31 * BSD LICENSE
32 * 32 *
33 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 33 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 3320cce3d57b..c2f31eb26bef 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -5,7 +5,7 @@
5 * 5 *
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 8 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as 11 * it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
30 * 30 *
31 * BSD LICENSE 31 * BSD LICENSE
32 * 32 *
33 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 33 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
@@ -2247,10 +2247,22 @@ struct iwl_link_quality_cmd {
2247 __le32 reserved2; 2247 __le32 reserved2;
2248} __attribute__ ((packed)); 2248} __attribute__ ((packed));
2249 2249
2250/*
2251 * BT configuration enable flags:
2252 * bit 0 - 1: BT channel announcement enabled
2253 * 0: disable
2254 * bit 1 - 1: priority of BT device enabled
2255 * 0: disable
2256 * bit 2 - 1: BT 2 wire support enabled
2257 * 0: disable
2258 */
2259#define BT_COEX_DISABLE (0x0)
2260#define BT_ENABLE_CHANNEL_ANNOUNCE BIT(0)
2261#define BT_ENABLE_PRIORITY BIT(1)
2262#define BT_ENABLE_2_WIRE BIT(2)
2263
2250#define BT_COEX_DISABLE (0x0) 2264#define BT_COEX_DISABLE (0x0)
2251#define BT_COEX_MODE_2W (0x1) 2265#define BT_COEX_ENABLE (BT_ENABLE_CHANNEL_ANNOUNCE | BT_ENABLE_PRIORITY)
2252#define BT_COEX_MODE_3W (0x2)
2253#define BT_COEX_MODE_4W (0x3)
2254 2266
2255#define BT_LEAD_TIME_MIN (0x0) 2267#define BT_LEAD_TIME_MIN (0x0)
2256#define BT_LEAD_TIME_DEF (0x1E) 2268#define BT_LEAD_TIME_DEF (0x1E)
@@ -3095,7 +3107,12 @@ struct statistics_general {
3095 __le32 ttl_timestamp; 3107 __le32 ttl_timestamp;
3096 struct statistics_div div; 3108 struct statistics_div div;
3097 __le32 rx_enable_counter; 3109 __le32 rx_enable_counter;
3098 __le32 reserved1; 3110 /*
3111 * num_of_sos_states:
3112 * count the number of times we have to re-tune
3113 * in order to get out of bad PHY status
3114 */
3115 __le32 num_of_sos_states;
3099 __le32 reserved2; 3116 __le32 reserved2;
3100 __le32 reserved3; 3117 __le32 reserved3;
3101} __attribute__ ((packed)); 3118} __attribute__ ((packed));
@@ -3160,13 +3177,30 @@ struct iwl_notif_statistics {
3160 3177
3161/* 3178/*
3162 * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command) 3179 * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command)
3180 *
3181 * uCode send MISSED_BEACONS_NOTIFICATION to driver when detect beacon missed
3182 * in regardless of how many missed beacons, which mean when driver receive the
3183 * notification, inside the command, it can find all the beacons information
3184 * which include number of total missed beacons, number of consecutive missed
3185 * beacons, number of beacons received and number of beacons expected to
3186 * receive.
3187 *
3188 * If uCode detected consecutive_missed_beacons > 5, it will reset the radio
3189 * in order to bring the radio/PHY back to working state; which has no relation
3190 * to when driver will perform sensitivity calibration.
3191 *
3192 * Driver should set it own missed_beacon_threshold to decide when to perform
3193 * sensitivity calibration based on number of consecutive missed beacons in
3194 * order to improve overall performance, especially in noisy environment.
3195 *
3163 */ 3196 */
3164/* if ucode missed CONSECUTIVE_MISSED_BCONS_TH beacons in a row, 3197
3165 * then this notification will be sent. */ 3198#define IWL_MISSED_BEACON_THRESHOLD_MIN (1)
3166#define CONSECUTIVE_MISSED_BCONS_TH 20 3199#define IWL_MISSED_BEACON_THRESHOLD_DEF (5)
3200#define IWL_MISSED_BEACON_THRESHOLD_MAX IWL_MISSED_BEACON_THRESHOLD_DEF
3167 3201
3168struct iwl_missed_beacon_notif { 3202struct iwl_missed_beacon_notif {
3169 __le32 consequtive_missed_beacons; 3203 __le32 consecutive_missed_beacons;
3170 __le32 total_missed_becons; 3204 __le32 total_missed_becons;
3171 __le32 num_expected_beacons; 3205 __le32 num_expected_beacons;
3172 __le32 num_recvd_beacons; 3206 __le32 num_recvd_beacons;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 5b56307a3812..02bf17ecaf54 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2,7 +2,7 @@
2 * 2 *
3 * GPL LICENSE SUMMARY 3 * GPL LICENSE SUMMARY
4 * 4 *
5 * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. 5 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as 8 * it under the terms of version 2 of the GNU General Public License as
@@ -47,6 +47,26 @@ MODULE_VERSION(IWLWIFI_VERSION);
47MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); 47MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
48MODULE_LICENSE("GPL"); 48MODULE_LICENSE("GPL");
49 49
50/*
51 * set bt_coex_active to true, uCode will do kill/defer
52 * every time the priority line is asserted (BT is sending signals on the
53 * priority line in the PCIx).
54 * set bt_coex_active to false, uCode will ignore the BT activity and
55 * perform the normal operation
56 *
57 * User might experience transmit issue on some platform due to WiFi/BT
58 * co-exist problem. The possible behaviors are:
59 * Able to scan and finding all the available AP
60 * Not able to associate with any AP
61 * On those platforms, WiFi communication can be restored by set
62 * "bt_coex_active" module parameter to "false"
63 *
64 * default: bt_coex_active = true (BT_COEX_ENABLE)
65 */
66static bool bt_coex_active = true;
67module_param(bt_coex_active, bool, S_IRUGO);
68MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist\n");
69
50static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { 70static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
51 {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, 71 {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
52 0, COEX_UNASSOC_IDLE_FLAGS}, 72 0, COEX_UNASSOC_IDLE_FLAGS},
@@ -257,8 +277,8 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
257 spin_lock_irqsave(&priv->lock, flags); 277 spin_lock_irqsave(&priv->lock, flags);
258 priv->cfg->ops->lib->apm_ops.init(priv); 278 priv->cfg->ops->lib->apm_ops.init(priv);
259 279
260 /* Set interrupt coalescing timer to 512 usecs */ 280 /* Set interrupt coalescing calibration timer to default (512 usecs) */
261 iwl_write8(priv, CSR_INT_COALESCING, 512 / 32); 281 iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF);
262 282
263 spin_unlock_irqrestore(&priv->lock, flags); 283 spin_unlock_irqrestore(&priv->lock, flags);
264 284
@@ -1353,6 +1373,8 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
1353 priv->cfg->ops->lib->dump_nic_error_log(priv); 1373 priv->cfg->ops->lib->dump_nic_error_log(priv);
1354 if (priv->cfg->ops->lib->dump_csr) 1374 if (priv->cfg->ops->lib->dump_csr)
1355 priv->cfg->ops->lib->dump_csr(priv); 1375 priv->cfg->ops->lib->dump_csr(priv);
1376 if (priv->cfg->ops->lib->dump_fh)
1377 priv->cfg->ops->lib->dump_fh(priv, NULL, false);
1356 priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false); 1378 priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);
1357#ifdef CONFIG_IWLWIFI_DEBUG 1379#ifdef CONFIG_IWLWIFI_DEBUG
1358 if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) 1380 if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)
@@ -1803,6 +1825,16 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
1803 if (val == 0xffffffff) 1825 if (val == 0xffffffff)
1804 val = 0; 1826 val = 0;
1805 1827
1828 /*
1829 * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
1830 * (bit 15 before shifting it to 31) to clear when using interrupt
1831 * coalescing. fortunately, bits 18 and 19 stay set when this happens
1832 * so we use them to decide on the real state of the Rx bit.
1833 * In order words, bit 15 is set if bit 18 or bit 19 are set.
1834 */
1835 if (val & 0xC0000)
1836 val |= 0x8000;
1837
1806 inta = (0xff & val) | ((0xff00 & val) << 16); 1838 inta = (0xff & val) | ((0xff00 & val) << 16);
1807 IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", 1839 IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n",
1808 inta, inta_mask, val); 1840 inta, inta_mask, val);
@@ -1965,13 +1997,20 @@ EXPORT_SYMBOL(iwl_isr_legacy);
1965int iwl_send_bt_config(struct iwl_priv *priv) 1997int iwl_send_bt_config(struct iwl_priv *priv)
1966{ 1998{
1967 struct iwl_bt_cmd bt_cmd = { 1999 struct iwl_bt_cmd bt_cmd = {
1968 .flags = BT_COEX_MODE_4W,
1969 .lead_time = BT_LEAD_TIME_DEF, 2000 .lead_time = BT_LEAD_TIME_DEF,
1970 .max_kill = BT_MAX_KILL_DEF, 2001 .max_kill = BT_MAX_KILL_DEF,
1971 .kill_ack_mask = 0, 2002 .kill_ack_mask = 0,
1972 .kill_cts_mask = 0, 2003 .kill_cts_mask = 0,
1973 }; 2004 };
1974 2005
2006 if (!bt_coex_active)
2007 bt_cmd.flags = BT_COEX_DISABLE;
2008 else
2009 bt_cmd.flags = BT_COEX_ENABLE;
2010
2011 IWL_DEBUG_INFO(priv, "BT coex %s\n",
2012 (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
2013
1975 return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, 2014 return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
1976 sizeof(struct iwl_bt_cmd), &bt_cmd); 2015 sizeof(struct iwl_bt_cmd), &bt_cmd);
1977} 2016}
@@ -2592,23 +2631,21 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw,
2592 struct ieee80211_vif *vif) 2631 struct ieee80211_vif *vif)
2593{ 2632{
2594 struct iwl_priv *priv = hw->priv; 2633 struct iwl_priv *priv = hw->priv;
2595 unsigned long flags; 2634 int err = 0;
2596 2635
2597 IWL_DEBUG_MAC80211(priv, "enter: type %d\n", vif->type); 2636 IWL_DEBUG_MAC80211(priv, "enter: type %d\n", vif->type);
2598 2637
2638 mutex_lock(&priv->mutex);
2639
2599 if (priv->vif) { 2640 if (priv->vif) {
2600 IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); 2641 IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n");
2601 return -EOPNOTSUPP; 2642 err = -EOPNOTSUPP;
2643 goto out;
2602 } 2644 }
2603 2645
2604 spin_lock_irqsave(&priv->lock, flags);
2605 priv->vif = vif; 2646 priv->vif = vif;
2606 priv->iw_mode = vif->type; 2647 priv->iw_mode = vif->type;
2607 2648
2608 spin_unlock_irqrestore(&priv->lock, flags);
2609
2610 mutex_lock(&priv->mutex);
2611
2612 if (vif->addr) { 2649 if (vif->addr) {
2613 IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); 2650 IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr);
2614 memcpy(priv->mac_addr, vif->addr, ETH_ALEN); 2651 memcpy(priv->mac_addr, vif->addr, ETH_ALEN);
@@ -2618,10 +2655,11 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw,
2618 /* we are not ready, will run again when ready */ 2655 /* we are not ready, will run again when ready */
2619 set_bit(STATUS_MODE_PENDING, &priv->status); 2656 set_bit(STATUS_MODE_PENDING, &priv->status);
2620 2657
2658 out:
2621 mutex_unlock(&priv->mutex); 2659 mutex_unlock(&priv->mutex);
2622 2660
2623 IWL_DEBUG_MAC80211(priv, "leave\n"); 2661 IWL_DEBUG_MAC80211(priv, "leave\n");
2624 return 0; 2662 return err;
2625} 2663}
2626EXPORT_SYMBOL(iwl_mac_add_interface); 2664EXPORT_SYMBOL(iwl_mac_add_interface);
2627 2665
@@ -3268,6 +3306,93 @@ void iwl_dump_csr(struct iwl_priv *priv)
3268} 3306}
3269EXPORT_SYMBOL(iwl_dump_csr); 3307EXPORT_SYMBOL(iwl_dump_csr);
3270 3308
3309const static char *get_fh_string(int cmd)
3310{
3311 switch (cmd) {
3312 IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
3313 IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
3314 IWL_CMD(FH_RSCSR_CHNL0_WPTR);
3315 IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
3316 IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
3317 IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
3318 IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
3319 IWL_CMD(FH_TSSR_TX_STATUS_REG);
3320 IWL_CMD(FH_TSSR_TX_ERROR_REG);
3321 default:
3322 return "UNKNOWN";
3323
3324 }
3325}
3326
3327int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
3328{
3329 int i;
3330#ifdef CONFIG_IWLWIFI_DEBUG
3331 int pos = 0;
3332 size_t bufsz = 0;
3333#endif
3334 u32 fh_tbl[] = {
3335 FH_RSCSR_CHNL0_STTS_WPTR_REG,
3336 FH_RSCSR_CHNL0_RBDCB_BASE_REG,
3337 FH_RSCSR_CHNL0_WPTR,
3338 FH_MEM_RCSR_CHNL0_CONFIG_REG,
3339 FH_MEM_RSSR_SHARED_CTRL_REG,
3340 FH_MEM_RSSR_RX_STATUS_REG,
3341 FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
3342 FH_TSSR_TX_STATUS_REG,
3343 FH_TSSR_TX_ERROR_REG
3344 };
3345#ifdef CONFIG_IWLWIFI_DEBUG
3346 if (display) {
3347 bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
3348 *buf = kmalloc(bufsz, GFP_KERNEL);
3349 if (!*buf)
3350 return -ENOMEM;
3351 pos += scnprintf(*buf + pos, bufsz - pos,
3352 "FH register values:\n");
3353 for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
3354 pos += scnprintf(*buf + pos, bufsz - pos,
3355 " %34s: 0X%08x\n",
3356 get_fh_string(fh_tbl[i]),
3357 iwl_read_direct32(priv, fh_tbl[i]));
3358 }
3359 return pos;
3360 }
3361#endif
3362 IWL_ERR(priv, "FH register values:\n");
3363 for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
3364 IWL_ERR(priv, " %34s: 0X%08x\n",
3365 get_fh_string(fh_tbl[i]),
3366 iwl_read_direct32(priv, fh_tbl[i]));
3367 }
3368 return 0;
3369}
3370EXPORT_SYMBOL(iwl_dump_fh);
3371
3372void iwl_force_rf_reset(struct iwl_priv *priv)
3373{
3374 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
3375 return;
3376
3377 if (!iwl_is_associated(priv)) {
3378 IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n");
3379 return;
3380 }
3381 /*
3382 * There is no easy and better way to force reset the radio,
3383 * the only known method is switching channel which will force to
3384 * reset and tune the radio.
3385 * Use internal short scan (single channel) operation to should
3386 * achieve this objective.
3387 * Driver should reset the radio when number of consecutive missed
3388 * beacon, or any other uCode error condition detected.
3389 */
3390 IWL_DEBUG_INFO(priv, "perform radio reset.\n");
3391 iwl_internal_short_hw_scan(priv);
3392 return;
3393}
3394EXPORT_SYMBOL(iwl_force_rf_reset);
3395
3271#ifdef CONFIG_PM 3396#ifdef CONFIG_PM
3272 3397
3273int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) 3398int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 8deb83bfe182..ec1fe1d7cc9a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -5,7 +5,7 @@
5 * 5 *
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. 8 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as 11 * it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
30 * 30 *
31 * BSD LICENSE 31 * BSD LICENSE
32 * 32 *
33 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 33 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
@@ -71,7 +71,7 @@ struct iwl_cmd;
71 71
72 72
73#define IWLWIFI_VERSION "in-tree:" 73#define IWLWIFI_VERSION "in-tree:"
74#define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation" 74#define DRV_COPYRIGHT "Copyright(c) 2003-2010 Intel Corporation"
75#define DRV_AUTHOR "<ilw@linux.intel.com>" 75#define DRV_AUTHOR "<ilw@linux.intel.com>"
76 76
77#define IWL_PCI_DEVICE(dev, subdev, cfg) \ 77#define IWL_PCI_DEVICE(dev, subdev, cfg) \
@@ -171,6 +171,7 @@ struct iwl_lib_ops {
171 bool full_log, char **buf, bool display); 171 bool full_log, char **buf, bool display);
172 void (*dump_nic_error_log)(struct iwl_priv *priv); 172 void (*dump_nic_error_log)(struct iwl_priv *priv);
173 void (*dump_csr)(struct iwl_priv *priv); 173 void (*dump_csr)(struct iwl_priv *priv);
174 int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);
174 int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); 175 int (*set_channel_switch)(struct iwl_priv *priv, u16 channel);
175 /* power management */ 176 /* power management */
176 struct iwl_apm_ops apm_ops; 177 struct iwl_apm_ops apm_ops;
@@ -187,6 +188,8 @@ struct iwl_lib_ops {
187 188
188 /* temperature */ 189 /* temperature */
189 struct iwl_temp_ops temp_ops; 190 struct iwl_temp_ops temp_ops;
191 /* station management */
192 void (*add_bcast_station)(struct iwl_priv *priv);
190}; 193};
191 194
192struct iwl_led_ops { 195struct iwl_led_ops {
@@ -231,6 +234,8 @@ struct iwl_mod_params {
231 * @adv_thermal_throttle: support advance thermal throttle 234 * @adv_thermal_throttle: support advance thermal throttle
232 * @support_ct_kill_exit: support ct kill exit condition 235 * @support_ct_kill_exit: support ct kill exit condition
233 * @support_wimax_coexist: support wimax/wifi co-exist 236 * @support_wimax_coexist: support wimax/wifi co-exist
237 * @plcp_delta_threshold: plcp error rate threshold used to trigger
238 * radio tuning when there is a high receiving plcp error rate
234 * 239 *
235 * We enable the driver to be backward compatible wrt API version. The 240 * We enable the driver to be backward compatible wrt API version. The
236 * driver specifies which APIs it supports (with @ucode_api_max being the 241 * driver specifies which APIs it supports (with @ucode_api_max being the
@@ -287,6 +292,7 @@ struct iwl_cfg {
287 bool adv_thermal_throttle; 292 bool adv_thermal_throttle;
288 bool support_ct_kill_exit; 293 bool support_ct_kill_exit;
289 const bool support_wimax_coexist; 294 const bool support_wimax_coexist;
295 u8 plcp_delta_threshold;
290}; 296};
291 297
292/*************************** 298/***************************
@@ -423,6 +429,8 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
423/* Handlers */ 429/* Handlers */
424void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, 430void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
425 struct iwl_rx_mem_buffer *rxb); 431 struct iwl_rx_mem_buffer *rxb);
432void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
433 struct iwl_rx_mem_buffer *rxb);
426void iwl_rx_statistics(struct iwl_priv *priv, 434void iwl_rx_statistics(struct iwl_priv *priv,
427 struct iwl_rx_mem_buffer *rxb); 435 struct iwl_rx_mem_buffer *rxb);
428void iwl_reply_statistics(struct iwl_priv *priv, 436void iwl_reply_statistics(struct iwl_priv *priv,
@@ -493,6 +501,8 @@ void iwl_init_scan_params(struct iwl_priv *priv);
493int iwl_scan_cancel(struct iwl_priv *priv); 501int iwl_scan_cancel(struct iwl_priv *priv);
494int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); 502int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
495int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); 503int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req);
504int iwl_internal_short_hw_scan(struct iwl_priv *priv);
505void iwl_force_rf_reset(struct iwl_priv *priv);
496u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, 506u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
497 const u8 *ie, int ie_len, int left); 507 const u8 *ie, int ie_len, int left);
498void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); 508void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
@@ -523,14 +533,6 @@ int iwl_send_calib_results(struct iwl_priv *priv);
523int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); 533int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len);
524void iwl_calib_free_results(struct iwl_priv *priv); 534void iwl_calib_free_results(struct iwl_priv *priv);
525 535
526/*******************************************************************************
527 * Spectrum Measureemtns in iwl-spectrum.c
528 ******************************************************************************/
529#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
530void iwl_setup_spectrum_handlers(struct iwl_priv *priv);
531#else
532static inline void iwl_setup_spectrum_handlers(struct iwl_priv *priv) {}
533#endif
534/***************************************************** 536/*****************************************************
535 * S e n d i n g H o s t C o m m a n d s * 537 * S e n d i n g H o s t C o m m a n d s *
536 *****************************************************/ 538 *****************************************************/
@@ -582,6 +584,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv);
582int iwl_dump_nic_event_log(struct iwl_priv *priv, 584int iwl_dump_nic_event_log(struct iwl_priv *priv,
583 bool full_log, char **buf, bool display); 585 bool full_log, char **buf, bool display);
584void iwl_dump_csr(struct iwl_priv *priv); 586void iwl_dump_csr(struct iwl_priv *priv);
587int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);
585#ifdef CONFIG_IWLWIFI_DEBUG 588#ifdef CONFIG_IWLWIFI_DEBUG
586void iwl_print_rx_config_cmd(struct iwl_priv *priv); 589void iwl_print_rx_config_cmd(struct iwl_priv *priv);
587#else 590#else
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index 1ec8cb4d5eae..1e00720bf8b1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -5,7 +5,7 @@
5 * 5 *
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 8 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as 11 * it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
30 * 30 *
31 * BSD LICENSE 31 * BSD LICENSE
32 * 32 *
33 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 33 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 58e0462cafa3..1c7b53d511c7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * Portions of this file are derived from the ipw3945 project. 5 * Portions of this file are derived from the ipw3945 project.
6 * 6 *
@@ -67,59 +67,6 @@ do { \
67 DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ 67 DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
68} while (0) 68} while (0)
69 69
70#ifdef CONFIG_IWLWIFI_DEBUGFS
71struct iwl_debugfs {
72 const char *name;
73 struct dentry *dir_drv;
74 struct dentry *dir_data;
75 struct dentry *dir_debug;
76 struct dentry *dir_rf;
77 struct dir_data_files {
78 struct dentry *file_sram;
79 struct dentry *file_nvm;
80 struct dentry *file_stations;
81 struct dentry *file_log_event;
82 struct dentry *file_channels;
83 struct dentry *file_status;
84 struct dentry *file_interrupt;
85 struct dentry *file_qos;
86 struct dentry *file_thermal_throttling;
87 struct dentry *file_led;
88 struct dentry *file_disable_ht40;
89 struct dentry *file_sleep_level_override;
90 struct dentry *file_current_sleep_command;
91 } dbgfs_data_files;
92 struct dir_rf_files {
93 struct dentry *file_disable_sensitivity;
94 struct dentry *file_disable_chain_noise;
95 struct dentry *file_disable_tx_power;
96 } dbgfs_rf_files;
97 struct dir_debug_files {
98 struct dentry *file_rx_statistics;
99 struct dentry *file_tx_statistics;
100 struct dentry *file_traffic_log;
101 struct dentry *file_rx_queue;
102 struct dentry *file_tx_queue;
103 struct dentry *file_ucode_rx_stats;
104 struct dentry *file_ucode_tx_stats;
105 struct dentry *file_ucode_general_stats;
106 struct dentry *file_sensitivity;
107 struct dentry *file_chain_noise;
108 struct dentry *file_tx_power;
109 struct dentry *file_power_save_status;
110 struct dentry *file_clear_ucode_statistics;
111 struct dentry *file_clear_traffic_statistics;
112 struct dentry *file_csr;
113 struct dentry *file_ucode_tracing;
114 } dbgfs_debug_files;
115 u32 sram_offset;
116 u32 sram_len;
117};
118
119int iwl_dbgfs_register(struct iwl_priv *priv, const char *name);
120void iwl_dbgfs_unregister(struct iwl_priv *priv);
121#endif
122
123#else 70#else
124#define IWL_DEBUG(__priv, level, fmt, args...) 71#define IWL_DEBUG(__priv, level, fmt, args...)
125#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) 72#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...)
@@ -128,9 +75,10 @@ static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
128{} 75{}
129#endif /* CONFIG_IWLWIFI_DEBUG */ 76#endif /* CONFIG_IWLWIFI_DEBUG */
130 77
131 78#ifdef CONFIG_IWLWIFI_DEBUGFS
132 79int iwl_dbgfs_register(struct iwl_priv *priv, const char *name);
133#ifndef CONFIG_IWLWIFI_DEBUGFS 80void iwl_dbgfs_unregister(struct iwl_priv *priv);
81#else
134static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) 82static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
135{ 83{
136 return 0; 84 return 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 4a2ac9311ba8..d134301b553c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -2,7 +2,7 @@
2 * 2 *
3 * GPL LICENSE SUMMARY 3 * GPL LICENSE SUMMARY
4 * 4 *
5 * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. 5 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as 8 * it under the terms of version 2 of the GNU General Public License as
@@ -41,43 +41,28 @@
41#include "iwl-calib.h" 41#include "iwl-calib.h"
42 42
43/* create and remove of files */ 43/* create and remove of files */
44#define DEBUGFS_ADD_DIR(name, parent) do { \ 44#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
45 dbgfs->dir_##name = debugfs_create_dir(#name, parent); \ 45 if (!debugfs_create_file(#name, mode, parent, priv, \
46 if (!(dbgfs->dir_##name)) \ 46 &iwl_dbgfs_##name##_ops)) \
47 goto err; \ 47 goto err; \
48} while (0) 48} while (0)
49 49
50#define DEBUGFS_ADD_FILE(name, parent, mode) do { \ 50#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \
51 dbgfs->dbgfs_##parent##_files.file_##name = \ 51 struct dentry *__tmp; \
52 debugfs_create_file(#name, mode, \ 52 __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \
53 dbgfs->dir_##parent, priv, \ 53 parent, ptr); \
54 &iwl_dbgfs_##name##_ops); \ 54 if (IS_ERR(__tmp) || !__tmp) \
55 if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \ 55 goto err; \
56 goto err; \
57} while (0) 56} while (0)
58 57
59#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ 58#define DEBUGFS_ADD_X32(name, parent, ptr) do { \
60 dbgfs->dbgfs_##parent##_files.file_##name = \ 59 struct dentry *__tmp; \
61 debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ 60 __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \
62 dbgfs->dir_##parent, ptr); \ 61 parent, ptr); \
63 if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \ 62 if (IS_ERR(__tmp) || !__tmp) \
64 || !dbgfs->dbgfs_##parent##_files.file_##name) \ 63 goto err; \
65 goto err; \
66} while (0) 64} while (0)
67 65
68#define DEBUGFS_ADD_X32(name, parent, ptr) do { \
69 dbgfs->dbgfs_##parent##_files.file_##name = \
70 debugfs_create_x32(#name, S_IRUSR, dbgfs->dir_##parent, ptr); \
71 if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \
72 || !dbgfs->dbgfs_##parent##_files.file_##name) \
73 goto err; \
74} while (0)
75
76#define DEBUGFS_REMOVE(name) do { \
77 debugfs_remove(name); \
78 name = NULL; \
79} while (0);
80
81/* file operation */ 66/* file operation */
82#define DEBUGFS_READ_FUNC(name) \ 67#define DEBUGFS_READ_FUNC(name) \
83static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ 68static ssize_t iwl_dbgfs_##name##_read(struct file *file, \
@@ -236,24 +221,24 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
236 size_t bufsz; 221 size_t bufsz;
237 222
238 /* default is to dump the entire data segment */ 223 /* default is to dump the entire data segment */
239 if (!priv->dbgfs->sram_offset && !priv->dbgfs->sram_len) { 224 if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
240 priv->dbgfs->sram_offset = 0x800000; 225 priv->dbgfs_sram_offset = 0x800000;
241 if (priv->ucode_type == UCODE_INIT) 226 if (priv->ucode_type == UCODE_INIT)
242 priv->dbgfs->sram_len = priv->ucode_init_data.len; 227 priv->dbgfs_sram_len = priv->ucode_init_data.len;
243 else 228 else
244 priv->dbgfs->sram_len = priv->ucode_data.len; 229 priv->dbgfs_sram_len = priv->ucode_data.len;
245 } 230 }
246 bufsz = 30 + priv->dbgfs->sram_len * sizeof(char) * 10; 231 bufsz = 30 + priv->dbgfs_sram_len * sizeof(char) * 10;
247 buf = kmalloc(bufsz, GFP_KERNEL); 232 buf = kmalloc(bufsz, GFP_KERNEL);
248 if (!buf) 233 if (!buf)
249 return -ENOMEM; 234 return -ENOMEM;
250 pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", 235 pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
251 priv->dbgfs->sram_len); 236 priv->dbgfs_sram_len);
252 pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", 237 pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
253 priv->dbgfs->sram_offset); 238 priv->dbgfs_sram_offset);
254 for (i = priv->dbgfs->sram_len; i > 0; i -= 4) { 239 for (i = priv->dbgfs_sram_len; i > 0; i -= 4) {
255 val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \ 240 val = iwl_read_targ_mem(priv, priv->dbgfs_sram_offset + \
256 priv->dbgfs->sram_len - i); 241 priv->dbgfs_sram_len - i);
257 if (i < 4) { 242 if (i < 4) {
258 switch (i) { 243 switch (i) {
259 case 1: 244 case 1:
@@ -293,11 +278,11 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file,
293 return -EFAULT; 278 return -EFAULT;
294 279
295 if (sscanf(buf, "%x,%x", &offset, &len) == 2) { 280 if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
296 priv->dbgfs->sram_offset = offset; 281 priv->dbgfs_sram_offset = offset;
297 priv->dbgfs->sram_len = len; 282 priv->dbgfs_sram_len = len;
298 } else { 283 } else {
299 priv->dbgfs->sram_offset = 0; 284 priv->dbgfs_sram_offset = 0;
300 priv->dbgfs->sram_len = 0; 285 priv->dbgfs_sram_len = 0;
301 } 286 }
302 287
303 return count; 288 return count;
@@ -429,8 +414,9 @@ static ssize_t iwl_dbgfs_log_event_read(struct file *file,
429 int pos = 0; 414 int pos = 0;
430 ssize_t ret = -ENOMEM; 415 ssize_t ret = -ENOMEM;
431 416
432 pos = priv->cfg->ops->lib->dump_nic_event_log(priv, true, &buf, true); 417 ret = pos = priv->cfg->ops->lib->dump_nic_event_log(
433 if (pos && buf) { 418 priv, true, &buf, true);
419 if (buf) {
434 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 420 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
435 kfree(buf); 421 kfree(buf);
436 } 422 }
@@ -829,7 +815,9 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
829 815
830 priv->power_data.debug_sleep_level_override = value; 816 priv->power_data.debug_sleep_level_override = value;
831 817
818 mutex_lock(&priv->mutex);
832 iwl_power_update_mode(priv, true); 819 iwl_power_update_mode(priv, true);
820 mutex_unlock(&priv->mutex);
833 821
834 return count; 822 return count;
835} 823}
@@ -1081,6 +1069,12 @@ static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf,
1081 return p; 1069 return p;
1082} 1070}
1083 1071
1072static const char ucode_stats_header[] =
1073 "%-32s current acumulative delta max\n";
1074static const char ucode_stats_short_format[] =
1075 " %-30s %10u\n";
1076static const char ucode_stats_format[] =
1077 " %-30s %10u %10u %10u %10u\n";
1084 1078
1085static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, 1079static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
1086 char __user *user_buf, 1080 char __user *user_buf,
@@ -1089,28 +1083,19 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
1089 struct iwl_priv *priv = file->private_data; 1083 struct iwl_priv *priv = file->private_data;
1090 int pos = 0; 1084 int pos = 0;
1091 char *buf; 1085 char *buf;
1092 int bufsz = sizeof(struct statistics_rx_phy) * 20 + 1086 int bufsz = sizeof(struct statistics_rx_phy) * 40 +
1093 sizeof(struct statistics_rx_non_phy) * 20 + 1087 sizeof(struct statistics_rx_non_phy) * 40 +
1094 sizeof(struct statistics_rx_ht_phy) * 20 + 400; 1088 sizeof(struct statistics_rx_ht_phy) * 40 + 400;
1095 ssize_t ret; 1089 ssize_t ret;
1096 struct statistics_rx_phy *ofdm, *accum_ofdm; 1090 struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
1097 struct statistics_rx_phy *cck, *accum_cck; 1091 struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
1098 struct statistics_rx_non_phy *general, *accum_general; 1092 struct statistics_rx_non_phy *general, *accum_general;
1099 struct statistics_rx_ht_phy *ht, *accum_ht; 1093 struct statistics_rx_non_phy *delta_general, *max_general;
1094 struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;
1100 1095
1101 if (!iwl_is_alive(priv)) 1096 if (!iwl_is_alive(priv))
1102 return -EAGAIN; 1097 return -EAGAIN;
1103 1098
1104 /* make request to uCode to retrieve statistics information */
1105 mutex_lock(&priv->mutex);
1106 ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
1107 mutex_unlock(&priv->mutex);
1108
1109 if (ret) {
1110 IWL_ERR(priv,
1111 "Error sending statistics request: %zd\n", ret);
1112 return -EAGAIN;
1113 }
1114 buf = kzalloc(bufsz, GFP_KERNEL); 1099 buf = kzalloc(bufsz, GFP_KERNEL);
1115 if (!buf) { 1100 if (!buf) {
1116 IWL_ERR(priv, "Can not allocate Buffer\n"); 1101 IWL_ERR(priv, "Can not allocate Buffer\n");
@@ -1129,267 +1114,401 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
1129 accum_cck = &priv->accum_statistics.rx.cck; 1114 accum_cck = &priv->accum_statistics.rx.cck;
1130 accum_general = &priv->accum_statistics.rx.general; 1115 accum_general = &priv->accum_statistics.rx.general;
1131 accum_ht = &priv->accum_statistics.rx.ofdm_ht; 1116 accum_ht = &priv->accum_statistics.rx.ofdm_ht;
1117 delta_ofdm = &priv->delta_statistics.rx.ofdm;
1118 delta_cck = &priv->delta_statistics.rx.cck;
1119 delta_general = &priv->delta_statistics.rx.general;
1120 delta_ht = &priv->delta_statistics.rx.ofdm_ht;
1121 max_ofdm = &priv->max_delta.rx.ofdm;
1122 max_cck = &priv->max_delta.rx.cck;
1123 max_general = &priv->max_delta.rx.general;
1124 max_ht = &priv->max_delta.rx.ofdm_ht;
1125
1132 pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); 1126 pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1133 pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n"); 1127 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
1134 pos += scnprintf(buf + pos, bufsz - pos, 1128 "Statistics_Rx - OFDM:");
1135 "\t\t\tcurrent\t\t\taccumulative\n"); 1129 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1136 pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt:\t\t%u\t\t\t%u\n", 1130 "ina_cnt:", le32_to_cpu(ofdm->ina_cnt),
1137 le32_to_cpu(ofdm->ina_cnt), accum_ofdm->ina_cnt); 1131 accum_ofdm->ina_cnt,
1138 pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt:\t\t%u\t\t\t%u\n", 1132 delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
1139 le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt); 1133 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1140 pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n", 1134 "fina_cnt:",
1141 le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err); 1135 le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
1142 pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n", 1136 delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
1143 le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err); 1137 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1144 pos += scnprintf(buf + pos, bufsz - pos, 1138 "plcp_err:",
1145 "overrun_err:\t\t%u\t\t\t%u\n", 1139 le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
1140 delta_ofdm->plcp_err, max_ofdm->plcp_err);
1141 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1142 "crc32_err:",
1143 le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
1144 delta_ofdm->crc32_err, max_ofdm->crc32_err);
1145 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1146 "overrun_err:",
1146 le32_to_cpu(ofdm->overrun_err), 1147 le32_to_cpu(ofdm->overrun_err),
1147 accum_ofdm->overrun_err); 1148 accum_ofdm->overrun_err,
1148 pos += scnprintf(buf + pos, bufsz - pos, 1149 delta_ofdm->overrun_err, max_ofdm->overrun_err);
1149 "early_overrun_err:\t%u\t\t\t%u\n", 1150 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1151 "early_overrun_err:",
1150 le32_to_cpu(ofdm->early_overrun_err), 1152 le32_to_cpu(ofdm->early_overrun_err),
1151 accum_ofdm->early_overrun_err); 1153 accum_ofdm->early_overrun_err,
1152 pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n", 1154 delta_ofdm->early_overrun_err,
1155 max_ofdm->early_overrun_err);
1156 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1157 "crc32_good:",
1153 le32_to_cpu(ofdm->crc32_good), 1158 le32_to_cpu(ofdm->crc32_good),
1154 accum_ofdm->crc32_good); 1159 accum_ofdm->crc32_good,
1155 pos += scnprintf(buf + pos, bufsz - pos, 1160 delta_ofdm->crc32_good, max_ofdm->crc32_good);
1156 "false_alarm_cnt:\t%u\t\t\t%u\n", 1161 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1162 "false_alarm_cnt:",
1157 le32_to_cpu(ofdm->false_alarm_cnt), 1163 le32_to_cpu(ofdm->false_alarm_cnt),
1158 accum_ofdm->false_alarm_cnt); 1164 accum_ofdm->false_alarm_cnt,
1159 pos += scnprintf(buf + pos, bufsz - pos, 1165 delta_ofdm->false_alarm_cnt,
1160 "fina_sync_err_cnt:\t%u\t\t\t%u\n", 1166 max_ofdm->false_alarm_cnt);
1167 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1168 "fina_sync_err_cnt:",
1161 le32_to_cpu(ofdm->fina_sync_err_cnt), 1169 le32_to_cpu(ofdm->fina_sync_err_cnt),
1162 accum_ofdm->fina_sync_err_cnt); 1170 accum_ofdm->fina_sync_err_cnt,
1163 pos += scnprintf(buf + pos, bufsz - pos, 1171 delta_ofdm->fina_sync_err_cnt,
1164 "sfd_timeout:\t\t%u\t\t\t%u\n", 1172 max_ofdm->fina_sync_err_cnt);
1173 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1174 "sfd_timeout:",
1165 le32_to_cpu(ofdm->sfd_timeout), 1175 le32_to_cpu(ofdm->sfd_timeout),
1166 accum_ofdm->sfd_timeout); 1176 accum_ofdm->sfd_timeout,
1167 pos += scnprintf(buf + pos, bufsz - pos, 1177 delta_ofdm->sfd_timeout,
1168 "fina_timeout:\t\t%u\t\t\t%u\n", 1178 max_ofdm->sfd_timeout);
1179 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1180 "fina_timeout:",
1169 le32_to_cpu(ofdm->fina_timeout), 1181 le32_to_cpu(ofdm->fina_timeout),
1170 accum_ofdm->fina_timeout); 1182 accum_ofdm->fina_timeout,
1171 pos += scnprintf(buf + pos, bufsz - pos, 1183 delta_ofdm->fina_timeout,
1172 "unresponded_rts:\t%u\t\t\t%u\n", 1184 max_ofdm->fina_timeout);
1185 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1186 "unresponded_rts:",
1173 le32_to_cpu(ofdm->unresponded_rts), 1187 le32_to_cpu(ofdm->unresponded_rts),
1174 accum_ofdm->unresponded_rts); 1188 accum_ofdm->unresponded_rts,
1175 pos += scnprintf(buf + pos, bufsz - pos, 1189 delta_ofdm->unresponded_rts,
1176 "rxe_frame_lmt_ovrun:\t%u\t\t\t%u\n", 1190 max_ofdm->unresponded_rts);
1191 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1192 "rxe_frame_lmt_ovrun:",
1177 le32_to_cpu(ofdm->rxe_frame_limit_overrun), 1193 le32_to_cpu(ofdm->rxe_frame_limit_overrun),
1178 accum_ofdm->rxe_frame_limit_overrun); 1194 accum_ofdm->rxe_frame_limit_overrun,
1179 pos += scnprintf(buf + pos, bufsz - pos, 1195 delta_ofdm->rxe_frame_limit_overrun,
1180 "sent_ack_cnt:\t\t%u\t\t\t%u\n", 1196 max_ofdm->rxe_frame_limit_overrun);
1197 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1198 "sent_ack_cnt:",
1181 le32_to_cpu(ofdm->sent_ack_cnt), 1199 le32_to_cpu(ofdm->sent_ack_cnt),
1182 accum_ofdm->sent_ack_cnt); 1200 accum_ofdm->sent_ack_cnt,
1183 pos += scnprintf(buf + pos, bufsz - pos, 1201 delta_ofdm->sent_ack_cnt,
1184 "sent_cts_cnt:\t\t%u\t\t\t%u\n", 1202 max_ofdm->sent_ack_cnt);
1203 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1204 "sent_cts_cnt:",
1185 le32_to_cpu(ofdm->sent_cts_cnt), 1205 le32_to_cpu(ofdm->sent_cts_cnt),
1186 accum_ofdm->sent_cts_cnt); 1206 accum_ofdm->sent_cts_cnt,
1187 pos += scnprintf(buf + pos, bufsz - pos, 1207 delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt);
1188 "sent_ba_rsp_cnt:\t%u\t\t\t%u\n", 1208 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1209 "sent_ba_rsp_cnt:",
1189 le32_to_cpu(ofdm->sent_ba_rsp_cnt), 1210 le32_to_cpu(ofdm->sent_ba_rsp_cnt),
1190 accum_ofdm->sent_ba_rsp_cnt); 1211 accum_ofdm->sent_ba_rsp_cnt,
1191 pos += scnprintf(buf + pos, bufsz - pos, 1212 delta_ofdm->sent_ba_rsp_cnt,
1192 "dsp_self_kill:\t\t%u\t\t\t%u\n", 1213 max_ofdm->sent_ba_rsp_cnt);
1214 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1215 "dsp_self_kill:",
1193 le32_to_cpu(ofdm->dsp_self_kill), 1216 le32_to_cpu(ofdm->dsp_self_kill),
1194 accum_ofdm->dsp_self_kill); 1217 accum_ofdm->dsp_self_kill,
1195 pos += scnprintf(buf + pos, bufsz - pos, 1218 delta_ofdm->dsp_self_kill,
1196 "mh_format_err:\t\t%u\t\t\t%u\n", 1219 max_ofdm->dsp_self_kill);
1220 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1221 "mh_format_err:",
1197 le32_to_cpu(ofdm->mh_format_err), 1222 le32_to_cpu(ofdm->mh_format_err),
1198 accum_ofdm->mh_format_err); 1223 accum_ofdm->mh_format_err,
1199 pos += scnprintf(buf + pos, bufsz - pos, 1224 delta_ofdm->mh_format_err,
1200 "re_acq_main_rssi_sum:\t%u\t\t\t%u\n", 1225 max_ofdm->mh_format_err);
1226 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1227 "re_acq_main_rssi_sum:",
1201 le32_to_cpu(ofdm->re_acq_main_rssi_sum), 1228 le32_to_cpu(ofdm->re_acq_main_rssi_sum),
1202 accum_ofdm->re_acq_main_rssi_sum); 1229 accum_ofdm->re_acq_main_rssi_sum,
1203 1230 delta_ofdm->re_acq_main_rssi_sum,
1204 pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n"); 1231 max_ofdm->re_acq_main_rssi_sum);
1205 pos += scnprintf(buf + pos, bufsz - pos, 1232
1206 "\t\t\tcurrent\t\t\taccumulative\n"); 1233 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
1207 pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt:\t\t%u\t\t\t%u\n", 1234 "Statistics_Rx - CCK:");
1208 le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt); 1235 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1209 pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt:\t\t%u\t\t\t%u\n", 1236 "ina_cnt:",
1210 le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt); 1237 le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
1211 pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n", 1238 delta_cck->ina_cnt, max_cck->ina_cnt);
1212 le32_to_cpu(cck->plcp_err), accum_cck->plcp_err); 1239 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1213 pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n", 1240 "fina_cnt:",
1214 le32_to_cpu(cck->crc32_err), accum_cck->crc32_err); 1241 le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
1215 pos += scnprintf(buf + pos, bufsz - pos, 1242 delta_cck->fina_cnt, max_cck->fina_cnt);
1216 "overrun_err:\t\t%u\t\t\t%u\n", 1243 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1244 "plcp_err:",
1245 le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
1246 delta_cck->plcp_err, max_cck->plcp_err);
1247 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1248 "crc32_err:",
1249 le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
1250 delta_cck->crc32_err, max_cck->crc32_err);
1251 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1252 "overrun_err:",
1217 le32_to_cpu(cck->overrun_err), 1253 le32_to_cpu(cck->overrun_err),
1218 accum_cck->overrun_err); 1254 accum_cck->overrun_err,
1219 pos += scnprintf(buf + pos, bufsz - pos, 1255 delta_cck->overrun_err, max_cck->overrun_err);
1220 "early_overrun_err:\t%u\t\t\t%u\n", 1256 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1257 "early_overrun_err:",
1221 le32_to_cpu(cck->early_overrun_err), 1258 le32_to_cpu(cck->early_overrun_err),
1222 accum_cck->early_overrun_err); 1259 accum_cck->early_overrun_err,
1223 pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n", 1260 delta_cck->early_overrun_err,
1224 le32_to_cpu(cck->crc32_good), accum_cck->crc32_good); 1261 max_cck->early_overrun_err);
1225 pos += scnprintf(buf + pos, bufsz - pos, 1262 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1226 "false_alarm_cnt:\t%u\t\t\t%u\n", 1263 "crc32_good:",
1264 le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
1265 delta_cck->crc32_good,
1266 max_cck->crc32_good);
1267 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1268 "false_alarm_cnt:",
1227 le32_to_cpu(cck->false_alarm_cnt), 1269 le32_to_cpu(cck->false_alarm_cnt),
1228 accum_cck->false_alarm_cnt); 1270 accum_cck->false_alarm_cnt,
1229 pos += scnprintf(buf + pos, bufsz - pos, 1271 delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
1230 "fina_sync_err_cnt:\t%u\t\t\t%u\n", 1272 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1273 "fina_sync_err_cnt:",
1231 le32_to_cpu(cck->fina_sync_err_cnt), 1274 le32_to_cpu(cck->fina_sync_err_cnt),
1232 accum_cck->fina_sync_err_cnt); 1275 accum_cck->fina_sync_err_cnt,
1233 pos += scnprintf(buf + pos, bufsz - pos, 1276 delta_cck->fina_sync_err_cnt,
1234 "sfd_timeout:\t\t%u\t\t\t%u\n", 1277 max_cck->fina_sync_err_cnt);
1278 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1279 "sfd_timeout:",
1235 le32_to_cpu(cck->sfd_timeout), 1280 le32_to_cpu(cck->sfd_timeout),
1236 accum_cck->sfd_timeout); 1281 accum_cck->sfd_timeout,
1237 pos += scnprintf(buf + pos, bufsz - pos, 1282 delta_cck->sfd_timeout, max_cck->sfd_timeout);
1238 "fina_timeout:\t\t%u\t\t\t%u\n", 1283 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1284 "fina_timeout:",
1239 le32_to_cpu(cck->fina_timeout), 1285 le32_to_cpu(cck->fina_timeout),
1240 accum_cck->fina_timeout); 1286 accum_cck->fina_timeout,
1241 pos += scnprintf(buf + pos, bufsz - pos, 1287 delta_cck->fina_timeout, max_cck->fina_timeout);
1242 "unresponded_rts:\t%u\t\t\t%u\n", 1288 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1289 "unresponded_rts:",
1243 le32_to_cpu(cck->unresponded_rts), 1290 le32_to_cpu(cck->unresponded_rts),
1244 accum_cck->unresponded_rts); 1291 accum_cck->unresponded_rts,
1245 pos += scnprintf(buf + pos, bufsz - pos, 1292 delta_cck->unresponded_rts,
1246 "rxe_frame_lmt_ovrun:\t%u\t\t\t%u\n", 1293 max_cck->unresponded_rts);
1294 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1295 "rxe_frame_lmt_ovrun:",
1247 le32_to_cpu(cck->rxe_frame_limit_overrun), 1296 le32_to_cpu(cck->rxe_frame_limit_overrun),
1248 accum_cck->rxe_frame_limit_overrun); 1297 accum_cck->rxe_frame_limit_overrun,
1249 pos += scnprintf(buf + pos, bufsz - pos, 1298 delta_cck->rxe_frame_limit_overrun,
1250 "sent_ack_cnt:\t\t%u\t\t\t%u\n", 1299 max_cck->rxe_frame_limit_overrun);
1300 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1301 "sent_ack_cnt:",
1251 le32_to_cpu(cck->sent_ack_cnt), 1302 le32_to_cpu(cck->sent_ack_cnt),
1252 accum_cck->sent_ack_cnt); 1303 accum_cck->sent_ack_cnt,
1253 pos += scnprintf(buf + pos, bufsz - pos, 1304 delta_cck->sent_ack_cnt,
1254 "sent_cts_cnt:\t\t%u\t\t\t%u\n", 1305 max_cck->sent_ack_cnt);
1306 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1307 "sent_cts_cnt:",
1255 le32_to_cpu(cck->sent_cts_cnt), 1308 le32_to_cpu(cck->sent_cts_cnt),
1256 accum_cck->sent_cts_cnt); 1309 accum_cck->sent_cts_cnt,
1257 pos += scnprintf(buf + pos, bufsz - pos, 1310 delta_cck->sent_cts_cnt,
1258 "sent_ba_rsp_cnt:\t%u\t\t\t%u\n", 1311 max_cck->sent_cts_cnt);
1312 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1313 "sent_ba_rsp_cnt:",
1259 le32_to_cpu(cck->sent_ba_rsp_cnt), 1314 le32_to_cpu(cck->sent_ba_rsp_cnt),
1260 accum_cck->sent_ba_rsp_cnt); 1315 accum_cck->sent_ba_rsp_cnt,
1261 pos += scnprintf(buf + pos, bufsz - pos, 1316 delta_cck->sent_ba_rsp_cnt,
1262 "dsp_self_kill:\t\t%u\t\t\t%u\n", 1317 max_cck->sent_ba_rsp_cnt);
1318 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1319 "dsp_self_kill:",
1263 le32_to_cpu(cck->dsp_self_kill), 1320 le32_to_cpu(cck->dsp_self_kill),
1264 accum_cck->dsp_self_kill); 1321 accum_cck->dsp_self_kill,
1265 pos += scnprintf(buf + pos, bufsz - pos, 1322 delta_cck->dsp_self_kill,
1266 "mh_format_err:\t\t%u\t\t\t%u\n", 1323 max_cck->dsp_self_kill);
1324 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1325 "mh_format_err:",
1267 le32_to_cpu(cck->mh_format_err), 1326 le32_to_cpu(cck->mh_format_err),
1268 accum_cck->mh_format_err); 1327 accum_cck->mh_format_err,
1269 pos += scnprintf(buf + pos, bufsz - pos, 1328 delta_cck->mh_format_err, max_cck->mh_format_err);
1270 "re_acq_main_rssi_sum:\t%u\t\t\t%u\n", 1329 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1330 "re_acq_main_rssi_sum:",
1271 le32_to_cpu(cck->re_acq_main_rssi_sum), 1331 le32_to_cpu(cck->re_acq_main_rssi_sum),
1272 accum_cck->re_acq_main_rssi_sum); 1332 accum_cck->re_acq_main_rssi_sum,
1273 1333 delta_cck->re_acq_main_rssi_sum,
1274 pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n"); 1334 max_cck->re_acq_main_rssi_sum);
1275 pos += scnprintf(buf + pos, bufsz - pos, 1335
1276 "\t\t\tcurrent\t\t\taccumulative\n"); 1336 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
1277 pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts:\t\t%u\t\t\t%u\n", 1337 "Statistics_Rx - GENERAL:");
1338 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1339 "bogus_cts:",
1278 le32_to_cpu(general->bogus_cts), 1340 le32_to_cpu(general->bogus_cts),
1279 accum_general->bogus_cts); 1341 accum_general->bogus_cts,
1280 pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack:\t\t%u\t\t\t%u\n", 1342 delta_general->bogus_cts, max_general->bogus_cts);
1343 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1344 "bogus_ack:",
1281 le32_to_cpu(general->bogus_ack), 1345 le32_to_cpu(general->bogus_ack),
1282 accum_general->bogus_ack); 1346 accum_general->bogus_ack,
1283 pos += scnprintf(buf + pos, bufsz - pos, 1347 delta_general->bogus_ack, max_general->bogus_ack);
1284 "non_bssid_frames:\t%u\t\t\t%u\n", 1348 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1349 "non_bssid_frames:",
1285 le32_to_cpu(general->non_bssid_frames), 1350 le32_to_cpu(general->non_bssid_frames),
1286 accum_general->non_bssid_frames); 1351 accum_general->non_bssid_frames,
1287 pos += scnprintf(buf + pos, bufsz - pos, 1352 delta_general->non_bssid_frames,
1288 "filtered_frames:\t%u\t\t\t%u\n", 1353 max_general->non_bssid_frames);
1354 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1355 "filtered_frames:",
1289 le32_to_cpu(general->filtered_frames), 1356 le32_to_cpu(general->filtered_frames),
1290 accum_general->filtered_frames); 1357 accum_general->filtered_frames,
1291 pos += scnprintf(buf + pos, bufsz - pos, 1358 delta_general->filtered_frames,
1292 "non_channel_beacons:\t%u\t\t\t%u\n", 1359 max_general->filtered_frames);
1360 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1361 "non_channel_beacons:",
1293 le32_to_cpu(general->non_channel_beacons), 1362 le32_to_cpu(general->non_channel_beacons),
1294 accum_general->non_channel_beacons); 1363 accum_general->non_channel_beacons,
1295 pos += scnprintf(buf + pos, bufsz - pos, 1364 delta_general->non_channel_beacons,
1296 "channel_beacons:\t%u\t\t\t%u\n", 1365 max_general->non_channel_beacons);
1366 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1367 "channel_beacons:",
1297 le32_to_cpu(general->channel_beacons), 1368 le32_to_cpu(general->channel_beacons),
1298 accum_general->channel_beacons); 1369 accum_general->channel_beacons,
1299 pos += scnprintf(buf + pos, bufsz - pos, 1370 delta_general->channel_beacons,
1300 "num_missed_bcon:\t%u\t\t\t%u\n", 1371 max_general->channel_beacons);
1372 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1373 "num_missed_bcon:",
1301 le32_to_cpu(general->num_missed_bcon), 1374 le32_to_cpu(general->num_missed_bcon),
1302 accum_general->num_missed_bcon); 1375 accum_general->num_missed_bcon,
1303 pos += scnprintf(buf + pos, bufsz - pos, 1376 delta_general->num_missed_bcon,
1304 "adc_rx_saturation_time:\t%u\t\t\t%u\n", 1377 max_general->num_missed_bcon);
1378 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1379 "adc_rx_saturation_time:",
1305 le32_to_cpu(general->adc_rx_saturation_time), 1380 le32_to_cpu(general->adc_rx_saturation_time),
1306 accum_general->adc_rx_saturation_time); 1381 accum_general->adc_rx_saturation_time,
1307 pos += scnprintf(buf + pos, bufsz - pos, 1382 delta_general->adc_rx_saturation_time,
1308 "ina_detect_search_tm:\t%u\t\t\t%u\n", 1383 max_general->adc_rx_saturation_time);
1384 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1385 "ina_detect_search_tm:",
1309 le32_to_cpu(general->ina_detection_search_time), 1386 le32_to_cpu(general->ina_detection_search_time),
1310 accum_general->ina_detection_search_time); 1387 accum_general->ina_detection_search_time,
1311 pos += scnprintf(buf + pos, bufsz - pos, 1388 delta_general->ina_detection_search_time,
1312 "beacon_silence_rssi_a:\t%u\t\t\t%u\n", 1389 max_general->ina_detection_search_time);
1390 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1391 "beacon_silence_rssi_a:",
1313 le32_to_cpu(general->beacon_silence_rssi_a), 1392 le32_to_cpu(general->beacon_silence_rssi_a),
1314 accum_general->beacon_silence_rssi_a); 1393 accum_general->beacon_silence_rssi_a,
1315 pos += scnprintf(buf + pos, bufsz - pos, 1394 delta_general->beacon_silence_rssi_a,
1316 "beacon_silence_rssi_b:\t%u\t\t\t%u\n", 1395 max_general->beacon_silence_rssi_a);
1396 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1397 "beacon_silence_rssi_b:",
1317 le32_to_cpu(general->beacon_silence_rssi_b), 1398 le32_to_cpu(general->beacon_silence_rssi_b),
1318 accum_general->beacon_silence_rssi_b); 1399 accum_general->beacon_silence_rssi_b,
1319 pos += scnprintf(buf + pos, bufsz - pos, 1400 delta_general->beacon_silence_rssi_b,
1320 "beacon_silence_rssi_c:\t%u\t\t\t%u\n", 1401 max_general->beacon_silence_rssi_b);
1402 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1403 "beacon_silence_rssi_c:",
1321 le32_to_cpu(general->beacon_silence_rssi_c), 1404 le32_to_cpu(general->beacon_silence_rssi_c),
1322 accum_general->beacon_silence_rssi_c); 1405 accum_general->beacon_silence_rssi_c,
1323 pos += scnprintf(buf + pos, bufsz - pos, 1406 delta_general->beacon_silence_rssi_c,
1324 "interference_data_flag:\t%u\t\t\t%u\n", 1407 max_general->beacon_silence_rssi_c);
1408 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1409 "interference_data_flag:",
1325 le32_to_cpu(general->interference_data_flag), 1410 le32_to_cpu(general->interference_data_flag),
1326 accum_general->interference_data_flag); 1411 accum_general->interference_data_flag,
1327 pos += scnprintf(buf + pos, bufsz - pos, 1412 delta_general->interference_data_flag,
1328 "channel_load:\t\t%u\t\t\t%u\n", 1413 max_general->interference_data_flag);
1414 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1415 "channel_load:",
1329 le32_to_cpu(general->channel_load), 1416 le32_to_cpu(general->channel_load),
1330 accum_general->channel_load); 1417 accum_general->channel_load,
1331 pos += scnprintf(buf + pos, bufsz - pos, 1418 delta_general->channel_load,
1332 "dsp_false_alarms:\t%u\t\t\t%u\n", 1419 max_general->channel_load);
1420 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1421 "dsp_false_alarms:",
1333 le32_to_cpu(general->dsp_false_alarms), 1422 le32_to_cpu(general->dsp_false_alarms),
1334 accum_general->dsp_false_alarms); 1423 accum_general->dsp_false_alarms,
1335 pos += scnprintf(buf + pos, bufsz - pos, 1424 delta_general->dsp_false_alarms,
1336 "beacon_rssi_a:\t\t%u\t\t\t%u\n", 1425 max_general->dsp_false_alarms);
1426 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1427 "beacon_rssi_a:",
1337 le32_to_cpu(general->beacon_rssi_a), 1428 le32_to_cpu(general->beacon_rssi_a),
1338 accum_general->beacon_rssi_a); 1429 accum_general->beacon_rssi_a,
1339 pos += scnprintf(buf + pos, bufsz - pos, 1430 delta_general->beacon_rssi_a,
1340 "beacon_rssi_b:\t\t%u\t\t\t%u\n", 1431 max_general->beacon_rssi_a);
1432 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1433 "beacon_rssi_b:",
1341 le32_to_cpu(general->beacon_rssi_b), 1434 le32_to_cpu(general->beacon_rssi_b),
1342 accum_general->beacon_rssi_b); 1435 accum_general->beacon_rssi_b,
1343 pos += scnprintf(buf + pos, bufsz - pos, 1436 delta_general->beacon_rssi_b,
1344 "beacon_rssi_c:\t\t%u\t\t\t%u\n", 1437 max_general->beacon_rssi_b);
1438 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1439 "beacon_rssi_c:",
1345 le32_to_cpu(general->beacon_rssi_c), 1440 le32_to_cpu(general->beacon_rssi_c),
1346 accum_general->beacon_rssi_c); 1441 accum_general->beacon_rssi_c,
1347 pos += scnprintf(buf + pos, bufsz - pos, 1442 delta_general->beacon_rssi_c,
1348 "beacon_energy_a:\t%u\t\t\t%u\n", 1443 max_general->beacon_rssi_c);
1444 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1445 "beacon_energy_a:",
1349 le32_to_cpu(general->beacon_energy_a), 1446 le32_to_cpu(general->beacon_energy_a),
1350 accum_general->beacon_energy_a); 1447 accum_general->beacon_energy_a,
1351 pos += scnprintf(buf + pos, bufsz - pos, 1448 delta_general->beacon_energy_a,
1352 "beacon_energy_b:\t%u\t\t\t%u\n", 1449 max_general->beacon_energy_a);
1450 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1451 "beacon_energy_b:",
1353 le32_to_cpu(general->beacon_energy_b), 1452 le32_to_cpu(general->beacon_energy_b),
1354 accum_general->beacon_energy_b); 1453 accum_general->beacon_energy_b,
1355 pos += scnprintf(buf + pos, bufsz - pos, 1454 delta_general->beacon_energy_b,
1356 "beacon_energy_c:\t%u\t\t\t%u\n", 1455 max_general->beacon_energy_b);
1456 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1457 "beacon_energy_c:",
1357 le32_to_cpu(general->beacon_energy_c), 1458 le32_to_cpu(general->beacon_energy_c),
1358 accum_general->beacon_energy_c); 1459 accum_general->beacon_energy_c,
1460 delta_general->beacon_energy_c,
1461 max_general->beacon_energy_c);
1359 1462
1360 pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n"); 1463 pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n");
1361 pos += scnprintf(buf + pos, bufsz - pos, 1464 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
1362 "\t\t\tcurrent\t\t\taccumulative\n"); 1465 "Statistics_Rx - OFDM_HT:");
1363 pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n", 1466 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1364 le32_to_cpu(ht->plcp_err), accum_ht->plcp_err); 1467 "plcp_err:",
1365 pos += scnprintf(buf + pos, bufsz - pos, 1468 le32_to_cpu(ht->plcp_err), accum_ht->plcp_err,
1366 "overrun_err:\t\t%u\t\t\t%u\n", 1469 delta_ht->plcp_err, max_ht->plcp_err);
1367 le32_to_cpu(ht->overrun_err), accum_ht->overrun_err); 1470 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1368 pos += scnprintf(buf + pos, bufsz - pos, 1471 "overrun_err:",
1369 "early_overrun_err:\t%u\t\t\t%u\n", 1472 le32_to_cpu(ht->overrun_err), accum_ht->overrun_err,
1473 delta_ht->overrun_err, max_ht->overrun_err);
1474 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1475 "early_overrun_err:",
1370 le32_to_cpu(ht->early_overrun_err), 1476 le32_to_cpu(ht->early_overrun_err),
1371 accum_ht->early_overrun_err); 1477 accum_ht->early_overrun_err,
1372 pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n", 1478 delta_ht->early_overrun_err,
1373 le32_to_cpu(ht->crc32_good), accum_ht->crc32_good); 1479 max_ht->early_overrun_err);
1374 pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n", 1480 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1375 le32_to_cpu(ht->crc32_err), accum_ht->crc32_err); 1481 "crc32_good:",
1376 pos += scnprintf(buf + pos, bufsz - pos, 1482 le32_to_cpu(ht->crc32_good), accum_ht->crc32_good,
1377 "mh_format_err:\t\t%u\t\t\t%u\n", 1483 delta_ht->crc32_good, max_ht->crc32_good);
1484 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1485 "crc32_err:",
1486 le32_to_cpu(ht->crc32_err), accum_ht->crc32_err,
1487 delta_ht->crc32_err, max_ht->crc32_err);
1488 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1489 "mh_format_err:",
1378 le32_to_cpu(ht->mh_format_err), 1490 le32_to_cpu(ht->mh_format_err),
1379 accum_ht->mh_format_err); 1491 accum_ht->mh_format_err,
1380 pos += scnprintf(buf + pos, bufsz - pos, 1492 delta_ht->mh_format_err, max_ht->mh_format_err);
1381 "agg_crc32_good:\t\t%u\t\t\t%u\n", 1493 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1494 "agg_crc32_good:",
1382 le32_to_cpu(ht->agg_crc32_good), 1495 le32_to_cpu(ht->agg_crc32_good),
1383 accum_ht->agg_crc32_good); 1496 accum_ht->agg_crc32_good,
1384 pos += scnprintf(buf + pos, bufsz - pos, 1497 delta_ht->agg_crc32_good, max_ht->agg_crc32_good);
1385 "agg_mpdu_cnt:\t\t%u\t\t\t%u\n", 1498 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1499 "agg_mpdu_cnt:",
1386 le32_to_cpu(ht->agg_mpdu_cnt), 1500 le32_to_cpu(ht->agg_mpdu_cnt),
1387 accum_ht->agg_mpdu_cnt); 1501 accum_ht->agg_mpdu_cnt,
1388 pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt:\t\t%u\t\t\t%u\n", 1502 delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt);
1389 le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt); 1503 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1390 pos += scnprintf(buf + pos, bufsz - pos, "unsupport_mcs:\t\t%u\t\t\t%u\n", 1504 "agg_cnt:",
1505 le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt,
1506 delta_ht->agg_cnt, max_ht->agg_cnt);
1507 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1508 "unsupport_mcs:",
1391 le32_to_cpu(ht->unsupport_mcs), 1509 le32_to_cpu(ht->unsupport_mcs),
1392 accum_ht->unsupport_mcs); 1510 accum_ht->unsupport_mcs,
1511 delta_ht->unsupport_mcs, max_ht->unsupport_mcs);
1393 1512
1394 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1513 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1395 kfree(buf); 1514 kfree(buf);
@@ -1403,23 +1522,13 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
1403 struct iwl_priv *priv = file->private_data; 1522 struct iwl_priv *priv = file->private_data;
1404 int pos = 0; 1523 int pos = 0;
1405 char *buf; 1524 char *buf;
1406 int bufsz = (sizeof(struct statistics_tx) * 24) + 250; 1525 int bufsz = (sizeof(struct statistics_tx) * 48) + 250;
1407 ssize_t ret; 1526 ssize_t ret;
1408 struct statistics_tx *tx, *accum_tx; 1527 struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
1409 1528
1410 if (!iwl_is_alive(priv)) 1529 if (!iwl_is_alive(priv))
1411 return -EAGAIN; 1530 return -EAGAIN;
1412 1531
1413 /* make request to uCode to retrieve statistics information */
1414 mutex_lock(&priv->mutex);
1415 ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
1416 mutex_unlock(&priv->mutex);
1417
1418 if (ret) {
1419 IWL_ERR(priv,
1420 "Error sending statistics request: %zd\n", ret);
1421 return -EAGAIN;
1422 }
1423 buf = kzalloc(bufsz, GFP_KERNEL); 1532 buf = kzalloc(bufsz, GFP_KERNEL);
1424 if (!buf) { 1533 if (!buf) {
1425 IWL_ERR(priv, "Can not allocate Buffer\n"); 1534 IWL_ERR(priv, "Can not allocate Buffer\n");
@@ -1432,106 +1541,148 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
1432 */ 1541 */
1433 tx = &priv->statistics.tx; 1542 tx = &priv->statistics.tx;
1434 accum_tx = &priv->accum_statistics.tx; 1543 accum_tx = &priv->accum_statistics.tx;
1544 delta_tx = &priv->delta_statistics.tx;
1545 max_tx = &priv->max_delta.tx;
1435 pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); 1546 pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1436 pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n"); 1547 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
1437 pos += scnprintf(buf + pos, bufsz - pos, 1548 "Statistics_Tx:");
1438 "\t\t\tcurrent\t\t\taccumulative\n"); 1549 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1439 pos += scnprintf(buf + pos, bufsz - pos, "preamble:\t\t\t%u\t\t\t%u\n", 1550 "preamble:",
1440 le32_to_cpu(tx->preamble_cnt), 1551 le32_to_cpu(tx->preamble_cnt),
1441 accum_tx->preamble_cnt); 1552 accum_tx->preamble_cnt,
1442 pos += scnprintf(buf + pos, bufsz - pos, 1553 delta_tx->preamble_cnt, max_tx->preamble_cnt);
1443 "rx_detected_cnt:\t\t%u\t\t\t%u\n", 1554 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1555 "rx_detected_cnt:",
1444 le32_to_cpu(tx->rx_detected_cnt), 1556 le32_to_cpu(tx->rx_detected_cnt),
1445 accum_tx->rx_detected_cnt); 1557 accum_tx->rx_detected_cnt,
1446 pos += scnprintf(buf + pos, bufsz - pos, 1558 delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
1447 "bt_prio_defer_cnt:\t\t%u\t\t\t%u\n", 1559 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1560 "bt_prio_defer_cnt:",
1448 le32_to_cpu(tx->bt_prio_defer_cnt), 1561 le32_to_cpu(tx->bt_prio_defer_cnt),
1449 accum_tx->bt_prio_defer_cnt); 1562 accum_tx->bt_prio_defer_cnt,
1450 pos += scnprintf(buf + pos, bufsz - pos, 1563 delta_tx->bt_prio_defer_cnt,
1451 "bt_prio_kill_cnt:\t\t%u\t\t\t%u\n", 1564 max_tx->bt_prio_defer_cnt);
1565 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1566 "bt_prio_kill_cnt:",
1452 le32_to_cpu(tx->bt_prio_kill_cnt), 1567 le32_to_cpu(tx->bt_prio_kill_cnt),
1453 accum_tx->bt_prio_kill_cnt); 1568 accum_tx->bt_prio_kill_cnt,
1454 pos += scnprintf(buf + pos, bufsz - pos, 1569 delta_tx->bt_prio_kill_cnt,
1455 "few_bytes_cnt:\t\t\t%u\t\t\t%u\n", 1570 max_tx->bt_prio_kill_cnt);
1571 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1572 "few_bytes_cnt:",
1456 le32_to_cpu(tx->few_bytes_cnt), 1573 le32_to_cpu(tx->few_bytes_cnt),
1457 accum_tx->few_bytes_cnt); 1574 accum_tx->few_bytes_cnt,
1458 pos += scnprintf(buf + pos, bufsz - pos, 1575 delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
1459 "cts_timeout:\t\t\t%u\t\t\t%u\n", 1576 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1460 le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout); 1577 "cts_timeout:",
1461 pos += scnprintf(buf + pos, bufsz - pos, 1578 le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
1462 "ack_timeout:\t\t\t%u\t\t\t%u\n", 1579 delta_tx->cts_timeout, max_tx->cts_timeout);
1580 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1581 "ack_timeout:",
1463 le32_to_cpu(tx->ack_timeout), 1582 le32_to_cpu(tx->ack_timeout),
1464 accum_tx->ack_timeout); 1583 accum_tx->ack_timeout,
1465 pos += scnprintf(buf + pos, bufsz - pos, 1584 delta_tx->ack_timeout, max_tx->ack_timeout);
1466 "expected_ack_cnt:\t\t%u\t\t\t%u\n", 1585 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1586 "expected_ack_cnt:",
1467 le32_to_cpu(tx->expected_ack_cnt), 1587 le32_to_cpu(tx->expected_ack_cnt),
1468 accum_tx->expected_ack_cnt); 1588 accum_tx->expected_ack_cnt,
1469 pos += scnprintf(buf + pos, bufsz - pos, 1589 delta_tx->expected_ack_cnt,
1470 "actual_ack_cnt:\t\t\t%u\t\t\t%u\n", 1590 max_tx->expected_ack_cnt);
1591 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1592 "actual_ack_cnt:",
1471 le32_to_cpu(tx->actual_ack_cnt), 1593 le32_to_cpu(tx->actual_ack_cnt),
1472 accum_tx->actual_ack_cnt); 1594 accum_tx->actual_ack_cnt,
1473 pos += scnprintf(buf + pos, bufsz - pos, 1595 delta_tx->actual_ack_cnt,
1474 "dump_msdu_cnt:\t\t\t%u\t\t\t%u\n", 1596 max_tx->actual_ack_cnt);
1597 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1598 "dump_msdu_cnt:",
1475 le32_to_cpu(tx->dump_msdu_cnt), 1599 le32_to_cpu(tx->dump_msdu_cnt),
1476 accum_tx->dump_msdu_cnt); 1600 accum_tx->dump_msdu_cnt,
1477 pos += scnprintf(buf + pos, bufsz - pos, 1601 delta_tx->dump_msdu_cnt,
1478 "abort_nxt_frame_mismatch:" 1602 max_tx->dump_msdu_cnt);
1479 "\t%u\t\t\t%u\n", 1603 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1604 "abort_nxt_frame_mismatch:",
1480 le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), 1605 le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt),
1481 accum_tx->burst_abort_next_frame_mismatch_cnt); 1606 accum_tx->burst_abort_next_frame_mismatch_cnt,
1482 pos += scnprintf(buf + pos, bufsz - pos, 1607 delta_tx->burst_abort_next_frame_mismatch_cnt,
1483 "abort_missing_nxt_frame:" 1608 max_tx->burst_abort_next_frame_mismatch_cnt);
1484 "\t%u\t\t\t%u\n", 1609 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1610 "abort_missing_nxt_frame:",
1485 le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), 1611 le32_to_cpu(tx->burst_abort_missing_next_frame_cnt),
1486 accum_tx->burst_abort_missing_next_frame_cnt); 1612 accum_tx->burst_abort_missing_next_frame_cnt,
1487 pos += scnprintf(buf + pos, bufsz - pos, 1613 delta_tx->burst_abort_missing_next_frame_cnt,
1488 "cts_timeout_collision:\t\t%u\t\t\t%u\n", 1614 max_tx->burst_abort_missing_next_frame_cnt);
1615 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1616 "cts_timeout_collision:",
1489 le32_to_cpu(tx->cts_timeout_collision), 1617 le32_to_cpu(tx->cts_timeout_collision),
1490 accum_tx->cts_timeout_collision); 1618 accum_tx->cts_timeout_collision,
1491 pos += scnprintf(buf + pos, bufsz - pos, 1619 delta_tx->cts_timeout_collision,
1492 "ack_ba_timeout_collision:\t%u\t\t\t%u\n", 1620 max_tx->cts_timeout_collision);
1621 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1622 "ack_ba_timeout_collision:",
1493 le32_to_cpu(tx->ack_or_ba_timeout_collision), 1623 le32_to_cpu(tx->ack_or_ba_timeout_collision),
1494 accum_tx->ack_or_ba_timeout_collision); 1624 accum_tx->ack_or_ba_timeout_collision,
1495 pos += scnprintf(buf + pos, bufsz - pos, 1625 delta_tx->ack_or_ba_timeout_collision,
1496 "agg ba_timeout:\t\t\t%u\t\t\t%u\n", 1626 max_tx->ack_or_ba_timeout_collision);
1627 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1628 "agg ba_timeout:",
1497 le32_to_cpu(tx->agg.ba_timeout), 1629 le32_to_cpu(tx->agg.ba_timeout),
1498 accum_tx->agg.ba_timeout); 1630 accum_tx->agg.ba_timeout,
1499 pos += scnprintf(buf + pos, bufsz - pos, 1631 delta_tx->agg.ba_timeout,
1500 "agg ba_resched_frames:\t\t%u\t\t\t%u\n", 1632 max_tx->agg.ba_timeout);
1633 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1634 "agg ba_resched_frames:",
1501 le32_to_cpu(tx->agg.ba_reschedule_frames), 1635 le32_to_cpu(tx->agg.ba_reschedule_frames),
1502 accum_tx->agg.ba_reschedule_frames); 1636 accum_tx->agg.ba_reschedule_frames,
1503 pos += scnprintf(buf + pos, bufsz - pos, 1637 delta_tx->agg.ba_reschedule_frames,
1504 "agg scd_query_agg_frame:\t%u\t\t\t%u\n", 1638 max_tx->agg.ba_reschedule_frames);
1639 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1640 "agg scd_query_agg_frame:",
1505 le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), 1641 le32_to_cpu(tx->agg.scd_query_agg_frame_cnt),
1506 accum_tx->agg.scd_query_agg_frame_cnt); 1642 accum_tx->agg.scd_query_agg_frame_cnt,
1507 pos += scnprintf(buf + pos, bufsz - pos, 1643 delta_tx->agg.scd_query_agg_frame_cnt,
1508 "agg scd_query_no_agg:\t\t%u\t\t\t%u\n", 1644 max_tx->agg.scd_query_agg_frame_cnt);
1645 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1646 "agg scd_query_no_agg:",
1509 le32_to_cpu(tx->agg.scd_query_no_agg), 1647 le32_to_cpu(tx->agg.scd_query_no_agg),
1510 accum_tx->agg.scd_query_no_agg); 1648 accum_tx->agg.scd_query_no_agg,
1511 pos += scnprintf(buf + pos, bufsz - pos, 1649 delta_tx->agg.scd_query_no_agg,
1512 "agg scd_query_agg:\t\t%u\t\t\t%u\n", 1650 max_tx->agg.scd_query_no_agg);
1651 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1652 "agg scd_query_agg:",
1513 le32_to_cpu(tx->agg.scd_query_agg), 1653 le32_to_cpu(tx->agg.scd_query_agg),
1514 accum_tx->agg.scd_query_agg); 1654 accum_tx->agg.scd_query_agg,
1515 pos += scnprintf(buf + pos, bufsz - pos, 1655 delta_tx->agg.scd_query_agg,
1516 "agg scd_query_mismatch:\t\t%u\t\t\t%u\n", 1656 max_tx->agg.scd_query_agg);
1657 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1658 "agg scd_query_mismatch:",
1517 le32_to_cpu(tx->agg.scd_query_mismatch), 1659 le32_to_cpu(tx->agg.scd_query_mismatch),
1518 accum_tx->agg.scd_query_mismatch); 1660 accum_tx->agg.scd_query_mismatch,
1519 pos += scnprintf(buf + pos, bufsz - pos, 1661 delta_tx->agg.scd_query_mismatch,
1520 "agg frame_not_ready:\t\t%u\t\t\t%u\n", 1662 max_tx->agg.scd_query_mismatch);
1663 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1664 "agg frame_not_ready:",
1521 le32_to_cpu(tx->agg.frame_not_ready), 1665 le32_to_cpu(tx->agg.frame_not_ready),
1522 accum_tx->agg.frame_not_ready); 1666 accum_tx->agg.frame_not_ready,
1523 pos += scnprintf(buf + pos, bufsz - pos, 1667 delta_tx->agg.frame_not_ready,
1524 "agg underrun:\t\t\t%u\t\t\t%u\n", 1668 max_tx->agg.frame_not_ready);
1669 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1670 "agg underrun:",
1525 le32_to_cpu(tx->agg.underrun), 1671 le32_to_cpu(tx->agg.underrun),
1526 accum_tx->agg.underrun); 1672 accum_tx->agg.underrun,
1527 pos += scnprintf(buf + pos, bufsz - pos, 1673 delta_tx->agg.underrun, max_tx->agg.underrun);
1528 "agg bt_prio_kill:\t\t%u\t\t\t%u\n", 1674 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1675 "agg bt_prio_kill:",
1529 le32_to_cpu(tx->agg.bt_prio_kill), 1676 le32_to_cpu(tx->agg.bt_prio_kill),
1530 accum_tx->agg.bt_prio_kill); 1677 accum_tx->agg.bt_prio_kill,
1531 pos += scnprintf(buf + pos, bufsz - pos, 1678 delta_tx->agg.bt_prio_kill,
1532 "agg rx_ba_rsp_cnt:\t\t%u\t\t\t%u\n", 1679 max_tx->agg.bt_prio_kill);
1680 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1681 "agg rx_ba_rsp_cnt:",
1533 le32_to_cpu(tx->agg.rx_ba_rsp_cnt), 1682 le32_to_cpu(tx->agg.rx_ba_rsp_cnt),
1534 accum_tx->agg.rx_ba_rsp_cnt); 1683 accum_tx->agg.rx_ba_rsp_cnt,
1684 delta_tx->agg.rx_ba_rsp_cnt,
1685 max_tx->agg.rx_ba_rsp_cnt);
1535 1686
1536 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1687 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1537 kfree(buf); 1688 kfree(buf);
@@ -1545,25 +1696,16 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
1545 struct iwl_priv *priv = file->private_data; 1696 struct iwl_priv *priv = file->private_data;
1546 int pos = 0; 1697 int pos = 0;
1547 char *buf; 1698 char *buf;
1548 int bufsz = sizeof(struct statistics_general) * 4 + 250; 1699 int bufsz = sizeof(struct statistics_general) * 10 + 300;
1549 ssize_t ret; 1700 ssize_t ret;
1550 struct statistics_general *general, *accum_general; 1701 struct statistics_general *general, *accum_general;
1551 struct statistics_dbg *dbg, *accum_dbg; 1702 struct statistics_general *delta_general, *max_general;
1552 struct statistics_div *div, *accum_div; 1703 struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
1704 struct statistics_div *div, *accum_div, *delta_div, *max_div;
1553 1705
1554 if (!iwl_is_alive(priv)) 1706 if (!iwl_is_alive(priv))
1555 return -EAGAIN; 1707 return -EAGAIN;
1556 1708
1557 /* make request to uCode to retrieve statistics information */
1558 mutex_lock(&priv->mutex);
1559 ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
1560 mutex_unlock(&priv->mutex);
1561
1562 if (ret) {
1563 IWL_ERR(priv,
1564 "Error sending statistics request: %zd\n", ret);
1565 return -EAGAIN;
1566 }
1567 buf = kzalloc(bufsz, GFP_KERNEL); 1709 buf = kzalloc(bufsz, GFP_KERNEL);
1568 if (!buf) { 1710 if (!buf) {
1569 IWL_ERR(priv, "Can not allocate Buffer\n"); 1711 IWL_ERR(priv, "Can not allocate Buffer\n");
@@ -1578,52 +1720,78 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
1578 dbg = &priv->statistics.general.dbg; 1720 dbg = &priv->statistics.general.dbg;
1579 div = &priv->statistics.general.div; 1721 div = &priv->statistics.general.div;
1580 accum_general = &priv->accum_statistics.general; 1722 accum_general = &priv->accum_statistics.general;
1723 delta_general = &priv->delta_statistics.general;
1724 max_general = &priv->max_delta.general;
1581 accum_dbg = &priv->accum_statistics.general.dbg; 1725 accum_dbg = &priv->accum_statistics.general.dbg;
1726 delta_dbg = &priv->delta_statistics.general.dbg;
1727 max_dbg = &priv->max_delta.general.dbg;
1582 accum_div = &priv->accum_statistics.general.div; 1728 accum_div = &priv->accum_statistics.general.div;
1729 delta_div = &priv->delta_statistics.general.div;
1730 max_div = &priv->max_delta.general.div;
1583 pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); 1731 pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1584 pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n"); 1732 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
1585 pos += scnprintf(buf + pos, bufsz - pos, 1733 "Statistics_General:");
1586 "\t\t\tcurrent\t\t\taccumulative\n"); 1734 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format,
1587 pos += scnprintf(buf + pos, bufsz - pos, "temperature:\t\t\t%u\n", 1735 "temperature:",
1588 le32_to_cpu(general->temperature)); 1736 le32_to_cpu(general->temperature));
1589 pos += scnprintf(buf + pos, bufsz - pos, "temperature_m:\t\t\t%u\n", 1737 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format,
1738 "temperature_m:",
1590 le32_to_cpu(general->temperature_m)); 1739 le32_to_cpu(general->temperature_m));
1591 pos += scnprintf(buf + pos, bufsz - pos, 1740 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1592 "burst_check:\t\t\t%u\t\t\t%u\n", 1741 "burst_check:",
1593 le32_to_cpu(dbg->burst_check), 1742 le32_to_cpu(dbg->burst_check),
1594 accum_dbg->burst_check); 1743 accum_dbg->burst_check,
1595 pos += scnprintf(buf + pos, bufsz - pos, 1744 delta_dbg->burst_check, max_dbg->burst_check);
1596 "burst_count:\t\t\t%u\t\t\t%u\n", 1745 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1746 "burst_count:",
1597 le32_to_cpu(dbg->burst_count), 1747 le32_to_cpu(dbg->burst_count),
1598 accum_dbg->burst_count); 1748 accum_dbg->burst_count,
1599 pos += scnprintf(buf + pos, bufsz - pos, 1749 delta_dbg->burst_count, max_dbg->burst_count);
1600 "sleep_time:\t\t\t%u\t\t\t%u\n", 1750 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1751 "sleep_time:",
1601 le32_to_cpu(general->sleep_time), 1752 le32_to_cpu(general->sleep_time),
1602 accum_general->sleep_time); 1753 accum_general->sleep_time,
1603 pos += scnprintf(buf + pos, bufsz - pos, 1754 delta_general->sleep_time, max_general->sleep_time);
1604 "slots_out:\t\t\t%u\t\t\t%u\n", 1755 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1756 "slots_out:",
1605 le32_to_cpu(general->slots_out), 1757 le32_to_cpu(general->slots_out),
1606 accum_general->slots_out); 1758 accum_general->slots_out,
1607 pos += scnprintf(buf + pos, bufsz - pos, 1759 delta_general->slots_out, max_general->slots_out);
1608 "slots_idle:\t\t\t%u\t\t\t%u\n", 1760 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1761 "slots_idle:",
1609 le32_to_cpu(general->slots_idle), 1762 le32_to_cpu(general->slots_idle),
1610 accum_general->slots_idle); 1763 accum_general->slots_idle,
1764 delta_general->slots_idle, max_general->slots_idle);
1611 pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n", 1765 pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
1612 le32_to_cpu(general->ttl_timestamp)); 1766 le32_to_cpu(general->ttl_timestamp));
1613 pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a:\t\t\t%u\t\t\t%u\n", 1767 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1614 le32_to_cpu(div->tx_on_a), accum_div->tx_on_a); 1768 "tx_on_a:",
1615 pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b:\t\t\t%u\t\t\t%u\n", 1769 le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
1616 le32_to_cpu(div->tx_on_b), accum_div->tx_on_b); 1770 delta_div->tx_on_a, max_div->tx_on_a);
1617 pos += scnprintf(buf + pos, bufsz - pos, 1771 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1618 "exec_time:\t\t\t%u\t\t\t%u\n", 1772 "tx_on_b:",
1619 le32_to_cpu(div->exec_time), accum_div->exec_time); 1773 le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
1620 pos += scnprintf(buf + pos, bufsz - pos, 1774 delta_div->tx_on_b, max_div->tx_on_b);
1621 "probe_time:\t\t\t%u\t\t\t%u\n", 1775 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1622 le32_to_cpu(div->probe_time), accum_div->probe_time); 1776 "exec_time:",
1623 pos += scnprintf(buf + pos, bufsz - pos, 1777 le32_to_cpu(div->exec_time), accum_div->exec_time,
1624 "rx_enable_counter:\t\t%u\t\t\t%u\n", 1778 delta_div->exec_time, max_div->exec_time);
1779 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1780 "probe_time:",
1781 le32_to_cpu(div->probe_time), accum_div->probe_time,
1782 delta_div->probe_time, max_div->probe_time);
1783 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1784 "rx_enable_counter:",
1625 le32_to_cpu(general->rx_enable_counter), 1785 le32_to_cpu(general->rx_enable_counter),
1626 accum_general->rx_enable_counter); 1786 accum_general->rx_enable_counter,
1787 delta_general->rx_enable_counter,
1788 max_general->rx_enable_counter);
1789 pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
1790 "num_of_sos_states:",
1791 le32_to_cpu(general->num_of_sos_states),
1792 accum_general->num_of_sos_states,
1793 delta_general->num_of_sos_states,
1794 max_general->num_of_sos_states);
1627 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1795 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1628 kfree(buf); 1796 kfree(buf);
1629 return ret; 1797 return ret;
@@ -1775,23 +1943,12 @@ static ssize_t iwl_dbgfs_tx_power_read(struct file *file,
1775 struct iwl_priv *priv = file->private_data; 1943 struct iwl_priv *priv = file->private_data;
1776 char buf[128]; 1944 char buf[128];
1777 int pos = 0; 1945 int pos = 0;
1778 ssize_t ret;
1779 const size_t bufsz = sizeof(buf); 1946 const size_t bufsz = sizeof(buf);
1780 struct statistics_tx *tx; 1947 struct statistics_tx *tx;
1781 1948
1782 if (!iwl_is_alive(priv)) 1949 if (!iwl_is_alive(priv))
1783 pos += scnprintf(buf + pos, bufsz - pos, "N/A\n"); 1950 pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
1784 else { 1951 else {
1785 /* make request to uCode to retrieve statistics information */
1786 mutex_lock(&priv->mutex);
1787 ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
1788 mutex_unlock(&priv->mutex);
1789
1790 if (ret) {
1791 IWL_ERR(priv, "Error sending statistics request: %zd\n",
1792 ret);
1793 return -EAGAIN;
1794 }
1795 tx = &priv->statistics.tx; 1952 tx = &priv->statistics.tx;
1796 if (tx->tx_power.ant_a || 1953 if (tx->tx_power.ant_a ||
1797 tx->tx_power.ant_b || 1954 tx->tx_power.ant_b ||
@@ -1940,6 +2097,132 @@ static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file,
1940 return count; 2097 return count;
1941} 2098}
1942 2099
2100static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
2101 char __user *user_buf,
2102 size_t count, loff_t *ppos)
2103{
2104 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
2105 char *buf;
2106 int pos = 0;
2107 ssize_t ret = -EFAULT;
2108
2109 if (priv->cfg->ops->lib->dump_fh) {
2110 ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true);
2111 if (buf) {
2112 ret = simple_read_from_buffer(user_buf,
2113 count, ppos, buf, pos);
2114 kfree(buf);
2115 }
2116 }
2117
2118 return ret;
2119}
2120
2121static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file,
2122 char __user *user_buf,
2123 size_t count, loff_t *ppos) {
2124
2125 struct iwl_priv *priv = file->private_data;
2126 int pos = 0;
2127 char buf[12];
2128 const size_t bufsz = sizeof(buf);
2129 ssize_t ret;
2130
2131 pos += scnprintf(buf + pos, bufsz - pos, "%d\n",
2132 priv->missed_beacon_threshold);
2133
2134 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2135 return ret;
2136}
2137
2138static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file,
2139 const char __user *user_buf,
2140 size_t count, loff_t *ppos)
2141{
2142 struct iwl_priv *priv = file->private_data;
2143 char buf[8];
2144 int buf_size;
2145 int missed;
2146
2147 memset(buf, 0, sizeof(buf));
2148 buf_size = min(count, sizeof(buf) - 1);
2149 if (copy_from_user(buf, user_buf, buf_size))
2150 return -EFAULT;
2151 if (sscanf(buf, "%d", &missed) != 1)
2152 return -EINVAL;
2153
2154 if (missed < IWL_MISSED_BEACON_THRESHOLD_MIN ||
2155 missed > IWL_MISSED_BEACON_THRESHOLD_MAX)
2156 priv->missed_beacon_threshold =
2157 IWL_MISSED_BEACON_THRESHOLD_DEF;
2158 else
2159 priv->missed_beacon_threshold = missed;
2160
2161 return count;
2162}
2163
2164static ssize_t iwl_dbgfs_internal_scan_write(struct file *file,
2165 const char __user *user_buf,
2166 size_t count, loff_t *ppos)
2167{
2168 struct iwl_priv *priv = file->private_data;
2169 char buf[8];
2170 int buf_size;
2171 int scan;
2172
2173 memset(buf, 0, sizeof(buf));
2174 buf_size = min(count, sizeof(buf) - 1);
2175 if (copy_from_user(buf, user_buf, buf_size))
2176 return -EFAULT;
2177 if (sscanf(buf, "%d", &scan) != 1)
2178 return -EINVAL;
2179
2180 iwl_internal_short_hw_scan(priv);
2181
2182 return count;
2183}
2184
2185static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,
2186 char __user *user_buf,
2187 size_t count, loff_t *ppos) {
2188
2189 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
2190 int pos = 0;
2191 char buf[12];
2192 const size_t bufsz = sizeof(buf);
2193 ssize_t ret;
2194
2195 pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
2196 priv->cfg->plcp_delta_threshold);
2197
2198 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2199 return ret;
2200}
2201
2202static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
2203 const char __user *user_buf,
2204 size_t count, loff_t *ppos) {
2205
2206 struct iwl_priv *priv = file->private_data;
2207 char buf[8];
2208 int buf_size;
2209 int plcp;
2210
2211 memset(buf, 0, sizeof(buf));
2212 buf_size = min(count, sizeof(buf) - 1);
2213 if (copy_from_user(buf, user_buf, buf_size))
2214 return -EFAULT;
2215 if (sscanf(buf, "%d", &plcp) != 1)
2216 return -EINVAL;
2217 if ((plcp <= IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
2218 (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
2219 priv->cfg->plcp_delta_threshold =
2220 IWL_MAX_PLCP_ERR_THRESHOLD_DEF;
2221 else
2222 priv->cfg->plcp_delta_threshold = plcp;
2223 return count;
2224}
2225
1943DEBUGFS_READ_FILE_OPS(rx_statistics); 2226DEBUGFS_READ_FILE_OPS(rx_statistics);
1944DEBUGFS_READ_FILE_OPS(tx_statistics); 2227DEBUGFS_READ_FILE_OPS(tx_statistics);
1945DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); 2228DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
@@ -1956,6 +2239,10 @@ DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
1956DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); 2239DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
1957DEBUGFS_WRITE_FILE_OPS(csr); 2240DEBUGFS_WRITE_FILE_OPS(csr);
1958DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); 2241DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
2242DEBUGFS_READ_FILE_OPS(fh_reg);
2243DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
2244DEBUGFS_WRITE_FILE_OPS(internal_scan);
2245DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
1959 2246
1960/* 2247/*
1961 * Create the debugfs files and directories 2248 * Create the debugfs files and directories
@@ -1963,71 +2250,73 @@ DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
1963 */ 2250 */
1964int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) 2251int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
1965{ 2252{
1966 struct iwl_debugfs *dbgfs;
1967 struct dentry *phyd = priv->hw->wiphy->debugfsdir; 2253 struct dentry *phyd = priv->hw->wiphy->debugfsdir;
1968 int ret = 0; 2254 struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
1969 2255
1970 dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL); 2256 dir_drv = debugfs_create_dir(name, phyd);
1971 if (!dbgfs) { 2257 if (!dir_drv)
1972 ret = -ENOMEM; 2258 return -ENOMEM;
1973 goto err;
1974 }
1975 2259
1976 priv->dbgfs = dbgfs; 2260 priv->debugfs_dir = dir_drv;
1977 dbgfs->name = name; 2261
1978 dbgfs->dir_drv = debugfs_create_dir(name, phyd); 2262 dir_data = debugfs_create_dir("data", dir_drv);
1979 if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)) { 2263 if (!dir_data)
1980 ret = -ENOENT; 2264 goto err;
2265 dir_rf = debugfs_create_dir("rf", dir_drv);
2266 if (!dir_rf)
2267 goto err;
2268 dir_debug = debugfs_create_dir("debug", dir_drv);
2269 if (!dir_debug)
1981 goto err; 2270 goto err;
1982 }
1983 2271
1984 DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); 2272 DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
1985 DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); 2273 DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
1986 DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv); 2274 DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR);
1987 DEBUGFS_ADD_FILE(nvm, data, S_IRUSR); 2275 DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
1988 DEBUGFS_ADD_FILE(sram, data, S_IWUSR | S_IRUSR); 2276 DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
1989 DEBUGFS_ADD_FILE(log_event, data, S_IWUSR | S_IRUSR); 2277 DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
1990 DEBUGFS_ADD_FILE(stations, data, S_IRUSR); 2278 DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
1991 DEBUGFS_ADD_FILE(channels, data, S_IRUSR); 2279 DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
1992 DEBUGFS_ADD_FILE(status, data, S_IRUSR); 2280 DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR);
1993 DEBUGFS_ADD_FILE(interrupt, data, S_IWUSR | S_IRUSR); 2281 DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR);
1994 DEBUGFS_ADD_FILE(qos, data, S_IRUSR); 2282 DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
1995 DEBUGFS_ADD_FILE(led, data, S_IRUSR); 2283 DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR);
1996 DEBUGFS_ADD_FILE(sleep_level_override, data, S_IWUSR | S_IRUSR); 2284 DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
1997 DEBUGFS_ADD_FILE(current_sleep_command, data, S_IRUSR); 2285 DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
1998 DEBUGFS_ADD_FILE(thermal_throttling, data, S_IRUSR); 2286 DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR);
1999 DEBUGFS_ADD_FILE(disable_ht40, data, S_IWUSR | S_IRUSR); 2287 DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
2000 DEBUGFS_ADD_FILE(rx_statistics, debug, S_IRUSR); 2288 DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
2001 DEBUGFS_ADD_FILE(tx_statistics, debug, S_IRUSR); 2289 DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
2002 DEBUGFS_ADD_FILE(traffic_log, debug, S_IWUSR | S_IRUSR); 2290 DEBUGFS_ADD_FILE(tx_power, dir_debug, S_IRUSR);
2003 DEBUGFS_ADD_FILE(rx_queue, debug, S_IRUSR); 2291 DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
2004 DEBUGFS_ADD_FILE(tx_queue, debug, S_IRUSR); 2292 DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR);
2005 DEBUGFS_ADD_FILE(tx_power, debug, S_IRUSR); 2293 DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
2006 DEBUGFS_ADD_FILE(power_save_status, debug, S_IRUSR); 2294 DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR);
2007 DEBUGFS_ADD_FILE(clear_ucode_statistics, debug, S_IWUSR); 2295 DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
2008 DEBUGFS_ADD_FILE(clear_traffic_statistics, debug, S_IWUSR); 2296 DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
2009 DEBUGFS_ADD_FILE(csr, debug, S_IWUSR); 2297 DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR);
2298 DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
2010 if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { 2299 if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
2011 DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR); 2300 DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
2012 DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR); 2301 DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
2013 DEBUGFS_ADD_FILE(ucode_general_stats, debug, S_IRUSR); 2302 DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
2014 DEBUGFS_ADD_FILE(sensitivity, debug, S_IRUSR); 2303 DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
2015 DEBUGFS_ADD_FILE(chain_noise, debug, S_IRUSR); 2304 DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
2016 DEBUGFS_ADD_FILE(ucode_tracing, debug, S_IWUSR | S_IRUSR); 2305 DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
2017 } 2306 }
2018 DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); 2307 DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal);
2019 DEBUGFS_ADD_BOOL(disable_chain_noise, rf, 2308 DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
2020 &priv->disable_chain_noise_cal); 2309 &priv->disable_chain_noise_cal);
2021 if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || 2310 if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
2022 ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945)) 2311 ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
2023 DEBUGFS_ADD_BOOL(disable_tx_power, rf, 2312 DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf,
2024 &priv->disable_tx_power_cal); 2313 &priv->disable_tx_power_cal);
2025 return 0; 2314 return 0;
2026 2315
2027err: 2316err:
2028 IWL_ERR(priv, "Can't open the debugfs directory\n"); 2317 IWL_ERR(priv, "Can't create the debugfs directory\n");
2029 iwl_dbgfs_unregister(priv); 2318 iwl_dbgfs_unregister(priv);
2030 return ret; 2319 return -ENOMEM;
2031} 2320}
2032EXPORT_SYMBOL(iwl_dbgfs_register); 2321EXPORT_SYMBOL(iwl_dbgfs_register);
2033 2322
@@ -2037,59 +2326,11 @@ EXPORT_SYMBOL(iwl_dbgfs_register);
2037 */ 2326 */
2038void iwl_dbgfs_unregister(struct iwl_priv *priv) 2327void iwl_dbgfs_unregister(struct iwl_priv *priv)
2039{ 2328{
2040 if (!priv->dbgfs) 2329 if (!priv->debugfs_dir)
2041 return; 2330 return;
2042 2331
2043 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sleep_level_override); 2332 debugfs_remove_recursive(priv->debugfs_dir);
2044 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_current_sleep_command); 2333 priv->debugfs_dir = NULL;
2045 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm);
2046 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
2047 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
2048 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
2049 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels);
2050 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status);
2051 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt);
2052 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos);
2053 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led);
2054 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling);
2055 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40);
2056 DEBUGFS_REMOVE(priv->dbgfs->dir_data);
2057 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_statistics);
2058 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_statistics);
2059 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log);
2060 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue);
2061 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue);
2062 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power);
2063 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_power_save_status);
2064 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
2065 file_clear_ucode_statistics);
2066 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
2067 file_clear_traffic_statistics);
2068 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_csr);
2069 if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
2070 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
2071 file_ucode_rx_stats);
2072 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
2073 file_ucode_tx_stats);
2074 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
2075 file_ucode_general_stats);
2076 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
2077 file_sensitivity);
2078 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
2079 file_chain_noise);
2080 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
2081 file_ucode_tracing);
2082 }
2083 DEBUGFS_REMOVE(priv->dbgfs->dir_debug);
2084 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
2085 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
2086 if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
2087 ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
2088 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power);
2089 DEBUGFS_REMOVE(priv->dbgfs->dir_rf);
2090 DEBUGFS_REMOVE(priv->dbgfs->dir_drv);
2091 kfree(priv->dbgfs);
2092 priv->dbgfs = NULL;
2093} 2334}
2094EXPORT_SYMBOL(iwl_dbgfs_unregister); 2335EXPORT_SYMBOL(iwl_dbgfs_unregister);
2095 2336
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 70f0e79c8e4a..55dc5a866542 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
@@ -1011,6 +1011,30 @@ struct iwl_event_log {
1011 int wraps_more_count; 1011 int wraps_more_count;
1012}; 1012};
1013 1013
1014/*
1015 * host interrupt timeout value
1016 * used with setting interrupt coalescing timer
1017 * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
1018 *
1019 * default interrupt coalescing timer is 64 x 32 = 2048 usecs
1020 * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
1021 */
1022#define IWL_HOST_INT_TIMEOUT_MAX (0xFF)
1023#define IWL_HOST_INT_TIMEOUT_DEF (0x40)
1024#define IWL_HOST_INT_TIMEOUT_MIN (0x0)
1025#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF)
1026#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
1027#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
1028
1029/*
1030 * This is the threshold value of plcp error rate per 100mSecs. It is
1031 * used to set and check for the validity of plcp_delta.
1032 */
1033#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (0)
1034#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50)
1035#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100)
1036#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255)
1037
1014struct iwl_priv { 1038struct iwl_priv {
1015 1039
1016 /* ieee device used by generic ieee processing code */ 1040 /* ieee device used by generic ieee processing code */
@@ -1031,13 +1055,16 @@ struct iwl_priv {
1031 1055
1032 struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; 1056 struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
1033 1057
1034#if defined(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) || defined(CONFIG_IWL3945_SPECTRUM_MEASUREMENT)
1035 /* spectrum measurement report caching */ 1058 /* spectrum measurement report caching */
1036 struct iwl_spectrum_notification measure_report; 1059 struct iwl_spectrum_notification measure_report;
1037 u8 measurement_status; 1060 u8 measurement_status;
1038#endif 1061
1039 /* ucode beacon time */ 1062 /* ucode beacon time */
1040 u32 ucode_beacon_time; 1063 u32 ucode_beacon_time;
1064 int missed_beacon_threshold;
1065
1066 /* storing the jiffies when the plcp error rate is received */
1067 unsigned long plcp_jiffies;
1041 1068
1042 /* we allocate array of iwl4965_channel_info for NIC's valid channels. 1069 /* we allocate array of iwl4965_channel_info for NIC's valid channels.
1043 * Access via channel # using indirect index array */ 1070 * Access via channel # using indirect index array */
@@ -1056,14 +1083,15 @@ struct iwl_priv {
1056 struct iwl_calib_result calib_results[IWL_CALIB_MAX]; 1083 struct iwl_calib_result calib_results[IWL_CALIB_MAX];
1057 1084
1058 /* Scan related variables */ 1085 /* Scan related variables */
1059 unsigned long last_scan_jiffies;
1060 unsigned long next_scan_jiffies; 1086 unsigned long next_scan_jiffies;
1061 unsigned long scan_start; 1087 unsigned long scan_start;
1062 unsigned long scan_pass_start; 1088 unsigned long scan_pass_start;
1063 unsigned long scan_start_tsf; 1089 unsigned long scan_start_tsf;
1090 unsigned long last_internal_scan_jiffies;
1064 void *scan; 1091 void *scan;
1065 int scan_bands; 1092 int scan_bands;
1066 struct cfg80211_scan_request *scan_request; 1093 struct cfg80211_scan_request *scan_request;
1094 bool is_internal_short_scan;
1067 u8 scan_tx_ant[IEEE80211_NUM_BANDS]; 1095 u8 scan_tx_ant[IEEE80211_NUM_BANDS];
1068 u8 mgmt_tx_ant; 1096 u8 mgmt_tx_ant;
1069 1097
@@ -1162,6 +1190,8 @@ struct iwl_priv {
1162 struct iwl_notif_statistics statistics; 1190 struct iwl_notif_statistics statistics;
1163#ifdef CONFIG_IWLWIFI_DEBUG 1191#ifdef CONFIG_IWLWIFI_DEBUG
1164 struct iwl_notif_statistics accum_statistics; 1192 struct iwl_notif_statistics accum_statistics;
1193 struct iwl_notif_statistics delta_statistics;
1194 struct iwl_notif_statistics max_delta;
1165#endif 1195#endif
1166 1196
1167 /* context information */ 1197 /* context information */
@@ -1234,15 +1264,10 @@ struct iwl_priv {
1234 1264
1235 struct workqueue_struct *workqueue; 1265 struct workqueue_struct *workqueue;
1236 1266
1237 struct work_struct up;
1238 struct work_struct restart; 1267 struct work_struct restart;
1239 struct work_struct calibrated_work;
1240 struct work_struct scan_completed; 1268 struct work_struct scan_completed;
1241 struct work_struct rx_replenish; 1269 struct work_struct rx_replenish;
1242 struct work_struct abort_scan; 1270 struct work_struct abort_scan;
1243 struct work_struct update_link_led;
1244 struct work_struct auth_work;
1245 struct work_struct report_work;
1246 struct work_struct request_scan; 1271 struct work_struct request_scan;
1247 struct work_struct beacon_update; 1272 struct work_struct beacon_update;
1248 struct work_struct tt_work; 1273 struct work_struct tt_work;
@@ -1278,7 +1303,8 @@ struct iwl_priv {
1278 u16 rx_traffic_idx; 1303 u16 rx_traffic_idx;
1279 u8 *tx_traffic; 1304 u8 *tx_traffic;
1280 u8 *rx_traffic; 1305 u8 *rx_traffic;
1281 struct iwl_debugfs *dbgfs; 1306 struct dentry *debugfs_dir;
1307 u32 dbgfs_sram_offset, dbgfs_sram_len;
1282#endif /* CONFIG_IWLWIFI_DEBUGFS */ 1308#endif /* CONFIG_IWLWIFI_DEBUGFS */
1283#endif /* CONFIG_IWLWIFI_DEBUG */ 1309#endif /* CONFIG_IWLWIFI_DEBUG */
1284 1310
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 4a30969689ff..fd37152abae3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -5,7 +5,7 @@
5 * 5 *
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. 8 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as 11 * it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
30 * 30 *
31 * BSD LICENSE 31 * BSD LICENSE
32 * 32 *
33 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 33 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 0cd9c02ee044..4e1ba824dc50 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -5,7 +5,7 @@
5 * 5 *
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. 8 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as 11 * it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
30 * 30 *
31 * BSD LICENSE 31 * BSD LICENSE
32 * 32 *
33 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 33 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h
index 65fa8a69fd5a..113c3669b9ce 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fh.h
@@ -5,7 +5,7 @@
5 * 5 *
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 8 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as 11 * it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
30 * 30 *
31 * BSD LICENSE 31 * BSD LICENSE
32 * 32 *
33 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 33 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
@@ -379,6 +379,25 @@
379 379
380#define FH_TSSR_TX_STATUS_REG (FH_TSSR_LOWER_BOUND + 0x010) 380#define FH_TSSR_TX_STATUS_REG (FH_TSSR_LOWER_BOUND + 0x010)
381 381
382/**
383 * Bit fields for TSSR(Tx Shared Status & Control) error status register:
384 * 31: Indicates an address error when accessed to internal memory
385 * uCode/driver must write "1" in order to clear this flag
386 * 30: Indicates that Host did not send the expected number of dwords to FH
387 * uCode/driver must write "1" in order to clear this flag
388 * 16-9:Each status bit is for one channel. Indicates that an (Error) ActDMA
389 * command was received from the scheduler while the TRB was already full
390 * with previous command
391 * uCode/driver must write "1" in order to clear this flag
392 * 7-0: Each status bit indicates a channel's TxCredit error. When an error
393 * bit is set, it indicates that the FH has received a full indication
394 * from the RTC TxFIFO and the current value of the TxCredit counter was
395 * not equal to zero. This mean that the credit mechanism was not
396 * synchronized to the TxFIFO status
397 * uCode/driver must write "1" in order to clear this flag
398 */
399#define FH_TSSR_TX_ERROR_REG (FH_TSSR_LOWER_BOUND + 0x018)
400
382#define FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) ((1 << (_chnl)) << 24) 401#define FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) ((1 << (_chnl)) << 24)
383#define FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl) ((1 << (_chnl)) << 16) 402#define FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl) ((1 << (_chnl)) << 16)
384 403
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 87d684efe110..86783c27d97c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -2,7 +2,7 @@
2 * 2 *
3 * GPL LICENSE SUMMARY 3 * GPL LICENSE SUMMARY
4 * 4 *
5 * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. 5 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as 8 * it under the terms of version 2 of the GNU General Public License as
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index bd0b12efb5c7..45af5bbc1c56 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * Portions of this file are derived from the ipw3945 project, as well 5 * Portions of this file are derived from the ipw3945 project, as well
6 * as portions of the ieee80211 subsystem header files. 6 * as portions of the ieee80211 subsystem header files.
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index e552d4c4bdbe..c719baf2585a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * Portions of this file are derived from the ipw3945 project. 5 * Portions of this file are derived from the ipw3945 project.
6 * 6 *
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index 46c7a95b88f0..a6f9c918aabc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h
index f47f053f02ea..49a70baa3fb6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.h
+++ b/drivers/net/wireless/iwlwifi/iwl-led.h
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 8ccc0bb1d9ed..1a1a9f081cc7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * Portions of this file are derived from the ipw3945 project, as well 5 * Portions of this file are derived from the ipw3945 project, as well
6 * as portions of the ieee80211 subsystem header files. 6 * as portions of the ieee80211 subsystem header files.
@@ -303,13 +303,12 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
303 sizeof(struct iwl_powertable_cmd), cmd); 303 sizeof(struct iwl_powertable_cmd), cmd);
304} 304}
305 305
306 306/* priv->mutex must be held */
307int iwl_power_update_mode(struct iwl_priv *priv, bool force) 307int iwl_power_update_mode(struct iwl_priv *priv, bool force)
308{ 308{
309 int ret = 0; 309 int ret = 0;
310 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 310 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
311 bool enabled = (priv->iw_mode == NL80211_IFTYPE_STATION) && 311 bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS;
312 (priv->hw->conf.flags & IEEE80211_CONF_PS);
313 bool update_chains; 312 bool update_chains;
314 struct iwl_powertable_cmd cmd; 313 struct iwl_powertable_cmd cmd;
315 int dtimper; 314 int dtimper;
@@ -319,7 +318,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
319 priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; 318 priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
320 319
321 if (priv->vif) 320 if (priv->vif)
322 dtimper = priv->vif->bss_conf.dtim_period; 321 dtimper = priv->hw->conf.ps_dtim_period;
323 else 322 else
324 dtimper = 1; 323 dtimper = 1;
325 324
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index 310c32e8f698..5db91c10dcc8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * Portions of this file are derived from the ipw3945 project, as well 5 * Portions of this file are derived from the ipw3945 project, as well
6 * as portions of the ieee80211 subsystem header files. 6 * as portions of the ieee80211 subsystem header files.
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index 6d95832db06d..d2d2a9174900 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -5,7 +5,7 @@
5 * 5 *
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 8 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as 11 * it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
30 * 30 *
31 * BSD LICENSE 31 * BSD LICENSE
32 * 32 *
33 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 33 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 6f36b6e79f5e..5df66382d922 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * Portions of this file are derived from the ipw3945 project, as well 5 * Portions of this file are derived from the ipw3945 project, as well
6 * as portions of the ieee80211 subsystem header files. 6 * as portions of the ieee80211 subsystem header files.
@@ -473,8 +473,8 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
473 (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| 473 (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
474 (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); 474 (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
475 475
476 /* Set interrupt coalescing timer to 64 x 32 = 2048 usecs */ 476 /* Set interrupt coalescing timer to default (2048 usecs) */
477 iwl_write8(priv, CSR_INT_COALESCING, 0x40); 477 iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
478 478
479 return 0; 479 return 0;
480} 480}
@@ -499,9 +499,10 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
499 struct iwl_missed_beacon_notif *missed_beacon; 499 struct iwl_missed_beacon_notif *missed_beacon;
500 500
501 missed_beacon = &pkt->u.missed_beacon; 501 missed_beacon = &pkt->u.missed_beacon;
502 if (le32_to_cpu(missed_beacon->consequtive_missed_beacons) > 5) { 502 if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
503 priv->missed_beacon_threshold) {
503 IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n", 504 IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
504 le32_to_cpu(missed_beacon->consequtive_missed_beacons), 505 le32_to_cpu(missed_beacon->consecutive_missed_beacons),
505 le32_to_cpu(missed_beacon->total_missed_becons), 506 le32_to_cpu(missed_beacon->total_missed_becons),
506 le32_to_cpu(missed_beacon->num_recvd_beacons), 507 le32_to_cpu(missed_beacon->num_recvd_beacons),
507 le32_to_cpu(missed_beacon->num_expected_beacons)); 508 le32_to_cpu(missed_beacon->num_expected_beacons));
@@ -511,6 +512,24 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
511} 512}
512EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); 513EXPORT_SYMBOL(iwl_rx_missed_beacon_notif);
513 514
515void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
516 struct iwl_rx_mem_buffer *rxb)
517{
518 struct iwl_rx_packet *pkt = rxb_addr(rxb);
519 struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
520
521 if (!report->state) {
522 IWL_DEBUG_11H(priv,
523 "Spectrum Measure Notification: Start\n");
524 return;
525 }
526
527 memcpy(&priv->measure_report, report, sizeof(*report));
528 priv->measurement_status |= MEASUREMENT_READY;
529}
530EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif);
531
532
514 533
515/* Calculate noise level, based on measurements during network silence just 534/* Calculate noise level, based on measurements during network silence just
516 * before arriving beacon. This measurement can be done only if we know 535 * before arriving beacon. This measurement can be done only if we know
@@ -564,15 +583,24 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv,
564 int i; 583 int i;
565 __le32 *prev_stats; 584 __le32 *prev_stats;
566 u32 *accum_stats; 585 u32 *accum_stats;
586 u32 *delta, *max_delta;
567 587
568 prev_stats = (__le32 *)&priv->statistics; 588 prev_stats = (__le32 *)&priv->statistics;
569 accum_stats = (u32 *)&priv->accum_statistics; 589 accum_stats = (u32 *)&priv->accum_statistics;
590 delta = (u32 *)&priv->delta_statistics;
591 max_delta = (u32 *)&priv->max_delta;
570 592
571 for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics); 593 for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics);
572 i += sizeof(__le32), stats++, prev_stats++, accum_stats++) 594 i += sizeof(__le32), stats++, prev_stats++, delta++,
573 if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) 595 max_delta++, accum_stats++) {
574 *accum_stats += (le32_to_cpu(*stats) - 596 if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
597 *delta = (le32_to_cpu(*stats) -
575 le32_to_cpu(*prev_stats)); 598 le32_to_cpu(*prev_stats));
599 *accum_stats += *delta;
600 if (*delta > *max_delta)
601 *max_delta = *delta;
602 }
603 }
576 604
577 /* reset accumulative statistics for "no-counter" type statistics */ 605 /* reset accumulative statistics for "no-counter" type statistics */
578 priv->accum_statistics.general.temperature = 606 priv->accum_statistics.general.temperature =
@@ -592,11 +620,15 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv,
592 620
593#define REG_RECALIB_PERIOD (60) 621#define REG_RECALIB_PERIOD (60)
594 622
623#define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n"
595void iwl_rx_statistics(struct iwl_priv *priv, 624void iwl_rx_statistics(struct iwl_priv *priv,
596 struct iwl_rx_mem_buffer *rxb) 625 struct iwl_rx_mem_buffer *rxb)
597{ 626{
598 int change; 627 int change;
599 struct iwl_rx_packet *pkt = rxb_addr(rxb); 628 struct iwl_rx_packet *pkt = rxb_addr(rxb);
629 int combined_plcp_delta;
630 unsigned int plcp_msec;
631 unsigned long plcp_received_jiffies;
600 632
601 IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", 633 IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
602 (int)sizeof(priv->statistics), 634 (int)sizeof(priv->statistics),
@@ -611,6 +643,56 @@ void iwl_rx_statistics(struct iwl_priv *priv,
611#ifdef CONFIG_IWLWIFI_DEBUG 643#ifdef CONFIG_IWLWIFI_DEBUG
612 iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); 644 iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
613#endif 645#endif
646 /*
647 * check for plcp_err and trigger radio reset if it exceeds
648 * the plcp error threshold plcp_delta.
649 */
650 plcp_received_jiffies = jiffies;
651 plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
652 (long) priv->plcp_jiffies);
653 priv->plcp_jiffies = plcp_received_jiffies;
654 /*
655 * check to make sure plcp_msec is not 0 to prevent division
656 * by zero.
657 */
658 if (plcp_msec) {
659 combined_plcp_delta =
660 (le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) -
661 le32_to_cpu(priv->statistics.rx.ofdm.plcp_err)) +
662 (le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) -
663 le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err));
664
665 if ((combined_plcp_delta > 0) &&
666 ((combined_plcp_delta * 100) / plcp_msec) >
667 priv->cfg->plcp_delta_threshold) {
668 /*
669 * if plcp_err exceed the threshold, the following
670 * data is printed in csv format:
671 * Text: plcp_err exceeded %d,
672 * Received ofdm.plcp_err,
673 * Current ofdm.plcp_err,
674 * Received ofdm_ht.plcp_err,
675 * Current ofdm_ht.plcp_err,
676 * combined_plcp_delta,
677 * plcp_msec
678 */
679 IWL_DEBUG_RADIO(priv, PLCP_MSG,
680 priv->cfg->plcp_delta_threshold,
681 le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err),
682 le32_to_cpu(priv->statistics.rx.ofdm.plcp_err),
683 le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err),
684 le32_to_cpu(
685 priv->statistics.rx.ofdm_ht.plcp_err),
686 combined_plcp_delta, plcp_msec);
687
688 /*
689 * Reset the RF radio due to the high plcp
690 * error rate
691 */
692 iwl_force_rf_reset(priv);
693 }
694 }
695
614 memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); 696 memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
615 697
616 set_bit(STATUS_STATISTICS, &priv->status); 698 set_bit(STATUS_STATISTICS, &priv->status);
@@ -638,11 +720,13 @@ void iwl_reply_statistics(struct iwl_priv *priv,
638 struct iwl_rx_packet *pkt = rxb_addr(rxb); 720 struct iwl_rx_packet *pkt = rxb_addr(rxb);
639 721
640 if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) { 722 if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
641 memset(&priv->statistics, 0,
642 sizeof(struct iwl_notif_statistics));
643#ifdef CONFIG_IWLWIFI_DEBUG 723#ifdef CONFIG_IWLWIFI_DEBUG
644 memset(&priv->accum_statistics, 0, 724 memset(&priv->accum_statistics, 0,
645 sizeof(struct iwl_notif_statistics)); 725 sizeof(struct iwl_notif_statistics));
726 memset(&priv->delta_statistics, 0,
727 sizeof(struct iwl_notif_statistics));
728 memset(&priv->max_delta, 0,
729 sizeof(struct iwl_notif_statistics));
646#endif 730#endif
647 IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); 731 IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
648 } 732 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index fa1c89ba6459..08faafae8497 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -2,7 +2,7 @@
2 * 2 *
3 * GPL LICENSE SUMMARY 3 * GPL LICENSE SUMMARY
4 * 4 *
5 * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. 5 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as 8 * it under the terms of version 2 of the GNU General Public License as
@@ -192,19 +192,17 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
192 IWL_DEBUG_SCAN(priv, "Scan ch.res: " 192 IWL_DEBUG_SCAN(priv, "Scan ch.res: "
193 "%d [802.11%s] " 193 "%d [802.11%s] "
194 "(TSF: 0x%08X:%08X) - %d " 194 "(TSF: 0x%08X:%08X) - %d "
195 "elapsed=%lu usec (%dms since last)\n", 195 "elapsed=%lu usec\n",
196 notif->channel, 196 notif->channel,
197 notif->band ? "bg" : "a", 197 notif->band ? "bg" : "a",
198 le32_to_cpu(notif->tsf_high), 198 le32_to_cpu(notif->tsf_high),
199 le32_to_cpu(notif->tsf_low), 199 le32_to_cpu(notif->tsf_low),
200 le32_to_cpu(notif->statistics[0]), 200 le32_to_cpu(notif->statistics[0]),
201 le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf, 201 le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf);
202 jiffies_to_msecs(elapsed_jiffies
203 (priv->last_scan_jiffies, jiffies)));
204#endif 202#endif
205 203
206 priv->last_scan_jiffies = jiffies; 204 if (!priv->is_internal_short_scan)
207 priv->next_scan_jiffies = 0; 205 priv->next_scan_jiffies = 0;
208} 206}
209 207
210/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ 208/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
@@ -250,8 +248,11 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
250 goto reschedule; 248 goto reschedule;
251 } 249 }
252 250
253 priv->last_scan_jiffies = jiffies; 251 if (!priv->is_internal_short_scan)
254 priv->next_scan_jiffies = 0; 252 priv->next_scan_jiffies = 0;
253 else
254 priv->last_internal_scan_jiffies = jiffies;
255
255 IWL_DEBUG_INFO(priv, "Setting scan to off\n"); 256 IWL_DEBUG_INFO(priv, "Setting scan to off\n");
256 257
257 clear_bit(STATUS_SCANNING, &priv->status); 258 clear_bit(STATUS_SCANNING, &priv->status);
@@ -314,6 +315,72 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
314} 315}
315EXPORT_SYMBOL(iwl_get_passive_dwell_time); 316EXPORT_SYMBOL(iwl_get_passive_dwell_time);
316 317
318static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
319 enum ieee80211_band band,
320 struct iwl_scan_channel *scan_ch)
321{
322 const struct ieee80211_supported_band *sband;
323 const struct iwl_channel_info *ch_info;
324 u16 passive_dwell = 0;
325 u16 active_dwell = 0;
326 int i, added = 0;
327 u16 channel = 0;
328
329 sband = iwl_get_hw_mode(priv, band);
330 if (!sband) {
331 IWL_ERR(priv, "invalid band\n");
332 return added;
333 }
334
335 active_dwell = iwl_get_active_dwell_time(priv, band, 0);
336 passive_dwell = iwl_get_passive_dwell_time(priv, band);
337
338 if (passive_dwell <= active_dwell)
339 passive_dwell = active_dwell + 1;
340
341 /* only scan single channel, good enough to reset the RF */
342 /* pick the first valid not in-use channel */
343 if (band == IEEE80211_BAND_5GHZ) {
344 for (i = 14; i < priv->channel_count; i++) {
345 if (priv->channel_info[i].channel !=
346 le16_to_cpu(priv->staging_rxon.channel)) {
347 channel = priv->channel_info[i].channel;
348 ch_info = iwl_get_channel_info(priv,
349 band, channel);
350 if (is_channel_valid(ch_info))
351 break;
352 }
353 }
354 } else {
355 for (i = 0; i < 14; i++) {
356 if (priv->channel_info[i].channel !=
357 le16_to_cpu(priv->staging_rxon.channel)) {
358 channel =
359 priv->channel_info[i].channel;
360 ch_info = iwl_get_channel_info(priv,
361 band, channel);
362 if (is_channel_valid(ch_info))
363 break;
364 }
365 }
366 }
367 if (channel) {
368 scan_ch->channel = cpu_to_le16(channel);
369 scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
370 scan_ch->active_dwell = cpu_to_le16(active_dwell);
371 scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
372 /* Set txpower levels to defaults */
373 scan_ch->dsp_atten = 110;
374 if (band == IEEE80211_BAND_5GHZ)
375 scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
376 else
377 scan_ch->tx_gain = ((1 << 5) | (5 << 3));
378 added++;
379 } else
380 IWL_ERR(priv, "no valid channel found\n");
381 return added;
382}
383
317static int iwl_get_channels_for_scan(struct iwl_priv *priv, 384static int iwl_get_channels_for_scan(struct iwl_priv *priv,
318 enum ieee80211_band band, 385 enum ieee80211_band band,
319 u8 is_active, u8 n_probes, 386 u8 is_active, u8 n_probes,
@@ -421,6 +488,7 @@ static int iwl_scan_initiate(struct iwl_priv *priv)
421 488
422 IWL_DEBUG_INFO(priv, "Starting scan...\n"); 489 IWL_DEBUG_INFO(priv, "Starting scan...\n");
423 set_bit(STATUS_SCANNING, &priv->status); 490 set_bit(STATUS_SCANNING, &priv->status);
491 priv->is_internal_short_scan = false;
424 priv->scan_start = jiffies; 492 priv->scan_start = jiffies;
425 priv->scan_pass_start = priv->scan_start; 493 priv->scan_pass_start = priv->scan_start;
426 494
@@ -461,15 +529,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
461 goto out_unlock; 529 goto out_unlock;
462 } 530 }
463 531
464 /* if we just finished scan ask for delay */
465 if (iwl_is_associated(priv) && priv->last_scan_jiffies &&
466 time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) {
467 IWL_DEBUG_SCAN(priv, "scan rejected: within previous scan period\n");
468 queue_work(priv->workqueue, &priv->scan_completed);
469 ret = 0;
470 goto out_unlock;
471 }
472
473 priv->scan_bands = 0; 532 priv->scan_bands = 0;
474 for (i = 0; i < req->n_channels; i++) 533 for (i = 0; i < req->n_channels; i++)
475 priv->scan_bands |= BIT(req->channels[i]->band); 534 priv->scan_bands |= BIT(req->channels[i]->band);
@@ -488,6 +547,54 @@ out_unlock:
488} 547}
489EXPORT_SYMBOL(iwl_mac_hw_scan); 548EXPORT_SYMBOL(iwl_mac_hw_scan);
490 549
550/*
551 * internal short scan, this function should only been called while associated.
552 * It will reset and tune the radio to prevent possible RF related problem
553 */
554#define IWL_DELAY_NEXT_INTERNAL_SCAN (HZ*1)
555
556int iwl_internal_short_hw_scan(struct iwl_priv *priv)
557{
558 int ret = 0;
559
560 if (!iwl_is_ready_rf(priv)) {
561 ret = -EIO;
562 IWL_DEBUG_SCAN(priv, "not ready or exit pending\n");
563 goto out;
564 }
565 if (test_bit(STATUS_SCANNING, &priv->status)) {
566 IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
567 ret = -EAGAIN;
568 goto out;
569 }
570 if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
571 IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
572 ret = -EAGAIN;
573 goto out;
574 }
575 if (priv->last_internal_scan_jiffies &&
576 time_after(priv->last_internal_scan_jiffies +
577 IWL_DELAY_NEXT_INTERNAL_SCAN, jiffies)) {
578 IWL_DEBUG_SCAN(priv, "internal scan rejected\n");
579 goto out;
580 }
581
582 priv->scan_bands = 0;
583 if (priv->band == IEEE80211_BAND_5GHZ)
584 priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ);
585 else
586 priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ);
587
588 IWL_DEBUG_SCAN(priv, "Start internal short scan...\n");
589 set_bit(STATUS_SCANNING, &priv->status);
590 priv->is_internal_short_scan = true;
591 queue_work(priv->workqueue, &priv->request_scan);
592
593out:
594 return ret;
595}
596EXPORT_SYMBOL(iwl_internal_short_hw_scan);
597
491#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) 598#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
492 599
493void iwl_bg_scan_check(struct work_struct *data) 600void iwl_bg_scan_check(struct work_struct *data)
@@ -551,7 +658,8 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
551 if (WARN_ON(left < ie_len)) 658 if (WARN_ON(left < ie_len))
552 return len; 659 return len;
553 660
554 memcpy(pos, ies, ie_len); 661 if (ies)
662 memcpy(pos, ies, ie_len);
555 len += ie_len; 663 len += ie_len;
556 left -= ie_len; 664 left -= ie_len;
557 665
@@ -654,7 +762,6 @@ static void iwl_bg_request_scan(struct work_struct *data)
654 unsigned long flags; 762 unsigned long flags;
655 763
656 IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); 764 IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
657
658 spin_lock_irqsave(&priv->lock, flags); 765 spin_lock_irqsave(&priv->lock, flags);
659 interval = priv->beacon_int; 766 interval = priv->beacon_int;
660 spin_unlock_irqrestore(&priv->lock, flags); 767 spin_unlock_irqrestore(&priv->lock, flags);
@@ -672,7 +779,9 @@ static void iwl_bg_request_scan(struct work_struct *data)
672 scan_suspend_time, interval); 779 scan_suspend_time, interval);
673 } 780 }
674 781
675 if (priv->scan_request->n_ssids) { 782 if (priv->is_internal_short_scan) {
783 IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
784 } else if (priv->scan_request->n_ssids) {
676 int i, p = 0; 785 int i, p = 0;
677 IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); 786 IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
678 for (i = 0; i < priv->scan_request->n_ssids; i++) { 787 for (i = 0; i < priv->scan_request->n_ssids; i++) {
@@ -753,24 +862,38 @@ static void iwl_bg_request_scan(struct work_struct *data)
753 rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; 862 rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
754 rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; 863 rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
755 scan->rx_chain = cpu_to_le16(rx_chain); 864 scan->rx_chain = cpu_to_le16(rx_chain);
756 cmd_len = iwl_fill_probe_req(priv, 865 if (!priv->is_internal_short_scan) {
757 (struct ieee80211_mgmt *)scan->data, 866 cmd_len = iwl_fill_probe_req(priv,
758 priv->scan_request->ie, 867 (struct ieee80211_mgmt *)scan->data,
759 priv->scan_request->ie_len, 868 priv->scan_request->ie,
760 IWL_MAX_SCAN_SIZE - sizeof(*scan)); 869 priv->scan_request->ie_len,
870 IWL_MAX_SCAN_SIZE - sizeof(*scan));
871 } else {
872 cmd_len = iwl_fill_probe_req(priv,
873 (struct ieee80211_mgmt *)scan->data,
874 NULL, 0,
875 IWL_MAX_SCAN_SIZE - sizeof(*scan));
761 876
877 }
762 scan->tx_cmd.len = cpu_to_le16(cmd_len); 878 scan->tx_cmd.len = cpu_to_le16(cmd_len);
763
764 if (iwl_is_monitor_mode(priv)) 879 if (iwl_is_monitor_mode(priv))
765 scan->filter_flags = RXON_FILTER_PROMISC_MSK; 880 scan->filter_flags = RXON_FILTER_PROMISC_MSK;
766 881
767 scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | 882 scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
768 RXON_FILTER_BCON_AWARE_MSK); 883 RXON_FILTER_BCON_AWARE_MSK);
769 884
770 scan->channel_count = 885 if (priv->is_internal_short_scan) {
771 iwl_get_channels_for_scan(priv, band, is_active, n_probes, 886 scan->channel_count =
772 (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); 887 iwl_get_single_channel_for_scan(priv, band,
773 888 (void *)&scan->data[le16_to_cpu(
889 scan->tx_cmd.len)]);
890 } else {
891 scan->channel_count =
892 iwl_get_channels_for_scan(priv, band,
893 is_active, n_probes,
894 (void *)&scan->data[le16_to_cpu(
895 scan->tx_cmd.len)]);
896 }
774 if (scan->channel_count == 0) { 897 if (scan->channel_count == 0) {
775 IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); 898 IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
776 goto done; 899 goto done;
@@ -831,7 +954,12 @@ void iwl_bg_scan_completed(struct work_struct *work)
831 954
832 cancel_delayed_work(&priv->scan_check); 955 cancel_delayed_work(&priv->scan_check);
833 956
834 ieee80211_scan_completed(priv->hw, false); 957 if (!priv->is_internal_short_scan)
958 ieee80211_scan_completed(priv->hw, false);
959 else {
960 priv->is_internal_short_scan = false;
961 IWL_DEBUG_SCAN(priv, "internal short scan completed\n");
962 }
835 963
836 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 964 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
837 return; 965 return;
diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.c b/drivers/net/wireless/iwlwifi/iwl-spectrum.c
deleted file mode 100644
index 1ea5cd345fe8..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-spectrum.c
+++ /dev/null
@@ -1,198 +0,0 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
4 *
5 * Portions of this file are derived from the ipw3945 project, as well
6 * as portions of the ieee80211 subsystem header files.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of version 2 of the GNU General Public License as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
20 *
21 * The full GNU General Public License is included in this distribution in the
22 * file called LICENSE.
23 *
24 * Contact Information:
25 * Intel Linux Wireless <ilw@linux.intel.com>
26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
27 *
28 *****************************************************************************/
29
30#include <linux/kernel.h>
31#include <linux/module.h>
32#include <linux/init.h>
33#include <linux/pci.h>
34#include <linux/delay.h>
35#include <linux/skbuff.h>
36#include <linux/netdevice.h>
37#include <linux/wireless.h>
38
39#include <net/mac80211.h>
40
41#include "iwl-eeprom.h"
42#include "iwl-dev.h"
43#include "iwl-core.h"
44#include "iwl-io.h"
45#include "iwl-spectrum.h"
46
47#define BEACON_TIME_MASK_LOW 0x00FFFFFF
48#define BEACON_TIME_MASK_HIGH 0xFF000000
49#define TIME_UNIT 1024
50
51/*
52 * extended beacon time format
53 * time in usec will be changed into a 32-bit value in 8:24 format
54 * the high 1 byte is the beacon counts
55 * the lower 3 bytes is the time in usec within one beacon interval
56 */
57
58/* TOOD: was used in sysfs debug interface need to add to mac */
59#if 0
60static u32 iwl_usecs_to_beacons(u32 usec, u32 beacon_interval)
61{
62 u32 quot;
63 u32 rem;
64 u32 interval = beacon_interval * 1024;
65
66 if (!interval || !usec)
67 return 0;
68
69 quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24);
70 rem = (usec % interval) & BEACON_TIME_MASK_LOW;
71
72 return (quot << 24) + rem;
73}
74
75/* base is usually what we get from ucode with each received frame,
76 * the same as HW timer counter counting down
77 */
78
79static __le32 iwl_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
80{
81 u32 base_low = base & BEACON_TIME_MASK_LOW;
82 u32 addon_low = addon & BEACON_TIME_MASK_LOW;
83 u32 interval = beacon_interval * TIME_UNIT;
84 u32 res = (base & BEACON_TIME_MASK_HIGH) +
85 (addon & BEACON_TIME_MASK_HIGH);
86
87 if (base_low > addon_low)
88 res += base_low - addon_low;
89 else if (base_low < addon_low) {
90 res += interval + base_low - addon_low;
91 res += (1 << 24);
92 } else
93 res += (1 << 24);
94
95 return cpu_to_le32(res);
96}
97static int iwl_get_measurement(struct iwl_priv *priv,
98 struct ieee80211_measurement_params *params,
99 u8 type)
100{
101 struct iwl4965_spectrum_cmd spectrum;
102 struct iwl_rx_packet *res;
103 struct iwl_host_cmd cmd = {
104 .id = REPLY_SPECTRUM_MEASUREMENT_CMD,
105 .data = (void *)&spectrum,
106 .meta.flags = CMD_WANT_SKB,
107 };
108 u32 add_time = le64_to_cpu(params->start_time);
109 int rc;
110 int spectrum_resp_status;
111 int duration = le16_to_cpu(params->duration);
112
113 if (iwl_is_associated(priv))
114 add_time =
115 iwl_usecs_to_beacons(
116 le64_to_cpu(params->start_time) - priv->last_tsf,
117 le16_to_cpu(priv->rxon_timing.beacon_interval));
118
119 memset(&spectrum, 0, sizeof(spectrum));
120
121 spectrum.channel_count = cpu_to_le16(1);
122 spectrum.flags =
123 RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK;
124 spectrum.filter_flags = MEASUREMENT_FILTER_FLAG;
125 cmd.len = sizeof(spectrum);
126 spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
127
128 if (iwl_is_associated(priv))
129 spectrum.start_time =
130 iwl_add_beacon_time(priv->last_beacon_time,
131 add_time,
132 le16_to_cpu(priv->rxon_timing.beacon_interval));
133 else
134 spectrum.start_time = 0;
135
136 spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
137 spectrum.channels[0].channel = params->channel;
138 spectrum.channels[0].type = type;
139 if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)
140 spectrum.flags |= RXON_FLG_BAND_24G_MSK |
141 RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
142
143 rc = iwl_send_cmd_sync(priv, &cmd);
144 if (rc)
145 return rc;
146
147 res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
148 if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
149 IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
150 rc = -EIO;
151 }
152
153 spectrum_resp_status = le16_to_cpu(res->u.spectrum.status);
154 switch (spectrum_resp_status) {
155 case 0: /* Command will be handled */
156 if (res->u.spectrum.id != 0xff) {
157 IWL_DEBUG_INFO(priv,
158 "Replaced existing measurement: %d\n",
159 res->u.spectrum.id);
160 priv->measurement_status &= ~MEASUREMENT_READY;
161 }
162 priv->measurement_status |= MEASUREMENT_ACTIVE;
163 rc = 0;
164 break;
165
166 case 1: /* Command will not be handled */
167 rc = -EAGAIN;
168 break;
169 }
170
171 dev_kfree_skb_any(cmd.meta.u.skb);
172
173 return rc;
174}
175#endif
176
177static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
178 struct iwl_rx_mem_buffer *rxb)
179{
180 struct iwl_rx_packet *pkt = rxb_addr(rxb);
181 struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
182
183 if (!report->state) {
184 IWL_DEBUG_11H(priv,
185 "Spectrum Measure Notification: Start\n");
186 return;
187 }
188
189 memcpy(&priv->measure_report, report, sizeof(*report));
190 priv->measurement_status |= MEASUREMENT_READY;
191}
192
193void iwl_setup_spectrum_handlers(struct iwl_priv *priv)
194{
195 priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
196 iwl_rx_spectrum_measure_notif;
197}
198EXPORT_SYMBOL(iwl_setup_spectrum_handlers);
diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.h b/drivers/net/wireless/iwlwifi/iwl-spectrum.h
index a77c1e619062..af6babee2891 100644
--- a/drivers/net/wireless/iwlwifi/iwl-spectrum.h
+++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.h
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * Portions of this file are derived from the ieee80211 subsystem header files. 5 * Portions of this file are derived from the ieee80211 subsystem header files.
6 * 6 *
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 90fbdb25399e..4a6686fa6b36 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * Portions of this file are derived from the ipw3945 project, as well 5 * Portions of this file are derived from the ipw3945 project, as well
6 * as portions of the ieee80211 subsystem header files. 6 * as portions of the ieee80211 subsystem header files.
@@ -80,46 +80,103 @@ int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
80} 80}
81EXPORT_SYMBOL(iwl_get_ra_sta_id); 81EXPORT_SYMBOL(iwl_get_ra_sta_id);
82 82
83/* priv->sta_lock must be held */
83static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) 84static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
84{ 85{
85 unsigned long flags;
86
87 spin_lock_irqsave(&priv->sta_lock, flags);
88 86
89 if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) 87 if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE))
90 IWL_ERR(priv, "ACTIVATE a non DRIVER active station %d\n", 88 IWL_ERR(priv, "ACTIVATE a non DRIVER active station id %u addr %pM\n",
91 sta_id); 89 sta_id, priv->stations[sta_id].sta.sta.addr);
92
93 priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE;
94 IWL_DEBUG_ASSOC(priv, "Added STA to Ucode: %pM\n",
95 priv->stations[sta_id].sta.sta.addr);
96 90
97 spin_unlock_irqrestore(&priv->sta_lock, flags); 91 if (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) {
92 IWL_DEBUG_ASSOC(priv,
93 "STA id %u addr %pM already present in uCode (according to driver)\n",
94 sta_id, priv->stations[sta_id].sta.sta.addr);
95 } else {
96 priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE;
97 IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n",
98 sta_id, priv->stations[sta_id].sta.sta.addr);
99 }
98} 100}
99 101
100static void iwl_add_sta_callback(struct iwl_priv *priv, 102static void iwl_process_add_sta_resp(struct iwl_priv *priv,
101 struct iwl_device_cmd *cmd, 103 struct iwl_addsta_cmd *addsta,
102 struct iwl_rx_packet *pkt) 104 struct iwl_rx_packet *pkt,
105 bool sync)
103{ 106{
104 struct iwl_addsta_cmd *addsta =
105 (struct iwl_addsta_cmd *)cmd->cmd.payload;
106 u8 sta_id = addsta->sta.sta_id; 107 u8 sta_id = addsta->sta.sta_id;
108 unsigned long flags;
107 109
108 if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { 110 if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
109 IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", 111 IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
110 pkt->hdr.flags); 112 pkt->hdr.flags);
111 return; 113 return;
112 } 114 }
113 115
116 IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
117 sta_id);
118
119 spin_lock_irqsave(&priv->sta_lock, flags);
120
114 switch (pkt->u.add_sta.status) { 121 switch (pkt->u.add_sta.status) {
115 case ADD_STA_SUCCESS_MSK: 122 case ADD_STA_SUCCESS_MSK:
123 IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
116 iwl_sta_ucode_activate(priv, sta_id); 124 iwl_sta_ucode_activate(priv, sta_id);
117 /* fall through */ 125 break;
126 case ADD_STA_NO_ROOM_IN_TABLE:
127 IWL_ERR(priv, "Adding station %d failed, no room in table.\n",
128 sta_id);
129 break;
130 case ADD_STA_NO_BLOCK_ACK_RESOURCE:
131 IWL_ERR(priv, "Adding station %d failed, no block ack resource.\n",
132 sta_id);
133 break;
134 case ADD_STA_MODIFY_NON_EXIST_STA:
135 IWL_ERR(priv, "Attempting to modify non-existing station %d \n",
136 sta_id);
137 break;
118 default: 138 default:
119 IWL_DEBUG_HC(priv, "Received REPLY_ADD_STA:(0x%08X)\n", 139 IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n",
120 pkt->u.add_sta.status); 140 pkt->u.add_sta.status);
121 break; 141 break;
122 } 142 }
143
144 IWL_DEBUG_INFO(priv, "%s station id %u addr %pM\n",
145 priv->stations[sta_id].sta.mode ==
146 STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
147 sta_id, priv->stations[sta_id].sta.sta.addr);
148
149 /*
150 * XXX: The MAC address in the command buffer is often changed from
151 * the original sent to the device. That is, the MAC address
152 * written to the command buffer often is not the same MAC adress
153 * read from the command buffer when the command returns. This
154 * issue has not yet been resolved and this debugging is left to
155 * observe the problem.
156 */
157 IWL_DEBUG_INFO(priv, "%s station according to cmd buffer %pM\n",
158 priv->stations[sta_id].sta.mode ==
159 STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
160 addsta->sta.addr);
161
162 /*
163 * Determine if we wanted to modify or add a station,
164 * if adding a station succeeded we have some more initialization
165 * to do when using station notification. TODO
166 */
167
168 spin_unlock_irqrestore(&priv->sta_lock, flags);
169}
170
171static void iwl_add_sta_callback(struct iwl_priv *priv,
172 struct iwl_device_cmd *cmd,
173 struct iwl_rx_packet *pkt)
174{
175 struct iwl_addsta_cmd *addsta =
176 (struct iwl_addsta_cmd *)cmd->cmd.payload;
177
178 iwl_process_add_sta_resp(priv, addsta, pkt, false);
179
123} 180}
124 181
125int iwl_send_add_sta(struct iwl_priv *priv, 182int iwl_send_add_sta(struct iwl_priv *priv,
@@ -145,24 +202,9 @@ int iwl_send_add_sta(struct iwl_priv *priv,
145 if (ret || (flags & CMD_ASYNC)) 202 if (ret || (flags & CMD_ASYNC))
146 return ret; 203 return ret;
147 204
148 pkt = (struct iwl_rx_packet *)cmd.reply_page;
149 if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
150 IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
151 pkt->hdr.flags);
152 ret = -EIO;
153 }
154
155 if (ret == 0) { 205 if (ret == 0) {
156 switch (pkt->u.add_sta.status) { 206 pkt = (struct iwl_rx_packet *)cmd.reply_page;
157 case ADD_STA_SUCCESS_MSK: 207 iwl_process_add_sta_resp(priv, sta, pkt, true);
158 iwl_sta_ucode_activate(priv, sta->sta.sta_id);
159 IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
160 break;
161 default:
162 ret = -EIO;
163 IWL_WARN(priv, "REPLY_ADD_STA failed\n");
164 break;
165 }
166 } 208 }
167 iwl_free_pages(priv, cmd.reply_page); 209 iwl_free_pages(priv, cmd.reply_page);
168 210
@@ -1003,24 +1045,19 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap)
1003 struct ieee80211_sta_ht_cap *cur_ht_config = NULL; 1045 struct ieee80211_sta_ht_cap *cur_ht_config = NULL;
1004 u8 sta_id; 1046 u8 sta_id;
1005 1047
1006 /* Add station to device's station table */
1007
1008 /* 1048 /*
1009 * XXX: This check is definitely not correct, if we're an AP 1049 * Set HT capabilities. It is ok to set this struct even if not using
1010 * it'll always be false which is not what we want, but 1050 * HT config: the priv->current_ht_config.is_ht flag will just be false
1011 * it doesn't look like iwlagn is prepared to be an HT
1012 * AP anyway.
1013 */ 1051 */
1014 if (priv->current_ht_config.is_ht) { 1052 rcu_read_lock();
1015 rcu_read_lock(); 1053 sta = ieee80211_find_sta(priv->vif, addr);
1016 sta = ieee80211_find_sta(priv->vif, addr); 1054 if (sta) {
1017 if (sta) { 1055 memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config));
1018 memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config)); 1056 cur_ht_config = &ht_config;
1019 cur_ht_config = &ht_config;
1020 }
1021 rcu_read_unlock();
1022 } 1057 }
1058 rcu_read_unlock();
1023 1059
1060 /* Add station to device's station table */
1024 sta_id = iwl_add_station(priv, addr, is_ap, CMD_SYNC, cur_ht_config); 1061 sta_id = iwl_add_station(priv, addr, is_ap, CMD_SYNC, cur_ht_config);
1025 1062
1026 /* Set up default rate scaling table in device's station table */ 1063 /* Set up default rate scaling table in device's station table */
@@ -1085,6 +1122,7 @@ static void iwl_sta_init_bcast_lq(struct iwl_priv *priv)
1085 */ 1122 */
1086void iwl_add_bcast_station(struct iwl_priv *priv) 1123void iwl_add_bcast_station(struct iwl_priv *priv)
1087{ 1124{
1125 IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n");
1088 iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL); 1126 iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL);
1089 1127
1090 /* Set up default rate scaling table in device's station table */ 1128 /* Set up default rate scaling table in device's station table */
@@ -1093,6 +1131,16 @@ void iwl_add_bcast_station(struct iwl_priv *priv)
1093EXPORT_SYMBOL(iwl_add_bcast_station); 1131EXPORT_SYMBOL(iwl_add_bcast_station);
1094 1132
1095/** 1133/**
1134 * iwl3945_add_bcast_station - add broadcast station into station table.
1135 */
1136void iwl3945_add_bcast_station(struct iwl_priv *priv)
1137{
1138 IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n");
1139 iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL);
1140}
1141EXPORT_SYMBOL(iwl3945_add_bcast_station);
1142
1143/**
1096 * iwl_get_sta_id - Find station's index within station table 1144 * iwl_get_sta_id - Find station's index within station table
1097 * 1145 *
1098 * If new IBSS station, create new entry in station table 1146 * If new IBSS station, create new entry in station table
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index 8d052de2d405..2dc35fe28f56 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * Portions of this file are derived from the ipw3945 project, as well 5 * Portions of this file are derived from the ipw3945 project, as well
6 * as portions of the ieee80211 subsystem header files. 6 * as portions of the ieee80211 subsystem header files.
@@ -53,6 +53,7 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
53 53
54int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); 54int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap);
55void iwl_add_bcast_station(struct iwl_priv *priv); 55void iwl_add_bcast_station(struct iwl_priv *priv);
56void iwl3945_add_bcast_station(struct iwl_priv *priv);
56int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); 57int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap);
57void iwl_clear_stations_table(struct iwl_priv *priv); 58void iwl_clear_stations_table(struct iwl_priv *priv);
58int iwl_get_free_ucode_key_index(struct iwl_priv *priv); 59int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 87ce2bd292c7..d365d13e3291 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * Portions of this file are derived from the ipw3945 project, as well 5 * Portions of this file are derived from the ipw3945 project, as well
6 * as portions of the ieee80211 subsystem header files. 6 * as portions of the ieee80211 subsystem header files.
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 10b0aa8024c4..119da54116de 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * Portions of this file are derived from the ipw3945 project, as well 5 * Portions of this file are derived from the ipw3945 project, as well
6 * as portions of the ieee80211 subsystem header files. 6 * as portions of the ieee80211 subsystem header files.
@@ -56,6 +56,7 @@
56#include "iwl-helpers.h" 56#include "iwl-helpers.h"
57#include "iwl-core.h" 57#include "iwl-core.h"
58#include "iwl-dev.h" 58#include "iwl-dev.h"
59#include "iwl-spectrum.h"
59 60
60/* 61/*
61 * module name, copyright, version, etc. 62 * module name, copyright, version, etc.
@@ -70,14 +71,13 @@
70#define VD 71#define VD
71#endif 72#endif
72 73
73#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT 74/*
74#define VS "s" 75 * add "s" to indicate spectrum measurement included.
75#else 76 * we add it here to be consistent with previous releases in which
76#define VS 77 * this was configurable.
77#endif 78 */
78 79#define DRV_VERSION IWLWIFI_VERSION VD "s"
79#define DRV_VERSION IWLWIFI_VERSION VD VS 80#define DRV_COPYRIGHT "Copyright(c) 2003-2010 Intel Corporation"
80#define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation"
81#define DRV_AUTHOR "<ilw@linux.intel.com>" 81#define DRV_AUTHOR "<ilw@linux.intel.com>"
82 82
83MODULE_DESCRIPTION(DRV_DESCRIPTION); 83MODULE_DESCRIPTION(DRV_DESCRIPTION);
@@ -689,10 +689,6 @@ drop:
689 return -1; 689 return -1;
690} 690}
691 691
692#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
693
694#include "iwl-spectrum.h"
695
696#define BEACON_TIME_MASK_LOW 0x00FFFFFF 692#define BEACON_TIME_MASK_LOW 0x00FFFFFF
697#define BEACON_TIME_MASK_HIGH 0xFF000000 693#define BEACON_TIME_MASK_HIGH 0xFF000000
698#define TIME_UNIT 1024 694#define TIME_UNIT 1024
@@ -819,7 +815,6 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
819 815
820 return rc; 816 return rc;
821} 817}
822#endif
823 818
824static void iwl3945_rx_reply_alive(struct iwl_priv *priv, 819static void iwl3945_rx_reply_alive(struct iwl_priv *priv,
825 struct iwl_rx_mem_buffer *rxb) 820 struct iwl_rx_mem_buffer *rxb)
@@ -962,6 +957,8 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
962 priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta; 957 priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta;
963 priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; 958 priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
964 priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; 959 priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
960 priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
961 iwl_rx_spectrum_measure_notif;
965 priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; 962 priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
966 priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = 963 priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
967 iwl_rx_pm_debug_statistics_notif; 964 iwl_rx_pm_debug_statistics_notif;
@@ -975,7 +972,6 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
975 priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics; 972 priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics;
976 priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics; 973 priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
977 974
978 iwl_setup_spectrum_handlers(priv);
979 iwl_setup_rx_scan_handlers(priv); 975 iwl_setup_rx_scan_handlers(priv);
980 priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif; 976 priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
981 977
@@ -1644,7 +1640,7 @@ int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
1644 base = le32_to_cpu(priv->card_alive.log_event_table_ptr); 1640 base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
1645 if (!iwl3945_hw_valid_rtc_data_addr(base)) { 1641 if (!iwl3945_hw_valid_rtc_data_addr(base)) {
1646 IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); 1642 IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
1647 return pos; 1643 return -EINVAL;
1648 } 1644 }
1649 1645
1650 /* event log header */ 1646 /* event log header */
@@ -1693,7 +1689,7 @@ int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
1693 bufsz = size * 48; 1689 bufsz = size * 48;
1694 *buf = kmalloc(bufsz, GFP_KERNEL); 1690 *buf = kmalloc(bufsz, GFP_KERNEL);
1695 if (!*buf) 1691 if (!*buf)
1696 return pos; 1692 return -ENOMEM;
1697 } 1693 }
1698 if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { 1694 if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
1699 /* if uCode has wrapped back to top of log, 1695 /* if uCode has wrapped back to top of log,
@@ -3037,18 +3033,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
3037 mutex_unlock(&priv->mutex); 3033 mutex_unlock(&priv->mutex);
3038} 3034}
3039 3035
3040static void iwl3945_bg_up(struct work_struct *data)
3041{
3042 struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
3043
3044 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
3045 return;
3046
3047 mutex_lock(&priv->mutex);
3048 __iwl3945_up(priv);
3049 mutex_unlock(&priv->mutex);
3050}
3051
3052static void iwl3945_bg_restart(struct work_struct *data) 3036static void iwl3945_bg_restart(struct work_struct *data)
3053{ 3037{
3054 struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); 3038 struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
@@ -3065,7 +3049,13 @@ static void iwl3945_bg_restart(struct work_struct *data)
3065 ieee80211_restart_hw(priv->hw); 3049 ieee80211_restart_hw(priv->hw);
3066 } else { 3050 } else {
3067 iwl3945_down(priv); 3051 iwl3945_down(priv);
3068 queue_work(priv->workqueue, &priv->up); 3052
3053 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
3054 return;
3055
3056 mutex_lock(&priv->mutex);
3057 __iwl3945_up(priv);
3058 mutex_unlock(&priv->mutex);
3069 } 3059 }
3070} 3060}
3071 3061
@@ -3569,8 +3559,6 @@ static ssize_t store_filter_flags(struct device *d,
3569static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, 3559static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
3570 store_filter_flags); 3560 store_filter_flags);
3571 3561
3572#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
3573
3574static ssize_t show_measurement(struct device *d, 3562static ssize_t show_measurement(struct device *d,
3575 struct device_attribute *attr, char *buf) 3563 struct device_attribute *attr, char *buf)
3576{ 3564{
@@ -3640,7 +3628,6 @@ static ssize_t store_measurement(struct device *d,
3640 3628
3641static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, 3629static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
3642 show_measurement, store_measurement); 3630 show_measurement, store_measurement);
3643#endif /* CONFIG_IWL3945_SPECTRUM_MEASUREMENT */
3644 3631
3645static ssize_t store_retry_rate(struct device *d, 3632static ssize_t store_retry_rate(struct device *d,
3646 struct device_attribute *attr, 3633 struct device_attribute *attr,
@@ -3789,7 +3776,6 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
3789 3776
3790 init_waitqueue_head(&priv->wait_command_queue); 3777 init_waitqueue_head(&priv->wait_command_queue);
3791 3778
3792 INIT_WORK(&priv->up, iwl3945_bg_up);
3793 INIT_WORK(&priv->restart, iwl3945_bg_restart); 3779 INIT_WORK(&priv->restart, iwl3945_bg_restart);
3794 INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish); 3780 INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish);
3795 INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); 3781 INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
@@ -3823,9 +3809,7 @@ static struct attribute *iwl3945_sysfs_entries[] = {
3823 &dev_attr_dump_errors.attr, 3809 &dev_attr_dump_errors.attr,
3824 &dev_attr_flags.attr, 3810 &dev_attr_flags.attr,
3825 &dev_attr_filter_flags.attr, 3811 &dev_attr_filter_flags.attr,
3826#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
3827 &dev_attr_measurement.attr, 3812 &dev_attr_measurement.attr,
3828#endif
3829 &dev_attr_retry_rate.attr, 3813 &dev_attr_retry_rate.attr,
3830 &dev_attr_statistics.attr, 3814 &dev_attr_statistics.attr,
3831 &dev_attr_status.attr, 3815 &dev_attr_status.attr,
@@ -3881,6 +3865,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
3881 priv->band = IEEE80211_BAND_2GHZ; 3865 priv->band = IEEE80211_BAND_2GHZ;
3882 3866
3883 priv->iw_mode = NL80211_IFTYPE_STATION; 3867 priv->iw_mode = NL80211_IFTYPE_STATION;
3868 priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
3884 3869
3885 iwl_reset_qos(priv); 3870 iwl_reset_qos(priv);
3886 3871
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index 5e650f358415..f03d5e4e59c3 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -1160,11 +1160,11 @@ int lbs_adhoc_stop(struct lbs_private *priv)
1160static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, 1160static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
1161 struct bss_descriptor *match_bss) 1161 struct bss_descriptor *match_bss)
1162{ 1162{
1163 if (!secinfo->wep_enabled && !secinfo->WPAenabled 1163 if (!secinfo->wep_enabled &&
1164 && !secinfo->WPA2enabled 1164 !secinfo->WPAenabled && !secinfo->WPA2enabled &&
1165 && match_bss->wpa_ie[0] != WLAN_EID_GENERIC 1165 match_bss->wpa_ie[0] != WLAN_EID_GENERIC &&
1166 && match_bss->rsn_ie[0] != WLAN_EID_RSN 1166 match_bss->rsn_ie[0] != WLAN_EID_RSN &&
1167 && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) 1167 !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
1168 return 1; 1168 return 1;
1169 else 1169 else
1170 return 0; 1170 return 0;
@@ -1173,9 +1173,9 @@ static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
1173static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, 1173static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
1174 struct bss_descriptor *match_bss) 1174 struct bss_descriptor *match_bss)
1175{ 1175{
1176 if (secinfo->wep_enabled && !secinfo->WPAenabled 1176 if (secinfo->wep_enabled &&
1177 && !secinfo->WPA2enabled 1177 !secinfo->WPAenabled && !secinfo->WPA2enabled &&
1178 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) 1178 (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
1179 return 1; 1179 return 1;
1180 else 1180 else
1181 return 0; 1181 return 0;
@@ -1184,8 +1184,8 @@ static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
1184static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, 1184static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
1185 struct bss_descriptor *match_bss) 1185 struct bss_descriptor *match_bss)
1186{ 1186{
1187 if (!secinfo->wep_enabled && secinfo->WPAenabled 1187 if (!secinfo->wep_enabled && secinfo->WPAenabled &&
1188 && (match_bss->wpa_ie[0] == WLAN_EID_GENERIC) 1188 (match_bss->wpa_ie[0] == WLAN_EID_GENERIC)
1189 /* privacy bit may NOT be set in some APs like LinkSys WRT54G 1189 /* privacy bit may NOT be set in some APs like LinkSys WRT54G
1190 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ 1190 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
1191 ) 1191 )
@@ -1210,11 +1210,11 @@ static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
1210static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, 1210static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
1211 struct bss_descriptor *match_bss) 1211 struct bss_descriptor *match_bss)
1212{ 1212{
1213 if (!secinfo->wep_enabled && !secinfo->WPAenabled 1213 if (!secinfo->wep_enabled &&
1214 && !secinfo->WPA2enabled 1214 !secinfo->WPAenabled && !secinfo->WPA2enabled &&
1215 && (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) 1215 (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) &&
1216 && (match_bss->rsn_ie[0] != WLAN_EID_RSN) 1216 (match_bss->rsn_ie[0] != WLAN_EID_RSN) &&
1217 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) 1217 (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
1218 return 1; 1218 return 1;
1219 else 1219 else
1220 return 0; 1220 return 0;
@@ -1525,8 +1525,8 @@ static int assoc_helper_associate(struct lbs_private *priv,
1525 /* If we're given and 'any' BSSID, try associating based on SSID */ 1525 /* If we're given and 'any' BSSID, try associating based on SSID */
1526 1526
1527 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { 1527 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
1528 if (compare_ether_addr(bssid_any, assoc_req->bssid) 1528 if (compare_ether_addr(bssid_any, assoc_req->bssid) &&
1529 && compare_ether_addr(bssid_off, assoc_req->bssid)) { 1529 compare_ether_addr(bssid_off, assoc_req->bssid)) {
1530 ret = assoc_helper_bssid(priv, assoc_req); 1530 ret = assoc_helper_bssid(priv, assoc_req);
1531 done = 1; 1531 done = 1;
1532 } 1532 }
@@ -1612,11 +1612,9 @@ static int assoc_helper_channel(struct lbs_private *priv,
1612 goto restore_mesh; 1612 goto restore_mesh;
1613 } 1613 }
1614 1614
1615 if ( assoc_req->secinfo.wep_enabled 1615 if (assoc_req->secinfo.wep_enabled &&
1616 && (assoc_req->wep_keys[0].len 1616 (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len ||
1617 || assoc_req->wep_keys[1].len 1617 assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)) {
1618 || assoc_req->wep_keys[2].len
1619 || assoc_req->wep_keys[3].len)) {
1620 /* Make sure WEP keys are re-sent to firmware */ 1618 /* Make sure WEP keys are re-sent to firmware */
1621 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); 1619 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
1622 } 1620 }
@@ -1983,14 +1981,14 @@ void lbs_association_worker(struct work_struct *work)
1983 assoc_req->secinfo.auth_mode); 1981 assoc_req->secinfo.auth_mode);
1984 1982
1985 /* If 'any' SSID was specified, find an SSID to associate with */ 1983 /* If 'any' SSID was specified, find an SSID to associate with */
1986 if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) 1984 if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) &&
1987 && !assoc_req->ssid_len) 1985 !assoc_req->ssid_len)
1988 find_any_ssid = 1; 1986 find_any_ssid = 1;
1989 1987
1990 /* But don't use 'any' SSID if there's a valid locked BSSID to use */ 1988 /* But don't use 'any' SSID if there's a valid locked BSSID to use */
1991 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { 1989 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
1992 if (compare_ether_addr(assoc_req->bssid, bssid_any) 1990 if (compare_ether_addr(assoc_req->bssid, bssid_any) &&
1993 && compare_ether_addr(assoc_req->bssid, bssid_off)) 1991 compare_ether_addr(assoc_req->bssid, bssid_off))
1994 find_any_ssid = 0; 1992 find_any_ssid = 0;
1995 } 1993 }
1996 1994
@@ -2052,13 +2050,6 @@ void lbs_association_worker(struct work_struct *work)
2052 goto out; 2050 goto out;
2053 } 2051 }
2054 2052
2055 if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)
2056 || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
2057 ret = assoc_helper_wep_keys(priv, assoc_req);
2058 if (ret)
2059 goto out;
2060 }
2061
2062 if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { 2053 if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
2063 ret = assoc_helper_secinfo(priv, assoc_req); 2054 ret = assoc_helper_secinfo(priv, assoc_req);
2064 if (ret) 2055 if (ret)
@@ -2071,18 +2062,31 @@ void lbs_association_worker(struct work_struct *work)
2071 goto out; 2062 goto out;
2072 } 2063 }
2073 2064
2074 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) 2065 /*
2075 || test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { 2066 * v10 FW wants WPA keys to be set/cleared before WEP key operations,
2067 * otherwise it will fail to correctly associate to WEP networks.
2068 * Other firmware versions don't appear to care.
2069 */
2070 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) ||
2071 test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
2076 ret = assoc_helper_wpa_keys(priv, assoc_req); 2072 ret = assoc_helper_wpa_keys(priv, assoc_req);
2077 if (ret) 2073 if (ret)
2078 goto out; 2074 goto out;
2079 } 2075 }
2080 2076
2077 if (test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) ||
2078 test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
2079 ret = assoc_helper_wep_keys(priv, assoc_req);
2080 if (ret)
2081 goto out;
2082 }
2083
2084
2081 /* SSID/BSSID should be the _last_ config option set, because they 2085 /* SSID/BSSID should be the _last_ config option set, because they
2082 * trigger the association attempt. 2086 * trigger the association attempt.
2083 */ 2087 */
2084 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) 2088 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) ||
2085 || test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { 2089 test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
2086 int success = 1; 2090 int success = 1;
2087 2091
2088 ret = assoc_helper_associate(priv, assoc_req); 2092 ret = assoc_helper_associate(priv, assoc_req);
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 84df3fcf37b3..0dbda8dfbd99 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -281,6 +281,8 @@ struct mac80211_hwsim_data {
281 struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; 281 struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)];
282 struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; 282 struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)];
283 283
284 struct mac_address addresses[2];
285
284 struct ieee80211_channel *channel; 286 struct ieee80211_channel *channel;
285 unsigned long beacon_int; /* in jiffies unit */ 287 unsigned long beacon_int; /* in jiffies unit */
286 unsigned int rx_filter; 288 unsigned int rx_filter;
@@ -1154,7 +1156,11 @@ static int __init init_mac80211_hwsim(void)
1154 SET_IEEE80211_DEV(hw, data->dev); 1156 SET_IEEE80211_DEV(hw, data->dev);
1155 addr[3] = i >> 8; 1157 addr[3] = i >> 8;
1156 addr[4] = i; 1158 addr[4] = i;
1157 SET_IEEE80211_PERM_ADDR(hw, addr); 1159 memcpy(data->addresses[0].addr, addr, ETH_ALEN);
1160 memcpy(data->addresses[1].addr, addr, ETH_ALEN);
1161 data->addresses[1].addr[0] |= 0x40;
1162 hw->wiphy->n_addresses = 2;
1163 hw->wiphy->addresses = data->addresses;
1158 1164
1159 hw->channel_change_time = 1; 1165 hw->channel_change_time = 1;
1160 hw->queues = 4; 1166 hw->queues = 4;
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 68546ca0ba37..f0f08f3919cc 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -3881,12 +3881,16 @@ static void mwl8k_finalize_join_worker(struct work_struct *work)
3881 struct mwl8k_priv *priv = 3881 struct mwl8k_priv *priv =
3882 container_of(work, struct mwl8k_priv, finalize_join_worker); 3882 container_of(work, struct mwl8k_priv, finalize_join_worker);
3883 struct sk_buff *skb = priv->beacon_skb; 3883 struct sk_buff *skb = priv->beacon_skb;
3884 struct mwl8k_vif *mwl8k_vif; 3884 struct ieee80211_mgmt *mgmt = (void *)skb->data;
3885 int len = skb->len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
3886 const u8 *tim = cfg80211_find_ie(WLAN_EID_TIM,
3887 mgmt->u.beacon.variable, len);
3888 int dtim_period = 1;
3889
3890 if (tim && tim[1] >= 2)
3891 dtim_period = tim[3];
3885 3892
3886 mwl8k_vif = mwl8k_first_vif(priv); 3893 mwl8k_cmd_finalize_join(priv->hw, skb->data, skb->len, dtim_period);
3887 if (mwl8k_vif != NULL)
3888 mwl8k_cmd_finalize_join(priv->hw, skb->data, skb->len,
3889 mwl8k_vif->vif->bss_conf.dtim_period);
3890 3894
3891 dev_kfree_skb(skb); 3895 dev_kfree_skb(skb);
3892 priv->beacon_skb = NULL; 3896 priv->beacon_skb = NULL;
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index 57c646598062..ed4bdffdd63e 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -157,6 +157,14 @@ static void p54p_refill_rx_ring(struct ieee80211_hw *dev,
157 skb_tail_pointer(skb), 157 skb_tail_pointer(skb),
158 priv->common.rx_mtu + 32, 158 priv->common.rx_mtu + 32,
159 PCI_DMA_FROMDEVICE); 159 PCI_DMA_FROMDEVICE);
160
161 if (pci_dma_mapping_error(priv->pdev, mapping)) {
162 dev_kfree_skb_any(skb);
163 dev_err(&priv->pdev->dev,
164 "RX DMA Mapping error\n");
165 break;
166 }
167
160 desc->host_addr = cpu_to_le32(mapping); 168 desc->host_addr = cpu_to_le32(mapping);
161 desc->device_addr = 0; // FIXME: necessary? 169 desc->device_addr = 0; // FIXME: necessary?
162 desc->len = cpu_to_le16(priv->common.rx_mtu + 32); 170 desc->len = cpu_to_le16(priv->common.rx_mtu + 32);
@@ -226,14 +234,14 @@ static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index,
226 p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf); 234 p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf);
227} 235}
228 236
229/* caller must hold priv->lock */
230static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, 237static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
231 int ring_index, struct p54p_desc *ring, u32 ring_limit, 238 int ring_index, struct p54p_desc *ring, u32 ring_limit,
232 void **tx_buf) 239 struct sk_buff **tx_buf)
233{ 240{
234 struct p54p_priv *priv = dev->priv; 241 struct p54p_priv *priv = dev->priv;
235 struct p54p_ring_control *ring_control = priv->ring_control; 242 struct p54p_ring_control *ring_control = priv->ring_control;
236 struct p54p_desc *desc; 243 struct p54p_desc *desc;
244 struct sk_buff *skb;
237 u32 idx, i; 245 u32 idx, i;
238 246
239 i = (*index) % ring_limit; 247 i = (*index) % ring_limit;
@@ -242,9 +250,8 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
242 250
243 while (i != idx) { 251 while (i != idx) {
244 desc = &ring[i]; 252 desc = &ring[i];
245 if (tx_buf[i]) 253
246 if (FREE_AFTER_TX((struct sk_buff *) tx_buf[i])) 254 skb = tx_buf[i];
247 p54_free_skb(dev, tx_buf[i]);
248 tx_buf[i] = NULL; 255 tx_buf[i] = NULL;
249 256
250 pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), 257 pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
@@ -255,17 +262,28 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
255 desc->len = 0; 262 desc->len = 0;
256 desc->flags = 0; 263 desc->flags = 0;
257 264
265 if (skb && FREE_AFTER_TX(skb))
266 p54_free_skb(dev, skb);
267
258 i++; 268 i++;
259 i %= ring_limit; 269 i %= ring_limit;
260 } 270 }
261} 271}
262 272
263static void p54p_rx_tasklet(unsigned long dev_id) 273static void p54p_tasklet(unsigned long dev_id)
264{ 274{
265 struct ieee80211_hw *dev = (struct ieee80211_hw *)dev_id; 275 struct ieee80211_hw *dev = (struct ieee80211_hw *)dev_id;
266 struct p54p_priv *priv = dev->priv; 276 struct p54p_priv *priv = dev->priv;
267 struct p54p_ring_control *ring_control = priv->ring_control; 277 struct p54p_ring_control *ring_control = priv->ring_control;
268 278
279 p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt,
280 ARRAY_SIZE(ring_control->tx_mgmt),
281 priv->tx_buf_mgmt);
282
283 p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data,
284 ARRAY_SIZE(ring_control->tx_data),
285 priv->tx_buf_data);
286
269 p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt, 287 p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt,
270 ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt); 288 ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt);
271 289
@@ -280,59 +298,49 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id)
280{ 298{
281 struct ieee80211_hw *dev = dev_id; 299 struct ieee80211_hw *dev = dev_id;
282 struct p54p_priv *priv = dev->priv; 300 struct p54p_priv *priv = dev->priv;
283 struct p54p_ring_control *ring_control = priv->ring_control;
284 __le32 reg; 301 __le32 reg;
285 302
286 spin_lock(&priv->lock);
287 reg = P54P_READ(int_ident); 303 reg = P54P_READ(int_ident);
288 if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) { 304 if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) {
289 spin_unlock(&priv->lock); 305 goto out;
290 return IRQ_HANDLED;
291 } 306 }
292
293 P54P_WRITE(int_ack, reg); 307 P54P_WRITE(int_ack, reg);
294 308
295 reg &= P54P_READ(int_enable); 309 reg &= P54P_READ(int_enable);
296 310
297 if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) { 311 if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE))
298 p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 312 tasklet_schedule(&priv->tasklet);
299 3, ring_control->tx_mgmt, 313 else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
300 ARRAY_SIZE(ring_control->tx_mgmt),
301 priv->tx_buf_mgmt);
302
303 p54p_check_tx_ring(dev, &priv->tx_idx_data,
304 1, ring_control->tx_data,
305 ARRAY_SIZE(ring_control->tx_data),
306 priv->tx_buf_data);
307
308 tasklet_schedule(&priv->rx_tasklet);
309
310 } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
311 complete(&priv->boot_comp); 314 complete(&priv->boot_comp);
312 315
313 spin_unlock(&priv->lock); 316out:
314
315 return reg ? IRQ_HANDLED : IRQ_NONE; 317 return reg ? IRQ_HANDLED : IRQ_NONE;
316} 318}
317 319
318static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb) 320static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
319{ 321{
322 unsigned long flags;
320 struct p54p_priv *priv = dev->priv; 323 struct p54p_priv *priv = dev->priv;
321 struct p54p_ring_control *ring_control = priv->ring_control; 324 struct p54p_ring_control *ring_control = priv->ring_control;
322 unsigned long flags;
323 struct p54p_desc *desc; 325 struct p54p_desc *desc;
324 dma_addr_t mapping; 326 dma_addr_t mapping;
325 u32 device_idx, idx, i; 327 u32 device_idx, idx, i;
326 328
327 spin_lock_irqsave(&priv->lock, flags); 329 spin_lock_irqsave(&priv->lock, flags);
328
329 device_idx = le32_to_cpu(ring_control->device_idx[1]); 330 device_idx = le32_to_cpu(ring_control->device_idx[1]);
330 idx = le32_to_cpu(ring_control->host_idx[1]); 331 idx = le32_to_cpu(ring_control->host_idx[1]);
331 i = idx % ARRAY_SIZE(ring_control->tx_data); 332 i = idx % ARRAY_SIZE(ring_control->tx_data);
332 333
333 priv->tx_buf_data[i] = skb;
334 mapping = pci_map_single(priv->pdev, skb->data, skb->len, 334 mapping = pci_map_single(priv->pdev, skb->data, skb->len,
335 PCI_DMA_TODEVICE); 335 PCI_DMA_TODEVICE);
336 if (pci_dma_mapping_error(priv->pdev, mapping)) {
337 spin_unlock_irqrestore(&priv->lock, flags);
338 p54_free_skb(dev, skb);
339 dev_err(&priv->pdev->dev, "TX DMA mapping error\n");
340 return ;
341 }
342 priv->tx_buf_data[i] = skb;
343
336 desc = &ring_control->tx_data[i]; 344 desc = &ring_control->tx_data[i];
337 desc->host_addr = cpu_to_le32(mapping); 345 desc->host_addr = cpu_to_le32(mapping);
338 desc->device_addr = ((struct p54_hdr *)skb->data)->req_id; 346 desc->device_addr = ((struct p54_hdr *)skb->data)->req_id;
@@ -354,14 +362,14 @@ static void p54p_stop(struct ieee80211_hw *dev)
354 unsigned int i; 362 unsigned int i;
355 struct p54p_desc *desc; 363 struct p54p_desc *desc;
356 364
357 tasklet_kill(&priv->rx_tasklet);
358
359 P54P_WRITE(int_enable, cpu_to_le32(0)); 365 P54P_WRITE(int_enable, cpu_to_le32(0));
360 P54P_READ(int_enable); 366 P54P_READ(int_enable);
361 udelay(10); 367 udelay(10);
362 368
363 free_irq(priv->pdev->irq, dev); 369 free_irq(priv->pdev->irq, dev);
364 370
371 tasklet_kill(&priv->tasklet);
372
365 P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); 373 P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
366 374
367 for (i = 0; i < ARRAY_SIZE(priv->rx_buf_data); i++) { 375 for (i = 0; i < ARRAY_SIZE(priv->rx_buf_data); i++) {
@@ -545,7 +553,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
545 priv->common.tx = p54p_tx; 553 priv->common.tx = p54p_tx;
546 554
547 spin_lock_init(&priv->lock); 555 spin_lock_init(&priv->lock);
548 tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev); 556 tasklet_init(&priv->tasklet, p54p_tasklet, (unsigned long)dev);
549 557
550 err = request_firmware(&priv->firmware, "isl3886pci", 558 err = request_firmware(&priv->firmware, "isl3886pci",
551 &priv->pdev->dev); 559 &priv->pdev->dev);
diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h
index fbb683953fb2..2feead617a3b 100644
--- a/drivers/net/wireless/p54/p54pci.h
+++ b/drivers/net/wireless/p54/p54pci.h
@@ -92,7 +92,7 @@ struct p54p_priv {
92 struct p54_common common; 92 struct p54_common common;
93 struct pci_dev *pdev; 93 struct pci_dev *pdev;
94 struct p54p_csr __iomem *map; 94 struct p54p_csr __iomem *map;
95 struct tasklet_struct rx_tasklet; 95 struct tasklet_struct tasklet;
96 const struct firmware *firmware; 96 const struct firmware *firmware;
97 spinlock_t lock; 97 spinlock_t lock;
98 struct p54p_ring_control *ring_control; 98 struct p54p_ring_control *ring_control;
@@ -101,8 +101,8 @@ struct p54p_priv {
101 u32 rx_idx_mgmt, tx_idx_mgmt; 101 u32 rx_idx_mgmt, tx_idx_mgmt;
102 struct sk_buff *rx_buf_data[8]; 102 struct sk_buff *rx_buf_data[8];
103 struct sk_buff *rx_buf_mgmt[4]; 103 struct sk_buff *rx_buf_mgmt[4];
104 void *tx_buf_data[32]; 104 struct sk_buff *tx_buf_data[32];
105 void *tx_buf_mgmt[4]; 105 struct sk_buff *tx_buf_mgmt[4];
106 struct completion boot_comp; 106 struct completion boot_comp;
107}; 107};
108 108
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c
index b9192bfcc557..2b928ecf47bd 100644
--- a/drivers/net/wireless/rtl818x/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c
@@ -761,6 +761,14 @@ static void rtl8180_configure_filter(struct ieee80211_hw *dev,
761 rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf); 761 rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf);
762} 762}
763 763
764static u64 rtl8180_get_tsf(struct ieee80211_hw *dev)
765{
766 struct rtl8180_priv *priv = dev->priv;
767
768 return rtl818x_ioread32(priv, &priv->map->TSFT[0]) |
769 (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32;
770}
771
764static const struct ieee80211_ops rtl8180_ops = { 772static const struct ieee80211_ops rtl8180_ops = {
765 .tx = rtl8180_tx, 773 .tx = rtl8180_tx,
766 .start = rtl8180_start, 774 .start = rtl8180_start,
@@ -771,6 +779,7 @@ static const struct ieee80211_ops rtl8180_ops = {
771 .bss_info_changed = rtl8180_bss_info_changed, 779 .bss_info_changed = rtl8180_bss_info_changed,
772 .prepare_multicast = rtl8180_prepare_multicast, 780 .prepare_multicast = rtl8180_prepare_multicast,
773 .configure_filter = rtl8180_configure_filter, 781 .configure_filter = rtl8180_configure_filter,
782 .get_tsf = rtl8180_get_tsf,
774}; 783};
775 784
776static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) 785static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom)
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index f336c63053c1..a05382557789 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -1265,6 +1265,14 @@ static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue,
1265 return 0; 1265 return 0;
1266} 1266}
1267 1267
1268static u64 rtl8187_get_tsf(struct ieee80211_hw *dev)
1269{
1270 struct rtl8187_priv *priv = dev->priv;
1271
1272 return rtl818x_ioread32(priv, &priv->map->TSFT[0]) |
1273 (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32;
1274}
1275
1268static const struct ieee80211_ops rtl8187_ops = { 1276static const struct ieee80211_ops rtl8187_ops = {
1269 .tx = rtl8187_tx, 1277 .tx = rtl8187_tx,
1270 .start = rtl8187_start, 1278 .start = rtl8187_start,
@@ -1276,7 +1284,8 @@ static const struct ieee80211_ops rtl8187_ops = {
1276 .prepare_multicast = rtl8187_prepare_multicast, 1284 .prepare_multicast = rtl8187_prepare_multicast,
1277 .configure_filter = rtl8187_configure_filter, 1285 .configure_filter = rtl8187_configure_filter,
1278 .conf_tx = rtl8187_conf_tx, 1286 .conf_tx = rtl8187_conf_tx,
1279 .rfkill_poll = rtl8187_rfkill_poll 1287 .rfkill_poll = rtl8187_rfkill_poll,
1288 .get_tsf = rtl8187_get_tsf,
1280}; 1289};
1281 1290
1282static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom) 1291static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom)
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h
index 6301578d1565..37c61c19cae5 100644
--- a/drivers/net/wireless/wl12xx/wl1251.h
+++ b/drivers/net/wireless/wl12xx/wl1251.h
@@ -341,9 +341,6 @@ struct wl1251 {
341 /* Are we currently scanning */ 341 /* Are we currently scanning */
342 bool scanning; 342 bool scanning;
343 343
344 /* Our association ID */
345 u16 aid;
346
347 /* Default key (for WEP) */ 344 /* Default key (for WEP) */
348 u32 default_key; 345 u32 default_key;
349 346
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index 595f0f94d16e..a717dde4822e 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -617,10 +617,13 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
617 617
618 wl->psm_requested = true; 618 wl->psm_requested = true;
619 619
620 wl->dtim_period = conf->ps_dtim_period;
621
622 ret = wl1251_acx_wr_tbtt_and_dtim(wl, wl->beacon_int,
623 wl->dtim_period);
624
620 /* 625 /*
621 * We enter PSM only if we're already associated. 626 * mac80211 enables PSM only if we're already associated.
622 * If we're not, we'll enter it when joining an SSID,
623 * through the bss_info_changed() hook.
624 */ 627 */
625 ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); 628 ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
626 if (ret < 0) 629 if (ret < 0)
@@ -943,7 +946,6 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
943 struct ieee80211_bss_conf *bss_conf, 946 struct ieee80211_bss_conf *bss_conf,
944 u32 changed) 947 u32 changed)
945{ 948{
946 enum wl1251_cmd_ps_mode mode;
947 struct wl1251 *wl = hw->priv; 949 struct wl1251 *wl = hw->priv;
948 struct sk_buff *beacon, *skb; 950 struct sk_buff *beacon, *skb;
949 int ret; 951 int ret;
@@ -984,11 +986,6 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
984 if (changed & BSS_CHANGED_ASSOC) { 986 if (changed & BSS_CHANGED_ASSOC) {
985 if (bss_conf->assoc) { 987 if (bss_conf->assoc) {
986 wl->beacon_int = bss_conf->beacon_int; 988 wl->beacon_int = bss_conf->beacon_int;
987 wl->dtim_period = bss_conf->dtim_period;
988
989 ret = wl1251_acx_wr_tbtt_and_dtim(wl, wl->beacon_int,
990 wl->dtim_period);
991 wl->aid = bss_conf->aid;
992 989
993 skb = ieee80211_pspoll_get(wl->hw, wl->vif); 990 skb = ieee80211_pspoll_get(wl->hw, wl->vif);
994 if (!skb) 991 if (!skb)
@@ -1001,17 +998,9 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
1001 if (ret < 0) 998 if (ret < 0)
1002 goto out_sleep; 999 goto out_sleep;
1003 1000
1004 ret = wl1251_acx_aid(wl, wl->aid); 1001 ret = wl1251_acx_aid(wl, bss_conf->aid);
1005 if (ret < 0) 1002 if (ret < 0)
1006 goto out_sleep; 1003 goto out_sleep;
1007
1008 /* If we want to go in PSM but we're not there yet */
1009 if (wl->psm_requested && !wl->psm) {
1010 mode = STATION_POWER_SAVE_MODE;
1011 ret = wl1251_ps_set_mode(wl, mode);
1012 if (ret < 0)
1013 goto out_sleep;
1014 }
1015 } else { 1004 } else {
1016 /* use defaults when not associated */ 1005 /* use defaults when not associated */
1017 wl->beacon_int = WL1251_DEFAULT_BEACON_INT; 1006 wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 842701906ae9..19984958ab7b 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -138,6 +138,8 @@
138#define IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK 0x03 138#define IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK 0x03
139#define IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT 5 139#define IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT 5
140 140
141#define IEEE80211_HT_CTL_LEN 4
142
141struct ieee80211_hdr { 143struct ieee80211_hdr {
142 __le16 frame_control; 144 __le16 frame_control;
143 __le16 duration_id; 145 __le16 duration_id;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 2af52704e670..a3f0a7ed31ac 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1195,6 +1195,10 @@ enum wiphy_flags {
1195 WIPHY_FLAG_4ADDR_STATION = BIT(6), 1195 WIPHY_FLAG_4ADDR_STATION = BIT(6),
1196}; 1196};
1197 1197
1198struct mac_address {
1199 u8 addr[ETH_ALEN];
1200};
1201
1198/** 1202/**
1199 * struct wiphy - wireless hardware description 1203 * struct wiphy - wireless hardware description
1200 * @idx: the wiphy index assigned to this item 1204 * @idx: the wiphy index assigned to this item
@@ -1213,12 +1217,28 @@ enum wiphy_flags {
1213 * -1 = fragmentation disabled, only odd values >= 256 used 1217 * -1 = fragmentation disabled, only odd values >= 256 used
1214 * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled 1218 * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled
1215 * @net: the network namespace this wiphy currently lives in 1219 * @net: the network namespace this wiphy currently lives in
1220 * @perm_addr: permanent MAC address of this device
1221 * @addr_mask: If the device supports multiple MAC addresses by masking,
1222 * set this to a mask with variable bits set to 1, e.g. if the last
1223 * four bits are variable then set it to 00:...:00:0f. The actual
1224 * variable bits shall be determined by the interfaces added, with
1225 * interfaces not matching the mask being rejected to be brought up.
1226 * @n_addresses: number of addresses in @addresses.
1227 * @addresses: If the device has more than one address, set this pointer
1228 * to a list of addresses (6 bytes each). The first one will be used
1229 * by default for perm_addr. In this case, the mask should be set to
1230 * all-zeroes. In this case it is assumed that the device can handle
1231 * the same number of arbitrary MAC addresses.
1216 */ 1232 */
1217struct wiphy { 1233struct wiphy {
1218 /* assign these fields before you register the wiphy */ 1234 /* assign these fields before you register the wiphy */
1219 1235
1220 /* permanent MAC address */ 1236 /* permanent MAC address(es) */
1221 u8 perm_addr[ETH_ALEN]; 1237 u8 perm_addr[ETH_ALEN];
1238 u8 addr_mask[ETH_ALEN];
1239
1240 u16 n_addresses;
1241 struct mac_address *addresses;
1222 1242
1223 /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ 1243 /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */
1224 u16 interface_modes; 1244 u16 interface_modes;
@@ -1638,6 +1658,22 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
1638 */ 1658 */
1639unsigned int cfg80211_classify8021d(struct sk_buff *skb); 1659unsigned int cfg80211_classify8021d(struct sk_buff *skb);
1640 1660
1661/**
1662 * cfg80211_find_ie - find information element in data
1663 *
1664 * @eid: element ID
1665 * @ies: data consisting of IEs
1666 * @len: length of data
1667 *
1668 * This function will return %NULL if the element ID could
1669 * not be found or if the element is invalid (claims to be
1670 * longer than the given data), or a pointer to the first byte
1671 * of the requested element, that is the byte containing the
1672 * element ID. There are no checks on the element length
1673 * other than having to fit into the given data.
1674 */
1675const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len);
1676
1641/* 1677/*
1642 * Regulatory helper functions for wiphys 1678 * Regulatory helper functions for wiphys
1643 */ 1679 */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index c90047de4428..74ccf30fdf8e 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -186,7 +186,8 @@ enum ieee80211_bss_change {
186 * @use_short_slot: use short slot time (only relevant for ERP); 186 * @use_short_slot: use short slot time (only relevant for ERP);
187 * if the hardware cannot handle this it must set the 187 * if the hardware cannot handle this it must set the
188 * IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag 188 * IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag
189 * @dtim_period: num of beacons before the next DTIM, for PSM 189 * @dtim_period: num of beacons before the next DTIM, for beaconing,
190 * not valid in station mode (cf. hw conf ps_dtim_period)
190 * @timestamp: beacon timestamp 191 * @timestamp: beacon timestamp
191 * @beacon_int: beacon interval 192 * @beacon_int: beacon interval
192 * @assoc_capability: capabilities taken from assoc resp 193 * @assoc_capability: capabilities taken from assoc resp
@@ -271,6 +272,11 @@ struct ieee80211_bss_conf {
271 * transmit function after the current frame, this can be used 272 * transmit function after the current frame, this can be used
272 * by drivers to kick the DMA queue only if unset or when the 273 * by drivers to kick the DMA queue only if unset or when the
273 * queue gets full. 274 * queue gets full.
275 * @IEEE80211_TX_INTFL_RETRANSMISSION: This frame is being retransmitted
276 * after TX status because the destination was asleep, it must not
277 * be modified again (no seqno assignment, crypto, etc.)
278 * @IEEE80211_TX_INTFL_HAS_RADIOTAP: This frame was injected and still
279 * has a radiotap header at skb->data.
274 */ 280 */
275enum mac80211_tx_control_flags { 281enum mac80211_tx_control_flags {
276 IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), 282 IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
@@ -291,6 +297,8 @@ enum mac80211_tx_control_flags {
291 IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16), 297 IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16),
292 IEEE80211_TX_CTL_PSPOLL_RESPONSE = BIT(17), 298 IEEE80211_TX_CTL_PSPOLL_RESPONSE = BIT(17),
293 IEEE80211_TX_CTL_MORE_FRAMES = BIT(18), 299 IEEE80211_TX_CTL_MORE_FRAMES = BIT(18),
300 IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19),
301 IEEE80211_TX_INTFL_HAS_RADIOTAP = BIT(20),
294}; 302};
295 303
296/** 304/**
@@ -644,6 +652,9 @@ enum ieee80211_smps_mode {
644 * value will be only achievable between DTIM frames, the hardware 652 * value will be only achievable between DTIM frames, the hardware
645 * needs to check for the multicast traffic bit in DTIM beacons. 653 * needs to check for the multicast traffic bit in DTIM beacons.
646 * This variable is valid only when the CONF_PS flag is set. 654 * This variable is valid only when the CONF_PS flag is set.
655 * @ps_dtim_period: The DTIM period of the AP we're connected to, for use
656 * in power saving. Power saving will not be enabled until a beacon
657 * has been received and the DTIM period is known.
647 * @dynamic_ps_timeout: The dynamic powersave timeout (in ms), see the 658 * @dynamic_ps_timeout: The dynamic powersave timeout (in ms), see the
648 * powersave documentation below. This variable is valid only when 659 * powersave documentation below. This variable is valid only when
649 * the CONF_PS flag is set. 660 * the CONF_PS flag is set.
@@ -670,6 +681,7 @@ struct ieee80211_conf {
670 int max_sleep_period; 681 int max_sleep_period;
671 682
672 u16 listen_interval; 683 u16 listen_interval;
684 u8 ps_dtim_period;
673 685
674 u8 long_frame_max_tx_count, short_frame_max_tx_count; 686 u8 long_frame_max_tx_count, short_frame_max_tx_count;
675 687
@@ -1485,7 +1497,7 @@ enum ieee80211_ampdu_mlme_action {
1485 * @update_tkip_key: See the section "Hardware crypto acceleration" 1497 * @update_tkip_key: See the section "Hardware crypto acceleration"
1486 * This callback will be called in the context of Rx. Called for drivers 1498 * This callback will be called in the context of Rx. Called for drivers
1487 * which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY. 1499 * which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY.
1488 * The callback can sleep. 1500 * The callback must be atomic.
1489 * 1501 *
1490 * @hw_scan: Ask the hardware to service the scan request, no need to start 1502 * @hw_scan: Ask the hardware to service the scan request, no need to start
1491 * the scan state machine in stack. The scan must honour the channel 1503 * the scan state machine in stack. The scan must honour the channel
@@ -1610,8 +1622,10 @@ struct ieee80211_ops {
1610 struct ieee80211_vif *vif, struct ieee80211_sta *sta, 1622 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
1611 struct ieee80211_key_conf *key); 1623 struct ieee80211_key_conf *key);
1612 void (*update_tkip_key)(struct ieee80211_hw *hw, 1624 void (*update_tkip_key)(struct ieee80211_hw *hw,
1613 struct ieee80211_key_conf *conf, const u8 *address, 1625 struct ieee80211_vif *vif,
1614 u32 iv32, u16 *phase1key); 1626 struct ieee80211_key_conf *conf,
1627 struct ieee80211_sta *sta,
1628 u32 iv32, u16 *phase1key);
1615 int (*hw_scan)(struct ieee80211_hw *hw, 1629 int (*hw_scan)(struct ieee80211_hw *hw,
1616 struct cfg80211_scan_request *req); 1630 struct cfg80211_scan_request *req);
1617 void (*sw_scan_start)(struct ieee80211_hw *hw); 1631 void (*sw_scan_start)(struct ieee80211_hw *hw);
diff --git a/include/net/regulatory.h b/include/net/regulatory.h
index 47995b81c5d7..f873ee37f7e4 100644
--- a/include/net/regulatory.h
+++ b/include/net/regulatory.h
@@ -39,6 +39,7 @@ enum environment_cap {
39 * 00 - World regulatory domain 39 * 00 - World regulatory domain
40 * 99 - built by driver but a specific alpha2 cannot be determined 40 * 99 - built by driver but a specific alpha2 cannot be determined
41 * 98 - result of an intersection between two regulatory domains 41 * 98 - result of an intersection between two regulatory domains
42 * 97 - regulatory domain has not yet been configured
42 * @intersect: indicates whether the wireless core should intersect 43 * @intersect: indicates whether the wireless core should intersect
43 * the requested regulatory domain with the presently set regulatory 44 * the requested regulatory domain with the presently set regulatory
44 * domain. 45 * domain.
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 0d4a759ba72c..d92800bb2d2f 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -120,36 +120,38 @@ STA_OPS(last_seq_ctrl);
120static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, 120static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
121 size_t count, loff_t *ppos) 121 size_t count, loff_t *ppos)
122{ 122{
123 char buf[30 + STA_TID_NUM * 70], *p = buf; 123 char buf[64 + STA_TID_NUM * 40], *p = buf;
124 int i; 124 int i;
125 struct sta_info *sta = file->private_data; 125 struct sta_info *sta = file->private_data;
126 126
127 spin_lock_bh(&sta->lock); 127 spin_lock_bh(&sta->lock);
128 p += scnprintf(p, sizeof(buf)+buf-p, "next dialog_token is %#02x\n", 128 p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n",
129 sta->ampdu_mlme.dialog_token_allocator + 1); 129 sta->ampdu_mlme.dialog_token_allocator + 1);
130 p += scnprintf(p, sizeof(buf) + buf - p,
131 "TID\t\tRX\tDTKN\tSSN\t\tTX\tDTKN\tSSN\tpending\n");
130 for (i = 0; i < STA_TID_NUM; i++) { 132 for (i = 0; i < STA_TID_NUM; i++) {
131 p += scnprintf(p, sizeof(buf)+buf-p, "TID %02d:", i); 133 p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i);
132 p += scnprintf(p, sizeof(buf)+buf-p, " RX=%x", 134 p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x",
133 sta->ampdu_mlme.tid_state_rx[i]); 135 sta->ampdu_mlme.tid_state_rx[i]);
134 p += scnprintf(p, sizeof(buf)+buf-p, "/DTKN=%#.2x", 136 p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
135 sta->ampdu_mlme.tid_state_rx[i] ? 137 sta->ampdu_mlme.tid_state_rx[i] ?
136 sta->ampdu_mlme.tid_rx[i]->dialog_token : 0); 138 sta->ampdu_mlme.tid_rx[i]->dialog_token : 0);
137 p += scnprintf(p, sizeof(buf)+buf-p, "/SSN=%#.3x", 139 p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x",
138 sta->ampdu_mlme.tid_state_rx[i] ? 140 sta->ampdu_mlme.tid_state_rx[i] ?
139 sta->ampdu_mlme.tid_rx[i]->ssn : 0); 141 sta->ampdu_mlme.tid_rx[i]->ssn : 0);
140 142
141 p += scnprintf(p, sizeof(buf)+buf-p, " TX=%x", 143 p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x",
142 sta->ampdu_mlme.tid_state_tx[i]); 144 sta->ampdu_mlme.tid_state_tx[i]);
143 p += scnprintf(p, sizeof(buf)+buf-p, "/DTKN=%#.2x", 145 p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
144 sta->ampdu_mlme.tid_state_tx[i] ? 146 sta->ampdu_mlme.tid_state_tx[i] ?
145 sta->ampdu_mlme.tid_tx[i]->dialog_token : 0); 147 sta->ampdu_mlme.tid_tx[i]->dialog_token : 0);
146 p += scnprintf(p, sizeof(buf)+buf-p, "/SSN=%#.3x", 148 p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x",
147 sta->ampdu_mlme.tid_state_tx[i] ? 149 sta->ampdu_mlme.tid_state_tx[i] ?
148 sta->ampdu_mlme.tid_tx[i]->ssn : 0); 150 sta->ampdu_mlme.tid_tx[i]->ssn : 0);
149 p += scnprintf(p, sizeof(buf)+buf-p, "/pending=%03d", 151 p += scnprintf(p, sizeof(buf) + buf - p, "\t%03d",
150 sta->ampdu_mlme.tid_state_tx[i] ? 152 sta->ampdu_mlme.tid_state_tx[i] ?
151 skb_queue_len(&sta->ampdu_mlme.tid_tx[i]->pending) : 0); 153 skb_queue_len(&sta->ampdu_mlme.tid_tx[i]->pending) : 0);
152 p += scnprintf(p, sizeof(buf)+buf-p, "\n"); 154 p += scnprintf(p, sizeof(buf) + buf - p, "\n");
153 } 155 }
154 spin_unlock_bh(&sta->lock); 156 spin_unlock_bh(&sta->lock);
155 157
@@ -165,7 +167,7 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
165 if (_cond) \ 167 if (_cond) \
166 p += scnprintf(p, sizeof(buf)+buf-p, "\t" _str "\n"); \ 168 p += scnprintf(p, sizeof(buf)+buf-p, "\t" _str "\n"); \
167 } while (0) 169 } while (0)
168 char buf[1024], *p = buf; 170 char buf[512], *p = buf;
169 int i; 171 int i;
170 struct sta_info *sta = file->private_data; 172 struct sta_info *sta = file->private_data;
171 struct ieee80211_sta_ht_cap *htc = &sta->sta.ht_cap; 173 struct ieee80211_sta_ht_cap *htc = &sta->sta.ht_cap;
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index de91d39e0276..6c31f38ac7f5 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -137,16 +137,20 @@ static inline int drv_set_key(struct ieee80211_local *local,
137} 137}
138 138
139static inline void drv_update_tkip_key(struct ieee80211_local *local, 139static inline void drv_update_tkip_key(struct ieee80211_local *local,
140 struct ieee80211_sub_if_data *sdata,
140 struct ieee80211_key_conf *conf, 141 struct ieee80211_key_conf *conf,
141 const u8 *address, u32 iv32, 142 struct sta_info *sta, u32 iv32,
142 u16 *phase1key) 143 u16 *phase1key)
143{ 144{
144 might_sleep(); 145 struct ieee80211_sta *ista = NULL;
146
147 if (sta)
148 ista = &sta->sta;
145 149
146 if (local->ops->update_tkip_key) 150 if (local->ops->update_tkip_key)
147 local->ops->update_tkip_key(&local->hw, conf, address, 151 local->ops->update_tkip_key(&local->hw, &sdata->vif, conf,
148 iv32, phase1key); 152 ista, iv32, phase1key);
149 trace_drv_update_tkip_key(local, conf, address, iv32); 153 trace_drv_update_tkip_key(local, sdata, conf, ista, iv32);
150} 154}
151 155
152static inline int drv_hw_scan(struct ieee80211_local *local, 156static inline int drv_hw_scan(struct ieee80211_local *local,
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index d6bd9f517401..502424b2538a 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -331,26 +331,29 @@ TRACE_EVENT(drv_set_key,
331 331
332TRACE_EVENT(drv_update_tkip_key, 332TRACE_EVENT(drv_update_tkip_key,
333 TP_PROTO(struct ieee80211_local *local, 333 TP_PROTO(struct ieee80211_local *local,
334 struct ieee80211_sub_if_data *sdata,
334 struct ieee80211_key_conf *conf, 335 struct ieee80211_key_conf *conf,
335 const u8 *address, u32 iv32), 336 struct ieee80211_sta *sta, u32 iv32),
336 337
337 TP_ARGS(local, conf, address, iv32), 338 TP_ARGS(local, sdata, conf, sta, iv32),
338 339
339 TP_STRUCT__entry( 340 TP_STRUCT__entry(
340 LOCAL_ENTRY 341 LOCAL_ENTRY
341 __array(u8, addr, 6) 342 VIF_ENTRY
343 STA_ENTRY
342 __field(u32, iv32) 344 __field(u32, iv32)
343 ), 345 ),
344 346
345 TP_fast_assign( 347 TP_fast_assign(
346 LOCAL_ASSIGN; 348 LOCAL_ASSIGN;
347 memcpy(__entry->addr, address, 6); 349 VIF_ASSIGN;
350 STA_ASSIGN;
348 __entry->iv32 = iv32; 351 __entry->iv32 = iv32;
349 ), 352 ),
350 353
351 TP_printk( 354 TP_printk(
352 LOCAL_PR_FMT " addr:%pM iv32:%#x", 355 LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " iv32:%#x",
353 LOCAL_PR_ARG, __entry->addr, __entry->iv32 356 LOCAL_PR_ARG,VIF_PR_ARG,STA_PR_ARG, __entry->iv32
354 ) 357 )
355); 358);
356 359
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 5bcde4c3fba1..f95750b423e3 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -293,12 +293,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
293 293
294 /* check if we need to merge IBSS */ 294 /* check if we need to merge IBSS */
295 295
296 /* merge only on beacons (???) */
297 if (!beacon)
298 goto put_bss;
299
300 /* we use a fixed BSSID */ 296 /* we use a fixed BSSID */
301 if (sdata->u.ibss.bssid) 297 if (sdata->u.ibss.fixed_bssid)
302 goto put_bss; 298 goto put_bss;
303 299
304 /* not an IBSS */ 300 /* not an IBSS */
@@ -454,6 +450,9 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
454 return active; 450 return active;
455} 451}
456 452
453/*
454 * This function is called with state == IEEE80211_IBSS_MLME_JOINED
455 */
457 456
458static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) 457static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
459{ 458{
@@ -519,6 +518,10 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
519 capability, 0); 518 capability, 0);
520} 519}
521 520
521/*
522 * This function is called with state == IEEE80211_IBSS_MLME_SEARCH
523 */
524
522static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) 525static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
523{ 526{
524 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 527 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
@@ -575,18 +578,14 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
575#endif /* CONFIG_MAC80211_IBSS_DEBUG */ 578#endif /* CONFIG_MAC80211_IBSS_DEBUG */
576 579
577 /* Selected IBSS not found in current scan results - try to scan */ 580 /* Selected IBSS not found in current scan results - try to scan */
578 if (ifibss->state == IEEE80211_IBSS_MLME_JOINED && 581 if (time_after(jiffies, ifibss->last_scan_completed +
579 !ieee80211_sta_active_ibss(sdata)) {
580 mod_timer(&ifibss->timer,
581 round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
582 } else if (time_after(jiffies, ifibss->last_scan_completed +
583 IEEE80211_SCAN_INTERVAL)) { 582 IEEE80211_SCAN_INTERVAL)) {
584 printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " 583 printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
585 "join\n", sdata->name); 584 "join\n", sdata->name);
586 585
587 ieee80211_request_internal_scan(sdata, ifibss->ssid, 586 ieee80211_request_internal_scan(sdata, ifibss->ssid,
588 ifibss->ssid_len); 587 ifibss->ssid_len);
589 } else if (ifibss->state != IEEE80211_IBSS_MLME_JOINED) { 588 } else {
590 int interval = IEEE80211_SCAN_INTERVAL; 589 int interval = IEEE80211_SCAN_INTERVAL;
591 590
592 if (time_after(jiffies, ifibss->ibss_join_req + 591 if (time_after(jiffies, ifibss->ibss_join_req +
@@ -604,7 +603,6 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
604 interval = IEEE80211_SCAN_INTERVAL_SLOW; 603 interval = IEEE80211_SCAN_INTERVAL_SLOW;
605 } 604 }
606 605
607 ifibss->state = IEEE80211_IBSS_MLME_SEARCH;
608 mod_timer(&ifibss->timer, 606 mod_timer(&ifibss->timer,
609 round_jiffies(jiffies + interval)); 607 round_jiffies(jiffies + interval));
610 } 608 }
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index c18f576f1848..3067fbd69d63 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -299,7 +299,6 @@ struct ieee80211_work {
299 } assoc; 299 } assoc;
300 struct { 300 struct {
301 u32 duration; 301 u32 duration;
302 bool started;
303 } remain; 302 } remain;
304 }; 303 };
305 304
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index edf21cebeee8..09fff4662e80 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -695,10 +695,14 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev,
695 695
696 hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); 696 hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
697 697
698 if (!ieee80211_is_data_qos(hdr->frame_control)) { 698 if (!ieee80211_is_data(hdr->frame_control)) {
699 skb->priority = 7; 699 skb->priority = 7;
700 return ieee802_1d_to_ac[skb->priority]; 700 return ieee802_1d_to_ac[skb->priority];
701 } 701 }
702 if (!ieee80211_is_data_qos(hdr->frame_control)) {
703 skb->priority = 0;
704 return ieee802_1d_to_ac[skb->priority];
705 }
702 706
703 p = ieee80211_get_qos_ctl(hdr); 707 p = ieee80211_get_qos_ctl(hdr);
704 skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK; 708 skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1e1d16c55ee5..86c6ad1b058d 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -484,6 +484,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
484 484
485 if (count == 1 && found->u.mgd.powersave && 485 if (count == 1 && found->u.mgd.powersave &&
486 found->u.mgd.associated && 486 found->u.mgd.associated &&
487 found->u.mgd.associated->beacon_ies &&
487 !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | 488 !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL |
488 IEEE80211_STA_CONNECTION_POLL))) { 489 IEEE80211_STA_CONNECTION_POLL))) {
489 s32 beaconint_us; 490 s32 beaconint_us;
@@ -497,14 +498,22 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
497 if (beaconint_us > latency) { 498 if (beaconint_us > latency) {
498 local->ps_sdata = NULL; 499 local->ps_sdata = NULL;
499 } else { 500 } else {
500 u8 dtimper = found->vif.bss_conf.dtim_period; 501 struct ieee80211_bss *bss;
501 int maxslp = 1; 502 int maxslp = 1;
503 u8 dtimper;
502 504
503 if (dtimper > 1) 505 bss = (void *)found->u.mgd.associated->priv;
506 dtimper = bss->dtim_period;
507
508 /* If the TIM IE is invalid, pretend the value is 1 */
509 if (!dtimper)
510 dtimper = 1;
511 else if (dtimper > 1)
504 maxslp = min_t(int, dtimper, 512 maxslp = min_t(int, dtimper,
505 latency / beaconint_us); 513 latency / beaconint_us);
506 514
507 local->hw.conf.max_sleep_period = maxslp; 515 local->hw.conf.max_sleep_period = maxslp;
516 local->hw.conf.ps_dtim_period = dtimper;
508 local->ps_sdata = found; 517 local->ps_sdata = found;
509 } 518 }
510 } else { 519 } else {
@@ -702,7 +711,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
702 /* set timing information */ 711 /* set timing information */
703 sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; 712 sdata->vif.bss_conf.beacon_int = cbss->beacon_interval;
704 sdata->vif.bss_conf.timestamp = cbss->tsf; 713 sdata->vif.bss_conf.timestamp = cbss->tsf;
705 sdata->vif.bss_conf.dtim_period = bss->dtim_period;
706 714
707 bss_info_changed |= BSS_CHANGED_BEACON_INT; 715 bss_info_changed |= BSS_CHANGED_BEACON_INT;
708 bss_info_changed |= ieee80211_handle_bss_capability(sdata, 716 bss_info_changed |= ieee80211_handle_bss_capability(sdata,
@@ -1168,6 +1176,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
1168 int freq; 1176 int freq;
1169 struct ieee80211_bss *bss; 1177 struct ieee80211_bss *bss;
1170 struct ieee80211_channel *channel; 1178 struct ieee80211_channel *channel;
1179 bool need_ps = false;
1180
1181 if (sdata->u.mgd.associated) {
1182 bss = (void *)sdata->u.mgd.associated->priv;
1183 /* not previously set so we may need to recalc */
1184 need_ps = !bss->dtim_period;
1185 }
1171 1186
1172 if (elems->ds_params && elems->ds_params_len == 1) 1187 if (elems->ds_params && elems->ds_params_len == 1)
1173 freq = ieee80211_channel_to_frequency(elems->ds_params[0]); 1188 freq = ieee80211_channel_to_frequency(elems->ds_params[0]);
@@ -1187,6 +1202,12 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
1187 if (!sdata->u.mgd.associated) 1202 if (!sdata->u.mgd.associated)
1188 return; 1203 return;
1189 1204
1205 if (need_ps) {
1206 mutex_lock(&local->iflist_mtx);
1207 ieee80211_recalc_ps(local, -1);
1208 mutex_unlock(&local->iflist_mtx);
1209 }
1210
1190 if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) && 1211 if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) &&
1191 (memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, 1212 (memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid,
1192 ETH_ALEN) == 0)) { 1213 ETH_ALEN) == 0)) {
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index 669dddd40521..998cf7a935b6 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -44,6 +44,10 @@ static inline void rate_control_tx_status(struct ieee80211_local *local,
44 struct rate_control_ref *ref = local->rate_ctrl; 44 struct rate_control_ref *ref = local->rate_ctrl;
45 struct ieee80211_sta *ista = &sta->sta; 45 struct ieee80211_sta *ista = &sta->sta;
46 void *priv_sta = sta->rate_ctrl_priv; 46 void *priv_sta = sta->rate_ctrl_priv;
47
48 if (!ref)
49 return;
50
47 ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); 51 ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb);
48} 52}
49 53
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c
index 29bc4c516238..2652a374974e 100644
--- a/net/mac80211/rc80211_pid_algo.c
+++ b/net/mac80211/rc80211_pid_algo.c
@@ -157,9 +157,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
157 157
158 /* In case nothing happened during the previous control interval, turn 158 /* In case nothing happened during the previous control interval, turn
159 * the sharpening factor on. */ 159 * the sharpening factor on. */
160 period = (HZ * pinfo->sampling_period + 500) / 1000; 160 period = msecs_to_jiffies(pinfo->sampling_period);
161 if (!period)
162 period = 1;
163 if (jiffies - spinfo->last_sample > 2 * period) 161 if (jiffies - spinfo->last_sample > 2 * period)
164 spinfo->sharp_cnt = pinfo->sharpen_duration; 162 spinfo->sharp_cnt = pinfo->sharpen_duration;
165 163
@@ -252,9 +250,7 @@ static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_ba
252 } 250 }
253 251
254 /* Update PID controller state. */ 252 /* Update PID controller state. */
255 period = (HZ * pinfo->sampling_period + 500) / 1000; 253 period = msecs_to_jiffies(pinfo->sampling_period);
256 if (!period)
257 period = 1;
258 if (time_after(jiffies, spinfo->last_sample + period)) 254 if (time_after(jiffies, spinfo->last_sample + period))
259 rate_control_pid_sample(pinfo, sband, sta, spinfo); 255 rate_control_pid_sample(pinfo, sband, sta, spinfo);
260} 256}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index a8e15b84c05b..5709307fcb9b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2348,22 +2348,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2348 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 2348 sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
2349 continue; 2349 continue;
2350 2350
2351 rx.sta = sta_info_get(sdata, hdr->addr2);
2352
2353 rx.flags |= IEEE80211_RX_RA_MATCH;
2354 prepares = prepare_for_handlers(sdata, &rx, hdr);
2355
2356 if (!prepares)
2357 continue;
2358
2359 if (status->flag & RX_FLAG_MMIC_ERROR) {
2360 rx.sdata = sdata;
2361 if (rx.flags & IEEE80211_RX_RA_MATCH)
2362 ieee80211_rx_michael_mic_report(hdr,
2363 &rx);
2364 continue;
2365 }
2366
2367 /* 2351 /*
2368 * frame is destined for this interface, but if it's 2352 * frame is destined for this interface, but if it's
2369 * not also for the previous one we handle that after 2353 * not also for the previous one we handle that after
@@ -2375,6 +2359,22 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2375 continue; 2359 continue;
2376 } 2360 }
2377 2361
2362 rx.sta = sta_info_get_bss(prev, hdr->addr2);
2363
2364 rx.flags |= IEEE80211_RX_RA_MATCH;
2365 prepares = prepare_for_handlers(prev, &rx, hdr);
2366
2367 if (!prepares)
2368 goto next;
2369
2370 if (status->flag & RX_FLAG_MMIC_ERROR) {
2371 rx.sdata = prev;
2372 if (rx.flags & IEEE80211_RX_RA_MATCH)
2373 ieee80211_rx_michael_mic_report(hdr,
2374 &rx);
2375 goto next;
2376 }
2377
2378 /* 2378 /*
2379 * frame was destined for the previous interface 2379 * frame was destined for the previous interface
2380 * so invoke RX handlers for it 2380 * so invoke RX handlers for it
@@ -2387,11 +2387,22 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2387 "multicast frame for %s\n", 2387 "multicast frame for %s\n",
2388 wiphy_name(local->hw.wiphy), 2388 wiphy_name(local->hw.wiphy),
2389 prev->name); 2389 prev->name);
2390 continue; 2390 goto next;
2391 } 2391 }
2392 ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate); 2392 ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate);
2393next:
2393 prev = sdata; 2394 prev = sdata;
2394 } 2395 }
2396
2397 if (prev) {
2398 rx.sta = sta_info_get_bss(prev, hdr->addr2);
2399
2400 rx.flags |= IEEE80211_RX_RA_MATCH;
2401 prepares = prepare_for_handlers(prev, &rx, hdr);
2402
2403 if (!prepares)
2404 prev = NULL;
2405 }
2395 } 2406 }
2396 if (prev) 2407 if (prev)
2397 ieee80211_invoke_rx_handlers(prev, &rx, skb, rate); 2408 ieee80211_invoke_rx_handlers(prev, &rx, skb, rate);
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 9afe2f9885dc..bc061f629674 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -111,10 +111,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
111 bss->dtim_period = tim_ie->dtim_period; 111 bss->dtim_period = tim_ie->dtim_period;
112 } 112 }
113 113
114 /* set default value for buggy AP/no TIM element */
115 if (bss->dtim_period == 0)
116 bss->dtim_period = 1;
117
118 bss->supp_rates_len = 0; 114 bss->supp_rates_len = 0;
119 if (elems->supp_rates) { 115 if (elems->supp_rates) {
120 clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; 116 clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 0ebcdda24200..e57ad6b1d7ea 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -45,29 +45,19 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
45 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 45 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
46 46
47 /* 47 /*
48 * XXX: This is temporary! 48 * This skb 'survived' a round-trip through the driver, and
49 * 49 * hopefully the driver didn't mangle it too badly. However,
50 * The problem here is that when we get here, the driver will 50 * we can definitely not rely on the the control information
51 * quite likely have pretty much overwritten info->control by 51 * being correct. Clear it so we don't get junk there, and
52 * using info->driver_data or info->rate_driver_data. Thus, 52 * indicate that it needs new processing, but must not be
53 * when passing out the frame to the driver again, we would be 53 * modified/encrypted again.
54 * passing completely bogus data since the driver would then
55 * expect a properly filled info->control. In mac80211 itself
56 * the same problem occurs, since we need info->control.vif
57 * internally.
58 *
59 * To fix this, we should send the frame through TX processing
60 * again. However, it's not that simple, since the frame will
61 * have been software-encrypted (if applicable) already, and
62 * encrypting it again doesn't do much good. So to properly do
63 * that, we not only have to skip the actual 'raw' encryption
64 * (key selection etc. still has to be done!) but also the
65 * sequence number assignment since that impacts the crypto
66 * encapsulation, of course.
67 *
68 * Hence, for now, fix the bug by just dropping the frame.
69 */ 54 */
70 goto drop; 55 memset(&info->control, 0, sizeof(info->control));
56
57 info->control.jiffies = jiffies;
58 info->control.vif = &sta->sdata->vif;
59 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING |
60 IEEE80211_TX_INTFL_RETRANSMISSION;
71 61
72 sta->tx_filtered_count++; 62 sta->tx_filtered_count++;
73 63
@@ -122,7 +112,6 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
122 return; 112 return;
123 } 113 }
124 114
125 drop:
126#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 115#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
127 if (net_ratelimit()) 116 if (net_ratelimit())
128 printk(KERN_DEBUG "%s: dropped TX filtered frame, " 117 printk(KERN_DEBUG "%s: dropped TX filtered frame, "
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c
index b73454a507f9..7ef491e9d66d 100644
--- a/net/mac80211/tkip.c
+++ b/net/mac80211/tkip.c
@@ -195,11 +195,13 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
195} 195}
196EXPORT_SYMBOL(ieee80211_get_tkip_key); 196EXPORT_SYMBOL(ieee80211_get_tkip_key);
197 197
198/* Encrypt packet payload with TKIP using @key. @pos is a pointer to the 198/*
199 * Encrypt packet payload with TKIP using @key. @pos is a pointer to the
199 * beginning of the buffer containing payload. This payload must include 200 * beginning of the buffer containing payload. This payload must include
200 * headroom of eight octets for IV and Ext. IV and taildroom of four octets 201 * the IV/Ext.IV and space for (taildroom) four octets for ICV.
201 * for ICV. @payload_len is the length of payload (_not_ including extra 202 * @payload_len is the length of payload (_not_ including IV/ICV length).
202 * headroom and tailroom). @ta is the transmitter addresses. */ 203 * @ta is the transmitter addresses.
204 */
203void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, 205void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
204 struct ieee80211_key *key, 206 struct ieee80211_key *key,
205 u8 *pos, size_t payload_len, u8 *ta) 207 u8 *pos, size_t payload_len, u8 *ta)
@@ -214,7 +216,6 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
214 216
215 tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key); 217 tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key);
216 218
217 pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16);
218 ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len); 219 ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len);
219} 220}
220 221
@@ -303,14 +304,12 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
303 if (key->local->ops->update_tkip_key && 304 if (key->local->ops->update_tkip_key &&
304 key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && 305 key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
305 key->u.tkip.rx[queue].state != TKIP_STATE_PHASE1_HW_UPLOADED) { 306 key->u.tkip.rx[queue].state != TKIP_STATE_PHASE1_HW_UPLOADED) {
306 static const u8 bcast[ETH_ALEN] = 307 struct ieee80211_sub_if_data *sdata = key->sdata;
307 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
308 const u8 *sta_addr = key->sta->sta.addr;
309
310 if (is_multicast_ether_addr(ra))
311 sta_addr = bcast;
312 308
313 drv_update_tkip_key(key->local, &key->conf, sta_addr, 309 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
310 sdata = container_of(key->sdata->bss,
311 struct ieee80211_sub_if_data, u.ap);
312 drv_update_tkip_key(key->local, sdata, &key->conf, key->sta,
314 iv32, key->u.tkip.rx[queue].p1k); 313 iv32, key->u.tkip.rx[queue].p1k);
315 key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED; 314 key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED;
316 } 315 }
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index daf81048c1f7..85e382aa894e 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -529,6 +529,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
529 tx->key = NULL; 529 tx->key = NULL;
530 530
531 if (tx->key) { 531 if (tx->key) {
532 bool skip_hw = false;
533
532 tx->key->tx_rx_count++; 534 tx->key->tx_rx_count++;
533 /* TODO: add threshold stuff again */ 535 /* TODO: add threshold stuff again */
534 536
@@ -545,16 +547,32 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
545 !ieee80211_use_mfp(hdr->frame_control, tx->sta, 547 !ieee80211_use_mfp(hdr->frame_control, tx->sta,
546 tx->skb)) 548 tx->skb))
547 tx->key = NULL; 549 tx->key = NULL;
550 else
551 skip_hw = (tx->key->conf.flags &
552 IEEE80211_KEY_FLAG_SW_MGMT) &&
553 ieee80211_is_mgmt(hdr->frame_control);
548 break; 554 break;
549 case ALG_AES_CMAC: 555 case ALG_AES_CMAC:
550 if (!ieee80211_is_mgmt(hdr->frame_control)) 556 if (!ieee80211_is_mgmt(hdr->frame_control))
551 tx->key = NULL; 557 tx->key = NULL;
552 break; 558 break;
553 } 559 }
560
561 if (!skip_hw && tx->key &&
562 tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
563 info->control.hw_key = &tx->key->conf;
554 } 564 }
555 565
556 if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) 566 return TX_CONTINUE;
557 info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 567}
568
569static ieee80211_tx_result debug_noinline
570ieee80211_tx_h_sta(struct ieee80211_tx_data *tx)
571{
572 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
573
574 if (tx->sta)
575 info->control.sta = &tx->sta->sta;
558 576
559 return TX_CONTINUE; 577 return TX_CONTINUE;
560} 578}
@@ -734,17 +752,6 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
734} 752}
735 753
736static ieee80211_tx_result debug_noinline 754static ieee80211_tx_result debug_noinline
737ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
738{
739 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
740
741 if (tx->sta)
742 info->control.sta = &tx->sta->sta;
743
744 return TX_CONTINUE;
745}
746
747static ieee80211_tx_result debug_noinline
748ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) 755ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
749{ 756{
750 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); 757 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
@@ -1101,7 +1108,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1101 tx->flags |= IEEE80211_TX_FRAGMENTED; 1108 tx->flags |= IEEE80211_TX_FRAGMENTED;
1102 1109
1103 /* process and remove the injection radiotap header */ 1110 /* process and remove the injection radiotap header */
1104 if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) { 1111 if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) {
1105 if (!__ieee80211_parse_tx_radiotap(tx, skb)) 1112 if (!__ieee80211_parse_tx_radiotap(tx, skb))
1106 return TX_DROP; 1113 return TX_DROP;
1107 1114
@@ -1110,6 +1117,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1110 * the radiotap header that was present and pre-filled 1117 * the radiotap header that was present and pre-filled
1111 * 'tx' with tx control information. 1118 * 'tx' with tx control information.
1112 */ 1119 */
1120 info->flags &= ~IEEE80211_TX_INTFL_HAS_RADIOTAP;
1113 } 1121 }
1114 1122
1115 /* 1123 /*
@@ -1125,6 +1133,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1125 tx->sta = rcu_dereference(sdata->u.vlan.sta); 1133 tx->sta = rcu_dereference(sdata->u.vlan.sta);
1126 if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr) 1134 if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr)
1127 return TX_DROP; 1135 return TX_DROP;
1136 } else if (info->flags & IEEE80211_TX_CTL_INJECTED) {
1137 tx->sta = sta_info_get_bss(sdata, hdr->addr1);
1128 } 1138 }
1129 if (!tx->sta) 1139 if (!tx->sta)
1130 tx->sta = sta_info_get(sdata, hdr->addr1); 1140 tx->sta = sta_info_get(sdata, hdr->addr1);
@@ -1279,6 +1289,7 @@ static int __ieee80211_tx(struct ieee80211_local *local,
1279static int invoke_tx_handlers(struct ieee80211_tx_data *tx) 1289static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
1280{ 1290{
1281 struct sk_buff *skb = tx->skb; 1291 struct sk_buff *skb = tx->skb;
1292 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1282 ieee80211_tx_result res = TX_DROP; 1293 ieee80211_tx_result res = TX_DROP;
1283 1294
1284#define CALL_TXH(txh) \ 1295#define CALL_TXH(txh) \
@@ -1292,10 +1303,14 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
1292 CALL_TXH(ieee80211_tx_h_check_assoc); 1303 CALL_TXH(ieee80211_tx_h_check_assoc);
1293 CALL_TXH(ieee80211_tx_h_ps_buf); 1304 CALL_TXH(ieee80211_tx_h_ps_buf);
1294 CALL_TXH(ieee80211_tx_h_select_key); 1305 CALL_TXH(ieee80211_tx_h_select_key);
1295 CALL_TXH(ieee80211_tx_h_michael_mic_add); 1306 CALL_TXH(ieee80211_tx_h_sta);
1296 if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) 1307 if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
1297 CALL_TXH(ieee80211_tx_h_rate_ctrl); 1308 CALL_TXH(ieee80211_tx_h_rate_ctrl);
1298 CALL_TXH(ieee80211_tx_h_misc); 1309
1310 if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION))
1311 goto txh_done;
1312
1313 CALL_TXH(ieee80211_tx_h_michael_mic_add);
1299 CALL_TXH(ieee80211_tx_h_sequence); 1314 CALL_TXH(ieee80211_tx_h_sequence);
1300 CALL_TXH(ieee80211_tx_h_fragment); 1315 CALL_TXH(ieee80211_tx_h_fragment);
1301 /* handlers after fragment must be aware of tx info fragmentation! */ 1316 /* handlers after fragment must be aware of tx info fragmentation! */
@@ -1487,7 +1502,8 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
1487 int hdrlen; 1502 int hdrlen;
1488 u16 len_rthdr; 1503 u16 len_rthdr;
1489 1504
1490 info->flags |= IEEE80211_TX_CTL_INJECTED; 1505 info->flags |= IEEE80211_TX_CTL_INJECTED |
1506 IEEE80211_TX_INTFL_HAS_RADIOTAP;
1491 1507
1492 len_rthdr = ieee80211_get_radiotap_len(skb->data); 1508 len_rthdr = ieee80211_get_radiotap_len(skb->data);
1493 hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); 1509 hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index 247123fe1a7a..5d745f2d7236 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -305,20 +305,19 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
305{ 305{
306 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 306 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
307 307
308 if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { 308 if (!info->control.hw_key) {
309 if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key, 309 if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key,
310 tx->key->conf.keylen, 310 tx->key->conf.keylen,
311 tx->key->conf.keyidx)) 311 tx->key->conf.keyidx))
312 return -1; 312 return -1;
313 } else { 313 } else if (info->control.hw_key->flags &
314 info->control.hw_key = &tx->key->conf; 314 IEEE80211_KEY_FLAG_GENERATE_IV) {
315 if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) { 315 if (!ieee80211_wep_add_iv(tx->local, skb,
316 if (!ieee80211_wep_add_iv(tx->local, skb, 316 tx->key->conf.keylen,
317 tx->key->conf.keylen, 317 tx->key->conf.keyidx))
318 tx->key->conf.keyidx)) 318 return -1;
319 return -1;
320 }
321 } 319 }
320
322 return 0; 321 return 0;
323} 322}
324 323
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index 81bd5d592bb4..7e708d5c88b4 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -535,8 +535,7 @@ ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk)
535 * First time we run, do nothing -- the generic code will 535 * First time we run, do nothing -- the generic code will
536 * have switched to the right channel etc. 536 * have switched to the right channel etc.
537 */ 537 */
538 if (!wk->remain.started) { 538 if (!wk->started) {
539 wk->remain.started = true;
540 wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration); 539 wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration);
541 540
542 cfg80211_ready_on_channel(wk->sdata->dev, (unsigned long) wk, 541 cfg80211_ready_on_channel(wk->sdata->dev, (unsigned long) wk,
@@ -821,15 +820,17 @@ static void ieee80211_work_work(struct work_struct *work)
821 mutex_lock(&local->work_mtx); 820 mutex_lock(&local->work_mtx);
822 821
823 list_for_each_entry_safe(wk, tmp, &local->work_list, list) { 822 list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
823 bool started = wk->started;
824
824 /* mark work as started if it's on the current off-channel */ 825 /* mark work as started if it's on the current off-channel */
825 if (!wk->started && local->tmp_channel && 826 if (!started && local->tmp_channel &&
826 wk->chan == local->tmp_channel && 827 wk->chan == local->tmp_channel &&
827 wk->chan_type == local->tmp_channel_type) { 828 wk->chan_type == local->tmp_channel_type) {
828 wk->started = true; 829 started = true;
829 wk->timeout = jiffies; 830 wk->timeout = jiffies;
830 } 831 }
831 832
832 if (!wk->started && !local->tmp_channel) { 833 if (!started && !local->tmp_channel) {
833 /* 834 /*
834 * TODO: could optimize this by leaving the 835 * TODO: could optimize this by leaving the
835 * station vifs in awake mode if they 836 * station vifs in awake mode if they
@@ -842,12 +843,12 @@ static void ieee80211_work_work(struct work_struct *work)
842 local->tmp_channel = wk->chan; 843 local->tmp_channel = wk->chan;
843 local->tmp_channel_type = wk->chan_type; 844 local->tmp_channel_type = wk->chan_type;
844 ieee80211_hw_config(local, 0); 845 ieee80211_hw_config(local, 0);
845 wk->started = true; 846 started = true;
846 wk->timeout = jiffies; 847 wk->timeout = jiffies;
847 } 848 }
848 849
849 /* don't try to work with items that aren't started */ 850 /* don't try to work with items that aren't started */
850 if (!wk->started) 851 if (!started)
851 continue; 852 continue;
852 853
853 if (time_is_after_jiffies(wk->timeout)) { 854 if (time_is_after_jiffies(wk->timeout)) {
@@ -882,6 +883,8 @@ static void ieee80211_work_work(struct work_struct *work)
882 break; 883 break;
883 } 884 }
884 885
886 wk->started = started;
887
885 switch (rma) { 888 switch (rma) {
886 case WORK_ACT_NONE: 889 case WORK_ACT_NONE:
887 /* might have changed the timeout */ 890 /* might have changed the timeout */
@@ -1022,8 +1025,6 @@ ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
1022 case IEEE80211_STYPE_PROBE_RESP: 1025 case IEEE80211_STYPE_PROBE_RESP:
1023 case IEEE80211_STYPE_ASSOC_RESP: 1026 case IEEE80211_STYPE_ASSOC_RESP:
1024 case IEEE80211_STYPE_REASSOC_RESP: 1027 case IEEE80211_STYPE_REASSOC_RESP:
1025 case IEEE80211_STYPE_DEAUTH:
1026 case IEEE80211_STYPE_DISASSOC:
1027 skb_queue_tail(&local->work_skb_queue, skb); 1028 skb_queue_tail(&local->work_skb_queue, skb);
1028 ieee80211_queue_work(&local->hw, &local->work_work); 1029 ieee80211_queue_work(&local->hw, &local->work_work);
1029 return RX_QUEUED; 1030 return RX_QUEUED;
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 5332014cb229..f4971cd45c64 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -31,8 +31,8 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
31 unsigned int hdrlen; 31 unsigned int hdrlen;
32 struct ieee80211_hdr *hdr; 32 struct ieee80211_hdr *hdr;
33 struct sk_buff *skb = tx->skb; 33 struct sk_buff *skb = tx->skb;
34 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
34 int authenticator; 35 int authenticator;
35 int wpa_test = 0;
36 int tail; 36 int tail;
37 37
38 hdr = (struct ieee80211_hdr *)skb->data; 38 hdr = (struct ieee80211_hdr *)skb->data;
@@ -47,16 +47,15 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
47 data = skb->data + hdrlen; 47 data = skb->data + hdrlen;
48 data_len = skb->len - hdrlen; 48 data_len = skb->len - hdrlen;
49 49
50 if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && 50 if (info->control.hw_key &&
51 !(tx->flags & IEEE80211_TX_FRAGMENTED) && 51 !(tx->flags & IEEE80211_TX_FRAGMENTED) &&
52 !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) && 52 !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
53 !wpa_test) { 53 /* hwaccel - with no need for SW-generated MMIC */
54 /* hwaccel - with no need for preallocated room for MMIC */
55 return TX_CONTINUE; 54 return TX_CONTINUE;
56 } 55 }
57 56
58 tail = MICHAEL_MIC_LEN; 57 tail = MICHAEL_MIC_LEN;
59 if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) 58 if (!info->control.hw_key)
60 tail += TKIP_ICV_LEN; 59 tail += TKIP_ICV_LEN;
61 60
62 if (WARN_ON(skb_tailroom(skb) < tail || 61 if (WARN_ON(skb_tailroom(skb) < tail ||
@@ -147,17 +146,16 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
147 int len, tail; 146 int len, tail;
148 u8 *pos; 147 u8 *pos;
149 148
150 if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && 149 if (info->control.hw_key &&
151 !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { 150 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
152 /* hwaccel - with no need for preallocated room for IV/ICV */ 151 /* hwaccel - with no need for software-generated IV */
153 info->control.hw_key = &tx->key->conf;
154 return 0; 152 return 0;
155 } 153 }
156 154
157 hdrlen = ieee80211_hdrlen(hdr->frame_control); 155 hdrlen = ieee80211_hdrlen(hdr->frame_control);
158 len = skb->len - hdrlen; 156 len = skb->len - hdrlen;
159 157
160 if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) 158 if (info->control.hw_key)
161 tail = 0; 159 tail = 0;
162 else 160 else
163 tail = TKIP_ICV_LEN; 161 tail = TKIP_ICV_LEN;
@@ -175,13 +173,11 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
175 if (key->u.tkip.tx.iv16 == 0) 173 if (key->u.tkip.tx.iv16 == 0)
176 key->u.tkip.tx.iv32++; 174 key->u.tkip.tx.iv32++;
177 175
178 if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { 176 pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16);
179 /* hwaccel - with preallocated room for IV */
180 ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16);
181 177
182 info->control.hw_key = &tx->key->conf; 178 /* hwaccel - with software IV */
179 if (info->control.hw_key)
183 return 0; 180 return 0;
184 }
185 181
186 /* Add room for ICV */ 182 /* Add room for ICV */
187 skb_put(skb, TKIP_ICV_LEN); 183 skb_put(skb, TKIP_ICV_LEN);
@@ -363,24 +359,20 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
363 int hdrlen, len, tail; 359 int hdrlen, len, tail;
364 u8 *pos, *pn; 360 u8 *pos, *pn;
365 int i; 361 int i;
366 bool skip_hw;
367
368 skip_hw = (tx->key->conf.flags & IEEE80211_KEY_FLAG_SW_MGMT) &&
369 ieee80211_is_mgmt(hdr->frame_control);
370 362
371 if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && 363 if (info->control.hw_key &&
372 !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) && 364 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
373 !skip_hw) { 365 /*
374 /* hwaccel - with no need for preallocated room for CCMP 366 * hwaccel has no need for preallocated room for CCMP
375 * header or MIC fields */ 367 * header or MIC fields
376 info->control.hw_key = &tx->key->conf; 368 */
377 return 0; 369 return 0;
378 } 370 }
379 371
380 hdrlen = ieee80211_hdrlen(hdr->frame_control); 372 hdrlen = ieee80211_hdrlen(hdr->frame_control);
381 len = skb->len - hdrlen; 373 len = skb->len - hdrlen;
382 374
383 if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) 375 if (info->control.hw_key)
384 tail = 0; 376 tail = 0;
385 else 377 else
386 tail = CCMP_MIC_LEN; 378 tail = CCMP_MIC_LEN;
@@ -405,11 +397,9 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
405 397
406 ccmp_pn2hdr(pos, pn, key->conf.keyidx); 398 ccmp_pn2hdr(pos, pn, key->conf.keyidx);
407 399
408 if ((key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && !skip_hw) { 400 /* hwaccel - with software CCMP header */
409 /* hwaccel - with preallocated room for CCMP header */ 401 if (info->control.hw_key)
410 info->control.hw_key = &tx->key->conf;
411 return 0; 402 return 0;
412 }
413 403
414 pos += CCMP_HDR_LEN; 404 pos += CCMP_HDR_LEN;
415 ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0); 405 ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0);
@@ -525,11 +515,8 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
525 u8 *pn, aad[20]; 515 u8 *pn, aad[20];
526 int i; 516 int i;
527 517
528 if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { 518 if (info->control.hw_key)
529 /* hwaccel */
530 info->control.hw_key = &tx->key->conf;
531 return 0; 519 return 0;
532 }
533 520
534 if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) 521 if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
535 return TX_DROP; 522 return TX_DROP;
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 20db90246de5..71b6b3a9cf1f 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * This is the linux wireless configuration interface. 2 * This is the linux wireless configuration interface.
3 * 3 *
4 * Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
5 */ 5 */
6 6
7#include <linux/if.h> 7#include <linux/if.h>
@@ -31,15 +31,10 @@ MODULE_AUTHOR("Johannes Berg");
31MODULE_LICENSE("GPL"); 31MODULE_LICENSE("GPL");
32MODULE_DESCRIPTION("wireless configuration support"); 32MODULE_DESCRIPTION("wireless configuration support");
33 33
34/* RCU might be appropriate here since we usually 34/* RCU-protected (and cfg80211_mutex for writers) */
35 * only read the list, and that can happen quite
36 * often because we need to do it for each command */
37LIST_HEAD(cfg80211_rdev_list); 35LIST_HEAD(cfg80211_rdev_list);
38int cfg80211_rdev_list_generation; 36int cfg80211_rdev_list_generation;
39 37
40/*
41 * This is used to protect the cfg80211_rdev_list
42 */
43DEFINE_MUTEX(cfg80211_mutex); 38DEFINE_MUTEX(cfg80211_mutex);
44 39
45/* for debugfs */ 40/* for debugfs */
@@ -418,6 +413,18 @@ int wiphy_register(struct wiphy *wiphy)
418 int i; 413 int i;
419 u16 ifmodes = wiphy->interface_modes; 414 u16 ifmodes = wiphy->interface_modes;
420 415
416 if (WARN_ON(wiphy->addresses && !wiphy->n_addresses))
417 return -EINVAL;
418
419 if (WARN_ON(wiphy->addresses &&
420 !is_zero_ether_addr(wiphy->perm_addr) &&
421 memcmp(wiphy->perm_addr, wiphy->addresses[0].addr,
422 ETH_ALEN)))
423 return -EINVAL;
424
425 if (wiphy->addresses)
426 memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN);
427
421 /* sanity check ifmodes */ 428 /* sanity check ifmodes */
422 WARN_ON(!ifmodes); 429 WARN_ON(!ifmodes);
423 ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; 430 ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1;
@@ -477,7 +484,7 @@ int wiphy_register(struct wiphy *wiphy)
477 /* set up regulatory info */ 484 /* set up regulatory info */
478 wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); 485 wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
479 486
480 list_add(&rdev->list, &cfg80211_rdev_list); 487 list_add_rcu(&rdev->list, &cfg80211_rdev_list);
481 cfg80211_rdev_list_generation++; 488 cfg80211_rdev_list_generation++;
482 489
483 mutex_unlock(&cfg80211_mutex); 490 mutex_unlock(&cfg80211_mutex);
@@ -554,7 +561,8 @@ void wiphy_unregister(struct wiphy *wiphy)
554 * it impossible to find from userspace. 561 * it impossible to find from userspace.
555 */ 562 */
556 debugfs_remove_recursive(rdev->wiphy.debugfsdir); 563 debugfs_remove_recursive(rdev->wiphy.debugfsdir);
557 list_del(&rdev->list); 564 list_del_rcu(&rdev->list);
565 synchronize_rcu();
558 566
559 /* 567 /*
560 * Try to grab rdev->mtx. If a command is still in progress, 568 * Try to grab rdev->mtx. If a command is still in progress,
@@ -670,7 +678,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
670 INIT_LIST_HEAD(&wdev->event_list); 678 INIT_LIST_HEAD(&wdev->event_list);
671 spin_lock_init(&wdev->event_lock); 679 spin_lock_init(&wdev->event_lock);
672 mutex_lock(&rdev->devlist_mtx); 680 mutex_lock(&rdev->devlist_mtx);
673 list_add(&wdev->list, &rdev->netdev_list); 681 list_add_rcu(&wdev->list, &rdev->netdev_list);
674 rdev->devlist_generation++; 682 rdev->devlist_generation++;
675 /* can only change netns with wiphy */ 683 /* can only change netns with wiphy */
676 dev->features |= NETIF_F_NETNS_LOCAL; 684 dev->features |= NETIF_F_NETNS_LOCAL;
@@ -782,13 +790,21 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
782 */ 790 */
783 if (!list_empty(&wdev->list)) { 791 if (!list_empty(&wdev->list)) {
784 sysfs_remove_link(&dev->dev.kobj, "phy80211"); 792 sysfs_remove_link(&dev->dev.kobj, "phy80211");
785 list_del_init(&wdev->list); 793 list_del_rcu(&wdev->list);
786 rdev->devlist_generation++; 794 rdev->devlist_generation++;
787#ifdef CONFIG_CFG80211_WEXT 795#ifdef CONFIG_CFG80211_WEXT
788 kfree(wdev->wext.keys); 796 kfree(wdev->wext.keys);
789#endif 797#endif
790 } 798 }
791 mutex_unlock(&rdev->devlist_mtx); 799 mutex_unlock(&rdev->devlist_mtx);
800 /*
801 * synchronise (so that we won't find this netdev
802 * from other code any more) and then clear the list
803 * head so that the above code can safely check for
804 * !list_empty() to avoid double-cleanup.
805 */
806 synchronize_rcu();
807 INIT_LIST_HEAD(&wdev->list);
792 break; 808 break;
793 case NETDEV_PRE_UP: 809 case NETDEV_PRE_UP:
794 if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) 810 if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 2d6a6b9c0c43..c326a667022a 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * Wireless configuration interface internals. 2 * Wireless configuration interface internals.
3 * 3 *
4 * Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
5 */ 5 */
6#ifndef __NET_WIRELESS_CORE_H 6#ifndef __NET_WIRELESS_CORE_H
7#define __NET_WIRELESS_CORE_H 7#define __NET_WIRELESS_CORE_H
@@ -48,6 +48,7 @@ struct cfg80211_registered_device {
48 48
49 /* associate netdev list */ 49 /* associate netdev list */
50 struct mutex devlist_mtx; 50 struct mutex devlist_mtx;
51 /* protected by devlist_mtx or RCU */
51 struct list_head netdev_list; 52 struct list_head netdev_list;
52 int devlist_generation; 53 int devlist_generation;
53 int opencount; /* also protected by devlist_mtx */ 54 int opencount; /* also protected by devlist_mtx */
diff --git a/net/wireless/lib80211_crypt_ccmp.c b/net/wireless/lib80211_crypt_ccmp.c
index 2301dc1edc4c..b7fa31d5fd13 100644
--- a/net/wireless/lib80211_crypt_ccmp.c
+++ b/net/wireless/lib80211_crypt_ccmp.c
@@ -237,7 +237,6 @@ static int lib80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
237 return -1; 237 return -1;
238 238
239 pos = skb->data + hdr_len + CCMP_HDR_LEN; 239 pos = skb->data + hdr_len + CCMP_HDR_LEN;
240 mic = skb_put(skb, CCMP_MIC_LEN);
241 hdr = (struct ieee80211_hdr *)skb->data; 240 hdr = (struct ieee80211_hdr *)skb->data;
242 ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); 241 ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
243 242
@@ -257,6 +256,7 @@ static int lib80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
257 pos += len; 256 pos += len;
258 } 257 }
259 258
259 mic = skb_put(skb, CCMP_MIC_LEN);
260 for (i = 0; i < CCMP_MIC_LEN; i++) 260 for (i = 0; i < CCMP_MIC_LEN; i++)
261 mic[i] = b[i] ^ s0[i]; 261 mic[i] = b[i] ^ s0[i];
262 262
diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c
index c36287399d7e..8cbdb32ff316 100644
--- a/net/wireless/lib80211_crypt_tkip.c
+++ b/net/wireless/lib80211_crypt_tkip.c
@@ -36,6 +36,8 @@ MODULE_AUTHOR("Jouni Malinen");
36MODULE_DESCRIPTION("lib80211 crypt: TKIP"); 36MODULE_DESCRIPTION("lib80211 crypt: TKIP");
37MODULE_LICENSE("GPL"); 37MODULE_LICENSE("GPL");
38 38
39#define TKIP_HDR_LEN 8
40
39struct lib80211_tkip_data { 41struct lib80211_tkip_data {
40#define TKIP_KEY_LEN 32 42#define TKIP_KEY_LEN 32
41 u8 key[TKIP_KEY_LEN]; 43 u8 key[TKIP_KEY_LEN];
@@ -314,13 +316,12 @@ static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
314 u8 * rc4key, int keylen, void *priv) 316 u8 * rc4key, int keylen, void *priv)
315{ 317{
316 struct lib80211_tkip_data *tkey = priv; 318 struct lib80211_tkip_data *tkey = priv;
317 int len;
318 u8 *pos; 319 u8 *pos;
319 struct ieee80211_hdr *hdr; 320 struct ieee80211_hdr *hdr;
320 321
321 hdr = (struct ieee80211_hdr *)skb->data; 322 hdr = (struct ieee80211_hdr *)skb->data;
322 323
323 if (skb_headroom(skb) < 8 || skb->len < hdr_len) 324 if (skb_headroom(skb) < TKIP_HDR_LEN || skb->len < hdr_len)
324 return -1; 325 return -1;
325 326
326 if (rc4key == NULL || keylen < 16) 327 if (rc4key == NULL || keylen < 16)
@@ -333,9 +334,8 @@ static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
333 } 334 }
334 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16); 335 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
335 336
336 len = skb->len - hdr_len; 337 pos = skb_push(skb, TKIP_HDR_LEN);
337 pos = skb_push(skb, 8); 338 memmove(pos, pos + TKIP_HDR_LEN, hdr_len);
338 memmove(pos, pos + 8, hdr_len);
339 pos += hdr_len; 339 pos += hdr_len;
340 340
341 *pos++ = *rc4key; 341 *pos++ = *rc4key;
@@ -353,7 +353,7 @@ static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
353 tkey->tx_iv32++; 353 tkey->tx_iv32++;
354 } 354 }
355 355
356 return 8; 356 return TKIP_HDR_LEN;
357} 357}
358 358
359static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) 359static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
@@ -384,9 +384,8 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
384 if ((lib80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0) 384 if ((lib80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0)
385 return -1; 385 return -1;
386 386
387 icv = skb_put(skb, 4);
388
389 crc = ~crc32_le(~0, pos, len); 387 crc = ~crc32_le(~0, pos, len);
388 icv = skb_put(skb, 4);
390 icv[0] = crc; 389 icv[0] = crc;
391 icv[1] = crc >> 8; 390 icv[1] = crc >> 8;
392 icv[2] = crc >> 16; 391 icv[2] = crc >> 16;
@@ -434,7 +433,7 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
434 return -1; 433 return -1;
435 } 434 }
436 435
437 if (skb->len < hdr_len + 8 + 4) 436 if (skb->len < hdr_len + TKIP_HDR_LEN + 4)
438 return -1; 437 return -1;
439 438
440 pos = skb->data + hdr_len; 439 pos = skb->data + hdr_len;
@@ -462,7 +461,7 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
462 } 461 }
463 iv16 = (pos[0] << 8) | pos[2]; 462 iv16 = (pos[0] << 8) | pos[2];
464 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); 463 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
465 pos += 8; 464 pos += TKIP_HDR_LEN;
466 465
467 if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) { 466 if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) {
468#ifdef CONFIG_LIB80211_DEBUG 467#ifdef CONFIG_LIB80211_DEBUG
@@ -523,8 +522,8 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
523 tkey->rx_iv16_new = iv16; 522 tkey->rx_iv16_new = iv16;
524 523
525 /* Remove IV and ICV */ 524 /* Remove IV and ICV */
526 memmove(skb->data + 8, skb->data, hdr_len); 525 memmove(skb->data + TKIP_HDR_LEN, skb->data, hdr_len);
527 skb_pull(skb, 8); 526 skb_pull(skb, TKIP_HDR_LEN);
528 skb_trim(skb, skb->len - 4); 527 skb_trim(skb, skb->len - 4);
529 528
530 return keyidx; 529 return keyidx;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4af7991a9ec8..5b79ecf17bea 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3571,6 +3571,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3571{ 3571{
3572 struct cfg80211_registered_device *rdev; 3572 struct cfg80211_registered_device *rdev;
3573 struct net_device *dev; 3573 struct net_device *dev;
3574 struct wireless_dev *wdev;
3574 struct cfg80211_crypto_settings crypto; 3575 struct cfg80211_crypto_settings crypto;
3575 struct ieee80211_channel *chan, *fixedchan; 3576 struct ieee80211_channel *chan, *fixedchan;
3576 const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; 3577 const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
@@ -3616,7 +3617,8 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3616 } 3617 }
3617 3618
3618 mutex_lock(&rdev->devlist_mtx); 3619 mutex_lock(&rdev->devlist_mtx);
3619 fixedchan = rdev_fixed_channel(rdev, NULL); 3620 wdev = dev->ieee80211_ptr;
3621 fixedchan = rdev_fixed_channel(rdev, wdev);
3620 if (fixedchan && chan != fixedchan) { 3622 if (fixedchan && chan != fixedchan) {
3621 err = -EBUSY; 3623 err = -EBUSY;
3622 mutex_unlock(&rdev->devlist_mtx); 3624 mutex_unlock(&rdev->devlist_mtx);
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 5f8071de7950..ed89c59bb431 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -134,6 +134,7 @@ static const struct ieee80211_regdomain *cfg80211_world_regdom =
134 &world_regdom; 134 &world_regdom;
135 135
136static char *ieee80211_regdom = "00"; 136static char *ieee80211_regdom = "00";
137static char user_alpha2[2];
137 138
138module_param(ieee80211_regdom, charp, 0444); 139module_param(ieee80211_regdom, charp, 0444);
139MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); 140MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
@@ -252,6 +253,27 @@ static bool regdom_changes(const char *alpha2)
252 return true; 253 return true;
253} 254}
254 255
256/*
257 * The NL80211_REGDOM_SET_BY_USER regdom alpha2 is cached, this lets
258 * you know if a valid regulatory hint with NL80211_REGDOM_SET_BY_USER
259 * has ever been issued.
260 */
261static bool is_user_regdom_saved(void)
262{
263 if (user_alpha2[0] == '9' && user_alpha2[1] == '7')
264 return false;
265
266 /* This would indicate a mistake on the design */
267 if (WARN((!is_world_regdom(user_alpha2) &&
268 !is_an_alpha2(user_alpha2)),
269 "Unexpected user alpha2: %c%c\n",
270 user_alpha2[0],
271 user_alpha2[1]))
272 return false;
273
274 return true;
275}
276
255/** 277/**
256 * country_ie_integrity_changes - tells us if the country IE has changed 278 * country_ie_integrity_changes - tells us if the country IE has changed
257 * @checksum: checksum of country IE of fields we are interested in 279 * @checksum: checksum of country IE of fields we are interested in
@@ -1646,7 +1668,7 @@ static int ignore_request(struct wiphy *wiphy,
1646 1668
1647 switch (pending_request->initiator) { 1669 switch (pending_request->initiator) {
1648 case NL80211_REGDOM_SET_BY_CORE: 1670 case NL80211_REGDOM_SET_BY_CORE:
1649 return -EINVAL; 1671 return 0;
1650 case NL80211_REGDOM_SET_BY_COUNTRY_IE: 1672 case NL80211_REGDOM_SET_BY_COUNTRY_IE:
1651 1673
1652 last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); 1674 last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
@@ -1785,6 +1807,11 @@ new_request:
1785 1807
1786 pending_request = NULL; 1808 pending_request = NULL;
1787 1809
1810 if (last_request->initiator == NL80211_REGDOM_SET_BY_USER) {
1811 user_alpha2[0] = last_request->alpha2[0];
1812 user_alpha2[1] = last_request->alpha2[1];
1813 }
1814
1788 /* When r == REG_INTERSECT we do need to call CRDA */ 1815 /* When r == REG_INTERSECT we do need to call CRDA */
1789 if (r < 0) { 1816 if (r < 0) {
1790 /* 1817 /*
@@ -1904,12 +1931,16 @@ static void queue_regulatory_request(struct regulatory_request *request)
1904 schedule_work(&reg_work); 1931 schedule_work(&reg_work);
1905} 1932}
1906 1933
1907/* Core regulatory hint -- happens once during cfg80211_init() */ 1934/*
1935 * Core regulatory hint -- happens during cfg80211_init()
1936 * and when we restore regulatory settings.
1937 */
1908static int regulatory_hint_core(const char *alpha2) 1938static int regulatory_hint_core(const char *alpha2)
1909{ 1939{
1910 struct regulatory_request *request; 1940 struct regulatory_request *request;
1911 1941
1912 BUG_ON(last_request); 1942 kfree(last_request);
1943 last_request = NULL;
1913 1944
1914 request = kzalloc(sizeof(struct regulatory_request), 1945 request = kzalloc(sizeof(struct regulatory_request),
1915 GFP_KERNEL); 1946 GFP_KERNEL);
@@ -1920,14 +1951,12 @@ static int regulatory_hint_core(const char *alpha2)
1920 request->alpha2[1] = alpha2[1]; 1951 request->alpha2[1] = alpha2[1];
1921 request->initiator = NL80211_REGDOM_SET_BY_CORE; 1952 request->initiator = NL80211_REGDOM_SET_BY_CORE;
1922 1953
1923 queue_regulatory_request(request);
1924
1925 /* 1954 /*
1926 * This ensures last_request is populated once modules 1955 * This ensures last_request is populated once modules
1927 * come swinging in and calling regulatory hints and 1956 * come swinging in and calling regulatory hints and
1928 * wiphy_apply_custom_regulatory(). 1957 * wiphy_apply_custom_regulatory().
1929 */ 1958 */
1930 flush_scheduled_work(); 1959 reg_process_hint(request);
1931 1960
1932 return 0; 1961 return 0;
1933} 1962}
@@ -2109,6 +2138,123 @@ out:
2109 mutex_unlock(&reg_mutex); 2138 mutex_unlock(&reg_mutex);
2110} 2139}
2111 2140
2141static void restore_alpha2(char *alpha2, bool reset_user)
2142{
2143 /* indicates there is no alpha2 to consider for restoration */
2144 alpha2[0] = '9';
2145 alpha2[1] = '7';
2146
2147 /* The user setting has precedence over the module parameter */
2148 if (is_user_regdom_saved()) {
2149 /* Unless we're asked to ignore it and reset it */
2150 if (reset_user) {
2151 REG_DBG_PRINT("cfg80211: Restoring regulatory settings "
2152 "including user preference\n");
2153 user_alpha2[0] = '9';
2154 user_alpha2[1] = '7';
2155
2156 /*
2157 * If we're ignoring user settings, we still need to
2158 * check the module parameter to ensure we put things
2159 * back as they were for a full restore.
2160 */
2161 if (!is_world_regdom(ieee80211_regdom)) {
2162 REG_DBG_PRINT("cfg80211: Keeping preference on "
2163 "module parameter ieee80211_regdom: %c%c\n",
2164 ieee80211_regdom[0],
2165 ieee80211_regdom[1]);
2166 alpha2[0] = ieee80211_regdom[0];
2167 alpha2[1] = ieee80211_regdom[1];
2168 }
2169 } else {
2170 REG_DBG_PRINT("cfg80211: Restoring regulatory settings "
2171 "while preserving user preference for: %c%c\n",
2172 user_alpha2[0],
2173 user_alpha2[1]);
2174 alpha2[0] = user_alpha2[0];
2175 alpha2[1] = user_alpha2[1];
2176 }
2177 } else if (!is_world_regdom(ieee80211_regdom)) {
2178 REG_DBG_PRINT("cfg80211: Keeping preference on "
2179 "module parameter ieee80211_regdom: %c%c\n",
2180 ieee80211_regdom[0],
2181 ieee80211_regdom[1]);
2182 alpha2[0] = ieee80211_regdom[0];
2183 alpha2[1] = ieee80211_regdom[1];
2184 } else
2185 REG_DBG_PRINT("cfg80211: Restoring regulatory settings\n");
2186}
2187
2188/*
2189 * Restoring regulatory settings involves ingoring any
2190 * possibly stale country IE information and user regulatory
2191 * settings if so desired, this includes any beacon hints
2192 * learned as we could have traveled outside to another country
2193 * after disconnection. To restore regulatory settings we do
2194 * exactly what we did at bootup:
2195 *
2196 * - send a core regulatory hint
2197 * - send a user regulatory hint if applicable
2198 *
2199 * Device drivers that send a regulatory hint for a specific country
2200 * keep their own regulatory domain on wiphy->regd so that does does
2201 * not need to be remembered.
2202 */
2203static void restore_regulatory_settings(bool reset_user)
2204{
2205 char alpha2[2];
2206 struct reg_beacon *reg_beacon, *btmp;
2207
2208 mutex_lock(&cfg80211_mutex);
2209 mutex_lock(&reg_mutex);
2210
2211 reset_regdomains();
2212 restore_alpha2(alpha2, reset_user);
2213
2214 /* Clear beacon hints */
2215 spin_lock_bh(&reg_pending_beacons_lock);
2216 if (!list_empty(&reg_pending_beacons)) {
2217 list_for_each_entry_safe(reg_beacon, btmp,
2218 &reg_pending_beacons, list) {
2219 list_del(&reg_beacon->list);
2220 kfree(reg_beacon);
2221 }
2222 }
2223 spin_unlock_bh(&reg_pending_beacons_lock);
2224
2225 if (!list_empty(&reg_beacon_list)) {
2226 list_for_each_entry_safe(reg_beacon, btmp,
2227 &reg_beacon_list, list) {
2228 list_del(&reg_beacon->list);
2229 kfree(reg_beacon);
2230 }
2231 }
2232
2233 /* First restore to the basic regulatory settings */
2234 cfg80211_regdomain = cfg80211_world_regdom;
2235
2236 mutex_unlock(&reg_mutex);
2237 mutex_unlock(&cfg80211_mutex);
2238
2239 regulatory_hint_core(cfg80211_regdomain->alpha2);
2240
2241 /*
2242 * This restores the ieee80211_regdom module parameter
2243 * preference or the last user requested regulatory
2244 * settings, user regulatory settings takes precedence.
2245 */
2246 if (is_an_alpha2(alpha2))
2247 regulatory_hint_user(user_alpha2);
2248}
2249
2250
2251void regulatory_hint_disconnect(void)
2252{
2253 REG_DBG_PRINT("cfg80211: All devices are disconnected, going to "
2254 "restore regulatory settings\n");
2255 restore_regulatory_settings(false);
2256}
2257
2112static bool freq_is_chan_12_13_14(u16 freq) 2258static bool freq_is_chan_12_13_14(u16 freq)
2113{ 2259{
2114 if (freq == ieee80211_channel_to_frequency(12) || 2260 if (freq == ieee80211_channel_to_frequency(12) ||
@@ -2498,6 +2644,9 @@ int regulatory_init(void)
2498 2644
2499 cfg80211_regdomain = cfg80211_world_regdom; 2645 cfg80211_regdomain = cfg80211_world_regdom;
2500 2646
2647 user_alpha2[0] = '9';
2648 user_alpha2[1] = '7';
2649
2501 /* We always try to get an update for the static regdomain */ 2650 /* We always try to get an update for the static regdomain */
2502 err = regulatory_hint_core(cfg80211_regdomain->alpha2); 2651 err = regulatory_hint_core(cfg80211_regdomain->alpha2);
2503 if (err) { 2652 if (err) {
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 3018508226ab..b26224a9f3bc 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -63,4 +63,22 @@ void regulatory_hint_11d(struct wiphy *wiphy,
63 u8 *country_ie, 63 u8 *country_ie,
64 u8 country_ie_len); 64 u8 country_ie_len);
65 65
66/**
67 * regulatory_hint_disconnect - informs all devices have been disconneted
68 *
69 * Regulotory rules can be enhanced further upon scanning and upon
70 * connection to an AP. These rules become stale if we disconnect
71 * and go to another country, whether or not we suspend and resume.
72 * If we suspend, go to another country and resume we'll automatically
73 * get disconnected shortly after resuming and things will be reset as well.
74 * This routine is a helper to restore regulatory settings to how they were
75 * prior to our first connect attempt. This includes ignoring country IE and
76 * beacon regulatory hints. The ieee80211_regdom module parameter will always
77 * be respected but if a user had set the regulatory domain that will take
78 * precedence.
79 *
80 * Must be called from process context.
81 */
82void regulatory_hint_disconnect(void);
83
66#endif /* __NET_WIRELESS_REG_H */ 84#endif /* __NET_WIRELESS_REG_H */
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 06b0231ee5e3..978cac3414b5 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -143,9 +143,9 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
143 dev->bss_generation++; 143 dev->bss_generation++;
144} 144}
145 145
146static u8 *find_ie(u8 num, u8 *ies, int len) 146const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
147{ 147{
148 while (len > 2 && ies[0] != num) { 148 while (len > 2 && ies[0] != eid) {
149 len -= ies[1] + 2; 149 len -= ies[1] + 2;
150 ies += ies[1] + 2; 150 ies += ies[1] + 2;
151 } 151 }
@@ -155,11 +155,12 @@ static u8 *find_ie(u8 num, u8 *ies, int len)
155 return NULL; 155 return NULL;
156 return ies; 156 return ies;
157} 157}
158EXPORT_SYMBOL(cfg80211_find_ie);
158 159
159static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2) 160static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2)
160{ 161{
161 const u8 *ie1 = find_ie(num, ies1, len1); 162 const u8 *ie1 = cfg80211_find_ie(num, ies1, len1);
162 const u8 *ie2 = find_ie(num, ies2, len2); 163 const u8 *ie2 = cfg80211_find_ie(num, ies2, len2);
163 int r; 164 int r;
164 165
165 if (!ie1 && !ie2) 166 if (!ie1 && !ie2)
@@ -185,9 +186,9 @@ static bool is_bss(struct cfg80211_bss *a,
185 if (!ssid) 186 if (!ssid)
186 return true; 187 return true;
187 188
188 ssidie = find_ie(WLAN_EID_SSID, 189 ssidie = cfg80211_find_ie(WLAN_EID_SSID,
189 a->information_elements, 190 a->information_elements,
190 a->len_information_elements); 191 a->len_information_elements);
191 if (!ssidie) 192 if (!ssidie)
192 return false; 193 return false;
193 if (ssidie[1] != ssid_len) 194 if (ssidie[1] != ssid_len)
@@ -204,9 +205,9 @@ static bool is_mesh(struct cfg80211_bss *a,
204 if (!is_zero_ether_addr(a->bssid)) 205 if (!is_zero_ether_addr(a->bssid))
205 return false; 206 return false;
206 207
207 ie = find_ie(WLAN_EID_MESH_ID, 208 ie = cfg80211_find_ie(WLAN_EID_MESH_ID,
208 a->information_elements, 209 a->information_elements,
209 a->len_information_elements); 210 a->len_information_elements);
210 if (!ie) 211 if (!ie)
211 return false; 212 return false;
212 if (ie[1] != meshidlen) 213 if (ie[1] != meshidlen)
@@ -214,9 +215,9 @@ static bool is_mesh(struct cfg80211_bss *a,
214 if (memcmp(ie + 2, meshid, meshidlen)) 215 if (memcmp(ie + 2, meshid, meshidlen))
215 return false; 216 return false;
216 217
217 ie = find_ie(WLAN_EID_MESH_CONFIG, 218 ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
218 a->information_elements, 219 a->information_elements,
219 a->len_information_elements); 220 a->len_information_elements);
220 if (!ie) 221 if (!ie)
221 return false; 222 return false;
222 if (ie[1] != sizeof(struct ieee80211_meshconf_ie)) 223 if (ie[1] != sizeof(struct ieee80211_meshconf_ie))
@@ -395,11 +396,12 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
395 396
396 if (is_zero_ether_addr(res->pub.bssid)) { 397 if (is_zero_ether_addr(res->pub.bssid)) {
397 /* must be mesh, verify */ 398 /* must be mesh, verify */
398 meshid = find_ie(WLAN_EID_MESH_ID, res->pub.information_elements, 399 meshid = cfg80211_find_ie(WLAN_EID_MESH_ID,
399 res->pub.len_information_elements); 400 res->pub.information_elements,
400 meshcfg = find_ie(WLAN_EID_MESH_CONFIG, 401 res->pub.len_information_elements);
401 res->pub.information_elements, 402 meshcfg = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
402 res->pub.len_information_elements); 403 res->pub.information_elements,
404 res->pub.len_information_elements);
403 if (!meshid || !meshcfg || 405 if (!meshid || !meshcfg ||
404 meshcfg[1] != sizeof(struct ieee80211_meshconf_ie)) { 406 meshcfg[1] != sizeof(struct ieee80211_meshconf_ie)) {
405 /* bogus mesh */ 407 /* bogus mesh */
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 745c37e7992e..17fde0da1b08 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -34,6 +34,44 @@ struct cfg80211_conn {
34 bool auto_auth, prev_bssid_valid; 34 bool auto_auth, prev_bssid_valid;
35}; 35};
36 36
37bool cfg80211_is_all_idle(void)
38{
39 struct cfg80211_registered_device *rdev;
40 struct wireless_dev *wdev;
41 bool is_all_idle = true;
42
43 mutex_lock(&cfg80211_mutex);
44
45 /*
46 * All devices must be idle as otherwise if you are actively
47 * scanning some new beacon hints could be learned and would
48 * count as new regulatory hints.
49 */
50 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
51 cfg80211_lock_rdev(rdev);
52 list_for_each_entry(wdev, &rdev->netdev_list, list) {
53 wdev_lock(wdev);
54 if (wdev->sme_state != CFG80211_SME_IDLE)
55 is_all_idle = false;
56 wdev_unlock(wdev);
57 }
58 cfg80211_unlock_rdev(rdev);
59 }
60
61 mutex_unlock(&cfg80211_mutex);
62
63 return is_all_idle;
64}
65
66static void disconnect_work(struct work_struct *work)
67{
68 if (!cfg80211_is_all_idle())
69 return;
70
71 regulatory_hint_disconnect();
72}
73
74static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
37 75
38static int cfg80211_conn_scan(struct wireless_dev *wdev) 76static int cfg80211_conn_scan(struct wireless_dev *wdev)
39{ 77{
@@ -658,6 +696,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
658 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); 696 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
659 wdev->wext.connect.ssid_len = 0; 697 wdev->wext.connect.ssid_len = 0;
660#endif 698#endif
699
700 schedule_work(&cfg80211_disconnect_work);
661} 701}
662 702
663void cfg80211_disconnected(struct net_device *dev, u16 reason, 703void cfg80211_disconnected(struct net_device *dev, u16 reason,
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c
index efe3c5c92b2d..9f2cef3e0ca0 100644
--- a/net/wireless/sysfs.c
+++ b/net/wireless/sysfs.c
@@ -33,10 +33,30 @@ static ssize_t name ## _show(struct device *dev, \
33 33
34SHOW_FMT(index, "%d", wiphy_idx); 34SHOW_FMT(index, "%d", wiphy_idx);
35SHOW_FMT(macaddress, "%pM", wiphy.perm_addr); 35SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
36SHOW_FMT(address_mask, "%pM", wiphy.addr_mask);
37
38static ssize_t addresses_show(struct device *dev,
39 struct device_attribute *attr,
40 char *buf)
41{
42 struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy;
43 char *start = buf;
44 int i;
45
46 if (!wiphy->addresses)
47 return sprintf(buf, "%pM\n", wiphy->perm_addr);
48
49 for (i = 0; i < wiphy->n_addresses; i++)
50 buf += sprintf(buf, "%pM\n", &wiphy->addresses[i].addr);
51
52 return buf - start;
53}
36 54
37static struct device_attribute ieee80211_dev_attrs[] = { 55static struct device_attribute ieee80211_dev_attrs[] = {
38 __ATTR_RO(index), 56 __ATTR_RO(index),
39 __ATTR_RO(macaddress), 57 __ATTR_RO(macaddress),
58 __ATTR_RO(address_mask),
59 __ATTR_RO(addresses),
40 {} 60 {}
41}; 61};
42 62
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 23557c1d0a9c..be2ab8c59e3a 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -227,8 +227,11 @@ unsigned int ieee80211_hdrlen(__le16 fc)
227 if (ieee80211_is_data(fc)) { 227 if (ieee80211_is_data(fc)) {
228 if (ieee80211_has_a4(fc)) 228 if (ieee80211_has_a4(fc))
229 hdrlen = 30; 229 hdrlen = 30;
230 if (ieee80211_is_data_qos(fc)) 230 if (ieee80211_is_data_qos(fc)) {
231 hdrlen += IEEE80211_QOS_CTL_LEN; 231 hdrlen += IEEE80211_QOS_CTL_LEN;
232 if (ieee80211_has_order(fc))
233 hdrlen += IEEE80211_HT_CTL_LEN;
234 }
232 goto out; 235 goto out;
233 } 236 }
234 237
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 966d2f01beac..b17eeae448d5 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -1214,7 +1214,7 @@ int cfg80211_wext_siwrate(struct net_device *dev,
1214 1214
1215 memset(&mask, 0, sizeof(mask)); 1215 memset(&mask, 0, sizeof(mask));
1216 fixed = 0; 1216 fixed = 0;
1217 maxrate = 0; 1217 maxrate = (u32)-1;
1218 1218
1219 if (rate->value < 0) { 1219 if (rate->value < 0) {
1220 /* nothing */ 1220 /* nothing */