diff options
author | David S. Miller <davem@davemloft.net> | 2010-02-04 11:58:14 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-04 11:58:14 -0500 |
commit | 10be7eb36b93364b98688831ee7d26f58402bb96 (patch) | |
tree | eb13ae80fcaa8baacd804a721c5a4962a501a2a4 | |
parent | 90c30335a70e96b8b8493b7deb15e6b30e6d9fce (diff) | |
parent | 5ffaf8a361b4c9025963959a744f21d8173c7669 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
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 | |||
1000 | CONFIG_SPIDER_NET=m | 1000 | CONFIG_SPIDER_NET=m |
1001 | CONFIG_GELIC_NET=m | 1001 | CONFIG_GELIC_NET=m |
1002 | CONFIG_GELIC_WIRELESS=y | 1002 | CONFIG_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 | |||
593 | CONFIG_NETDEV_1000=y | 593 | CONFIG_NETDEV_1000=y |
594 | CONFIG_GELIC_NET=y | 594 | CONFIG_GELIC_NET=y |
595 | CONFIG_GELIC_WIRELESS=y | 595 | CONFIG_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 | ||
2371 | config 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 | |||
2385 | config FSL_PQ_MDIO | 2371 | config 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 */ | ||
1394 | static 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 | |||
1418 | static 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); | ||
1453 | out: | ||
1454 | spin_unlock_irqrestore(&wl->lock, irqflag); | ||
1455 | pr_debug("%s:->\n", __func__); | ||
1456 | return ret; | ||
1457 | } | ||
1458 | |||
1459 | static 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 */ |
1500 | static int gelic_wl_get_nick(struct net_device *net_dev, | 1393 | static 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 | ||
2410 | static 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 | |||
2426 | static const iw_handler gelic_wl_private_handler[] = | ||
2427 | { | ||
2428 | gelic_wl_priv_set_psk, | ||
2429 | gelic_wl_priv_get_psk, | ||
2430 | }; | ||
2431 | #endif | ||
2432 | |||
2433 | static const struct iw_handler_def gelic_wl_wext_handler_def = { | 2304 | static 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 | ||
2445 | static struct net_device * __devinit gelic_wl_alloc(struct gelic_card *card) | 2310 | static 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 | ||
75 | struct ath_bus_ops { | 75 | struct 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); | ||
1564 | err: | ||
1565 | return ret; | ||
1550 | } | 1566 | } |
1551 | 1567 | ||
1552 | static void | 1568 | static 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 | ||
30 | static 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 | |||
36 | static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | 30 | static 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 | ||
55 | static struct ath_bus_ops ath_ahb_bus_ops = { | 49 | static 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 | ||
538 | static inline void ath_bus_cleanup(struct ath_common *common) | ||
539 | { | ||
540 | common->bus_ops->cleanup(common); | ||
541 | } | ||
542 | |||
543 | extern struct ieee80211_ops ath9k_ops; | 541 | extern struct ieee80211_ops ath9k_ops; |
544 | extern int modparam_nohwcrypt; | 542 | extern 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 | ||
33 | enum ath_btcoex_scheme { | 35 | enum 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 | |||
78 | static ssize_t read_file_dma(struct file *file, char __user *user_buf, | 80 | static 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 | ||
162 | static const struct file_operations fops_dma = { | 171 | static 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 | ||
1626 | skip_chan_change: | 1629 | skip_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 | ||
52 | static 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 | |||
62 | static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data) | 53 | static 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 | ||
99 | static const struct ath_bus_ops ath_pci_bus_ops = { | 90 | static 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 |
68 | void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...); | 68 | void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...) |
69 | __attribute__ ((format (printf, 3, 4))); | ||
69 | #else | 70 | #else |
70 | static inline void ath_print(struct ath_common *common, | 71 | static inline void __attribute__ ((format (printf, 3, 4))) |
71 | int dbg_mask, | 72 | ath_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 | ||
846 | static void b43_op_update_tkip_key(struct ieee80211_hw *hw, | 846 | static 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)) | |
868 | out_unlock: | 870 | return; |
869 | mutex_unlock(&wl->mutex); | 871 | keymac_write(dev, index, sta->addr); |
870 | } | 872 | } |
871 | 873 | ||
872 | static void do_key_write(struct b43_wldev *dev, | 874 | static 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 */ | ||
426 | struct 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 | ||
6 | struct b43_wldev; | 6 | struct b43_wldev; |
7 | 7 | ||
8 | /* Complex number using 2 32-bit signed integers */ | ||
9 | struct 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 | */ |
419 | void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on); | 428 | void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on); |
420 | 429 | ||
430 | struct 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 */ | ||
1771 | typedef struct {s32 i, q;} lpphy_c32; | ||
1772 | |||
1773 | static 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 | |||
1811 | static void lpphy_run_samples(struct b43_wldev *dev, u16 samples, u16 loops, | 1770 | static 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 | ||
58 | enum 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 | |||
67 | static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd, | ||
68 | u8 *events, u8 *delays, u8 length); | ||
69 | static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, | ||
70 | enum b43_nphy_rf_sequence seq); | ||
71 | |||
58 | void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) | 72 | void 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 | ||
237 | static 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 */ |
342 | static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable) | 252 | static 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 */ | ||
338 | static 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 */ | ||
352 | static 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 */ | ||
436 | static 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 */ | ||
459 | static 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 */ |
484 | static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask) | 518 | static 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 */ | ||
691 | static 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 */ | ||
718 | static 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 */ | ||
846 | static 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 */ | ||
957 | static 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 */ | ||
997 | static 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 | */ | ||
1060 | static 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 */ |
657 | static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev) | 1071 | static 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 | ||
723 | enum b43_nphy_rf_sequence { | 1136 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */ |
724 | B43_RFSEQ_RX2TX, | 1137 | static 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 */ | ||
732 | static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, | 1162 | static 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"); |
756 | ok: | 1187 | ok: |
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 */ | ||
1192 | static 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 | ||
761 | static void b43_nphy_bphy_init(struct b43_wldev *dev) | 1267 | static 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 */ | 1346 | static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type) |
841 | static 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 | |||
1395 | static 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 */ | ||
1483 | static 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 */ |
901 | static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf) | 1492 | static 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 */ | ||
1984 | static 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 */ | ||
1993 | static 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 */ |
1344 | static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) | 2021 | static 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 */ | ||
2103 | static 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 */ | ||
2132 | static 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 */ |
1427 | static void b43_nphy_restore_cal(struct b43_wldev *dev) | 2198 | static 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, ¶ms[i]); | 2297 | b43_nphy_iq_cal_gain_params(dev, i, target, ¶ms[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 | ||
2886 | const 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 */ | ||
2911 | const 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 */ | ||
2929 | const 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 | |||
2886 | static inline void assert_ntab_array_sizes(void) | 2947 | static 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 | ||
2983 | u32 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 | |||
3014 | void 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 | |||
2922 | void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value) | 3049 | void 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 | ||
3082 | void 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 | ||
54 | struct nphy_rf_control_override_rev2 { | ||
55 | u8 addr0; | ||
56 | u8 addr1; | ||
57 | u16 bmask; | ||
58 | u8 shift; | ||
59 | }; | ||
60 | |||
61 | struct 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 | ||
161 | u32 b43_ntab_read(struct b43_wldev *dev, u32 offset); | ||
162 | void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset, | ||
163 | unsigned int nr_elements, void *_data); | ||
145 | void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value); | 164 | void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value); |
165 | void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset, | ||
166 | unsigned int nr_elements, const void *_data); | ||
146 | 167 | ||
147 | void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev); | 168 | void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev); |
148 | void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev); | 169 | void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev); |
@@ -172,5 +193,11 @@ extern const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[]; | |||
172 | extern const u16 tbl_tx_iqlo_cal_cmds_recal[]; | 193 | extern const u16 tbl_tx_iqlo_cal_cmds_recal[]; |
173 | extern const u16 tbl_tx_iqlo_cal_cmds_fullcal[]; | 194 | extern const u16 tbl_tx_iqlo_cal_cmds_fullcal[]; |
174 | extern const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[]; | 195 | extern const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[]; |
196 | extern const s16 tbl_tx_filter_coef_rev4[7][15]; | ||
197 | |||
198 | extern const struct nphy_rf_control_override_rev2 | ||
199 | tbl_rf_control_override_rev2[]; | ||
200 | extern 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 @@ | |||
1 | config IWLWIFI | 1 | config 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 | ||
6 | config 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 | |||
12 | config IWLWIFI_DEBUG | 6 | config 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 | |||
124 | config 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 | |||
3 | iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o | 3 | iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o |
4 | iwlcore-objs += iwl-scan.o iwl-led.o | 4 | iwlcore-objs += iwl-scan.o iwl-led.o |
5 | iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | 5 | iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o |
6 | iwlcore-$(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) += iwl-spectrum.o | ||
7 | iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | 6 | iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o |
8 | 7 | ||
9 | CFLAGS_iwl-devtrace.o := -I$(src) | 8 | CFLAGS_iwl-devtrace.o := -I$(src) |
@@ -20,3 +19,5 @@ iwlagn-$(CONFIG_IWL5000) += iwl-1000.o | |||
20 | # 3945 | 19 | # 3945 |
21 | obj-$(CONFIG_IWL3945) += iwl3945.o | 20 | obj-$(CONFIG_IWL3945) += iwl3945.o |
22 | iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o | 21 | iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o |
22 | |||
23 | ccflags-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 | ||
92 | static 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 | |||
117 | static 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 | |||
92 | static struct iwl_lib_ops iwl1000_lib = { | 162 | static 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 | ||
144 | static const struct iwl_ops iwl1000_ops = { | 216 | static 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 | ||
179 | struct iwl_cfg iwl1000_bg_cfg = { | 252 | struct 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 | ||
205 | MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); | 279 | MODULE_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 | ||
2801 | static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { | 2798 | static 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 | ||
2835 | static struct iwl_cfg iwl3945_abg_cfg = { | 2833 | static 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 | ||
2852 | DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { | 2851 | DEFINE_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 | ||
2211 | static const struct iwl_ops iwl4965_ops = { | 2212 | static 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 | */ |
415 | static int iwl5000_load_section(struct iwl_priv *priv, | 415 | static 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 | |||
453 | static 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"); | 469 | static 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 | ||
503 | int iwl5000_load_ucode(struct iwl_priv *priv) | 484 | int 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 | ||
1507 | static struct iwl_lib_ops iwl5150_lib = { | 1490 | static 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 | ||
1560 | static const struct iwl_ops iwl5000_ops = { | 1544 | static 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 | ||
1607 | struct iwl_cfg iwl5100_bgn_cfg = { | 1592 | struct 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 | ||
1631 | struct iwl_cfg iwl5100_abg_cfg = { | 1617 | struct 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 | ||
1653 | struct iwl_cfg iwl5100_agn_cfg = { | 1640 | struct 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 | ||
1677 | struct iwl_cfg iwl5350_agn_cfg = { | 1665 | struct 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 | ||
1701 | struct iwl_cfg iwl5150_agn_cfg = { | 1690 | struct 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 | ||
1725 | struct iwl_cfg iwl5150_abg_cfg = { | 1715 | struct 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 | ||
1747 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); | 1738 | MODULE_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 | ||
256 | static const struct iwl_ops iwl6000_ops = { | 272 | static 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 | ||
312 | struct iwl_cfg iwl6000i_2abg_cfg = { | 329 | struct 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 | ||
341 | struct iwl_cfg iwl6000i_2bg_cfg = { | 359 | struct 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 | ||
370 | struct iwl_cfg iwl6050_2agn_cfg = { | 389 | struct 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 | ||
400 | struct iwl_cfg iwl6050_2abg_cfg = { | 420 | struct 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 | ||
429 | struct iwl_cfg iwl6000_3agn_cfg = { | 450 | struct 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 | ||
459 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); | 481 | MODULE_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 | ||
85 | MODULE_DESCRIPTION(DRV_DESCRIPTION); | 79 | MODULE_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 | ||
707 | void iwl_continuous_event_trace(struct iwl_priv *priv) | 702 | static 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 | ||
1767 | static const char *desc_lookup(int i) | 1763 | static 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 | ||
2446 | static 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 | |||
2458 | static void iwl_bg_restart(struct work_struct *data) | 2442 | static 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 | */ |
2610 | static int iwl_setup_mac(struct iwl_priv *priv) | 2600 | static 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 | ||
2841 | static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, | 2831 | static 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 | ||
3168 | struct iwl_missed_beacon_notif { | 3202 | struct 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); | |||
47 | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | 47 | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); |
48 | MODULE_LICENSE("GPL"); | 48 | MODULE_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 | */ | ||
66 | static bool bt_coex_active = true; | ||
67 | module_param(bt_coex_active, bool, S_IRUGO); | ||
68 | MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist\n"); | ||
69 | |||
50 | static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { | 70 | static 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); | |||
1965 | int iwl_send_bt_config(struct iwl_priv *priv) | 1997 | int 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 | } |
2626 | EXPORT_SYMBOL(iwl_mac_add_interface); | 2664 | EXPORT_SYMBOL(iwl_mac_add_interface); |
2627 | 2665 | ||
@@ -3268,6 +3306,93 @@ void iwl_dump_csr(struct iwl_priv *priv) | |||
3268 | } | 3306 | } |
3269 | EXPORT_SYMBOL(iwl_dump_csr); | 3307 | EXPORT_SYMBOL(iwl_dump_csr); |
3270 | 3308 | ||
3309 | const 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 | |||
3327 | int 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 | } | ||
3370 | EXPORT_SYMBOL(iwl_dump_fh); | ||
3371 | |||
3372 | void 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 | } | ||
3394 | EXPORT_SYMBOL(iwl_force_rf_reset); | ||
3395 | |||
3271 | #ifdef CONFIG_PM | 3396 | #ifdef CONFIG_PM |
3272 | 3397 | ||
3273 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) | 3398 | int 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 | ||
192 | struct iwl_led_ops { | 195 | struct 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 */ |
424 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | 430 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, |
425 | struct iwl_rx_mem_buffer *rxb); | 431 | struct iwl_rx_mem_buffer *rxb); |
432 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | ||
433 | struct iwl_rx_mem_buffer *rxb); | ||
426 | void iwl_rx_statistics(struct iwl_priv *priv, | 434 | void iwl_rx_statistics(struct iwl_priv *priv, |
427 | struct iwl_rx_mem_buffer *rxb); | 435 | struct iwl_rx_mem_buffer *rxb); |
428 | void iwl_reply_statistics(struct iwl_priv *priv, | 436 | void iwl_reply_statistics(struct iwl_priv *priv, |
@@ -493,6 +501,8 @@ void iwl_init_scan_params(struct iwl_priv *priv); | |||
493 | int iwl_scan_cancel(struct iwl_priv *priv); | 501 | int iwl_scan_cancel(struct iwl_priv *priv); |
494 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); | 502 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); |
495 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); | 503 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); |
504 | int iwl_internal_short_hw_scan(struct iwl_priv *priv); | ||
505 | void iwl_force_rf_reset(struct iwl_priv *priv); | ||
496 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | 506 | u16 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); |
498 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); | 508 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); |
@@ -523,14 +533,6 @@ int iwl_send_calib_results(struct iwl_priv *priv); | |||
523 | int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); | 533 | int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); |
524 | void iwl_calib_free_results(struct iwl_priv *priv); | 534 | void 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 | ||
530 | void iwl_setup_spectrum_handlers(struct iwl_priv *priv); | ||
531 | #else | ||
532 | static 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); | |||
582 | int iwl_dump_nic_event_log(struct iwl_priv *priv, | 584 | int 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); |
584 | void iwl_dump_csr(struct iwl_priv *priv); | 586 | void iwl_dump_csr(struct iwl_priv *priv); |
587 | int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); | ||
585 | #ifdef CONFIG_IWLWIFI_DEBUG | 588 | #ifdef CONFIG_IWLWIFI_DEBUG |
586 | void iwl_print_rx_config_cmd(struct iwl_priv *priv); | 589 | void 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 | ||
71 | struct 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 | |||
119 | int iwl_dbgfs_register(struct iwl_priv *priv, const char *name); | ||
120 | void 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 | 79 | int iwl_dbgfs_register(struct iwl_priv *priv, const char *name); | |
133 | #ifndef CONFIG_IWLWIFI_DEBUGFS | 80 | void iwl_dbgfs_unregister(struct iwl_priv *priv); |
81 | #else | ||
134 | static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | 82 | static 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) \ |
83 | static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ | 68 | static 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 | ||
1072 | static const char ucode_stats_header[] = | ||
1073 | "%-32s current acumulative delta max\n"; | ||
1074 | static const char ucode_stats_short_format[] = | ||
1075 | " %-30s %10u\n"; | ||
1076 | static const char ucode_stats_format[] = | ||
1077 | " %-30s %10u %10u %10u %10u\n"; | ||
1084 | 1078 | ||
1085 | static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, | 1079 | static 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 | ||
2100 | static 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 | |||
2121 | static 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 | |||
2138 | static 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 | |||
2164 | static 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 | |||
2185 | static 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 | |||
2202 | static 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 | |||
1943 | DEBUGFS_READ_FILE_OPS(rx_statistics); | 2226 | DEBUGFS_READ_FILE_OPS(rx_statistics); |
1944 | DEBUGFS_READ_FILE_OPS(tx_statistics); | 2227 | DEBUGFS_READ_FILE_OPS(tx_statistics); |
1945 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | 2228 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); |
@@ -1956,6 +2239,10 @@ DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); | |||
1956 | DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); | 2239 | DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); |
1957 | DEBUGFS_WRITE_FILE_OPS(csr); | 2240 | DEBUGFS_WRITE_FILE_OPS(csr); |
1958 | DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); | 2241 | DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); |
2242 | DEBUGFS_READ_FILE_OPS(fh_reg); | ||
2243 | DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); | ||
2244 | DEBUGFS_WRITE_FILE_OPS(internal_scan); | ||
2245 | DEBUGFS_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 | */ |
1964 | int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | 2251 | int 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 | ||
2027 | err: | 2316 | err: |
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 | } |
2032 | EXPORT_SYMBOL(iwl_dbgfs_register); | 2321 | EXPORT_SYMBOL(iwl_dbgfs_register); |
2033 | 2322 | ||
@@ -2037,59 +2326,11 @@ EXPORT_SYMBOL(iwl_dbgfs_register); | |||
2037 | */ | 2326 | */ |
2038 | void iwl_dbgfs_unregister(struct iwl_priv *priv) | 2327 | void 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 | } |
2094 | EXPORT_SYMBOL(iwl_dbgfs_unregister); | 2335 | EXPORT_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 | |||
1014 | struct iwl_priv { | 1038 | struct 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 */ | |
307 | int iwl_power_update_mode(struct iwl_priv *priv, bool force) | 307 | int 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 | } |
512 | EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); | 513 | EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); |
513 | 514 | ||
515 | void 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 | } | ||
530 | EXPORT_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" | ||
595 | void iwl_rx_statistics(struct iwl_priv *priv, | 624 | void 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 | } |
315 | EXPORT_SYMBOL(iwl_get_passive_dwell_time); | 316 | EXPORT_SYMBOL(iwl_get_passive_dwell_time); |
316 | 317 | ||
318 | static 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 | |||
317 | static int iwl_get_channels_for_scan(struct iwl_priv *priv, | 384 | static 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 | } |
489 | EXPORT_SYMBOL(iwl_mac_hw_scan); | 548 | EXPORT_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 | |||
556 | int 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 | |||
593 | out: | ||
594 | return ret; | ||
595 | } | ||
596 | EXPORT_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 | ||
493 | void iwl_bg_scan_check(struct work_struct *data) | 600 | void 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 | ||
60 | static 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 | |||
79 | static __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 | } | ||
97 | static 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 | |||
177 | static 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 | |||
193 | void iwl_setup_spectrum_handlers(struct iwl_priv *priv) | ||
194 | { | ||
195 | priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] = | ||
196 | iwl_rx_spectrum_measure_notif; | ||
197 | } | ||
198 | EXPORT_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 | } |
81 | EXPORT_SYMBOL(iwl_get_ra_sta_id); | 81 | EXPORT_SYMBOL(iwl_get_ra_sta_id); |
82 | 82 | ||
83 | /* priv->sta_lock must be held */ | ||
83 | static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) | 84 | static 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 | ||
100 | static void iwl_add_sta_callback(struct iwl_priv *priv, | 102 | static 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 | |||
171 | static 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 | ||
125 | int iwl_send_add_sta(struct iwl_priv *priv, | 182 | int 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 | */ |
1086 | void iwl_add_bcast_station(struct iwl_priv *priv) | 1123 | void 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) | |||
1093 | EXPORT_SYMBOL(iwl_add_bcast_station); | 1131 | EXPORT_SYMBOL(iwl_add_bcast_station); |
1094 | 1132 | ||
1095 | /** | 1133 | /** |
1134 | * iwl3945_add_bcast_station - add broadcast station into station table. | ||
1135 | */ | ||
1136 | void 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 | } | ||
1141 | EXPORT_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 | ||
54 | int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); | 54 | int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); |
55 | void iwl_add_bcast_station(struct iwl_priv *priv); | 55 | void iwl_add_bcast_station(struct iwl_priv *priv); |
56 | void iwl3945_add_bcast_station(struct iwl_priv *priv); | ||
56 | int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); | 57 | int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); |
57 | void iwl_clear_stations_table(struct iwl_priv *priv); | 58 | void iwl_clear_stations_table(struct iwl_priv *priv); |
58 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv); | 59 | int 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 | ||
83 | MODULE_DESCRIPTION(DRV_DESCRIPTION); | 83 | MODULE_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 | ||
824 | static void iwl3945_rx_reply_alive(struct iwl_priv *priv, | 819 | static 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 | ||
3040 | static 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 | |||
3052 | static void iwl3945_bg_restart(struct work_struct *data) | 3036 | static 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, | |||
3569 | static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, | 3559 | static 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 | |||
3574 | static ssize_t show_measurement(struct device *d, | 3562 | static 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 | ||
3641 | static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, | 3629 | static 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 | ||
3645 | static ssize_t store_retry_rate(struct device *d, | 3632 | static 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) | |||
1160 | static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, | 1160 | static 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, | |||
1173 | static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, | 1173 | static 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, | |||
1184 | static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, | 1184 | static 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, | |||
1210 | static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, | 1210 | static 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 */ | ||
230 | static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, | 237 | static 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 | ||
263 | static void p54p_rx_tasklet(unsigned long dev_id) | 273 | static 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); | 316 | out: |
314 | |||
315 | return reg ? IRQ_HANDLED : IRQ_NONE; | 317 | return reg ? IRQ_HANDLED : IRQ_NONE; |
316 | } | 318 | } |
317 | 319 | ||
318 | static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | 320 | static 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 | ||
764 | static 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 | |||
764 | static const struct ieee80211_ops rtl8180_ops = { | 772 | static 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 | ||
776 | static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) | 785 | static 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 | ||
1268 | static 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 | |||
1268 | static const struct ieee80211_ops rtl8187_ops = { | 1276 | static 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 | ||
1282 | static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom) | 1291 | static 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 | |||
141 | struct ieee80211_hdr { | 143 | struct 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 | ||
1198 | struct 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 | */ |
1217 | struct wiphy { | 1233 | struct 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 | */ |
1639 | unsigned int cfg80211_classify8021d(struct sk_buff *skb); | 1659 | unsigned 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 | */ | ||
1675 | const 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 | */ |
275 | enum mac80211_tx_control_flags { | 281 | enum 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); | |||
120 | static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | 120 | static 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 | ||
139 | static inline void drv_update_tkip_key(struct ieee80211_local *local, | 139 | static 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 | ||
152 | static inline int drv_hw_scan(struct ieee80211_local *local, | 156 | static 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 | ||
332 | TRACE_EVENT(drv_update_tkip_key, | 332 | TRACE_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 | ||
458 | static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | 457 | static 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 | |||
522 | static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | 525 | static 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); |
2393 | next: | ||
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 | } |
196 | EXPORT_SYMBOL(ieee80211_get_tkip_key); | 196 | EXPORT_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 | */ | ||
203 | void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, | 205 | void 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 | |||
569 | static ieee80211_tx_result debug_noinline | ||
570 | ieee80211_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 | ||
736 | static ieee80211_tx_result debug_noinline | 754 | static ieee80211_tx_result debug_noinline |
737 | ieee80211_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 | |||
747 | static ieee80211_tx_result debug_noinline | ||
748 | ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | 755 | ieee80211_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, | |||
1279 | static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | 1289 | static 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"); | |||
31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
32 | MODULE_DESCRIPTION("wireless configuration support"); | 32 | MODULE_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 */ | ||
37 | LIST_HEAD(cfg80211_rdev_list); | 35 | LIST_HEAD(cfg80211_rdev_list); |
38 | int cfg80211_rdev_list_generation; | 36 | int cfg80211_rdev_list_generation; |
39 | 37 | ||
40 | /* | ||
41 | * This is used to protect the cfg80211_rdev_list | ||
42 | */ | ||
43 | DEFINE_MUTEX(cfg80211_mutex); | 38 | DEFINE_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"); | |||
36 | MODULE_DESCRIPTION("lib80211 crypt: TKIP"); | 36 | MODULE_DESCRIPTION("lib80211 crypt: TKIP"); |
37 | MODULE_LICENSE("GPL"); | 37 | MODULE_LICENSE("GPL"); |
38 | 38 | ||
39 | #define TKIP_HDR_LEN 8 | ||
40 | |||
39 | struct lib80211_tkip_data { | 41 | struct 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 | ||
359 | static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | 359 | static 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 | ||
136 | static char *ieee80211_regdom = "00"; | 136 | static char *ieee80211_regdom = "00"; |
137 | static char user_alpha2[2]; | ||
137 | 138 | ||
138 | module_param(ieee80211_regdom, charp, 0444); | 139 | module_param(ieee80211_regdom, charp, 0444); |
139 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | 140 | MODULE_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 | */ | ||
261 | static 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(®_work); | 1931 | schedule_work(®_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 | */ | ||
1908 | static int regulatory_hint_core(const char *alpha2) | 1938 | static 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(®_mutex); | 2138 | mutex_unlock(®_mutex); |
2110 | } | 2139 | } |
2111 | 2140 | ||
2141 | static 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 | */ | ||
2203 | static 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(®_mutex); | ||
2210 | |||
2211 | reset_regdomains(); | ||
2212 | restore_alpha2(alpha2, reset_user); | ||
2213 | |||
2214 | /* Clear beacon hints */ | ||
2215 | spin_lock_bh(®_pending_beacons_lock); | ||
2216 | if (!list_empty(®_pending_beacons)) { | ||
2217 | list_for_each_entry_safe(reg_beacon, btmp, | ||
2218 | ®_pending_beacons, list) { | ||
2219 | list_del(®_beacon->list); | ||
2220 | kfree(reg_beacon); | ||
2221 | } | ||
2222 | } | ||
2223 | spin_unlock_bh(®_pending_beacons_lock); | ||
2224 | |||
2225 | if (!list_empty(®_beacon_list)) { | ||
2226 | list_for_each_entry_safe(reg_beacon, btmp, | ||
2227 | ®_beacon_list, list) { | ||
2228 | list_del(®_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(®_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 | |||
2251 | void 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 | |||
2112 | static bool freq_is_chan_12_13_14(u16 freq) | 2258 | static 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 | */ | ||
82 | void 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 | ||
146 | static u8 *find_ie(u8 num, u8 *ies, int len) | 146 | const 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 | } |
158 | EXPORT_SYMBOL(cfg80211_find_ie); | ||
158 | 159 | ||
159 | static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2) | 160 | static 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 | ||
37 | bool 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 | |||
66 | static void disconnect_work(struct work_struct *work) | ||
67 | { | ||
68 | if (!cfg80211_is_all_idle()) | ||
69 | return; | ||
70 | |||
71 | regulatory_hint_disconnect(); | ||
72 | } | ||
73 | |||
74 | static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work); | ||
37 | 75 | ||
38 | static int cfg80211_conn_scan(struct wireless_dev *wdev) | 76 | static 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 | ||
663 | void cfg80211_disconnected(struct net_device *dev, u16 reason, | 703 | void 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 | ||
34 | SHOW_FMT(index, "%d", wiphy_idx); | 34 | SHOW_FMT(index, "%d", wiphy_idx); |
35 | SHOW_FMT(macaddress, "%pM", wiphy.perm_addr); | 35 | SHOW_FMT(macaddress, "%pM", wiphy.perm_addr); |
36 | SHOW_FMT(address_mask, "%pM", wiphy.addr_mask); | ||
37 | |||
38 | static 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 | ||
37 | static struct device_attribute ieee80211_dev_attrs[] = { | 55 | static 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 */ |